mini-tree-react

1.1.1 • Public • Published

mini-tree-react

Simple tree view realization for ReactJS

npm npm bundle size License GitHub last commit

Table of contents

Getting started

Install

For start using mini-tree-react you need to install mini-tree-react package. Enter the command: npm i mini-tree-react --save-dev.

Base example

import React from 'react';
import ReactDOM from 'react-dom';
import { Tree, defConf } from 'mini-tree-react';
 
const children = [
  {
    content: 'Item-1',
    children: [
      {
        content: 'Subitem-1-1'
      },
      {
        content: 'Subitem-1-2'
      }        
    ]
  },
  {
    content: 'Item-2',
    children: [
      {
        content: 'Subitem-2-1'
      },
      {
        content: 'Subitem-2-2'
      }         
    ]
  }
];
const conf = defConf('my-tree', children);
 
const root = document.getElementById('root');
ReactDOM.render((<Tree conf={ conf } />), root);

Tree configuration

Expand and Collapse

You can expand and collapse child tree items by double-clicking. ExpandModels contains several commonly used models:

ExpandModels.none - without expand and collapse;

ExpandModels.single - only one child can be expand;

ExpandModels.multi - all children can be expand at the same time;

Also you can define your own model of expand:

const myExpandModel = (conf) => (event, data, expand) => {
  expand.apply(data, [ /* true - expanded, false - collapsed */ ])
};
const conf = {
  expand: myExpandModel
}; 

Selection and Unselection

You can select and unselect child tree items by mouse click. SelectModels contains several commonly used models:

SelectModels.none - without selection and unselection;

SelectModels.single - only one child can be select;

SelectModels.multi - all children can be select at the same time;

Also you can define your own selection model:

const mySelectModel = (conf) => (event, data, select) => {
  select.apply(data, [ /* true - selected, false - unselected */ ])
};
const conf = {
  select: mySelectModel
}; 

Resolve children

To get tree's children you must use resolve model. ResolveModels contains several commonly used models:

ResolveModels.field - Resolve children by field in tree's configuration;

const conf = {
  resolve: ResolveModels.field(),
  children: [ /* some children */ ],
  child: {
    children: 'children' // You can specify a field name for `ResolveModels.field`
  }
};

ResolveModels.param - Resolve children by parameter. This model uses by default in defConf function;

const conf = {
  resolve: ResolveModels.param([ /* Some children */ ]),
};

Also you can define your own model of resolve:

const myResolveModel = (parent, childConf, resolve) => {
  const children = [/* some children */];
  resolve.apply(childConf, [ children ]);
};
const conf = {
  resolve: myResolveModel
};

State filter

You can filter the state data before component will render. This can be useful when you want tree elements to be expanded or selected at the initialization stage and etc. Below you can see base example.

 const conf = defConf('my-tree', [ /* some children */ ]);
 conf.state = (type, data, state) => {
   return state;
 };  
 
 const root = document.getElementById('root');
 ReactDOM.render((<Tree conf={ conf } />), root);

type parameter is a reason of update state, it's define in UpdateStateType. Below you can see all options for the type value.

UpdateStateType.TREE_INIT - Tree component initialization;

UpdateStateType.ITEM_INIT - Tree item component initialization;

UpdateStateType.TREE_RESOLVED - Children of the tree resolved;

UpdateStateType.ITEM_RESOLVED - Children of the tree item resolved;

UpdateStateType.ITEM_EXPANDED - Tree item expanded;

UpdateStateType.ITEM_SELECTED - Tree item selected;

data parameter is data for component rendering. For tree component data is the configuration data, for item component data is the item value.

state parameter is state after some action, but before filtering. For tree component state has structure:

{
  children: array
}

For tree item component state has structure:

{
  selected: true | false,
  expanded: true | false,
  children: array
}

mini-tree-react has some of the most commonly used state filters in StateFilters. Below you can see these filters.

toggleSelected(state: object, selected: boolean) - state filter for selection value changing;

 const conf = defConf('my-tree', [ /* some children */ ]);
 conf.state = (type, data, state) => {
   if (type === UpdateStateType.ITEM_INIT) {
     return StateFilters.toggleSelected(state, true); // all items are selected
   }
 };  
 
 const root = document.getElementById('root');
 ReactDOM.render((<Tree conf={ conf } />), root);

