@hitachivantara/uikit-react-core 5.36.1 → 5.36.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 (110) hide show
  1. package/dist/cjs/components/Card/Header/Header.cjs +1 -0
  2. package/dist/cjs/components/Card/Header/Header.cjs.map +1 -1
  3. package/dist/cjs/components/Card/Header/Header.styles.cjs +6 -10
  4. package/dist/cjs/components/Card/Header/Header.styles.cjs.map +1 -1
  5. package/dist/cjs/components/Section/Section.cjs +4 -3
  6. package/dist/cjs/components/Section/Section.cjs.map +1 -1
  7. package/dist/cjs/components/TreeView/TreeItem/DefaultContent.cjs +24 -8
  8. package/dist/cjs/components/TreeView/TreeItem/DefaultContent.cjs.map +1 -1
  9. package/dist/cjs/components/TreeView/TreeItem/TreeItem.cjs +7 -6
  10. package/dist/cjs/components/TreeView/TreeItem/TreeItem.cjs.map +1 -1
  11. package/dist/cjs/components/TreeView/TreeItem/useHvTreeItem.cjs +2 -3
  12. package/dist/cjs/components/TreeView/TreeItem/useHvTreeItem.cjs.map +1 -1
  13. package/dist/cjs/components/TreeView/TreeView.cjs +4 -4
  14. package/dist/cjs/components/TreeView/TreeView.cjs.map +1 -1
  15. package/dist/cjs/components/TreeView/internals/DescendantProvider.cjs +146 -0
  16. package/dist/cjs/components/TreeView/internals/DescendantProvider.cjs.map +1 -0
  17. package/dist/cjs/components/TreeView/internals/TreeViewProvider.cjs +34 -0
  18. package/dist/cjs/components/TreeView/internals/TreeViewProvider.cjs.map +1 -0
  19. package/dist/cjs/components/TreeView/internals/corePlugins.cjs +6 -0
  20. package/dist/cjs/components/TreeView/internals/corePlugins.cjs.map +1 -0
  21. package/dist/cjs/components/TreeView/internals/hooks/plugins/defaultPlugins.cjs +11 -0
  22. package/dist/cjs/components/TreeView/internals/hooks/plugins/defaultPlugins.cjs.map +1 -0
  23. package/dist/cjs/components/TreeView/internals/hooks/plugins/useTreeViewContextValueBuilder.cjs +28 -0
  24. package/dist/cjs/components/TreeView/internals/hooks/plugins/useTreeViewContextValueBuilder.cjs.map +1 -0
  25. package/dist/cjs/components/TreeView/internals/hooks/plugins/useTreeViewExpansion.cjs +80 -0
  26. package/dist/cjs/components/TreeView/internals/hooks/plugins/useTreeViewExpansion.cjs.map +1 -0
  27. package/dist/cjs/components/TreeView/internals/hooks/plugins/useTreeViewFocus.cjs +105 -0
  28. package/dist/cjs/components/TreeView/internals/hooks/plugins/useTreeViewFocus.cjs.map +1 -0
  29. package/dist/cjs/components/TreeView/internals/hooks/plugins/useTreeViewKeyboardNavigation.cjs +237 -0
  30. package/dist/cjs/components/TreeView/internals/hooks/plugins/useTreeViewKeyboardNavigation.cjs.map +1 -0
  31. package/dist/cjs/components/TreeView/internals/hooks/plugins/useTreeViewNodes.cjs +82 -0
  32. package/dist/cjs/components/TreeView/internals/hooks/plugins/useTreeViewNodes.cjs.map +1 -0
  33. package/dist/cjs/components/TreeView/internals/hooks/plugins/useTreeViewSelection.cjs +232 -0
  34. package/dist/cjs/components/TreeView/internals/hooks/plugins/useTreeViewSelection.cjs.map +1 -0
  35. package/dist/cjs/components/TreeView/internals/hooks/useInstanceEventHandler.cjs +93 -0
  36. package/dist/cjs/components/TreeView/internals/hooks/useInstanceEventHandler.cjs.map +1 -0
  37. package/dist/cjs/components/TreeView/internals/hooks/useTreeView.cjs +87 -0
  38. package/dist/cjs/components/TreeView/internals/hooks/useTreeView.cjs.map +1 -0
  39. package/dist/cjs/components/TreeView/internals/hooks/useTreeViewInstanceEvents.cjs +52 -0
  40. package/dist/cjs/components/TreeView/internals/hooks/useTreeViewInstanceEvents.cjs.map +1 -0
  41. package/dist/cjs/components/TreeView/internals/hooks/useTreeViewModels.cjs +58 -0
  42. package/dist/cjs/components/TreeView/internals/hooks/useTreeViewModels.cjs.map +1 -0
  43. package/dist/cjs/components/TreeView/internals/hooks/utils.cjs +47 -0
  44. package/dist/cjs/components/TreeView/internals/hooks/utils.cjs.map +1 -0
  45. package/dist/cjs/components/TreeView/internals/utils/EventManager.cjs +62 -0
  46. package/dist/cjs/components/TreeView/internals/utils/EventManager.cjs.map +1 -0
  47. package/dist/cjs/components/TreeView/internals/utils/FinalizationRegistryBasedCleanupTracking.cjs +22 -0
  48. package/dist/cjs/components/TreeView/internals/utils/FinalizationRegistryBasedCleanupTracking.cjs.map +1 -0
  49. package/dist/cjs/components/TreeView/internals/utils/TimerBasedCleanupTracking.cjs +41 -0
  50. package/dist/cjs/components/TreeView/internals/utils/TimerBasedCleanupTracking.cjs.map +1 -0
  51. package/dist/cjs/components/TreeView/internals/utils/publishTreeViewEvent.cjs +7 -0
  52. package/dist/cjs/components/TreeView/internals/utils/publishTreeViewEvent.cjs.map +1 -0
  53. package/dist/esm/components/Card/Header/Header.js +1 -0
  54. package/dist/esm/components/Card/Header/Header.js.map +1 -1
  55. package/dist/esm/components/Card/Header/Header.styles.js +6 -10
  56. package/dist/esm/components/Card/Header/Header.styles.js.map +1 -1
  57. package/dist/esm/components/Section/Section.js +4 -3
  58. package/dist/esm/components/Section/Section.js.map +1 -1
  59. package/dist/esm/components/TreeView/TreeItem/DefaultContent.js +18 -2
  60. package/dist/esm/components/TreeView/TreeItem/DefaultContent.js.map +1 -1
  61. package/dist/esm/components/TreeView/TreeItem/TreeItem.js +3 -4
  62. package/dist/esm/components/TreeView/TreeItem/TreeItem.js.map +1 -1
  63. package/dist/esm/components/TreeView/TreeItem/useHvTreeItem.js +1 -2
  64. package/dist/esm/components/TreeView/TreeItem/useHvTreeItem.js.map +1 -1
  65. package/dist/esm/components/TreeView/TreeView.js +4 -4
  66. package/dist/esm/components/TreeView/TreeView.js.map +1 -1
  67. package/dist/esm/components/TreeView/internals/DescendantProvider.js +127 -0
  68. package/dist/esm/components/TreeView/internals/DescendantProvider.js.map +1 -0
  69. package/dist/esm/components/TreeView/internals/TreeViewProvider.js +34 -0
  70. package/dist/esm/components/TreeView/internals/TreeViewProvider.js.map +1 -0
  71. package/dist/esm/components/TreeView/internals/corePlugins.js +6 -0
  72. package/dist/esm/components/TreeView/internals/corePlugins.js.map +1 -0
  73. package/dist/esm/components/TreeView/internals/hooks/plugins/defaultPlugins.js +11 -0
  74. package/dist/esm/components/TreeView/internals/hooks/plugins/defaultPlugins.js.map +1 -0
  75. package/dist/esm/components/TreeView/internals/hooks/plugins/useTreeViewContextValueBuilder.js +28 -0
  76. package/dist/esm/components/TreeView/internals/hooks/plugins/useTreeViewContextValueBuilder.js.map +1 -0
  77. package/dist/esm/components/TreeView/internals/hooks/plugins/useTreeViewExpansion.js +61 -0
  78. package/dist/esm/components/TreeView/internals/hooks/plugins/useTreeViewExpansion.js.map +1 -0
  79. package/dist/esm/components/TreeView/internals/hooks/plugins/useTreeViewFocus.js +86 -0
  80. package/dist/esm/components/TreeView/internals/hooks/plugins/useTreeViewFocus.js.map +1 -0
  81. package/dist/esm/components/TreeView/internals/hooks/plugins/useTreeViewKeyboardNavigation.js +218 -0
  82. package/dist/esm/components/TreeView/internals/hooks/plugins/useTreeViewKeyboardNavigation.js.map +1 -0
  83. package/dist/esm/components/TreeView/internals/hooks/plugins/useTreeViewNodes.js +63 -0
  84. package/dist/esm/components/TreeView/internals/hooks/plugins/useTreeViewNodes.js.map +1 -0
  85. package/dist/esm/components/TreeView/internals/hooks/plugins/useTreeViewSelection.js +213 -0
  86. package/dist/esm/components/TreeView/internals/hooks/plugins/useTreeViewSelection.js.map +1 -0
  87. package/dist/esm/components/TreeView/internals/hooks/useInstanceEventHandler.js +74 -0
  88. package/dist/esm/components/TreeView/internals/hooks/useInstanceEventHandler.js.map +1 -0
  89. package/dist/esm/components/TreeView/internals/hooks/useTreeView.js +68 -0
  90. package/dist/esm/components/TreeView/internals/hooks/useTreeView.js.map +1 -0
  91. package/dist/esm/components/TreeView/internals/hooks/useTreeViewInstanceEvents.js +33 -0
  92. package/dist/esm/components/TreeView/internals/hooks/useTreeViewInstanceEvents.js.map +1 -0
  93. package/dist/esm/components/TreeView/internals/hooks/useTreeViewModels.js +39 -0
  94. package/dist/esm/components/TreeView/internals/hooks/useTreeViewModels.js.map +1 -0
  95. package/dist/esm/components/TreeView/internals/hooks/utils.js +47 -0
  96. package/dist/esm/components/TreeView/internals/hooks/utils.js.map +1 -0
  97. package/dist/esm/components/TreeView/internals/utils/EventManager.js +62 -0
  98. package/dist/esm/components/TreeView/internals/utils/EventManager.js.map +1 -0
  99. package/dist/esm/components/TreeView/internals/utils/FinalizationRegistryBasedCleanupTracking.js +22 -0
  100. package/dist/esm/components/TreeView/internals/utils/FinalizationRegistryBasedCleanupTracking.js.map +1 -0
  101. package/dist/esm/components/TreeView/internals/utils/TimerBasedCleanupTracking.js +41 -0
  102. package/dist/esm/components/TreeView/internals/utils/TimerBasedCleanupTracking.js.map +1 -0
  103. package/dist/esm/components/TreeView/internals/utils/publishTreeViewEvent.js +7 -0
  104. package/dist/esm/components/TreeView/internals/utils/publishTreeViewEvent.js.map +1 -0
  105. package/dist/types/index.d.ts +216 -14
  106. package/package.json +5 -6
  107. package/dist/cjs/components/TreeView/internals.cjs +0 -30
  108. package/dist/cjs/components/TreeView/internals.cjs.map +0 -1
  109. package/dist/esm/components/TreeView/internals.js +0 -15
  110. package/dist/esm/components/TreeView/internals.js.map +0 -1
