react-native-tree-multi-select 0.5.3 → 0.8.3

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 (55) hide show
  1. package/README.md +5 -6
  2. package/lib/commonjs/TreeView.js +42 -48
  3. package/lib/commonjs/TreeView.js.map +1 -1
  4. package/lib/commonjs/components/NodeList.js +98 -92
  5. package/lib/commonjs/components/NodeList.js.map +1 -1
  6. package/lib/commonjs/helpers/expandCollapse.helper.js +21 -8
  7. package/lib/commonjs/helpers/expandCollapse.helper.js.map +1 -1
  8. package/lib/commonjs/helpers/initNodeMap.helper.js +14 -3
  9. package/lib/commonjs/helpers/initNodeMap.helper.js.map +1 -1
  10. package/lib/commonjs/helpers/selectAll.helper.js +32 -14
  11. package/lib/commonjs/helpers/selectAll.helper.js.map +1 -1
  12. package/lib/commonjs/helpers/toggleCheckbox.helper.js +34 -27
  13. package/lib/commonjs/helpers/toggleCheckbox.helper.js.map +1 -1
  14. package/lib/commonjs/store/global.store.js +92 -0
  15. package/lib/commonjs/store/global.store.js.map +1 -0
  16. package/lib/module/TreeView.js +42 -46
  17. package/lib/module/TreeView.js.map +1 -1
  18. package/lib/module/components/NodeList.js +96 -92
  19. package/lib/module/components/NodeList.js.map +1 -1
  20. package/lib/module/helpers/expandCollapse.helper.js +21 -8
  21. package/lib/module/helpers/expandCollapse.helper.js.map +1 -1
  22. package/lib/module/helpers/initNodeMap.helper.js +14 -3
  23. package/lib/module/helpers/initNodeMap.helper.js.map +1 -1
  24. package/lib/module/helpers/selectAll.helper.js +32 -14
  25. package/lib/module/helpers/selectAll.helper.js.map +1 -1
  26. package/lib/module/helpers/toggleCheckbox.helper.js +34 -27
  27. package/lib/module/helpers/toggleCheckbox.helper.js.map +1 -1
  28. package/lib/module/store/global.store.js +85 -0
  29. package/lib/module/store/global.store.js.map +1 -0
  30. package/lib/typescript/TreeView.d.ts.map +1 -1
  31. package/lib/typescript/components/NodeList.d.ts.map +1 -1
  32. package/lib/typescript/helpers/expandCollapse.helper.d.ts.map +1 -1
  33. package/lib/typescript/helpers/initNodeMap.helper.d.ts.map +1 -1
  34. package/lib/typescript/helpers/selectAll.helper.d.ts.map +1 -1
  35. package/lib/typescript/helpers/toggleCheckbox.helper.d.ts.map +1 -1
  36. package/lib/typescript/store/global.store.d.ts +24 -0
  37. package/lib/typescript/store/global.store.d.ts.map +1 -0
  38. package/lib/typescript/types/treeView.types.d.ts +0 -4
  39. package/lib/typescript/types/treeView.types.d.ts.map +1 -1
  40. package/package.json +23 -14
  41. package/src/TreeView.tsx +53 -62
  42. package/src/components/NodeList.tsx +102 -107
  43. package/src/helpers/expandCollapse.helper.ts +12 -12
  44. package/src/helpers/initNodeMap.helper.ts +15 -5
  45. package/src/helpers/selectAll.helper.ts +20 -13
  46. package/src/helpers/toggleCheckbox.helper.ts +36 -24
  47. package/src/store/global.store.ts +111 -0
  48. package/src/types/treeView.types.ts +0 -5
  49. package/lib/commonjs/signals/global.signals.js +0 -42
  50. package/lib/commonjs/signals/global.signals.js.map +0 -1
  51. package/lib/module/signals/global.signals.js +0 -26
  52. package/lib/module/signals/global.signals.js.map +0 -1
  53. package/lib/typescript/signals/global.signals.d.ts +0 -11
  54. package/lib/typescript/signals/global.signals.d.ts.map +0 -1
  55. package/src/signals/global.signals.ts +0 -36
