@atlaskit/tree
Version:
A React Component for displaying expandable and sortable tree hierarchies
125 lines • 4.49 kB
JavaScript
import { __assign, __read, __spread, __values } from "tslib";
import { getParentPath, getIndexAmongSiblings } from './path';
/*
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 var flattenTree = function (tree, path) {
if (path === void 0) { path = []; }
return tree.items[tree.rootId]
? tree.items[tree.rootId].children.reduce(function (accum, itemId, index) {
// iterating through all the children on the given level
var item = tree.items[itemId];
var currentPath = __spread(path, [index]);
// we create a flattened item for the current item
var currentItem = createFlattenedItem(item, currentPath);
// we flatten its children
var children = flattenChildren(tree, item, currentPath);
// append to the accumulator
return __spread(accum, [currentItem], children);
}, [])
: [];
};
/*
Constructs a new FlattenedItem
*/
var createFlattenedItem = function (item, currentPath) {
return {
item: item,
path: currentPath,
};
};
/*
Flatten the children of the given subtree
*/
var flattenChildren = function (tree, item, currentPath) {
return item.isExpanded
? flattenTree({ rootId: item.id, items: tree.items }, currentPath)
: [];
};
/*
Changes the tree data structure with minimal reference changes.
*/
export var mutateTree = function (tree, itemId, mutation) {
var _a;
var itemToChange = tree.items[itemId];
if (!itemToChange) {
// Item not found
return tree;
}
// Returning a clone of the tree structure and overwriting the field coming in mutation
return {
// rootId should not change
rootId: tree.rootId,
items: __assign(__assign({}, tree.items), (_a = {}, _a[itemId] = __assign(__assign({}, itemToChange), mutation), _a)),
};
};
export var getItem = function (tree, path) {
var e_1, _a;
var cursor = tree.items[tree.rootId];
try {
for (var path_1 = __values(path), path_1_1 = path_1.next(); !path_1_1.done; path_1_1 = path_1.next()) {
var i = path_1_1.value;
cursor = tree.items[cursor.children[i]];
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (path_1_1 && !path_1_1.done && (_a = path_1.return)) _a.call(path_1);
}
finally { if (e_1) throw e_1.error; }
}
return cursor;
};
export var getParent = function (tree, path) {
var parentPath = getParentPath(path);
return getItem(tree, parentPath);
};
export var getTreePosition = function (tree, path) {
var parent = getParent(tree, path);
var index = getIndexAmongSiblings(path);
return {
parentId: parent.id,
index: index,
};
};
var hasLoadedChildren = function (item) {
return !!item.hasChildren && item.children.length > 0;
};
var isLeafItem = function (item) { return !item.hasChildren; };
var removeItemFromTree = function (tree, position) {
var sourceParent = tree.items[position.parentId];
var newSourceChildren = __spread(sourceParent.children);
var itemRemoved = newSourceChildren.splice(position.index, 1)[0];
var newTree = mutateTree(tree, position.parentId, {
children: newSourceChildren,
hasChildren: newSourceChildren.length > 0,
isExpanded: newSourceChildren.length > 0 && sourceParent.isExpanded,
});
return {
tree: newTree,
itemRemoved: itemRemoved,
};
};
var addItemToTree = function (tree, position, item) {
var destinationParent = tree.items[position.parentId];
var newDestinationChildren = __spread(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,
});
};
export var moveItemOnTree = function (tree, from, to) {
var _a = removeItemFromTree(tree, from), treeWithoutSource = _a.tree, itemRemoved = _a.itemRemoved;
return addItemToTree(treeWithoutSource, to, itemRemoved);
};
//# sourceMappingURL=tree.js.map