@mui/x-tree-view 7.0.0-beta.7 → 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 +195 -12
- package/README.md +1 -1
- package/RichTreeView/RichTreeView.js +12 -14
- package/RichTreeView/RichTreeView.types.d.ts +1 -1
- package/SimpleTreeView/SimpleTreeView.js +3 -4
- package/TreeItem/TreeItem.js +43 -35
- package/TreeItem/TreeItem.types.d.ts +3 -3
- 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.js +16 -17
- package/TreeItem2Icon/TreeItem2Icon.js +5 -6
- package/TreeItem2Provider/TreeItem2Provider.js +3 -3
- package/TreeItem2Provider/TreeItem2Provider.types.d.ts +1 -1
- package/TreeView/TreeView.d.ts +1 -1
- package/TreeView/TreeView.js +1 -1
- package/hooks/useTreeItem2Utils/useTreeItem2Utils.d.ts +2 -2
- package/hooks/useTreeItem2Utils/useTreeItem2Utils.js +12 -12
- package/index.js +1 -1
- package/internals/hooks/useInstanceEventHandler.js +5 -10
- package/internals/models/plugin.d.ts +1 -1
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +11 -18
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +3 -3
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +59 -43
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +6 -5
- package/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
- package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +1 -1
- package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +17 -18
- package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.types.d.ts +2 -2
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +70 -77
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +4 -1
- package/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +24 -29
- package/internals/plugins/useTreeViewNodes/useTreeViewNodes.types.d.ts +11 -11
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +18 -21
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +4 -4
- package/internals/useTreeView/useTreeView.js +5 -6
- 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 +7 -7
- package/modern/SimpleTreeView/SimpleTreeView.js +1 -1
- package/modern/TreeItem/TreeItem.js +31 -22
- package/modern/TreeItem/TreeItemContent.js +10 -10
- package/modern/TreeItem/useTreeItemState.js +13 -13
- package/modern/TreeItem2/TreeItem2.js +11 -11
- package/modern/TreeItem2Provider/TreeItem2Provider.js +3 -3
- package/modern/TreeView/TreeView.js +1 -1
- package/modern/hooks/useTreeItem2Utils/useTreeItem2Utils.js +12 -12
- package/modern/index.js +1 -1
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +7 -7
- package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +57 -38
- package/modern/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
- package/modern/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +17 -17
- package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +69 -74
- package/modern/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +19 -20
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +13 -13
- package/modern/internals/useTreeView/useTreeView.js +3 -4
- package/modern/internals/useTreeView/useTreeView.utils.js +22 -22
- package/modern/internals/utils/utils.js +1 -0
- package/modern/useTreeItem2/useTreeItem2.js +23 -12
- package/node/RichTreeView/RichTreeView.js +7 -7
- package/node/SimpleTreeView/SimpleTreeView.js +1 -1
- package/node/TreeItem/TreeItem.js +31 -22
- package/node/TreeItem/TreeItemContent.js +10 -10
- package/node/TreeItem/useTreeItemState.js +13 -13
- package/node/TreeItem2/TreeItem2.js +11 -11
- package/node/TreeItem2Provider/TreeItem2Provider.js +3 -3
- package/node/TreeView/TreeView.js +1 -1
- package/node/hooks/useTreeItem2Utils/useTreeItem2Utils.js +12 -12
- package/node/index.js +1 -1
- package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +7 -7
- package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +57 -38
- package/node/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
- package/node/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +17 -17
- package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +69 -74
- package/node/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +19 -20
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +13 -13
- package/node/internals/useTreeView/useTreeView.js +3 -4
- package/node/internals/useTreeView/useTreeView.utils.js +22 -22
- package/node/internals/utils/utils.js +1 -0
- package/node/useTreeItem2/useTreeItem2.js +23 -12
- package/package.json +5 -5
- package/useTreeItem2/useTreeItem2.js +26 -18
- package/useTreeItem2/useTreeItem2.types.d.ts +9 -7
|
@@ -41,12 +41,12 @@ const useTreeViewJSXNodes = ({
|
|
|
41
41
|
});
|
|
42
42
|
});
|
|
43
43
|
});
|
|
44
|
-
const removeJSXNode = (0, _useEventCallback.default)(
|
|
44
|
+
const removeJSXNode = (0, _useEventCallback.default)(itemId => {
|
|
45
45
|
setState(prevState => {
|
|
46
46
|
const newNodeMap = (0, _extends2.default)({}, prevState.nodes.nodeMap);
|
|
47
47
|
const newItemMap = (0, _extends2.default)({}, prevState.nodes.itemMap);
|
|
48
|
-
delete newNodeMap[
|
|
49
|
-
delete newItemMap[
|
|
48
|
+
delete newNodeMap[itemId];
|
|
49
|
+
delete newItemMap[itemId];
|
|
50
50
|
return (0, _extends2.default)({}, prevState, {
|
|
51
51
|
nodes: (0, _extends2.default)({}, prevState.nodes, {
|
|
52
52
|
nodeMap: newNodeMap,
|
|
@@ -55,18 +55,18 @@ const useTreeViewJSXNodes = ({
|
|
|
55
55
|
});
|
|
56
56
|
});
|
|
57
57
|
(0, _publishTreeViewEvent.publishTreeViewEvent)(instance, 'removeNode', {
|
|
58
|
-
id:
|
|
58
|
+
id: itemId
|
|
59
59
|
});
|
|
60
60
|
});
|
|
61
|
-
const mapFirstCharFromJSX = (0, _useEventCallback.default)((
|
|
61
|
+
const mapFirstCharFromJSX = (0, _useEventCallback.default)((itemId, firstChar) => {
|
|
62
62
|
instance.updateFirstCharMap(firstCharMap => {
|
|
63
|
-
firstCharMap[
|
|
63
|
+
firstCharMap[itemId] = firstChar;
|
|
64
64
|
return firstCharMap;
|
|
65
65
|
});
|
|
66
66
|
return () => {
|
|
67
67
|
instance.updateFirstCharMap(firstCharMap => {
|
|
68
68
|
const newMap = (0, _extends2.default)({}, firstCharMap);
|
|
69
|
-
delete newMap[
|
|
69
|
+
delete newMap[itemId];
|
|
70
70
|
return newMap;
|
|
71
71
|
});
|
|
72
72
|
};
|
|
@@ -87,7 +87,7 @@ const useTreeViewJSXNodesItemPlugin = ({
|
|
|
87
87
|
children,
|
|
88
88
|
disabled = false,
|
|
89
89
|
label,
|
|
90
|
-
|
|
90
|
+
itemId,
|
|
91
91
|
id
|
|
92
92
|
} = props;
|
|
93
93
|
const {
|
|
@@ -106,8 +106,8 @@ const useTreeViewJSXNodesItemPlugin = ({
|
|
|
106
106
|
const handleContentRef = (0, _useForkRef.default)(pluginContentRef, contentRef);
|
|
107
107
|
const descendant = React.useMemo(() => ({
|
|
108
108
|
element: treeItemElement,
|
|
109
|
-
id:
|
|
110
|
-
}), [
|
|
109
|
+
id: itemId
|
|
110
|
+
}), [itemId, treeItemElement]);
|
|
111
111
|
const {
|
|
112
112
|
index,
|
|
113
113
|
parentId
|
|
@@ -116,23 +116,23 @@ const useTreeViewJSXNodesItemPlugin = ({
|
|
|
116
116
|
// On the first render a node's index will be -1. We want to wait for the real index.
|
|
117
117
|
if (index !== -1) {
|
|
118
118
|
instance.insertJSXNode({
|
|
119
|
-
id:
|
|
119
|
+
id: itemId,
|
|
120
120
|
idAttribute: id,
|
|
121
121
|
index,
|
|
122
122
|
parentId,
|
|
123
123
|
expandable,
|
|
124
124
|
disabled
|
|
125
125
|
});
|
|
126
|
-
return () => instance.removeJSXNode(
|
|
126
|
+
return () => instance.removeJSXNode(itemId);
|
|
127
127
|
}
|
|
128
128
|
return undefined;
|
|
129
|
-
}, [instance, parentId, index,
|
|
129
|
+
}, [instance, parentId, index, itemId, expandable, disabled, id]);
|
|
130
130
|
React.useEffect(() => {
|
|
131
131
|
if (label) {
|
|
132
|
-
return instance.mapFirstCharFromJSX(
|
|
132
|
+
return instance.mapFirstCharFromJSX(itemId, (pluginContentRef.current?.textContent ?? '').substring(0, 1).toLowerCase());
|
|
133
133
|
}
|
|
134
134
|
return undefined;
|
|
135
|
-
}, [instance,
|
|
135
|
+
}, [instance, itemId, label]);
|
|
136
136
|
return {
|
|
137
137
|
contentRef: handleContentRef,
|
|
138
138
|
rootRef: handleRootRef
|
|
@@ -141,9 +141,9 @@ const useTreeViewJSXNodesItemPlugin = ({
|
|
|
141
141
|
useTreeViewJSXNodes.itemPlugin = useTreeViewJSXNodesItemPlugin;
|
|
142
142
|
useTreeViewJSXNodes.wrapItem = ({
|
|
143
143
|
children,
|
|
144
|
-
|
|
144
|
+
itemId
|
|
145
145
|
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(_DescendantProvider.DescendantProvider, {
|
|
146
|
-
id:
|
|
146
|
+
id: itemId,
|
|
147
147
|
children: children
|
|
148
148
|
});
|
|
149
149
|
useTreeViewJSXNodes.params = {};
|
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,20 +85,17 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
89
85
|
}
|
|
90
86
|
return null;
|
|
91
87
|
};
|
|
92
|
-
const
|
|
93
|
-
const
|
|
94
|
-
return !instance.isNodeDisabled(
|
|
88
|
+
const canToggleItemSelection = itemId => !params.disableSelection && !instance.isNodeDisabled(itemId);
|
|
89
|
+
const canToggleItemExpansion = itemId => {
|
|
90
|
+
return !instance.isNodeDisabled(itemId) && instance.isNodeExpandable(itemId);
|
|
95
91
|
};
|
|
96
92
|
|
|
97
93
|
// ARIA specification: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/#keyboardinteraction
|
|
98
|
-
const
|
|
99
|
-
otherHandlers.onKeyDown?.(event);
|
|
94
|
+
const handleItemKeyDown = (event, itemId) => {
|
|
100
95
|
if (event.defaultMuiPrevented) {
|
|
101
96
|
return;
|
|
102
97
|
}
|
|
103
|
-
|
|
104
|
-
// If the tree is empty, there will be no focused node
|
|
105
|
-
if (event.altKey || event.currentTarget !== event.target || state.focusedNodeId == null) {
|
|
98
|
+
if (event.altKey || event.currentTarget !== event.target) {
|
|
106
99
|
return;
|
|
107
100
|
}
|
|
108
101
|
const ctrlPressed = event.ctrlKey || event.metaKey;
|
|
@@ -111,17 +104,17 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
111
104
|
// eslint-disable-next-line default-case
|
|
112
105
|
switch (true) {
|
|
113
106
|
// Select the node when pressing "Space"
|
|
114
|
-
case key === ' ' &&
|
|
107
|
+
case key === ' ' && canToggleItemSelection(itemId):
|
|
115
108
|
{
|
|
116
109
|
event.preventDefault();
|
|
117
110
|
if (params.multiSelect && event.shiftKey) {
|
|
118
111
|
instance.selectRange(event, {
|
|
119
|
-
end:
|
|
112
|
+
end: itemId
|
|
120
113
|
});
|
|
121
114
|
} else if (params.multiSelect) {
|
|
122
|
-
instance.selectNode(event,
|
|
115
|
+
instance.selectNode(event, itemId, true);
|
|
123
116
|
} else {
|
|
124
|
-
instance.selectNode(event,
|
|
117
|
+
instance.selectNode(event, itemId);
|
|
125
118
|
}
|
|
126
119
|
break;
|
|
127
120
|
}
|
|
@@ -130,84 +123,87 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
130
123
|
// If the focused node has no children, we select it.
|
|
131
124
|
case key === 'Enter':
|
|
132
125
|
{
|
|
133
|
-
if (
|
|
134
|
-
instance.toggleNodeExpansion(event,
|
|
126
|
+
if (canToggleItemExpansion(itemId)) {
|
|
127
|
+
instance.toggleNodeExpansion(event, itemId);
|
|
135
128
|
event.preventDefault();
|
|
136
|
-
} else if (
|
|
129
|
+
} else if (canToggleItemSelection(itemId)) {
|
|
137
130
|
if (params.multiSelect) {
|
|
138
131
|
event.preventDefault();
|
|
139
|
-
instance.selectNode(event,
|
|
140
|
-
} else if (!instance.isNodeSelected(
|
|
141
|
-
instance.selectNode(event,
|
|
132
|
+
instance.selectNode(event, itemId, true);
|
|
133
|
+
} else if (!instance.isNodeSelected(itemId)) {
|
|
134
|
+
instance.selectNode(event, itemId);
|
|
142
135
|
event.preventDefault();
|
|
143
136
|
}
|
|
144
137
|
}
|
|
145
138
|
break;
|
|
146
139
|
}
|
|
147
140
|
|
|
148
|
-
// Focus the next focusable
|
|
141
|
+
// Focus the next focusable item
|
|
149
142
|
case key === 'ArrowDown':
|
|
150
143
|
{
|
|
151
|
-
const
|
|
152
|
-
if (
|
|
144
|
+
const nextItem = (0, _useTreeView.getNextNode)(instance, itemId);
|
|
145
|
+
if (nextItem) {
|
|
153
146
|
event.preventDefault();
|
|
154
|
-
instance.focusItem(event,
|
|
147
|
+
instance.focusItem(event, nextItem);
|
|
155
148
|
|
|
156
149
|
// Multi select behavior when pressing Shift + ArrowDown
|
|
157
|
-
// Toggles the selection state of the next
|
|
158
|
-
if (params.multiSelect && event.shiftKey &&
|
|
150
|
+
// Toggles the selection state of the next item
|
|
151
|
+
if (params.multiSelect && event.shiftKey && canToggleItemSelection(nextItem)) {
|
|
159
152
|
instance.selectRange(event, {
|
|
160
|
-
end:
|
|
161
|
-
current:
|
|
153
|
+
end: nextItem,
|
|
154
|
+
current: itemId
|
|
162
155
|
}, true);
|
|
163
156
|
}
|
|
164
157
|
}
|
|
165
158
|
break;
|
|
166
159
|
}
|
|
167
160
|
|
|
168
|
-
// Focuses the previous focusable
|
|
161
|
+
// Focuses the previous focusable item
|
|
169
162
|
case key === 'ArrowUp':
|
|
170
163
|
{
|
|
171
|
-
const
|
|
172
|
-
if (
|
|
164
|
+
const previousItem = (0, _useTreeView.getPreviousNode)(instance, itemId);
|
|
165
|
+
if (previousItem) {
|
|
173
166
|
event.preventDefault();
|
|
174
|
-
instance.focusItem(event,
|
|
167
|
+
instance.focusItem(event, previousItem);
|
|
175
168
|
|
|
176
169
|
// Multi select behavior when pressing Shift + ArrowUp
|
|
177
|
-
// Toggles the selection state of the previous
|
|
178
|
-
if (params.multiSelect && event.shiftKey &&
|
|
170
|
+
// Toggles the selection state of the previous item
|
|
171
|
+
if (params.multiSelect && event.shiftKey && canToggleItemSelection(previousItem)) {
|
|
179
172
|
instance.selectRange(event, {
|
|
180
|
-
end:
|
|
181
|
-
current:
|
|
173
|
+
end: previousItem,
|
|
174
|
+
current: itemId
|
|
182
175
|
}, true);
|
|
183
176
|
}
|
|
184
177
|
}
|
|
185
178
|
break;
|
|
186
179
|
}
|
|
187
180
|
|
|
188
|
-
// If the focused
|
|
189
|
-
// 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
|
|
190
183
|
case key === 'ArrowRight' && !isRTL || key === 'ArrowLeft' && isRTL:
|
|
191
184
|
{
|
|
192
|
-
if (instance.isNodeExpanded(
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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);
|
|
197
193
|
event.preventDefault();
|
|
198
194
|
}
|
|
199
195
|
break;
|
|
200
196
|
}
|
|
201
197
|
|
|
202
|
-
// If the focused
|
|
203
|
-
// 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
|
|
204
200
|
case key === 'ArrowLeft' && !isRTL || key === 'ArrowRight' && isRTL:
|
|
205
201
|
{
|
|
206
|
-
if (
|
|
207
|
-
instance.toggleNodeExpansion(event,
|
|
202
|
+
if (canToggleItemExpansion(itemId) && instance.isNodeExpanded(itemId)) {
|
|
203
|
+
instance.toggleNodeExpansion(event, itemId);
|
|
208
204
|
event.preventDefault();
|
|
209
205
|
} else {
|
|
210
|
-
const parent = instance.getNode(
|
|
206
|
+
const parent = instance.getNode(itemId).parentId;
|
|
211
207
|
if (parent) {
|
|
212
208
|
instance.focusItem(event, parent);
|
|
213
209
|
event.preventDefault();
|
|
@@ -223,31 +219,31 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
223
219
|
|
|
224
220
|
// Multi select behavior when pressing Ctrl + Shift + Home
|
|
225
221
|
// Selects the focused node and all nodes up to the first node.
|
|
226
|
-
if (
|
|
227
|
-
instance.rangeSelectToFirst(event,
|
|
222
|
+
if (canToggleItemSelection(itemId) && params.multiSelect && ctrlPressed && event.shiftKey) {
|
|
223
|
+
instance.rangeSelectToFirst(event, itemId);
|
|
228
224
|
}
|
|
229
225
|
event.preventDefault();
|
|
230
226
|
break;
|
|
231
227
|
}
|
|
232
228
|
|
|
233
|
-
// Focuses the last
|
|
229
|
+
// Focuses the last item in the tree
|
|
234
230
|
case key === 'End':
|
|
235
231
|
{
|
|
236
232
|
instance.focusItem(event, (0, _useTreeView.getLastNode)(instance));
|
|
237
233
|
|
|
238
234
|
// Multi select behavior when pressing Ctrl + Shirt + End
|
|
239
|
-
// Selects the focused
|
|
240
|
-
if (
|
|
241
|
-
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);
|
|
242
238
|
}
|
|
243
239
|
event.preventDefault();
|
|
244
240
|
break;
|
|
245
241
|
}
|
|
246
242
|
|
|
247
|
-
// 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
|
|
248
244
|
case key === '*':
|
|
249
245
|
{
|
|
250
|
-
instance.expandAllSiblings(event,
|
|
246
|
+
instance.expandAllSiblings(event, itemId);
|
|
251
247
|
event.preventDefault();
|
|
252
248
|
break;
|
|
253
249
|
}
|
|
@@ -268,7 +264,7 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
268
264
|
// TODO: Support typing multiple characters
|
|
269
265
|
case !ctrlPressed && !event.shiftKey && isPrintableCharacter(key):
|
|
270
266
|
{
|
|
271
|
-
const matchingNode =
|
|
267
|
+
const matchingNode = getFirstMatchingItem(itemId, key);
|
|
272
268
|
if (matchingNode != null) {
|
|
273
269
|
instance.focusItem(event, matchingNode);
|
|
274
270
|
event.preventDefault();
|
|
@@ -277,11 +273,10 @@ const useTreeViewKeyboardNavigation = ({
|
|
|
277
273
|
}
|
|
278
274
|
}
|
|
279
275
|
};
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
};
|
|
276
|
+
(0, _useTreeView.populateInstance)(instance, {
|
|
277
|
+
updateFirstCharMap,
|
|
278
|
+
handleItemKeyDown
|
|
279
|
+
});
|
|
285
280
|
};
|
|
286
281
|
exports.useTreeViewKeyboardNavigation = useTreeViewKeyboardNavigation;
|
|
287
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
|
};
|
|
@@ -113,19 +112,19 @@ const useTreeViewNodes = ({
|
|
|
113
112
|
});
|
|
114
113
|
}, [instance, setState, params.items, params.isItemDisabled, params.getItemId, params.getItemLabel]);
|
|
115
114
|
const getNodesToRender = () => {
|
|
116
|
-
const
|
|
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(
|
|
127
|
+
return state.nodes.nodeTree.map(getPropsFromItemId);
|
|
129
128
|
};
|
|
130
129
|
(0, _useTreeView.populateInstance)(instance, {
|
|
131
130
|
getNode,
|
|
@@ -44,26 +44,26 @@ const useTreeViewSelection = ({
|
|
|
44
44
|
}
|
|
45
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
53
|
if (Array.isArray(models.selectedItems.value)) {
|
|
54
54
|
let newSelected;
|
|
55
|
-
if (models.selectedItems.value.indexOf(
|
|
56
|
-
newSelected = models.selectedItems.value.filter(id => id !==
|
|
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 ? [
|
|
63
|
+
const newSelected = params.multiSelect ? [itemId] : itemId;
|
|
64
64
|
setSelectedItems(event, newSelected);
|
|
65
65
|
}
|
|
66
|
-
lastSelectedNode.current =
|
|
66
|
+
lastSelectedNode.current = itemId;
|
|
67
67
|
lastSelectionWasRange.current = false;
|
|
68
68
|
currentRangeSelection.current = [];
|
|
69
69
|
};
|
|
@@ -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)
|
|
@@ -97,13 +97,13 @@ const useTreeView = inParams => {
|
|
|
97
97
|
};
|
|
98
98
|
const itemWrappers = plugins.map(plugin => plugin.wrapItem).filter(wrapItem => !!wrapItem);
|
|
99
99
|
contextValue.wrapItem = ({
|
|
100
|
-
|
|
100
|
+
itemId,
|
|
101
101
|
children
|
|
102
102
|
}) => {
|
|
103
103
|
let finalChildren = children;
|
|
104
104
|
itemWrappers.forEach(itemWrapper => {
|
|
105
105
|
finalChildren = itemWrapper({
|
|
106
|
-
|
|
106
|
+
itemId,
|
|
107
107
|
children: finalChildren
|
|
108
108
|
});
|
|
109
109
|
});
|
|
@@ -111,8 +111,7 @@ const useTreeView = inParams => {
|
|
|
111
111
|
};
|
|
112
112
|
const getRootProps = (otherHandlers = {}) => {
|
|
113
113
|
const rootProps = (0, _extends2.default)({
|
|
114
|
-
role: 'tree'
|
|
115
|
-
tabIndex: 0
|
|
114
|
+
role: 'tree'
|
|
116
115
|
}, otherHandlers, {
|
|
117
116
|
ref: handleRootRef
|
|
118
117
|
});
|
|
@@ -4,46 +4,46 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.populatePublicAPI = exports.populateInstance = exports.getPreviousNode = exports.getNextNode = exports.getLastNode = exports.getFirstNode = void 0;
|
|
7
|
-
const getPreviousNode = (instance,
|
|
8
|
-
const
|
|
9
|
-
const siblings = instance.getNavigableChildrenIds(
|
|
10
|
-
const
|
|
11
|
-
if (
|
|
12
|
-
return
|
|
7
|
+
const getPreviousNode = (instance, itemId) => {
|
|
8
|
+
const item = instance.getNode(itemId);
|
|
9
|
+
const siblings = instance.getNavigableChildrenIds(item.parentId);
|
|
10
|
+
const itemIndex = siblings.indexOf(itemId);
|
|
11
|
+
if (itemIndex === 0) {
|
|
12
|
+
return item.parentId;
|
|
13
13
|
}
|
|
14
|
-
let
|
|
15
|
-
while (instance.isNodeExpanded(
|
|
16
|
-
|
|
14
|
+
let currentItem = siblings[itemIndex - 1];
|
|
15
|
+
while (instance.isNodeExpanded(currentItem) && instance.getNavigableChildrenIds(currentItem).length > 0) {
|
|
16
|
+
currentItem = instance.getNavigableChildrenIds(currentItem).pop();
|
|
17
17
|
}
|
|
18
|
-
return
|
|
18
|
+
return currentItem;
|
|
19
19
|
};
|
|
20
20
|
exports.getPreviousNode = getPreviousNode;
|
|
21
|
-
const getNextNode = (instance,
|
|
21
|
+
const getNextNode = (instance, itemId) => {
|
|
22
22
|
// If expanded get first child
|
|
23
|
-
if (instance.isNodeExpanded(
|
|
24
|
-
return instance.getNavigableChildrenIds(
|
|
23
|
+
if (instance.isNodeExpanded(itemId) && instance.getNavigableChildrenIds(itemId).length > 0) {
|
|
24
|
+
return instance.getNavigableChildrenIds(itemId)[0];
|
|
25
25
|
}
|
|
26
|
-
let
|
|
27
|
-
while (
|
|
26
|
+
let item = instance.getNode(itemId);
|
|
27
|
+
while (item != null) {
|
|
28
28
|
// Try to get next sibling
|
|
29
|
-
const siblings = instance.getNavigableChildrenIds(
|
|
30
|
-
const nextSibling = siblings[siblings.indexOf(
|
|
29
|
+
const siblings = instance.getNavigableChildrenIds(item.parentId);
|
|
30
|
+
const nextSibling = siblings[siblings.indexOf(item.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
|
+
item = instance.getNode(item.parentId);
|
|
37
37
|
}
|
|
38
38
|
return null;
|
|
39
39
|
};
|
|
40
40
|
exports.getNextNode = getNextNode;
|
|
41
41
|
const getLastNode = instance => {
|
|
42
|
-
let
|
|
43
|
-
while (instance.isNodeExpanded(
|
|
44
|
-
|
|
42
|
+
let lastItem = instance.getNavigableChildrenIds(null).pop();
|
|
43
|
+
while (instance.isNodeExpanded(lastItem)) {
|
|
44
|
+
lastItem = instance.getNavigableChildrenIds(lastItem).pop();
|
|
45
45
|
}
|
|
46
|
-
return
|
|
46
|
+
return lastItem;
|
|
47
47
|
};
|
|
48
48
|
exports.getLastNode = getLastNode;
|
|
49
49
|
const getFirstNode = instance => instance.getNavigableChildrenIds(null)[0];
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.getActiveElement = void 0;
|
|
7
|
+
// https://www.abeautifulsite.net/posts/finding-the-active-element-in-a-shadow-root/
|
|
7
8
|
const getActiveElement = (root = document) => {
|
|
8
9
|
const activeEl = root.activeElement;
|
|
9
10
|
if (!activeEl) {
|