@snack-uikit/tree 0.10.2-preview-e308d174.0 → 0.10.2-preview-f95ba740.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.
- package/README.md +29 -0
- package/dist/cjs/helpers/__tests__/collectEmptyNestedNodesInExpanded.spec.d.ts +1 -0
- package/dist/cjs/helpers/__tests__/collectEmptyNestedNodesInExpanded.spec.js +80 -0
- package/dist/cjs/helpers/__tests__/setChildrenOfTreeNode.spec.d.ts +1 -0
- package/dist/cjs/helpers/__tests__/setChildrenOfTreeNode.spec.js +102 -0
- package/dist/cjs/helpers/collectEmptyNestedNodesInExpanded.d.ts +2 -0
- package/dist/cjs/helpers/collectEmptyNestedNodesInExpanded.js +17 -0
- package/dist/cjs/helpers/index.d.ts +2 -0
- package/dist/cjs/helpers/index.js +3 -1
- package/dist/cjs/helpers/setChildrenOfTreeNode.d.ts +2 -0
- package/dist/cjs/helpers/setChildrenOfTreeNode.js +28 -0
- package/dist/cjs/helpers/sortTreeItemsByTitle.js +2 -2
- package/dist/cjs/helpers/traverse.d.ts +6 -0
- package/dist/cjs/helpers/traverse.js +38 -2
- package/dist/cjs/hooks/index.d.ts +2 -0
- package/dist/cjs/hooks/index.js +26 -0
- package/dist/cjs/hooks/useTreeMultiSelection.d.ts +12 -0
- package/dist/cjs/hooks/useTreeMultiSelection.js +82 -0
- package/dist/cjs/hooks/useTreeWithPreload.d.ts +33 -0
- package/dist/cjs/hooks/useTreeWithPreload.js +138 -0
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.js +27 -1
- package/dist/cjs/types.d.ts +12 -0
- package/dist/esm/helpers/__tests__/collectEmptyNestedNodesInExpanded.spec.d.ts +1 -0
- package/dist/esm/helpers/__tests__/collectEmptyNestedNodesInExpanded.spec.js +64 -0
- package/dist/esm/helpers/__tests__/setChildrenOfTreeNode.spec.d.ts +1 -0
- package/dist/esm/helpers/__tests__/setChildrenOfTreeNode.spec.js +50 -0
- package/dist/esm/helpers/collectEmptyNestedNodesInExpanded.d.ts +2 -0
- package/dist/esm/helpers/collectEmptyNestedNodesInExpanded.js +11 -0
- package/dist/esm/helpers/index.d.ts +2 -0
- package/dist/esm/helpers/index.js +2 -0
- package/dist/esm/helpers/setChildrenOfTreeNode.d.ts +2 -0
- package/dist/esm/helpers/setChildrenOfTreeNode.js +20 -0
- package/dist/esm/helpers/sortTreeItemsByTitle.js +2 -2
- package/dist/esm/helpers/traverse.d.ts +6 -0
- package/dist/esm/helpers/traverse.js +24 -0
- package/dist/esm/hooks/index.d.ts +2 -0
- package/dist/esm/hooks/index.js +2 -0
- package/dist/esm/hooks/useTreeMultiSelection.d.ts +12 -0
- package/dist/esm/hooks/useTreeMultiSelection.js +43 -0
- package/dist/esm/hooks/useTreeWithPreload.d.ts +33 -0
- package/dist/esm/hooks/useTreeWithPreload.js +98 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/types.d.ts +12 -0
- package/package.json +6 -4
- package/src/helpers/__tests__/collectEmptyNestedNodesInExpanded.spec.ts +88 -0
- package/src/helpers/__tests__/setChildrenOfTreeNode.spec.ts +68 -0
- package/src/helpers/collectEmptyNestedNodesInExpanded.ts +16 -0
- package/src/helpers/index.ts +2 -0
- package/src/helpers/setChildrenOfTreeNode.ts +30 -0
- package/src/helpers/sortTreeItemsByTitle.ts +2 -2
- package/src/helpers/traverse.ts +37 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/useTreeMultiSelection.ts +61 -0
- package/src/hooks/useTreeWithPreload.ts +150 -0
- package/src/index.ts +2 -0
- package/src/types.ts +9 -0
package/README.md
CHANGED
|
@@ -90,6 +90,18 @@ function TreeAsyncLoadExample() {
|
|
|
90
90
|
|
|
91
91
|
[//]: DOCUMENTATION_SECTION_START
|
|
92
92
|
[//]: THIS_SECTION_IS_AUTOGENERATED_PLEASE_DONT_EDIT_IT
|
|
93
|
+
## getSearchedTreeItems
|
|
94
|
+
### Props
|
|
95
|
+
| name | type | default value | description |
|
|
96
|
+
|------|------|---------------|-------------|
|
|
97
|
+
| tree* | `ExtendedTreeNodeProps[]` | - | |
|
|
98
|
+
| searchOptions | `Partial<{ query: string; includeChildrenMatchedParent: boolean; }>` | - | |
|
|
99
|
+
## getSearchedTreeNodeById
|
|
100
|
+
### Props
|
|
101
|
+
| name | type | default value | description |
|
|
102
|
+
|------|------|---------------|-------------|
|
|
103
|
+
| searchOptions* | `{ id: I; includeNested?: boolean; }` | - | |
|
|
104
|
+
| tree* | `T[]` | - | |
|
|
93
105
|
## Tree
|
|
94
106
|
### Props
|
|
95
107
|
| name | type | default value | description |
|
|
@@ -108,6 +120,23 @@ function TreeAsyncLoadExample() {
|
|
|
108
120
|
| selected | `string \| string[]` | - | Состояние для выбраных элементов: <br> - При <strong>selectionMode</strong>=`Multi` - принимает массив строк <br> - При <strong>selectionMode</strong>=`Single` - принимает строку |
|
|
109
121
|
| onSelect | `((selectedKeys: string[], node: TreeNodeProps) => void) \| ((selectedKey: string, node: TreeNodeProps) => void)` | - | Колбэк при изменении выбраных элементов: <br> - При <strong>selectionMode</strong>=`Multi` - возвращает массив строк <br> - При <strong>selectionMode</strong>=`Single` - возвращает строку |
|
|
110
122
|
| showToggle | `boolean` | - | |
|
|
123
|
+
## useTreeWithPreload
|
|
124
|
+
### Props
|
|
125
|
+
| name | type | default value | description |
|
|
126
|
+
|------|------|---------------|-------------|
|
|
127
|
+
| mapNodeToRecordItem* | `(node: TTreeNode) => TRecordValue` | - | |
|
|
128
|
+
| onSearch* | `(params: SearchParams) => Promise<SearchResult<TTreeNode>>` | - | |
|
|
129
|
+
| onPreloadNodes* | `(nodes: string[]) => Promise<Record<string, TTreeNode[]>>` | - | |
|
|
130
|
+
| onPreloadNode* | `(node: TreeNodeProps) => Promise<TTreeNode[]>` | - | |
|
|
131
|
+
| initTree* | `TTreeNode[]` | - | |
|
|
132
|
+
## useTreeMultiSelection
|
|
133
|
+
### Props
|
|
134
|
+
| name | type | default value | description |
|
|
135
|
+
|------|------|---------------|-------------|
|
|
136
|
+
| onSelect* | `SelectHandler` | - | |
|
|
137
|
+
| onDataLoad* | `PreloadNodeHandler<TTreeNode>` | - | |
|
|
138
|
+
| selected | `string[]` | - | |
|
|
139
|
+
| onChangeSelected | `(newSelected: string[]) => void` | - | |
|
|
111
140
|
|
|
112
141
|
|
|
113
142
|
[//]: DOCUMENTATION_SECTION_END
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
const vitest_1 = require("vitest");
|
|
7
|
+
const collectEmptyNestedNodesInExpanded_1 = require("../collectEmptyNestedNodesInExpanded");
|
|
8
|
+
const node = (id, nested) => Object.assign({
|
|
9
|
+
id,
|
|
10
|
+
title: id
|
|
11
|
+
}, nested !== undefined && {
|
|
12
|
+
nested
|
|
13
|
+
});
|
|
14
|
+
(0, vitest_1.describe)('collectEmptyNestedNodesInExpanded', () => {
|
|
15
|
+
(0, vitest_1.it)('returns nodes with empty nested array that are in expandedIds', () => {
|
|
16
|
+
const tree = [node('a', []), node('b', [node('b1')])];
|
|
17
|
+
const expandedIds = new Set(['a']);
|
|
18
|
+
const result = (0, collectEmptyNestedNodesInExpanded_1.collectEmptyNestedNodesInExpanded)(tree, expandedIds);
|
|
19
|
+
(0, vitest_1.expect)(result).toHaveLength(1);
|
|
20
|
+
(0, vitest_1.expect)(result[0]).toMatchObject({
|
|
21
|
+
id: 'a',
|
|
22
|
+
nested: []
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
(0, vitest_1.it)('does not return nodes with empty nested if not in expandedIds', () => {
|
|
26
|
+
const tree = [node('a', []), node('b', [])];
|
|
27
|
+
const expandedIds = new Set(['b']);
|
|
28
|
+
const result = (0, collectEmptyNestedNodesInExpanded_1.collectEmptyNestedNodesInExpanded)(tree, expandedIds);
|
|
29
|
+
(0, vitest_1.expect)(result).toHaveLength(1);
|
|
30
|
+
(0, vitest_1.expect)(result[0].id).toBe('b');
|
|
31
|
+
});
|
|
32
|
+
(0, vitest_1.it)('does not return nodes that have non-empty nested', () => {
|
|
33
|
+
const tree = [node('a', [node('a1')]), node('b', [])];
|
|
34
|
+
const expandedIds = new Set(['a', 'b']);
|
|
35
|
+
const result = (0, collectEmptyNestedNodesInExpanded_1.collectEmptyNestedNodesInExpanded)(tree, expandedIds);
|
|
36
|
+
(0, vitest_1.expect)(result).toHaveLength(1);
|
|
37
|
+
(0, vitest_1.expect)(result[0].id).toBe('b');
|
|
38
|
+
});
|
|
39
|
+
(0, vitest_1.it)('does not return nodes without nested property (leaf)', () => {
|
|
40
|
+
const tree = [node('leaf'), node('empty', [])];
|
|
41
|
+
const expandedIds = new Set(['leaf', 'empty']);
|
|
42
|
+
const result = (0, collectEmptyNestedNodesInExpanded_1.collectEmptyNestedNodesInExpanded)(tree, expandedIds);
|
|
43
|
+
(0, vitest_1.expect)(result).toHaveLength(1);
|
|
44
|
+
(0, vitest_1.expect)(result[0].id).toBe('empty');
|
|
45
|
+
});
|
|
46
|
+
(0, vitest_1.it)('returns empty array for empty tree', () => {
|
|
47
|
+
const result = (0, collectEmptyNestedNodesInExpanded_1.collectEmptyNestedNodesInExpanded)([], new Set(['any']));
|
|
48
|
+
(0, vitest_1.expect)(result).toEqual([]);
|
|
49
|
+
});
|
|
50
|
+
(0, vitest_1.it)('returns empty array when expandedIds is empty', () => {
|
|
51
|
+
const tree = [node('a', []), node('b', [])];
|
|
52
|
+
const result = (0, collectEmptyNestedNodesInExpanded_1.collectEmptyNestedNodesInExpanded)(tree, new Set());
|
|
53
|
+
(0, vitest_1.expect)(result).toEqual([]);
|
|
54
|
+
});
|
|
55
|
+
(0, vitest_1.it)('collects from deeply nested nodes', () => {
|
|
56
|
+
const child = node('child', []);
|
|
57
|
+
const tree = [node('root', [node('mid', [child])])];
|
|
58
|
+
const expandedIds = new Set(['root', 'mid', 'child']);
|
|
59
|
+
const result = (0, collectEmptyNestedNodesInExpanded_1.collectEmptyNestedNodesInExpanded)(tree, expandedIds);
|
|
60
|
+
(0, vitest_1.expect)(result).toHaveLength(1);
|
|
61
|
+
(0, vitest_1.expect)(result[0]).toMatchObject({
|
|
62
|
+
id: 'child',
|
|
63
|
+
nested: []
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
(0, vitest_1.it)('returns all matching nodes from different levels', () => {
|
|
67
|
+
const tree = [node('a', []), node('b', [node('b1', []), node('b2', [])])];
|
|
68
|
+
const expandedIds = new Set(['a', 'b', 'b1', 'b2']);
|
|
69
|
+
const result = (0, collectEmptyNestedNodesInExpanded_1.collectEmptyNestedNodesInExpanded)(tree, expandedIds);
|
|
70
|
+
(0, vitest_1.expect)(result).toHaveLength(3);
|
|
71
|
+
(0, vitest_1.expect)(result.map(n => n.id).sort()).toEqual(['a', 'b1', 'b2']);
|
|
72
|
+
});
|
|
73
|
+
(0, vitest_1.it)('only includes node if both empty nested and expanded', () => {
|
|
74
|
+
const tree = [node('expanded', []), node('collapsed', [])];
|
|
75
|
+
const expandedIds = new Set(['expanded']);
|
|
76
|
+
const result = (0, collectEmptyNestedNodesInExpanded_1.collectEmptyNestedNodesInExpanded)(tree, expandedIds);
|
|
77
|
+
(0, vitest_1.expect)(result).toHaveLength(1);
|
|
78
|
+
(0, vitest_1.expect)(result[0].id).toBe('expanded');
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
const vitest_1 = require("vitest");
|
|
7
|
+
const setChildrenOfTreeNode_1 = require("../setChildrenOfTreeNode");
|
|
8
|
+
const node = (id, nested) => Object.assign({
|
|
9
|
+
id,
|
|
10
|
+
title: id
|
|
11
|
+
}, nested !== undefined && {
|
|
12
|
+
nested: nested.map(n => Object.assign(Object.assign({}, n), {
|
|
13
|
+
title: n.id
|
|
14
|
+
}))
|
|
15
|
+
});
|
|
16
|
+
(0, vitest_1.describe)('setChildrenOfTreeNode', () => {
|
|
17
|
+
(0, vitest_1.it)('replaces nested for root-level node', () => {
|
|
18
|
+
const tree = [node('a', [{
|
|
19
|
+
id: 'a1',
|
|
20
|
+
title: 'a1'
|
|
21
|
+
}]), node('b', [{
|
|
22
|
+
id: 'b1',
|
|
23
|
+
title: 'b1'
|
|
24
|
+
}])];
|
|
25
|
+
const children = [node('new1'), node('new2')];
|
|
26
|
+
const result = (0, setChildrenOfTreeNode_1.setChildrenOfTreeNode)(tree, 'b', children);
|
|
27
|
+
(0, vitest_1.expect)(result).toHaveLength(2);
|
|
28
|
+
(0, vitest_1.expect)(result[0]).toMatchObject({
|
|
29
|
+
id: 'a',
|
|
30
|
+
nested: [{
|
|
31
|
+
id: 'a1'
|
|
32
|
+
}]
|
|
33
|
+
});
|
|
34
|
+
(0, vitest_1.expect)(result[1]).toMatchObject({
|
|
35
|
+
id: 'b',
|
|
36
|
+
nested: [{
|
|
37
|
+
id: 'new1'
|
|
38
|
+
}, {
|
|
39
|
+
id: 'new2'
|
|
40
|
+
}]
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
(0, vitest_1.it)('replaces nested for deeply nested node', () => {
|
|
44
|
+
const childWithNested = node('child');
|
|
45
|
+
childWithNested.nested = [{
|
|
46
|
+
id: 'grand',
|
|
47
|
+
title: 'grand'
|
|
48
|
+
}];
|
|
49
|
+
const tree = [node('root', [childWithNested])];
|
|
50
|
+
const children = [node('replacement')];
|
|
51
|
+
const result = (0, setChildrenOfTreeNode_1.setChildrenOfTreeNode)(tree, 'child', children);
|
|
52
|
+
const root = result[0];
|
|
53
|
+
(0, vitest_1.expect)(root.nested).toHaveLength(1);
|
|
54
|
+
(0, vitest_1.expect)(root.nested[0]).toMatchObject({
|
|
55
|
+
id: 'child',
|
|
56
|
+
nested: [{
|
|
57
|
+
id: 'replacement'
|
|
58
|
+
}]
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
(0, vitest_1.it)('returns cloned tree when node is not found', () => {
|
|
62
|
+
const tree = [node('a'), node('b')];
|
|
63
|
+
const result = (0, setChildrenOfTreeNode_1.setChildrenOfTreeNode)(tree, 'missing', [node('x')]);
|
|
64
|
+
(0, vitest_1.expect)(result).toHaveLength(2);
|
|
65
|
+
(0, vitest_1.expect)(result[0]).toMatchObject({
|
|
66
|
+
id: 'a'
|
|
67
|
+
});
|
|
68
|
+
(0, vitest_1.expect)(result[1]).toMatchObject({
|
|
69
|
+
id: 'b'
|
|
70
|
+
});
|
|
71
|
+
(0, vitest_1.expect)(result).not.toBe(tree);
|
|
72
|
+
});
|
|
73
|
+
(0, vitest_1.it)('returns empty array for empty tree', () => {
|
|
74
|
+
const result = (0, setChildrenOfTreeNode_1.setChildrenOfTreeNode)([], 'any', [node('x')]);
|
|
75
|
+
(0, vitest_1.expect)(result).toEqual([]);
|
|
76
|
+
});
|
|
77
|
+
(0, vitest_1.it)('sets children for target node that had no nested (leaf)', () => {
|
|
78
|
+
const tree = [node('leaf'), node('other')];
|
|
79
|
+
const children = [node('new1')];
|
|
80
|
+
const result = (0, setChildrenOfTreeNode_1.setChildrenOfTreeNode)(tree, 'leaf', children);
|
|
81
|
+
(0, vitest_1.expect)(result[0]).toMatchObject({
|
|
82
|
+
id: 'leaf',
|
|
83
|
+
nested: [{
|
|
84
|
+
id: 'new1'
|
|
85
|
+
}]
|
|
86
|
+
});
|
|
87
|
+
(0, vitest_1.expect)(result[1]).toMatchObject({
|
|
88
|
+
id: 'other'
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
(0, vitest_1.it)('preserves order of root nodes when target is second', () => {
|
|
92
|
+
const tree = [node('first'), node('second', [{
|
|
93
|
+
id: 's1',
|
|
94
|
+
title: 's1'
|
|
95
|
+
}]), node('third')];
|
|
96
|
+
const children = [node('new1'), node('new2')];
|
|
97
|
+
const result = (0, setChildrenOfTreeNode_1.setChildrenOfTreeNode)(tree, 'second', children);
|
|
98
|
+
(0, vitest_1.expect)(result.map(n => n.id)).toEqual(['first', 'second', 'third']);
|
|
99
|
+
(0, vitest_1.expect)(result[1].nested).toHaveLength(2);
|
|
100
|
+
(0, vitest_1.expect)(result[1].nested.map(n => n.id)).toEqual(['new1', 'new2']);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.collectEmptyNestedNodesInExpanded = collectEmptyNestedNodesInExpanded;
|
|
7
|
+
const traverse_1 = require("./traverse");
|
|
8
|
+
function collectEmptyNestedNodesInExpanded(nodes, expandedIds) {
|
|
9
|
+
const result = [];
|
|
10
|
+
(0, traverse_1.traverse)(nodes, node => {
|
|
11
|
+
const hasEmptyNested = Array.isArray(node.nested) && node.nested.length === 0;
|
|
12
|
+
if (hasEmptyNested && expandedIds.has(node.id)) {
|
|
13
|
+
result.push(node);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
@@ -29,4 +29,6 @@ __exportStar(require("./getSearchedTreeItems"), exports);
|
|
|
29
29
|
__exportStar(require("./getSearchedTreeNodeById"), exports);
|
|
30
30
|
__exportStar(require("./lookupTreeForSelectedNodes"), exports);
|
|
31
31
|
__exportStar(require("./sortTreeItemsByTitle"), exports);
|
|
32
|
-
__exportStar(require("./traverse"), exports);
|
|
32
|
+
__exportStar(require("./traverse"), exports);
|
|
33
|
+
__exportStar(require("./setChildrenOfTreeNode"), exports);
|
|
34
|
+
__exportStar(require("./collectEmptyNestedNodesInExpanded"), exports);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.setChildrenOfTreeNode = void 0;
|
|
7
|
+
const traverse_1 = require("./traverse");
|
|
8
|
+
const setChildrenOfTreeNode = (tree, nodeId, children) => {
|
|
9
|
+
const result = [];
|
|
10
|
+
(0, traverse_1.traverseWithTarget)(tree, result, (source, _depth, targetList) => {
|
|
11
|
+
var _a;
|
|
12
|
+
const isTarget = source.id === nodeId;
|
|
13
|
+
const hasNested = Array.isArray(source.nested);
|
|
14
|
+
let newNested;
|
|
15
|
+
if (isTarget) {
|
|
16
|
+
newNested = children;
|
|
17
|
+
} else if (hasNested) {
|
|
18
|
+
newNested = [];
|
|
19
|
+
}
|
|
20
|
+
const newNode = newNested !== undefined ? Object.assign(Object.assign({}, source), {
|
|
21
|
+
nested: newNested
|
|
22
|
+
}) : Object.assign({}, source);
|
|
23
|
+
targetList.push(newNode);
|
|
24
|
+
return !isTarget && hasNested && ((_a = source.nested) === null || _a === void 0 ? void 0 : _a.length) ? newNested : undefined;
|
|
25
|
+
});
|
|
26
|
+
return result;
|
|
27
|
+
};
|
|
28
|
+
exports.setChildrenOfTreeNode = setChildrenOfTreeNode;
|
|
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.sortTreeItemsByTitle = void 0;
|
|
7
7
|
const extractTreeNodeTitle_1 = require("./extractTreeNodeTitle");
|
|
8
8
|
const sortTreeItemsByTitle = items => items === null || items === void 0 ? void 0 : items.toSorted((itemA, itemB) => {
|
|
9
|
-
const valueA = (0, extractTreeNodeTitle_1.extractTreeNodeTitle)(itemA);
|
|
10
|
-
const valueB = (0, extractTreeNodeTitle_1.extractTreeNodeTitle)(itemB);
|
|
9
|
+
const valueA = (0, extractTreeNodeTitle_1.extractTreeNodeTitle)(itemA).toLowerCase();
|
|
10
|
+
const valueB = (0, extractTreeNodeTitle_1.extractTreeNodeTitle)(itemB).toLowerCase();
|
|
11
11
|
return valueA.localeCompare(valueB);
|
|
12
12
|
});
|
|
13
13
|
exports.sortTreeItemsByTitle = sortTreeItemsByTitle;
|
|
@@ -1,2 +1,8 @@
|
|
|
1
1
|
import { TreeNodeProps } from '../';
|
|
2
2
|
export declare const traverse: <T extends TreeNodeProps>(nodes: T[], callback: (node: T, depth: number) => void) => void;
|
|
3
|
+
/**
|
|
4
|
+
* BFS с указанием целевого списка для каждого узла.
|
|
5
|
+
* Очередь хранит (node, depth, targetList). Callback добавляет узел в targetList
|
|
6
|
+
* и возвращает массив для детей (или undefined, чтобы не обходить детей).
|
|
7
|
+
*/
|
|
8
|
+
export declare const traverseWithTarget: <T extends TreeNodeProps>(nodes: T[], rootTargetList: T[], callback: (node: T, depth: number, targetList: T[]) => T[] | undefined) => void;
|
|
@@ -8,7 +8,7 @@ var __importDefault = void 0 && (void 0).__importDefault || function (mod) {
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", {
|
|
9
9
|
value: true
|
|
10
10
|
});
|
|
11
|
-
exports.traverse = void 0;
|
|
11
|
+
exports.traverseWithTarget = exports.traverse = void 0;
|
|
12
12
|
const queue_fifo_1 = __importDefault(require("queue-fifo"));
|
|
13
13
|
const traverse = (nodes, callback) => {
|
|
14
14
|
var _a;
|
|
@@ -37,4 +37,40 @@ const traverse = (nodes, callback) => {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
};
|
|
40
|
-
exports.traverse = traverse;
|
|
40
|
+
exports.traverse = traverse;
|
|
41
|
+
/**
|
|
42
|
+
* BFS с указанием целевого списка для каждого узла.
|
|
43
|
+
* Очередь хранит (node, depth, targetList). Callback добавляет узел в targetList
|
|
44
|
+
* и возвращает массив для детей (или undefined, чтобы не обходить детей).
|
|
45
|
+
*/
|
|
46
|
+
const traverseWithTarget = (nodes, rootTargetList, callback) => {
|
|
47
|
+
var _a;
|
|
48
|
+
const queue = new queue_fifo_1.default();
|
|
49
|
+
for (const node of nodes) {
|
|
50
|
+
queue.enqueue({
|
|
51
|
+
node,
|
|
52
|
+
depth: 0,
|
|
53
|
+
targetList: rootTargetList
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
while (!queue.isEmpty()) {
|
|
57
|
+
const item = queue.dequeue();
|
|
58
|
+
if (!item) continue;
|
|
59
|
+
const {
|
|
60
|
+
node,
|
|
61
|
+
depth,
|
|
62
|
+
targetList
|
|
63
|
+
} = item;
|
|
64
|
+
const childTargetList = callback(node, depth, targetList);
|
|
65
|
+
if (childTargetList !== undefined && ((_a = node.nested) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
66
|
+
for (const child of node.nested) {
|
|
67
|
+
queue.enqueue({
|
|
68
|
+
node: child,
|
|
69
|
+
depth: depth + 1,
|
|
70
|
+
targetList: childTargetList
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
exports.traverseWithTarget = traverseWithTarget;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = {
|
|
8
|
+
enumerable: true,
|
|
9
|
+
get: function () {
|
|
10
|
+
return m[k];
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
} : function (o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
});
|
|
19
|
+
var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) {
|
|
20
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
21
|
+
};
|
|
22
|
+
Object.defineProperty(exports, "__esModule", {
|
|
23
|
+
value: true
|
|
24
|
+
});
|
|
25
|
+
__exportStar(require("./useTreeWithPreload"), exports);
|
|
26
|
+
__exportStar(require("./useTreeMultiSelection"), exports);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PreloadNodeHandler, SelectHandler, TreeNodeProps } from '../types';
|
|
2
|
+
type UseTreeMultiSelectionParams<TTreeNode extends TreeNodeProps> = {
|
|
3
|
+
onDataLoad: PreloadNodeHandler<TTreeNode>;
|
|
4
|
+
onSelect: SelectHandler;
|
|
5
|
+
selected?: string[];
|
|
6
|
+
onChangeSelected?: (newSelected: string[]) => void;
|
|
7
|
+
};
|
|
8
|
+
export declare function useTreeMultiSelection<TTreeNode extends TreeNodeProps>({ onDataLoad, onSelect: onSelectProp, selected, onChangeSelected, }: UseTreeMultiSelectionParams<TTreeNode>): {
|
|
9
|
+
selected: string[];
|
|
10
|
+
onSelect: (selectedKeys: string[], node: TreeNodeProps) => Promise<void>;
|
|
11
|
+
};
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var __awaiter = void 0 && (void 0).__awaiter || function (thisArg, _arguments, P, generator) {
|
|
4
|
+
function adopt(value) {
|
|
5
|
+
return value instanceof P ? value : new P(function (resolve) {
|
|
6
|
+
resolve(value);
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
+
function fulfilled(value) {
|
|
11
|
+
try {
|
|
12
|
+
step(generator.next(value));
|
|
13
|
+
} catch (e) {
|
|
14
|
+
reject(e);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function rejected(value) {
|
|
18
|
+
try {
|
|
19
|
+
step(generator["throw"](value));
|
|
20
|
+
} catch (e) {
|
|
21
|
+
reject(e);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function step(result) {
|
|
25
|
+
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
26
|
+
}
|
|
27
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
Object.defineProperty(exports, "__esModule", {
|
|
31
|
+
value: true
|
|
32
|
+
});
|
|
33
|
+
exports.useTreeMultiSelection = useTreeMultiSelection;
|
|
34
|
+
const react_1 = require("react");
|
|
35
|
+
const utils_1 = require("@snack-uikit/utils");
|
|
36
|
+
const getNewSelectedIds = (selectedIds, added, removed) => {
|
|
37
|
+
const result = new Set(selectedIds);
|
|
38
|
+
added.forEach(id => {
|
|
39
|
+
result.add(id);
|
|
40
|
+
});
|
|
41
|
+
removed.forEach(id => {
|
|
42
|
+
result.delete(id);
|
|
43
|
+
});
|
|
44
|
+
return Array.from(result);
|
|
45
|
+
};
|
|
46
|
+
function useTreeMultiSelection(_ref) {
|
|
47
|
+
let {
|
|
48
|
+
onDataLoad,
|
|
49
|
+
onSelect: onSelectProp,
|
|
50
|
+
selected,
|
|
51
|
+
onChangeSelected
|
|
52
|
+
} = _ref;
|
|
53
|
+
const [selectedIds = [], setSelectedIds] = (0, utils_1.useValueControl)({
|
|
54
|
+
value: selected,
|
|
55
|
+
defaultValue: [],
|
|
56
|
+
onChange: onChangeSelected
|
|
57
|
+
});
|
|
58
|
+
const onSelect = (0, react_1.useCallback)((selectedKeys, node) => __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
const isSelected = selectedKeys.includes(node.id);
|
|
60
|
+
const clonedNode = structuredClone(node);
|
|
61
|
+
if (node.nested && !node.nested.length) {
|
|
62
|
+
const {
|
|
63
|
+
preloadedChildren
|
|
64
|
+
} = yield onDataLoad(node);
|
|
65
|
+
clonedNode.nested = preloadedChildren;
|
|
66
|
+
}
|
|
67
|
+
const {
|
|
68
|
+
added,
|
|
69
|
+
removed
|
|
70
|
+
} = onSelectProp({
|
|
71
|
+
selectedKeys,
|
|
72
|
+
node: clonedNode,
|
|
73
|
+
isSelected
|
|
74
|
+
});
|
|
75
|
+
const updatedSelectedIds = getNewSelectedIds(selectedIds, added, removed);
|
|
76
|
+
setSelectedIds(updatedSelectedIds);
|
|
77
|
+
}), [onDataLoad, onSelectProp, selectedIds, setSelectedIds]);
|
|
78
|
+
return {
|
|
79
|
+
selected: selectedIds,
|
|
80
|
+
onSelect
|
|
81
|
+
};
|
|
82
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { TreeNodeProps } from '../types';
|
|
2
|
+
export type SearchResult<TTreeNode extends TreeNodeProps> = {
|
|
3
|
+
tree: TTreeNode[];
|
|
4
|
+
needPreloadNodes: string[];
|
|
5
|
+
};
|
|
6
|
+
export type SearchParams = {
|
|
7
|
+
search: string;
|
|
8
|
+
expandedNodes: string[];
|
|
9
|
+
};
|
|
10
|
+
type UseTreeWithPreloadParams<TRecordValue, TTreeNode extends TreeNodeProps> = {
|
|
11
|
+
initTree: TTreeNode[];
|
|
12
|
+
onPreloadNode: (node: TreeNodeProps) => Promise<TTreeNode[]>;
|
|
13
|
+
onPreloadNodes: (nodes: string[]) => Promise<Record<string, TTreeNode[]>>;
|
|
14
|
+
onSearch: (params: SearchParams) => Promise<SearchResult<TTreeNode>>;
|
|
15
|
+
mapNodeToRecordItem: (node: TTreeNode) => TRecordValue;
|
|
16
|
+
};
|
|
17
|
+
export declare function useTreeWithPreload<TRecordValue, TTreeNode extends TreeNodeProps>({ initTree, onPreloadNode, onPreloadNodes, onSearch, mapNodeToRecordItem, }: UseTreeWithPreloadParams<TRecordValue, TTreeNode>): {
|
|
18
|
+
tree: import("@siberiacancode/reactuse").StateRef<TTreeNode[]>;
|
|
19
|
+
expandedNodes: import("@siberiacancode/reactuse").StateRef<string[]>;
|
|
20
|
+
loading: boolean;
|
|
21
|
+
treeItemsRecord: import("@siberiacancode/reactuse").StateRef<Record<string, TRecordValue>>;
|
|
22
|
+
search: {
|
|
23
|
+
value: string;
|
|
24
|
+
onChange: import("react").Dispatch<import("react").SetStateAction<string>>;
|
|
25
|
+
};
|
|
26
|
+
onExpand: (nodes: string[]) => void;
|
|
27
|
+
onDataLoad: (node: TreeNodeProps) => Promise<{
|
|
28
|
+
preloadedChildren: TTreeNode[];
|
|
29
|
+
updatedTree: TTreeNode[];
|
|
30
|
+
newTreeItemsRecord: Record<string, TRecordValue>;
|
|
31
|
+
}>;
|
|
32
|
+
};
|
|
33
|
+
export {};
|