Git Product home page Git Product logo

bosket's Introduction

bosket-logo
Bosket
travis-badge npm-badge license-badge

Bosket is collection of tree views for front-end frameworks.

A versatile, powerful and simple way to display nested data.

Purpose

Bosket is a library of tree views implementations for front-end reactive frameworks.

Tree views, which are basically an elegant way to display nested lists, are very versatile and can for example be used as file explorers, menus, table of contents or category lists.

The core logic is written in plain javascript without any dependencies.

Framework implementations rely on this very same code, which makes new implementations easy to write and by extension new frameworks easy to support.


Tree view example : reactive nested lists

bosket-itemtree-gif

Documentation

Please check out the Bosket website for more details including the full documentation.

Supported frameworks

License

MIT

bosket's People

Contributors

elbywan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bosket's Issues

Custom sorting function

Hi again!

I would like to create my own sorting function in Vue 2.0, according to whether it is a folder or a leaf. However, I only get infinite loops:

      sort: (a, b) => {
        if((a.children && b.children) || (!a.children && !b.children)) {
          return a.name.localeCompare(b.name)
        } else if (a.children && !b.children) {
          return -1
        } else {
          return 1
        }
      }

Could you please help me understand how the sort function works?

Add tree node dynamically

I wonder what is the best way to add a tree node dynamically.
Using Angular, I modified the input variable for the model, but change detection is not happening. Only if I create a copy of the model, the change is recognized in the tree. For this I do the following to make a copy of the model:

this.model = JSON.parse(JSON.stringify(this.model))

However this seems not to be the best way. Does anyone have a better solution? If I could get a hold of the actual TreeViewNode-component, I probably could tell it, to get updated.

Module not found: Can't resolve 'react-transition-group/CSSTransitionGroup'

Hello,
I have a react configuration.

I try to install with a simple create app install and yarn install or npm install, after I put bosket in package.json, but I have the following error:

./~/bosket/react/traits/transitions.js
Module not found: Can't resolve 'react-transition-group/CSSTransitionGroup' in '/Users/j3di/Downloads/react-bosquet/node_modules/bosket/react/traits'

I try add react-transition-group in my package.json but it doesn't work..

my package.json configuration


{
  "name": "react-bosquet",
  "description": "",
  "dependencies": {
    "react": "15.6.1",
    "react-dom": "15.6.1",
    "react-scripts": "1.0.10",
    "bosket": "0.2.1",
    "react-transition-group":"2.2.0"
  },
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject"
  }
}


Clearing the search when starting drag

When using search, then it would be good to have the functionality to clear the search when starting a drag.

Version: Vue

Use case:
Users searches for a specific item. Initiates drag and wants to position the draggable element between two specific elements.
Problem: User cannot make the drop since the items aren't visible.

I tried just to clear the input but being Vue, the $data.searchInput doesn't change and therefore the tree doesn't update.

Tree items disappearing

Clicking around tree items in the Riot.js demo, items sometimes disappear completely or move to another branch in the tree.

Expand/Open a node programmatically

Is there a way to expand a node programmatically? It's an important feature especially if you want to open a certain tree path and select a certain sub-node.

Do you have any ideas? I'm using the angular implementation.

don't render opener symbol for empty children arrays

we have in core/logic.js:

_this.hasChildren = function (item) { return item[_this.inputs.get().category] && item[_this.inputs.get().category] instanceof Array; }

it's possible to make one more check for array's length?

_this.hasChildren = function (item) { return item[_this.inputs.get().category] && item[_this.inputs.get().category] instanceof Array && item[_this.inputs.get().category].length; }

Folding collapses whole tree (Angular)

Hey,

first off, great work so far, I really like this component.

I'm not sure if I just don't get the strategies or if this is a bug.
I use the following strategies
strategies = { click: ['select', 'unfold-on-selection'], selection: ['single'], fold: ['no-child-selection', 'not-selected'] };
What kind of expected is that when I click on an unfolded item (expanded?!), that only this item gets collapsed/folded and not the whole tree.

But I also want to be able to use the activated route '.../item/{[id}' to use that id and select an item in the tree. I had a look at this issue Auto expand on load,
but I really had no idea how to use this within my component. So I choose to set the [selection] on my will at loading.

Am I missing something?

Thanks in advance :)

Demo

Maybe it escaped me, but I couldn't see a demo on the website, nor a link in the GitHub readme.

