@mui/x-tree-view 7.0.0 → 7.1.1
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 +246 -4
- package/README.md +1 -1
- package/RichTreeView/RichTreeView.d.ts +2 -2
- package/RichTreeView/RichTreeView.js +11 -9
- package/SimpleTreeView/SimpleTreeView.js +4 -2
- package/SimpleTreeView/SimpleTreeView.plugins.d.ts +1 -1
- package/SimpleTreeView/SimpleTreeView.plugins.js +2 -2
- package/TreeItem/TreeItem.js +4 -4
- package/TreeItem/treeItemClasses.d.ts +1 -1
- package/TreeItem/useTreeItemState.js +9 -9
- package/TreeItem2Icon/TreeItem2Icon.types.d.ts +4 -4
- package/TreeView/TreeView.js +2 -1
- package/hooks/useTreeItem2Utils/useTreeItem2Utils.js +8 -8
- package/hooks/useTreeViewApiRef.d.ts +1 -1
- package/index.js +1 -1
- package/internals/TreeViewProvider/DescendantProvider.d.ts +1 -1
- package/internals/TreeViewProvider/DescendantProvider.js +1 -1
- package/internals/index.d.ts +18 -8
- package/internals/index.js +11 -0
- package/internals/models/plugin.d.ts +1 -1
- package/internals/plugins/defaultPlugins.d.ts +3 -3
- package/internals/plugins/defaultPlugins.js +2 -2
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +32 -18
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +16 -6
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +35 -33
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +17 -9
- package/internals/plugins/useTreeViewIcons/useTreeViewIcons.types.d.ts +6 -6
- package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +1 -1
- package/internals/plugins/useTreeViewItems/index.d.ts +2 -0
- package/internals/plugins/useTreeViewItems/index.js +1 -0
- package/internals/plugins/useTreeViewItems/useTreeViewItems.d.ts +3 -0
- package/internals/plugins/{useTreeViewNodes/useTreeViewNodes.js → useTreeViewItems/useTreeViewItems.js} +43 -33
- package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +104 -0
- package/internals/plugins/useTreeViewJSXItems/index.d.ts +2 -0
- package/internals/plugins/useTreeViewJSXItems/index.js +1 -0
- package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.d.ts +3 -0
- package/{modern/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js → internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js} +26 -25
- package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.types.d.ts +18 -0
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +40 -44
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +2 -2
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +34 -34
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +6 -6
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.d.ts +7 -7
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +5 -5
- package/internals/useTreeView/useTreeView.utils.d.ts +5 -5
- package/internals/useTreeView/useTreeView.utils.js +15 -15
- package/internals/useTreeView/useTreeViewModels.js +2 -2
- package/modern/RichTreeView/RichTreeView.js +11 -9
- package/modern/SimpleTreeView/SimpleTreeView.js +4 -2
- package/modern/SimpleTreeView/SimpleTreeView.plugins.js +2 -2
- package/modern/TreeItem/TreeItem.js +4 -4
- package/modern/TreeItem/useTreeItemState.js +9 -9
- package/modern/TreeView/TreeView.js +2 -1
- package/modern/hooks/useTreeItem2Utils/useTreeItem2Utils.js +8 -8
- package/modern/index.js +1 -1
- package/modern/internals/TreeViewProvider/DescendantProvider.js +1 -1
- package/modern/internals/index.js +11 -0
- package/modern/internals/plugins/defaultPlugins.js +2 -2
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +32 -18
- package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +35 -33
- package/modern/internals/plugins/useTreeViewItems/index.js +1 -0
- package/modern/internals/plugins/{useTreeViewNodes/useTreeViewNodes.js → useTreeViewItems/useTreeViewItems.js} +43 -33
- package/modern/internals/plugins/useTreeViewJSXItems/index.js +1 -0
- package/{internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js → modern/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js} +26 -25
- package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +40 -44
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +34 -34
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +5 -5
- package/modern/internals/useTreeView/useTreeView.utils.js +15 -15
- package/modern/internals/useTreeView/useTreeViewModels.js +2 -2
- package/node/RichTreeView/RichTreeView.js +11 -9
- package/node/SimpleTreeView/SimpleTreeView.js +4 -2
- package/node/SimpleTreeView/SimpleTreeView.plugins.js +2 -2
- package/node/TreeItem/TreeItem.js +4 -4
- package/node/TreeItem/useTreeItemState.js +9 -9
- package/node/TreeView/TreeView.js +2 -1
- package/node/hooks/useTreeItem2Utils/useTreeItem2Utils.js +8 -8
- package/node/index.js +1 -1
- package/node/internals/TreeViewProvider/DescendantProvider.js +1 -1
- package/node/internals/index.js +70 -0
- package/node/internals/plugins/defaultPlugins.js +2 -2
- package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +31 -17
- package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +35 -33
- package/node/internals/plugins/useTreeViewItems/index.js +12 -0
- package/node/internals/plugins/{useTreeViewNodes/useTreeViewNodes.js → useTreeViewItems/useTreeViewItems.js} +45 -35
- package/node/internals/plugins/useTreeViewJSXItems/index.js +12 -0
- package/node/internals/plugins/{useTreeViewJSXNodes/useTreeViewJSXNodes.js → useTreeViewJSXItems/useTreeViewJSXItems.js} +28 -27
- package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +39 -43
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +33 -33
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +5 -5
- package/node/internals/useTreeView/useTreeView.utils.js +20 -20
- package/node/internals/useTreeView/useTreeViewModels.js +2 -2
- package/package.json +2 -2
- package/useTreeItem2/useTreeItem2.d.ts +1 -1
- package/internals/plugins/useTreeViewJSXNodes/index.d.ts +0 -2
- package/internals/plugins/useTreeViewJSXNodes/index.js +0 -1
- package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.d.ts +0 -3
- package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.types.d.ts +0 -18
- package/internals/plugins/useTreeViewNodes/index.d.ts +0 -2
- package/internals/plugins/useTreeViewNodes/index.js +0 -1
- package/internals/plugins/useTreeViewNodes/useTreeViewNodes.d.ts +0 -3
- package/internals/plugins/useTreeViewNodes/useTreeViewNodes.types.d.ts +0 -88
- package/modern/internals/plugins/useTreeViewJSXNodes/index.js +0 -1
- package/modern/internals/plugins/useTreeViewNodes/index.js +0 -1
- package/node/internals/plugins/useTreeViewJSXNodes/index.js +0 -12
- package/node/internals/plugins/useTreeViewNodes/index.js +0 -12
- /package/internals/plugins/{useTreeViewJSXNodes/useTreeViewJSXNodes.types.js → useTreeViewItems/useTreeViewItems.types.js} +0 -0
- /package/internals/plugins/{useTreeViewNodes/useTreeViewNodes.types.js → useTreeViewJSXItems/useTreeViewJSXItems.types.js} +0 -0
- /package/modern/internals/plugins/{useTreeViewJSXNodes/useTreeViewJSXNodes.types.js → useTreeViewItems/useTreeViewItems.types.js} +0 -0
- /package/modern/internals/plugins/{useTreeViewNodes/useTreeViewNodes.types.js → useTreeViewJSXItems/useTreeViewJSXItems.types.js} +0 -0
- /package/node/internals/plugins/{useTreeViewJSXNodes/useTreeViewJSXNodes.types.js → useTreeViewItems/useTreeViewItems.types.js} +0 -0
- /package/node/internals/plugins/{useTreeViewNodes/useTreeViewNodes.types.js → useTreeViewJSXItems/useTreeViewJSXItems.types.js} +0 -0
package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js
CHANGED
|
@@ -24,30 +24,26 @@ function findNextFirstChar(firstChars, startIndex, char) {
|
|
|
24
24
|
}
|
|
25
25
|
const useTreeViewKeyboardNavigation = ({
|
|
26
26
|
instance,
|
|
27
|
-
params
|
|
27
|
+
params,
|
|
28
|
+
state
|
|
28
29
|
}) => {
|
|
29
30
|
const theme = (0, _styles.useTheme)();
|
|
30
31
|
const isRTL = theme.direction === 'rtl';
|
|
31
32
|
const firstCharMap = React.useRef({});
|
|
32
|
-
const hasFirstCharMapBeenUpdatedImperatively = React.useRef(false);
|
|
33
33
|
const updateFirstCharMap = (0, _useEventCallback.default)(callback => {
|
|
34
|
-
hasFirstCharMapBeenUpdatedImperatively.current = true;
|
|
35
34
|
firstCharMap.current = callback(firstCharMap.current);
|
|
36
35
|
});
|
|
37
36
|
React.useEffect(() => {
|
|
38
|
-
if (
|
|
37
|
+
if (instance.areItemUpdatesPrevented()) {
|
|
39
38
|
return;
|
|
40
39
|
}
|
|
41
40
|
const newFirstCharMap = {};
|
|
42
|
-
const processItem =
|
|
43
|
-
|
|
44
|
-
const itemId = getItemId ? getItemId(item) : item.id;
|
|
45
|
-
newFirstCharMap[itemId] = instance.getNode(itemId).label.substring(0, 1).toLowerCase();
|
|
46
|
-
item.children?.forEach(processItem);
|
|
41
|
+
const processItem = node => {
|
|
42
|
+
newFirstCharMap[node.id] = node.label.substring(0, 1).toLowerCase();
|
|
47
43
|
};
|
|
48
|
-
|
|
44
|
+
Object.values(state.items.nodeMap).forEach(processItem);
|
|
49
45
|
firstCharMap.current = newFirstCharMap;
|
|
50
|
-
}, [
|
|
46
|
+
}, [state.items.nodeMap, params.getItemId, instance]);
|
|
51
47
|
const getFirstMatchingItem = (itemId, firstChar) => {
|
|
52
48
|
let start;
|
|
53
49
|
let index;
|
|
@@ -57,8 +53,8 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
57
53
|
// This really only works since the ids are strings
|
|
58
54
|
Object.keys(firstCharMap.current).forEach(mapItemId => {
|
|
59
55
|
const map = instance.getNode(mapItemId);
|
|
60
|
-
const visible = map.parentId ? instance.
|
|
61
|
-
const shouldBeSkipped = params.disabledItemsFocusable ? false : instance.
|
|
56
|
+
const visible = map.parentId ? instance.isItemExpanded(map.parentId) : true;
|
|
57
|
+
const shouldBeSkipped = params.disabledItemsFocusable ? false : instance.isItemDisabled(mapItemId);
|
|
62
58
|
if (visible && !shouldBeSkipped) {
|
|
63
59
|
firstCharIds.push(mapItemId);
|
|
64
60
|
firstChars.push(firstCharMap.current[mapItemId]);
|
|
@@ -85,9 +81,9 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
85
81
|
}
|
|
86
82
|
return null;
|
|
87
83
|
};
|
|
88
|
-
const canToggleItemSelection = itemId => !params.disableSelection && !instance.
|
|
84
|
+
const canToggleItemSelection = itemId => !params.disableSelection && !instance.isItemDisabled(itemId);
|
|
89
85
|
const canToggleItemExpansion = itemId => {
|
|
90
|
-
return !instance.
|
|
86
|
+
return !instance.isItemDisabled(itemId) && instance.isItemExpandable(itemId);
|
|
91
87
|
};
|
|
92
88
|
|
|
93
89
|
// ARIA specification: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/#keyboardinteraction
|
|
@@ -103,7 +99,7 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
103
99
|
|
|
104
100
|
// eslint-disable-next-line default-case
|
|
105
101
|
switch (true) {
|
|
106
|
-
// Select the
|
|
102
|
+
// Select the item when pressing "Space"
|
|
107
103
|
case key === ' ' && canToggleItemSelection(itemId):
|
|
108
104
|
{
|
|
109
105
|
event.preventDefault();
|
|
@@ -112,26 +108,26 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
112
108
|
end: itemId
|
|
113
109
|
});
|
|
114
110
|
} else if (params.multiSelect) {
|
|
115
|
-
instance.
|
|
111
|
+
instance.selectItem(event, itemId, true);
|
|
116
112
|
} else {
|
|
117
|
-
instance.
|
|
113
|
+
instance.selectItem(event, itemId);
|
|
118
114
|
}
|
|
119
115
|
break;
|
|
120
116
|
}
|
|
121
117
|
|
|
122
|
-
// If the focused
|
|
123
|
-
// If the focused
|
|
118
|
+
// If the focused item has children, we expand it.
|
|
119
|
+
// If the focused item has no children, we select it.
|
|
124
120
|
case key === 'Enter':
|
|
125
121
|
{
|
|
126
122
|
if (canToggleItemExpansion(itemId)) {
|
|
127
|
-
instance.
|
|
123
|
+
instance.toggleItemExpansion(event, itemId);
|
|
128
124
|
event.preventDefault();
|
|
129
125
|
} else if (canToggleItemSelection(itemId)) {
|
|
130
126
|
if (params.multiSelect) {
|
|
131
127
|
event.preventDefault();
|
|
132
|
-
instance.
|
|
133
|
-
} else if (!instance.
|
|
134
|
-
instance.
|
|
128
|
+
instance.selectItem(event, itemId, true);
|
|
129
|
+
} else if (!instance.isItemSelected(itemId)) {
|
|
130
|
+
instance.selectItem(event, itemId);
|
|
135
131
|
event.preventDefault();
|
|
136
132
|
}
|
|
137
133
|
}
|
|
@@ -141,7 +137,7 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
141
137
|
// Focus the next focusable item
|
|
142
138
|
case key === 'ArrowDown':
|
|
143
139
|
{
|
|
144
|
-
const nextItem = (0, _useTreeView.
|
|
140
|
+
const nextItem = (0, _useTreeView.getNextItem)(instance, itemId);
|
|
145
141
|
if (nextItem) {
|
|
146
142
|
event.preventDefault();
|
|
147
143
|
instance.focusItem(event, nextItem);
|
|
@@ -161,7 +157,7 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
161
157
|
// Focuses the previous focusable item
|
|
162
158
|
case key === 'ArrowUp':
|
|
163
159
|
{
|
|
164
|
-
const previousItem = (0, _useTreeView.
|
|
160
|
+
const previousItem = (0, _useTreeView.getPreviousItem)(instance, itemId);
|
|
165
161
|
if (previousItem) {
|
|
166
162
|
event.preventDefault();
|
|
167
163
|
instance.focusItem(event, previousItem);
|
|
@@ -182,14 +178,14 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
182
178
|
// If the focused item is collapsed and has children, we expand it
|
|
183
179
|
case key === 'ArrowRight' && !isRTL || key === 'ArrowLeft' && isRTL:
|
|
184
180
|
{
|
|
185
|
-
if (instance.
|
|
186
|
-
const
|
|
187
|
-
if (
|
|
188
|
-
instance.focusItem(event,
|
|
181
|
+
if (instance.isItemExpanded(itemId)) {
|
|
182
|
+
const nextItemId = (0, _useTreeView.getNextItem)(instance, itemId);
|
|
183
|
+
if (nextItemId) {
|
|
184
|
+
instance.focusItem(event, nextItemId);
|
|
189
185
|
event.preventDefault();
|
|
190
186
|
}
|
|
191
187
|
} else if (canToggleItemExpansion(itemId)) {
|
|
192
|
-
instance.
|
|
188
|
+
instance.toggleItemExpansion(event, itemId);
|
|
193
189
|
event.preventDefault();
|
|
194
190
|
}
|
|
195
191
|
break;
|
|
@@ -199,8 +195,8 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
199
195
|
// If the focused item is collapsed and has a parent, we move the focus to this parent
|
|
200
196
|
case key === 'ArrowLeft' && !isRTL || key === 'ArrowRight' && isRTL:
|
|
201
197
|
{
|
|
202
|
-
if (canToggleItemExpansion(itemId) && instance.
|
|
203
|
-
instance.
|
|
198
|
+
if (canToggleItemExpansion(itemId) && instance.isItemExpanded(itemId)) {
|
|
199
|
+
instance.toggleItemExpansion(event, itemId);
|
|
204
200
|
event.preventDefault();
|
|
205
201
|
} else {
|
|
206
202
|
const parent = instance.getNode(itemId).parentId;
|
|
@@ -212,13 +208,13 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
212
208
|
break;
|
|
213
209
|
}
|
|
214
210
|
|
|
215
|
-
// Focuses the first
|
|
211
|
+
// Focuses the first item in the tree
|
|
216
212
|
case key === 'Home':
|
|
217
213
|
{
|
|
218
|
-
instance.focusItem(event, (0, _useTreeView.
|
|
214
|
+
instance.focusItem(event, (0, _useTreeView.getFirstItem)(instance));
|
|
219
215
|
|
|
220
216
|
// Multi select behavior when pressing Ctrl + Shift + Home
|
|
221
|
-
// Selects the focused
|
|
217
|
+
// Selects the focused item and all items up to the first item.
|
|
222
218
|
if (canToggleItemSelection(itemId) && params.multiSelect && ctrlPressed && event.shiftKey) {
|
|
223
219
|
instance.rangeSelectToFirst(event, itemId);
|
|
224
220
|
}
|
|
@@ -229,7 +225,7 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
229
225
|
// Focuses the last item in the tree
|
|
230
226
|
case key === 'End':
|
|
231
227
|
{
|
|
232
|
-
instance.focusItem(event, (0, _useTreeView.
|
|
228
|
+
instance.focusItem(event, (0, _useTreeView.getLastItem)(instance));
|
|
233
229
|
|
|
234
230
|
// Multi select behavior when pressing Ctrl + Shirt + End
|
|
235
231
|
// Selects the focused item and all the items down to the last item.
|
|
@@ -249,12 +245,12 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
249
245
|
}
|
|
250
246
|
|
|
251
247
|
// Multi select behavior when pressing Ctrl + a
|
|
252
|
-
// Selects all the
|
|
248
|
+
// Selects all the items
|
|
253
249
|
case key === 'a' && ctrlPressed && params.multiSelect && !params.disableSelection:
|
|
254
250
|
{
|
|
255
251
|
instance.selectRange(event, {
|
|
256
|
-
start: (0, _useTreeView.
|
|
257
|
-
end: (0, _useTreeView.
|
|
252
|
+
start: (0, _useTreeView.getFirstItem)(instance),
|
|
253
|
+
end: (0, _useTreeView.getLastItem)(instance)
|
|
258
254
|
});
|
|
259
255
|
event.preventDefault();
|
|
260
256
|
break;
|
|
@@ -264,9 +260,9 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
264
260
|
// TODO: Support typing multiple characters
|
|
265
261
|
case !ctrlPressed && !event.shiftKey && isPrintableCharacter(key):
|
|
266
262
|
{
|
|
267
|
-
const
|
|
268
|
-
if (
|
|
269
|
-
instance.focusItem(event,
|
|
263
|
+
const matchingItem = getFirstMatchingItem(itemId, key);
|
|
264
|
+
if (matchingItem != null) {
|
|
265
|
+
instance.focusItem(event, matchingItem);
|
|
270
266
|
event.preventDefault();
|
|
271
267
|
}
|
|
272
268
|
break;
|
|
@@ -16,13 +16,13 @@ const useTreeViewSelection = ({
|
|
|
16
16
|
params,
|
|
17
17
|
models
|
|
18
18
|
}) => {
|
|
19
|
-
const
|
|
19
|
+
const lastSelectedItem = React.useRef(null);
|
|
20
20
|
const lastSelectionWasRange = React.useRef(false);
|
|
21
21
|
const currentRangeSelection = React.useRef([]);
|
|
22
22
|
const setSelectedItems = (event, newSelectedItems) => {
|
|
23
23
|
if (params.onItemSelectionToggle) {
|
|
24
24
|
if (params.multiSelect) {
|
|
25
|
-
const addedItems = newSelectedItems.filter(itemId => !instance.
|
|
25
|
+
const addedItems = newSelectedItems.filter(itemId => !instance.isItemSelected(itemId));
|
|
26
26
|
const removedItems = models.selectedItems.value.filter(itemId => !newSelectedItems.includes(itemId));
|
|
27
27
|
addedItems.forEach(itemId => {
|
|
28
28
|
params.onItemSelectionToggle(event, itemId, true);
|
|
@@ -44,8 +44,8 @@ const useTreeViewSelection = ({
|
|
|
44
44
|
}
|
|
45
45
|
models.selectedItems.setControlledValue(newSelectedItems);
|
|
46
46
|
};
|
|
47
|
-
const
|
|
48
|
-
const
|
|
47
|
+
const isItemSelected = itemId => Array.isArray(models.selectedItems.value) ? models.selectedItems.value.indexOf(itemId) !== -1 : models.selectedItems.value === itemId;
|
|
48
|
+
const selectItem = (event, itemId, multiple = false) => {
|
|
49
49
|
if (params.disableSelection) {
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
@@ -63,27 +63,27 @@ const useTreeViewSelection = ({
|
|
|
63
63
|
const newSelected = params.multiSelect ? [itemId] : itemId;
|
|
64
64
|
setSelectedItems(event, newSelected);
|
|
65
65
|
}
|
|
66
|
-
|
|
66
|
+
lastSelectedItem.current = itemId;
|
|
67
67
|
lastSelectionWasRange.current = false;
|
|
68
68
|
currentRangeSelection.current = [];
|
|
69
69
|
};
|
|
70
|
-
const
|
|
71
|
-
const [first, last] = (0, _useTreeViewSelection.findOrderInTremauxTree)(instance,
|
|
72
|
-
const
|
|
70
|
+
const getItemsInRange = (itemAId, itemBId) => {
|
|
71
|
+
const [first, last] = (0, _useTreeViewSelection.findOrderInTremauxTree)(instance, itemAId, itemBId);
|
|
72
|
+
const items = [first];
|
|
73
73
|
let current = first;
|
|
74
74
|
while (current !== last) {
|
|
75
|
-
current = (0, _useTreeView.
|
|
76
|
-
|
|
75
|
+
current = (0, _useTreeView.getNextItem)(instance, current);
|
|
76
|
+
items.push(current);
|
|
77
77
|
}
|
|
78
|
-
return
|
|
78
|
+
return items;
|
|
79
79
|
};
|
|
80
|
-
const handleRangeArrowSelect = (event,
|
|
80
|
+
const handleRangeArrowSelect = (event, items) => {
|
|
81
81
|
let base = models.selectedItems.value.slice();
|
|
82
82
|
const {
|
|
83
83
|
start,
|
|
84
84
|
next,
|
|
85
85
|
current
|
|
86
|
-
} =
|
|
86
|
+
} = items;
|
|
87
87
|
if (!next || !current) {
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
@@ -104,32 +104,32 @@ const useTreeViewSelection = ({
|
|
|
104
104
|
}
|
|
105
105
|
setSelectedItems(event, base);
|
|
106
106
|
};
|
|
107
|
-
const handleRangeSelect = (event,
|
|
107
|
+
const handleRangeSelect = (event, items) => {
|
|
108
108
|
let base = models.selectedItems.value.slice();
|
|
109
109
|
const {
|
|
110
110
|
start,
|
|
111
111
|
end
|
|
112
|
-
} =
|
|
113
|
-
// If last selection was a range selection ignore
|
|
112
|
+
} = items;
|
|
113
|
+
// If last selection was a range selection ignore items that were selected.
|
|
114
114
|
if (lastSelectionWasRange.current) {
|
|
115
115
|
base = base.filter(id => currentRangeSelection.current.indexOf(id) === -1);
|
|
116
116
|
}
|
|
117
|
-
let range =
|
|
118
|
-
range = range.filter(
|
|
117
|
+
let range = getItemsInRange(start, end);
|
|
118
|
+
range = range.filter(item => !instance.isItemDisabled(item));
|
|
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
|
-
const selectRange = (event,
|
|
124
|
+
const selectRange = (event, items, stacked = false) => {
|
|
125
125
|
if (params.disableSelection) {
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
128
|
const {
|
|
129
|
-
start =
|
|
129
|
+
start = lastSelectedItem.current,
|
|
130
130
|
end,
|
|
131
131
|
current
|
|
132
|
-
} =
|
|
132
|
+
} = items;
|
|
133
133
|
if (stacked) {
|
|
134
134
|
handleRangeArrowSelect(event, {
|
|
135
135
|
start,
|
|
@@ -145,28 +145,28 @@ const useTreeViewSelection = ({
|
|
|
145
145
|
lastSelectionWasRange.current = true;
|
|
146
146
|
};
|
|
147
147
|
const rangeSelectToFirst = (event, itemId) => {
|
|
148
|
-
if (!
|
|
149
|
-
|
|
148
|
+
if (!lastSelectedItem.current) {
|
|
149
|
+
lastSelectedItem.current = itemId;
|
|
150
150
|
}
|
|
151
|
-
const start = lastSelectionWasRange.current ?
|
|
151
|
+
const start = lastSelectionWasRange.current ? lastSelectedItem.current : itemId;
|
|
152
152
|
instance.selectRange(event, {
|
|
153
153
|
start,
|
|
154
|
-
end: (0, _useTreeView.
|
|
154
|
+
end: (0, _useTreeView.getFirstItem)(instance)
|
|
155
155
|
});
|
|
156
156
|
};
|
|
157
157
|
const rangeSelectToLast = (event, itemId) => {
|
|
158
|
-
if (!
|
|
159
|
-
|
|
158
|
+
if (!lastSelectedItem.current) {
|
|
159
|
+
lastSelectedItem.current = itemId;
|
|
160
160
|
}
|
|
161
|
-
const start = lastSelectionWasRange.current ?
|
|
161
|
+
const start = lastSelectionWasRange.current ? lastSelectedItem.current : itemId;
|
|
162
162
|
instance.selectRange(event, {
|
|
163
163
|
start,
|
|
164
|
-
end: (0, _useTreeView.
|
|
164
|
+
end: (0, _useTreeView.getLastItem)(instance)
|
|
165
165
|
});
|
|
166
166
|
};
|
|
167
167
|
(0, _useTreeView.populateInstance)(instance, {
|
|
168
|
-
|
|
169
|
-
|
|
168
|
+
isItemSelected,
|
|
169
|
+
selectItem,
|
|
170
170
|
selectRange,
|
|
171
171
|
rangeSelectToLast,
|
|
172
172
|
rangeSelectToFirst
|
|
@@ -188,11 +188,11 @@ useTreeViewSelection.models = {
|
|
|
188
188
|
getDefaultValue: params => params.defaultSelectedItems
|
|
189
189
|
}
|
|
190
190
|
};
|
|
191
|
-
const
|
|
191
|
+
const DEFAULT_SELECTED_ITEMS = [];
|
|
192
192
|
useTreeViewSelection.getDefaultizedParams = params => (0, _extends2.default)({}, params, {
|
|
193
193
|
disableSelection: params.disableSelection ?? false,
|
|
194
194
|
multiSelect: params.multiSelect ?? false,
|
|
195
|
-
defaultSelectedItems: params.defaultSelectedItems ?? (params.multiSelect ?
|
|
195
|
+
defaultSelectedItems: params.defaultSelectedItems ?? (params.multiSelect ? DEFAULT_SELECTED_ITEMS : null)
|
|
196
196
|
});
|
|
197
197
|
useTreeViewSelection.params = {
|
|
198
198
|
disableSelection: true,
|
|
@@ -6,16 +6,16 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.findOrderInTremauxTree = void 0;
|
|
7
7
|
/**
|
|
8
8
|
* This is used to determine the start and end of a selection range so
|
|
9
|
-
* we can get the
|
|
9
|
+
* we can get the items between the two border items.
|
|
10
10
|
*
|
|
11
|
-
* It finds the
|
|
11
|
+
* It finds the items' common ancestor using
|
|
12
12
|
* a naive implementation of a lowest common ancestor algorithm
|
|
13
13
|
* (https://en.wikipedia.org/wiki/Lowest_common_ancestor).
|
|
14
|
-
* Then compares the ancestor's 2 children that are ancestors of
|
|
15
|
-
* so we can compare their indexes to work out which
|
|
14
|
+
* Then compares the ancestor's 2 children that are ancestors of itemA and ItemB
|
|
15
|
+
* so we can compare their indexes to work out which item comes first in a depth first search.
|
|
16
16
|
* (https://en.wikipedia.org/wiki/Depth-first_search)
|
|
17
17
|
*
|
|
18
|
-
* Another way to put it is which
|
|
18
|
+
* Another way to put it is which item is shallower in a trémaux tree
|
|
19
19
|
* https://en.wikipedia.org/wiki/Tr%C3%A9maux_tree
|
|
20
20
|
*/
|
|
21
21
|
const findOrderInTremauxTree = (instance, nodeAId, nodeBId) => {
|
|
@@ -3,51 +3,51 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.populatePublicAPI = exports.populateInstance = exports.
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const siblings = instance.getNavigableChildrenIds(
|
|
6
|
+
exports.populatePublicAPI = exports.populateInstance = exports.getPreviousItem = exports.getNextItem = exports.getLastItem = exports.getFirstItem = void 0;
|
|
7
|
+
const getPreviousItem = (instance, itemId) => {
|
|
8
|
+
const node = instance.getNode(itemId);
|
|
9
|
+
const siblings = instance.getNavigableChildrenIds(node.parentId);
|
|
10
10
|
const itemIndex = siblings.indexOf(itemId);
|
|
11
11
|
if (itemIndex === 0) {
|
|
12
|
-
return
|
|
12
|
+
return node.parentId;
|
|
13
13
|
}
|
|
14
14
|
let currentItem = siblings[itemIndex - 1];
|
|
15
|
-
while (instance.
|
|
15
|
+
while (instance.isItemExpanded(currentItem) && instance.getNavigableChildrenIds(currentItem).length > 0) {
|
|
16
16
|
currentItem = instance.getNavigableChildrenIds(currentItem).pop();
|
|
17
17
|
}
|
|
18
18
|
return currentItem;
|
|
19
19
|
};
|
|
20
|
-
exports.
|
|
21
|
-
const
|
|
20
|
+
exports.getPreviousItem = getPreviousItem;
|
|
21
|
+
const getNextItem = (instance, itemId) => {
|
|
22
22
|
// If expanded get first child
|
|
23
|
-
if (instance.
|
|
23
|
+
if (instance.isItemExpanded(itemId) && instance.getNavigableChildrenIds(itemId).length > 0) {
|
|
24
24
|
return instance.getNavigableChildrenIds(itemId)[0];
|
|
25
25
|
}
|
|
26
|
-
let
|
|
27
|
-
while (
|
|
26
|
+
let node = instance.getNode(itemId);
|
|
27
|
+
while (node != null) {
|
|
28
28
|
// Try to get next sibling
|
|
29
|
-
const siblings = instance.getNavigableChildrenIds(
|
|
30
|
-
const nextSibling = siblings[siblings.indexOf(
|
|
29
|
+
const siblings = instance.getNavigableChildrenIds(node.parentId);
|
|
30
|
+
const nextSibling = siblings[siblings.indexOf(node.id) + 1];
|
|
31
31
|
if (nextSibling) {
|
|
32
32
|
return nextSibling;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
// If the sibling does not exist, go up a level to the parent and try again.
|
|
36
|
-
|
|
36
|
+
node = instance.getNode(node.parentId);
|
|
37
37
|
}
|
|
38
38
|
return null;
|
|
39
39
|
};
|
|
40
|
-
exports.
|
|
41
|
-
const
|
|
40
|
+
exports.getNextItem = getNextItem;
|
|
41
|
+
const getLastItem = instance => {
|
|
42
42
|
let lastItem = instance.getNavigableChildrenIds(null).pop();
|
|
43
|
-
while (instance.
|
|
43
|
+
while (instance.isItemExpanded(lastItem)) {
|
|
44
44
|
lastItem = instance.getNavigableChildrenIds(lastItem).pop();
|
|
45
45
|
}
|
|
46
46
|
return lastItem;
|
|
47
47
|
};
|
|
48
|
-
exports.
|
|
49
|
-
const
|
|
50
|
-
exports.
|
|
48
|
+
exports.getLastItem = getLastItem;
|
|
49
|
+
const getFirstItem = instance => instance.getNavigableChildrenIds(null)[0];
|
|
50
|
+
exports.getFirstItem = getFirstItem;
|
|
51
51
|
const populateInstance = (instance, methods) => {
|
|
52
52
|
Object.assign(instance, methods);
|
|
53
53
|
};
|
|
@@ -31,7 +31,7 @@ const useTreeViewModels = (plugins, props) => {
|
|
|
31
31
|
return initialState;
|
|
32
32
|
});
|
|
33
33
|
const models = Object.fromEntries(Object.entries(modelsRef.current).map(([modelName, model]) => {
|
|
34
|
-
const value =
|
|
34
|
+
const value = props[modelName] ?? modelsState[modelName];
|
|
35
35
|
return [modelName, {
|
|
36
36
|
value,
|
|
37
37
|
setControlledValue: newValue => {
|
|
@@ -62,7 +62,7 @@ const useTreeViewModels = (plugins, props) => {
|
|
|
62
62
|
if (!model.isControlled && defaultValue !== newDefaultValue) {
|
|
63
63
|
console.error([`MUI X: A component is changing the default ${modelName} state of an uncontrolled TreeView after being initialized. ` + `To suppress this warning opt to use a controlled TreeView.`].join('\n'));
|
|
64
64
|
}
|
|
65
|
-
}, [JSON.stringify(
|
|
65
|
+
}, [JSON.stringify(newDefaultValue)]);
|
|
66
66
|
});
|
|
67
67
|
}
|
|
68
68
|
/* eslint-enable react-hooks/rules-of-hooks, react-hooks/exhaustive-deps */
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mui/x-tree-view",
|
|
3
|
-
"version": "7.
|
|
4
|
-
"description": "The community edition of the
|
|
3
|
+
"version": "7.1.1",
|
|
4
|
+
"description": "The community edition of the Tree View components (MUI X).",
|
|
5
5
|
"author": "MUI Team",
|
|
6
6
|
"main": "./node/index.js",
|
|
7
7
|
"license": "MIT",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { UseTreeItem2Parameters, UseTreeItem2ReturnValue } from './useTreeItem2.types';
|
|
2
|
-
export declare const useTreeItem2: <TPlugins extends [import("../internals").UseTreeViewIdSignature, import("../internals").
|
|
2
|
+
export declare const useTreeItem2: <TPlugins extends [import("../internals").UseTreeViewIdSignature, import("../internals").UseTreeViewItemsSignature, import("../internals").UseTreeViewExpansionSignature, import("../internals").UseTreeViewSelectionSignature, import("../internals").UseTreeViewFocusSignature, import("../internals").UseTreeViewKeyboardNavigationSignature, import("../internals").UseTreeViewIconsSignature] = [import("../internals").UseTreeViewIdSignature, import("../internals").UseTreeViewItemsSignature, import("../internals").UseTreeViewExpansionSignature, import("../internals").UseTreeViewSelectionSignature, import("../internals").UseTreeViewFocusSignature, import("../internals").UseTreeViewKeyboardNavigationSignature, import("../internals").UseTreeViewIconsSignature]>(parameters: UseTreeItem2Parameters) => UseTreeItem2ReturnValue<TPlugins>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { useTreeViewJSXNodes } from './useTreeViewJSXNodes';
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { TreeViewNode, TreeViewPluginSignature } from '../../models';
|
|
2
|
-
import { UseTreeViewNodesSignature } from '../useTreeViewNodes';
|
|
3
|
-
import { UseTreeViewKeyboardNavigationSignature } from '../useTreeViewKeyboardNavigation';
|
|
4
|
-
export interface UseTreeViewNodesInstance {
|
|
5
|
-
insertJSXNode: (node: TreeViewNode) => void;
|
|
6
|
-
removeJSXNode: (itemId: string) => void;
|
|
7
|
-
mapFirstCharFromJSX: (itemId: string, firstChar: string) => () => void;
|
|
8
|
-
}
|
|
9
|
-
export interface UseTreeViewNodesParameters {
|
|
10
|
-
}
|
|
11
|
-
export interface UseTreeViewNodesDefaultizedParameters {
|
|
12
|
-
}
|
|
13
|
-
export type UseTreeViewJSXNodesSignature = TreeViewPluginSignature<{
|
|
14
|
-
params: UseTreeViewNodesParameters;
|
|
15
|
-
defaultizedParams: UseTreeViewNodesDefaultizedParameters;
|
|
16
|
-
instance: UseTreeViewNodesInstance;
|
|
17
|
-
dependantPlugins: [UseTreeViewNodesSignature, UseTreeViewKeyboardNavigationSignature];
|
|
18
|
-
}>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { useTreeViewNodes } from './useTreeViewNodes';
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { TreeViewNode, DefaultizedProps, TreeViewPluginSignature } from '../../models';
|
|
2
|
-
import { TreeViewItemId } from '../../../models';
|
|
3
|
-
interface TreeViewNodeProps {
|
|
4
|
-
label: string;
|
|
5
|
-
itemId: string;
|
|
6
|
-
id: string | undefined;
|
|
7
|
-
children?: TreeViewNodeProps[];
|
|
8
|
-
}
|
|
9
|
-
export interface UseTreeViewNodesInstance<R extends {}> {
|
|
10
|
-
getNode: (itemId: string) => TreeViewNode;
|
|
11
|
-
getItem: (itemId: string) => R;
|
|
12
|
-
getNodesToRender: () => TreeViewNodeProps[];
|
|
13
|
-
getChildrenIds: (itemId: string | null) => string[];
|
|
14
|
-
getNavigableChildrenIds: (itemId: string | null) => string[];
|
|
15
|
-
isNodeDisabled: (itemId: string | null) => itemId is string;
|
|
16
|
-
}
|
|
17
|
-
export interface UseTreeViewNodesPublicAPI<R extends {}> extends Pick<UseTreeViewNodesInstance<R>, 'getItem'> {
|
|
18
|
-
}
|
|
19
|
-
export interface UseTreeViewNodesParameters<R extends {}> {
|
|
20
|
-
/**
|
|
21
|
-
* If `true`, will allow focus on disabled items.
|
|
22
|
-
* @default false
|
|
23
|
-
*/
|
|
24
|
-
disabledItemsFocusable?: boolean;
|
|
25
|
-
items: readonly R[];
|
|
26
|
-
/**
|
|
27
|
-
* Used to determine if a given item should be disabled.
|
|
28
|
-
* @template R
|
|
29
|
-
* @param {R} item The item to check.
|
|
30
|
-
* @returns {boolean} `true` if the item should be disabled.
|
|
31
|
-
*/
|
|
32
|
-
isItemDisabled?: (item: R) => boolean;
|
|
33
|
-
/**
|
|
34
|
-
* Used to determine the string label for a given item.
|
|
35
|
-
*
|
|
36
|
-
* @template R
|
|
37
|
-
* @param {R} item The item to check.
|
|
38
|
-
* @returns {string} The label of the item.
|
|
39
|
-
* @default `(item) => item.label`
|
|
40
|
-
*/
|
|
41
|
-
getItemLabel?: (item: R) => string;
|
|
42
|
-
/**
|
|
43
|
-
* Used to determine the string label for a given item.
|
|
44
|
-
*
|
|
45
|
-
* @template R
|
|
46
|
-
* @param {R} item The item to check.
|
|
47
|
-
* @returns {string} The id of the item.
|
|
48
|
-
* @default `(item) => item.id`
|
|
49
|
-
*/
|
|
50
|
-
getItemId?: (item: R) => TreeViewItemId;
|
|
51
|
-
}
|
|
52
|
-
export type UseTreeViewNodesDefaultizedParameters<R extends {}> = DefaultizedProps<UseTreeViewNodesParameters<R>, 'disabledItemsFocusable'>;
|
|
53
|
-
interface UseTreeViewNodesEventLookup {
|
|
54
|
-
removeNode: {
|
|
55
|
-
params: {
|
|
56
|
-
id: string;
|
|
57
|
-
};
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
export interface TreeViewItemIdAndChildren {
|
|
61
|
-
id: TreeViewItemId;
|
|
62
|
-
children?: TreeViewItemIdAndChildren[];
|
|
63
|
-
}
|
|
64
|
-
export interface UseTreeViewNodesState<R extends {}> {
|
|
65
|
-
nodes: {
|
|
66
|
-
nodeTree: TreeViewItemIdAndChildren[];
|
|
67
|
-
nodeMap: TreeViewNodeMap;
|
|
68
|
-
itemMap: TreeViewItemMap<R>;
|
|
69
|
-
};
|
|
70
|
-
}
|
|
71
|
-
interface UseTreeViewNodesContextValue extends Pick<UseTreeViewNodesDefaultizedParameters<any>, 'disabledItemsFocusable'> {
|
|
72
|
-
}
|
|
73
|
-
export type UseTreeViewNodesSignature = TreeViewPluginSignature<{
|
|
74
|
-
params: UseTreeViewNodesParameters<any>;
|
|
75
|
-
defaultizedParams: UseTreeViewNodesDefaultizedParameters<any>;
|
|
76
|
-
instance: UseTreeViewNodesInstance<any>;
|
|
77
|
-
publicAPI: UseTreeViewNodesPublicAPI<any>;
|
|
78
|
-
events: UseTreeViewNodesEventLookup;
|
|
79
|
-
state: UseTreeViewNodesState<any>;
|
|
80
|
-
contextValue: UseTreeViewNodesContextValue;
|
|
81
|
-
}>;
|
|
82
|
-
export type TreeViewNodeMap = {
|
|
83
|
-
[itemId: string]: TreeViewNode;
|
|
84
|
-
};
|
|
85
|
-
export type TreeViewItemMap<R extends {}> = {
|
|
86
|
-
[itemId: string]: R;
|
|
87
|
-
};
|
|
88
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { useTreeViewJSXNodes } from './useTreeViewJSXNodes';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { useTreeViewNodes } from './useTreeViewNodes';
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
Object.defineProperty(exports, "useTreeViewJSXNodes", {
|
|
7
|
-
enumerable: true,
|
|
8
|
-
get: function () {
|
|
9
|
-
return _useTreeViewJSXNodes.useTreeViewJSXNodes;
|
|
10
|
-
}
|
|
11
|
-
});
|
|
12
|
-
var _useTreeViewJSXNodes = require("./useTreeViewJSXNodes");
|