@mui/x-tree-view 7.0.0-beta.6 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +311 -12
- package/README.md +1 -1
- package/RichTreeView/RichTreeView.js +34 -36
- package/RichTreeView/RichTreeView.types.d.ts +3 -2
- package/SimpleTreeView/SimpleTreeView.js +25 -26
- package/TreeItem/TreeItem.js +94 -82
- package/TreeItem/TreeItem.types.d.ts +13 -11
- package/TreeItem/TreeItemContent.d.ts +7 -7
- package/TreeItem/TreeItemContent.js +10 -10
- package/TreeItem/useTreeItemState.d.ts +1 -1
- package/TreeItem/useTreeItemState.js +13 -13
- package/TreeItem2/TreeItem2.d.ts +18 -0
- package/TreeItem2/TreeItem2.js +300 -0
- package/TreeItem2/TreeItem2.types.d.ts +64 -0
- package/TreeItem2/TreeItem2.types.js +1 -0
- package/TreeItem2/index.d.ts +2 -0
- package/TreeItem2/index.js +1 -0
- package/TreeItem2/package.json +6 -0
- package/TreeItem2Icon/TreeItem2Icon.d.ts +7 -0
- package/TreeItem2Icon/TreeItem2Icon.js +67 -0
- package/TreeItem2Icon/TreeItem2Icon.types.d.ts +40 -0
- package/TreeItem2Icon/TreeItem2Icon.types.js +1 -0
- package/TreeItem2Icon/index.d.ts +2 -0
- package/TreeItem2Icon/index.js +1 -0
- package/TreeItem2Icon/package.json +6 -0
- package/TreeItem2Provider/TreeItem2Provider.d.ts +7 -0
- package/TreeItem2Provider/TreeItem2Provider.js +24 -0
- package/TreeItem2Provider/TreeItem2Provider.types.d.ts +6 -0
- package/TreeItem2Provider/TreeItem2Provider.types.js +1 -0
- package/TreeItem2Provider/index.d.ts +2 -0
- package/TreeItem2Provider/index.js +1 -0
- package/TreeItem2Provider/package.json +6 -0
- package/TreeView/TreeView.d.ts +1 -1
- package/TreeView/TreeView.js +23 -23
- package/hooks/index.d.ts +1 -0
- package/hooks/index.js +2 -1
- package/hooks/useTreeItem2Utils/index.d.ts +1 -0
- package/hooks/useTreeItem2Utils/index.js +1 -0
- package/hooks/useTreeItem2Utils/useTreeItem2Utils.d.ts +15 -0
- package/hooks/useTreeItem2Utils/useTreeItem2Utils.js +61 -0
- package/index.d.ts +5 -1
- package/index.js +9 -2
- package/internals/TreeViewProvider/TreeViewContext.d.ts +3 -1
- package/internals/TreeViewProvider/TreeViewProvider.types.d.ts +4 -2
- package/internals/hooks/useInstanceEventHandler.js +5 -10
- package/internals/hooks/useLazyRef.d.ts +1 -2
- package/internals/hooks/useLazyRef.js +1 -11
- package/internals/hooks/useOnMount.d.ts +1 -2
- package/internals/hooks/useOnMount.js +1 -7
- package/internals/hooks/useTimeout.d.ts +1 -11
- package/internals/hooks/useTimeout.js +1 -36
- package/internals/models/plugin.d.ts +19 -16
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +31 -38
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +14 -14
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +67 -51
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +9 -8
- package/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
- package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +1 -1
- package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +30 -31
- package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.types.d.ts +2 -2
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +75 -80
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +4 -1
- package/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +26 -31
- package/internals/plugins/useTreeViewNodes/useTreeViewNodes.types.d.ts +11 -11
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +47 -50
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +15 -15
- package/internals/useTreeView/useTreeView.js +28 -27
- package/internals/useTreeView/useTreeView.utils.d.ts +2 -2
- package/internals/useTreeView/useTreeView.utils.js +22 -22
- package/internals/utils/extractPluginParamsFromProps.js +2 -2
- package/internals/utils/utils.js +1 -0
- package/modern/RichTreeView/RichTreeView.js +29 -29
- package/modern/SimpleTreeView/SimpleTreeView.js +23 -23
- package/modern/TreeItem/TreeItem.js +83 -70
- package/modern/TreeItem/TreeItemContent.js +10 -10
- package/modern/TreeItem/useTreeItemState.js +13 -13
- package/modern/TreeItem2/TreeItem2.js +300 -0
- package/modern/TreeItem2/TreeItem2.types.js +1 -0
- package/modern/TreeItem2/index.js +1 -0
- package/modern/TreeItem2Icon/TreeItem2Icon.js +67 -0
- package/modern/TreeItem2Icon/TreeItem2Icon.types.js +1 -0
- package/modern/TreeItem2Icon/index.js +1 -0
- package/modern/TreeItem2Provider/TreeItem2Provider.js +24 -0
- package/modern/TreeItem2Provider/TreeItem2Provider.types.js +1 -0
- package/modern/TreeItem2Provider/index.js +1 -0
- package/modern/TreeView/TreeView.js +23 -23
- package/modern/hooks/index.js +2 -1
- package/modern/hooks/useTreeItem2Utils/index.js +1 -0
- package/modern/hooks/useTreeItem2Utils/useTreeItem2Utils.js +61 -0
- package/modern/index.js +9 -2
- package/modern/internals/hooks/useLazyRef.js +1 -11
- package/modern/internals/hooks/useOnMount.js +1 -7
- package/modern/internals/hooks/useTimeout.js +1 -36
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +29 -29
- package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +65 -46
- package/modern/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
- package/modern/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +30 -30
- package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +74 -77
- package/modern/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +21 -22
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +43 -43
- package/modern/internals/useTreeView/useTreeView.js +28 -27
- package/modern/internals/useTreeView/useTreeView.utils.js +22 -22
- package/modern/internals/utils/utils.js +1 -0
- package/modern/useTreeItem2/index.js +1 -0
- package/modern/useTreeItem2/useTreeItem2.js +146 -0
- package/modern/useTreeItem2/useTreeItem2.types.js +1 -0
- package/node/RichTreeView/RichTreeView.js +29 -29
- package/node/SimpleTreeView/SimpleTreeView.js +23 -23
- package/node/TreeItem/TreeItem.js +83 -70
- package/node/TreeItem/TreeItemContent.js +10 -10
- package/node/TreeItem/useTreeItemState.js +13 -13
- package/node/TreeItem2/TreeItem2.js +308 -0
- package/node/TreeItem2/TreeItem2.types.js +5 -0
- package/node/TreeItem2/index.js +42 -0
- package/node/TreeItem2Icon/TreeItem2Icon.js +75 -0
- package/node/TreeItem2Icon/TreeItem2Icon.types.js +5 -0
- package/node/TreeItem2Icon/index.js +12 -0
- package/node/TreeItem2Provider/TreeItem2Provider.js +30 -0
- package/node/TreeItem2Provider/TreeItem2Provider.types.js +5 -0
- package/node/TreeItem2Provider/index.js +12 -0
- package/node/TreeView/TreeView.js +23 -23
- package/node/hooks/index.js +8 -1
- package/node/hooks/useTreeItem2Utils/index.js +12 -0
- package/node/hooks/useTreeItem2Utils/useTreeItem2Utils.js +68 -0
- package/node/index.js +61 -13
- package/node/internals/hooks/useLazyRef.js +7 -13
- package/node/internals/hooks/useOnMount.js +8 -10
- package/node/internals/hooks/useTimeout.js +7 -37
- package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +29 -29
- package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +65 -46
- package/node/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
- package/node/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +30 -30
- package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +74 -77
- package/node/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +21 -22
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +43 -43
- package/node/internals/useTreeView/useTreeView.js +28 -27
- package/node/internals/useTreeView/useTreeView.utils.js +22 -22
- package/node/internals/utils/utils.js +1 -0
- package/node/useTreeItem2/index.js +12 -0
- package/node/useTreeItem2/useTreeItem2.js +154 -0
- package/node/useTreeItem2/useTreeItem2.types.js +5 -0
- package/package.json +5 -5
- package/themeAugmentation/components.d.ts +5 -0
- package/themeAugmentation/overrides.d.ts +1 -0
- package/themeAugmentation/props.d.ts +2 -0
- package/useTreeItem2/index.d.ts +2 -0
- package/useTreeItem2/index.js +1 -0
- package/useTreeItem2/package.json +6 -0
- package/useTreeItem2/useTreeItem2.d.ts +2 -0
- package/useTreeItem2/useTreeItem2.js +146 -0
- package/useTreeItem2/useTreeItem2.types.d.ts +115 -0
- package/useTreeItem2/useTreeItem2.types.js +1 -0
package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js
CHANGED
|
@@ -24,8 +24,7 @@ function findNextFirstChar(firstChars, startIndex, char) {
|
|
|
24
24
|
}
|
|
25
25
|
const useTreeViewKeyboardNavigation = ({
|
|
26
26
|
instance,
|
|
27
|
-
params
|
|
28
|
-
state
|
|
27
|
+
params
|
|
29
28
|
}) => {
|
|
30
29
|
const theme = (0, _styles.useTheme)();
|
|
31
30
|
const isRTL = theme.direction === 'rtl';
|
|
@@ -42,35 +41,32 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
42
41
|
const newFirstCharMap = {};
|
|
43
42
|
const processItem = item => {
|
|
44
43
|
const getItemId = params.getItemId;
|
|
45
|
-
const
|
|
46
|
-
newFirstCharMap[
|
|
44
|
+
const itemId = getItemId ? getItemId(item) : item.id;
|
|
45
|
+
newFirstCharMap[itemId] = instance.getNode(itemId).label.substring(0, 1).toLowerCase();
|
|
47
46
|
item.children?.forEach(processItem);
|
|
48
47
|
};
|
|
49
48
|
params.items.forEach(processItem);
|
|
50
49
|
firstCharMap.current = newFirstCharMap;
|
|
51
50
|
}, [params.items, params.getItemId, instance]);
|
|
52
|
-
(
|
|
53
|
-
updateFirstCharMap
|
|
54
|
-
});
|
|
55
|
-
const getFirstMatchingNode = (nodeId, firstChar) => {
|
|
51
|
+
const getFirstMatchingItem = (itemId, firstChar) => {
|
|
56
52
|
let start;
|
|
57
53
|
let index;
|
|
58
54
|
const lowercaseChar = firstChar.toLowerCase();
|
|
59
55
|
const firstCharIds = [];
|
|
60
56
|
const firstChars = [];
|
|
61
57
|
// This really only works since the ids are strings
|
|
62
|
-
Object.keys(firstCharMap.current).forEach(
|
|
63
|
-
const map = instance.getNode(
|
|
58
|
+
Object.keys(firstCharMap.current).forEach(mapItemId => {
|
|
59
|
+
const map = instance.getNode(mapItemId);
|
|
64
60
|
const visible = map.parentId ? instance.isNodeExpanded(map.parentId) : true;
|
|
65
|
-
const shouldBeSkipped = params.disabledItemsFocusable ? false : instance.isNodeDisabled(
|
|
61
|
+
const shouldBeSkipped = params.disabledItemsFocusable ? false : instance.isNodeDisabled(mapItemId);
|
|
66
62
|
if (visible && !shouldBeSkipped) {
|
|
67
|
-
firstCharIds.push(
|
|
68
|
-
firstChars.push(firstCharMap.current[
|
|
63
|
+
firstCharIds.push(mapItemId);
|
|
64
|
+
firstChars.push(firstCharMap.current[mapItemId]);
|
|
69
65
|
}
|
|
70
66
|
});
|
|
71
67
|
|
|
72
68
|
// Get start index for search based on position of currentItem
|
|
73
|
-
start = firstCharIds.indexOf(
|
|
69
|
+
start = firstCharIds.indexOf(itemId) + 1;
|
|
74
70
|
if (start >= firstCharIds.length) {
|
|
75
71
|
start = 0;
|
|
76
72
|
}
|
|
@@ -89,18 +85,17 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
89
85
|
}
|
|
90
86
|
return null;
|
|
91
87
|
};
|
|
92
|
-
const
|
|
93
|
-
const
|
|
88
|
+
const canToggleItemSelection = itemId => !params.disableSelection && !instance.isNodeDisabled(itemId);
|
|
89
|
+
const canToggleItemExpansion = itemId => {
|
|
90
|
+
return !instance.isNodeDisabled(itemId) && instance.isNodeExpandable(itemId);
|
|
91
|
+
};
|
|
94
92
|
|
|
95
93
|
// ARIA specification: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/#keyboardinteraction
|
|
96
|
-
const
|
|
97
|
-
otherHandlers.onKeyDown?.(event);
|
|
94
|
+
const handleItemKeyDown = (event, itemId) => {
|
|
98
95
|
if (event.defaultMuiPrevented) {
|
|
99
96
|
return;
|
|
100
97
|
}
|
|
101
|
-
|
|
102
|
-
// If the tree is empty there will be no focused node
|
|
103
|
-
if (event.altKey || event.currentTarget !== event.target || state.focusedNodeId == null) {
|
|
98
|
+
if (event.altKey || event.currentTarget !== event.target) {
|
|
104
99
|
return;
|
|
105
100
|
}
|
|
106
101
|
const ctrlPressed = event.ctrlKey || event.metaKey;
|
|
@@ -109,17 +104,17 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
109
104
|
// eslint-disable-next-line default-case
|
|
110
105
|
switch (true) {
|
|
111
106
|
// Select the node when pressing "Space"
|
|
112
|
-
case key === ' ' &&
|
|
107
|
+
case key === ' ' && canToggleItemSelection(itemId):
|
|
113
108
|
{
|
|
114
109
|
event.preventDefault();
|
|
115
110
|
if (params.multiSelect && event.shiftKey) {
|
|
116
111
|
instance.selectRange(event, {
|
|
117
|
-
end:
|
|
112
|
+
end: itemId
|
|
118
113
|
});
|
|
119
114
|
} else if (params.multiSelect) {
|
|
120
|
-
instance.selectNode(event,
|
|
115
|
+
instance.selectNode(event, itemId, true);
|
|
121
116
|
} else {
|
|
122
|
-
instance.selectNode(event,
|
|
117
|
+
instance.selectNode(event, itemId);
|
|
123
118
|
}
|
|
124
119
|
break;
|
|
125
120
|
}
|
|
@@ -128,86 +123,89 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
128
123
|
// If the focused node has no children, we select it.
|
|
129
124
|
case key === 'Enter':
|
|
130
125
|
{
|
|
131
|
-
if (
|
|
132
|
-
instance.toggleNodeExpansion(event,
|
|
126
|
+
if (canToggleItemExpansion(itemId)) {
|
|
127
|
+
instance.toggleNodeExpansion(event, itemId);
|
|
133
128
|
event.preventDefault();
|
|
134
|
-
} else if (
|
|
129
|
+
} else if (canToggleItemSelection(itemId)) {
|
|
135
130
|
if (params.multiSelect) {
|
|
136
131
|
event.preventDefault();
|
|
137
|
-
instance.selectNode(event,
|
|
138
|
-
} else if (!instance.isNodeSelected(
|
|
139
|
-
instance.selectNode(event,
|
|
132
|
+
instance.selectNode(event, itemId, true);
|
|
133
|
+
} else if (!instance.isNodeSelected(itemId)) {
|
|
134
|
+
instance.selectNode(event, itemId);
|
|
140
135
|
event.preventDefault();
|
|
141
136
|
}
|
|
142
137
|
}
|
|
143
138
|
break;
|
|
144
139
|
}
|
|
145
140
|
|
|
146
|
-
// Focus the next focusable
|
|
141
|
+
// Focus the next focusable item
|
|
147
142
|
case key === 'ArrowDown':
|
|
148
143
|
{
|
|
149
|
-
const
|
|
150
|
-
if (
|
|
144
|
+
const nextItem = (0, _useTreeView.getNextNode)(instance, itemId);
|
|
145
|
+
if (nextItem) {
|
|
151
146
|
event.preventDefault();
|
|
152
|
-
instance.
|
|
147
|
+
instance.focusItem(event, nextItem);
|
|
153
148
|
|
|
154
149
|
// Multi select behavior when pressing Shift + ArrowDown
|
|
155
|
-
// Toggles the selection state of the next
|
|
156
|
-
if (params.multiSelect && event.shiftKey &&
|
|
150
|
+
// Toggles the selection state of the next item
|
|
151
|
+
if (params.multiSelect && event.shiftKey && canToggleItemSelection(nextItem)) {
|
|
157
152
|
instance.selectRange(event, {
|
|
158
|
-
end:
|
|
159
|
-
current:
|
|
153
|
+
end: nextItem,
|
|
154
|
+
current: itemId
|
|
160
155
|
}, true);
|
|
161
156
|
}
|
|
162
157
|
}
|
|
163
158
|
break;
|
|
164
159
|
}
|
|
165
160
|
|
|
166
|
-
// Focuses the previous focusable
|
|
161
|
+
// Focuses the previous focusable item
|
|
167
162
|
case key === 'ArrowUp':
|
|
168
163
|
{
|
|
169
|
-
const
|
|
170
|
-
if (
|
|
164
|
+
const previousItem = (0, _useTreeView.getPreviousNode)(instance, itemId);
|
|
165
|
+
if (previousItem) {
|
|
171
166
|
event.preventDefault();
|
|
172
|
-
instance.
|
|
167
|
+
instance.focusItem(event, previousItem);
|
|
173
168
|
|
|
174
169
|
// Multi select behavior when pressing Shift + ArrowUp
|
|
175
|
-
// Toggles the selection state of the previous
|
|
176
|
-
if (params.multiSelect && event.shiftKey &&
|
|
170
|
+
// Toggles the selection state of the previous item
|
|
171
|
+
if (params.multiSelect && event.shiftKey && canToggleItemSelection(previousItem)) {
|
|
177
172
|
instance.selectRange(event, {
|
|
178
|
-
end:
|
|
179
|
-
current:
|
|
173
|
+
end: previousItem,
|
|
174
|
+
current: itemId
|
|
180
175
|
}, true);
|
|
181
176
|
}
|
|
182
177
|
}
|
|
183
178
|
break;
|
|
184
179
|
}
|
|
185
180
|
|
|
186
|
-
// If the focused
|
|
187
|
-
// If the focused
|
|
181
|
+
// If the focused item is expanded, we move the focus to its first child
|
|
182
|
+
// If the focused item is collapsed and has children, we expand it
|
|
188
183
|
case key === 'ArrowRight' && !isRTL || key === 'ArrowLeft' && isRTL:
|
|
189
184
|
{
|
|
190
|
-
if (instance.isNodeExpanded(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
185
|
+
if (instance.isNodeExpanded(itemId)) {
|
|
186
|
+
const nextNodeId = (0, _useTreeView.getNextNode)(instance, itemId);
|
|
187
|
+
if (nextNodeId) {
|
|
188
|
+
instance.focusItem(event, nextNodeId);
|
|
189
|
+
event.preventDefault();
|
|
190
|
+
}
|
|
191
|
+
} else if (canToggleItemExpansion(itemId)) {
|
|
192
|
+
instance.toggleNodeExpansion(event, itemId);
|
|
195
193
|
event.preventDefault();
|
|
196
194
|
}
|
|
197
195
|
break;
|
|
198
196
|
}
|
|
199
197
|
|
|
200
|
-
// If the focused
|
|
201
|
-
// If the focused
|
|
198
|
+
// If the focused item is expanded, we collapse it
|
|
199
|
+
// If the focused item is collapsed and has a parent, we move the focus to this parent
|
|
202
200
|
case key === 'ArrowLeft' && !isRTL || key === 'ArrowRight' && isRTL:
|
|
203
201
|
{
|
|
204
|
-
if (
|
|
205
|
-
instance.toggleNodeExpansion(event,
|
|
202
|
+
if (canToggleItemExpansion(itemId) && instance.isNodeExpanded(itemId)) {
|
|
203
|
+
instance.toggleNodeExpansion(event, itemId);
|
|
206
204
|
event.preventDefault();
|
|
207
205
|
} else {
|
|
208
|
-
const parent = instance.getNode(
|
|
206
|
+
const parent = instance.getNode(itemId).parentId;
|
|
209
207
|
if (parent) {
|
|
210
|
-
instance.
|
|
208
|
+
instance.focusItem(event, parent);
|
|
211
209
|
event.preventDefault();
|
|
212
210
|
}
|
|
213
211
|
}
|
|
@@ -217,35 +215,35 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
217
215
|
// Focuses the first node in the tree
|
|
218
216
|
case key === 'Home':
|
|
219
217
|
{
|
|
220
|
-
instance.
|
|
218
|
+
instance.focusItem(event, (0, _useTreeView.getFirstNode)(instance));
|
|
221
219
|
|
|
222
220
|
// Multi select behavior when pressing Ctrl + Shift + Home
|
|
223
221
|
// Selects the focused node and all nodes up to the first node.
|
|
224
|
-
if (
|
|
225
|
-
instance.rangeSelectToFirst(event,
|
|
222
|
+
if (canToggleItemSelection(itemId) && params.multiSelect && ctrlPressed && event.shiftKey) {
|
|
223
|
+
instance.rangeSelectToFirst(event, itemId);
|
|
226
224
|
}
|
|
227
225
|
event.preventDefault();
|
|
228
226
|
break;
|
|
229
227
|
}
|
|
230
228
|
|
|
231
|
-
// Focuses the last
|
|
229
|
+
// Focuses the last item in the tree
|
|
232
230
|
case key === 'End':
|
|
233
231
|
{
|
|
234
|
-
instance.
|
|
232
|
+
instance.focusItem(event, (0, _useTreeView.getLastNode)(instance));
|
|
235
233
|
|
|
236
234
|
// Multi select behavior when pressing Ctrl + Shirt + End
|
|
237
|
-
// Selects the focused
|
|
238
|
-
if (
|
|
239
|
-
instance.rangeSelectToLast(event,
|
|
235
|
+
// Selects the focused item and all the items down to the last item.
|
|
236
|
+
if (canToggleItemSelection(itemId) && params.multiSelect && ctrlPressed && event.shiftKey) {
|
|
237
|
+
instance.rangeSelectToLast(event, itemId);
|
|
240
238
|
}
|
|
241
239
|
event.preventDefault();
|
|
242
240
|
break;
|
|
243
241
|
}
|
|
244
242
|
|
|
245
|
-
// Expand all siblings that are at the same level as the focused
|
|
243
|
+
// Expand all siblings that are at the same level as the focused item
|
|
246
244
|
case key === '*':
|
|
247
245
|
{
|
|
248
|
-
instance.expandAllSiblings(event,
|
|
246
|
+
instance.expandAllSiblings(event, itemId);
|
|
249
247
|
event.preventDefault();
|
|
250
248
|
break;
|
|
251
249
|
}
|
|
@@ -266,20 +264,19 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
266
264
|
// TODO: Support typing multiple characters
|
|
267
265
|
case !ctrlPressed && !event.shiftKey && isPrintableCharacter(key):
|
|
268
266
|
{
|
|
269
|
-
const matchingNode =
|
|
267
|
+
const matchingNode = getFirstMatchingItem(itemId, key);
|
|
270
268
|
if (matchingNode != null) {
|
|
271
|
-
instance.
|
|
269
|
+
instance.focusItem(event, matchingNode);
|
|
272
270
|
event.preventDefault();
|
|
273
271
|
}
|
|
274
272
|
break;
|
|
275
273
|
}
|
|
276
274
|
}
|
|
277
275
|
};
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
};
|
|
276
|
+
(0, _useTreeView.populateInstance)(instance, {
|
|
277
|
+
updateFirstCharMap,
|
|
278
|
+
handleItemKeyDown
|
|
279
|
+
});
|
|
283
280
|
};
|
|
284
281
|
exports.useTreeViewKeyboardNavigation = useTreeViewKeyboardNavigation;
|
|
285
282
|
useTreeViewKeyboardNavigation.params = {};
|
|
@@ -7,7 +7,6 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.useTreeViewNodes = void 0;
|
|
8
8
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
9
9
|
var React = _interopRequireWildcard(require("react"));
|
|
10
|
-
var _useEventCallback = _interopRequireDefault(require("@mui/utils/useEventCallback"));
|
|
11
10
|
var _useTreeView = require("../../useTreeView/useTreeView.utils");
|
|
12
11
|
var _publishTreeViewEvent = require("../../utils/publishTreeViewEvent");
|
|
13
12
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
@@ -61,34 +60,34 @@ const useTreeViewNodes = ({
|
|
|
61
60
|
state,
|
|
62
61
|
setState
|
|
63
62
|
}) => {
|
|
64
|
-
const getNode = React.useCallback(
|
|
65
|
-
const getItem = React.useCallback(
|
|
66
|
-
const isNodeDisabled = React.useCallback(
|
|
67
|
-
if (
|
|
63
|
+
const getNode = React.useCallback(itemId => state.nodes.nodeMap[itemId], [state.nodes.nodeMap]);
|
|
64
|
+
const getItem = React.useCallback(itemId => state.nodes.itemMap[itemId], [state.nodes.itemMap]);
|
|
65
|
+
const isNodeDisabled = React.useCallback(itemId => {
|
|
66
|
+
if (itemId == null) {
|
|
68
67
|
return false;
|
|
69
68
|
}
|
|
70
|
-
let
|
|
69
|
+
let item = instance.getNode(itemId);
|
|
71
70
|
|
|
72
|
-
// This can be called before the
|
|
73
|
-
if (!
|
|
71
|
+
// This can be called before the item has been added to the node map.
|
|
72
|
+
if (!item) {
|
|
74
73
|
return false;
|
|
75
74
|
}
|
|
76
|
-
if (
|
|
75
|
+
if (item.disabled) {
|
|
77
76
|
return true;
|
|
78
77
|
}
|
|
79
|
-
while (
|
|
80
|
-
|
|
81
|
-
if (
|
|
78
|
+
while (item.parentId != null) {
|
|
79
|
+
item = instance.getNode(item.parentId);
|
|
80
|
+
if (item.disabled) {
|
|
82
81
|
return true;
|
|
83
82
|
}
|
|
84
83
|
}
|
|
85
84
|
return false;
|
|
86
85
|
}, [instance]);
|
|
87
|
-
const getChildrenIds =
|
|
88
|
-
const getNavigableChildrenIds =
|
|
89
|
-
let childrenIds = instance.getChildrenIds(
|
|
86
|
+
const getChildrenIds = React.useCallback(itemId => Object.values(state.nodes.nodeMap).filter(item => item.parentId === itemId).sort((a, b) => a.index - b.index).map(child => child.id), [state.nodes.nodeMap]);
|
|
87
|
+
const getNavigableChildrenIds = itemId => {
|
|
88
|
+
let childrenIds = instance.getChildrenIds(itemId);
|
|
90
89
|
if (!params.disabledItemsFocusable) {
|
|
91
|
-
childrenIds = childrenIds.filter(
|
|
90
|
+
childrenIds = childrenIds.filter(item => !instance.isNodeDisabled(item));
|
|
92
91
|
}
|
|
93
92
|
return childrenIds;
|
|
94
93
|
};
|
|
@@ -112,21 +111,21 @@ const useTreeViewNodes = ({
|
|
|
112
111
|
});
|
|
113
112
|
});
|
|
114
113
|
}, [instance, setState, params.items, params.isItemDisabled, params.getItemId, params.getItemLabel]);
|
|
115
|
-
const getNodesToRender = (
|
|
116
|
-
const
|
|
114
|
+
const getNodesToRender = () => {
|
|
115
|
+
const getPropsFromItemId = ({
|
|
117
116
|
id,
|
|
118
117
|
children
|
|
119
118
|
}) => {
|
|
120
119
|
const node = state.nodes.nodeMap[id];
|
|
121
120
|
return {
|
|
122
121
|
label: node.label,
|
|
123
|
-
|
|
122
|
+
itemId: node.id,
|
|
124
123
|
id: node.idAttribute,
|
|
125
|
-
children: children?.map(
|
|
124
|
+
children: children?.map(getPropsFromItemId)
|
|
126
125
|
};
|
|
127
126
|
};
|
|
128
|
-
return state.nodes.nodeTree.map(
|
|
129
|
-
}
|
|
127
|
+
return state.nodes.nodeTree.map(getPropsFromItemId);
|
|
128
|
+
};
|
|
130
129
|
(0, _useTreeView.populateInstance)(instance, {
|
|
131
130
|
getNode,
|
|
132
131
|
getItem,
|
|
@@ -19,51 +19,51 @@ const useTreeViewSelection = ({
|
|
|
19
19
|
const lastSelectedNode = React.useRef(null);
|
|
20
20
|
const lastSelectionWasRange = React.useRef(false);
|
|
21
21
|
const currentRangeSelection = React.useRef([]);
|
|
22
|
-
const
|
|
23
|
-
if (params.
|
|
22
|
+
const setSelectedItems = (event, newSelectedItems) => {
|
|
23
|
+
if (params.onItemSelectionToggle) {
|
|
24
24
|
if (params.multiSelect) {
|
|
25
|
-
const
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
params.
|
|
25
|
+
const addedItems = newSelectedItems.filter(itemId => !instance.isNodeSelected(itemId));
|
|
26
|
+
const removedItems = models.selectedItems.value.filter(itemId => !newSelectedItems.includes(itemId));
|
|
27
|
+
addedItems.forEach(itemId => {
|
|
28
|
+
params.onItemSelectionToggle(event, itemId, true);
|
|
29
29
|
});
|
|
30
|
-
|
|
31
|
-
params.
|
|
30
|
+
removedItems.forEach(itemId => {
|
|
31
|
+
params.onItemSelectionToggle(event, itemId, false);
|
|
32
32
|
});
|
|
33
|
-
} else if (
|
|
34
|
-
if (models.
|
|
35
|
-
params.
|
|
33
|
+
} else if (newSelectedItems !== models.selectedItems.value) {
|
|
34
|
+
if (models.selectedItems.value != null) {
|
|
35
|
+
params.onItemSelectionToggle(event, models.selectedItems.value, false);
|
|
36
36
|
}
|
|
37
|
-
if (
|
|
38
|
-
params.
|
|
37
|
+
if (newSelectedItems != null) {
|
|
38
|
+
params.onItemSelectionToggle(event, newSelectedItems, true);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
if (params.
|
|
43
|
-
params.
|
|
42
|
+
if (params.onSelectedItemsChange) {
|
|
43
|
+
params.onSelectedItemsChange(event, newSelectedItems);
|
|
44
44
|
}
|
|
45
|
-
models.
|
|
45
|
+
models.selectedItems.setControlledValue(newSelectedItems);
|
|
46
46
|
};
|
|
47
|
-
const isNodeSelected =
|
|
48
|
-
const selectNode = (event,
|
|
47
|
+
const isNodeSelected = itemId => Array.isArray(models.selectedItems.value) ? models.selectedItems.value.indexOf(itemId) !== -1 : models.selectedItems.value === itemId;
|
|
48
|
+
const selectNode = (event, itemId, multiple = false) => {
|
|
49
49
|
if (params.disableSelection) {
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
52
|
if (multiple) {
|
|
53
|
-
if (Array.isArray(models.
|
|
53
|
+
if (Array.isArray(models.selectedItems.value)) {
|
|
54
54
|
let newSelected;
|
|
55
|
-
if (models.
|
|
56
|
-
newSelected = models.
|
|
55
|
+
if (models.selectedItems.value.indexOf(itemId) !== -1) {
|
|
56
|
+
newSelected = models.selectedItems.value.filter(id => id !== itemId);
|
|
57
57
|
} else {
|
|
58
|
-
newSelected = [
|
|
58
|
+
newSelected = [itemId].concat(models.selectedItems.value);
|
|
59
59
|
}
|
|
60
|
-
|
|
60
|
+
setSelectedItems(event, newSelected);
|
|
61
61
|
}
|
|
62
62
|
} else {
|
|
63
|
-
const newSelected = params.multiSelect ? [
|
|
64
|
-
|
|
63
|
+
const newSelected = params.multiSelect ? [itemId] : itemId;
|
|
64
|
+
setSelectedItems(event, newSelected);
|
|
65
65
|
}
|
|
66
|
-
lastSelectedNode.current =
|
|
66
|
+
lastSelectedNode.current = itemId;
|
|
67
67
|
lastSelectionWasRange.current = false;
|
|
68
68
|
currentRangeSelection.current = [];
|
|
69
69
|
};
|
|
@@ -78,7 +78,7 @@ const useTreeViewSelection = ({
|
|
|
78
78
|
return nodes;
|
|
79
79
|
};
|
|
80
80
|
const handleRangeArrowSelect = (event, nodes) => {
|
|
81
|
-
let base = models.
|
|
81
|
+
let base = models.selectedItems.value.slice();
|
|
82
82
|
const {
|
|
83
83
|
start,
|
|
84
84
|
next,
|
|
@@ -102,10 +102,10 @@ const useTreeViewSelection = ({
|
|
|
102
102
|
base.push(next);
|
|
103
103
|
currentRangeSelection.current.push(current, next);
|
|
104
104
|
}
|
|
105
|
-
|
|
105
|
+
setSelectedItems(event, base);
|
|
106
106
|
};
|
|
107
107
|
const handleRangeSelect = (event, nodes) => {
|
|
108
|
-
let base = models.
|
|
108
|
+
let base = models.selectedItems.value.slice();
|
|
109
109
|
const {
|
|
110
110
|
start,
|
|
111
111
|
end
|
|
@@ -119,7 +119,7 @@ const useTreeViewSelection = ({
|
|
|
119
119
|
currentRangeSelection.current = range;
|
|
120
120
|
let newSelected = base.concat(range);
|
|
121
121
|
newSelected = newSelected.filter((id, i) => newSelected.indexOf(id) === i);
|
|
122
|
-
|
|
122
|
+
setSelectedItems(event, newSelected);
|
|
123
123
|
};
|
|
124
124
|
const selectRange = (event, nodes, stacked = false) => {
|
|
125
125
|
if (params.disableSelection) {
|
|
@@ -144,21 +144,21 @@ const useTreeViewSelection = ({
|
|
|
144
144
|
}
|
|
145
145
|
lastSelectionWasRange.current = true;
|
|
146
146
|
};
|
|
147
|
-
const rangeSelectToFirst = (event,
|
|
147
|
+
const rangeSelectToFirst = (event, itemId) => {
|
|
148
148
|
if (!lastSelectedNode.current) {
|
|
149
|
-
lastSelectedNode.current =
|
|
149
|
+
lastSelectedNode.current = itemId;
|
|
150
150
|
}
|
|
151
|
-
const start = lastSelectionWasRange.current ? lastSelectedNode.current :
|
|
151
|
+
const start = lastSelectionWasRange.current ? lastSelectedNode.current : itemId;
|
|
152
152
|
instance.selectRange(event, {
|
|
153
153
|
start,
|
|
154
154
|
end: (0, _useTreeView.getFirstNode)(instance)
|
|
155
155
|
});
|
|
156
156
|
};
|
|
157
|
-
const rangeSelectToLast = (event,
|
|
157
|
+
const rangeSelectToLast = (event, itemId) => {
|
|
158
158
|
if (!lastSelectedNode.current) {
|
|
159
|
-
lastSelectedNode.current =
|
|
159
|
+
lastSelectedNode.current = itemId;
|
|
160
160
|
}
|
|
161
|
-
const start = lastSelectionWasRange.current ? lastSelectedNode.current :
|
|
161
|
+
const start = lastSelectionWasRange.current ? lastSelectedNode.current : itemId;
|
|
162
162
|
instance.selectRange(event, {
|
|
163
163
|
start,
|
|
164
164
|
end: (0, _useTreeView.getLastNode)(instance)
|
|
@@ -184,21 +184,21 @@ const useTreeViewSelection = ({
|
|
|
184
184
|
};
|
|
185
185
|
exports.useTreeViewSelection = useTreeViewSelection;
|
|
186
186
|
useTreeViewSelection.models = {
|
|
187
|
-
|
|
188
|
-
getDefaultValue: params => params.
|
|
187
|
+
selectedItems: {
|
|
188
|
+
getDefaultValue: params => params.defaultSelectedItems
|
|
189
189
|
}
|
|
190
190
|
};
|
|
191
191
|
const DEFAULT_SELECTED_NODES = [];
|
|
192
192
|
useTreeViewSelection.getDefaultizedParams = params => (0, _extends2.default)({}, params, {
|
|
193
193
|
disableSelection: params.disableSelection ?? false,
|
|
194
194
|
multiSelect: params.multiSelect ?? false,
|
|
195
|
-
|
|
195
|
+
defaultSelectedItems: params.defaultSelectedItems ?? (params.multiSelect ? DEFAULT_SELECTED_NODES : null)
|
|
196
196
|
});
|
|
197
197
|
useTreeViewSelection.params = {
|
|
198
198
|
disableSelection: true,
|
|
199
199
|
multiSelect: true,
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
200
|
+
defaultSelectedItems: true,
|
|
201
|
+
selectedItems: true,
|
|
202
|
+
onSelectedItemsChange: true,
|
|
203
|
+
onItemSelectionToggle: true
|
|
204
204
|
};
|
|
@@ -48,6 +48,7 @@ const useTreeView = inParams => {
|
|
|
48
48
|
});
|
|
49
49
|
const rootPropsGetters = [];
|
|
50
50
|
const contextValue = {
|
|
51
|
+
publicAPI,
|
|
51
52
|
instance: instance
|
|
52
53
|
};
|
|
53
54
|
const runPlugin = plugin => {
|
|
@@ -70,47 +71,47 @@ const useTreeView = inParams => {
|
|
|
70
71
|
}
|
|
71
72
|
};
|
|
72
73
|
plugins.forEach(runPlugin);
|
|
73
|
-
contextValue.runItemPlugins =
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}) => {
|
|
77
|
-
let finalProps = props;
|
|
78
|
-
let finalRef = ref;
|
|
79
|
-
const itemWrappers = [];
|
|
74
|
+
contextValue.runItemPlugins = itemPluginProps => {
|
|
75
|
+
let finalRootRef = null;
|
|
76
|
+
let finalContentRef = null;
|
|
80
77
|
plugins.forEach(plugin => {
|
|
81
78
|
if (!plugin.itemPlugin) {
|
|
82
79
|
return;
|
|
83
80
|
}
|
|
84
81
|
const itemPluginResponse = plugin.itemPlugin({
|
|
85
|
-
props:
|
|
86
|
-
|
|
82
|
+
props: itemPluginProps,
|
|
83
|
+
rootRef: finalRootRef,
|
|
84
|
+
contentRef: finalContentRef
|
|
87
85
|
});
|
|
88
|
-
if (itemPluginResponse?.
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
if (itemPluginResponse?.ref) {
|
|
92
|
-
finalRef = itemPluginResponse.ref;
|
|
86
|
+
if (itemPluginResponse?.rootRef) {
|
|
87
|
+
finalRootRef = itemPluginResponse.rootRef;
|
|
93
88
|
}
|
|
94
|
-
if (itemPluginResponse?.
|
|
95
|
-
|
|
89
|
+
if (itemPluginResponse?.contentRef) {
|
|
90
|
+
finalContentRef = itemPluginResponse.contentRef;
|
|
96
91
|
}
|
|
97
92
|
});
|
|
98
93
|
return {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
wrapItem: children => {
|
|
102
|
-
let finalChildren = children;
|
|
103
|
-
itemWrappers.forEach(itemWrapper => {
|
|
104
|
-
finalChildren = itemWrapper(finalChildren);
|
|
105
|
-
});
|
|
106
|
-
return finalChildren;
|
|
107
|
-
}
|
|
94
|
+
contentRef: finalContentRef,
|
|
95
|
+
rootRef: finalRootRef
|
|
108
96
|
};
|
|
109
97
|
};
|
|
98
|
+
const itemWrappers = plugins.map(plugin => plugin.wrapItem).filter(wrapItem => !!wrapItem);
|
|
99
|
+
contextValue.wrapItem = ({
|
|
100
|
+
itemId,
|
|
101
|
+
children
|
|
102
|
+
}) => {
|
|
103
|
+
let finalChildren = children;
|
|
104
|
+
itemWrappers.forEach(itemWrapper => {
|
|
105
|
+
finalChildren = itemWrapper({
|
|
106
|
+
itemId,
|
|
107
|
+
children: finalChildren
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
return finalChildren;
|
|
111
|
+
};
|
|
110
112
|
const getRootProps = (otherHandlers = {}) => {
|
|
111
113
|
const rootProps = (0, _extends2.default)({
|
|
112
|
-
role: 'tree'
|
|
113
|
-
tabIndex: 0
|
|
114
|
+
role: 'tree'
|
|
114
115
|
}, otherHandlers, {
|
|
115
116
|
ref: handleRootRef
|
|
116
117
|
});
|