@@ -1,4 +1,4 @@
1
- import React from "react";
1
+ import React, { useEffect, useState } from "react";
2
2
  import {
3
3
  View,
4
4
  StyleSheet,
@@ -6,13 +6,6 @@ import {
6
6
  TouchableOpacity,
7
7
  type TouchableOpacityProps,
8
8
  } from "react-native";
9
- import {
10
- computed,
11
- effect,
12
- Signal,
13
- useComputed,
14
- useSignal
15
- } from "@preact/signals-react";
16
9
  import { FlashList } from "@shopify/flash-list";
17
10
 
18
11
  import type {
@@ -26,14 +19,7 @@ import type {
26
19
  __FlattenedTreeNode__,
27
20
  } from "../types/treeView.types";
28
21
 
29
- import {
30
- expanded,
31
- globalData,
32
- innerMostChildrenIds,
33
- searchKeys,
34
- searchText,
35
- state
36
- } from "../signals/global.signals";
22
+ import { useStore } from "../store/global.store";
37
23
  import {
38
24
  doesNodeContainSearchTerm,
39
25
  handleToggleExpand,
@@ -64,74 +50,80 @@ function _NodeList(props: NodeListProps) {
64
50
  ExpandCollapseTouchableComponent,
65
51
  } = props;
66
52
 
67
- const filteredTree = React.useMemo(() => {
68
- return computed(() => {
69
- const searchTrimmed = searchText.value.trim().toLowerCase();
70
-
71
- const filterTreeData = (_nodes: TreeNode[]): TreeNode[] => {
72
- let filtered: TreeNode[] = [];
73
-
74
- for (let node of _nodes) {
75
- if (!searchTrimmed || doesNodeContainSearchTerm(node, searchTrimmed, searchKeys.value)) {
76
- // If node itself matches, include it and all its descendants
77
- filtered.push(node);
78
- } else if (node.children) {
79
- // If node does not match, check its children and include them if they match
80
- const childMatches = filterTreeData(node.children);
81
- if (childMatches.length > 0) {
82
- // If any children match, include the node, replacing its children with the matching ones
83
- filtered.push({ ...node, children: childMatches });
84
- }
53
+ const {
54
+ expanded,
55
+ globalData,
56
+ updatedInnerMostChildrenIds,
57
+ searchKeys,
58
+ searchText
59
+ } = useStore();
60
+
61
+ const [filteredTree, setFilteredTree] = useState<TreeNode[]>([]);
62
+ const [flattenedFilteredNodes, setFlattenedFilteredNodes]
63
+ = useState<__FlattenedTreeNode__[]>([]);
64
+
65
+ useEffect(() => {
66
+ const searchTrimmed = searchText.trim().toLowerCase();
67
+
68
+ const filterTreeData = (_nodes: TreeNode[]): TreeNode[] => {
69
+ let filtered: TreeNode[] = [];
70
+
71
+ for (let node of _nodes) {
72
+ if (!searchTrimmed || doesNodeContainSearchTerm(node, searchTrimmed, searchKeys)) {
73
+ // If node itself matches, include it and all its descendants
74
+ filtered.push(node);
75
+ } else if (node.children) {
76
+ // If node does not match, check its children and include them if they match
77
+ const childMatches = filterTreeData(node.children);
78
+ if (childMatches.length > 0) {
79
+ // If any children match, include the node, replacing its children with the matching ones
80
+ filtered.push({ ...node, children: childMatches });
85
81
  }
86
82
  }
83
+ }
87
84
 
88
- return filtered;
89
- };
90
-
91
- return filterTreeData(globalData.value);
92
- });
93
- }, []);
94
-
95
- const flattenedFilteredNodes = React.useMemo(() => {
96
- return computed(() => {
97
- const flattenTreeData = (
98
- _nodes: TreeNode[],
99
- level: number = 0,
100
- ): __FlattenedTreeNode__[] => {
101
- let flattened: __FlattenedTreeNode__[] = [];
102
- for (let node of _nodes) {
103
- flattened.push({ ...node, level });
104
- if (node.children && expanded.value.has(node.id)) {
105
- flattened = [...flattened, ...flattenTreeData(node.children, level + 1)];
106
- }
107
- }
108
- return flattened;
109
- };
85
+ return filtered;
86
+ };
110
87
 
111
- return flattenTreeData(filteredTree.value);
112
- });
113
- // eslint-disable-next-line react-hooks/exhaustive-deps
114
- }, []);
88
+ const tempFilterTree = filterTreeData(globalData);
89
+ setFilteredTree(tempFilterTree);
90
+ }, [searchText, searchKeys, globalData]);
115
91
 
116
92
  React.useEffect(() => {
117
- effect(() => {
118
- const allLeafIds: string[] = [];
119
- const getLeafNodes = (_nodes: TreeNode[]) => {
120
- for (let node of _nodes) {
121
- if (node.children) {
122
- getLeafNodes(node.children);
123
- } else {
124
- allLeafIds.push(node.id);
125
- }
93
+ const flattenTreeData = (
94
+ _nodes: TreeNode[],
95
+ level: number = 0,
96
+ ): __FlattenedTreeNode__[] => {
97
+ let flattened: __FlattenedTreeNode__[] = [];
98
+ for (let node of _nodes) {
99
+ flattened.push({ ...node, level });
100
+ if (node.children && expanded.has(node.id)) {
101
+ flattened = [...flattened, ...flattenTreeData(node.children, level + 1)];
126
102
  }
127
- };
103
+ }
104
+ return flattened;
105
+ };
106
+
107
+ const tempFlattenTreeData = flattenTreeData(filteredTree);
108
+ setFlattenedFilteredNodes(tempFlattenTreeData);
109
+ }, [filteredTree, expanded]);
110
+
111
+ useEffect(() => {
112
+ const allLeafIds: string[] = [];
113
+ const getLeafNodes = (_nodes: TreeNode[]) => {
114
+ for (let node of _nodes) {
115
+ if (node.children) {
116
+ getLeafNodes(node.children);
117
+ } else {
118
+ allLeafIds.push(node.id);
119
+ }
120
+ }
121
+ };
128
122
 
129
- getLeafNodes(filteredTree.value);
123
+ getLeafNodes(filteredTree);
130
124
 
131
- innerMostChildrenIds.value = allLeafIds;
132
- });
133
- // eslint-disable-next-line react-hooks/exhaustive-deps
134
- }, []);
125
+ updatedInnerMostChildrenIds(allLeafIds);
126
+ }, [filteredTree, updatedInnerMostChildrenIds]);
135
127
 
136
128
  const nodeRenderer = React.useCallback((
137
129
  { item }: { item: __FlattenedTreeNode__; }
@@ -140,6 +132,7 @@ function _NodeList(props: NodeListProps) {
140
132
  <Node
141
133
  node={item}
142
134
  level={item.level || 0}
135
+
143
136
  checkBoxViewStyleProps={checkBoxViewStyleProps}
144
137
 
145
138
  CheckboxComponent={CheckboxComponent}
@@ -162,7 +155,7 @@ function _NodeList(props: NodeListProps) {
162
155
  removeClippedSubviews={true}
163
156
  keyboardShouldPersistTaps="handled"
164
157
  drawDistance={50}
165
- data={flattenedFilteredNodes.value}
158
+ data={flattenedFilteredNodes}
166
159
  renderItem={nodeRenderer}
167
160
  keyExtractor={keyExtractor}
168
161
  ListHeaderComponent={<HeaderFooterView />}
@@ -189,10 +182,23 @@ interface NodeProps {
189
182
  ExpandCollapseTouchableComponent?: React.ComponentType<TouchableOpacityProps>;
190
183
  }
191
184
 
185
+ function getValue(
186
+ isChecked: boolean,
187
+ isIndeterminate: boolean
188
+ ): CheckboxValueType {
189
+ if (isIndeterminate) {
190
+ return 'indeterminate';
191
+ } else if (isChecked) {
192
+ return true;
193
+ } else {
194
+ return false;
195
+ }
196
+ }
197
+
192
198
  const Node = React.memo(_Node);
193
199
  function _Node(props: NodeProps) {
194
200
  const {
195
- node: _node,
201
+ node,
196
202
  level,
197
203
 
198
204
  checkBoxViewStyleProps,
@@ -202,36 +208,25 @@ function _Node(props: NodeProps) {
202
208
  ExpandCollapseTouchableComponent = TouchableOpacity,
203
209
  } = props;
204
210
 
205
- const node = useSignal(_node);
206
- React.useEffect(() => {
207
- node.value = _node;
208
- // eslint-disable-next-line react-hooks/exhaustive-deps
209
- }, [_node]);
210
-
211
- const isChecked = useComputed(() => state.value.checked.has(node.value.id));
212
- const isIndeterminate = useComputed(() => state.value.indeterminate.has(
213
- node.value.id
214
- ));
215
- const value: Signal<CheckboxValueType> = useComputed(() => {
216
- if (isIndeterminate.value) {
217
- return 'indeterminate';
218
- } else if (isChecked.value) {
219
- return true;
220
- } else {
221
- return false;
222
- }
223
- });
224
- const isExpanded = useComputed(() => expanded.value.has(node.value.id));
211
+ const { expanded, checked, indeterminate } = useStore();
212
+
213
+ const isChecked = checked.has(node.id);
214
+ const isIndeterminate = indeterminate.has(node.id);
215
+ const isExpanded = expanded.has(node.id);
216
+
217
+ const [value, setValue] = useState(getValue(isChecked, isIndeterminate));
218
+
219
+ useEffect(() => {
220
+ setValue(getValue(isChecked, isIndeterminate));
221
+ }, [isChecked, isIndeterminate]);
225
222
 
226
223
  const _onToggleExpand = React.useCallback(() => {
227
- handleToggleExpand(node.value.id);
228
- // eslint-disable-next-line react-hooks/exhaustive-deps
229
- }, []);
224
+ handleToggleExpand(node.id);
225
+ }, [node.id]);
230
226
 
231
227
  const _onCheck = React.useCallback(() => {
232
- toggleCheckboxes([node.value.id]);
233
- // eslint-disable-next-line react-hooks/exhaustive-deps
234
- }, []);
228
+ toggleCheckboxes([node.id]);
229
+ }, [node.id]);
235
230
 
236
231
  return (
237
232
  <View style={[
@@ -240,17 +235,17 @@ function _Node(props: NodeProps) {
240
235
  ]}>
241
236
  <View style={styles.nodeCheckboxAndArrowRow}>
242
237
  <CheckboxComponent
243
- text={node.value.name}
238
+ text={node.name}
244
239
  onValueChange={_onCheck}
245
- value={value.value}
240
+ value={value}
246
241
  {...checkBoxViewStyleProps} />
247
242
 
248
- {node.value.children?.length ? (
243
+ {node.children?.length ? (
249
244
  <ExpandCollapseTouchableComponent
250
245
  style={styles.nodeExpandableArrowTouchable}
251
246
  onPress={_onToggleExpand}>
252
247
  <ExpandCollapseIconComponent
253
- isExpanded={isExpanded.value}
248
+ isExpanded={isExpanded}
254
249
  />
255
250
  </ExpandCollapseTouchableComponent>
256
251
  ) : null}
@@ -1,9 +1,5 @@
1
1
  import { TreeNode } from "../types/treeView.types";
2
- import {
3
- expanded,
4
- globalData,
5
- nodeMap
6
- } from "../signals/global.signals";
2
+ import { useStore } from "../store/global.store";
7
3
 
8
4
  /**
9
5
  * Toggle the expanded state of a tree node by its ID.
@@ -14,8 +10,10 @@ import {
14
10
  * @param id - The ID of the tree node to toggle.
15
11
  */
16
12
  export function handleToggleExpand(id: string) {
13
+ const { globalData, expanded, updateExpanded } = useStore.getState();
14
+
17
15
  // Create a new Set based on the current expanded state
18
- const newExpanded = new Set(expanded.value);
16
+ const newExpanded = new Set(expanded);
19
17
 
20
18
  /**
21
19
  * Recursively deletes a node and its descendants from the expanded set.
@@ -52,9 +50,9 @@ export function handleToggleExpand(id: string) {
52
50
  }
53
51
 
54
52
  // Find the node to expand or collapse
55
- const node = findNode(globalData.value);
53
+ const node = findNode(globalData);
56
54
 
57
- if (expanded.value.has(id)) {
55
+ if (expanded.has(id)) {
58
56
  // If the node is currently expanded, collapse it and its descendants
59
57
  newExpanded.delete(id);
60
58
  if (node) {
@@ -66,23 +64,25 @@ export function handleToggleExpand(id: string) {
66
64
  }
67
65
 
68
66
  // Set the new expanded state
69
- expanded.value = newExpanded;
67
+ updateExpanded(newExpanded);
70
68
  };
71
69
 
72
70
  /**
73
71
  * Expand all nodes in the tree.
74
72
  */
75
73
  export function expandAll() {
74
+ const { nodeMap, updateExpanded } = useStore.getState();
76
75
  // Create a new Set containing the IDs of all nodes
77
- const newExpanded = new Set(nodeMap.value.keys());
78
- expanded.value = newExpanded;
76
+ const newExpanded = new Set(nodeMap.keys());
77
+ updateExpanded(newExpanded);
79
78
  };
80
79
 
81
80
  /**
82
81
  * Collapse all nodes in the tree.
83
82
  */
84
83
  export function collapseAll() {
84
+ const { updateExpanded } = useStore.getState();
85
85
  // Create an empty Set
86
86
  const newExpanded = new Set<string>();
87
- expanded.value = newExpanded;
87
+ updateExpanded(newExpanded);
88
88
  };
@@ -1,8 +1,7 @@
1
1
  import type { TreeNode } from "../types/treeView.types";
2
2
  import {
3
- childToParentMap,
4
- nodeMap,
5
- } from "../signals/global.signals";
3
+ useStore
4
+ } from "../store/global.store";
6
5
  import { toggleCheckboxes } from "./toggleCheckbox.helper";
7
6
 
8
7
  /**
@@ -18,6 +17,14 @@ export function initializeNodeMaps(
18
17
  initialData: TreeNode[],
19
18
  preselectedIds: string[] = [],
20
19
  ) {
20
+ const {
21
+ updateNodeMap,
22
+ updateChildToParentMap
23
+ } = useStore.getState();
24
+
25
+ const tempNodeMap: Map<string, TreeNode> = new Map();;
26
+ const tempChildToParentMap: Map<string, string> = new Map();;
27
+
21
28
  /**
22
29
  * Recursively processes nodes, adding them to the nodeMap and childToParentMap.
23
30
  *
@@ -30,9 +37,9 @@ export function initializeNodeMaps(
30
37
  ) => {
31
38
  nodes.forEach((node) => {
32
39
  // Each node is added to the nodeMap with its ID as the key
33
- nodeMap.value.set(node.id, node);
40
+ tempNodeMap.set(node.id, node);
34
41
  // If the node has a parent, its ID is mapped to the parent's ID in the childToParentMap
35
- if (parentId) childToParentMap.value.set(node.id, parentId);
42
+ if (parentId) tempChildToParentMap.set(node.id, parentId);
36
43
  // If the node has children, recursively process them
37
44
  if (node.children) processNodes(node.children, node.id);
38
45
  });
@@ -41,6 +48,9 @@ export function initializeNodeMaps(
41
48
  // Begin processing with the initial tree data
42
49
  processNodes(initialData);
43
50
 
51
+ updateNodeMap(tempNodeMap);
52
+ updateChildToParentMap(tempChildToParentMap);
53
+
44
54
  // Check any preselected nodes
45
55
  toggleCheckboxes(preselectedIds, true);
46
56
  }
@@ -1,9 +1,4 @@
1
- import {
2
- innerMostChildrenIds,
3
- nodeMap,
4
- searchText,
5
- state
6
- } from "../signals/global.signals";
1
+ import { useStore } from "../store/global.store";
7
2
  import { toggleCheckboxes } from "./toggleCheckbox.helper";
8
3
 
9
4
  /**
@@ -12,12 +7,15 @@ import { toggleCheckboxes } from "./toggleCheckbox.helper";
12
7
  * If there is no search text, then it selects all nodes; otherwise, it selects all visible nodes.
13
8
  */
14
9
  export function selectAllFiltered() {
10
+ const { searchText, innerMostChildrenIds } = useStore.getState();
11
+
12
+
15
13
  // If there's no search text, select all nodes
16
- if (!searchText.value) {
14
+ if (!searchText) {
17
15
  selectAll();
18
16
  } else {
19
17
  // If there's search text, only select the visible nodes
20
- toggleCheckboxes(innerMostChildrenIds.value, true);
18
+ toggleCheckboxes(innerMostChildrenIds, true);
21
19
  }
22
20
  };
23
21
 
@@ -27,12 +25,14 @@ export function selectAllFiltered() {
27
25
  * If there is no search text, then it unselects all nodes; otherwise, it unselects all visible nodes.
28
26
  */
29
27
  export function unselectAllFiltered() {
28
+ const { searchText, innerMostChildrenIds } = useStore.getState();
29
+
30
30
  // If there's no search text, unselect all nodes
31
- if (!searchText.value) {
31
+ if (!searchText) {
32
32
  unselectAll();
33
33
  } else {
34
34
  // If there's search text, only unselect the visible nodes
35
- toggleCheckboxes(innerMostChildrenIds.value, false);
35
+ toggleCheckboxes(innerMostChildrenIds, false);
36
36
  }
37
37
  };
38
38
 
@@ -42,10 +42,14 @@ export function unselectAllFiltered() {
42
42
  * This function selects all nodes by adding all node ids to the checked set and clearing the indeterminate set.
43
43
  */
44
44
  export function selectAll() {
45
+ const { nodeMap, updateChecked, updateIndeterminate } = useStore.getState();
46
+
45
47
  // Create a new set containing the ids of all nodes
46
- const newChecked = new Set(nodeMap.value.keys());
48
+ const newChecked = new Set(nodeMap.keys());
47
49
  // Update the state to mark all nodes as checked
48
- state.value = ({ checked: newChecked, indeterminate: new Set() });
50
+
51
+ updateChecked(newChecked);
52
+ updateIndeterminate(new Set());
49
53
  };
50
54
 
51
55
  /**
@@ -54,6 +58,9 @@ export function selectAll() {
54
58
  * This function unselects all nodes by clearing both the checked and indeterminate sets.
55
59
  */
56
60
  export function unselectAll() {
61
+ const { updateChecked, updateIndeterminate } = useStore.getState();
57
62
  // Update the state to mark all nodes as unchecked
58
- state.value = ({ checked: new Set(), indeterminate: new Set() });
63
+
64
+ updateChecked(new Set());
65
+ updateIndeterminate(new Set());
59
66
  };
@@ -1,4 +1,4 @@
1
- import { childToParentMap, nodeMap, state } from "../signals/global.signals";
1
+ import { useStore } from "../store/global.store";
2
2
 
3
3
  /**
4
4
  * Function to toggle checkbox state for a tree structure.
@@ -8,9 +8,20 @@ import { childToParentMap, nodeMap, state } from "../signals/global.signals";
8
8
  * If not provided, the check state will be toggled based on the current state.
9
9
  */
10
10
  export function toggleCheckboxes(ids: string[], forceCheck?: boolean) {
11
+ const {
12
+ checked,
13
+ updateChecked,
14
+
15
+ indeterminate,
16
+ updateIndeterminate,
17
+
18
+ nodeMap,
19
+ childToParentMap
20
+ } = useStore.getState();
21
+
11
22
  // Create new sets for checked and indeterminate state so as not to mutate the original state.
12
- const checked = new Set(state.value.checked);
13
- const indeterminate = new Set(state.value.indeterminate);
23
+ const tempChecked = new Set(checked);
24
+ const tempIndeterminate = new Set(indeterminate);
14
25
 
15
26
  // Maps for memoization of the recursive functions areAllDescendantsChecked and areAnyDescendantsChecked.
16
27
  const memoAllDescendantsChecked = new Map();
@@ -24,16 +35,16 @@ export function toggleCheckboxes(ids: string[], forceCheck?: boolean) {
24
35
  const toggleNodeAndChildren = (nodeId: string, isChecked: boolean) => {
25
36
  // Set or unset this node in the checked set, and remove it from the indeterminate set.
26
37
  if (isChecked) {
27
- checked.add(nodeId);
28
- indeterminate.delete(nodeId);
38
+ tempChecked.add(nodeId);
39
+ tempIndeterminate.delete(nodeId);
29
40
  } else {
30
- checked.delete(nodeId);
41
+ tempChecked.delete(nodeId);
31
42
  }
32
43
 
33
44
  // Get the node from the node map and recursively apply the same state to all its children.
34
- const node = nodeMap.value.get(nodeId);
45
+ const node = nodeMap.get(nodeId);
35
46
  node?.children?.forEach((childNode) => {
36
- if (isChecked) indeterminate.delete(childNode.id);
47
+ if (isChecked) tempIndeterminate.delete(childNode.id);
37
48
  toggleNodeAndChildren(childNode.id, isChecked);
38
49
  });
39
50
  };
@@ -50,7 +61,7 @@ export function toggleCheckboxes(ids: string[], forceCheck?: boolean) {
50
61
  return memoAllDescendantsChecked.get(nodeId);
51
62
  }
52
63
 
53
- const node = nodeMap.value.get(nodeId);
64
+ const node = nodeMap.get(nodeId);
54
65
  let allChecked = true;
55
66
  if (node?.children) {
56
67
  // If the node has children, recursively check all children.
@@ -59,7 +70,7 @@ export function toggleCheckboxes(ids: string[], forceCheck?: boolean) {
59
70
  }
60
71
  } else {
61
72
  // If the node has no children, its state is equal to whether it is in the checked set.
62
- allChecked = checked.has(nodeId);
73
+ allChecked = tempChecked.has(nodeId);
63
74
  }
64
75
 
65
76
  // Store the result in the map and return it.
@@ -79,7 +90,7 @@ export function toggleCheckboxes(ids: string[], forceCheck?: boolean) {
79
90
  return memoAnyDescendantsChecked.get(nodeId);
80
91
  }
81
92
 
82
- const node = nodeMap.value.get(nodeId);
93
+ const node = nodeMap.get(nodeId);
83
94
  let anyChecked = false;
84
95
  if (node?.children) {
85
96
  // If the node has children, recursively check all children.
@@ -88,7 +99,7 @@ export function toggleCheckboxes(ids: string[], forceCheck?: boolean) {
88
99
  }
89
100
  } else {
90
101
  // If the node has no children, its state is equal to whether it is in the checked set.
91
- anyChecked = checked.has(nodeId);
102
+ anyChecked = tempChecked.has(nodeId);
92
103
  }
93
104
 
94
105
  // Store the result in the map and return it.
@@ -101,32 +112,32 @@ export function toggleCheckboxes(ids: string[], forceCheck?: boolean) {
101
112
  * @param {string} nodeId - The id of the node to be updated.
102
113
  */
103
114
  const updateNodeAndAncestorsState = (nodeId: string) => {
104
- const node = nodeMap.value.get(nodeId);
115
+ const node = nodeMap.get(nodeId);
105
116
  const hasOnlyOneChild = node?.children && node.children.length === 1;
106
117
 
107
118
  // Update the node's state based on the state of its descendants.
108
119
  if (areAllDescendantsChecked(nodeId)) {
109
- checked.add(nodeId);
110
- indeterminate.delete(nodeId);
120
+ tempChecked.add(nodeId);
121
+ tempIndeterminate.delete(nodeId);
111
122
  } else if (areAnyDescendantsChecked(nodeId)) {
112
123
  if (hasOnlyOneChild) {
113
124
  // If a node has only one child and it's not checked,
114
125
  // remove this node from both checked and indeterminate sets.
115
- checked.delete(nodeId);
116
- indeterminate.delete(nodeId);
126
+ tempChecked.delete(nodeId);
127
+ tempIndeterminate.delete(nodeId);
117
128
  } else {
118
- checked.delete(nodeId);
119
- indeterminate.add(nodeId);
129
+ tempChecked.delete(nodeId);
130
+ tempIndeterminate.add(nodeId);
120
131
  }
121
132
  } else {
122
- checked.delete(nodeId);
123
- indeterminate.delete(nodeId);
133
+ tempChecked.delete(nodeId);
134
+ tempIndeterminate.delete(nodeId);
124
135
  }
125
136
  };
126
137
 
127
138
  // Toggle the clicked nodes and their children.
128
139
  ids.forEach((id) => {
129
- const isChecked = checked.has(id);
140
+ const isChecked = tempChecked.has(id);
130
141
  toggleNodeAndChildren(id, forceCheck === undefined ? !isChecked : forceCheck);
131
142
  });
132
143
 
@@ -135,10 +146,11 @@ export function toggleCheckboxes(ids: string[], forceCheck?: boolean) {
135
146
  let currentNodeId: string | undefined = id;
136
147
  while (currentNodeId) {
137
148
  updateNodeAndAncestorsState(currentNodeId);
138
- currentNodeId = childToParentMap.value.get(currentNodeId);
149
+ currentNodeId = childToParentMap.get(currentNodeId);
139
150
  }
140
151
  });
141
152
 
142
153
  // Update the state object with the new checked and indeterminate sets.
143
- state.value = ({ checked, indeterminate });
154
+ updateChecked(tempChecked);
155
+ updateIndeterminate(tempIndeterminate);
144
156
  };