That would be much appreciated!

build not working on windows

npm start gets this error

> [email protected] bundle-templates C:\Users\J83528\Desktop\tmp\bosket-master
> scripts/bundle-hbs.js

'scripts' is not recognized as an internal or external command,
operable program or batch file.
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] bundle-templates: `scripts/bundle-hbs.js`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] bundle-templates script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\J83528\AppData\Roaming\npm-cache\_logs\2018-07-09T20_18_58_048Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] bundle: `webpack --progress --colors --config config/webpack.config.js -p && npm run bundle-templates`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] bundle script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\J83528\AppData\Roaming\npm-cache\_logs\2018-07-09T20_18_58_099Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build: `npm run build-js && npm run build-ts && npm run bundle`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] build script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\J83528\AppData\Roaming\npm-cache\_logs\2018-07-09T20_18_58_147Z-debug.log
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] start: `npm run build && npm run build-docs`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\J83528\AppData\Roaming\npm-cache\_logs\2018-07-09T20_18_58_193Z-debug.log

Expose nodeEvents

Hi,

I am just wondering if there is a way to expose/use nodeEvents in bosket/src/core/dragndrop.js?
What I am trying to do is to show different animation on drag enter and drag leave in a sortable tree.

Thanks,

Drag and Drop not working on IE 11

this.pluckPreset.drag(target, event, inputs);
ERROR Error: Unexpected call to method or property access.
this.pluckPreset.drop(target, event, inputs);
ERROR TypeError: Object doesn't support property or method 'indexOf'

Drag and drop issues

When you use drag & drop there is no indication where the drop will occur.

Also the entire branch appears selected, although I'm only dragging a single item,

Finally I'm unable to drop an item so that it becomes an descendant of an item.

You might want look at using Dragula https://github.com/bevacqua/dragula instead of what I assume is your own d&d implementation.

Where is the selected list stored

Hi again,

