@keenmate/svelte-treeview 1.0.0-beta.0 → 1.0.0-beta.1

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.
@@ -1,18 +1,29 @@
1
1
  import { SelectionModes, VisualState } from '../types.js';
2
2
  export class SelectionProvider {
3
3
  helper;
4
- props;
5
4
  recursiveMode;
6
5
  constructor(treeHelper, recursive) {
7
6
  this.helper = treeHelper;
8
- this.props = treeHelper.props;
9
7
  this.recursiveMode = recursive;
10
8
  }
11
- path(node) {
12
- return this.helper.path(node);
9
+ markSelected(tree, selectedNodeIds) {
10
+ const visualStates = this.computeVisualStates(tree, selectedNodeIds);
11
+ tree.forEach((node) => {
12
+ if (selectedNodeIds.includes(node.id ?? '')) {
13
+ node.selected = true;
14
+ node.visualState = VisualState.selected;
15
+ return;
16
+ }
17
+ node.selected = false;
18
+ const visualState = visualStates[node.id ?? ''];
19
+ if (!visualState) {
20
+ node.visualState = VisualState.notSelected;
21
+ }
22
+ node.visualState = visualState;
23
+ });
13
24
  }
14
25
  isNodeSelected(node) {
15
- return (this.props.selected(node) === true || this.props.visualState(node) === VisualState.selected);
26
+ return node.selected === true || node.visualState === VisualState.selected;
16
27
  }
17
28
  isSelected(nodeId, visualStates, selectedNodeIds) {
18
29
  const selected = selectedNodeIds.includes(nodeId);
@@ -24,11 +35,11 @@ export class SelectionProvider {
24
35
  getSelectableDirectChildren(tree, parentNodePath) {
25
36
  return this.helper
26
37
  .getDirectChildren(tree, parentNodePath)
27
- .filter((node) => this.isSelectable(node, SelectionModes.all));
38
+ .filter((node) => isSelectable(node, SelectionModes.all));
28
39
  }
29
40
  setSelection(tree, nodePath, changeTo, oldSelection) {
30
41
  const node = this.helper.findNode(tree, nodePath);
31
- const nodeHasChildren = node ? this.props.hasChildren(node) : false;
42
+ const nodeHasChildren = node ? node.hasChildren : false;
32
43
  // allow selection of root node
33
44
  if (nodePath === null || (this.recursiveMode && nodeHasChildren)) {
34
45
  return this.changeSelectedRecursively(tree, nodePath, changeTo, oldSelection);
@@ -39,12 +50,13 @@ export class SelectionProvider {
39
50
  console.warn('Node %s doesnt exits', nodePath);
40
51
  return oldSelection;
41
52
  }
53
+ const nodeId = node.id ?? '';
42
54
  // prevent double selection
43
- const filteredSelection = oldSelection.filter((x) => x !== this.props.id(node));
55
+ const filteredSelection = oldSelection.filter((x) => x !== nodeId);
44
56
  if (changeTo === false) {
45
57
  return filteredSelection;
46
58
  }
47
- return [...filteredSelection, this.props.id(node) ?? ''];
59
+ return [...filteredSelection, nodeId];
48
60
  }
49
61
  }
50
62
  /** Computes visual states for all nodes. Used for computing initial visual states when tree changes */
@@ -54,24 +66,13 @@ export class SelectionProvider {
54
66
  // if some node is not selectable, are all its children also not selectable?
55
67
  const rootELements = this.getSelectableDirectChildren(tree, null);
56
68
  rootELements.forEach((node) => {
57
- if (this.props.hasChildren(node) == true) {
69
+ if (node.hasChildren == true) {
58
70
  const result = this.computeVisualStateRecursively(tree, node, selectedNodeIds, visualStates);
59
- visualStates[this.props.id(node) ?? ''] = result.state;
71
+ visualStates[node.id ?? ''] = result.state;
60
72
  }
61
73
  });
62
74
  return visualStates;
63
75
  }
64
- isSelectable(node, showCheckboxes) {
65
- if (showCheckboxes === SelectionModes.all) {
66
- return this.props.checkbox(node) !== false;
67
- }
68
- //show only if pop is true
69
- if (showCheckboxes === SelectionModes.perNode) {
70
- return this.props.checkbox(node) === true;
71
- }
72
- //dont show at all
73
- return false;
74
- }
75
76
  computeVisualState(directChildrenVisualStates) {
76
77
  if (!directChildrenVisualStates || directChildrenVisualStates?.length == 0)
77
78
  return VisualState.selected;
@@ -95,19 +96,19 @@ export class SelectionProvider {
95
96
  * @returns New visual state for node
96
97
  */
97
98
  computeVisualStateRecursively(tree, node, selectedNodeIds, visualStates) {
98
- const directChildren = this.getSelectableDirectChildren(tree, this.path(node));
99
+ const directChildren = this.getSelectableDirectChildren(tree, node.path);
99
100
  const directChildrenStates = [];
100
101
  // using recustion compute from leaft nodes to root
101
102
  directChildren.forEach((child) => {
102
- if (!this.props.hasChildren(child)) {
103
- const childState = selectedNodeIds.includes(this.props.id(child) ?? '')
103
+ if (!child.hasChildren) {
104
+ const childState = selectedNodeIds.includes(child.id ?? '')
104
105
  ? VisualState.selected
105
106
  : VisualState.notSelected;
106
107
  directChildrenStates.push(childState);
107
108
  return;
108
109
  }
109
110
  const result = this.computeVisualStateRecursively(tree, child, selectedNodeIds, visualStates);
110
- visualStates[this.props.id(child) ?? ''] = result.state;
111
+ visualStates[child.id ?? ''] = result.state;
111
112
  if (!result.ignore) {
112
113
  directChildrenStates.push(result.state);
113
114
  }
@@ -120,22 +121,33 @@ export class SelectionProvider {
120
121
  let newSelection = [...oldSelection];
121
122
  tree.forEach((node) => {
122
123
  // match itself and all children
123
- if (this.path(node)?.startsWith(parentNodePath ?? '')) {
124
+ if (node.path?.startsWith(parentNodePath ?? '')) {
124
125
  //dont change if not selectable
125
- if (!this.isSelectable(node, SelectionModes.all)) {
126
+ if (!isSelectable(node, SelectionModes.all)) {
126
127
  return;
127
128
  }
128
129
  // in recursive mode only update leaf nodes
129
- if (this.recursiveMode && this.props.hasChildren(node)) {
130
+ if (this.recursiveMode && node.hasChildren) {
130
131
  return;
131
132
  }
132
133
  // prevent double selection
133
- newSelection = newSelection.filter((x) => x !== this.props.id(node) ?? '');
134
+ newSelection = newSelection.filter((x) => x !== node.id ?? '');
134
135
  if (changeTo === true) {
135
- newSelection.push(this.props.id(node) ?? '');
136
+ newSelection.push(node.id ?? '');
136
137
  }
137
138
  }
138
139
  });
139
140
  return newSelection;
140
141
  }
141
142
  }
143
+ export function isSelectable(node, showCheckboxes) {
144
+ if (showCheckboxes === SelectionModes.all) {
145
+ return node.checkbox !== false;
146
+ }
147
+ //show only if pop is true
148
+ if (showCheckboxes === SelectionModes.perNode) {
149
+ return node.checkbox === true;
150
+ }
151
+ //dont show at all
152
+ return false;
153
+ }
@@ -1,105 +1,105 @@
1
-
2
- $treeview-lines: solid black 1px
3
- .treeview
4
- padding: 0
5
- //will show lines if you set show-lines to root element
6
- &.show-lines
7
- ul
8
- &:before
9
- border-left: $treeview-lines
10
- li:before
11
- border-top: $treeview-lines
12
- margin: 0
13
- padding: 0
14
- list-style: none
15
- ul, li
16
- margin: 0
17
- padding: 0
18
- list-style: none
19
- ul
20
- margin-left: 0.4em
21
- position: relative
22
- margin-left: .3em
23
- &:before
24
- content: ""
25
- display: block
26
- width: 0
27
- position: absolute
28
- top: 0
29
- bottom: 0
30
- left: 0
31
- li:before
32
- content: ""
33
- display: block
34
- width: 10px
35
- height: 0
36
- margin-top: -1px
37
- position: absolute
38
- top: 0.8em
39
- left: 0
40
- li:not(.has-children):before
41
- width: 26px
42
-
43
- li:last-child:before
44
- background: #fff
45
- height: auto
46
- top: 1em
47
- bottom: 0
48
-
49
- li
50
- margin: 0
51
- padding: 0 0.8em
52
- color: #555
53
- font-weight: 700
54
- position: relative
55
- &:not(.has-children)
56
- .tree-item
57
- margin-left: 14px
58
-
59
- .tree-item
60
- display: flex
61
- column-gap: 0.4em
62
- align-items: center
63
- padding: 4px 0
64
-
65
- .no-arrow
66
- padding-left: .5rem
67
-
68
- .arrow
69
- cursor: pointer
70
- display: inline-block
71
-
72
- .arrowDown
73
- transform: rotate(90deg)
74
-
75
- .invisible
76
- visibility: hidden
77
-
78
- .inserting-highlighted
79
- color: red
80
- .hover
81
- font-weight: bold
82
- .insert-line
83
- position: absolute
84
- left: 0
85
- z-index: 99
86
- height: 2px
87
- width: 200px
88
- background-color: blue
89
- display: block
90
- border-radius: 3px
91
- margin-left: 28px
92
- margin-bottom: -2px
93
- margin-top: -2px
94
- .insert-line-child
95
- margin-left: calc( 28px + 5em )
96
- background-color: red
97
- height: 6px
98
-
99
- .insert-line-wrapper
100
- position: relative
101
-
102
- .currently-dragged
103
- color: LightGray
104
- .pointer-cursor
105
- cursor: grab
1
+
2
+ $treeview-lines: solid black 1px
3
+ .treeview
4
+ padding: 0
5
+ //will show lines if you set show-lines to root element
6
+ &.show-lines
7
+ ul
8
+ &:before
9
+ border-left: $treeview-lines
10
+ li:before
11
+ border-top: $treeview-lines
12
+ margin: 0
13
+ padding: 0
14
+ list-style: none
15
+ ul, li
16
+ margin: 0
17
+ padding: 0
18
+ list-style: none
19
+ ul
20
+ margin-left: 0.4em
21
+ position: relative
22
+ margin-left: .3em
23
+ &:before
24
+ content: ""
25
+ display: block
26
+ width: 0
27
+ position: absolute
28
+ top: 0
29
+ bottom: 0
30
+ left: 0
31
+ li:before
32
+ content: ""
33
+ display: block
34
+ width: 10px
35
+ height: 0
36
+ margin-top: -1px
37
+ position: absolute
38
+ top: 0.8em
39
+ left: 0
40
+ li:not(.has-children):before
41
+ width: 26px
42
+
43
+ li:last-child:before
44
+ background: #fff
45
+ height: auto
46
+ top: 1em
47
+ bottom: 0
48
+
49
+ li
50
+ margin: 0
51
+ padding: 0 0.8em
52
+ color: #555
53
+ font-weight: 700
54
+ position: relative
55
+ &:not(.has-children)
56
+ .tree-item
57
+ margin-left: 14px
58
+
59
+ .tree-item
60
+ display: flex
61
+ column-gap: 0.4em
62
+ align-items: center
63
+ padding: 4px 0
64
+
65
+ .no-arrow
66
+ padding-left: .5rem
67
+
68
+ .arrow
69
+ cursor: pointer
70
+ display: inline-block
71
+
72
+ .arrowDown
73
+ transform: rotate(90deg)
74
+
75
+ .invisible
76
+ visibility: hidden
77
+
78
+ .inserting-highlighted
79
+ color: red
80
+ .hover
81
+ font-weight: bold
82
+ .insert-line
83
+ position: absolute
84
+ left: 0
85
+ z-index: 99
86
+ height: 2px
87
+ width: 200px
88
+ background-color: blue
89
+ display: block
90
+ border-radius: 3px
91
+ margin-left: 28px
92
+ margin-bottom: -2px
93
+ margin-top: -2px
94
+ .insert-line-child
95
+ margin-left: calc( 28px + 5em )
96
+ background-color: red
97
+ height: 6px
98
+
99
+ .insert-line-wrapper
100
+ position: relative
101
+
102
+ .currently-dragged
103
+ color: LightGray
104
+ .pointer-cursor
105
+ cursor: grab
package/dist/types.d.ts CHANGED
@@ -2,15 +2,38 @@ export type Props = {
2
2
  nodeId: string;
3
3
  nodePath: string;
4
4
  hasChildren: string;
5
- expanded: string;
6
- selected: string;
7
5
  useCallback: string;
8
6
  priority: string;
9
7
  isDraggable: string;
10
8
  insertDisabled: string;
11
9
  nestDisabled: string;
12
10
  checkbox: string;
13
- visualState: string;
11
+ };
12
+ export type MappedNode = {
13
+ id: NodeId;
14
+ path: NodePath;
15
+ hasChildren: boolean;
16
+ useCallback: boolean;
17
+ priority: number;
18
+ isDraggable: boolean;
19
+ insertDisabled: boolean;
20
+ nestDisabled: boolean;
21
+ checkbox: boolean;
22
+ };
23
+ export type Node = {
24
+ originalNode: any;
25
+ id: NodeId;
26
+ path: NodePath;
27
+ hasChildren: boolean;
28
+ useCallback: boolean;
29
+ priority: number;
30
+ isDraggable: boolean;
31
+ insertDisabled: boolean;
32
+ nestDisabled: boolean;
33
+ checkbox: boolean;
34
+ visualState: VisualState;
35
+ expanded: boolean;
36
+ selected: boolean;
14
37
  };
15
38
  export declare enum VisualState {
16
39
  indeterminate = "indeterminate",
@@ -22,7 +45,6 @@ export declare enum SelectionModes {
22
45
  perNode = "perNode",
23
46
  none = "none"
24
47
  }
25
- export type Node = object;
26
48
  export type Tree = Node[];
27
49
  export declare enum InsertionType {
28
50
  above = "above",
@@ -43,12 +65,9 @@ export type CustomizableClasses = {
43
65
  };
44
66
  export type DragEnterCallback = (draggendNode: Node, oldParent: Node, newParent: Node) => boolean;
45
67
  export type BeforeMovedCallback = (draggendNode: Node, oldParent: Node, newParent: Node, insertionType: string) => boolean;
46
- export type ExpandedCallback = (node: Node) => Promise<Node[]>;
68
+ export type ExpandedCallback = (node: Node) => Promise<void>;
47
69
  export type HelperConfig = {
48
70
  separator: string;
49
- recursive?: boolean;
50
- recalculateNodePath?: boolean;
51
- checkboxes?: SelectionModes;
52
71
  };
53
72
  export declare enum HighlighType {
54
73
  nest = "nest",
@@ -59,3 +78,5 @@ export declare enum HighlighType {
59
78
  export type TreeVisualStates = {
60
79
  [nodePath: string]: VisualState;
61
80
  };
81
+ export type ProvidedTree = any[];
82
+ export type FilterFunction = (node: Node) => boolean;
package/package.json CHANGED
@@ -1,71 +1,71 @@
1
- {
2
- "name": "@keenmate/svelte-treeview",
3
- "version": "1.0.0-beta.0",
4
- "scripts": {
5
- "dev": "vite dev",
6
- "build": "vite build && npm run package",
7
- "preview": "vite preview",
8
- "package": "svelte-kit sync && svelte-package && publint",
9
- "prepublishOnly": "npm run package",
10
- "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
11
- "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
12
- "lint": "prettier --plugin-search-dir . --check . && eslint .",
13
- "format": "prettier --plugin-search-dir . --write .",
14
- "test": "vitest",
15
- "test:loud": "vitest --silent=false",
16
- "coverage": "vitest run --coverage"
17
- },
18
- "exports": {
19
- ".": {
20
- "types": "./dist/index.d.ts",
21
- "svelte": "./dist/index.js"
22
- }
23
- },
24
- "files": [
25
- "dist",
26
- "!dist/**/*.test.*",
27
- "!dist/**/*.spec.*"
28
- ],
29
- "peerDependencies": {
30
- "svelte": "^4.0.0"
31
- },
32
- "devDependencies": {
33
- "@keenmate/svelte-adminlte": "^1.1.3",
34
- "@sveltejs/adapter-auto": "^2.0.0",
35
- "@sveltejs/kit": "^1.20.4",
36
- "@sveltejs/package": "^2.0.0",
37
- "@types/marked": "^5.0.0",
38
- "@types/node": "^20.3.3",
39
- "@typescript-eslint/eslint-plugin": "^5.45.0",
40
- "@typescript-eslint/parser": "^5.45.0",
41
- "@vitest/coverage-v8": "^1.4.0",
42
- "eslint": "^8.28.0",
43
- "eslint-config-prettier": "^8.5.0",
44
- "eslint-plugin-svelte": "^2.30.0",
45
- "marked": "^5.1.0",
46
- "prettier": "^2.8.0",
47
- "prettier-plugin-svelte": "^2.10.1",
48
- "publint": "^0.1.9",
49
- "rollup-plugin-string": "^3.0.0",
50
- "sass": "^1.49.0",
51
- "svelte": "^4.0.0",
52
- "svelte-check": "^3.4.3",
53
- "svelte-multiselect": "github:KeenMate/svelte-multiselect",
54
- "svelte-preprocess": "^5.0.4",
55
- "tslib": "^2.4.1",
56
- "typescript": "^5.4.4",
57
- "vite": "^4.3.6",
58
- "vitest": "^1.4.0"
59
- },
60
- "svelte": "./dist/index.js",
61
- "types": "./dist/index.d.ts",
62
- "type": "module",
63
- "dependencies": {
64
- "@types/lodash.unionby": "^4.8.9",
65
- "@types/lodash.uniq": "^4.5.9",
66
- "@types/lodash.uniqby": "^4.7.9",
67
- "lodash.unionby": "^4.8.0",
68
- "lodash.uniq": "^4.5.0",
69
- "lodash.uniqby": "^4.7.0"
70
- }
71
- }
1
+ {
2
+ "name": "@keenmate/svelte-treeview",
3
+ "version": "1.0.0-beta.1",
4
+ "scripts": {
5
+ "dev": "vite dev",
6
+ "build": "vite build && npm run package",
7
+ "preview": "vite preview",
8
+ "package": "svelte-kit sync && svelte-package && publint",
9
+ "prepublishOnly": "npm run package",
10
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
11
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
12
+ "lint": "prettier --plugin-search-dir . --check . && eslint .",
13
+ "format": "prettier --plugin-search-dir . --write .",
14
+ "test": "vitest",
15
+ "test:loud": "vitest --silent=false",
16
+ "coverage": "vitest run --coverage"
17
+ },
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "svelte": "./dist/index.js"
22
+ }
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "!dist/**/*.test.*",
27
+ "!dist/**/*.spec.*"
28
+ ],
29
+ "peerDependencies": {
30
+ "svelte": "^4.0.0"
31
+ },
32
+ "devDependencies": {
33
+ "@keenmate/svelte-adminlte": "^1.1.3",
34
+ "@sveltejs/adapter-auto": "^2.0.0",
35
+ "@sveltejs/kit": "^1.20.4",
36
+ "@sveltejs/package": "^2.0.0",
37
+ "@types/marked": "^5.0.0",
38
+ "@types/node": "^20.3.3",
39
+ "@typescript-eslint/eslint-plugin": "^5.45.0",
40
+ "@typescript-eslint/parser": "^5.45.0",
41
+ "@vitest/coverage-v8": "^1.4.0",
42
+ "eslint": "^8.28.0",
43
+ "eslint-config-prettier": "^8.5.0",
44
+ "eslint-plugin-svelte": "^2.30.0",
45
+ "marked": "^5.1.0",
46
+ "prettier": "^2.8.0",
47
+ "prettier-plugin-svelte": "^2.10.1",
48
+ "publint": "^0.1.9",
49
+ "rollup-plugin-string": "^3.0.0",
50
+ "sass": "^1.49.0",
51
+ "svelte": "^4.0.0",
52
+ "svelte-check": "^3.4.3",
53
+ "svelte-multiselect": "github:KeenMate/svelte-multiselect",
54
+ "svelte-preprocess": "^5.0.4",
55
+ "tslib": "^2.4.1",
56
+ "typescript": "^5.4.4",
57
+ "vite": "^4.3.6",
58
+ "vitest": "^1.4.0"
59
+ },
60
+ "svelte": "./dist/index.js",
61
+ "types": "./dist/index.d.ts",
62
+ "type": "module",
63
+ "dependencies": {
64
+ "@types/lodash.unionby": "^4.8.9",
65
+ "@types/lodash.uniq": "^4.5.9",
66
+ "@types/lodash.uniqby": "^4.7.9",
67
+ "lodash.unionby": "^4.8.0",
68
+ "lodash.uniq": "^4.5.0",
69
+ "lodash.uniqby": "^4.7.0"
70
+ }
71
+ }
@@ -1,31 +0,0 @@
1
- import type { Node, NodePath, Props, VisualState } from '../types.js';
2
- export declare class PropertyHelper {
3
- props: Props;
4
- constructor(props: Props);
5
- private getVal;
6
- private setVal;
7
- id(node: Node): string;
8
- setId(node: Node, id: string): void;
9
- path(node: Node | null): NodePath;
10
- setPath(node: Node, path: NodePath): void;
11
- hasChildren(node: Node): boolean;
12
- setHasChildren(node: Node, hasChildren: boolean): void;
13
- expanded(node: Node): boolean | null;
14
- setExpanded(node: Node, expanded: boolean): void;
15
- selected(node: Node): boolean | null;
16
- setSelected(node: Node, selected: boolean | null): void;
17
- useCallback(node: Node): boolean;
18
- setUseCallback(node: Node, useCallback: boolean): void;
19
- priority(node: Node): number;
20
- setPriority(node: Node, priority: number | undefined): void;
21
- isDraggable(node: Node): boolean;
22
- setIsDraggable(node: Node, isDraggable: boolean): void;
23
- insertDisabled(node: Node | null): boolean;
24
- setInsertDisabled(node: Node, insertDisabled: boolean): void;
25
- nestDisabled(node: Node | null): boolean;
26
- setNestDisabled(node: Node, nestDisabled: boolean): void;
27
- checkbox(node: Node): boolean | null;
28
- setCheckbox(node: Node, checkbox: boolean): void;
29
- visualState(node: Node): VisualState | null;
30
- setVisualState(node: Node, visualState: VisualState | null): void;
31
- }