@keenmate/svelte-treeview 0.2.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,82 @@
1
+ export class PropertyHelper {
2
+ props;
3
+ constructor(props) {
4
+ this.props = props;
5
+ }
6
+ getVal(node, key) {
7
+ return node?.[key];
8
+ }
9
+ setVal(node, key, value) {
10
+ node[key] = value;
11
+ }
12
+ path(node) {
13
+ // root node
14
+ if (node === null) {
15
+ return null;
16
+ }
17
+ return this.getVal(node, this.props.nodePath);
18
+ }
19
+ setPath(node, path) {
20
+ this.setVal(node, this.props.nodePath, path);
21
+ }
22
+ hasChildren(node) {
23
+ return this.getVal(node, this.props.hasChildren) ?? false;
24
+ }
25
+ setHasChildren(node, hasChildren) {
26
+ this.setVal(node, this.props.hasChildren, hasChildren);
27
+ }
28
+ expanded(node) {
29
+ return this.getVal(node, this.props.expanded) ?? null;
30
+ }
31
+ setExpanded(node, expanded) {
32
+ this.setVal(node, this.props.expanded, expanded);
33
+ }
34
+ selected(node) {
35
+ return this.getVal(node, this.props.selected);
36
+ }
37
+ setSelected(node, selected) {
38
+ this.setVal(node, this.props.selected, selected);
39
+ }
40
+ useCallback(node) {
41
+ return this.getVal(node, this.props.useCallback) ?? false;
42
+ }
43
+ setUseCallback(node, useCallback) {
44
+ this.setVal(node, this.props.useCallback, useCallback);
45
+ }
46
+ priority(node) {
47
+ return this.getVal(node, this.props.priority) ?? 0;
48
+ }
49
+ setPriority(node, priority) {
50
+ this.setVal(node, this.props.priority, priority);
51
+ }
52
+ isDraggable(node) {
53
+ return this.getVal(node, this.props.isDraggable) ?? false;
54
+ }
55
+ setIsDraggable(node, isDraggable) {
56
+ this.setVal(node, this.props.isDraggable, isDraggable);
57
+ }
58
+ insertDisabled(node) {
59
+ return this.getVal(node, this.props.insertDisabled) ?? false;
60
+ }
61
+ setInsertDisabled(node, insertDisabled) {
62
+ this.setVal(node, this.props.insertDisabled, insertDisabled);
63
+ }
64
+ nestDisabled(node) {
65
+ return this.getVal(node, this.props.nestDisabled) ?? false;
66
+ }
67
+ setNestDisabled(node, nestDisabled) {
68
+ this.setVal(node, this.props.nestDisabled, nestDisabled);
69
+ }
70
+ checkbox(node) {
71
+ return this.getVal(node, this.props.checkbox) ?? null;
72
+ }
73
+ setCheckbox(node, checkbox) {
74
+ this.setVal(node, this.props.checkbox, checkbox);
75
+ }
76
+ visualState(node) {
77
+ return this.getVal(node, this.props.visualState) ?? null;
78
+ }
79
+ setVisualState(node, visualState) {
80
+ this.setVal(node, this.props.visualState, visualState);
81
+ }
82
+ }
@@ -1,22 +1,30 @@
1
- export class SelectionHelper {
2
- constructor(treeHelper: any);
3
- helper: any;
4
- props: any;
5
- path(node: any): any;
6
- selected(node: any): any;
7
- getChildrenWithCheckboxes(tree: any, parentNodePath: any): any;
8
- changeSelection(tree: any, nodePath: any, filteredTree: any): any;
9
- toggleSelected(tree: any, nodePath: any): void;
10
- changeSelectedForChildren(tree: any, parentNodePath: any, changeTo: any, filteredTree: any): any;
11
- updateLeafNodeSelection(node: any, changeTo: any): void;
12
- /**Calculates visual state based on children */
13
- getVisualState(filteredTree: any, node: any): string;
14
- /** recursibly recomputes parent visual state until root */
15
- recomputeAllParentVisualState(tree: any, filteredTree: any, nodePath: any): any;
1
+ import type { PropertyHelper } from './property-helper.js';
2
+ import type { TreeHelper } from './tree-helper.js';
3
+ import { SelectionModes, type Node, type NodePath, type Tree } from '../types.js';
4
+ export declare class SelectionHelper {
5
+ helper: TreeHelper;
6
+ props: PropertyHelper;
7
+ recursiveMode: boolean;
8
+ constructor(treeHelper: TreeHelper, recursive: boolean);
9
+ private path;
10
+ isSelected(node: Node): boolean;
11
+ getSelectableDirectChildren(tree: Tree, parentNodePath: string | null): unknown[];
12
+ setSelection(tree: Tree, nodePath: NodePath, changeTo: boolean): void;
13
+ private changeSelectedRecursively;
16
14
  /** Computes visual states for all nodes. Used for computing initial visual states when tree changes */
17
- computeInitialVisualStates(tree: any, filteredTree: any): any;
18
- /** Recursivly computes visual state for children */
19
- computeChildrenVisualStates(tree: any, filteredTree: any, node: any): any;
20
- deleteSelected(tree: any): any;
21
- isSelectable(node: any, showCheckboxes: any): boolean;
15
+ recomputeAllVisualStates(tree: Tree): void;
16
+ deleteSelected(tree: Tree): void;
17
+ isSelectable(node: Node, showCheckboxes: SelectionModes): boolean;
18
+ private computeVisualStates;
19
+ /** recursibly recomputes parent visual state until root */
20
+ private recomputeParentVisualState;
21
+ /**
22
+ * Computes visual state from leaf to node
23
+ * @param tree
24
+ * @param filteredTree
25
+ * @param node
26
+ * @returns New visual state for node
27
+ */
28
+ private computeVisualStateRecursively;
29
+ private getVisualState;
22
30
  }
@@ -1,182 +1,148 @@
1
- // @ts-nocheck
2
- import { checkboxesType, visualStateType } from "../consts";
3
-
4
- export class SelectionHelper {
5
- constructor(treeHelper) {
6
- this.helper = treeHelper;
7
- this.props = treeHelper.props;
8
- }
9
-
10
- path(node) {
11
- return this.helper.path(node);
12
- }
13
- selected(node) {
14
- return node[this.props.selected];
15
- }
16
-
17
- getChildrenWithCheckboxes(tree, parentNodePath) {
18
- return this.helper
19
- .getDirectChildren(tree, parentNodePath)
20
- .filter((node) => this.isSelectable(node, checkboxesType.all));
21
- }
22
-
23
- changeSelection(tree, nodePath, filteredTree) {
24
- this.toggleSelected(tree, nodePath);
25
-
26
- const recursive = this.helper.config?.recursive ?? false;
27
-
28
- if (recursive) {
29
- tree = this.recomputeAllParentVisualState(tree, filteredTree, nodePath);
30
- }
31
-
32
- return tree;
33
- }
34
-
35
- toggleSelected(tree, nodePath) {
36
- const node = this.helper.findNode(tree, nodePath);
37
-
38
- node[this.props.selected] = !node[this.props.selected];
39
- }
40
-
41
- changeSelectedForChildren(tree, parentNodePath, changeTo, filteredTree) {
42
- tree = tree.map((node) => {
43
- //changes itself
44
- if (parentNodePath == this.path(node)) {
45
- this.updateLeafNodeSelection(node, changeTo);
46
- }
47
-
48
- if (!parentNodePath) {
49
- // TODO i think this isnt working
50
- // this only updates
51
-
52
- //top level
53
- this.updateLeafNodeSelection(node, changeTo);
54
- } else {
55
- //if parentNodePath isnt root
56
- if (
57
- this.path(node).startsWith(parentNodePath.toString()) &&
58
- this.path(node) != parentNodePath.toString()
59
- ) {
60
- this.updateLeafNodeSelection(node, changeTo);
61
- }
62
- }
63
- return node;
64
- });
65
-
66
- tree = this.recomputeAllParentVisualState(
67
- tree,
68
- filteredTree,
69
- parentNodePath
70
- );
71
- return tree;
72
- }
73
-
74
- //changes selected or visual state depending on
75
- updateLeafNodeSelection(node, changeTo) {
76
- //dont change if not selectable
77
- if (!this.isSelectable(node, checkboxesType.all)) {
78
- return;
79
- }
80
- if (!node[this.props.hasChildren]) {
81
- node[this.props.selected] = changeTo;
82
- } else {
83
- node.__visual_state = changeTo.toString();
84
- }
85
- }
86
-
87
- /**Calculates visual state based on children */
88
- getVisualState(filteredTree, node) {
89
- const children = this.getChildrenWithCheckboxes(
90
- filteredTree,
91
- this.path(node)
92
- );
93
-
94
- if (!children || children?.length == 0) return visualStateType.notSelected;
95
-
96
- //if every child is selected or vs=true return true
97
- if (
98
- children.every(
99
- (x) =>
100
- x[this.props.selected] === true ||
101
- x.__visual_state === visualStateType.selected
102
- )
103
- ) {
104
- return visualStateType.selected;
105
- }
106
- //at least sone child is selected or indeterminate
107
- else if (
108
- children.some((x) => {
109
- return (
110
- x[this.props.selected] === true ||
111
- x.__visual_state === visualStateType.indeterminate ||
112
- x.__visual_state === visualStateType.selected
113
- );
114
- })
115
- ) {
116
- return visualStateType.indeterminate;
117
- } else {
118
- return visualStateType.notSelected;
119
- }
120
- }
121
-
122
- /** recursibly recomputes parent visual state until root */
123
- recomputeAllParentVisualState(tree, filteredTree, nodePath) {
124
- const parent = this.helper.getParentNodePath(nodePath);
125
-
126
- let newstate;
127
- filteredTree.forEach((x) => {
128
- if (this.path(x) == parent) {
129
- newstate = this.getVisualState(filteredTree, x);
130
- x.__visual_state = newstate;
131
- }
132
- });
133
- if (this.helper.getParentNodePath(parent) != "") {
134
- tree = this.recomputeAllParentVisualState(tree, filteredTree, parent);
135
- }
136
- return tree;
137
- }
138
-
139
- /** Computes visual states for all nodes. Used for computing initial visual states when tree changes */
140
- computeInitialVisualStates(tree, filteredTree) {
141
- let rootELements = this.getChildrenWithCheckboxes(tree, null);
142
- rootELements.forEach((x) => {
143
- if (x[this.props.hasChildren] == true) {
144
- tree = this.computeChildrenVisualStates(tree, filteredTree, x);
145
- x.__visual_state = this.getVisualState(filteredTree, x);
146
- }
147
- });
148
- return tree;
149
- }
150
- /** Recursivly computes visual state for children */
151
- computeChildrenVisualStates(tree, filteredTree, node) {
152
- let children = this.getChildrenWithCheckboxes(tree, this.path(node));
153
- //foreaches all children if it has children, it calls itself, then it computes __vs => will compute from childern to parent
154
- children.forEach((x) => {
155
- if (x[this.props.hasChildren] === true) {
156
- tree = this.computeChildrenVisualStates(tree, filteredTree, x);
157
- x.__visual_state = this.getVisualState(filteredTree, x);
158
- }
159
- });
160
- return tree;
161
- }
162
-
163
- deleteSelected(tree) {
164
- return tree.map((node) => {
165
- node[this.props.selected] = false;
166
- node.__visual_state = undefined;
167
- return node;
168
- });
169
- }
170
-
171
- isSelectable(node, showCheckboxes) {
172
- if (showCheckboxes == checkboxesType.all) {
173
- return node[this.props.checkbox] !== false;
174
- }
175
- //show only if pop is true
176
- if (showCheckboxes == checkboxesType.perNode) {
177
- return node[this.props.checkbox] === true;
178
- }
179
- //dont show at all
180
- return false;
181
- }
182
- }
1
+ import { SelectionModes, VisualStates } from '../types.js';
2
+ export class SelectionHelper {
3
+ helper;
4
+ props;
5
+ recursiveMode;
6
+ constructor(treeHelper, recursive) {
7
+ this.helper = treeHelper;
8
+ this.props = treeHelper.props;
9
+ this.recursiveMode = recursive;
10
+ }
11
+ path(node) {
12
+ return this.helper.path(node);
13
+ }
14
+ isSelected(node) {
15
+ return (this.props.selected(node) === true || this.props.visualState(node) === VisualStates.selected);
16
+ }
17
+ getSelectableDirectChildren(tree, parentNodePath) {
18
+ return this.helper
19
+ .getDirectChildren(tree, parentNodePath)
20
+ .filter((node) => this.isSelectable(node, SelectionModes.all));
21
+ }
22
+ setSelection(tree, nodePath, changeTo) {
23
+ const node = this.helper.findNode(tree, nodePath);
24
+ // allow selection of root node
25
+ if ((this.recursiveMode && this.props.hasChildren(node)) || nodePath === null) {
26
+ this.changeSelectedRecursively(tree, nodePath, changeTo);
27
+ }
28
+ else {
29
+ if (!node) {
30
+ // throw new Error('Node not found ' + nodePath);
31
+ console.warn('Node %s doesnt exits', nodePath);
32
+ return;
33
+ }
34
+ this.props.setSelected(node, changeTo);
35
+ }
36
+ }
37
+ changeSelectedRecursively(tree, parentNodePath, changeTo) {
38
+ tree.forEach((node) => {
39
+ // match itself and all children
40
+ if (this.path(node)?.startsWith(parentNodePath ?? '')) {
41
+ //dont change if not selectable
42
+ if (!this.isSelectable(node, SelectionModes.all)) {
43
+ return;
44
+ }
45
+ // in recursive mode only update leaf nodes
46
+ if (this.recursiveMode && this.props.hasChildren(node)) {
47
+ return;
48
+ }
49
+ this.props.setSelected(node, changeTo);
50
+ }
51
+ });
52
+ }
53
+ /** Computes visual states for all nodes. Used for computing initial visual states when tree changes */
54
+ recomputeAllVisualStates(tree) {
55
+ // TODO is this really the case?
56
+ // if some node is not selectable, are all its children also not selectable?
57
+ const rootELements = this.getSelectableDirectChildren(tree, null);
58
+ rootELements.forEach((x) => {
59
+ if (this.props.hasChildren(x) == true) {
60
+ const result = this.computeVisualStateRecursively(tree, x);
61
+ this.props.setVisualState(x, result.state);
62
+ }
63
+ });
64
+ }
65
+ deleteSelected(tree) {
66
+ return tree.forEach((node) => {
67
+ this.props.setSelected(node, false);
68
+ this.props.setVisualState(node, null);
69
+ });
70
+ }
71
+ isSelectable(node, showCheckboxes) {
72
+ if (showCheckboxes === SelectionModes.all) {
73
+ return this.props.checkbox(node) !== false;
74
+ }
75
+ //show only if pop is true
76
+ if (showCheckboxes === SelectionModes.perNode) {
77
+ return this.props.checkbox(node) === true;
78
+ }
79
+ //dont show at all
80
+ return false;
81
+ }
82
+ computeVisualStates(directChildrenVisualStates) {
83
+ if (!directChildrenVisualStates || directChildrenVisualStates?.length == 0)
84
+ return VisualStates.selected;
85
+ //if every child is selected or vs=true return true
86
+ if (directChildrenVisualStates.every((state) => state === VisualStates.selected)) {
87
+ return VisualStates.selected;
88
+ }
89
+ //at least sone child is selected or indeterminate
90
+ else if (directChildrenVisualStates.some((state) => state === VisualStates.selected || state === VisualStates.indeterminate)) {
91
+ return VisualStates.indeterminate;
92
+ }
93
+ else {
94
+ return VisualStates.notSelected;
95
+ }
96
+ }
97
+ /** recursibly recomputes parent visual state until root */
98
+ recomputeParentVisualState(tree, filteredTree, nodePath) {
99
+ // no need to recompute state for root
100
+ if (nodePath === null) {
101
+ return;
102
+ }
103
+ // TODO maybe check that this node have children
104
+ const parentNode = this.helper.findNode(tree, nodePath);
105
+ const directChildren = this.helper.getDirectChildren(tree, nodePath);
106
+ const directChildrenVisualStates = directChildren.map((node) => this.getVisualState(node));
107
+ const newState = this.computeVisualStates(directChildrenVisualStates);
108
+ this.props.setVisualState(parentNode, newState);
109
+ // use recursion, because we need to traverse from node to root
110
+ const ParentPath = this.helper.getParentNodePath(nodePath);
111
+ this.recomputeParentVisualState(tree, filteredTree, ParentPath);
112
+ }
113
+ /**
114
+ * Computes visual state from leaf to node
115
+ * @param tree
116
+ * @param filteredTree
117
+ * @param node
118
+ * @returns New visual state for node
119
+ */
120
+ computeVisualStateRecursively(tree, node) {
121
+ const directChildren = this.getSelectableDirectChildren(tree, this.path(node));
122
+ const directChildrenStates = [];
123
+ // using recustion compute from leaft nodes to root
124
+ directChildren.forEach((child) => {
125
+ if (!this.props.hasChildren(child)) {
126
+ const childState = this.isSelected(child)
127
+ ? VisualStates.selected
128
+ : VisualStates.notSelected;
129
+ directChildrenStates.push(childState);
130
+ return;
131
+ }
132
+ const result = this.computeVisualStateRecursively(tree, child);
133
+ this.props.setVisualState(child, result.state);
134
+ if (!result.ignore) {
135
+ directChildrenStates.push(result.state);
136
+ }
137
+ });
138
+ // if no children, all are selected, but dont count it for recursive computationq
139
+ const ignore = directChildrenStates.length === 0;
140
+ return { ignore, state: this.computeVisualStates(directChildrenStates) };
141
+ }
142
+ getVisualState(node) {
143
+ if (this.props.hasChildren(node)) {
144
+ return this.props.visualState(node) ?? VisualStates.notSelected;
145
+ }
146
+ return this.isSelected(node) ? VisualStates.selected : VisualStates.notSelected;
147
+ }
148
+ }
@@ -1,33 +1,34 @@
1
- export class TreeHelper {
2
- constructor(propNames: any, config?: {});
3
- props: any;
4
- config: {};
1
+ import { SelectionHelper } from './selection-helpers.js';
2
+ import { DragAndDropHelper } from './drag-drop-helpers.js';
3
+ import type { Node, NodePath, HelperConfig } from '../types.js';
4
+ import type { PropertyHelper } from './property-helper.js';
5
+ export declare class TreeHelper {
6
+ props: PropertyHelper;
7
+ config: HelperConfig;
5
8
  selection: SelectionHelper;
6
9
  dragDrop: DragAndDropHelper;
7
- path(node: any): any;
8
- getParentNodePath(nodePath: any): any;
9
- hasChildren(tree: any, nodePath: any): any;
10
- findNode(tree: any, nodePath: any): any;
11
- nodePathIsChild(nodePath: any): any;
12
- getDirectChildren(tree: any, parentNodePath: any): any;
13
- allCHildren(tree: any, parentNodePath: any): any;
14
- getAllLeafNodes(tree: any): any;
15
- joinTrees(filteredTree: any, tree: any): any;
16
- mergeTrees(oldTree: any, addedTree: any, nodePath?: string): any;
10
+ constructor(props: PropertyHelper, config?: HelperConfig);
11
+ path(node: Node | null): NodePath;
12
+ getParentNodePath(nodePath: NodePath): NodePath;
13
+ isChildrenOf(parentNodePath: NodePath, childrenNodePath: NodePath): boolean | undefined;
14
+ hasChildren(tree: Node[], nodePath: NodePath): unknown;
15
+ findNode(tree: Node[], nodePath: NodePath): Node;
16
+ nodePathIsChild(nodePath: NodePath): boolean | undefined;
17
+ getDirectChildren(tree: Node[], parentNodePath: NodePath): unknown[];
18
+ allCHildren(tree: Node[], parentNodePath: NodePath): unknown[];
19
+ getAllLeafNodes(tree: Node[]): unknown[];
20
+ joinTrees(filteredTree: Node[], tree: Node[]): unknown[];
21
+ mergeTrees(oldTree: Node[], addedTree: Node[], nodePath?: string): unknown[];
17
22
  /** toggles expansion on
18
23
  */
19
- changeExpansion(tree: any, node: any, changeTo: any): void;
24
+ changeExpansion(tree: Node[], node: Node, changeTo: boolean): void;
20
25
  /** changes expansion of every node that has this.hasChildren set to true
21
26
  */
22
- changeEveryExpansion(tree: any, changeTo: any): any;
27
+ changeEveryExpansion(tree: Node[], changeTo: boolean): unknown[];
23
28
  /** changes expansion of every node that has this.hasChildren set to true if they are abose set level and expansion property isnt set
24
29
  */
25
- expandToLevel(tree: any, level: any): any;
26
- getDepthLevel(nodePath: any): number;
27
- searchTree(tree: any, filter: any, leafesOnly: any): any;
28
- getParents(tree: any, node: any): any;
30
+ expandToLevel(tree: Node[], level: number): unknown[];
31
+ getDepthLevel(nodePath: NodePath): number;
32
+ searchTree(tree: Node[], filter: (node: unknown) => boolean): unknown[];
33
+ getParents(tree: Node[], node: Node): unknown[];
29
34
  }
30
- declare function _default(...args: any[]): TreeHelper;
31
- export default _default;
32
- import { SelectionHelper } from './selection-helpers';
33
- import { DragAndDropHelper } from './drag-drop-helpers';