(I'm sorry for having so many questions in a few amount of time ๐Ÿ˜† !)

Still using Vue.js, I was wondering how to access the selected list. I would like to store it in my store in vuex, so that when I reload the tree (after I add a child for example), I get the same opened folders.

Thank you @elbywan

Use of custom display function with tags

Hi,

I'm trying to display my items according to this template :

<span>
<span style="font-size:80%;color:#3298FF;font-weight:bold;"> item.type </span> item.name 
</span>

In that, I have created a display function:

display: item => {
          return createElement('span', {
              'class': this.itemClass(item.actif)
            }, 
            [
              createElement('span', this.itemStyle(item.type), item.type),
              item.name,
              createElement('i', {
                'class':{
                  state: true,
                  fa: true,
                  'fa-exclamation-triangle': item.late,
                  'fa-power-off': item.actif
                }
              }),
              createElement('i', {
                'class':{
                  state: true,
                  fa: true,
                  'fa-pause': item.standby
                }
              })
            ]
          )
        }

However, I get the error 'createElement is not defined', how do I implement my own model ?

Reorder Nodes

Hello,

I am just wondering if you can reorder a node in a tree? Similar to sortable. Right now I believe you can only drag nodes into groups but you can not reorder them.

Thanks,

Why npm -d?

I'm unclear why it's recommended to install this package as a development dependency instead of a regular one. My linter is too.

tx.

Electron-Vue-Bosket

Hi.
I have a problem with model.

<template>
  <div id="app">
       <TreeView :model="model" category="children"></TreeView>
  </div>
</template>

<script>
  import { TreeView } from "@bosket/vue"
  import { string } from "@bosket/tools"

  export default {
    name: 'test-bosket',
    components: {
      "TreeView": TreeView
    },
    data: function() {
            return {
              selection: [],
              category: "children",
              model: [{
                label: "Animals",
                  children: [{
                    label: "Mammals",
                      children: [
                        { label: "Tiger" },
                        { label: "Platypus" },
                        { label: "Bear" }
                      ]
                    }, {
                    label: "Reptiles",
                      children: [
                        { label: "Turtle" },
                        { label: "Crocodile" }
                      ]
                    }]
              }]
        }
    }
  }
</script>

<style>
  /* CSS */
</style>

When I try to run app? I have error.

 [Vue warn]: Error in render: "TypeError: Cannot read property 'indexOf' of undefined"

found in

---> <TreeViewNode>
       <WithTransitionTreeViewNode>
         <TreeView>
           <WithLabelsTreeView>
             <WithListenerWithLabelsTreeView>
               <WithListenerWithListenerWithLabelsTreeView>
                 <Passmanager> at src/renderer/App.vue
                   <Root>
And error stack
TypeError: Cannot read property 'indexOf' of undefined
    at Object.contains (/node_modules/@bosket/tools/bundle/tools.umd.min.js:1:3284)
    at n.o.isSelected (/node_modules/@bosket/core/bundle/core.umd.min.js:1:11309)
    at n.o.liCss (/node_modules/@bosket/core/bundle/core.umd.min.js:1:12388)
    at /node_modules/@bosket/vue/bundle/vue.umd.min.js:1:7413
    at Array.map (native)
    at Proxy.render (/node_modules/@bosket/vue/bundle/vue.umd.min.js:1:7346)
    at VueComponent.Vue._render (webpack-internal:///0:4545:22)
    at VueComponent.updateComponent (webpack-internal:///0:2789:21)
    at Watcher.get (webpack-internal:///0:3143:25)
    at new Watcher (webpack-internal:///0:3132:12)

Can you help me solve this problem?

Detecting fold/unfold click

Hello,
I'am using the VueJS version of bosket and I'am struggled with probably a stupid thing, how could i detect that a click on the opener has been made, I knowh there is the onSelect method which is triggered when an item is selected, but i would like to know is if there is a way to have a kind of OnOpener method which would provide the state of the node (fold/unfold) and the item corresponding to it but without selecting the item.

Thanks,
JM

doesn't load async children when searching

I would like to have my tree view search even in items that haven't been asynchronously loaded yet. So it would walk through the whole tree, resolve promises if they are not resolved yet and then search based on the results.

Right now when I search and the tree items haven't been expanded yet, they are not searched because their children weren't resolved yet.

Selecting a node programmatically

Hello,
Maybe it is possible natively, but i haven't found it how, but how could i selected a node programmatically?
I'am working with VueJS.

Here is my use case:
I have the tree view component on the left part of my app and when i click on a node (Node1) it expands its children (Node1.1, Node1.2, Node1.3,...)
Then on the right part of my app i have the content page component which will sometimes display the list of the children too (Node1.1, Node1.2, Node1.3,...)
What i would like is when in the content page i click on let's say Node1.2 , that in the tree view the node Node1.2 would be selected, and so the expension of its children would be triggered

Thanks for your help.
JM

Drag on same level

Hello @elbywan ,

First your tool is very very awesome thanks for this simple and easy to use.

I need your help for the drag and drop.

I want drag element but only with the same level between the source Item and the destination Item.

I try Many solutions, but I don't arrive drag only the same element with the same level or except when a specific properties in model allowIt , specialy with async element.
Also it's possible to open automatically the children when I drag element over it?

You can see the model here: https://stackblitz.com/edit/react-zasmjr?file=model.js

all elements have a level.

Thanks for your help

Multiselect with selected nodes always open (vue)

Hi, I'm trying to build a folders system. Nodes with children are my folders and nodes without children are my files. I need to open multiple folder nodes (multiselection ), but with only one file item selected at the same time.

So I tried to made some strategies to acomplish these behaivor:

{
    selection: [
        'multiple',
        (item, selection) => {
            // Take only folders
            var modifiedSelection = selection.filter((node) => {
                return node.children ? true : false;
            });

            if (!item.children) {
                modifiedSelection.push(item);
            }

            return modifiedSelection;
        }
    ],
    click: ['select'],
    fold: [
        (item) => {

            var recurseCheck = node => {
                return this.isSelected(node)
                || node['children']
                && node['children'] instanceof Array
                && node['children'].some(recurseCheck);
            }

            return !recurseCheck(item)
        }
    ]
}

The isSelected method:

isSelected(item) {

    var found = this.selection.filter((selectionItem) => {
        if (selectionItem.id == item.id && selectionItem.children == item.children) {
            return true;
        }
        return false;
    });

    return found.length > 0 ? true : false;
}

This works more or less how I expected. However lets say that I'm having these structure

--folder A
----item A1
----item A2

--folder B
----item B1
----item B2

When the folder A is selected I can open/close folder B and select any of the items inside. But when for example item A1 is selected and I pick folder B or any other element inside of B, the folder A is closed because the selection losts any reference to A or any of it's items.

folders

Any idea about how I can mantain the folder A opened?

Having only children-less elements loading asynchronously

Hi,
Working with vuejs, let's say I have a tree with :

  • Folder-0
    • Folder-0.1
    • Folder-0.2
    • Item-0.1
    • ...
    • Item-0.200
  • ...

Because my items are so numerous, I'd like to load them asynchronously, while all the subfolders (= tree elements with children) are preloaded.

I tried both parts: loading asynchronously my items and loading only the folders and subfolders, but I can't figure out the proper syntax for mixing both.
Do you have a clue ?

Thank you.

model is undefined (in using computed property)

Hey, it's me again ๐Ÿ˜…
I'm trying to add a custom children() function, based on properties. Thus, I decided to use a computed property, which takes an input array and returns the same array, but with a children() function. This didn't work, so I stripped it down to the code of one of your examples (one entry with async children), but this didn't work too...Then, I moved if from computed, back to data() and everything works fine. Am I missing something or is it not intended to use computed?
Thanks in advance!

Edit: the error occurs when I click on the opener to show the children.

[Vue warn]: Error in render: "TypeError: model is undefined"

found in

---> <TreeViewNode>
       <WithTransitionTreeViewNode>
         <TreeViewNode>
           <WithTransitionTreeViewNode>
             <TreeView>
               <WithLabelsTreeView>
                 <WithListenerWithLabelsTreeView>
                   <WithListenerWithListenerWithLabelsTreeView>
                     <TestTree> at resources/assets/js/components/TestTree.vue
                       <Root>

My Component:

<script>
    import { TreeView } from '@bosket/vue';

    export default {
        components: {
            'tree-view': TreeView
        },
        props: ['arr'],
        mounted() {},
        methods: {
            onSelect(newSelection) {
                this.selection = newSelection
            }
        },
        data() {
            return {
                selection: [],
                strategies: {
                    selection: ["single"],
                    click: ["select"],
                    fold: ["opener-control"]
                },
                category: "children",
                display: (item, inputs) => {
                    return item.label;
                }
            }
        },
        computed: {
            model() {
                return [{
                    name: "Asynchronous children",
                    children: () =>
                        new Promise(resolve =>
                            setTimeout(() =>
                                resolve([{ label: "It took exactly one second to fetch me the first time, I am cached afterwards." }]), 1000))
                }];
            }
        }
    }
</script>

Selecting/Opening/Closing nodes is really slow for large trees

Hey,

I am currently working on managing a large project with bosket (~500 root entries, 20k total entries). Although children are loaded asynchronically, any action (selecting/opening/closing nodes) on that tree takes several seconds. I suspect some sort of filter/map being applied to the whole tree on every action. Is there a way to avoid these loading times? I would really like to continue working with bosket =)

Custom search placeholder

It would be nice to have custom search placeholder, as current default one doesn't look very good with foreign language.

Export core modules to UMD

I'm still using RequireJS with RiotJS. I can see bosket/riot/index.js contains the core modules, like dragndrop but I have no access to them, for example to use the dragndrop.selection preset. Is there a way to access them, or could you export them as part of the pre-built index.js module?

Edit tree node contents

I am using the display prop to render custom text and display an "edit" button in react. i am passing the object passed to the display function to the onClick handler of the button to be used for editing. is the object passed to the display function the actual object from within the original tree model? i.e. if I update the passed object am i updating the original data? If not, how could I programmatically delete and add a new node with the updated content? or update and render the original data?

    mainTreeProps = {
        ...this.treeProps, display: d => <div><Button onClick={() => {
            d.items ? this.props.EditGroup(d) : this.props.EditItem(d);
        }}>Edit</Button>{d.name}</div>
    };

(i.e. is "d" a copy or a reference to the object in the original model / object)

Own packages

Hello,

Do you think it possible to separate each module with his own package.
I mean instead have "bosket/react" , the package was "bosket-react" for example with only file for react,
one for vue => "bosket-vue" etc etc...

Because I use unpkg.com for load package like a cdn in my project , and I would like make demo with playground editor like https://stackblitz.com/

Other thing, I see You use typescrpit can you put a file typescript definition file in the root of project ? I would like use the intellisence of typescript. thanks for your answer

bosket + redux

Hello!

Thank you for this component!

I'm trying to use it without a local state.

For example:

const regions = this.props.regionsTree.regions;  // redux store

const tree = {
  category: 'sub_regions', // name of the property containing the children
  selection: [],
  model: regions, // object for iterate
  display: (_) => _.region, // field for show
  onSelect: (newSelection, item, ancestors, neighbours) => {
    // newSelection     -> updated array containing all the selected items
    // item             -> the newly selected item (excluding the old one in case of multi selection)
    // ancestors        -> the ancestors of the newly selected item
    // neighbours       -> the neighbours of the newly selected item
    this.selection = newSelection;
  },
};

/* Drag'n'drop presets */

const dragndrop = {
  // To drag or drop on specific items
  // you can use a function : (item) => true/false
  draggable: true,
  droppable: true,
  drag: null,  // action to perform on drag
  drop: null,  // action to perform on drop
  over: null,  // hook on dragover
  enter: null,  // hook on dragenter
  leave: null,  // hook on dragleave
  cancel: null,  // action to perform on cancellation
  guard: null,   // prevents dragover and drop
};

    <TreeView
      {...tree}
      dragndrop={dragndrop}
      onSelect={tree.onSelect}
    />

Of course, drag'n'drop don't work (need describe action).

Do you have an example of using a TreeView with Redux?

Tree doesn't reset when search field is emptied

When testing the Riot demo, there's a native type="search" (x) button when the search field has a value. However, clicking on it doesn't reset the tree display, it only empties the field itself. Perhaps a different event (like input) should be used?

How to add custom html?

How to add custom html? For example, I want to add a button to edit an item and a button to delete a member. How can i do this?

ReferenceError: h is not defined

Hey, I think about switching from AngularJS to Vue, but need a plugin to display tree-like hierarchy with drag&drop and easy customization. Seems like bosket is the only solution. So thanks for that! :)

But the customization is what gives me headache. I built a sample app using laravel-mix bundled with Vue. After fixing the webpack/babel setup to be able to use

display: (item, inputs) =>
    <strong>{ item.label }</strong>,

in my component, which should also display the tree. But since this is now fixed, I get the ReferenceError.
Full message:

 [Vue warn]: Error in render: "ReferenceError: h is not defined"

found in

---> <TreeViewNode>
       <WithTransitionTreeViewNode>
         <TreeView>
           <WithLabelsTreeView>
             <WithListenerWithLabelsTreeView>
               <WithListenerWithListenerWithLabelsTreeView>
                 <ExampleComponent> at resources/assets/js/components/ExampleComponent.vue
                   <Root>

When I switch back to a simple display function (e.g. display: function(item) { return item.label; }) it works.

Is this a problem with bosket or still an error with my setup?

My added .babelrc (without it html was not allowed in display())

{
    "presets": [
        [ "env", { "modules": false } ]
    ],
    "plugins": [
        "transform-vue-jsx",
        "transform-object-rest-spread",
        "transform-class-properties",
    ]
}

app.js

import { TreeView } from '@bosket/vue';
import ExampleComponent from './components/ExampleComponent.vue';

require('./bootstrap');

window.Vue = require('vue');

Vue.component('example-component', ExampleComponent);
Vue.component('tree-view', TreeView);

const app = new Vue({
    el: '#app'
});

Add options to search (delay, minimum length)

I would like to add to features to the search box:

  • Wait [...] milliseconds before searching to avoid the browser to search before the user has entered a search term.
  • Set a minimum length of characters. It makes no sense to search for a single character in larger trees.

Any idea how to implement these features?

dragging with handle

instead of dragging the whole tree item, would it be possible to add a way to define a handle to drag & drop with instead?

I mean something like this:

https://wiki.almworks.com/download/attachments/10422865/issue_handle.png?version=1&modificationDate=1353336367000&api=v2

Drag and drop reordering

The demo uses a custom sort function, so I was expecting that without that you'd be able to reorder nodes amongst siblings. However, this doesn't seem to be possible - I can only change the hierarchy/nesting, not simply reorder these items.

Would it be possible to add this (as a flag, perhaps)?

Model rebind causes opened nodes to collapse

Hi @elbywan - love this component! It's been very useful.

One issue I have is when the model changes, any opened nodes automatically collapse. Ideally we'd like an option to keep all node's expanded/collapsed state when the model changes.

This may be an option already but I have not found it - we currently use these strategies:

:strategies="{
selection: ['single'],
click: ['select', 'unfold-on-selection'],
fold: ['opener-control']
}"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.