toggleExpanded(state: object, expanded: boolean) - state filter for expand value changing;

 const conf = defConf('my-tree', [ /* some children */ ]);
 conf.state = (type, data, state) => {
   if (type === UpdateStateType.ITEM_INIT) {
     return StateFilters.toggleExpanded(state, true); // all items are expanded
   }
 };  
 
 const root = document.getElementById('root');
 ReactDOM.render((<Tree conf={ conf } />), root);

Global methods

mini-tree-react has global methods:

defConf(id: string, children: array): object - default configuration creating;

Standard configuration looks like this:

const manualConf = {
  id: 'my-tree',
  expand: ExpandModels.multi,
  select: SelectModels.multi,
  resolve: param([ /* some children */ ]),
  state: (type, data, state) => state,
  child: {
    id: 'id',
    content: 'content'
  }
};

If you uses defConf function then, the above code can be replaced by this code:

const conf = defConf('my-tree', [ /* some children */ ]);

findTree(id: string): object - tree searching by identifier;

After the tree is found, you can use the tree methods. See methods in the section Tree methods

const tree = findTree('my-tree');

Tree methods

Tree has methods:

findChild(selector: string): object - for child searching by id or treeIndex. treeIndex is specified by the rule: the parent treeIndex plus the index of the item in the array. Below you can to see treeIndex example:

item - 0
  item - 00
item - 1
  item - 10
    item - 100

Although treeIndex seems like a good option, it's better to use identifiers to search. After the tree's child is found, you can use the children methods. See methods in the section Children methods

const tree = findTree('my-tree');
// Searching by id
let child = tree.findChild('my-item-id');
// Searching by treeIndex
child = tree.findChild('010');

hasChildren(): boolean - for children existence checking;

const tree = findTree('my-tree');
if (tree.hasChildren()) {
  /* some processing */
}

getChildren(): array - for to get children;

 const tree = findTree('my-tree');
 const selectedChildren = tree.getChildren()
                              .map((child) => child.isSelected());

Child configuration

Tree's child configuration must contains id and content fields. id field contains child's identifier, it's can be use for child searching. content field contains data for rendering. These fields can be string or function type. Via string type you can to describe field name into data of child. Via function type you can to return any data. By default uses string type, where id value is id and content value is content.

Example with string type:

import React from 'react';
import ReactDOM from 'react-dom';
import { Tree, defConf } from 'mini-tree-react';
 
const children = [
  {
    id: 'my-item',
    content: 'My item',
  }
];
const conf = defConf('my-tree', children);
conf.child = {
  id: 'id',
  content: 'content'
};
 
const root = document.getElementById('root');
ReactDOM.render((<Tree conf={ conf } />), root);

Example with function type:

import React from 'react';
import ReactDOM from 'react-dom';
import { Tree, defConf } from 'mini-tree-react';
 
const children = [
  {
    id: 'my-item',
    content: 'My item',
  }
];
const conf = defConf('my-tree', children);
conf.child = {
  id: (data) => data.item.id,
  content: (data) => (<span>{ data.item.content }</span>)
};
 
const root = document.getElementById('root');
ReactDOM.render((<Tree conf={ conf } />), root);

Listeners

The children of the tree have events that you can to listen:

onClick - for listen to the click event;

onDoubleClick - for listen to the double click event;

onSelect - for listen to the selection event;

onUnselect - for listen to the unselection event;

onExpand - for listen to expansion event;

onCollapse - for listen to the collapse event;

These fields can be string or function type. Via string type you can to describe the function name into data of the child. Via function type you can describe the function being called.

Example with string type:

import React from 'react';
import ReactDOM from 'react-dom';
import { Tree, defConf } from 'mini-tree-react';
 
