@react-fabric/data 1.0.0-beta.6 → 1.0.0-beta.60

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.
Files changed (103) hide show
  1. package/{src/histogram/Histogram.module.css → css/_histogram.css} +16 -13
  2. package/css/styles.css +24 -0
  3. package/dist/cjs/checklist/CheckList.js +23 -0
  4. package/dist/cjs/histogram/Histogram.js +37 -7
  5. package/dist/cjs/hooks/useFilteredList.js +88 -10
  6. package/dist/cjs/hooks/usePagination.js +27 -4
  7. package/dist/cjs/hooks/useSelectableList.js +29 -0
  8. package/dist/cjs/i18n/ar.json.js +8 -1
  9. package/dist/cjs/i18n/en.json.js +8 -1
  10. package/dist/cjs/json/JsonViewer.js +67 -27
  11. package/dist/cjs/pagination/Pagination.js +10 -0
  12. package/dist/cjs/table/AddColumn.js +1 -1
  13. package/dist/cjs/table/BodyCell.js +5 -4
  14. package/dist/cjs/table/BodyRow.js +2 -2
  15. package/dist/cjs/table/CheckboxCell.js +1 -1
  16. package/dist/cjs/table/ColumnFilters.js +97 -0
  17. package/dist/cjs/table/HeaderCell.js +71 -43
  18. package/dist/cjs/table/Table.js +58 -12
  19. package/dist/cjs/table/types.js +29 -0
  20. package/dist/cjs/table/useResizer.js +4 -4
  21. package/dist/cjs/table/useVirtualTable.js +127 -19
  22. package/dist/cjs/tree/TreeNode.js +48 -30
  23. package/dist/cjs/tree/TreePanel.js +45 -11
  24. package/dist/cjs/tree/useTree.js +199 -38
  25. package/dist/cjs/tree/utils.js +39 -12
  26. package/dist/cjs/virtual/Gallery.js +97 -45
  27. package/dist/cjs/virtual/List.js +93 -39
  28. package/dist/cjs/virtual/Scroller.js +16 -8
  29. package/dist/esm/checklist/CheckList.js +23 -0
  30. package/dist/esm/histogram/Histogram.js +38 -8
  31. package/dist/esm/hooks/useFilteredList.js +89 -11
  32. package/dist/esm/hooks/usePagination.js +27 -4
  33. package/dist/esm/hooks/useSelectableList.js +29 -0
  34. package/dist/esm/i18n/ar.json.js +8 -2
  35. package/dist/esm/i18n/en.json.js +8 -2
  36. package/dist/esm/json/JsonViewer.js +68 -28
  37. package/dist/esm/pagination/Pagination.js +10 -0
  38. package/dist/esm/table/AddColumn.js +1 -1
  39. package/dist/esm/table/BodyCell.js +5 -4
  40. package/dist/esm/table/BodyRow.js +2 -2
  41. package/dist/esm/table/CheckboxCell.js +1 -1
  42. package/dist/esm/table/ColumnFilters.js +97 -0
  43. package/dist/esm/table/HeaderCell.js +72 -44
  44. package/dist/esm/table/Table.js +59 -13
  45. package/dist/esm/table/types.js +29 -0
  46. package/dist/esm/table/useResizer.js +4 -4
  47. package/dist/esm/table/useVirtualTable.js +129 -21
  48. package/dist/esm/tree/TreeNode.js +51 -33
  49. package/dist/esm/tree/TreePanel.js +46 -12
  50. package/dist/esm/tree/useTree.js +202 -41
  51. package/dist/esm/tree/utils.js +40 -13
  52. package/dist/esm/virtual/Gallery.js +97 -45
  53. package/dist/esm/virtual/List.js +93 -39
  54. package/dist/esm/virtual/Scroller.js +16 -8
  55. package/dist/types/checklist/CheckList.d.ts +22 -0
  56. package/dist/types/histogram/Histogram.d.ts +28 -1
  57. package/dist/types/hooks/useFilteredList.d.ts +66 -5
  58. package/dist/types/hooks/usePagination.d.ts +19 -0
  59. package/dist/types/hooks/useSelectableList.d.ts +29 -0
  60. package/dist/types/json/JsonViewer.d.ts +27 -2
  61. package/dist/types/pagination/Pagination.d.ts +10 -1
  62. package/dist/types/table/ColumnFilters.d.ts +9 -0
  63. package/dist/types/table/HeaderCell.d.ts +1 -1
  64. package/dist/types/table/Table.d.ts +14 -1
  65. package/dist/types/table/types.d.ts +44 -5
  66. package/dist/types/table/useVirtualTable.d.ts +23 -9
  67. package/dist/types/tree/TreeNode.d.ts +1 -1
  68. package/dist/types/tree/TreePanel.d.ts +42 -1
  69. package/dist/types/tree/types.d.ts +65 -19
  70. package/dist/types/tree/useTree.d.ts +9 -10
  71. package/dist/types/tree/utils.d.ts +10 -3
  72. package/dist/types/virtual/Gallery.d.ts +42 -3
  73. package/dist/types/virtual/List.d.ts +42 -3
  74. package/package.json +16 -14
  75. package/src/checklist/CheckList.tsx +22 -0
  76. package/src/histogram/Histogram.tsx +40 -10
  77. package/src/hooks/useFilteredList.tsx +109 -9
  78. package/src/hooks/usePagination.tsx +32 -7
  79. package/src/hooks/useSelectableList.ts +29 -0
  80. package/src/i18n/ar.json +5 -0
  81. package/src/i18n/en.json +5 -0
  82. package/src/json/JsonViewer.tsx +71 -35
  83. package/src/pagination/Pagination.tsx +10 -0
  84. package/src/table/AddColumn.tsx +1 -1
  85. package/src/table/BodyCell.tsx +6 -4
  86. package/src/table/BodyRow.tsx +3 -2
  87. package/src/table/CheckboxCell.tsx +1 -1
  88. package/src/table/ColumnFilters.tsx +105 -0
  89. package/src/table/HeaderCell.tsx +72 -18
  90. package/src/table/Table.tsx +99 -11
  91. package/src/table/types.ts +46 -8
  92. package/src/table/useResizer.ts +5 -3
  93. package/src/table/useVirtualTable.ts +158 -27
  94. package/src/tree/TreeNode.tsx +98 -58
  95. package/src/tree/TreePanel.tsx +77 -6
  96. package/src/tree/types.ts +73 -18
  97. package/src/tree/useTree.ts +220 -44
  98. package/src/tree/utils.ts +58 -20
  99. package/src/virtual/Gallery.tsx +118 -54
  100. package/src/virtual/List.tsx +99 -39
  101. package/src/virtual/Scroller.tsx +16 -8
  102. package/dist/cjs/histogram/Histogram.module.css +0 -1
  103. package/dist/esm/histogram/Histogram.module.css +0 -1
