@mui/x-tree-view 7.0.0-beta.7 → 7.1.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 +266 -12
- package/README.md +1 -1
- package/RichTreeView/RichTreeView.js +15 -17
- package/RichTreeView/RichTreeView.types.d.ts +1 -1
- package/SimpleTreeView/SimpleTreeView.js +3 -4
- package/SimpleTreeView/SimpleTreeView.plugins.d.ts +1 -1
- package/SimpleTreeView/SimpleTreeView.plugins.js +2 -2
- 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/treeItemClasses.d.ts +1 -1
- 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/TreeItem2Icon/TreeItem2Icon.types.d.ts +4 -4
- 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/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/hooks/useInstanceEventHandler.js +5 -10
- package/internals/index.d.ts +2 -2
- 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 +17 -24
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +6 -6
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +76 -58
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +9 -8
- package/internals/plugins/useTreeViewIcons/useTreeViewIcons.types.d.ts +6 -6
- package/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
- package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +2 -2
- 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/{modern/internals/plugins/useTreeViewNodes/useTreeViewNodes.js → internals/plugins/useTreeViewItems/useTreeViewItems.js} +42 -33
- package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +99 -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} +41 -40
- package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.types.d.ts +18 -0
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +85 -96
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +6 -3
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +44 -47
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +8 -8
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.d.ts +7 -7
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +5 -5
- package/internals/useTreeView/useTreeView.js +5 -6
- package/internals/useTreeView/useTreeView.utils.d.ts +5 -5
- package/internals/useTreeView/useTreeView.utils.js +18 -18
- package/internals/utils/extractPluginParamsFromProps.js +2 -2
- package/internals/utils/utils.js +1 -0
- package/modern/RichTreeView/RichTreeView.js +11 -11
- package/modern/SimpleTreeView/SimpleTreeView.js +1 -1
- package/modern/SimpleTreeView/SimpleTreeView.plugins.js +2 -2
- 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/TreeViewProvider/DescendantProvider.js +1 -1
- package/modern/internals/plugins/defaultPlugins.js +2 -2
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +14 -14
- package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +74 -53
- package/modern/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
- package/modern/internals/plugins/useTreeViewItems/index.js +1 -0
- package/{internals/plugins/useTreeViewNodes/useTreeViewNodes.js → modern/internals/plugins/useTreeViewItems/useTreeViewItems.js} +46 -41
- package/modern/internals/plugins/useTreeViewJSXItems/index.js +1 -0
- package/{internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js → modern/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js} +41 -41
- package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +85 -94
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +40 -40
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +5 -5
- package/modern/internals/useTreeView/useTreeView.js +3 -4
- package/modern/internals/useTreeView/useTreeView.utils.js +18 -18
- package/modern/internals/utils/utils.js +1 -0
- package/modern/useTreeItem2/useTreeItem2.js +23 -12
- package/node/RichTreeView/RichTreeView.js +11 -11
- package/node/SimpleTreeView/SimpleTreeView.js +1 -1
- package/node/SimpleTreeView/SimpleTreeView.plugins.js +2 -2
- 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/TreeViewProvider/DescendantProvider.js +1 -1
- package/node/internals/plugins/defaultPlugins.js +2 -2
- package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +14 -14
- package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +74 -53
- package/node/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
- package/node/internals/plugins/useTreeViewItems/index.js +12 -0
- package/node/internals/plugins/{useTreeViewNodes/useTreeViewNodes.js → useTreeViewItems/useTreeViewItems.js} +44 -35
- package/node/internals/plugins/useTreeViewJSXItems/index.js +12 -0
- package/node/internals/plugins/{useTreeViewJSXNodes/useTreeViewJSXNodes.js → useTreeViewJSXItems/useTreeViewJSXItems.js} +43 -42
- package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +84 -93
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +39 -39
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +5 -5
- package/node/internals/useTreeView/useTreeView.js +3 -4
- package/node/internals/useTreeView/useTreeView.utils.js +23 -23
- package/node/internals/utils/utils.js +1 -0
- package/node/useTreeItem2/useTreeItem2.js +23 -12
- package/package.json +5 -5
- package/useTreeItem2/useTreeItem2.d.ts +1 -1
- package/useTreeItem2/useTreeItem2.js +26 -18
- package/useTreeItem2/useTreeItem2.types.d.ts +9 -7
- 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
|
@@ -11,11 +11,11 @@ export const useTreeViewExpansion = ({
|
|
|
11
11
|
params.onExpandedItemsChange?.(event, value);
|
|
12
12
|
models.expandedItems.setControlledValue(value);
|
|
13
13
|
};
|
|
14
|
-
const
|
|
15
|
-
return Array.isArray(models.expandedItems.value) ? models.expandedItems.value.indexOf(
|
|
14
|
+
const isItemExpanded = React.useCallback(itemId => {
|
|
15
|
+
return Array.isArray(models.expandedItems.value) ? models.expandedItems.value.indexOf(itemId) !== -1 : false;
|
|
16
16
|
}, [models.expandedItems.value]);
|
|
17
|
-
const
|
|
18
|
-
const
|
|
17
|
+
const isItemExpandable = React.useCallback(itemId => !!instance.getNode(itemId)?.expandable, [instance]);
|
|
18
|
+
const toggleItemExpansion = useEventCallback((event, itemId) => {
|
|
19
19
|
if (itemId == null) {
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
@@ -31,24 +31,24 @@ export const useTreeViewExpansion = ({
|
|
|
31
31
|
}
|
|
32
32
|
setExpandedItems(event, newExpanded);
|
|
33
33
|
});
|
|
34
|
-
const expandAllSiblings = (event,
|
|
35
|
-
const node = instance.getNode(
|
|
34
|
+
const expandAllSiblings = (event, itemId) => {
|
|
35
|
+
const node = instance.getNode(itemId);
|
|
36
36
|
const siblings = instance.getChildrenIds(node.parentId);
|
|
37
|
-
const diff = siblings.filter(child => instance.
|
|
37
|
+
const diff = siblings.filter(child => instance.isItemExpandable(child) && !instance.isItemExpanded(child));
|
|
38
38
|
const newExpanded = models.expandedItems.value.concat(diff);
|
|
39
39
|
if (diff.length > 0) {
|
|
40
40
|
if (params.onItemExpansionToggle) {
|
|
41
|
-
diff.forEach(
|
|
42
|
-
params.onItemExpansionToggle(event,
|
|
41
|
+
diff.forEach(newlyExpandedItemId => {
|
|
42
|
+
params.onItemExpansionToggle(event, newlyExpandedItemId, true);
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
setExpandedItems(event, newExpanded);
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
48
|
populateInstance(instance, {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
isItemExpanded,
|
|
50
|
+
isItemExpandable,
|
|
51
|
+
toggleItemExpansion,
|
|
52
52
|
expandAllSiblings
|
|
53
53
|
});
|
|
54
54
|
};
|
|
@@ -57,9 +57,9 @@ useTreeViewExpansion.models = {
|
|
|
57
57
|
getDefaultValue: params => params.defaultExpandedItems
|
|
58
58
|
}
|
|
59
59
|
};
|
|
60
|
-
const
|
|
60
|
+
const DEFAULT_EXPANDED_ITEMS = [];
|
|
61
61
|
useTreeViewExpansion.getDefaultizedParams = params => _extends({}, params, {
|
|
62
|
-
defaultExpandedItems: params.defaultExpandedItems ??
|
|
62
|
+
defaultExpandedItems: params.defaultExpandedItems ?? DEFAULT_EXPANDED_ITEMS
|
|
63
63
|
});
|
|
64
64
|
useTreeViewExpansion.params = {
|
|
65
65
|
expandedItems: true,
|
|
@@ -5,6 +5,22 @@ import ownerDocument from '@mui/utils/ownerDocument';
|
|
|
5
5
|
import { populateInstance, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
|
|
6
6
|
import { useInstanceEventHandler } from '../../hooks/useInstanceEventHandler';
|
|
7
7
|
import { getActiveElement } from '../../utils/utils';
|
|
8
|
+
const useTabbableItemId = (instance, selectedItems) => {
|
|
9
|
+
const isItemVisible = itemId => {
|
|
10
|
+
const node = instance.getNode(itemId);
|
|
11
|
+
return node && (node.parentId == null || instance.isItemExpanded(node.parentId));
|
|
12
|
+
};
|
|
13
|
+
let tabbableItemId;
|
|
14
|
+
if (Array.isArray(selectedItems)) {
|
|
15
|
+
tabbableItemId = selectedItems.find(isItemVisible);
|
|
16
|
+
} else if (selectedItems != null && isItemVisible(selectedItems)) {
|
|
17
|
+
tabbableItemId = selectedItems;
|
|
18
|
+
}
|
|
19
|
+
if (tabbableItemId == null) {
|
|
20
|
+
tabbableItemId = instance.getNavigableChildrenIds(null)[0];
|
|
21
|
+
}
|
|
22
|
+
return tabbableItemId;
|
|
23
|
+
};
|
|
8
24
|
export const useTreeViewFocus = ({
|
|
9
25
|
instance,
|
|
10
26
|
publicAPI,
|
|
@@ -14,94 +30,99 @@ export const useTreeViewFocus = ({
|
|
|
14
30
|
models,
|
|
15
31
|
rootRef
|
|
16
32
|
}) => {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
33
|
+
const tabbableItemId = useTabbableItemId(instance, models.selectedItems.value);
|
|
34
|
+
const setFocusedItemId = useEventCallback(itemId => {
|
|
35
|
+
const cleanItemId = typeof itemId === 'function' ? itemId(state.focusedItemId) : itemId;
|
|
36
|
+
if (state.focusedItemId !== cleanItemId) {
|
|
20
37
|
setState(prevState => _extends({}, prevState, {
|
|
21
|
-
|
|
38
|
+
focusedItemId: cleanItemId
|
|
22
39
|
}));
|
|
23
40
|
}
|
|
24
41
|
});
|
|
25
|
-
const isTreeViewFocused = React.useCallback(() => !!rootRef.current && rootRef.current
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const node = instance.getNode(
|
|
29
|
-
return node && (node.parentId == null || instance.
|
|
42
|
+
const isTreeViewFocused = React.useCallback(() => !!rootRef.current && rootRef.current.contains(getActiveElement(ownerDocument(rootRef.current))), [rootRef]);
|
|
43
|
+
const isItemFocused = React.useCallback(itemId => state.focusedItemId === itemId && isTreeViewFocused(), [state.focusedItemId, isTreeViewFocused]);
|
|
44
|
+
const isItemVisible = itemId => {
|
|
45
|
+
const node = instance.getNode(itemId);
|
|
46
|
+
return node && (node.parentId == null || instance.isItemExpanded(node.parentId));
|
|
30
47
|
};
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
48
|
+
const innerFocusItem = (event, itemId) => {
|
|
49
|
+
const node = instance.getNode(itemId);
|
|
50
|
+
const itemElement = document.getElementById(instance.getTreeItemId(itemId, node.idAttribute));
|
|
51
|
+
if (itemElement) {
|
|
52
|
+
itemElement.focus();
|
|
53
|
+
}
|
|
54
|
+
setFocusedItemId(itemId);
|
|
55
|
+
if (params.onItemFocus) {
|
|
56
|
+
params.onItemFocus(event, itemId);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const focusItem = useEventCallback((event, itemId) => {
|
|
60
|
+
// If we receive an itemId, and it is visible, the focus will be set to it
|
|
61
|
+
if (isItemVisible(itemId)) {
|
|
62
|
+
innerFocusItem(event, itemId);
|
|
41
63
|
}
|
|
42
64
|
});
|
|
43
|
-
const
|
|
44
|
-
let
|
|
65
|
+
const focusDefaultItem = useEventCallback(event => {
|
|
66
|
+
let itemToFocusId;
|
|
45
67
|
if (Array.isArray(models.selectedItems.value)) {
|
|
46
|
-
|
|
47
|
-
} else if (models.selectedItems.value != null &&
|
|
48
|
-
|
|
68
|
+
itemToFocusId = models.selectedItems.value.find(isItemVisible);
|
|
69
|
+
} else if (models.selectedItems.value != null && isItemVisible(models.selectedItems.value)) {
|
|
70
|
+
itemToFocusId = models.selectedItems.value;
|
|
49
71
|
}
|
|
50
|
-
if (
|
|
51
|
-
|
|
52
|
-
}
|
|
53
|
-
setFocusedNodeId(nodeToFocusId);
|
|
54
|
-
if (params.onItemFocus) {
|
|
55
|
-
params.onItemFocus(event, nodeToFocusId);
|
|
72
|
+
if (itemToFocusId == null) {
|
|
73
|
+
itemToFocusId = instance.getNavigableChildrenIds(null)[0];
|
|
56
74
|
}
|
|
75
|
+
innerFocusItem(event, itemToFocusId);
|
|
57
76
|
});
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
77
|
+
const removeFocusedItem = useEventCallback(() => {
|
|
78
|
+
if (state.focusedItemId == null) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const node = instance.getNode(state.focusedItemId);
|
|
82
|
+
if (node) {
|
|
83
|
+
const itemElement = document.getElementById(instance.getTreeItemId(state.focusedItemId, node.idAttribute));
|
|
84
|
+
if (itemElement) {
|
|
85
|
+
itemElement.blur();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
setFocusedItemId(null);
|
|
62
89
|
});
|
|
90
|
+
const canItemBeTabbed = itemId => itemId === tabbableItemId;
|
|
63
91
|
populateInstance(instance, {
|
|
64
|
-
|
|
92
|
+
isItemFocused,
|
|
93
|
+
canItemBeTabbed,
|
|
65
94
|
focusItem,
|
|
66
|
-
|
|
67
|
-
|
|
95
|
+
focusDefaultItem,
|
|
96
|
+
removeFocusedItem
|
|
68
97
|
});
|
|
69
98
|
populatePublicAPI(publicAPI, {
|
|
70
99
|
focusItem
|
|
71
100
|
});
|
|
72
|
-
useInstanceEventHandler(instance, '
|
|
101
|
+
useInstanceEventHandler(instance, 'removeItem', ({
|
|
73
102
|
id
|
|
74
103
|
}) => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
return oldFocusedNodeId;
|
|
80
|
-
});
|
|
104
|
+
if (state.focusedItemId === id) {
|
|
105
|
+
instance.focusDefaultItem(null);
|
|
106
|
+
}
|
|
81
107
|
});
|
|
82
108
|
const createHandleFocus = otherHandlers => event => {
|
|
83
109
|
otherHandlers.onFocus?.(event);
|
|
84
110
|
// if the event bubbled (which is React specific) we don't want to steal focus
|
|
85
111
|
if (event.target === event.currentTarget) {
|
|
86
|
-
instance.
|
|
112
|
+
instance.focusDefaultItem(event);
|
|
87
113
|
}
|
|
88
114
|
};
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
setFocusedNodeId(null);
|
|
92
|
-
};
|
|
93
|
-
const focusedNode = instance.getNode(state.focusedNodeId);
|
|
94
|
-
const activeDescendant = focusedNode ? instance.getTreeItemId(focusedNode.id, focusedNode.idAttribute) : null;
|
|
115
|
+
const focusedItem = instance.getNode(state.focusedItemId);
|
|
116
|
+
const activeDescendant = focusedItem ? instance.getTreeItemId(focusedItem.id, focusedItem.idAttribute) : null;
|
|
95
117
|
return {
|
|
96
118
|
getRootProps: otherHandlers => ({
|
|
97
119
|
onFocus: createHandleFocus(otherHandlers),
|
|
98
|
-
onBlur: createHandleBlur(otherHandlers),
|
|
99
120
|
'aria-activedescendant': activeDescendant ?? undefined
|
|
100
121
|
})
|
|
101
122
|
};
|
|
102
123
|
};
|
|
103
124
|
useTreeViewFocus.getInitialState = () => ({
|
|
104
|
-
|
|
125
|
+
focusedItemId: null
|
|
105
126
|
});
|
|
106
127
|
useTreeViewFocus.params = {
|
|
107
128
|
onItemFocus: true
|
|
@@ -6,7 +6,7 @@ export const useTreeViewId = ({
|
|
|
6
6
|
params
|
|
7
7
|
}) => {
|
|
8
8
|
const treeId = useId(params.id);
|
|
9
|
-
const getTreeItemId = React.useCallback((
|
|
9
|
+
const getTreeItemId = React.useCallback((itemId, idAttribute) => idAttribute ?? `${treeId}-${itemId}`, [treeId]);
|
|
10
10
|
populateInstance(instance, {
|
|
11
11
|
getTreeItemId
|
|
12
12
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useTreeViewItems } from './useTreeViewItems';
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import useEventCallback from '@mui/utils/useEventCallback';
|
|
4
3
|
import { populateInstance, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
|
|
5
4
|
import { publishTreeViewEvent } from '../../utils/publishTreeViewEvent';
|
|
6
|
-
const
|
|
5
|
+
const updateItemsState = ({
|
|
7
6
|
items,
|
|
8
7
|
isItemDisabled,
|
|
9
8
|
getItemLabel,
|
|
@@ -12,7 +11,6 @@ const updateNodesState = ({
|
|
|
12
11
|
const nodeMap = {};
|
|
13
12
|
const itemMap = {};
|
|
14
13
|
const processItem = (item, index, parentId) => {
|
|
15
|
-
var _item$children, _item$children2;
|
|
16
14
|
const id = getItemId ? getItemId(item) : item.id;
|
|
17
15
|
if (id == null) {
|
|
18
16
|
throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', 'An item was provided without id in the `items` prop:', JSON.stringify(item)].join('\n'));
|
|
@@ -30,13 +28,13 @@ const updateNodesState = ({
|
|
|
30
28
|
index,
|
|
31
29
|
parentId,
|
|
32
30
|
idAttribute: undefined,
|
|
33
|
-
expandable: !!
|
|
31
|
+
expandable: !!item.children?.length,
|
|
34
32
|
disabled: isItemDisabled ? isItemDisabled(item) : false
|
|
35
33
|
};
|
|
36
34
|
itemMap[id] = item;
|
|
37
35
|
return {
|
|
38
36
|
id,
|
|
39
|
-
children:
|
|
37
|
+
children: item.children?.map((child, childIndex) => processItem(child, childIndex, id))
|
|
40
38
|
};
|
|
41
39
|
};
|
|
42
40
|
const nodeTree = items.map((item, itemIndex) => processItem(item, itemIndex, null));
|
|
@@ -46,22 +44,22 @@ const updateNodesState = ({
|
|
|
46
44
|
itemMap
|
|
47
45
|
};
|
|
48
46
|
};
|
|
49
|
-
export const
|
|
47
|
+
export const useTreeViewItems = ({
|
|
50
48
|
instance,
|
|
51
49
|
publicAPI,
|
|
52
50
|
params,
|
|
53
51
|
state,
|
|
54
52
|
setState
|
|
55
53
|
}) => {
|
|
56
|
-
const getNode = React.useCallback(
|
|
57
|
-
const getItem = React.useCallback(
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
54
|
+
const getNode = React.useCallback(itemId => state.items.nodeMap[itemId], [state.items.nodeMap]);
|
|
55
|
+
const getItem = React.useCallback(itemId => state.items.itemMap[itemId], [state.items.itemMap]);
|
|
56
|
+
const isItemDisabled = React.useCallback(itemId => {
|
|
57
|
+
if (itemId == null) {
|
|
60
58
|
return false;
|
|
61
59
|
}
|
|
62
|
-
let node = instance.getNode(
|
|
60
|
+
let node = instance.getNode(itemId);
|
|
63
61
|
|
|
64
|
-
// This can be called before the
|
|
62
|
+
// This can be called before the item has been added to the item map.
|
|
65
63
|
if (!node) {
|
|
66
64
|
return false;
|
|
67
65
|
}
|
|
@@ -76,56 +74,66 @@ export const useTreeViewNodes = ({
|
|
|
76
74
|
}
|
|
77
75
|
return false;
|
|
78
76
|
}, [instance]);
|
|
79
|
-
const getChildrenIds =
|
|
80
|
-
const getNavigableChildrenIds =
|
|
81
|
-
let childrenIds = instance.getChildrenIds(
|
|
77
|
+
const getChildrenIds = React.useCallback(itemId => Object.values(state.items.nodeMap).filter(item => item.parentId === itemId).sort((a, b) => a.index - b.index).map(child => child.id), [state.items.nodeMap]);
|
|
78
|
+
const getNavigableChildrenIds = itemId => {
|
|
79
|
+
let childrenIds = instance.getChildrenIds(itemId);
|
|
82
80
|
if (!params.disabledItemsFocusable) {
|
|
83
|
-
childrenIds = childrenIds.filter(
|
|
81
|
+
childrenIds = childrenIds.filter(item => !instance.isItemDisabled(item));
|
|
84
82
|
}
|
|
85
83
|
return childrenIds;
|
|
86
84
|
};
|
|
85
|
+
const areItemUpdatesPreventedRef = React.useRef(false);
|
|
86
|
+
const preventItemUpdates = React.useCallback(() => {
|
|
87
|
+
areItemUpdatesPreventedRef.current = true;
|
|
88
|
+
}, []);
|
|
89
|
+
const areItemUpdatesPrevented = React.useCallback(() => areItemUpdatesPreventedRef.current, []);
|
|
87
90
|
React.useEffect(() => {
|
|
91
|
+
if (instance.areItemUpdatesPrevented()) {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
88
94
|
setState(prevState => {
|
|
89
|
-
const newState =
|
|
95
|
+
const newState = updateItemsState({
|
|
90
96
|
items: params.items,
|
|
91
97
|
isItemDisabled: params.isItemDisabled,
|
|
92
98
|
getItemId: params.getItemId,
|
|
93
99
|
getItemLabel: params.getItemLabel
|
|
94
100
|
});
|
|
95
|
-
Object.values(prevState.
|
|
96
|
-
if (!newState.nodeMap[
|
|
97
|
-
publishTreeViewEvent(instance, '
|
|
98
|
-
id:
|
|
101
|
+
Object.values(prevState.items.nodeMap).forEach(item => {
|
|
102
|
+
if (!newState.nodeMap[item.id]) {
|
|
103
|
+
publishTreeViewEvent(instance, 'removeItem', {
|
|
104
|
+
id: item.id
|
|
99
105
|
});
|
|
100
106
|
}
|
|
101
107
|
});
|
|
102
108
|
return _extends({}, prevState, {
|
|
103
|
-
|
|
109
|
+
items: newState
|
|
104
110
|
});
|
|
105
111
|
});
|
|
106
112
|
}, [instance, setState, params.items, params.isItemDisabled, params.getItemId, params.getItemLabel]);
|
|
107
|
-
const
|
|
108
|
-
const
|
|
113
|
+
const getItemsToRender = () => {
|
|
114
|
+
const getPropsFromItemId = ({
|
|
109
115
|
id,
|
|
110
116
|
children
|
|
111
117
|
}) => {
|
|
112
|
-
const
|
|
118
|
+
const item = state.items.nodeMap[id];
|
|
113
119
|
return {
|
|
114
|
-
label:
|
|
115
|
-
|
|
116
|
-
id:
|
|
117
|
-
children: children
|
|
120
|
+
label: item.label,
|
|
121
|
+
itemId: item.id,
|
|
122
|
+
id: item.idAttribute,
|
|
123
|
+
children: children?.map(getPropsFromItemId)
|
|
118
124
|
};
|
|
119
125
|
};
|
|
120
|
-
return state.
|
|
126
|
+
return state.items.nodeTree.map(getPropsFromItemId);
|
|
121
127
|
};
|
|
122
128
|
populateInstance(instance, {
|
|
123
129
|
getNode,
|
|
124
130
|
getItem,
|
|
125
|
-
|
|
131
|
+
getItemsToRender,
|
|
126
132
|
getChildrenIds,
|
|
127
133
|
getNavigableChildrenIds,
|
|
128
|
-
|
|
134
|
+
isItemDisabled,
|
|
135
|
+
preventItemUpdates,
|
|
136
|
+
areItemUpdatesPrevented
|
|
129
137
|
});
|
|
130
138
|
populatePublicAPI(publicAPI, {
|
|
131
139
|
getItem
|
|
@@ -136,21 +144,18 @@ export const useTreeViewNodes = ({
|
|
|
136
144
|
}
|
|
137
145
|
};
|
|
138
146
|
};
|
|
139
|
-
|
|
140
|
-
|
|
147
|
+
useTreeViewItems.getInitialState = params => ({
|
|
148
|
+
items: updateItemsState({
|
|
141
149
|
items: params.items,
|
|
142
150
|
isItemDisabled: params.isItemDisabled,
|
|
143
151
|
getItemId: params.getItemId,
|
|
144
152
|
getItemLabel: params.getItemLabel
|
|
145
153
|
})
|
|
146
154
|
});
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
});
|
|
152
|
-
};
|
|
153
|
-
useTreeViewNodes.params = {
|
|
155
|
+
useTreeViewItems.getDefaultizedParams = params => _extends({}, params, {
|
|
156
|
+
disabledItemsFocusable: params.disabledItemsFocusable ?? false
|
|
157
|
+
});
|
|
158
|
+
useTreeViewItems.params = {
|
|
154
159
|
disabledItemsFocusable: true,
|
|
155
160
|
items: true,
|
|
156
161
|
isItemDisabled: true,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useTreeViewJSXItems } from './useTreeViewJSXItems';
|
|
@@ -7,68 +7,69 @@ import { publishTreeViewEvent } from '../../utils/publishTreeViewEvent';
|
|
|
7
7
|
import { useTreeViewContext } from '../../TreeViewProvider/useTreeViewContext';
|
|
8
8
|
import { DescendantProvider, useDescendant } from '../../TreeViewProvider/DescendantProvider';
|
|
9
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
|
-
export const
|
|
10
|
+
export const useTreeViewJSXItems = ({
|
|
11
11
|
instance,
|
|
12
12
|
setState
|
|
13
13
|
}) => {
|
|
14
|
-
|
|
14
|
+
instance.preventItemUpdates();
|
|
15
|
+
const insertJSXItem = useEventCallback(item => {
|
|
15
16
|
setState(prevState => {
|
|
16
|
-
if (prevState.
|
|
17
|
-
throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', `Tow items were provided with the same id in the \`items\` prop: "${
|
|
17
|
+
if (prevState.items.nodeMap[item.id] != null) {
|
|
18
|
+
throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', `Tow items were provided with the same id in the \`items\` prop: "${item.id}"`].join('\n'));
|
|
18
19
|
}
|
|
19
20
|
return _extends({}, prevState, {
|
|
20
|
-
|
|
21
|
-
nodeMap: _extends({}, prevState.
|
|
22
|
-
[
|
|
21
|
+
items: _extends({}, prevState.items, {
|
|
22
|
+
nodeMap: _extends({}, prevState.items.nodeMap, {
|
|
23
|
+
[item.id]: item
|
|
23
24
|
}),
|
|
24
25
|
// For `SimpleTreeView`, we don't have a proper `item` object, so we create a very basic one.
|
|
25
|
-
itemMap: _extends({}, prevState.
|
|
26
|
-
[
|
|
27
|
-
id:
|
|
28
|
-
label:
|
|
26
|
+
itemMap: _extends({}, prevState.items.itemMap, {
|
|
27
|
+
[item.id]: {
|
|
28
|
+
id: item.id,
|
|
29
|
+
label: item.label
|
|
29
30
|
}
|
|
30
31
|
})
|
|
31
32
|
})
|
|
32
33
|
});
|
|
33
34
|
});
|
|
34
35
|
});
|
|
35
|
-
const
|
|
36
|
+
const removeJSXItem = useEventCallback(itemId => {
|
|
36
37
|
setState(prevState => {
|
|
37
|
-
const newNodeMap = _extends({}, prevState.
|
|
38
|
-
const newItemMap = _extends({}, prevState.
|
|
39
|
-
delete newNodeMap[
|
|
40
|
-
delete newItemMap[
|
|
38
|
+
const newNodeMap = _extends({}, prevState.items.nodeMap);
|
|
39
|
+
const newItemMap = _extends({}, prevState.items.itemMap);
|
|
40
|
+
delete newNodeMap[itemId];
|
|
41
|
+
delete newItemMap[itemId];
|
|
41
42
|
return _extends({}, prevState, {
|
|
42
|
-
|
|
43
|
+
items: _extends({}, prevState.items, {
|
|
43
44
|
nodeMap: newNodeMap,
|
|
44
45
|
itemMap: newItemMap
|
|
45
46
|
})
|
|
46
47
|
});
|
|
47
48
|
});
|
|
48
|
-
publishTreeViewEvent(instance, '
|
|
49
|
-
id:
|
|
49
|
+
publishTreeViewEvent(instance, 'removeItem', {
|
|
50
|
+
id: itemId
|
|
50
51
|
});
|
|
51
52
|
});
|
|
52
|
-
const mapFirstCharFromJSX = useEventCallback((
|
|
53
|
+
const mapFirstCharFromJSX = useEventCallback((itemId, firstChar) => {
|
|
53
54
|
instance.updateFirstCharMap(firstCharMap => {
|
|
54
|
-
firstCharMap[
|
|
55
|
+
firstCharMap[itemId] = firstChar;
|
|
55
56
|
return firstCharMap;
|
|
56
57
|
});
|
|
57
58
|
return () => {
|
|
58
59
|
instance.updateFirstCharMap(firstCharMap => {
|
|
59
60
|
const newMap = _extends({}, firstCharMap);
|
|
60
|
-
delete newMap[
|
|
61
|
+
delete newMap[itemId];
|
|
61
62
|
return newMap;
|
|
62
63
|
});
|
|
63
64
|
};
|
|
64
65
|
});
|
|
65
66
|
populateInstance(instance, {
|
|
66
|
-
|
|
67
|
-
|
|
67
|
+
insertJSXItem,
|
|
68
|
+
removeJSXItem,
|
|
68
69
|
mapFirstCharFromJSX
|
|
69
70
|
});
|
|
70
71
|
};
|
|
71
|
-
const
|
|
72
|
+
const useTreeViewJSXItemsItemPlugin = ({
|
|
72
73
|
props,
|
|
73
74
|
rootRef,
|
|
74
75
|
contentRef
|
|
@@ -77,7 +78,7 @@ const useTreeViewJSXNodesItemPlugin = ({
|
|
|
77
78
|
children,
|
|
78
79
|
disabled = false,
|
|
79
80
|
label,
|
|
80
|
-
|
|
81
|
+
itemId,
|
|
81
82
|
id
|
|
82
83
|
} = props;
|
|
83
84
|
const {
|
|
@@ -96,45 +97,44 @@ const useTreeViewJSXNodesItemPlugin = ({
|
|
|
96
97
|
const handleContentRef = useForkRef(pluginContentRef, contentRef);
|
|
97
98
|
const descendant = React.useMemo(() => ({
|
|
98
99
|
element: treeItemElement,
|
|
99
|
-
id:
|
|
100
|
-
}), [
|
|
100
|
+
id: itemId
|
|
101
|
+
}), [itemId, treeItemElement]);
|
|
101
102
|
const {
|
|
102
103
|
index,
|
|
103
104
|
parentId
|
|
104
105
|
} = useDescendant(descendant);
|
|
105
106
|
React.useEffect(() => {
|
|
106
|
-
// On the first render a
|
|
107
|
+
// On the first render a item's index will be -1. We want to wait for the real index.
|
|
107
108
|
if (index !== -1) {
|
|
108
|
-
instance.
|
|
109
|
-
id:
|
|
109
|
+
instance.insertJSXItem({
|
|
110
|
+
id: itemId,
|
|
110
111
|
idAttribute: id,
|
|
111
112
|
index,
|
|
112
113
|
parentId,
|
|
113
114
|
expandable,
|
|
114
115
|
disabled
|
|
115
116
|
});
|
|
116
|
-
return () => instance.
|
|
117
|
+
return () => instance.removeJSXItem(itemId);
|
|
117
118
|
}
|
|
118
119
|
return undefined;
|
|
119
|
-
}, [instance, parentId, index,
|
|
120
|
+
}, [instance, parentId, index, itemId, expandable, disabled, id]);
|
|
120
121
|
React.useEffect(() => {
|
|
121
122
|
if (label) {
|
|
122
|
-
|
|
123
|
-
return instance.mapFirstCharFromJSX(nodeId, ((_pluginContentRef$cur = (_pluginContentRef$cur2 = pluginContentRef.current) == null ? void 0 : _pluginContentRef$cur2.textContent) != null ? _pluginContentRef$cur : '').substring(0, 1).toLowerCase());
|
|
123
|
+
return instance.mapFirstCharFromJSX(itemId, (pluginContentRef.current?.textContent ?? '').substring(0, 1).toLowerCase());
|
|
124
124
|
}
|
|
125
125
|
return undefined;
|
|
126
|
-
}, [instance,
|
|
126
|
+
}, [instance, itemId, label]);
|
|
127
127
|
return {
|
|
128
128
|
contentRef: handleContentRef,
|
|
129
129
|
rootRef: handleRootRef
|
|
130
130
|
};
|
|
131
131
|
};
|
|
132
|
-
|
|
133
|
-
|
|
132
|
+
useTreeViewJSXItems.itemPlugin = useTreeViewJSXItemsItemPlugin;
|
|
133
|
+
useTreeViewJSXItems.wrapItem = ({
|
|
134
134
|
children,
|
|
135
|
-
|
|
135
|
+
itemId
|
|
136
136
|
}) => /*#__PURE__*/_jsx(DescendantProvider, {
|
|
137
|
-
id:
|
|
137
|
+
id: itemId,
|
|
138
138
|
children: children
|
|
139
139
|
});
|
|
140
|
-
|
|
140
|
+
useTreeViewJSXItems.params = {};
|