1.1.0 • Published 2 years ago

tree-handler v1.1.0

Weekly downloads
1
License
MIT
Repository
github
Last release
2 years ago

NPM\ GitHub Workflow Status (branch) codecov Known Vulnerabilities npm version

Tree Handler

tree-handler is a module to easily manipulate tree structures.

API

Parse tree

import treeHandler from 'tree-handler';
const model = {
  id: 'root',
  children: [
    { id: 'A', children: [] },
    { id: 'B', children: [] },
  ],
};
const tree = treeHandler.parse(model);

Parse with a custom children property

import treeHandler from 'tree-handler';
const model = {
  id: 'root',
  subtasks: [
    { id: 'A', subtasks: [] },
    { id: 'B', subtasks: [] },
  ],
};
const tree = treeHandler.parse(model, { childrenProperty: 'subtasks' });

Find a single node that matches a criteria

tree.findOne((node) => node.model.id === 'A');

Find many nodes that match a criteria

tree.find((node) => node.model.type === 'cake');

Add a new node as an object

tree.addChild({ id: '123', type: 'chocolate', children: [] });

Add a new node as a node

const newNode = treeHandler.parse({
  id: '123',
  type: 'chocolate',
  children: [],
});
tree.addChild(newNode);

Delete a node

const node = tree.findOne((node) => node.model.id === 'A');
node.delete();

Move a node under a new parent

const modelA = {
  id: 'A',
  children: [
    { id: 'B', children: [{ id: 'B1', children: [] }] },
    {
      id: 'C',
      children: [
        { id: 'C1', children: [] },
        { id: 'C2', children: [] },
      ],
    },
  ],
};

const tree = treeHandler.parse(modelA);

tree.moveUnderParnet({
  node: (node) => node.model.id === 'B1',
  toParent: (node) => node.model.id === 'C',
  atIndex: 1,
});

Move a node next to a sibling

tree.moveToSibling({
  node: (node) => node.model.id === 'B1',
  toSibling: (node) => node.model.id === 'C2',
  at: 'BEFORE', // options: BEFORE, AFTER
});

Filter Tree Nodes

the filter function will return to us new TreeNode classes based on the filter conditions. There are two modes to filter a tree structure.

Remove Children Mode (Default)

this one is the "expected" way of filtering a tree structure's nodes. If a node should be filtered out, then that node along its children will be removed.

const dataTree = {
  id: '1',
  tag: 'pending',
  subtasks: [
    {
      id: '2',
      tag: 'pending',
      subtasks: [
        { id: '4', tag: 'complete', subtasks: [] },
        { id: '46', tag: 'in progress', subtasks: [] },
      ],
    },
    {
      id: '3',
      tag: 'in progress',
      subtasks: [
        {
          id: '4',
          tag: 'pending',
          subtasks: [
            {
              id: '6',
              tag: 'complete',
              subtasks: [
                {
                  id: '10',
                  tag: 'pending',
                  subtasks: [{ id: '11', tag: 'complete', subtasks: [] }],
                },
              ],
            },
            {
              id: '7',
              tag: 'complete',
              subtasks: [{ id: '74', tag: 'in progress', subtasks: [] }],
            },
          ],
        },
        { id: '5', tag: 'pending', subtasks: [] },
      ],
    },
    { id: '4', tag: 'complete', subtasks: [] },
  ],
};

const tree = treeHandler.parse(dataTree, {
  childrenProperty: 'subtasks',
});
const newTree = tree.filter((node) => node.tag !== 'in progress');

console.log(newTree);

result:

{
  id: '1',
  tag: 'pending',
  subtasks: [
    {
      id: '2',
      tag: 'pending',
      subtasks: [{ id: '4', tag: 'complete', subtasks: [] }],
    },
    { id: '4', tag: 'complete', subtasks: [] },
  ],
};

Merge Children Mode

this filtering method is unique. What it does is that it filtering out each node indiviually. Meaning if a node should be filtered out, and if it has children that should not be filtered out, then those children will be moved to the same depth level and starting index number of their parent.

const dataTree = {
  id: '1',
  tag: 'pending',
  subtasks: [
    { id: '2', tag: 'pending', subtasks: [] },
    {
      id: '3',
      tag: 'in progress',
      subtasks: [
        {
          id: '4',
          tag: 'pending',
          subtasks: [
            {
              id: '6',
              tag: 'complete',
              subtasks: [
                {
                  id: '10',
                  tag: 'pending',
                  subtasks: [{ id: '10', tag: 'complete', subtasks: [] }],
                },
              ],
            },
            { id: '7', tag: 'complete', subtasks: [] },
          ],
        },
        { id: '5', tag: 'pending', subtasks: [] },
      ],
    },
    { id: '4', tag: 'complete', subtasks: [] },
  ],
};

const treeResult =
const tree = treeHandler.parse(dataTree, { childrenProperty: 'subtasks' });
const newTrees = tree.filter(
  (node) => node.tag !== 'in progress',
  'mergeChildren'
);

console.log(newTrees)

result:

[
  {
    id: '1',
    tag: 'pending',
    subtasks: [
      { id: '2', tag: 'pending', subtasks: [] },
      {
        id: '4',
        tag: 'pending',
        subtasks: [
          {
            id: '6',
            tag: 'complete',
            subtasks: [
              {
                id: '10',
                tag: 'pending',
                subtasks: [{ id: '10', tag: 'complete', subtasks: [] }],
              },
            ],
          },
          { id: '7', tag: 'complete', subtasks: [] },
        ],
      },
      { id: '5', tag: 'pending', subtasks: [] },
      { id: '4', tag: 'complete', subtasks: [] },
    ],
  },
];

Flatten tree to array of nodes

tree.flatten();

Loop across every node in the tree

tree.forEach((node) => {
  console.log(node);
});

Credits

Heavily inspired by tree-model

1.1.0

2 years ago

10.0.11

4 years ago

1.0.11

4 years ago

1.0.10

4 years ago

1.0.9

4 years ago

1.0.8

4 years ago

1.0.7

4 years ago

1.0.6

4 years ago

1.0.5

4 years ago

1.0.4

4 years ago

1.0.3

4 years ago

1.0.2

4 years ago

1.0.1

4 years ago

1.0.0

4 years ago