@@ -22,10 +22,20 @@
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
- import { useCallback, useEffect, useReducer, useRef } from "react";
28
- import { type InternalNode, type TreeNodeType } from "./types";
27
+ import {
28
+ useCallback,
29
+ useEffect,
30
+ useReducer,
31
+ useRef,
32
+ useEffectEvent,
33
+ } from "react";
34
+ import {
35
+ type InternalNode,
36
+ type TreeNodeType,
37
+ type TreePanelProps,
38
+ } from "./types";
29
39
  import {
30
40
  filterTree,
31
41
  flattenTree,
@@ -52,6 +62,10 @@ type TreeActions =
52
62
  * update item check state
53
63
  */
54
64
  | { type: "checked"; id: string[] }
65
+ /**
66
+ * toggle item select, used as action handler
67
+ */
68
+ | { type: "toggleSelect"; id: string; shiftKey?: boolean }
55
69
  /**
56
70
  * toggle item check, used as action handler
57
71
  */
@@ -71,13 +85,18 @@ type TreeActions =
71
85
  /**
72
86
  * collapse all nodes
73
87
  */
74
- | { type: "collapseAll" };
88
+ | { type: "collapseAll" }
89
+ /**
90
+ * loaded dynamic nodes
91
+ */
92
+ | { type: "loaded" };
75
93
 
76
94
  interface TreeState {
77
95
  items: InternalNode[];
78
96
  itemMap: Map<string, InternalNode>;
79
97
  tree: InternalNode[];
80
- selected?: string;
98
+ query?: string;
99
+ selected?: AnyObject;
81
100
  checked?: string[];
82
101
  }
83
102
 
@@ -87,47 +106,139 @@ export const useTree = <T extends KeyValue>({
87
106
  items = EMPTY_ARRAY,
88
107
  checked = EMPTY_ARRAY,
89
108
  selected,
109
+ multiple,
110
+ sorter,
90
111
  matcher,
112
+ onLoad,
113
+ onQuery,
91
114
  onSelect,
92
115
  onChecked,
93
- }: {
94
- items?: Array<TreeNodeType<T>>;
95
- selected?: string;
96
- checked?: string[];
97
- onSelect?: (id: string) => void;
98
- onChecked?: (leafs: string[], nodes: string[]) => void;
99
- matcher?: (data: T, query: string) => boolean;
116
+ defaultExpanded,
117
+ onExpandToggle,
118
+ }: Partial<TreePanelProps<T>> & {
119
+ selected?: AnyObject;
120
+ multiple?: boolean;
100
121
  }) => {
101
- const componentEvents = useRef({ onSelect, onChecked });
102
-
122
+ const eventSelect = useEffectEvent(onSelect ?? (() => undefined));
123
+ const eventChecked = useEffectEvent(onChecked ?? (() => undefined));
124
+ const intialExpand = useRef([...(defaultExpanded ?? EMPTY_ARRAY)]);
103
125
  const itemList = createItemList(items);
104
126
 
127
+ const fireExpandToggle = useCallback(
128
+ (itemMap: InternalNode[]) => {
129
+ const expandedList = itemMap
130
+ .filter((node) => node.open)
131
+ .map((node) => node.id);
132
+ setTimeout(() => onExpandToggle?.(expandedList), 100);
133
+ },
134
+ [onExpandToggle],
135
+ );
136
+
137
+ const loadChildren = useCallback(
138
+ (node: InternalNode) => {
139
+ if (node.open && !node.leaf && !node.children?.length) {
140
+ node.loading = true;
141
+ // delay onload callback to avoid state issues
142
+ setTimeout(() => {
143
+ void Promise.resolve(onLoad?.(node.id))
144
+ .then((resp = EMPTY_ARRAY) => {
145
+ node.children = refactorTree(
146
+ resp,
147
+ { sorter, defaultExpanded },
148
+ { level: node.level + 1, parent: node.id },
149
+ );
150
+ })
151
+ .finally(() => {
152
+ node.loading = false;
153
+ dispatch({ type: "loaded" });
154
+ intialExpand.current?.length > 0 &&
155
+ dispatch({
156
+ type: "expand",
157
+ id: intialExpand.current.shift() as unknown as string,
158
+ });
159
+ });
160
+ }, 100);
161
+ } else {
162
+ dispatch({ type: "loaded" });
163
+ intialExpand.current?.length > 0 &&
164
+ dispatch({
165
+ type: "expand",
166
+ id: intialExpand.current.shift() as unknown as string,
167
+ });
168
+ }
169
+ },
170
+ [onLoad],
171
+ );
172
+
173
+ const fireSelected = useDebounce((nodeId: any, data: T) => {
174
+ eventSelect(nodeId, data);
175
+ }, []);
176
+
177
+ const fireChecked = useDebounce(
178
+ (leafs: string[], nodes: string[], partials: string[]) => {
179
+ eventChecked(leafs, nodes, partials);
180
+ },
181
+ [],
182
+ );
183
+
184
+ const fireQuery = useDebounce(
185
+ (query: string) => {
186
+ onQuery?.(query);
187
+ },
188
+ [onQuery],
189
+ );
190
+
105
191
  const [state, dispatch] = useReducer(
106
192
  (state: TreeState, action: TreeActions) => {
107
193
  if (action.type === "load") {
108
- state.items = refactorTree(action.items);
194
+ state.items = refactorTree(action.items, { sorter, defaultExpanded });
109
195
  state.itemMap = makeTreeMap(state.items);
110
196
  state.tree = flattenTree(state.items);
197
+ state.selected = undefined;
198
+ state.checked = undefined;
199
+ state.query = "";
111
200
  return { ...state };
112
201
  }
113
202
  if (action.type === "toggleExpand") {
114
203
  const node = state.itemMap.get(action.id);
115
- node && (node.open = !node.open);
204
+ if (node && !node.leaf) {
205
+ node && (node.open = !node.open);
206
+ loadChildren(node);
207
+ return { ...state };
208
+ }
209
+ }
210
+ if (action.type === "loaded") {
211
+ state.itemMap = makeTreeMap(state.items);
212
+ fireExpandToggle(Array.from(state.itemMap.values()));
116
213
  state.tree = flattenTree(state.items);
214
+ state.selected = selected;
215
+ updateSelection({
216
+ nodes: state.itemMap,
217
+ multiple,
218
+ selected,
219
+ });
220
+ state.checked?.forEach((id) => updateChecked(state.itemMap, id, 1));
117
221
  return { ...state };
118
222
  }
119
223
  if (action.type === "expand") {
120
- // TODO: check if children available, if not call onLoad to fetch node children
121
224
  const node = state.itemMap.get(action.id);
122
- node && (node.open = true);
123
- state.tree = flattenTree(state.items);
124
- return { ...state };
225
+ if (node && !node.leaf) {
226
+ node.open = true;
227
+ let parentId = node.parent;
228
+ while (parentId) {
229
+ const node = state.itemMap.get(parentId);
230
+ node && (node.open = true);
231
+ parentId = node?.parent;
232
+ }
233
+ loadChildren(node);
234
+ return { ...state };
235
+ }
125
236
  }
126
237
  if (action.type === "expandAll") {
127
- // TODO: prevent opening dynamic nodes that dont have children
128
238
  state.itemMap.forEach((node) => {
129
- !node.leaf && (node.open = true);
239
+ !node.leaf && node.children?.length && (node.open = true);
130
240
  });
241
+ fireExpandToggle(Array.from(state.itemMap.values()));
131
242
  state.tree = flattenTree(state.items);
132
243
  return { ...state };
133
244
  }
@@ -135,34 +246,77 @@ export const useTree = <T extends KeyValue>({
135
246
  state.itemMap.forEach((node) => {
136
247
  !node.leaf && (node.open = false);
137
248
  });
249
+ fireExpandToggle([]);
138
250
  state.tree = flattenTree(state.items);
139
251
  return { ...state };
140
252
  }
141
253
  if (action.type === "filter") {
142
- filterTree(state.itemMap, action.query, matcher);
254
+ if (onQuery) {
255
+ // TODO: onQuery should provide new tree listing
256
+ // save current tree state as preQueryState
257
+ // on clearing filter restore preQueryState
258
+ if (!isEmpty(action.query)) {
259
+ // state.prevItems = state.items;
260
+ fireQuery(action.query);
261
+ } else {
262
+ // state.items = state.prevItems;
263
+ // build tree map
264
+ }
265
+ } else {
266
+ filterTree(state.itemMap, action.query, matcher);
267
+ state.tree = flattenTree(state.items);
268
+ }
269
+ return { ...state, query: action.query };
270
+ }
271
+ if (action.type === "toggleSelect") {
272
+ if (multiple) {
273
+ const isSelected = state.selected?.includes(action.id);
274
+ if (action.shiftKey && isSelected)
275
+ state.selected =
276
+ state.selected?.filter((id: string) => id !== action.id) ?? [];
277
+ else if (action.shiftKey && !isSelected)
278
+ state.selected = [...(state.selected ?? []), action.id];
279
+ else state.selected = [action.id];
280
+ } else {
281
+ state.selected = action.id;
282
+ }
283
+ updateSelection({
284
+ nodes: state.itemMap,
285
+ selected: state.selected,
286
+ multiple,
287
+ });
143
288
  state.tree = flattenTree(state.items);
289
+ fireSelected(state.selected, state.itemMap.get(action.id)?.data);
144
290
  return { ...state };
145
291
  }
146
292
  if (action.type === "select") {
147
- if (state.selected) {
148
- updateSelection(state.itemMap, state.selected);
149
- }
150
- updateSelection(state.itemMap, action.id, true);
293
+ state.selected = action.id;
294
+ updateSelection({
295
+ nodes: state.itemMap,
296
+ multiple,
297
+ selected: action.id,
298
+ });
151
299
  state.tree = flattenTree(state.items);
152
- componentEvents.current.onSelect?.(action.id);
153
- return { ...state, selected: action.id };
300
+ return { ...state };
154
301
  }
155
302
  if (action.type === "toggleCheck") {
156
303
  updateChecked(state.itemMap, action.id);
157
- const checkList: string[][] = [[], []];
304
+ const checkList: string[][] = [[], [], []];
158
305
  Array.from(state.itemMap.values())
159
- .filter((node) => node.checked === 1)
160
- .forEach((node) => checkList[node.leaf ? 0 : 1].push(node.id));
161
- componentEvents.current.onChecked?.(checkList[0], checkList[1]);
162
- return { ...state };
306
+ .filter((node) => node.checked !== 0)
307
+ .forEach((node) =>
308
+ checkList[node.leaf ? 0 : node.checked].push(node.id),
309
+ );
310
+ fireChecked(
311
+ checkList[0], // leafs
312
+ checkList[1], // nodes
313
+ checkList[2], // partials
314
+ );
315
+ return { ...state, checked: checkList[0] };
163
316
  }
164
317
  if (action.type === "checked") {
165
- action.id.forEach((id) => updateChecked(state.itemMap, id));
318
+ state.itemMap.forEach((item) => (item.checked = 0));
319
+ action.id.forEach((id) => updateChecked(state.itemMap, id, 1));
166
320
  return { ...state, checked: action.id };
167
321
  }
168
322
  return state;
@@ -172,15 +326,20 @@ export const useTree = <T extends KeyValue>({
172
326
  items: [],
173
327
  tree: [],
174
328
  checked: [],
329
+ query: "",
175
330
  },
176
331
  );
177
332
 
178
- useEffect(() => {
179
- componentEvents.current = { onSelect, onChecked };
180
- }, [onSelect, onChecked]);
181
-
182
333
  useEffect(() => {
183
334
  dispatch({ type: "load", items: itemList });
335
+ itemList.length &&
336
+ intialExpand.current?.length > 0 &&
337
+ dispatch({
338
+ type: "expand",
339
+ id: intialExpand.current.shift() as unknown as string,
340
+ });
341
+ selected && dispatch({ type: "select", id: selected });
342
+ checked && dispatch({ type: "checked", id: checked });
184
343
  }, [itemList]);
185
344
 
186
345
  useEffect(() => {
@@ -199,14 +358,24 @@ export const useTree = <T extends KeyValue>({
199
358
  dispatch({ type: "toggleCheck", id });
200
359
  }, []);
201
360
 
202
- const select = useCallback((id: string) => {
203
- dispatch({ type: "select", id });
361
+ const select = useCallback((id: string, shiftKey = false) => {
362
+ dispatch({ type: "toggleSelect", id, shiftKey });
204
363
  }, []);
205
364
 
206
365
  const expand = useCallback((id: string) => {
207
366
  dispatch({ type: "expand", id });
208
367
  }, []);
209
368
 
369
+ const expandAndLoad = useCallback((expandList: string[]) => {
370
+ if (expandList.length > 0) {
371
+ intialExpand.current = [...expandList];
372
+ dispatch({
373
+ type: "expand",
374
+ id: intialExpand.current.shift() as unknown as string,
375
+ });
376
+ }
377
+ }, []);
378
+
210
379
  const expandAll = useCallback(() => {
211
380
  dispatch({ type: "expandAll" });
212
381
  }, []);
@@ -215,16 +384,23 @@ export const useTree = <T extends KeyValue>({
215
384
  dispatch({ type: "collapseAll" });
216
385
  }, []);
217
386
 
218
- const onFilter = useDebounce((query: string) => {
219
- dispatch({ type: "filter", query });
220
- }, []);
387
+ const onFilter = useDebounce(
388
+ (query: string) => {
389
+ dispatch({ type: "filter", query });
390
+ },
391
+ [],
392
+ 300,
393
+ );
221
394
 
222
395
  return {
223
396
  tree: state.tree,
397
+ query: state.query,
398
+ selected: state.selected,
224
399
  toggleExpand,
225
400
  expandAll,
226
401
  collapseAll,
227
402
  toggleCheck,
403
+ expandAndLoad,
228
404
  select,
229
405
  expand,
230
406
  onFilter,
package/src/tree/utils.ts CHANGED
@@ -21,10 +21,15 @@
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 { compareValues, isString, matchString } from "@react-fabric/utilities";
24
+ import {
25
+ compareValues,
26
+ isArray,
27
+ isString,
28
+ matchString,
29
+ } from "@react-fabric/utilities";
25
30
  import { type InternalNode, type TreeNodeType } from "./types";
26
31
 
27
- const sorter = (a: TreeNodeType, b: TreeNodeType) => {
32
+ const defaultSorter = (a: TreeNodeType, b: TreeNodeType) => {
28
33
  if (!!a.leaf !== !!b.leaf) return a.leaf ? 1 : -1;
29
34
  return compareValues()(a.label, b.label);
30
35
  };
@@ -48,13 +53,17 @@ const getIntermediate = (list: AnyObject[] = []) => {
48
53
  // convert node item to internal node used by the tree
49
54
  export const refactorTree = (
50
55
  nodes: TreeNodeType[],
56
+ {
57
+ sorter = defaultSorter,
58
+ defaultExpanded = [],
59
+ }: { sorter?: any; defaultExpanded?: string[] },
51
60
  options: { level: number; parent?: string } = { level: 0, parent: undefined },
52
61
  ) => {
53
62
  const list: InternalNode[] = [];
54
-
55
- nodes.sort(sorter).forEach((node) => {
63
+ if (sorter !== false) nodes = nodes.sort(sorter);
64
+ nodes.forEach((node) => {
56
65
  list.push({
57
- open: false,
66
+ open: defaultExpanded.includes(node.id) && !!node.children?.length,
58
67
  level: options.level,
59
68
  parent: options.parent,
60
69
  checked: 0,
@@ -66,10 +75,14 @@ export const refactorTree = (
66
75
  leaf: !!node.leaf,
67
76
  children:
68
77
  node.children &&
69
- refactorTree(node.children, {
70
- level: options.level + 1,
71
- parent: node.id,
72
- }),
78
+ refactorTree(
79
+ node.children,
80
+ { sorter, defaultExpanded },
81
+ {
82
+ level: options.level + 1,
83
+ parent: node.id,
84
+ },
85
+ ),
73
86
  });
74
87
  });
75
88
 
@@ -106,34 +119,59 @@ export const flattenTree = (
106
119
  [...lines, idx === filtered.length - 1 ? 0 : 1],
107
120
  ),
108
121
  );
122
+ node.open &&
123
+ node.children?.length === 0 &&
124
+ list.push({
125
+ empty: true,
126
+ leaf: true,
127
+ lines: [...lines, idx === filtered.length - 1 ? 0 : 1, 2],
128
+ } as any);
109
129
  });
110
130
  return list;
111
131
  };
112
132
 
113
- export const updateSelection = (
114
- nodes: Map<string, InternalNode>,
115
- id: string,
116
- selected?: true,
117
- ) => {
118
- const node = nodes.get(id);
133
+ const selectNode = (nodes: Map<string, InternalNode>, id?: string) => {
134
+ const node = nodes.get(id ?? "");
119
135
  if (node) {
120
136
  // change selection
121
- node.selected = selected;
137
+ node.selected = true;
122
138
  // update all parent childSelected flag
123
139
  let parent = node.parent;
124
140
  while (parent) {
125
141
  const parentNode = nodes.get(parent);
126
- parentNode && (parentNode.childSelected = selected);
127
- selected && parentNode && (parentNode.open = true);
142
+ parentNode && (parentNode.childSelected = true);
143
+ // selected && parentNode && (parentNode.open = true);
128
144
  parent = parentNode?.parent;
129
145
  }
130
146
  }
131
147
  };
132
148
 
133
- export const updateChecked = (list: Map<string, AnyObject>, id: string) => {
149
+ export const updateSelection = ({
150
+ nodes,
151
+ multiple,
152
+ selected,
153
+ }: {
154
+ nodes: Map<string, InternalNode>;
155
+ multiple?: boolean;
156
+ selected?: string | string[];
157
+ }) => {
158
+ nodes.forEach((node) => {
159
+ node.selected = undefined;
160
+ node.childSelected = undefined;
161
+ });
162
+ multiple && isArray(selected)
163
+ ? selected?.forEach((id) => selectNode(nodes, id))
164
+ : selectNode(nodes, selected as string);
165
+ };
166
+
167
+ export const updateChecked = (
168
+ list: Map<string, AnyObject>,
169
+ id: string,
170
+ checked?: 0 | 1 | 2,
171
+ ) => {
134
172
  const node = list.get(id);
135
173
  if (node) {
136
- node.checked = node.checked === 1 ? 0 : 1;
174
+ node.checked = checked ?? node.checked === 0 ? 1 : 0;
137
175
  // check all children
138
176
  node.children &&
139
177
  getChildren(node.children).forEach(