@keenmate/svelte-treeview 0.1.0

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,29 @@
1
+ export class DragAndDropHelper {
2
+ constructor(treeHelper: any);
3
+ helper: any;
4
+ props: any;
5
+ separator: any;
6
+ path(node: any): any;
7
+ /**
8
+ * moves node from one parent to another
9
+ * @param {Object[]} tree - tree
10
+ * @param {nodePath} movedNodePath - nodepath of moved(dragged) node
11
+ * @param {nodePath} targetNodePath - nodepath of node where it should be moved ( either bellow it in priority or as child)
12
+ * @param {int} insType - if true, it will insert moved node as child of target node, if false, it will insert it bellow it in priority
13
+ * @param {boolean} recalculateNodePath - wont recalculare id of moved node, used when last part of nodePath is always unique
14
+ */
15
+ moveNode(tree: Object[], movedNodePath: nodePath, targetNodePath: nodePath, insType: int, recalculateNodePath: boolean): Object[] | undefined;
16
+ calculateNewNodePath(tree: any, parentNodePath: any, movedNodePath: any, recalculateNodePath: any): any;
17
+ updatePriority(tree: any, node: any, parentNodePath: any, newNodePath: any, targetNode: any, insType: any): void;
18
+ /** recomputes all priorities after inserted priority.F
19
+ * Also changes all priorities to be one apart (1,5,6 => 1,2,3)
20
+ */
21
+ recalculatesPriorities(tree: any, parentNode: any, movedNodePath: any, insertedPriority?: number): void;
22
+ /** return biggest value of nodepath number that children are using +1 */
23
+ getNextNodeId(tree: any, parentPath: any): number;
24
+ getInsertionPosition(e: any, element: any): 1 | -1;
25
+ huminifyInsType(insType: any): "before" | "inside" | "after" | undefined;
26
+ /** orders nodes by priorityProp
27
+ */
28
+ OrderByPriority(tree: any): any;
29
+ }
@@ -0,0 +1,193 @@
1
+ // @ts-nocheck
2
+ export class DragAndDropHelper {
3
+ constructor(treeHelper) {
4
+ this.helper = treeHelper;
5
+ this.props = treeHelper.props;
6
+
7
+ this.separator = this.helper.config.separator ?? '.';
8
+ }
9
+
10
+ path(node) {
11
+ return this.helper.path(node);
12
+ }
13
+
14
+ /**
15
+ * moves node from one parent to another
16
+ * @param {Object[]} tree - tree
17
+ * @param {nodePath} movedNodePath - nodepath of moved(dragged) node
18
+ * @param {nodePath} targetNodePath - nodepath of node where it should be moved ( either bellow it in priority or as child)
19
+ * @param {int} insType - if true, it will insert moved node as child of target node, if false, it will insert it bellow it in priority
20
+ * @param {boolean} recalculateNodePath - wont recalculare id of moved node, used when last part of nodePath is always unique
21
+ */
22
+ moveNode(tree, movedNodePath, targetNodePath, insType, recalculateNodePath) {
23
+ const isNesting = insType == 0;
24
+ console.log({ tree, movedNodePath, targetNodePath, insType });
25
+ // if you are not isNestinging, you want to be on same level
26
+ //so you will have same parent as target node
27
+ const parentNodePath = isNesting
28
+ ? targetNodePath
29
+ : this.helper.getParentNodePath(targetNodePath);
30
+
31
+ //trying to move parent to child
32
+ if (parentNodePath.startsWith(movedNodePath)) return;
33
+
34
+ const changedParent = this.helper.getParentNodePath(movedNodePath) !== parentNodePath;
35
+
36
+ let newNodePath = movedNodePath;
37
+
38
+ //dont create new node if you only moved inside same parent
39
+ if (changedParent) {
40
+ newNodePath = this.calculateNewNodePath(
41
+ tree,
42
+ parentNodePath,
43
+ movedNodePath,
44
+ recalculateNodePath
45
+ );
46
+ }
47
+
48
+ //* find target node
49
+
50
+ let targetNode = this.helper.findNode(tree, targetNodePath);
51
+
52
+ let movedNode;
53
+
54
+ //move nodes
55
+ tree = tree.map((node) => {
56
+ //make sure that parent's haschild is set to true, so that children are visible
57
+ if (this.path(node) == parentNodePath) {
58
+ node[this.props.hasChildren] = true;
59
+ node[this.props.expanded] = true;
60
+ }
61
+
62
+ //move moved nodes to new location ( if location is being changed)
63
+ if (changedParent && this.path(node).startsWith(movedNodePath)) {
64
+ //replace old parent with new one
65
+ const newPath = this.path(node).replace(movedNodePath, newNodePath);
66
+ node[this.props.nodePath] = newPath;
67
+ }
68
+
69
+ //if it is moved node
70
+ if (this.path(node) === newNodePath) {
71
+ movedNode = node;
72
+
73
+ //? not sure if this is best
74
+ this.updatePriority(tree, movedNode, parentNodePath, newNodePath, targetNode, insType);
75
+ }
76
+ return node;
77
+ });
78
+
79
+ //* insert node at right possition of array
80
+
81
+ let oldIndex = tree.findIndex((x) => this.path(x) == newNodePath);
82
+ tree.splice(oldIndex, 1);
83
+
84
+ let index = tree.findIndex((x) => this.path(x) == this.path(targetNode));
85
+
86
+ tree.splice(index + (insType == 1 ? 0 : 1), 0, movedNode);
87
+
88
+ //TODO maybe add option to setting this.hasChildren to false when moved last children
89
+
90
+ //hide plus icon if parent of moved node doesnt have any more children
91
+ let oldParent = this.helper.findNode(tree, this.helper.getParentNodePath(movedNodePath));
92
+
93
+ //moved last node
94
+ const oldParentHasChildren = this.helper.allCHildren(tree, this.path(oldParent)).length;
95
+ if (oldParent && !oldParentHasChildren) {
96
+ oldParent[this.props.hasChildren] = false;
97
+ }
98
+
99
+ return tree;
100
+ }
101
+
102
+ calculateNewNodePath(tree, parentNodePath, movedNodePath, recalculateNodePath) {
103
+ //node id is last part of nodePath
104
+ let nodeId;
105
+ if (recalculateNodePath) {
106
+ nodeId = this.getNextNodeId(tree, parentNodePath);
107
+ } else {
108
+ //get last segment of path
109
+ nodeId = movedNodePath.split(this.separator).slice(-1)[0];
110
+ }
111
+ return (parentNodePath ? parentNodePath + this.separator : '') + nodeId;
112
+ }
113
+
114
+ updatePriority(tree, node, parentNodePath, newNodePath, targetNode, insType) {
115
+ const isNesting = insType == 0;
116
+ if (isNesting || targetNode[this.props.priority] != null) {
117
+ let newpriority = 0;
118
+ if (!isNesting) {
119
+ //calculate next
120
+ newpriority = targetNode[this.props.priority] ?? 0;
121
+ if (insType == -1) {
122
+ newpriority += 1;
123
+ } else {
124
+ //targetNode[this.props.priority] -= 1;
125
+ }
126
+ }
127
+ this.recalculatesPriorities(tree, parentNodePath, newNodePath, newpriority);
128
+
129
+ node[this.props.priority] = newpriority;
130
+ } else {
131
+ //so old priority doesnt mess up orderring
132
+ node[this.props.priority] = undefined;
133
+ }
134
+ }
135
+
136
+ /** recomputes all priorities after inserted priority.F
137
+ * Also changes all priorities to be one apart (1,5,6 => 1,2,3)
138
+ */
139
+ //? maybe it will recalculate properly if dont set insertedPriority
140
+ recalculatesPriorities(tree, parentNode, movedNodePath, insertedPriority = -1) {
141
+ let nextPriority = insertedPriority + 1;
142
+ this.OrderByPriority(this.helper.allCHildren(tree, parentNode)).forEach((node) => {
143
+ if (node[this.props.priority] >= insertedPriority && this.path(node) != movedNodePath) {
144
+ node[this.props.priority] = nextPriority++;
145
+ }
146
+ });
147
+ }
148
+
149
+ /** return biggest value of nodepath number that children are using +1 */
150
+ getNextNodeId(tree, parentPath) {
151
+ let max = 0;
152
+ //findes biggest nodeNumber for
153
+ this.helper.allCHildren(tree, parentPath).forEach((node) => {
154
+ const parent = this.helper.getParentNodePath(this.path(node));
155
+
156
+ if (parent === parentPath) {
157
+ let num = this.path(node).substring(parent ? parent.length + 1 : 0);
158
+ max = Math.max(max, num);
159
+ }
160
+ });
161
+ return parseInt(max) + 1;
162
+ }
163
+
164
+ getInsertionPosition(e, element) {
165
+ let targetCords = element.getBoundingClientRect();
166
+ let half = targetCords.bottom - targetCords.height / 2;
167
+
168
+ if (e.y < half) {
169
+ return 1;
170
+ }
171
+ return -1;
172
+ }
173
+
174
+ huminifyInsType(insType) {
175
+ switch (insType) {
176
+ case 1:
177
+ return 'before';
178
+ case 0:
179
+ return 'inside';
180
+ case -1:
181
+ return 'after';
182
+ }
183
+ }
184
+
185
+ /** orders nodes by priorityProp
186
+ */
187
+ OrderByPriority(tree) {
188
+ tree.sort((a, b) => {
189
+ !!b[this.props.priority] ? a[this.props.priority] > b[this.props.priority] : true;
190
+ });
191
+ return tree;
192
+ }
193
+ }
@@ -0,0 +1,22 @@
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;
16
+ /** 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;
22
+ }
@@ -0,0 +1,182 @@
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
+ }
@@ -0,0 +1,33 @@
1
+ export class TreeHelper {
2
+ constructor(propNames: any, config?: {});
3
+ props: any;
4
+ config: {};
5
+ selection: SelectionHelper;
6
+ 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;
17
+ /** toggles expansion on
18
+ */
19
+ changeExpansion(tree: any, node: any, changeTo: any): void;
20
+ /** changes expansion of every node that has this.hasChildren set to true
21
+ */
22
+ changeEveryExpansion(tree: any, changeTo: any): any;
23
+ /** changes expansion of every node that has this.hasChildren set to true if they are abose set level and expansion property isnt set
24
+ */
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;
29
+ }
30
+ declare function _default(...args: any[]): TreeHelper;
31
+ export default _default;
32
+ import { SelectionHelper } from './selection-helpers';
33
+ import { DragAndDropHelper } from './drag-drop-helpers';
@@ -0,0 +1,169 @@
1
+ // @ts-nocheck
2
+ import orderBy from 'lodash.unionby'; // used by tree merge
3
+ import unique from 'lodash.uniq'; // used by tree merge
4
+ import { SelectionHelper } from './selection-helpers';
5
+ import { DragAndDropHelper } from './drag-drop-helpers';
6
+ import { defaultPropNames } from '../consts.js';
7
+
8
+ export class TreeHelper {
9
+ constructor(propNames, config = {}) {
10
+ this.props = { ...defaultPropNames, ...propNames };
11
+ this.config = config;
12
+ this.selection = new SelectionHelper(this);
13
+ this.dragDrop = new DragAndDropHelper(this);
14
+ }
15
+
16
+ path(node) {
17
+ return node?.[this.props.nodePath];
18
+ }
19
+
20
+ //#region basic helpres
21
+
22
+ getParentNodePath(nodePath) {
23
+ const separator = this.config.separator ?? '.';
24
+ const parentPath = nodePath?.substring(0, nodePath.lastIndexOf(separator));
25
+ return parentPath;
26
+ }
27
+
28
+ hasChildren(tree, nodePath) {
29
+ return tree?.find((x) => this.getParentNodePath(this.path(x)) === nodePath);
30
+ }
31
+
32
+ findNode(tree, nodePath) {
33
+ return tree.find((node) => this.path(node) === nodePath);
34
+ }
35
+
36
+ nodePathIsChild(nodePath) {
37
+ const separator = this.config.separator ?? '.';
38
+
39
+ const includesSeparator = nodePath?.includes(separator);
40
+ return includesSeparator;
41
+ }
42
+
43
+ getDirectChildren(tree, parentNodePath) {
44
+ const children = (tree || []).filter((x) =>
45
+ !parentNodePath
46
+ ? !this.nodePathIsChild(this.path(x))
47
+ : this.getParentNodePath(this.path(x)) === parentNodePath
48
+ );
49
+
50
+ return children;
51
+ }
52
+
53
+ allCHildren(tree, parentNodePath) {
54
+ let children;
55
+ children = tree.filter((x) => {
56
+ if (!parentNodePath) {
57
+ //top level
58
+ return !this.nodePathIsChild(this.path(x));
59
+ } else {
60
+ return this.path(x).startsWith(parentNodePath.toString()) && this.path(x) != parentNodePath;
61
+ }
62
+ });
63
+ return children;
64
+ }
65
+
66
+ getAllLeafNodes(tree) {
67
+ return tree.filter((x) => {
68
+ return x[this.props.hasChildren] == undefined || x[this.props.hasChildren] == false;
69
+ });
70
+ }
71
+
72
+ joinTrees(filteredTree, tree) {
73
+ return tree.map((tnode) => this.findNode(filteredTree, this.path(tnode)) || tnode);
74
+ }
75
+
76
+ mergeTrees(oldTree, addedTree, nodePath = 'nodePath') {
77
+ return orderBy(addedTree, oldTree, nodePath);
78
+ }
79
+
80
+ /** toggles expansion on
81
+ */
82
+ changeExpansion(tree, node, changeTo) {
83
+ let foundNode = this.findNode(tree, this.path(node));
84
+
85
+ foundNode[this.props.expanded] = changeTo;
86
+ }
87
+
88
+ /** changes expansion of every node that has this.hasChildren set to true
89
+ */
90
+ changeEveryExpansion(tree, changeTo) {
91
+ return tree.map((node) => {
92
+ if (node[this.props.hasChildren] == true) node[this.props.expanded] = changeTo;
93
+ return node;
94
+ });
95
+ }
96
+
97
+ /** changes expansion of every node that has this.hasChildren set to true if they are abose set level and expansion property isnt set
98
+ */
99
+ expandToLevel(tree, level) {
100
+ return tree.map((n) => {
101
+ if (
102
+ n[this.props.expanded] == undefined &&
103
+ n[this.props.expanded] == null &&
104
+ n[this.props.useCallback] != true &&
105
+ this.getDepthLevel(this.path(n)) <= level
106
+ ) {
107
+ n[this.props.expanded] = true;
108
+ }
109
+ return n;
110
+ });
111
+ }
112
+
113
+ //based on number of dots
114
+ getDepthLevel(nodePath) {
115
+ const separator = this.config.separator ?? '.';
116
+ return nodePath.split(separator).length - 1;
117
+ }
118
+
119
+ //#endregion
120
+
121
+ searchTree(tree, filter, leafesOnly) {
122
+ let filteredNodes;
123
+ if (leafesOnly) {
124
+ filteredNodes = this.getAllLeafNodes(tree).filter(filter);
125
+ } else {
126
+ console.log(tree);
127
+ filteredNodes = tree.filter(filter);
128
+ }
129
+
130
+ const resultNodes = [];
131
+
132
+ //console.log("matching nodes length:" + matchingPathes.length)
133
+ filteredNodes.forEach((node) => {
134
+ resultNodes.push(node);
135
+
136
+ const parentNodes = this.getParents(tree, node);
137
+ resultNodes.push(...parentNodes);
138
+ });
139
+
140
+ const uniqueNodes = unique(resultNodes, (node) => this.path(node));
141
+
142
+ return uniqueNodes;
143
+ }
144
+
145
+ getParents(tree, node) {
146
+ const parentsPaths = [];
147
+
148
+ let nodePath = this.path(node);
149
+
150
+ // get all parents
151
+ while (nodePath.length > 0) {
152
+ nodePath = this.getParentNodePath(nodePath);
153
+ parentsPaths.push(nodePath);
154
+ }
155
+
156
+ //find nodes for given ids
157
+ const parentNodes = tree.filter((n) =>
158
+ parentsPaths.some((parentNodePath) => this.path(n) === parentNodePath)
159
+ );
160
+
161
+ return parentNodes;
162
+ }
163
+ }
164
+
165
+ export default (...args) => {
166
+ // TODO redundant now, maybe remove
167
+ let helper = new TreeHelper(...args);
168
+ return helper;
169
+ };
@@ -0,0 +1,5 @@
1
+ export { default as TreeView } from "./TreeView.svelte";
2
+ export { default as MenuDivider } from "./menu/MenuDivider.svelte";
3
+ export { default as MenuOption } from "./menu/MenuOption.svelte";
4
+ export { TreeHelper } from "./helpers/tree-helper.js";
5
+ export * as Constants from "./consts.js";
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export { default as TreeView } from './TreeView.svelte';
2
+ export { default as MenuDivider } from './menu/MenuDivider.svelte';
3
+ export { default as MenuOption } from './menu/MenuOption.svelte';
4
+ export { TreeHelper } from './helpers/tree-helper.js';
5
+ export * as Constants from './consts.js';
@@ -0,0 +1,33 @@
1
+ <script>
2
+ // @ts-nocheck
3
+
4
+ import Menu from './Menu.svelte';
5
+
6
+ let pos = { x: 0, y: 0 };
7
+ let showMenu = false;
8
+ let node = null;
9
+
10
+ export async function onRightClick(e, n) {
11
+ if (showMenu) {
12
+ showMenu = false;
13
+ await new Promise((res) => setTimeout(res, 100));
14
+ }
15
+ node = n;
16
+ pos = { x: e.clientX, y: e.clientY };
17
+ showMenu = true;
18
+ }
19
+
20
+ function closeMenu() {
21
+ showMenu = false;
22
+ node = null;
23
+ }
24
+ </script>
25
+
26
+ <svelte:window on:click={closeMenu} />
27
+ {#if showMenu}
28
+ <Menu {...pos} on:click={closeMenu} on:clickoutside={closeMenu}>
29
+ <slot {node}>
30
+ <b> context menu openned from: {node?.nodePath}</b>
31
+ </slot>
32
+ </Menu>
33
+ {/if}