UNPKG

@atlaskit/tree

Version:

A React Component for displaying expandable and sortable tree hierarchies

88 lines (85 loc) 2.87 kB
import { getParentPath, getIndexAmongSiblings } from './path'; import { mutateTree } from './mutateTree'; /* Transforms tree structure into flat list of items for rendering purposes. We recursively go through all the elements and its children first on each level */ export const flattenTree = (tree, path = []) => tree.items[tree.rootId] ? tree.items[tree.rootId].children.reduce((accum, itemId, index) => { // iterating through all the children on the given level const item = tree.items[itemId]; const currentPath = [...path, index]; // we create a flattened item for the current item const currentItem = createFlattenedItem(item, currentPath); // we flatten its children const children = flattenChildren(tree, item, currentPath); // append to the accumulator return [...accum, currentItem, ...children]; }, []) : []; /* Constructs a new FlattenedItem */ const createFlattenedItem = (item, currentPath) => { return { item, path: currentPath }; }; /* Flatten the children of the given subtree */ const flattenChildren = (tree, item, currentPath) => { return item.isExpanded ? flattenTree({ rootId: item.id, items: tree.items }, currentPath) : []; }; export const getItem = (tree, path) => { let cursor = tree.items[tree.rootId]; for (const i of path) { cursor = tree.items[cursor.children[i]]; } return cursor; }; export const getParent = (tree, path) => { const parentPath = getParentPath(path); return getItem(tree, parentPath); }; export const getTreePosition = (tree, path) => { const parent = getParent(tree, path); const index = getIndexAmongSiblings(path); return { parentId: parent.id, index }; }; const hasLoadedChildren = item => !!item.hasChildren && item.children.length > 0; const isLeafItem = item => !item.hasChildren; export const removeItemFromTree = (tree, position) => { const sourceParent = tree.items[position.parentId]; const newSourceChildren = [...sourceParent.children]; const itemRemoved = newSourceChildren.splice(position.index, 1)[0]; const newTree = mutateTree(tree, position.parentId, { children: newSourceChildren, hasChildren: newSourceChildren.length > 0, isExpanded: newSourceChildren.length > 0 && sourceParent.isExpanded }); return { tree: newTree, itemRemoved }; }; export const addItemToTree = (tree, position, item) => { const destinationParent = tree.items[position.parentId]; const newDestinationChildren = [...destinationParent.children]; if (typeof position.index === 'undefined') { if (hasLoadedChildren(destinationParent) || isLeafItem(destinationParent)) { newDestinationChildren.push(item); } } else { newDestinationChildren.splice(position.index, 0, item); } return mutateTree(tree, position.parentId, { children: newDestinationChildren, hasChildren: true }); };