@react-fabric/data 1.0.0-beta.55 → 1.0.0-beta.56
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/dist/cjs/tree/TreeNode.js +1 -0
- package/dist/cjs/tree/TreePanel.js +13 -0
- package/dist/cjs/tree/useTree.js +51 -30
- package/dist/cjs/tree/utils.js +2 -1
- package/dist/esm/tree/TreeNode.js +1 -0
- package/dist/esm/tree/TreePanel.js +14 -1
- package/dist/esm/tree/useTree.js +52 -31
- package/dist/esm/tree/utils.js +2 -1
- package/dist/types/tree/types.d.ts +1 -0
- package/dist/types/tree/useTree.d.ts +2 -0
- package/dist/types/tree/utils.d.ts +1 -1
- package/package.json +3 -3
- package/src/tree/TreeNode.tsx +1 -0
- package/src/tree/TreePanel.tsx +9 -1
- package/src/tree/types.ts +1 -2
- package/src/tree/useTree.ts +54 -28
- package/src/tree/utils.ts +3 -2
|
@@ -66,6 +66,7 @@ var TreeNode = function TreeNode(_ref) {
|
|
|
66
66
|
className: classNames("flex flex-nowrap items-center"),
|
|
67
67
|
"data-testid": node["data-testid"],
|
|
68
68
|
"data-test-value": node["data-test-value"],
|
|
69
|
+
"data-id": node.id,
|
|
69
70
|
children: [filler, node.loading && /*#__PURE__*/jsxRuntime.jsx("div", {
|
|
70
71
|
className: "flex-initial w-6",
|
|
71
72
|
children: /*#__PURE__*/jsxRuntime.jsx(core.Icon, {
|
|
@@ -58,10 +58,12 @@ var TreePanel = function TreePanel(_ref) {
|
|
|
58
58
|
}),
|
|
59
59
|
tree = _useTree.tree,
|
|
60
60
|
query = _useTree.query,
|
|
61
|
+
currentSelected = _useTree.selected,
|
|
61
62
|
toggleExpand = _useTree.toggleExpand,
|
|
62
63
|
toggleCheck = _useTree.toggleCheck,
|
|
63
64
|
expandAll = _useTree.expandAll,
|
|
64
65
|
collapseAll = _useTree.collapseAll,
|
|
66
|
+
expandAndLoad = _useTree.expandAndLoad,
|
|
65
67
|
_select = _useTree.select,
|
|
66
68
|
expand = _useTree.expand,
|
|
67
69
|
onFilter = _useTree.onFilter;
|
|
@@ -87,11 +89,22 @@ var TreePanel = function TreePanel(_ref) {
|
|
|
87
89
|
open: function open(id) {
|
|
88
90
|
return expand(id);
|
|
89
91
|
},
|
|
92
|
+
openAndLoad: function openAndLoad(list) {
|
|
93
|
+
return expandAndLoad(list);
|
|
94
|
+
},
|
|
90
95
|
select: function select(id) {
|
|
91
96
|
return _select(id);
|
|
92
97
|
}
|
|
93
98
|
};
|
|
94
99
|
}, []);
|
|
100
|
+
react.useEffect(function () {
|
|
101
|
+
var index = tree.findIndex(function (n) {
|
|
102
|
+
return n.id === currentSelected;
|
|
103
|
+
});
|
|
104
|
+
virtualizer.scrollToIndex(index, {
|
|
105
|
+
align: "auto"
|
|
106
|
+
});
|
|
107
|
+
}, [currentSelected]);
|
|
95
108
|
return /*#__PURE__*/jsxRuntime.jsxs(core.Section, {
|
|
96
109
|
children: [/*#__PURE__*/jsxRuntime.jsxs(core.Header, {
|
|
97
110
|
flex: true,
|
package/dist/cjs/tree/useTree.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var _defineProperty = require('@babel/runtime/helpers/defineProperty');
|
|
4
4
|
var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
|
|
5
|
+
var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
|
|
5
6
|
var core = require('@react-fabric/core');
|
|
6
7
|
var utilities = require('@react-fabric/utilities');
|
|
7
8
|
var memoizeOne = require('memoize-one');
|
|
@@ -31,7 +32,7 @@ var useTree = function useTree(_ref) {
|
|
|
31
32
|
onSelect: onSelect,
|
|
32
33
|
onChecked: onChecked
|
|
33
34
|
});
|
|
34
|
-
var intialExpand = react.useRef(defaultExpanded !== null && defaultExpanded !== void 0 ? defaultExpanded : utilities.EMPTY_ARRAY);
|
|
35
|
+
var intialExpand = react.useRef(_toConsumableArray(defaultExpanded !== null && defaultExpanded !== void 0 ? defaultExpanded : utilities.EMPTY_ARRAY));
|
|
35
36
|
var itemList = createItemList(items);
|
|
36
37
|
var fireExpandToggle = react.useCallback(function (itemMap) {
|
|
37
38
|
var expandedList = itemMap.filter(function (node) {
|
|
@@ -47,26 +48,29 @@ var useTree = function useTree(_ref) {
|
|
|
47
48
|
var _node$children;
|
|
48
49
|
if (node.open && !node.leaf && !((_node$children = node.children) !== null && _node$children !== void 0 && _node$children.length)) {
|
|
49
50
|
node.loading = true;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
51
|
+
// delay onload callback to avoid state issues
|
|
52
|
+
setTimeout(function () {
|
|
53
|
+
void Promise.resolve(onLoad === null || onLoad === void 0 ? void 0 : onLoad(node.id)).then(function () {
|
|
54
|
+
var resp = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : utilities.EMPTY_ARRAY;
|
|
55
|
+
node.children = utils.refactorTree(resp, {
|
|
56
|
+
sorter: sorter,
|
|
57
|
+
defaultExpanded: defaultExpanded
|
|
58
|
+
}, {
|
|
59
|
+
level: node.level + 1,
|
|
60
|
+
parent: node.id
|
|
61
|
+
});
|
|
62
|
+
})["finally"](function () {
|
|
63
|
+
var _intialExpand$current;
|
|
64
|
+
node.loading = false;
|
|
65
|
+
dispatch({
|
|
66
|
+
type: "loaded"
|
|
67
|
+
});
|
|
68
|
+
((_intialExpand$current = intialExpand.current) === null || _intialExpand$current === void 0 ? void 0 : _intialExpand$current.length) > 0 && dispatch({
|
|
69
|
+
type: "expand",
|
|
70
|
+
id: intialExpand.current.shift()
|
|
71
|
+
});
|
|
68
72
|
});
|
|
69
|
-
});
|
|
73
|
+
}, 100);
|
|
70
74
|
} else {
|
|
71
75
|
var _intialExpand$current2;
|
|
72
76
|
dispatch({
|
|
@@ -86,6 +90,9 @@ var useTree = function useTree(_ref) {
|
|
|
86
90
|
var _componentEvents$curr3, _componentEvents$curr4;
|
|
87
91
|
(_componentEvents$curr3 = (_componentEvents$curr4 = componentEvents.current).onChecked) === null || _componentEvents$curr3 === void 0 || _componentEvents$curr3.call(_componentEvents$curr4, leafs, nodes, partials);
|
|
88
92
|
}, [onChecked]);
|
|
93
|
+
var fireQuery = core.useDebounce(function (query) {
|
|
94
|
+
onQuery === null || onQuery === void 0 || onQuery(query);
|
|
95
|
+
}, [onQuery]);
|
|
89
96
|
var _useReducer = react.useReducer(function (state, action) {
|
|
90
97
|
if (action.type === "load") {
|
|
91
98
|
state.items = utils.refactorTree(action.items, {
|
|
@@ -112,7 +119,7 @@ var useTree = function useTree(_ref) {
|
|
|
112
119
|
state.itemMap = utils.makeTreeMap(state.items);
|
|
113
120
|
fireExpandToggle(Array.from(state.itemMap.values()));
|
|
114
121
|
state.tree = utils.flattenTree(state.items);
|
|
115
|
-
state.selected
|
|
122
|
+
state.selected = utils.updateSelection(state.itemMap, selected, true);
|
|
116
123
|
(_state$checked = state.checked) === null || _state$checked === void 0 || _state$checked.forEach(function (id) {
|
|
117
124
|
return utils.updateChecked(state.itemMap, id, 1);
|
|
118
125
|
});
|
|
@@ -151,8 +158,13 @@ var useTree = function useTree(_ref) {
|
|
|
151
158
|
}
|
|
152
159
|
if (action.type === "filter") {
|
|
153
160
|
if (onQuery) {
|
|
154
|
-
|
|
155
|
-
|
|
161
|
+
// TODO: onQuery should provide new tree listing
|
|
162
|
+
// save current tree state as preQueryState
|
|
163
|
+
// on clearing filter restore preQueryState
|
|
164
|
+
if (!utilities.isEmpty(action.query)) {
|
|
165
|
+
// state.prevItems = state.items;
|
|
166
|
+
fireQuery(action.query);
|
|
167
|
+
}
|
|
156
168
|
} else {
|
|
157
169
|
utils.filterTree(state.itemMap, action.query, matcher);
|
|
158
170
|
state.tree = utils.flattenTree(state.items);
|
|
@@ -162,12 +174,11 @@ var useTree = function useTree(_ref) {
|
|
|
162
174
|
});
|
|
163
175
|
}
|
|
164
176
|
if (action.type === "toggleSelect") {
|
|
165
|
-
if (state.selected) {
|
|
166
|
-
utils.updateSelection(state.itemMap, state.selected);
|
|
167
|
-
}
|
|
168
177
|
if (!onSelect) {
|
|
169
|
-
|
|
170
|
-
|
|
178
|
+
if (state.selected) {
|
|
179
|
+
utils.updateSelection(state.itemMap, state.selected);
|
|
180
|
+
}
|
|
181
|
+
state.selected = utils.updateSelection(state.itemMap, action.id, true);
|
|
171
182
|
state.tree = utils.flattenTree(state.items);
|
|
172
183
|
} else {
|
|
173
184
|
var _state$itemMap$get;
|
|
@@ -179,8 +190,7 @@ var useTree = function useTree(_ref) {
|
|
|
179
190
|
if (state.selected) {
|
|
180
191
|
utils.updateSelection(state.itemMap, state.selected);
|
|
181
192
|
}
|
|
182
|
-
utils.updateSelection(state.itemMap, action.id, true);
|
|
183
|
-
state.selected = action.id;
|
|
193
|
+
state.selected = utils.updateSelection(state.itemMap, action.id, true);
|
|
184
194
|
state.tree = utils.flattenTree(state.items);
|
|
185
195
|
return _objectSpread({}, state);
|
|
186
196
|
}
|
|
@@ -285,6 +295,15 @@ var useTree = function useTree(_ref) {
|
|
|
285
295
|
id: id
|
|
286
296
|
});
|
|
287
297
|
}, []);
|
|
298
|
+
var expandAndLoad = react.useCallback(function (expandList) {
|
|
299
|
+
if (expandList.length > 0) {
|
|
300
|
+
intialExpand.current = _toConsumableArray(expandList);
|
|
301
|
+
dispatch({
|
|
302
|
+
type: "expand",
|
|
303
|
+
id: intialExpand.current.shift()
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}, []);
|
|
288
307
|
var expandAll = react.useCallback(function () {
|
|
289
308
|
dispatch({
|
|
290
309
|
type: "expandAll"
|
|
@@ -304,10 +323,12 @@ var useTree = function useTree(_ref) {
|
|
|
304
323
|
return {
|
|
305
324
|
tree: state.tree,
|
|
306
325
|
query: state.query,
|
|
326
|
+
selected: state.selected,
|
|
307
327
|
toggleExpand: toggleExpand,
|
|
308
328
|
expandAll: expandAll,
|
|
309
329
|
collapseAll: collapseAll,
|
|
310
330
|
toggleCheck: toggleCheck,
|
|
331
|
+
expandAndLoad: expandAndLoad,
|
|
311
332
|
select: select,
|
|
312
333
|
expand: expand,
|
|
313
334
|
onFilter: onFilter
|
package/dist/cjs/tree/utils.js
CHANGED
|
@@ -96,7 +96,7 @@ var flattenTree = function flattenTree(nodes) {
|
|
|
96
96
|
return list;
|
|
97
97
|
};
|
|
98
98
|
var updateSelection = function updateSelection(nodes, id, selected) {
|
|
99
|
-
var node = nodes.get(id);
|
|
99
|
+
var node = nodes.get(id !== null && id !== void 0 ? id : "");
|
|
100
100
|
if (node) {
|
|
101
101
|
// change selection
|
|
102
102
|
node.selected = selected;
|
|
@@ -108,6 +108,7 @@ var updateSelection = function updateSelection(nodes, id, selected) {
|
|
|
108
108
|
// selected && parentNode && (parentNode.open = true);
|
|
109
109
|
parent = parentNode === null || parentNode === void 0 ? void 0 : parentNode.parent;
|
|
110
110
|
}
|
|
111
|
+
return id;
|
|
111
112
|
}
|
|
112
113
|
};
|
|
113
114
|
var updateChecked = function updateChecked(list, id, checked) {
|
|
@@ -66,6 +66,7 @@ var TreeNode = function TreeNode(_ref) {
|
|
|
66
66
|
className: classNames("flex flex-nowrap items-center"),
|
|
67
67
|
"data-testid": node["data-testid"],
|
|
68
68
|
"data-test-value": node["data-test-value"],
|
|
69
|
+
"data-id": node.id,
|
|
69
70
|
children: [filler, node.loading && /*#__PURE__*/jsx("div", {
|
|
70
71
|
className: "flex-initial w-6",
|
|
71
72
|
children: /*#__PURE__*/jsx(Icon, {
|
|
@@ -5,7 +5,7 @@ import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProper
|
|
|
5
5
|
import { CoreIcons, Section, Header, Icon, ButtonGroup, Button } from '@react-fabric/core';
|
|
6
6
|
import { Search } from '@react-fabric/form';
|
|
7
7
|
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
8
|
-
import { useRef, useMemo, useImperativeHandle } from 'react';
|
|
8
|
+
import { useRef, useMemo, useImperativeHandle, useEffect } from 'react';
|
|
9
9
|
import { TreeNode } from './TreeNode.js';
|
|
10
10
|
import { iconExpandAll, iconCollapseAll } from './types.js';
|
|
11
11
|
import { useTree } from './useTree.js';
|
|
@@ -58,10 +58,12 @@ var TreePanel = function TreePanel(_ref) {
|
|
|
58
58
|
}),
|
|
59
59
|
tree = _useTree.tree,
|
|
60
60
|
query = _useTree.query,
|
|
61
|
+
currentSelected = _useTree.selected,
|
|
61
62
|
toggleExpand = _useTree.toggleExpand,
|
|
62
63
|
toggleCheck = _useTree.toggleCheck,
|
|
63
64
|
expandAll = _useTree.expandAll,
|
|
64
65
|
collapseAll = _useTree.collapseAll,
|
|
66
|
+
expandAndLoad = _useTree.expandAndLoad,
|
|
65
67
|
_select = _useTree.select,
|
|
66
68
|
expand = _useTree.expand,
|
|
67
69
|
onFilter = _useTree.onFilter;
|
|
@@ -87,11 +89,22 @@ var TreePanel = function TreePanel(_ref) {
|
|
|
87
89
|
open: function open(id) {
|
|
88
90
|
return expand(id);
|
|
89
91
|
},
|
|
92
|
+
openAndLoad: function openAndLoad(list) {
|
|
93
|
+
return expandAndLoad(list);
|
|
94
|
+
},
|
|
90
95
|
select: function select(id) {
|
|
91
96
|
return _select(id);
|
|
92
97
|
}
|
|
93
98
|
};
|
|
94
99
|
}, []);
|
|
100
|
+
useEffect(function () {
|
|
101
|
+
var index = tree.findIndex(function (n) {
|
|
102
|
+
return n.id === currentSelected;
|
|
103
|
+
});
|
|
104
|
+
virtualizer.scrollToIndex(index, {
|
|
105
|
+
align: "auto"
|
|
106
|
+
});
|
|
107
|
+
}, [currentSelected]);
|
|
95
108
|
return /*#__PURE__*/jsxs(Section, {
|
|
96
109
|
children: [/*#__PURE__*/jsxs(Header, {
|
|
97
110
|
flex: true,
|
package/dist/esm/tree/useTree.js
CHANGED
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
4
4
|
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
5
|
+
import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
|
|
5
6
|
import { useDebounce } from '@react-fabric/core';
|
|
6
|
-
import { EMPTY_ARRAY } from '@react-fabric/utilities';
|
|
7
|
+
import { EMPTY_ARRAY, isEmpty } from '@react-fabric/utilities';
|
|
7
8
|
import memoizeOne from 'memoize-one';
|
|
8
9
|
import { useRef, useCallback, useReducer, useEffect } from 'react';
|
|
9
10
|
import { refactorTree, makeTreeMap, flattenTree, updateSelection, updateChecked, filterTree } from './utils.js';
|
|
@@ -31,7 +32,7 @@ var useTree = function useTree(_ref) {
|
|
|
31
32
|
onSelect: onSelect,
|
|
32
33
|
onChecked: onChecked
|
|
33
34
|
});
|
|
34
|
-
var intialExpand = useRef(defaultExpanded !== null && defaultExpanded !== void 0 ? defaultExpanded : EMPTY_ARRAY);
|
|
35
|
+
var intialExpand = useRef(_toConsumableArray(defaultExpanded !== null && defaultExpanded !== void 0 ? defaultExpanded : EMPTY_ARRAY));
|
|
35
36
|
var itemList = createItemList(items);
|
|
36
37
|
var fireExpandToggle = useCallback(function (itemMap) {
|
|
37
38
|
var expandedList = itemMap.filter(function (node) {
|
|
@@ -47,26 +48,29 @@ var useTree = function useTree(_ref) {
|
|
|
47
48
|
var _node$children;
|
|
48
49
|
if (node.open && !node.leaf && !((_node$children = node.children) !== null && _node$children !== void 0 && _node$children.length)) {
|
|
49
50
|
node.loading = true;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
51
|
+
// delay onload callback to avoid state issues
|
|
52
|
+
setTimeout(function () {
|
|
53
|
+
void Promise.resolve(onLoad === null || onLoad === void 0 ? void 0 : onLoad(node.id)).then(function () {
|
|
54
|
+
var resp = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : EMPTY_ARRAY;
|
|
55
|
+
node.children = refactorTree(resp, {
|
|
56
|
+
sorter: sorter,
|
|
57
|
+
defaultExpanded: defaultExpanded
|
|
58
|
+
}, {
|
|
59
|
+
level: node.level + 1,
|
|
60
|
+
parent: node.id
|
|
61
|
+
});
|
|
62
|
+
})["finally"](function () {
|
|
63
|
+
var _intialExpand$current;
|
|
64
|
+
node.loading = false;
|
|
65
|
+
dispatch({
|
|
66
|
+
type: "loaded"
|
|
67
|
+
});
|
|
68
|
+
((_intialExpand$current = intialExpand.current) === null || _intialExpand$current === void 0 ? void 0 : _intialExpand$current.length) > 0 && dispatch({
|
|
69
|
+
type: "expand",
|
|
70
|
+
id: intialExpand.current.shift()
|
|
71
|
+
});
|
|
68
72
|
});
|
|
69
|
-
});
|
|
73
|
+
}, 100);
|
|
70
74
|
} else {
|
|
71
75
|
var _intialExpand$current2;
|
|
72
76
|
dispatch({
|
|
@@ -86,6 +90,9 @@ var useTree = function useTree(_ref) {
|
|
|
86
90
|
var _componentEvents$curr3, _componentEvents$curr4;
|
|
87
91
|
(_componentEvents$curr3 = (_componentEvents$curr4 = componentEvents.current).onChecked) === null || _componentEvents$curr3 === void 0 || _componentEvents$curr3.call(_componentEvents$curr4, leafs, nodes, partials);
|
|
88
92
|
}, [onChecked]);
|
|
93
|
+
var fireQuery = useDebounce(function (query) {
|
|
94
|
+
onQuery === null || onQuery === void 0 || onQuery(query);
|
|
95
|
+
}, [onQuery]);
|
|
89
96
|
var _useReducer = useReducer(function (state, action) {
|
|
90
97
|
if (action.type === "load") {
|
|
91
98
|
state.items = refactorTree(action.items, {
|
|
@@ -112,7 +119,7 @@ var useTree = function useTree(_ref) {
|
|
|
112
119
|
state.itemMap = makeTreeMap(state.items);
|
|
113
120
|
fireExpandToggle(Array.from(state.itemMap.values()));
|
|
114
121
|
state.tree = flattenTree(state.items);
|
|
115
|
-
state.selected
|
|
122
|
+
state.selected = updateSelection(state.itemMap, selected, true);
|
|
116
123
|
(_state$checked = state.checked) === null || _state$checked === void 0 || _state$checked.forEach(function (id) {
|
|
117
124
|
return updateChecked(state.itemMap, id, 1);
|
|
118
125
|
});
|
|
@@ -151,8 +158,13 @@ var useTree = function useTree(_ref) {
|
|
|
151
158
|
}
|
|
152
159
|
if (action.type === "filter") {
|
|
153
160
|
if (onQuery) {
|
|
154
|
-
|
|
155
|
-
|
|
161
|
+
// TODO: onQuery should provide new tree listing
|
|
162
|
+
// save current tree state as preQueryState
|
|
163
|
+
// on clearing filter restore preQueryState
|
|
164
|
+
if (!isEmpty(action.query)) {
|
|
165
|
+
// state.prevItems = state.items;
|
|
166
|
+
fireQuery(action.query);
|
|
167
|
+
}
|
|
156
168
|
} else {
|
|
157
169
|
filterTree(state.itemMap, action.query, matcher);
|
|
158
170
|
state.tree = flattenTree(state.items);
|
|
@@ -162,12 +174,11 @@ var useTree = function useTree(_ref) {
|
|
|
162
174
|
});
|
|
163
175
|
}
|
|
164
176
|
if (action.type === "toggleSelect") {
|
|
165
|
-
if (state.selected) {
|
|
166
|
-
updateSelection(state.itemMap, state.selected);
|
|
167
|
-
}
|
|
168
177
|
if (!onSelect) {
|
|
169
|
-
|
|
170
|
-
|
|
178
|
+
if (state.selected) {
|
|
179
|
+
updateSelection(state.itemMap, state.selected);
|
|
180
|
+
}
|
|
181
|
+
state.selected = updateSelection(state.itemMap, action.id, true);
|
|
171
182
|
state.tree = flattenTree(state.items);
|
|
172
183
|
} else {
|
|
173
184
|
var _state$itemMap$get;
|
|
@@ -179,8 +190,7 @@ var useTree = function useTree(_ref) {
|
|
|
179
190
|
if (state.selected) {
|
|
180
191
|
updateSelection(state.itemMap, state.selected);
|
|
181
192
|
}
|
|
182
|
-
updateSelection(state.itemMap, action.id, true);
|
|
183
|
-
state.selected = action.id;
|
|
193
|
+
state.selected = updateSelection(state.itemMap, action.id, true);
|
|
184
194
|
state.tree = flattenTree(state.items);
|
|
185
195
|
return _objectSpread({}, state);
|
|
186
196
|
}
|
|
@@ -285,6 +295,15 @@ var useTree = function useTree(_ref) {
|
|
|
285
295
|
id: id
|
|
286
296
|
});
|
|
287
297
|
}, []);
|
|
298
|
+
var expandAndLoad = useCallback(function (expandList) {
|
|
299
|
+
if (expandList.length > 0) {
|
|
300
|
+
intialExpand.current = _toConsumableArray(expandList);
|
|
301
|
+
dispatch({
|
|
302
|
+
type: "expand",
|
|
303
|
+
id: intialExpand.current.shift()
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}, []);
|
|
288
307
|
var expandAll = useCallback(function () {
|
|
289
308
|
dispatch({
|
|
290
309
|
type: "expandAll"
|
|
@@ -304,10 +323,12 @@ var useTree = function useTree(_ref) {
|
|
|
304
323
|
return {
|
|
305
324
|
tree: state.tree,
|
|
306
325
|
query: state.query,
|
|
326
|
+
selected: state.selected,
|
|
307
327
|
toggleExpand: toggleExpand,
|
|
308
328
|
expandAll: expandAll,
|
|
309
329
|
collapseAll: collapseAll,
|
|
310
330
|
toggleCheck: toggleCheck,
|
|
331
|
+
expandAndLoad: expandAndLoad,
|
|
311
332
|
select: select,
|
|
312
333
|
expand: expand,
|
|
313
334
|
onFilter: onFilter
|
package/dist/esm/tree/utils.js
CHANGED
|
@@ -96,7 +96,7 @@ var flattenTree = function flattenTree(nodes) {
|
|
|
96
96
|
return list;
|
|
97
97
|
};
|
|
98
98
|
var updateSelection = function updateSelection(nodes, id, selected) {
|
|
99
|
-
var node = nodes.get(id);
|
|
99
|
+
var node = nodes.get(id !== null && id !== void 0 ? id : "");
|
|
100
100
|
if (node) {
|
|
101
101
|
// change selection
|
|
102
102
|
node.selected = selected;
|
|
@@ -108,6 +108,7 @@ var updateSelection = function updateSelection(nodes, id, selected) {
|
|
|
108
108
|
// selected && parentNode && (parentNode.open = true);
|
|
109
109
|
parent = parentNode === null || parentNode === void 0 ? void 0 : parentNode.parent;
|
|
110
110
|
}
|
|
111
|
+
return id;
|
|
111
112
|
}
|
|
112
113
|
};
|
|
113
114
|
var updateChecked = function updateChecked(list, id, checked) {
|
|
@@ -77,6 +77,7 @@ export interface TreeNodeProps extends ChildProp {
|
|
|
77
77
|
export interface TreeRef {
|
|
78
78
|
select: (id: string) => void;
|
|
79
79
|
open: (id: string) => void;
|
|
80
|
+
openAndLoad: (list: string[]) => void;
|
|
80
81
|
}
|
|
81
82
|
export interface TreePanelProps<T extends KeyValue = KeyValue> extends TestProps, RefProp<TreeRef> {
|
|
82
83
|
items?: Array<TreeNodeType<T>>;
|
|
@@ -2,10 +2,12 @@ import { type InternalNode, type TreePanelProps } from "./types";
|
|
|
2
2
|
export declare const useTree: <T extends KeyValue>({ items, checked, selected, sorter, matcher, onLoad, onQuery, onSelect, onChecked, defaultExpanded, onExpandToggle, }: Partial<TreePanelProps<T>>) => {
|
|
3
3
|
tree: InternalNode[];
|
|
4
4
|
query: string | undefined;
|
|
5
|
+
selected: string | undefined;
|
|
5
6
|
toggleExpand: (id: string) => void;
|
|
6
7
|
expandAll: () => void;
|
|
7
8
|
collapseAll: () => void;
|
|
8
9
|
toggleCheck: (id: string) => void;
|
|
10
|
+
expandAndLoad: (expandList: string[]) => void;
|
|
9
11
|
select: (id: string) => void;
|
|
10
12
|
expand: (id: string) => void;
|
|
11
13
|
onFilter: {
|
|
@@ -8,6 +8,6 @@ export declare const refactorTree: (nodes: TreeNodeType[], { sorter, defaultExpa
|
|
|
8
8
|
}) => InternalNode[];
|
|
9
9
|
export declare const makeTreeMap: (nodes: InternalNode[], map?: Map<any, any>) => Map<any, any>;
|
|
10
10
|
export declare const flattenTree: (nodes: InternalNode[], lines?: Array<0 | 1 | 2 | 3>) => InternalNode[];
|
|
11
|
-
export declare const updateSelection: (nodes: Map<string, InternalNode>, id
|
|
11
|
+
export declare const updateSelection: (nodes: Map<string, InternalNode>, id?: string, selected?: true) => string | undefined;
|
|
12
12
|
export declare const updateChecked: (list: Map<string, AnyObject>, id: string, checked?: 0 | 1 | 2) => void;
|
|
13
13
|
export declare const filterTree: (nodes: Map<string, InternalNode>, query?: string, matcher?: AnyObject) => void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-fabric/data",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.56",
|
|
4
4
|
"description": "RUF: Data package",
|
|
5
5
|
"author": "Adarsh Pastakia <adarshpastakia@outlook.com>",
|
|
6
6
|
"license": "MIT",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@react-fabric/core": "^1.0.0-beta.55",
|
|
39
39
|
"@react-fabric/date": "^1.0.0-beta.55",
|
|
40
|
-
"@react-fabric/form": "^1.0.0-beta.
|
|
40
|
+
"@react-fabric/form": "^1.0.0-beta.56",
|
|
41
41
|
"@react-fabric/utilities": "^1.0.0-beta.52",
|
|
42
42
|
"@tanstack/react-virtual": "^3.13.9",
|
|
43
43
|
"classnames": "^2.5.1",
|
|
@@ -54,5 +54,5 @@
|
|
|
54
54
|
"node": ">=18.12.0",
|
|
55
55
|
"npm": ">=8.19.0"
|
|
56
56
|
},
|
|
57
|
-
"gitHead": "
|
|
57
|
+
"gitHead": "fd9dd6cfd1a58efb5c4bfb6446928a78cb4f4266"
|
|
58
58
|
}
|
package/src/tree/TreeNode.tsx
CHANGED
package/src/tree/TreePanel.tsx
CHANGED
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
} from "@react-fabric/core";
|
|
32
32
|
import { Search } from "@react-fabric/form";
|
|
33
33
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
34
|
-
import { useImperativeHandle, useMemo, useRef } from "react";
|
|
34
|
+
import { useEffect, useImperativeHandle, useMemo, useRef } from "react";
|
|
35
35
|
import { TreeNode } from "./TreeNode";
|
|
36
36
|
import { iconCollapseAll, iconExpandAll, type TreePanelProps } from "./types";
|
|
37
37
|
import { useTree } from "./useTree";
|
|
@@ -110,10 +110,12 @@ export const TreePanel = <T extends KeyValue>({
|
|
|
110
110
|
const {
|
|
111
111
|
tree,
|
|
112
112
|
query,
|
|
113
|
+
selected: currentSelected,
|
|
113
114
|
toggleExpand,
|
|
114
115
|
toggleCheck,
|
|
115
116
|
expandAll,
|
|
116
117
|
collapseAll,
|
|
118
|
+
expandAndLoad,
|
|
117
119
|
select,
|
|
118
120
|
expand,
|
|
119
121
|
onFilter,
|
|
@@ -154,11 +156,17 @@ export const TreePanel = <T extends KeyValue>({
|
|
|
154
156
|
ref,
|
|
155
157
|
() => ({
|
|
156
158
|
open: (id: string) => expand(id),
|
|
159
|
+
openAndLoad: (list: string[]) => expandAndLoad(list),
|
|
157
160
|
select: (id: string) => select(id),
|
|
158
161
|
}),
|
|
159
162
|
[],
|
|
160
163
|
);
|
|
161
164
|
|
|
165
|
+
useEffect(() => {
|
|
166
|
+
const index = tree.findIndex((n) => n.id === currentSelected);
|
|
167
|
+
virtualizer.scrollToIndex(index, { align: "auto" });
|
|
168
|
+
}, [currentSelected]);
|
|
169
|
+
|
|
162
170
|
return (
|
|
163
171
|
<Section>
|
|
164
172
|
<Header
|
package/src/tree/types.ts
CHANGED
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { AvatarProps } from "@react-fabric/core/dist/types/components/avatar/Avatar";
|
|
25
24
|
import {
|
|
26
25
|
type BadgeType,
|
|
27
26
|
type ChildProp,
|
|
@@ -31,7 +30,6 @@ import {
|
|
|
31
30
|
type RefProp,
|
|
32
31
|
type TestProps,
|
|
33
32
|
} from "@react-fabric/core/dist/types/types";
|
|
34
|
-
import { type ElementType } from "react";
|
|
35
33
|
|
|
36
34
|
interface TreeBaseNode<T> extends Omit<IconProps, "icon">, CssProp, TestProps {
|
|
37
35
|
id: string;
|
|
@@ -120,6 +118,7 @@ export interface TreeNodeProps extends ChildProp {
|
|
|
120
118
|
export interface TreeRef {
|
|
121
119
|
select: (id: string) => void;
|
|
122
120
|
open: (id: string) => void;
|
|
121
|
+
openAndLoad: (list: string[]) => void;
|
|
123
122
|
}
|
|
124
123
|
|
|
125
124
|
export interface TreePanelProps<T extends KeyValue = KeyValue>
|
package/src/tree/useTree.ts
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
24
|
import { useDebounce } from "@react-fabric/core";
|
|
25
|
-
import { EMPTY_ARRAY } from "@react-fabric/utilities";
|
|
25
|
+
import { EMPTY_ARRAY, isEmpty } from "@react-fabric/utilities";
|
|
26
26
|
import memoizeOne from "memoize-one";
|
|
27
27
|
import { useCallback, useEffect, useReducer, useRef } from "react";
|
|
28
28
|
import {
|
|
@@ -110,7 +110,7 @@ export const useTree = <T extends KeyValue>({
|
|
|
110
110
|
onExpandToggle,
|
|
111
111
|
}: Partial<TreePanelProps<T>>) => {
|
|
112
112
|
const componentEvents = useRef({ onSelect, onChecked });
|
|
113
|
-
const intialExpand = useRef(defaultExpanded ?? EMPTY_ARRAY);
|
|
113
|
+
const intialExpand = useRef([...(defaultExpanded ?? EMPTY_ARRAY)]);
|
|
114
114
|
const itemList = createItemList(items);
|
|
115
115
|
|
|
116
116
|
const fireExpandToggle = useCallback(
|
|
@@ -127,23 +127,26 @@ export const useTree = <T extends KeyValue>({
|
|
|
127
127
|
(node: InternalNode) => {
|
|
128
128
|
if (node.open && !node.leaf && !node.children?.length) {
|
|
129
129
|
node.loading = true;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
dispatch({
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
130
|
+
// delay onload callback to avoid state issues
|
|
131
|
+
setTimeout(() => {
|
|
132
|
+
void Promise.resolve(onLoad?.(node.id))
|
|
133
|
+
.then((resp = EMPTY_ARRAY) => {
|
|
134
|
+
node.children = refactorTree(
|
|
135
|
+
resp,
|
|
136
|
+
{ sorter, defaultExpanded },
|
|
137
|
+
{ level: node.level + 1, parent: node.id },
|
|
138
|
+
);
|
|
139
|
+
})
|
|
140
|
+
.finally(() => {
|
|
141
|
+
node.loading = false;
|
|
142
|
+
dispatch({ type: "loaded" });
|
|
143
|
+
intialExpand.current?.length > 0 &&
|
|
144
|
+
dispatch({
|
|
145
|
+
type: "expand",
|
|
146
|
+
id: intialExpand.current.shift() as unknown as string,
|
|
147
|
+
});
|
|
148
|
+
});
|
|
149
|
+
}, 100);
|
|
147
150
|
} else {
|
|
148
151
|
dispatch({ type: "loaded" });
|
|
149
152
|
intialExpand.current?.length > 0 &&
|
|
@@ -170,6 +173,13 @@ export const useTree = <T extends KeyValue>({
|
|
|
170
173
|
[onChecked],
|
|
171
174
|
);
|
|
172
175
|
|
|
176
|
+
const fireQuery = useDebounce(
|
|
177
|
+
(query: string) => {
|
|
178
|
+
onQuery?.(query);
|
|
179
|
+
},
|
|
180
|
+
[onQuery],
|
|
181
|
+
);
|
|
182
|
+
|
|
173
183
|
const [state, dispatch] = useReducer(
|
|
174
184
|
(state: TreeState, action: TreeActions) => {
|
|
175
185
|
if (action.type === "load") {
|
|
@@ -193,7 +203,7 @@ export const useTree = <T extends KeyValue>({
|
|
|
193
203
|
state.itemMap = makeTreeMap(state.items);
|
|
194
204
|
fireExpandToggle(Array.from(state.itemMap.values()));
|
|
195
205
|
state.tree = flattenTree(state.items);
|
|
196
|
-
state.selected
|
|
206
|
+
state.selected = updateSelection(state.itemMap, selected, true);
|
|
197
207
|
state.checked?.forEach((id) => updateChecked(state.itemMap, id, 1));
|
|
198
208
|
return { ...state };
|
|
199
209
|
}
|
|
@@ -229,7 +239,16 @@ export const useTree = <T extends KeyValue>({
|
|
|
229
239
|
}
|
|
230
240
|
if (action.type === "filter") {
|
|
231
241
|
if (onQuery) {
|
|
232
|
-
onQuery
|
|
242
|
+
// TODO: onQuery should provide new tree listing
|
|
243
|
+
// save current tree state as preQueryState
|
|
244
|
+
// on clearing filter restore preQueryState
|
|
245
|
+
if (!isEmpty(action.query)) {
|
|
246
|
+
// state.prevItems = state.items;
|
|
247
|
+
fireQuery(action.query);
|
|
248
|
+
} else {
|
|
249
|
+
// state.items = state.prevItems;
|
|
250
|
+
// build tree map
|
|
251
|
+
}
|
|
233
252
|
} else {
|
|
234
253
|
filterTree(state.itemMap, action.query, matcher);
|
|
235
254
|
state.tree = flattenTree(state.items);
|
|
@@ -237,12 +256,11 @@ export const useTree = <T extends KeyValue>({
|
|
|
237
256
|
return { ...state, query: action.query };
|
|
238
257
|
}
|
|
239
258
|
if (action.type === "toggleSelect") {
|
|
240
|
-
if (state.selected) {
|
|
241
|
-
updateSelection(state.itemMap, state.selected);
|
|
242
|
-
}
|
|
243
259
|
if (!onSelect) {
|
|
244
|
-
|
|
245
|
-
|
|
260
|
+
if (state.selected) {
|
|
261
|
+
updateSelection(state.itemMap, state.selected);
|
|
262
|
+
}
|
|
263
|
+
state.selected = updateSelection(state.itemMap, action.id, true);
|
|
246
264
|
state.tree = flattenTree(state.items);
|
|
247
265
|
} else {
|
|
248
266
|
fireSelected(action.id, state.itemMap.get(action.id)?.data);
|
|
@@ -253,8 +271,7 @@ export const useTree = <T extends KeyValue>({
|
|
|
253
271
|
if (state.selected) {
|
|
254
272
|
updateSelection(state.itemMap, state.selected);
|
|
255
273
|
}
|
|
256
|
-
updateSelection(state.itemMap, action.id, true);
|
|
257
|
-
state.selected = action.id;
|
|
274
|
+
state.selected = updateSelection(state.itemMap, action.id, true);
|
|
258
275
|
state.tree = flattenTree(state.items);
|
|
259
276
|
return { ...state };
|
|
260
277
|
}
|
|
@@ -329,6 +346,13 @@ export const useTree = <T extends KeyValue>({
|
|
|
329
346
|
dispatch({ type: "expand", id });
|
|
330
347
|
}, []);
|
|
331
348
|
|
|
349
|
+
const expandAndLoad = useCallback((expandList: string[]) => {
|
|
350
|
+
if (expandList.length > 0) {
|
|
351
|
+
intialExpand.current = [...expandList];
|
|
352
|
+
dispatch({ type: "expand", id: intialExpand.current.shift() as string });
|
|
353
|
+
}
|
|
354
|
+
}, []);
|
|
355
|
+
|
|
332
356
|
const expandAll = useCallback(() => {
|
|
333
357
|
dispatch({ type: "expandAll" });
|
|
334
358
|
}, []);
|
|
@@ -348,10 +372,12 @@ export const useTree = <T extends KeyValue>({
|
|
|
348
372
|
return {
|
|
349
373
|
tree: state.tree,
|
|
350
374
|
query: state.query,
|
|
375
|
+
selected: state.selected,
|
|
351
376
|
toggleExpand,
|
|
352
377
|
expandAll,
|
|
353
378
|
collapseAll,
|
|
354
379
|
toggleCheck,
|
|
380
|
+
expandAndLoad,
|
|
355
381
|
select,
|
|
356
382
|
expand,
|
|
357
383
|
onFilter,
|
package/src/tree/utils.ts
CHANGED
|
@@ -127,10 +127,10 @@ export const flattenTree = (
|
|
|
127
127
|
|
|
128
128
|
export const updateSelection = (
|
|
129
129
|
nodes: Map<string, InternalNode>,
|
|
130
|
-
id
|
|
130
|
+
id?: string,
|
|
131
131
|
selected?: true,
|
|
132
132
|
) => {
|
|
133
|
-
const node = nodes.get(id);
|
|
133
|
+
const node = nodes.get(id ?? "");
|
|
134
134
|
if (node) {
|
|
135
135
|
// change selection
|
|
136
136
|
node.selected = selected;
|
|
@@ -142,6 +142,7 @@ export const updateSelection = (
|
|
|
142
142
|
// selected && parentNode && (parentNode.open = true);
|
|
143
143
|
parent = parentNode?.parent;
|
|
144
144
|
}
|
|
145
|
+
return id;
|
|
145
146
|
}
|
|
146
147
|
};
|
|
147
148
|
|