const children = [
  {
    id: 'my-item',
    content: 'My item',
    click: (event, data) => { /* Some processing */ },
    doubleClick: (event, data) => { /* Some processing */ },
    select: (event, data) => { /* Some processing */ },
    unselect: (event, data) => { /* Some processing */ },
    expand: (event, data) => { /* Some processing */ },
    collapse: (event, data) => { /* Some processing */ }
  }
];
const conf = defConf('my-tree', children);
conf.child = {
  id: 'id',
  content: 'content',
  onClick: 'click',
  onDoubleClick: 'doubleClick',
  onSelect: 'select',
  onUnselect: 'unselect',
  onExpand: 'expand',
  onCollapse: 'collapse'
};
 
const root = document.getElementById('root');
ReactDOM.render((<Tree conf={ conf } />), root);

Example with function type:

import React from 'react';
import ReactDOM from 'react-dom';
import { Tree, defConf } from 'mini-tree-react';
 
const children = [
  {
    id: 'my-item',
    content: 'My item',
  }
];
const conf = defConf('my-tree', children);
conf.child = {
  id: 'id',
  content: 'content',
  onClick: (event, data) => { /* Some processing */ },
  onDoubleClick: (event, data) => { /* Some processing */ },
  onSelect: (event, data) => { /* Some processing */ },
  onUnselect: (event, data) => { /* Some processing */ },
  onExpand: (event, data) => { /* Some processing */ },
  onCollapse: (event, data) => { /* Some processing */ }
};
 
const root = document.getElementById('root');
ReactDOM.render((<Tree conf={ conf } />), root);

Children methods

Children has methods:

toggleSelected(): void - for select/unselect children;

const tree = findTree('my-tree');
tree.findChild('my-item').toggleSelected();

toggleExpanded(): void - for expand/collapse children;

const tree = findTree('my-tree');
tree.findChild('my-item').toggleExpanded();    

hasChildren(): boolean - for children existence checking;

const child = findTree('my-tree').findChild('my-item');
if (child.hasChildren()) {
  /* some processing */
}

getChildren(): array - for to get children;

const child = findTree('my-tree').findChild('my-item');
// All children selecting
child.getChildren()
     .forEach((child) => child.toggleSelected());

isSelected(): boolean - for current selection value checking;

 const child = findTree('my-tree').findChild('my-item');
 // To get all selected children
 const selectedChildren = child.getChildren()
                               .map((child) => child.isSelected()); 

isExpanded(): boolean - for current expansion value checking;

 const child = findTree('my-tree').findChild('my-item');
 // To get all expanded children
 const selectedChildren = child.getChildren()
                               .map((child) => child.isExpanded()); 

getData(): object - for to get child's data;

 const child = findTree('my-tree').findChild('my-item');
 // To get data of child
 const data = child.getData(); 

getParent(): object - for to get parent;

 // Expand all
 let child = findTree('my-tree').findChild('my-item');
 do {
   child.toggleExpanded();
   child = child.getParent();
 } while (child);
  

Styling

Below you can see base description of mini-tree-react styles. Use this description to simplify styling. Also you can find this description in file: mini-tree-react.css, it is can be load via css-loader and style-loader, more information on css-loader.

.mini-tree {
  padding: 0;
  list-style: none;
  margin-left: 25px;
  border-left: 0.5px solid #ccc;
  overflow: unset !important;
}
.mini-tree-item-behavior {
  display: block;
  line-height: 14px;
  padding: 15px 0 15px 25px;
  cursor: default;
  white-space: nowrap;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
}
.mini-tree-item-behavior:hover {
  color: rgb(99, 122, 156);
  cursor: pointer;
}
.mini-tree-item-behavior.selected {
  color: rgb(64, 116, 191);
}
.mini-tree-item {    
  overflow: hidden;
  position: relative;
}
.mini-tree-item:before {    
  top: 22px;
  width: 15px;
  content: ' ';
  position: absolute;
  display: inline-block;
  border: 0.5px solid #ccc;
}
.mini-tree-item-content {}
.mini-tree-items {
  padding: 0;
  list-style: none;
  margin-left: 25px;
  border-left: 0.5px solid #ccc;
  display: none;
}
.mini-tree-items.expanded {
  display: inherit;
}  

Package Sidebar

Install

npm i mini-tree-react

Weekly Downloads

3

Version

1.1.1

License

Apache-2.0

Unpacked Size

1.18 MB

Total Files

8

Last publish

Collaborators

  • andrey-yurzanov