svelte-tree-view
Version:
Display JSON objects in a customizable tree-view
73 lines (72 loc) • 3.21 kB
JavaScript
import { get, writable } from 'svelte/store';
import { createNode, recurseObjectProperties } from '../tree-utils';
export const createTreeStore = (propsStore) => {
const defaultRootNode = createNode(0, 'root', [], 0, null);
const tree = writable(defaultRootNode);
const treeMap = writable(new Map());
const iteratedValues = writable(new Map());
return {
tree,
treeMap,
defaultRootNode,
init(newTree, newTreeMap, iterated) {
if (newTree) {
tree.set(newTree);
}
else {
tree.set(defaultRootNode);
}
treeMap.set(newTreeMap);
iteratedValues.set(iterated);
},
getNode(id) {
return get(treeMap).get(id);
},
toggleCollapse(id) {
const node = get(treeMap).get(id);
if (!node) {
console.warn(`Attempted to collapse non-existent node: ${id}`);
return;
}
const updatedNode = { ...node, collapsed: !node.collapsed };
treeMap.update(m => new Map(m.set(node.id, updatedNode)));
const recursionOpts = get(propsStore.recursionOpts);
if (recursionOpts) {
this.expandNodeChildren(updatedNode, recursionOpts);
}
},
expandNodeChildren(node, recursionOpts) {
const parent = this.getNode((node === null || node === void 0 ? void 0 : node.parentId) || '') || null;
if (!parent) {
// Only root node has no parent and it should not be expandable
throw Error('No parent in expandNodeChildren for node: ' + node);
}
const newTreeMap = new Map(get(treeMap));
const oldTreeMap = get(treeMap);
const previouslyIterated = get(iteratedValues);
const nodeWithUpdatedChildren = recurseObjectProperties(node.index, node.key, node.value, node.depth, !node.collapsed, // Ensure that when uncollapsed the node's children are always recursed
parent, newTreeMap, oldTreeMap, previouslyIterated, false, // Never recompute shouldExpandNode since it may override the collapsing of this node
recursionOpts);
if (!nodeWithUpdatedChildren)
return;
parent.children = parent.children.map(c => c.id === nodeWithUpdatedChildren.id ? nodeWithUpdatedChildren : c);
newTreeMap.set(nodeWithUpdatedChildren.id, nodeWithUpdatedChildren);
newTreeMap.set(parent.id, parent);
treeMap.set(newTreeMap);
iteratedValues.set(previouslyIterated);
},
expandAllNodesToNode(id) {
function recurseNodeUpwards(updated, node) {
if (!node)
return;
updated.set(node.id, { ...node, collapsed: false });
if (node.parentId) {
recurseNodeUpwards(updated, updated.get(node.parentId));
}
}
const updated = new Map(get(treeMap));
recurseNodeUpwards(updated, updated.get(id));
treeMap.set(updated);
}
};
};