Restructure code
This commit is contained in:
144
mixins/tree-managed-state.js
Normal file
144
mixins/tree-managed-state.js
Normal file
@@ -0,0 +1,144 @@
|
||||
export const TreeManagedStateMixin = (superClass) => class TreeManagedStateMixin extends superClass {
|
||||
_isExpandableNode(node) {
|
||||
if (!node) return false;
|
||||
if (Array.isArray(node.children) && node.children.length > 0) return true;
|
||||
if (typeof this.loadChildren === 'function') {
|
||||
if (typeof node.showAsExpandable === 'boolean') return node.showAsExpandable;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
_findNodeByKey(key) {
|
||||
let found = null;
|
||||
const walk = (nodes, path) => {
|
||||
if (!Array.isArray(nodes)) return;
|
||||
nodes.forEach((node, index) => {
|
||||
if (found) return;
|
||||
const slug = node?.slug ?? `${index}`;
|
||||
const nextPath = [...path, slug];
|
||||
const nodeKey = nextPath.join('/');
|
||||
if (nodeKey === key) {
|
||||
found = node;
|
||||
return;
|
||||
}
|
||||
if (Array.isArray(node?.children) && node.children.length > 0) {
|
||||
walk(node.children, nextPath);
|
||||
}
|
||||
});
|
||||
};
|
||||
walk(this.roots, []);
|
||||
return found;
|
||||
}
|
||||
|
||||
getRootKey() {
|
||||
const roots = Array.isArray(this.roots) ? this.roots : [];
|
||||
if (!roots.length) return '';
|
||||
const first = roots[0];
|
||||
const slug = first?.slug ?? '0';
|
||||
return String(slug);
|
||||
}
|
||||
|
||||
_updateNodeStatesByKey(key, updater) {
|
||||
const map = (nodes, path = []) => {
|
||||
if (!Array.isArray(nodes)) return nodes;
|
||||
return nodes.map((node, index) => {
|
||||
const slug = node?.slug ?? `${index}`;
|
||||
const nextPath = [...path, slug];
|
||||
const nodeKey = nextPath.join('/');
|
||||
|
||||
let nextNode = node;
|
||||
if (nodeKey === key) {
|
||||
nextNode = updater(node) ?? node;
|
||||
}
|
||||
|
||||
const children = Array.isArray(nextNode?.children)
|
||||
? map(nextNode.children, nextPath)
|
||||
: nextNode?.children;
|
||||
|
||||
if (children !== nextNode?.children) {
|
||||
return { ...nextNode, children };
|
||||
}
|
||||
|
||||
return nextNode;
|
||||
});
|
||||
};
|
||||
|
||||
this.roots = map(this.roots);
|
||||
}
|
||||
|
||||
_applySelectionStates() {
|
||||
const selected = new Set(this._selectedPathSet);
|
||||
const selectionState = this.selectionState;
|
||||
const { nodes } = this._mapTree(this.roots, (node, path) => {
|
||||
const key = Array.isArray(path) ? path.join('/') : '';
|
||||
const states = Array.isArray(node?.states) ? node.states : [];
|
||||
const without = states.filter((s) => s !== selectionState);
|
||||
if (selected.has(key)) {
|
||||
if (!without.includes(selectionState)) without.push(selectionState);
|
||||
return { ...node, states: without };
|
||||
}
|
||||
if (without.length !== states.length) {
|
||||
return { ...node, states: without };
|
||||
}
|
||||
return node;
|
||||
});
|
||||
this.roots = nodes;
|
||||
}
|
||||
|
||||
_rebuildManagedTree() {
|
||||
this._expandedPathSet = new Set(this.expandedPaths || this._expandedPathSet);
|
||||
this._selectedPathSet = new Set(this.selectedPaths || this._selectedPathSet);
|
||||
|
||||
const { nodes, allPaths, expandedPaths, selectedPaths } = this.constructor.buildTree(
|
||||
Array.isArray(this.items) ? this.items : [],
|
||||
{
|
||||
expandedPaths: this._expandedPathSet,
|
||||
selectedPaths: this._selectedPathSet,
|
||||
selectionState: this.selectionState,
|
||||
applyStates: this.applyStates,
|
||||
knownPaths: this._knownPaths,
|
||||
autoExpandNew: this.autoExpandNew,
|
||||
}
|
||||
);
|
||||
|
||||
this._knownPaths = allPaths;
|
||||
this._expandedPathSet = new Set([...expandedPaths].filter((p) => allPaths.has(p)));
|
||||
this._selectedPathSet = new Set([...selectedPaths].filter((p) => allPaths.has(p)));
|
||||
this.roots = nodes;
|
||||
}
|
||||
|
||||
getNodesWithState(state) {
|
||||
const matches = [];
|
||||
this._walkNodes(this.roots, [], (node, path) => {
|
||||
if (Array.isArray(node?.states) && node.states.includes(state)) {
|
||||
matches.push({ node, path });
|
||||
}
|
||||
});
|
||||
return matches;
|
||||
}
|
||||
|
||||
clearState(state) {
|
||||
const { nodes } = this._mapTree(this.roots, (node) => {
|
||||
const states = Array.isArray(node?.states)
|
||||
? node.states.filter((s) => s !== state)
|
||||
: [];
|
||||
const changed = (node.states?.length ?? 0) !== states.length;
|
||||
return changed ? { ...node, states } : node;
|
||||
});
|
||||
return nodes;
|
||||
}
|
||||
|
||||
applyStateIf(state, predicate) {
|
||||
if (typeof predicate !== 'function') return this.roots;
|
||||
const { nodes } = this._mapTree(this.roots, (node, path) => {
|
||||
const states = Array.isArray(node?.states) ? [...node.states] : [];
|
||||
if (predicate(node, path) && !states.includes(state)) {
|
||||
states.push(state);
|
||||
return { ...node, states };
|
||||
}
|
||||
return node;
|
||||
});
|
||||
return nodes;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user