@@ -0,0 +1,218 @@
1
+ import * as React from "react";
2
+ import { useTheme } from "@mui/material/styles";
3
+ import { useEventCallback } from "@mui/material/utils";
4
+ import { populateInstance, getFirstNode, getLastNode, getPreviousNode, getNextNode } from "../utils.js";
5
+ function isPrintableCharacter(string) {
6
+ return string && string.length === 1 && string.match(/\S/);
7
+ }
8
+ function findNextFirstChar(firstChars, startIndex, char) {
9
+ for (let i = startIndex; i < firstChars.length; i += 1) {
10
+ if (char === firstChars[i]) {
11
+ return i;
12
+ }
13
+ }
14
+ return -1;
15
+ }
16
+ const useTreeViewKeyboardNavigation = ({
17
+ instance,
18
+ params,
19
+ state
20
+ }) => {
21
+ const theme = useTheme();
22
+ const isRtl = theme.direction === "rtl";
23
+ const firstCharMap = React.useRef({});
24
+ const mapFirstChar = useEventCallback((nodeId, firstChar) => {
25
+ firstCharMap.current[nodeId] = firstChar;
26
+ return () => {
27
+ const newMap = {
28
+ ...firstCharMap.current
29
+ };
30
+ delete newMap[nodeId];
31
+ firstCharMap.current = newMap;
32
+ };
33
+ });
34
+ populateInstance(instance, {
35
+ mapFirstChar
36
+ });
37
+ const handleNextArrow = (event) => {
38
+ if (state.focusedNodeId != null && instance.isNodeExpandable(state.focusedNodeId)) {
39
+ if (instance.isNodeExpanded(state.focusedNodeId)) {
40
+ instance.focusNode(event, getNextNode(instance, state.focusedNodeId));
41
+ } else if (!instance.isNodeDisabled(state.focusedNodeId)) {
42
+ instance.toggleNodeExpansion(event, state.focusedNodeId);
43
+ }
44
+ }
45
+ return true;
46
+ };
47
+ const handlePreviousArrow = (event) => {
48
+ if (state.focusedNodeId == null) {
49
+ return false;
50
+ }
51
+ if (instance.isNodeExpanded(state.focusedNodeId) && !instance.isNodeDisabled(state.focusedNodeId)) {
52
+ instance.toggleNodeExpansion(event, state.focusedNodeId);
53
+ return true;
54
+ }
55
+ const parent = instance.getNode(state.focusedNodeId).parentId;
56
+ if (parent) {
57
+ instance.focusNode(event, parent);
58
+ return true;
59
+ }
60
+ return false;
61
+ };
62
+ const focusByFirstCharacter = (event, nodeId, firstChar) => {
63
+ let start;
64
+ let index;
65
+ const lowercaseChar = firstChar.toLowerCase();
66
+ const firstCharIds = [];
67
+ const firstChars = [];
68
+ Object.keys(firstCharMap.current).forEach((mapNodeId) => {
69
+ const map = instance.getNode(mapNodeId);
70
+ const visible = map.parentId ? instance.isNodeExpanded(map.parentId) : true;
71
+ const shouldBeSkipped = params.disabledItemsFocusable ? false : instance.isNodeDisabled(mapNodeId);
72
+ if (visible && !shouldBeSkipped) {
73
+ firstCharIds.push(mapNodeId);
74
+ firstChars.push(firstCharMap.current[mapNodeId]);
75
+ }
76
+ });
77
+ start = firstCharIds.indexOf(nodeId) + 1;
78
+ if (start >= firstCharIds.length) {
79
+ start = 0;
80
+ }
81
+ index = findNextFirstChar(firstChars, start, lowercaseChar);
82
+ if (index === -1) {
83
+ index = findNextFirstChar(firstChars, 0, lowercaseChar);
84
+ }
85
+ if (index > -1) {
86
+ instance.focusNode(event, firstCharIds[index]);
87
+ }
88
+ };
89
+ const selectNextNode = (event, id) => {
90
+ if (!instance.isNodeDisabled(getNextNode(instance, id))) {
91
+ instance.selectRange(event, {
92
+ end: getNextNode(instance, id),
93
+ current: id
94
+ }, true);
95
+ }
96
+ };
97
+ const selectPreviousNode = (event, nodeId) => {
98
+ if (!instance.isNodeDisabled(getPreviousNode(instance, nodeId))) {
99
+ instance.selectRange(event, {
100
+ end: getPreviousNode(instance, nodeId),
101
+ current: nodeId
102
+ }, true);
103
+ }
104
+ };
105
+ const createHandleKeyDown = (otherHandlers) => (event) => {
106
+ otherHandlers.onKeyDown?.(event);
107
+ let flag = false;
108
+ const {
109
+ key
110
+ } = event;
111
+ if (event.altKey || event.currentTarget !== event.target || state.focusedNodeId == null) {
112
+ return;
113
+ }
114
+ const ctrlPressed = event.ctrlKey || event.metaKey;
115
+ switch (key) {
116
+ case " ":
117
+ if (!params.disableSelection && !instance.isNodeDisabled(state.focusedNodeId)) {
118
+ flag = true;
119
+ if (params.multiSelect && event.shiftKey) {
120
+ instance.selectRange(event, {
121
+ end: state.focusedNodeId
122
+ });
123
+ } else if (params.multiSelect) {
124
+ instance.selectNode(event, state.focusedNodeId, true);
125
+ } else {
126
+ instance.selectNode(event, state.focusedNodeId);
127
+ }
128
+ }
129
+ event.stopPropagation();
130
+ break;
131
+ case "Enter":
132
+ if (!instance.isNodeDisabled(state.focusedNodeId)) {
133
+ if (instance.isNodeExpandable(state.focusedNodeId)) {
134
+ instance.toggleNodeExpansion(event, state.focusedNodeId);
135
+ flag = true;
136
+ } else if (!params.disableSelection) {
137
+ flag = true;
138
+ if (params.multiSelect) {
139
+ instance.selectNode(event, state.focusedNodeId, true);
140
+ } else {
141
+ instance.selectNode(event, state.focusedNodeId);
142
+ }
143
+ }
144
+ }
145
+ event.stopPropagation();
146
+ break;
147
+ case "ArrowDown":
148
+ if (params.multiSelect && event.shiftKey && !params.disableSelection) {
149
+ selectNextNode(event, state.focusedNodeId);
150
+ }
151
+ instance.focusNode(event, getNextNode(instance, state.focusedNodeId));
152
+ flag = true;
153
+ break;
154
+ case "ArrowUp":
155
+ if (params.multiSelect && event.shiftKey && !params.disableSelection) {
156
+ selectPreviousNode(event, state.focusedNodeId);
157
+ }
158
+ instance.focusNode(event, getPreviousNode(instance, state.focusedNodeId));
159
+ flag = true;
160
+ break;
161
+ case "ArrowRight":
162
+ if (isRtl) {
163
+ flag = handlePreviousArrow(event);
164
+ } else {
165
+ flag = handleNextArrow(event);
166
+ }
167
+ break;
168
+ case "ArrowLeft":
169
+ if (isRtl) {
170
+ flag = handleNextArrow(event);
171
+ } else {
172
+ flag = handlePreviousArrow(event);
173
+ }
174
+ break;
175
+ case "Home":
176
+ if (params.multiSelect && ctrlPressed && event.shiftKey && !params.disableSelection && !instance.isNodeDisabled(state.focusedNodeId)) {
177
+ instance.rangeSelectToFirst(event, state.focusedNodeId);
178
+ }
179
+ instance.focusNode(event, getFirstNode(instance));
180
+ flag = true;
181
+ break;
182
+ case "End":
183
+ if (params.multiSelect && ctrlPressed && event.shiftKey && !params.disableSelection && !instance.isNodeDisabled(state.focusedNodeId)) {
184
+ instance.rangeSelectToLast(event, state.focusedNodeId);
185
+ }
186
+ instance.focusNode(event, getLastNode(instance));
187
+ flag = true;
188
+ break;
189
+ default:
190
+ if (key === "*") {
191
+ instance.expandAllSiblings(event, state.focusedNodeId);
192
+ flag = true;
193
+ } else if (params.multiSelect && ctrlPressed && key.toLowerCase() === "a" && !params.disableSelection) {
194
+ instance.selectRange(event, {
195
+ start: getFirstNode(instance),
196
+ end: getLastNode(instance)
197
+ });
198
+ flag = true;
199
+ } else if (!ctrlPressed && !event.shiftKey && isPrintableCharacter(key)) {
200
+ focusByFirstCharacter(event, state.focusedNodeId, key);
201
+ flag = true;
202
+ }
203
+ }
204
+ if (flag) {
205
+ event.preventDefault();
206
+ event.stopPropagation();
207
+ }
208
+ };
209
+ return {
210
+ getRootProps: (otherHandlers) => ({
211
+ onKeyDown: createHandleKeyDown(otherHandlers)
212
+ })
213
+ };
214
+ };
215
+ export {
216
+ useTreeViewKeyboardNavigation
217
+ };
218
+ //# sourceMappingURL=useTreeViewKeyboardNavigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTreeViewKeyboardNavigation.js","sources":["../../../../../../../src/components/TreeView/internals/hooks/plugins/useTreeViewKeyboardNavigation.ts"],"sourcesContent":["import * as React from \"react\";\nimport { useTheme } from \"@mui/material/styles\";\nimport { useEventCallback } from \"@mui/material/utils\";\nimport { EventHandlers } from \"@mui/base/utils\";\n\nimport { TreeViewPlugin, TreeViewPluginSignature } from \"../../types\";\nimport {\n getFirstNode,\n getLastNode,\n getNextNode,\n getPreviousNode,\n populateInstance,\n} from \"../utils\";\nimport type { UseTreeViewNodesSignature } from \"./useTreeViewNodes\";\nimport type { UseTreeViewSelectionSignature } from \"./useTreeViewSelection\";\nimport type { UseTreeViewFocusSignature } from \"./useTreeViewFocus\";\nimport type { UseTreeViewExpansionSignature } from \"./useTreeViewExpansion\";\n\nfunction isPrintableCharacter(string: string) {\n return string && string.length === 1 && string.match(/\\S/);\n}\n\nfunction findNextFirstChar(\n firstChars: string[],\n startIndex: number,\n char: string\n) {\n for (let i = startIndex; i < firstChars.length; i += 1) {\n if (char === firstChars[i]) {\n return i;\n }\n }\n return -1;\n}\n\nexport interface UseTreeViewKeyboardNavigationInstance {\n mapFirstChar: (nodeId: string, firstChar: string) => () => void;\n}\n\nexport type UseTreeViewKeyboardNavigationSignature = TreeViewPluginSignature<\n {},\n {},\n UseTreeViewKeyboardNavigationInstance,\n {},\n {},\n never,\n [\n UseTreeViewNodesSignature,\n UseTreeViewSelectionSignature<any>,\n UseTreeViewFocusSignature,\n UseTreeViewExpansionSignature\n ]\n>;\n\nexport const useTreeViewKeyboardNavigation: TreeViewPlugin<\n UseTreeViewKeyboardNavigationSignature\n> = ({ instance, params, state }) => {\n const theme = useTheme();\n const isRtl = theme.direction === \"rtl\";\n const firstCharMap = React.useRef<{ [nodeId: string]: string }>({});\n\n const mapFirstChar = useEventCallback((nodeId: string, firstChar: string) => {\n firstCharMap.current[nodeId] = firstChar;\n\n return () => {\n const newMap = { ...firstCharMap.current };\n delete newMap[nodeId];\n firstCharMap.current = newMap;\n };\n });\n\n populateInstance<UseTreeViewKeyboardNavigationSignature>(instance, {\n mapFirstChar,\n });\n\n const handleNextArrow = (event: React.KeyboardEvent<HTMLUListElement>) => {\n if (\n state.focusedNodeId != null &&\n instance.isNodeExpandable(state.focusedNodeId)\n ) {\n if (instance.isNodeExpanded(state.focusedNodeId)) {\n instance.focusNode(event, getNextNode(instance, state.focusedNodeId));\n } else if (!instance.isNodeDisabled(state.focusedNodeId)) {\n instance.toggleNodeExpansion(event, state.focusedNodeId);\n }\n }\n return true;\n };\n\n const handlePreviousArrow = (\n event: React.KeyboardEvent<HTMLUListElement>\n ) => {\n if (state.focusedNodeId == null) {\n return false;\n }\n\n if (\n instance.isNodeExpanded(state.focusedNodeId) &&\n !instance.isNodeDisabled(state.focusedNodeId)\n ) {\n instance.toggleNodeExpansion(event, state.focusedNodeId!);\n return true;\n }\n\n const parent = instance.getNode(state.focusedNodeId).parentId;\n if (parent) {\n instance.focusNode(event, parent);\n return true;\n }\n return false;\n };\n\n const focusByFirstCharacter = (\n event: React.KeyboardEvent<HTMLUListElement>,\n nodeId: string,\n firstChar: string\n ) => {\n let start: number;\n let index: number;\n const lowercaseChar = firstChar.toLowerCase();\n\n const firstCharIds: string[] = [];\n const firstChars: string[] = [];\n // This really only works since the ids are strings\n Object.keys(firstCharMap.current).forEach((mapNodeId) => {\n const map = instance.getNode(mapNodeId);\n const visible = map.parentId\n ? instance.isNodeExpanded(map.parentId)\n : true;\n const shouldBeSkipped = params.disabledItemsFocusable\n ? false\n : instance.isNodeDisabled(mapNodeId);\n\n if (visible && !shouldBeSkipped) {\n firstCharIds.push(mapNodeId);\n firstChars.push(firstCharMap.current[mapNodeId]);\n }\n });\n\n // Get start index for search based on position of currentItem\n start = firstCharIds.indexOf(nodeId) + 1;\n if (start >= firstCharIds.length) {\n start = 0;\n }\n\n // Check remaining slots in the menu\n index = findNextFirstChar(firstChars, start, lowercaseChar);\n\n // If not found in remaining slots, check from beginning\n if (index === -1) {\n index = findNextFirstChar(firstChars, 0, lowercaseChar);\n }\n\n // If match was found...\n if (index > -1) {\n instance.focusNode(event, firstCharIds[index]);\n }\n };\n\n const selectNextNode = (\n event: React.KeyboardEvent<HTMLUListElement>,\n id: string\n ) => {\n if (!instance.isNodeDisabled(getNextNode(instance, id))) {\n instance.selectRange(\n event,\n {\n end: getNextNode(instance, id),\n current: id,\n },\n true\n );\n }\n };\n\n const selectPreviousNode = (\n event: React.KeyboardEvent<HTMLUListElement>,\n nodeId: string\n ) => {\n if (!instance.isNodeDisabled(getPreviousNode(instance, nodeId))) {\n instance.selectRange(\n event,\n {\n end: getPreviousNode(instance, nodeId)!,\n current: nodeId,\n },\n true\n );\n }\n };\n\n const createHandleKeyDown =\n (otherHandlers: EventHandlers) =>\n (event: React.KeyboardEvent<HTMLUListElement>) => {\n otherHandlers.onKeyDown?.(event);\n\n let flag = false;\n const { key } = event;\n\n // If the tree is empty there will be no focused node\n if (\n event.altKey ||\n event.currentTarget !== event.target ||\n state.focusedNodeId == null\n ) {\n return;\n }\n\n const ctrlPressed = event.ctrlKey || event.metaKey;\n switch (key) {\n case \" \":\n if (\n !params.disableSelection &&\n !instance.isNodeDisabled(state.focusedNodeId)\n ) {\n flag = true;\n if (params.multiSelect && event.shiftKey) {\n instance.selectRange(event, { end: state.focusedNodeId });\n } else if (params.multiSelect) {\n instance.selectNode(event, state.focusedNodeId, true);\n } else {\n instance.selectNode(event, state.focusedNodeId);\n }\n }\n event.stopPropagation();\n break;\n case \"Enter\":\n if (!instance.isNodeDisabled(state.focusedNodeId)) {\n if (instance.isNodeExpandable(state.focusedNodeId)) {\n instance.toggleNodeExpansion(event, state.focusedNodeId);\n flag = true;\n } else if (!params.disableSelection) {\n flag = true;\n if (params.multiSelect) {\n instance.selectNode(event, state.focusedNodeId, true);\n } else {\n instance.selectNode(event, state.focusedNodeId);\n }\n }\n }\n event.stopPropagation();\n break;\n case \"ArrowDown\":\n if (\n params.multiSelect &&\n event.shiftKey &&\n !params.disableSelection\n ) {\n selectNextNode(event, state.focusedNodeId);\n }\n instance.focusNode(event, getNextNode(instance, state.focusedNodeId));\n flag = true;\n break;\n case \"ArrowUp\":\n if (\n params.multiSelect &&\n event.shiftKey &&\n !params.disableSelection\n ) {\n selectPreviousNode(event, state.focusedNodeId);\n }\n instance.focusNode(\n event,\n getPreviousNode(instance, state.focusedNodeId)\n );\n flag = true;\n break;\n case \"ArrowRight\":\n if (isRtl) {\n flag = handlePreviousArrow(event);\n } else {\n flag = handleNextArrow(event);\n }\n break;\n case \"ArrowLeft\":\n if (isRtl) {\n flag = handleNextArrow(event);\n } else {\n flag = handlePreviousArrow(event);\n }\n break;\n case \"Home\":\n if (\n params.multiSelect &&\n ctrlPressed &&\n event.shiftKey &&\n !params.disableSelection &&\n !instance.isNodeDisabled(state.focusedNodeId)\n ) {\n instance.rangeSelectToFirst(event, state.focusedNodeId);\n }\n instance.focusNode(event, getFirstNode(instance));\n flag = true;\n break;\n case \"End\":\n if (\n params.multiSelect &&\n ctrlPressed &&\n event.shiftKey &&\n !params.disableSelection &&\n !instance.isNodeDisabled(state.focusedNodeId)\n ) {\n instance.rangeSelectToLast(event, state.focusedNodeId);\n }\n instance.focusNode(event, getLastNode(instance));\n flag = true;\n break;\n default:\n if (key === \"*\") {\n instance.expandAllSiblings(event, state.focusedNodeId);\n flag = true;\n } else if (\n params.multiSelect &&\n ctrlPressed &&\n key.toLowerCase() === \"a\" &&\n !params.disableSelection\n ) {\n instance.selectRange(event, {\n start: getFirstNode(instance),\n end: getLastNode(instance),\n });\n flag = true;\n } else if (\n !ctrlPressed &&\n !event.shiftKey &&\n isPrintableCharacter(key)\n ) {\n focusByFirstCharacter(event, state.focusedNodeId, key);\n flag = true;\n }\n }\n\n if (flag) {\n event.preventDefault();\n event.stopPropagation();\n }\n };\n\n return {\n getRootProps: (otherHandlers) => ({\n onKeyDown: createHandleKeyDown(otherHandlers),\n }),\n };\n};\n"],"names":["isPrintableCharacter","string","length","match","findNextFirstChar","firstChars","startIndex","char","i","useTreeViewKeyboardNavigation","instance","params","state","theme","useTheme","isRtl","direction","firstCharMap","React","useRef","mapFirstChar","useEventCallback","nodeId","firstChar","current","newMap","populateInstance","handleNextArrow","event","focusedNodeId","isNodeExpandable","isNodeExpanded","focusNode","getNextNode","isNodeDisabled","toggleNodeExpansion","handlePreviousArrow","parent","getNode","parentId","focusByFirstCharacter","start","index","lowercaseChar","toLowerCase","firstCharIds","Object","keys","forEach","mapNodeId","map","visible","shouldBeSkipped","disabledItemsFocusable","push","indexOf","selectNextNode","id","selectRange","end","selectPreviousNode","getPreviousNode","createHandleKeyDown","otherHandlers","onKeyDown","flag","key","altKey","currentTarget","target","ctrlPressed","ctrlKey","metaKey","disableSelection","multiSelect","shiftKey","selectNode","stopPropagation","rangeSelectToFirst","getFirstNode","rangeSelectToLast","getLastNode","expandAllSiblings","preventDefault","getRootProps"],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ import * as React from "react";
2
+ import { useEventCallback } from "@mui/material/utils";
3
+ import { populateInstance } from "../utils.js";
4
+ import { publishTreeViewEvent } from "../../utils/publishTreeViewEvent.js";
5
+ const useTreeViewNodes = ({
6
+ instance,
7
+ params
8
+ }) => {
9
+ const nodeMap = React.useRef({});
10
+ const getNode = React.useCallback((nodeId) => nodeMap.current[nodeId], []);
11
+ const insertNode = React.useCallback((node) => {
12
+ nodeMap.current[node.id] = node;
13
+ }, []);
14
+ const removeNode = React.useCallback((nodeId) => {
15
+ const newMap = {
16
+ ...nodeMap.current
17
+ };
18
+ delete newMap[nodeId];
19
+ nodeMap.current = newMap;
20
+ publishTreeViewEvent(instance, "removeNode", {
21
+ id: nodeId
22
+ });
23
+ }, [instance]);
24
+ const isNodeDisabled = React.useCallback((nodeId) => {
25
+ if (nodeId == null) {
26
+ return false;
27
+ }
28
+ let node = instance.getNode(nodeId);
29
+ if (!node) {
30
+ return false;
31
+ }
32
+ if (node.disabled) {
33
+ return true;
34
+ }
35
+ while (node.parentId != null) {
36
+ node = instance.getNode(node.parentId);
37
+ if (node.disabled) {
38
+ return true;
39
+ }
40
+ }
41
+ return false;
42
+ }, [instance]);
43
+ const getChildrenIds = useEventCallback((nodeId) => Object.values(nodeMap.current).filter((node) => node.parentId === nodeId).sort((a, b) => a.index - b.index).map((child) => child.id));
44
+ const getNavigableChildrenIds = (nodeId) => {
45
+ let childrenIds = instance.getChildrenIds(nodeId);
46
+ if (!params.disabledItemsFocusable) {
47
+ childrenIds = childrenIds.filter((node) => !instance.isNodeDisabled(node));
48
+ }
49
+ return childrenIds;
50
+ };
51
+ populateInstance(instance, {
52
+ getNode,
53
+ updateNode: insertNode,
54
+ removeNode,
55
+ getChildrenIds,
56
+ getNavigableChildrenIds,
57
+ isNodeDisabled
58
+ });
59
+ };
60
+ export {
61
+ useTreeViewNodes
62
+ };
63
+ //# sourceMappingURL=useTreeViewNodes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTreeViewNodes.js","sources":["../../../../../../../src/components/TreeView/internals/hooks/plugins/useTreeViewNodes.ts"],"sourcesContent":["import * as React from \"react\";\nimport { useEventCallback } from \"@mui/material/utils\";\n\nimport {\n DefaultizedProps,\n TreeViewNode,\n TreeViewPlugin,\n TreeViewPluginSignature,\n} from \"../../types\";\nimport { populateInstance } from \"../utils\";\nimport { publishTreeViewEvent } from \"../../utils/publishTreeViewEvent\";\n\nexport interface UseTreeViewNodesInstance {\n getNode: (nodeId: string) => TreeViewNode;\n updateNode: (node: TreeViewNode) => void;\n removeNode: (nodeId: string) => void;\n getChildrenIds: (nodeId: string | null) => string[];\n getNavigableChildrenIds: (nodeId: string | null) => string[];\n isNodeDisabled: (nodeId: string | null) => nodeId is string;\n}\n\nexport interface UseTreeViewNodesParameters {\n /**\n * If `true`, will allow focus on disabled items.\n * @default false\n */\n disabledItemsFocusable?: boolean;\n}\n\nexport type UseTreeViewNodesDefaultizedParameters = DefaultizedProps<\n UseTreeViewNodesParameters,\n \"disabledItemsFocusable\"\n>;\n\ninterface UseTreeViewNodesEventLookup {\n removeNode: {\n params: { id: string };\n };\n}\n\nexport type UseTreeViewNodesSignature = TreeViewPluginSignature<\n UseTreeViewNodesParameters,\n UseTreeViewNodesDefaultizedParameters,\n UseTreeViewNodesInstance,\n UseTreeViewNodesEventLookup,\n {},\n never,\n []\n>;\n\nexport const useTreeViewNodes: TreeViewPlugin<UseTreeViewNodesSignature> = ({\n instance,\n params,\n}) => {\n const nodeMap = React.useRef<{ [nodeId: string]: TreeViewNode }>({});\n\n const getNode = React.useCallback(\n (nodeId: string) => nodeMap.current[nodeId],\n []\n );\n\n const insertNode = React.useCallback((node: TreeViewNode) => {\n nodeMap.current[node.id] = node;\n }, []);\n\n const removeNode = React.useCallback(\n (nodeId: string) => {\n const newMap = { ...nodeMap.current };\n delete newMap[nodeId];\n nodeMap.current = newMap;\n publishTreeViewEvent(instance as any, \"removeNode\", { id: nodeId });\n },\n [instance]\n );\n\n const isNodeDisabled = React.useCallback(\n (nodeId: string | null): nodeId is string => {\n if (nodeId == null) {\n return false;\n }\n\n let node = instance.getNode(nodeId);\n\n // This can be called before the node has been added to the node map.\n if (!node) {\n return false;\n }\n\n if (node.disabled) {\n return true;\n }\n\n while (node.parentId != null) {\n node = instance.getNode(node.parentId);\n if (node.disabled) {\n return true;\n }\n }\n\n return false;\n },\n [instance]\n );\n\n const getChildrenIds = useEventCallback((nodeId: string | null) =>\n Object.values(nodeMap.current)\n .filter((node) => node.parentId === nodeId)\n .sort((a, b) => a.index - b.index)\n .map((child) => child.id)\n );\n\n const getNavigableChildrenIds = (nodeId: string | null) => {\n let childrenIds = instance.getChildrenIds(nodeId);\n\n if (!params.disabledItemsFocusable) {\n childrenIds = childrenIds.filter(\n (node) => !instance.isNodeDisabled(node)\n );\n }\n return childrenIds;\n };\n\n populateInstance<UseTreeViewNodesSignature>(instance, {\n getNode,\n updateNode: insertNode,\n removeNode,\n getChildrenIds,\n getNavigableChildrenIds,\n isNodeDisabled,\n });\n};\n"],"names":["useTreeViewNodes","instance","params","nodeMap","React","useRef","getNode","useCallback","nodeId","current","insertNode","node","id","removeNode","newMap","publishTreeViewEvent","isNodeDisabled","disabled","parentId","getChildrenIds","useEventCallback","Object","values","filter","sort","a","b","index","map","child","getNavigableChildrenIds","childrenIds","disabledItemsFocusable","populateInstance","updateNode"],"mappings":";;;;AAkDO,MAAMA,mBAA8DA,CAAC;AAAA,EAC1EC;AAAAA,EACAC;AACF,MAAM;AACJ,QAAMC,UAAUC,MAAMC,OAA2C,CAAE,CAAA;AAE7DC,QAAAA,UAAUF,MAAMG,YACpB,CAACC,WAAmBL,QAAQM,QAAQD,MAAM,GAC1C,CAAA,CACF;AAEA,QAAME,aAAaN,MAAMG,YAAY,CAACI,SAAuB;AACnDF,YAAAA,QAAQE,KAAKC,EAAE,IAAID;AAAAA,EAC7B,GAAG,CAAE,CAAA;AAEL,QAAME,aAAaT,MAAMG,YACvB,CAACC,WAAmB;AAClB,UAAMM,SAAS;AAAA,MAAE,GAAGX,QAAQM;AAAAA,IAAAA;AAC5B,WAAOK,OAAON,MAAM;AACpBL,YAAQM,UAAUK;AAClBC,yBAAqBd,UAAiB,cAAc;AAAA,MAAEW,IAAIJ;AAAAA,IAAAA,CAAQ;AAAA,EAAA,GAEpE,CAACP,QAAQ,CACX;AAEA,QAAMe,iBAAiBZ,MAAMG,YAC3B,CAACC,WAA4C;AAC3C,QAAIA,UAAU,MAAM;AACX,aAAA;AAAA,IACT;AAEIG,QAAAA,OAAOV,SAASK,QAAQE,MAAM;AAGlC,QAAI,CAACG,MAAM;AACF,aAAA;AAAA,IACT;AAEA,QAAIA,KAAKM,UAAU;AACV,aAAA;AAAA,IACT;AAEON,WAAAA,KAAKO,YAAY,MAAM;AACrBjB,aAAAA,SAASK,QAAQK,KAAKO,QAAQ;AACrC,UAAIP,KAAKM,UAAU;AACV,eAAA;AAAA,MACT;AAAA,IACF;AAEO,WAAA;AAAA,EAAA,GAET,CAAChB,QAAQ,CACX;AAEA,QAAMkB,iBAAiBC,iBAAiB,CAACZ,WACvCa,OAAOC,OAAOnB,QAAQM,OAAO,EAC1Bc,OAAQZ,CAASA,SAAAA,KAAKO,aAAaV,MAAM,EACzCgB,KAAK,CAACC,GAAGC,MAAMD,EAAEE,QAAQD,EAAEC,KAAK,EAChCC,IAAKC,CAAAA,UAAUA,MAAMjB,EAAE,CAC5B;AAEMkB,QAAAA,0BAA0BA,CAACtB,WAA0B;AACrDuB,QAAAA,cAAc9B,SAASkB,eAAeX,MAAM;AAE5C,QAAA,CAACN,OAAO8B,wBAAwB;AAClCD,oBAAcA,YAAYR,OACvBZ,CAAAA,SAAS,CAACV,SAASe,eAAeL,IAAI,CACzC;AAAA,IACF;AACOoB,WAAAA;AAAAA,EAAAA;AAGTE,mBAA4ChC,UAAU;AAAA,IACpDK;AAAAA,IACA4B,YAAYxB;AAAAA,IACZG;AAAAA,IACAM;AAAAA,IACAW;AAAAA,IACAd;AAAAA,EAAAA,CACD;AACH;"}
@@ -0,0 +1,213 @@
1
+ import * as React from "react";
2
+ import { populateInstance, getFirstNode, getLastNode, getNextNode } from "../utils.js";
3
+ const findOrderInTremauxTree = (instance, nodeAId, nodeBId) => {
4
+ if (nodeAId === nodeBId) {
5
+ return [nodeAId, nodeBId];
6
+ }
7
+ const nodeA = instance.getNode(nodeAId);
8
+ const nodeB = instance.getNode(nodeBId);
9
+ if (nodeA.parentId === nodeB.id || nodeB.parentId === nodeA.id) {
10
+ return nodeB.parentId === nodeA.id ? [nodeA.id, nodeB.id] : [nodeB.id, nodeA.id];
11
+ }
12
+ const aFamily = [nodeA.id];
13
+ const bFamily = [nodeB.id];
14
+ let aAncestor = nodeA.parentId;
15
+ let bAncestor = nodeB.parentId;
16
+ let aAncestorIsCommon = bFamily.indexOf(aAncestor) !== -1;
17
+ let bAncestorIsCommon = aFamily.indexOf(bAncestor) !== -1;
18
+ let continueA = true;
19
+ let continueB = true;
20
+ while (!bAncestorIsCommon && !aAncestorIsCommon) {
21
+ if (continueA) {
22
+ aFamily.push(aAncestor);
23
+ aAncestorIsCommon = bFamily.indexOf(aAncestor) !== -1;
24
+ continueA = aAncestor !== null;
25
+ if (!aAncestorIsCommon && continueA) {
26
+ aAncestor = instance.getNode(aAncestor).parentId;
27
+ }
28
+ }
29
+ if (continueB && !aAncestorIsCommon) {
30
+ bFamily.push(bAncestor);
31
+ bAncestorIsCommon = aFamily.indexOf(bAncestor) !== -1;
32
+ continueB = bAncestor !== null;
33
+ if (!bAncestorIsCommon && continueB) {
34
+ bAncestor = instance.getNode(bAncestor).parentId;
35
+ }
36
+ }
37
+ }
38
+ const commonAncestor = aAncestorIsCommon ? aAncestor : bAncestor;
39
+ const ancestorFamily = instance.getChildrenIds(commonAncestor);
40
+ const aSide = aFamily[aFamily.indexOf(commonAncestor) - 1];
41
+ const bSide = bFamily[bFamily.indexOf(commonAncestor) - 1];
42
+ return ancestorFamily.indexOf(aSide) < ancestorFamily.indexOf(bSide) ? [nodeAId, nodeBId] : [nodeBId, nodeAId];
43
+ };
44
+ const useTreeViewSelection = ({
45
+ instance,
46
+ params,
47
+ models
48
+ }) => {
49
+ const lastSelectedNode = React.useRef(null);
50
+ const lastSelectionWasRange = React.useRef(false);
51
+ const currentRangeSelection = React.useRef([]);
52
+ const isNodeSelected = (nodeId) => Array.isArray(models.selected.value) ? models.selected.value.indexOf(nodeId) !== -1 : models.selected.value === nodeId;
53
+ const selectNode = (event, nodeId, multiple = false) => {
54
+ if (params.disableSelection) {
55
+ return;
56
+ }
57
+ if (multiple) {
58
+ if (Array.isArray(models.selected.value)) {
59
+ let newSelected;
60
+ if (models.selected.value.indexOf(nodeId) !== -1) {
61
+ newSelected = models.selected.value.filter((id) => id !== nodeId);
62
+ } else {
63
+ newSelected = [nodeId].concat(models.selected.value);
64
+ }
65
+ if (params.onNodeSelect) {
66
+ params.onNodeSelect(event, newSelected);
67
+ }
68
+ models.selected.setValue(newSelected);
69
+ }
70
+ } else {
71
+ const newSelected = params.multiSelect ? [nodeId] : nodeId;
72
+ if (params.onNodeSelect) {
73
+ params.onNodeSelect(event, newSelected);
74
+ }
75
+ models.selected.setValue(newSelected);
76
+ }
77
+ lastSelectedNode.current = nodeId;
78
+ lastSelectionWasRange.current = false;
79
+ currentRangeSelection.current = [];
80
+ };
81
+ const getNodesInRange = (nodeAId, nodeBId) => {
82
+ const [first, last] = findOrderInTremauxTree(instance, nodeAId, nodeBId);
83
+ const nodes = [first];
84
+ let current = first;
85
+ while (current !== last) {
86
+ current = getNextNode(instance, current);
87
+ nodes.push(current);
88
+ }
89
+ return nodes;
90
+ };
91
+ const handleRangeArrowSelect = (event, nodes) => {
92
+ let base = models.selected.value.slice();
93
+ const {
94
+ start,
95
+ next,
96
+ current
97
+ } = nodes;
98
+ if (!next || !current) {
99
+ return;
100
+ }
101
+ if (currentRangeSelection.current.indexOf(current) === -1) {
102
+ currentRangeSelection.current = [];
103
+ }
104
+ if (lastSelectionWasRange.current) {
105
+ if (currentRangeSelection.current.indexOf(next) !== -1) {
106
+ base = base.filter((id) => id === start || id !== current);
107
+ currentRangeSelection.current = currentRangeSelection.current.filter((id) => id === start || id !== current);
108
+ } else {
109
+ base.push(next);
110
+ currentRangeSelection.current.push(next);
111
+ }
112
+ } else {
113
+ base.push(next);
114
+ currentRangeSelection.current.push(current, next);
115
+ }
116
+ if (params.onNodeSelect) {
117
+ params.onNodeSelect(event, base);
118
+ }
119
+ models.selected.setValue(base);
120
+ };
121
+ const handleRangeSelect = (event, nodes) => {
122
+ let base = models.selected.value.slice();
123
+ const {
124
+ start,
125
+ end
126
+ } = nodes;
127
+ if (lastSelectionWasRange.current) {
128
+ base = base.filter((id) => currentRangeSelection.current.indexOf(id) === -1);
129
+ }
130
+ let range = getNodesInRange(start, end);
131
+ range = range.filter((node) => !instance.isNodeDisabled(node));
132
+ currentRangeSelection.current = range;
133
+ let newSelected = base.concat(range);
134
+ newSelected = newSelected.filter((id, i) => newSelected.indexOf(id) === i);
135
+ if (params.onNodeSelect) {
136
+ params.onNodeSelect(event, newSelected);
137
+ }
138
+ models.selected.setValue(newSelected);
139
+ };
140
+ const selectRange = (event, nodes, stacked = false) => {
141
+ if (params.disableSelection) {
142
+ return;
143
+ }
144
+ const {
145
+ start = lastSelectedNode.current,
146
+ end,
147
+ current
148
+ } = nodes;
149
+ if (stacked) {
150
+ handleRangeArrowSelect(event, {
151
+ start,
152
+ next: end,
153
+ current
154
+ });
155
+ } else if (start != null && end != null) {
156
+ handleRangeSelect(event, {
157
+ start,
158
+ end
159
+ });
160
+ }
161
+ lastSelectionWasRange.current = true;
162
+ };
163
+ const rangeSelectToFirst = (event, nodeId) => {
164
+ if (!lastSelectedNode.current) {
165
+ lastSelectedNode.current = nodeId;
166
+ }
167
+ const start = lastSelectionWasRange.current ? lastSelectedNode.current : nodeId;
168
+ instance.selectRange(event, {
169
+ start,
170
+ end: getFirstNode(instance)
171
+ });
172
+ };
173
+ const rangeSelectToLast = (event, nodeId) => {
174
+ if (!lastSelectedNode.current) {
175
+ lastSelectedNode.current = nodeId;
176
+ }
177
+ const start = lastSelectionWasRange.current ? lastSelectedNode.current : nodeId;
178
+ instance.selectRange(event, {
179
+ start,
180
+ end: getLastNode(instance)
181
+ });
182
+ };
183
+ populateInstance(instance, {
184
+ isNodeSelected,
185
+ selectNode,
186
+ selectRange,
187
+ rangeSelectToLast,
188
+ rangeSelectToFirst
189
+ });
190
+ return {
191
+ getRootProps: () => ({
192
+ "aria-multiselectable": params.multiSelect
193
+ })
194
+ };
195
+ };
196
+ useTreeViewSelection.models = {
197
+ selected: {
198
+ controlledProp: "selected",
199
+ defaultProp: "defaultSelected"
200
+ }
201
+ };
202
+ const DEFAULT_SELECTED = [];
203
+ useTreeViewSelection.getDefaultizedParams = (params) => ({
204
+ ...params,
205
+ disableSelection: params.disableSelection ?? false,
206
+ multiSelect: params.multiSelect ?? false,
207
+ defaultSelected: params.defaultSelected ?? (params.multiSelect ? DEFAULT_SELECTED : null)
208
+ });
209
+ export {
210
+ findOrderInTremauxTree,
211
+ useTreeViewSelection
212
+ };
213
+ //# sourceMappingURL=useTreeViewSelection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTreeViewSelection.js","sources":["../../../../../../../src/components/TreeView/internals/hooks/plugins/useTreeViewSelection.ts"],"sourcesContent":["import * as React from \"react\";\n\nimport type {\n TreeViewPlugin,\n TreeViewItemRange,\n DefaultizedProps,\n TreeViewPluginSignature,\n TreeViewInstance,\n} from \"../../types\";\nimport {\n populateInstance,\n getNextNode,\n getFirstNode,\n getLastNode,\n} from \"../utils\";\nimport type { UseTreeViewNodesSignature } from \"./useTreeViewNodes\";\nimport type { UseTreeViewExpansionSignature } from \"./useTreeViewExpansion\";\n\n/**\n * This is used to determine the start and end of a selection range so\n * we can get the nodes between the two border nodes.\n *\n * It finds the nodes' common ancestor using\n * a naive implementation of a lowest common ancestor algorithm\n * (https://en.wikipedia.org/wiki/Lowest_common_ancestor).\n * Then compares the ancestor's 2 children that are ancestors of nodeA and NodeB\n * so we can compare their indexes to work out which node comes first in a depth first search.\n * (https://en.wikipedia.org/wiki/Depth-first_search)\n *\n * Another way to put it is which node is shallower in a trémaux tree\n * https://en.wikipedia.org/wiki/Tr%C3%A9maux_tree\n */\nexport const findOrderInTremauxTree = (\n instance: TreeViewInstance<[UseTreeViewNodesSignature]>,\n nodeAId: string,\n nodeBId: string\n) => {\n if (nodeAId === nodeBId) {\n return [nodeAId, nodeBId];\n }\n\n const nodeA = instance.getNode(nodeAId);\n const nodeB = instance.getNode(nodeBId);\n\n if (nodeA.parentId === nodeB.id || nodeB.parentId === nodeA.id) {\n return nodeB.parentId === nodeA.id\n ? [nodeA.id, nodeB.id]\n : [nodeB.id, nodeA.id];\n }\n\n const aFamily: (string | null)[] = [nodeA.id];\n const bFamily: (string | null)[] = [nodeB.id];\n\n let aAncestor = nodeA.parentId;\n let bAncestor = nodeB.parentId;\n\n let aAncestorIsCommon = bFamily.indexOf(aAncestor) !== -1;\n let bAncestorIsCommon = aFamily.indexOf(bAncestor) !== -1;\n\n let continueA = true;\n let continueB = true;\n\n while (!bAncestorIsCommon && !aAncestorIsCommon) {\n if (continueA) {\n aFamily.push(aAncestor);\n aAncestorIsCommon = bFamily.indexOf(aAncestor) !== -1;\n continueA = aAncestor !== null;\n if (!aAncestorIsCommon && continueA) {\n aAncestor = instance.getNode(aAncestor!).parentId;\n }\n }\n\n if (continueB && !aAncestorIsCommon) {\n bFamily.push(bAncestor);\n bAncestorIsCommon = aFamily.indexOf(bAncestor) !== -1;\n continueB = bAncestor !== null;\n if (!bAncestorIsCommon && continueB) {\n bAncestor = instance.getNode(bAncestor!).parentId;\n }\n }\n }\n\n const commonAncestor = aAncestorIsCommon ? aAncestor : bAncestor;\n const ancestorFamily = instance.getChildrenIds(commonAncestor);\n\n const aSide = aFamily[aFamily.indexOf(commonAncestor) - 1];\n const bSide = bFamily[bFamily.indexOf(commonAncestor) - 1];\n\n return ancestorFamily.indexOf(aSide!) < ancestorFamily.indexOf(bSide!)\n ? [nodeAId, nodeBId]\n : [nodeBId, nodeAId];\n};\n\nexport interface UseTreeViewSelectionInstance {\n isNodeSelected: (nodeId: string) => boolean;\n selectNode: (\n event: React.SyntheticEvent,\n nodeId: string,\n multiple?: boolean\n ) => void;\n selectRange: (\n event: React.SyntheticEvent,\n nodes: TreeViewItemRange,\n stacked?: boolean\n ) => void;\n rangeSelectToFirst: (\n event: React.KeyboardEvent<HTMLUListElement>,\n nodeId: string\n ) => void;\n rangeSelectToLast: (\n event: React.KeyboardEvent<HTMLUListElement>,\n nodeId: string\n ) => void;\n}\n\ntype TreeViewSelectionValue<Multiple extends boolean | undefined> =\n Multiple extends true ? string[] : string | null;\n\nexport interface UseTreeViewSelectionParameters<\n Multiple extends boolean | undefined\n> {\n /**\n * If `true` selection is disabled.\n * @default false\n */\n disableSelection?: boolean;\n /**\n * Selected node ids. (Uncontrolled)\n * When `multiSelect` is true this takes an array of strings; when false (default) a string.\n * @default []\n */\n defaultSelected?: TreeViewSelectionValue<Multiple>;\n /**\n * Selected node ids. (Controlled)\n * When `multiSelect` is true this takes an array of strings; when false (default) a string.\n */\n selected?: TreeViewSelectionValue<Multiple>;\n /**\n * If true `ctrl` and `shift` will trigger multiselect.\n * @default false\n */\n multiSelect?: Multiple;\n /**\n * Callback fired when tree items are selected/unselected.\n * @param {React.SyntheticEvent} event The event source of the callback\n * @param {string[] | string} nodeIds Ids of the selected nodes. When `multiSelect` is true\n * this is an array of strings; when false (default) a string.\n */\n onNodeSelect?: (\n event: React.SyntheticEvent,\n nodeIds: Exclude<TreeViewSelectionValue<Multiple>, null>\n ) => void;\n}\n\nexport type UseTreeViewSelectionDefaultizedParameters<\n Multiple extends boolean\n> = DefaultizedProps<\n UseTreeViewSelectionParameters<Multiple>,\n \"disableSelection\" | \"defaultSelected\" | \"multiSelect\"\n>;\n\nexport type UseTreeViewSelectionSignature<\n Multiple extends boolean | undefined\n> = TreeViewPluginSignature<\n UseTreeViewSelectionParameters<Multiple>,\n UseTreeViewSelectionDefaultizedParameters<\n Multiple extends undefined ? false : Multiple\n >,\n UseTreeViewSelectionInstance,\n {},\n {},\n \"selected\",\n [\n UseTreeViewNodesSignature,\n UseTreeViewExpansionSignature,\n UseTreeViewNodesSignature\n ]\n>;\n\nexport const useTreeViewSelection: TreeViewPlugin<\n UseTreeViewSelectionSignature<any>\n> = ({ instance, params, models }) => {\n const lastSelectedNode = React.useRef<string | null>(null);\n const lastSelectionWasRange = React.useRef(false);\n const currentRangeSelection = React.useRef<string[]>([]);\n\n const isNodeSelected = (nodeId: string) =>\n Array.isArray(models.selected.value)\n ? models.selected.value.indexOf(nodeId) !== -1\n : models.selected.value === nodeId;\n\n const selectNode = (\n event: React.SyntheticEvent,\n nodeId: string,\n multiple = false\n ) => {\n if (params.disableSelection) {\n return;\n }\n\n if (multiple) {\n if (Array.isArray(models.selected.value)) {\n let newSelected: string[];\n if (models.selected.value.indexOf(nodeId) !== -1) {\n newSelected = models.selected.value.filter((id) => id !== nodeId);\n } else {\n newSelected = [nodeId].concat(models.selected.value);\n }\n\n if (params.onNodeSelect) {\n (params.onNodeSelect as UseTreeViewSelectionDefaultizedParameters<true>[\"onNodeSelect\"])!(\n event,\n newSelected\n );\n }\n\n models.selected.setValue(newSelected);\n }\n } else {\n const newSelected = params.multiSelect ? [nodeId] : nodeId;\n\n if (params.onNodeSelect) {\n params.onNodeSelect(event, newSelected as string & string[]);\n }\n\n models.selected.setValue(newSelected);\n }\n lastSelectedNode.current = nodeId;\n lastSelectionWasRange.current = false;\n currentRangeSelection.current = [];\n };\n\n const getNodesInRange = (nodeAId: string, nodeBId: string) => {\n const [first, last] = findOrderInTremauxTree(instance, nodeAId, nodeBId);\n const nodes = [first];\n\n let current = first;\n\n while (current !== last) {\n current = getNextNode(instance, current)!;\n nodes.push(current);\n }\n\n return nodes;\n };\n\n const handleRangeArrowSelect = (\n event: React.SyntheticEvent,\n nodes: TreeViewItemRange\n ) => {\n let base = (models.selected.value as string[]).slice();\n const { start, next, current } = nodes;\n\n if (!next || !current) {\n return;\n }\n\n if (currentRangeSelection.current.indexOf(current) === -1) {\n currentRangeSelection.current = [];\n }\n\n if (lastSelectionWasRange.current) {\n if (currentRangeSelection.current.indexOf(next) !== -1) {\n base = base.filter((id) => id === start || id !== current);\n currentRangeSelection.current = currentRangeSelection.current.filter(\n (id) => id === start || id !== current\n );\n } else {\n base.push(next);\n currentRangeSelection.current.push(next);\n }\n } else {\n base.push(next);\n currentRangeSelection.current.push(current, next);\n }\n\n if (params.onNodeSelect) {\n (params.onNodeSelect as UseTreeViewSelectionDefaultizedParameters<true>[\"onNodeSelect\"])!(\n event,\n base\n );\n }\n\n models.selected.setValue(base);\n };\n\n const handleRangeSelect = (\n event: React.SyntheticEvent,\n nodes: { start: string; end: string }\n ) => {\n let base = (models.selected.value as string[]).slice();\n const { start, end } = nodes;\n // If last selection was a range selection ignore nodes that were selected.\n if (lastSelectionWasRange.current) {\n base = base.filter(\n (id) => currentRangeSelection.current.indexOf(id) === -1\n );\n }\n\n let range = getNodesInRange(start, end);\n range = range.filter((node) => !instance.isNodeDisabled(node));\n currentRangeSelection.current = range;\n let newSelected = base.concat(range);\n newSelected = newSelected.filter((id, i) => newSelected.indexOf(id) === i);\n\n if (params.onNodeSelect) {\n (params.onNodeSelect as UseTreeViewSelectionDefaultizedParameters<true>[\"onNodeSelect\"])!(\n event,\n newSelected\n );\n }\n\n models.selected.setValue(newSelected);\n };\n\n const selectRange = (\n event: React.SyntheticEvent,\n nodes: TreeViewItemRange,\n stacked = false\n ) => {\n if (params.disableSelection) {\n return;\n }\n\n const { start = lastSelectedNode.current, end, current } = nodes;\n if (stacked) {\n handleRangeArrowSelect(event, { start, next: end, current });\n } else if (start != null && end != null) {\n handleRangeSelect(event, { start, end });\n }\n lastSelectionWasRange.current = true;\n };\n\n const rangeSelectToFirst = (\n event: React.KeyboardEvent<HTMLUListElement>,\n nodeId: string\n ) => {\n if (!lastSelectedNode.current) {\n lastSelectedNode.current = nodeId;\n }\n\n const start = lastSelectionWasRange.current\n ? lastSelectedNode.current\n : nodeId;\n\n instance.selectRange(event, {\n start,\n end: getFirstNode(instance),\n });\n };\n\n const rangeSelectToLast = (\n event: React.KeyboardEvent<HTMLUListElement>,\n nodeId: string\n ) => {\n if (!lastSelectedNode.current) {\n lastSelectedNode.current = nodeId;\n }\n\n const start = lastSelectionWasRange.current\n ? lastSelectedNode.current\n : nodeId;\n\n instance.selectRange(event, {\n start,\n end: getLastNode(instance),\n });\n };\n\n populateInstance<UseTreeViewSelectionSignature<any>>(instance, {\n isNodeSelected,\n selectNode,\n selectRange,\n rangeSelectToLast,\n rangeSelectToFirst,\n });\n\n return {\n getRootProps: () => ({\n \"aria-multiselectable\": params.multiSelect,\n }),\n };\n};\n\nuseTreeViewSelection.models = {\n selected: { controlledProp: \"selected\", defaultProp: \"defaultSelected\" },\n};\n\nconst DEFAULT_SELECTED: string[] = [];\n\nuseTreeViewSelection.getDefaultizedParams = (params) => ({\n ...params,\n disableSelection: params.disableSelection ?? false,\n multiSelect: params.multiSelect ?? false,\n defaultSelected:\n params.defaultSelected ?? (params.multiSelect ? DEFAULT_SELECTED : null),\n});\n"],"names":["findOrderInTremauxTree","instance","nodeAId","nodeBId","nodeA","getNode","nodeB","parentId","id","aFamily","bFamily","aAncestor","bAncestor","aAncestorIsCommon","indexOf","bAncestorIsCommon","continueA","continueB","push","commonAncestor","ancestorFamily","getChildrenIds","aSide","bSide","useTreeViewSelection","params","models","lastSelectedNode","React","useRef","lastSelectionWasRange","currentRangeSelection","isNodeSelected","nodeId","Array","isArray","selected","value","selectNode","event","multiple","disableSelection","newSelected","filter","concat","onNodeSelect","setValue","multiSelect","current","getNodesInRange","first","last","nodes","getNextNode","handleRangeArrowSelect","base","slice","start","next","handleRangeSelect","end","range","node","isNodeDisabled","i","selectRange","stacked","rangeSelectToFirst","getFirstNode","rangeSelectToLast","getLastNode","populateInstance","getRootProps","controlledProp","defaultProp","DEFAULT_SELECTED","getDefaultizedParams","defaultSelected"],"mappings":"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"}
@@ -0,0 +1,74 @@
1
+ import * as React from "react";
2
+ import { TimerBasedCleanupTracking } from "../utils/TimerBasedCleanupTracking.js";
3
+ import { FinalizationRegistryBasedCleanupTracking } from "../utils/FinalizationRegistryBasedCleanupTracking.js";
4
+ class ObjectToBeRetainedByReact {
5
+ }
6
+ function createUseInstanceEventHandler(registryContainer2) {
7
+ let cleanupTokensCounter = 0;
8
+ return function useInstanceEventHandler2(instance, eventName, handler) {
9
+ if (registryContainer2.registry === null) {
10
+ registryContainer2.registry = typeof FinalizationRegistry !== "undefined" ? new FinalizationRegistryBasedCleanupTracking() : new TimerBasedCleanupTracking();
11
+ }
12
+ const [objectRetainedByReact] = React.useState(new ObjectToBeRetainedByReact());
13
+ const subscription = React.useRef(null);
14
+ const handlerRef = React.useRef();
15
+ handlerRef.current = handler;
16
+ const cleanupTokenRef = React.useRef(null);
17
+ if (!subscription.current && handlerRef.current) {
18
+ const enhancedHandler = (params, event) => {
19
+ if (!event.defaultMuiPrevented) {
20
+ handlerRef.current?.(params, event);
21
+ }
22
+ };
23
+ subscription.current = instance.$$subscribeEvent(eventName, enhancedHandler);
24
+ cleanupTokensCounter += 1;
25
+ cleanupTokenRef.current = {
26
+ cleanupToken: cleanupTokensCounter
27
+ };
28
+ registryContainer2.registry.register(
29
+ objectRetainedByReact,
30
+ // The callback below will be called once this reference stops being retained
31
+ () => {
32
+ subscription.current?.();
33
+ subscription.current = null;
34
+ cleanupTokenRef.current = null;
35
+ },
36
+ cleanupTokenRef.current
37
+ );
38
+ } else if (!handlerRef.current && subscription.current) {
39
+ subscription.current();
40
+ subscription.current = null;
41
+ if (cleanupTokenRef.current) {
42
+ registryContainer2.registry.unregister(cleanupTokenRef.current);
43
+ cleanupTokenRef.current = null;
44
+ }
45
+ }
46
+ React.useEffect(() => {
47
+ if (!subscription.current && handlerRef.current) {
48
+ const enhancedHandler = (params, event) => {
49
+ if (!event.defaultMuiPrevented) {
50
+ handlerRef.current?.(params, event);
51
+ }
52
+ };
53
+ subscription.current = instance.$$subscribeEvent(eventName, enhancedHandler);
54
+ }
55
+ if (cleanupTokenRef.current && registryContainer2.registry) {
56
+ registryContainer2.registry.unregister(cleanupTokenRef.current);
57
+ cleanupTokenRef.current = null;
58
+ }
59
+ return () => {
60
+ subscription.current?.();
61
+ subscription.current = null;
62
+ };
63
+ }, [instance, eventName]);
64
+ };
65
+ }
66
+ const registryContainer = {
67
+ registry: null
68
+ };
69
+ const useInstanceEventHandler = createUseInstanceEventHandler(registryContainer);
70
+ export {
71
+ createUseInstanceEventHandler,
72
+ useInstanceEventHandler
73
+ };
74
+ //# sourceMappingURL=useInstanceEventHandler.js.map