@mui/x-tree-view 7.0.0-alpha.7 → 7.0.0-alpha.9
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 +554 -51
- package/README.md +1 -1
- package/RichTreeView/RichTreeView.js +14 -79
- package/RichTreeView/RichTreeView.types.d.ts +6 -9
- package/RichTreeView/index.d.ts +1 -1
- package/SimpleTreeView/SimpleTreeView.js +17 -75
- package/SimpleTreeView/SimpleTreeView.plugins.d.ts +4 -2
- package/SimpleTreeView/SimpleTreeView.types.d.ts +8 -7
- package/SimpleTreeView/index.d.ts +1 -1
- package/TreeItem/TreeItem.js +62 -39
- package/TreeItem/TreeItem.types.d.ts +33 -17
- package/TreeItem/TreeItemContent.d.ts +0 -3
- package/TreeItem/TreeItemContent.js +2 -5
- package/TreeItem/index.d.ts +2 -2
- package/TreeItem/index.js +1 -1
- package/TreeItem/{useTreeItem.d.ts → useTreeItemState.d.ts} +1 -1
- package/TreeItem/{useTreeItem.js → useTreeItemState.js} +4 -2
- package/TreeView/TreeView.js +1 -22
- package/TreeView/TreeView.types.d.ts +5 -1
- package/TreeView/index.d.ts +1 -1
- package/icons/icons.d.ts +6 -0
- package/icons/icons.js +9 -0
- package/icons/index.d.ts +1 -0
- package/icons/index.js +1 -0
- package/icons/package.json +6 -0
- package/index.d.ts +1 -0
- package/index.js +3 -2
- package/internals/TreeViewProvider/TreeViewContext.d.ts +4 -2
- package/internals/TreeViewProvider/TreeViewProvider.types.d.ts +3 -11
- package/internals/TreeViewProvider/useTreeViewContext.js +1 -1
- package/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +2 -1
- package/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.types.d.ts +3 -2
- package/internals/index.d.ts +15 -0
- package/internals/index.js +4 -0
- package/internals/models/MuiCancellableEvent.d.ts +4 -0
- package/internals/models/helpers.d.ts +7 -1
- package/internals/models/plugin.d.ts +65 -20
- package/internals/models/treeView.d.ts +1 -2
- package/internals/package.json +6 -0
- package/internals/plugins/defaultPlugins.d.ts +6 -4
- package/internals/plugins/defaultPlugins.js +2 -2
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +14 -10
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +7 -3
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +2 -5
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +12 -6
- package/internals/plugins/useTreeViewIcons/index.d.ts +2 -0
- package/internals/plugins/useTreeViewIcons/index.js +1 -0
- package/internals/plugins/useTreeViewIcons/useTreeViewIcons.d.ts +3 -0
- package/internals/plugins/useTreeViewIcons/useTreeViewIcons.js +22 -0
- package/internals/plugins/useTreeViewIcons/useTreeViewIcons.types.d.ts +43 -0
- package/internals/plugins/useTreeViewId/useTreeViewId.js +3 -0
- package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +6 -2
- package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +2 -1
- package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.types.d.ts +6 -4
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +155 -112
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +9 -6
- package/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +21 -3
- package/internals/plugins/useTreeViewNodes/useTreeViewNodes.types.d.ts +10 -2
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +17 -5
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +15 -5
- package/internals/useTreeView/useTreeView.js +7 -3
- package/internals/useTreeView/useTreeView.types.d.ts +6 -6
- package/internals/useTreeView/useTreeViewModels.js +12 -13
- package/internals/utils/extractPluginParamsFromProps.d.ts +16 -0
- package/internals/utils/extractPluginParamsFromProps.js +38 -0
- package/legacy/RichTreeView/RichTreeView.js +15 -77
- package/legacy/SimpleTreeView/SimpleTreeView.js +14 -70
- package/legacy/TreeItem/TreeItem.js +63 -39
- package/legacy/TreeItem/TreeItemContent.js +9 -12
- package/legacy/TreeItem/index.js +1 -1
- package/legacy/TreeItem/{useTreeItem.js → useTreeItemState.js} +2 -2
- package/legacy/TreeView/TreeView.js +1 -22
- package/legacy/icons/icons.js +9 -0
- package/legacy/icons/index.js +1 -0
- package/legacy/index.js +3 -2
- package/legacy/internals/TreeViewProvider/useTreeViewContext.js +1 -1
- package/legacy/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +2 -1
- package/legacy/internals/index.js +4 -0
- package/legacy/internals/plugins/defaultPlugins.js +2 -2
- package/legacy/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +16 -10
- package/legacy/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +2 -5
- package/legacy/internals/plugins/useTreeViewIcons/index.js +1 -0
- package/legacy/internals/plugins/useTreeViewIcons/useTreeViewIcons.js +21 -0
- package/legacy/internals/plugins/useTreeViewIcons/useTreeViewIcons.types.js +1 -0
- package/legacy/internals/plugins/useTreeViewId/useTreeViewId.js +3 -0
- package/legacy/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +2 -1
- package/legacy/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +157 -110
- package/legacy/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +20 -2
- package/legacy/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +20 -6
- package/legacy/internals/useTreeView/useTreeView.js +6 -2
- package/legacy/internals/useTreeView/useTreeViewModels.js +12 -13
- package/legacy/internals/utils/extractPluginParamsFromProps.js +36 -0
- package/modern/RichTreeView/RichTreeView.js +14 -79
- package/modern/SimpleTreeView/SimpleTreeView.js +17 -75
- package/modern/TreeItem/TreeItem.js +61 -39
- package/modern/TreeItem/TreeItemContent.js +2 -5
- package/modern/TreeItem/index.js +1 -1
- package/modern/TreeItem/{useTreeItem.js → useTreeItemState.js} +4 -2
- package/modern/TreeView/TreeView.js +1 -22
- package/modern/icons/icons.js +9 -0
- package/modern/icons/index.js +1 -0
- package/modern/index.js +3 -2
- package/modern/internals/TreeViewProvider/useTreeViewContext.js +1 -1
- package/modern/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +2 -1
- package/modern/internals/index.js +4 -0
- package/modern/internals/models/MuiCancellableEvent.js +1 -0
- package/modern/internals/plugins/defaultPlugins.js +2 -2
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +14 -11
- package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +3 -3
- package/modern/internals/plugins/useTreeViewIcons/index.js +1 -0
- package/modern/internals/plugins/useTreeViewIcons/useTreeViewIcons.js +22 -0
- package/modern/internals/plugins/useTreeViewIcons/useTreeViewIcons.types.js +1 -0
- package/modern/internals/plugins/useTreeViewId/useTreeViewId.js +3 -0
- package/modern/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +2 -1
- package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +155 -112
- package/modern/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +18 -3
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +18 -6
- package/modern/internals/useTreeView/useTreeView.js +7 -3
- package/modern/internals/useTreeView/useTreeViewModels.js +12 -13
- package/modern/internals/utils/extractPluginParamsFromProps.js +38 -0
- package/node/RichTreeView/RichTreeView.js +14 -79
- package/node/SimpleTreeView/SimpleTreeView.js +17 -75
- package/node/TreeItem/TreeItem.js +61 -39
- package/node/TreeItem/TreeItemContent.js +2 -5
- package/node/TreeItem/index.js +4 -4
- package/node/TreeItem/{useTreeItem.js → useTreeItemState.js} +5 -3
- package/node/TreeView/TreeView.js +1 -22
- package/node/icons/icons.js +17 -0
- package/node/icons/index.js +16 -0
- package/node/index.js +13 -1
- package/node/internals/TreeViewProvider/useTreeViewContext.js +1 -1
- package/node/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +2 -1
- package/node/internals/index.js +33 -0
- package/node/internals/plugins/defaultPlugins.js +2 -2
- package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +14 -11
- package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +3 -3
- package/node/internals/plugins/useTreeViewIcons/index.js +12 -0
- package/node/internals/plugins/useTreeViewIcons/useTreeViewIcons.js +29 -0
- package/node/internals/plugins/useTreeViewIcons/useTreeViewIcons.types.js +5 -0
- package/node/internals/plugins/useTreeViewId/useTreeViewId.js +4 -1
- package/node/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +2 -1
- package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +155 -112
- package/node/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +18 -3
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +18 -6
- package/node/internals/useTreeView/useTreeView.js +7 -3
- package/node/internals/useTreeView/useTreeViewModels.js +12 -13
- package/node/internals/utils/extractPluginParamsFromProps.js +46 -0
- package/package.json +7 -7
- package/themeAugmentation/components.d.ts +4 -4
- package/internals/plugins/useTreeViewContextValueBuilder/index.d.ts +0 -2
- package/internals/plugins/useTreeViewContextValueBuilder/index.js +0 -1
- package/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.d.ts +0 -3
- package/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.js +0 -26
- package/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.types.d.ts +0 -29
- package/legacy/internals/plugins/useTreeViewContextValueBuilder/index.js +0 -1
- package/legacy/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.js +0 -28
- package/modern/internals/plugins/useTreeViewContextValueBuilder/index.js +0 -1
- package/modern/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.js +0 -26
- package/node/internals/plugins/useTreeViewContextValueBuilder/index.js +0 -12
- package/node/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.js +0 -33
- /package/internals/{plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.types.js → models/MuiCancellableEvent.js} +0 -0
- /package/{legacy/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.types.js → internals/plugins/useTreeViewIcons/useTreeViewIcons.types.js} +0 -0
- /package/{modern/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.types.js → legacy/internals/models/MuiCancellableEvent.js} +0 -0
- /package/node/internals/{plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.types.js → models/MuiCancellableEvent.js} +0 -0
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { useTreeViewContext } from '../internals/TreeViewProvider/useTreeViewContext';
|
|
2
|
-
export function
|
|
2
|
+
export function useTreeItemState(nodeId) {
|
|
3
3
|
const {
|
|
4
4
|
instance,
|
|
5
|
-
|
|
5
|
+
selection: {
|
|
6
|
+
multiSelect
|
|
7
|
+
}
|
|
6
8
|
} = useTreeViewContext();
|
|
7
9
|
const expandable = instance.isNodeExpandable(nodeId);
|
|
8
10
|
const expanded = instance.isNodeExpanded(nodeId);
|
|
@@ -23,7 +23,7 @@ const TreeViewRoot = styled(SimpleTreeViewRoot, {
|
|
|
23
23
|
let warnedOnce = false;
|
|
24
24
|
const warn = () => {
|
|
25
25
|
if (!warnedOnce) {
|
|
26
|
-
console.warn(['MUI: The TreeView component was renamed SimpleTreeView.', 'The component with the old naming will be removed in the version v8.0.0.', '', "You should use `import { SimpleTreeView } from '@mui/x-tree-view'`", "or `import { SimpleTreeView } from '@mui/x-tree-view/TreeView'`"].join('\n'));
|
|
26
|
+
console.warn(['MUI X: The TreeView component was renamed SimpleTreeView.', 'The component with the old naming will be removed in the version v8.0.0.', '', "You should use `import { SimpleTreeView } from '@mui/x-tree-view'`", "or `import { SimpleTreeView } from '@mui/x-tree-view/TreeView'`"].join('\n'));
|
|
27
27
|
warnedOnce = true;
|
|
28
28
|
}
|
|
29
29
|
};
|
|
@@ -72,34 +72,13 @@ process.env.NODE_ENV !== "production" ? TreeView.propTypes = {
|
|
|
72
72
|
* Override or extend the styles applied to the component.
|
|
73
73
|
*/
|
|
74
74
|
classes: PropTypes.object,
|
|
75
|
-
/**
|
|
76
|
-
* className applied to the root element.
|
|
77
|
-
*/
|
|
78
75
|
className: PropTypes.string,
|
|
79
|
-
/**
|
|
80
|
-
* The default icon used to collapse the node.
|
|
81
|
-
*/
|
|
82
|
-
defaultCollapseIcon: PropTypes.node,
|
|
83
|
-
/**
|
|
84
|
-
* The default icon displayed next to a end node. This is applied to all
|
|
85
|
-
* tree nodes and can be overridden by the TreeItem `icon` prop.
|
|
86
|
-
*/
|
|
87
|
-
defaultEndIcon: PropTypes.node,
|
|
88
76
|
/**
|
|
89
77
|
* Expanded node ids.
|
|
90
78
|
* Used when the item's expansion is not controlled.
|
|
91
79
|
* @default []
|
|
92
80
|
*/
|
|
93
81
|
defaultExpandedNodes: PropTypes.arrayOf(PropTypes.string),
|
|
94
|
-
/**
|
|
95
|
-
* The default icon used to expand the node.
|
|
96
|
-
*/
|
|
97
|
-
defaultExpandIcon: PropTypes.node,
|
|
98
|
-
/**
|
|
99
|
-
* The default icon displayed next to a parent node. This is applied to all
|
|
100
|
-
* parent nodes and can be overridden by the TreeItem `icon` prop.
|
|
101
|
-
*/
|
|
102
|
-
defaultParentIcon: PropTypes.node,
|
|
103
82
|
/**
|
|
104
83
|
* Selected node ids. (Uncontrolled)
|
|
105
84
|
* When `multiSelect` is true this takes an array of strings; when false (default) a string.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createSvgIcon } from '@mui/material/utils';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
export const TreeViewExpandIcon = createSvgIcon( /*#__PURE__*/_jsx("path", {
|
|
5
|
+
d: "M10 6 8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"
|
|
6
|
+
}), 'TreeViewExpandIcon');
|
|
7
|
+
export const TreeViewCollapseIcon = createSvgIcon( /*#__PURE__*/_jsx("path", {
|
|
8
|
+
d: "M16.59 8.59 12 13.17 7.41 8.59 6 10l6 6 6-6z"
|
|
9
|
+
}), 'TreeViewCollapseIcon');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './icons';
|
package/modern/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @mui/x-tree-view v7.0.0-alpha.
|
|
2
|
+
* @mui/x-tree-view v7.0.0-alpha.9
|
|
3
3
|
*
|
|
4
4
|
* @license MIT
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
@@ -10,4 +10,5 @@ export * from './TreeView';
|
|
|
10
10
|
export * from './SimpleTreeView';
|
|
11
11
|
export * from './RichTreeView';
|
|
12
12
|
export { unstable_resetCleanupTracking } from './internals/hooks/useInstanceEventHandler';
|
|
13
|
-
export * from './models';
|
|
13
|
+
export * from './models';
|
|
14
|
+
export * from './icons';
|
|
@@ -3,7 +3,7 @@ import { TreeViewContext } from './TreeViewContext';
|
|
|
3
3
|
export const useTreeViewContext = () => {
|
|
4
4
|
const context = React.useContext(TreeViewContext);
|
|
5
5
|
if (context == null) {
|
|
6
|
-
throw new Error(['MUI: Could not find the Tree View context.', 'It looks like you rendered your component outside of a SimpleTreeView or RichTreeView parent component.', 'This can also happen if you are bundling multiple versions of the Tree View.'].join('\n'));
|
|
6
|
+
throw new Error(['MUI X: Could not find the Tree View context.', 'It looks like you rendered your component outside of a SimpleTreeView or RichTreeView parent component.', 'This can also happen if you are bundling multiple versions of the Tree View.'].join('\n'));
|
|
7
7
|
}
|
|
8
8
|
return context;
|
|
9
9
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,7 +4,7 @@ import { useTreeViewExpansion } from './useTreeViewExpansion';
|
|
|
4
4
|
import { useTreeViewSelection } from './useTreeViewSelection';
|
|
5
5
|
import { useTreeViewFocus } from './useTreeViewFocus';
|
|
6
6
|
import { useTreeViewKeyboardNavigation } from './useTreeViewKeyboardNavigation';
|
|
7
|
-
import {
|
|
8
|
-
export const DEFAULT_TREE_VIEW_PLUGINS = [useTreeViewId, useTreeViewNodes, useTreeViewExpansion, useTreeViewSelection, useTreeViewFocus, useTreeViewKeyboardNavigation,
|
|
7
|
+
import { useTreeViewIcons } from './useTreeViewIcons';
|
|
8
|
+
export const DEFAULT_TREE_VIEW_PLUGINS = [useTreeViewId, useTreeViewNodes, useTreeViewExpansion, useTreeViewSelection, useTreeViewFocus, useTreeViewKeyboardNavigation, useTreeViewIcons];
|
|
9
9
|
|
|
10
10
|
// We can't infer this type from the plugin, otherwise we would lose the generics.
|
|
@@ -7,6 +7,10 @@ export const useTreeViewExpansion = ({
|
|
|
7
7
|
params,
|
|
8
8
|
models
|
|
9
9
|
}) => {
|
|
10
|
+
const setExpandedNodes = (event, value) => {
|
|
11
|
+
params.onExpandedNodesChange?.(event, value);
|
|
12
|
+
models.expandedNodes.setControlledValue(value);
|
|
13
|
+
};
|
|
10
14
|
const isNodeExpanded = React.useCallback(nodeId => {
|
|
11
15
|
return Array.isArray(models.expandedNodes.value) ? models.expandedNodes.value.indexOf(nodeId) !== -1 : false;
|
|
12
16
|
}, [models.expandedNodes.value]);
|
|
@@ -25,10 +29,7 @@ export const useTreeViewExpansion = ({
|
|
|
25
29
|
if (params.onNodeExpansionToggle) {
|
|
26
30
|
params.onNodeExpansionToggle(event, nodeId, !isExpandedBefore);
|
|
27
31
|
}
|
|
28
|
-
|
|
29
|
-
params.onExpandedNodesChange(event, newExpanded);
|
|
30
|
-
}
|
|
31
|
-
models.expandedNodes.setValue(newExpanded);
|
|
32
|
+
setExpandedNodes(event, newExpanded);
|
|
32
33
|
});
|
|
33
34
|
const expandAllSiblings = (event, nodeId) => {
|
|
34
35
|
const node = instance.getNode(nodeId);
|
|
@@ -41,10 +42,7 @@ export const useTreeViewExpansion = ({
|
|
|
41
42
|
params.onNodeExpansionToggle(event, newlyExpandedNodeId, true);
|
|
42
43
|
});
|
|
43
44
|
}
|
|
44
|
-
|
|
45
|
-
params.onExpandedNodesChange(event, newExpanded);
|
|
46
|
-
}
|
|
47
|
-
models.expandedNodes.setValue(newExpanded);
|
|
45
|
+
setExpandedNodes(event, newExpanded);
|
|
48
46
|
}
|
|
49
47
|
};
|
|
50
48
|
populateInstance(instance, {
|
|
@@ -56,11 +54,16 @@ export const useTreeViewExpansion = ({
|
|
|
56
54
|
};
|
|
57
55
|
useTreeViewExpansion.models = {
|
|
58
56
|
expandedNodes: {
|
|
59
|
-
|
|
60
|
-
defaultProp: 'defaultExpandedNodes'
|
|
57
|
+
getDefaultValue: params => params.defaultExpandedNodes
|
|
61
58
|
}
|
|
62
59
|
};
|
|
63
60
|
const DEFAULT_EXPANDED_NODES = [];
|
|
64
61
|
useTreeViewExpansion.getDefaultizedParams = params => _extends({}, params, {
|
|
65
62
|
defaultExpandedNodes: params.defaultExpandedNodes ?? DEFAULT_EXPANDED_NODES
|
|
66
|
-
});
|
|
63
|
+
});
|
|
64
|
+
useTreeViewExpansion.params = {
|
|
65
|
+
expandedNodes: true,
|
|
66
|
+
defaultExpandedNodes: true,
|
|
67
|
+
onExpandedNodesChange: true,
|
|
68
|
+
onNodeExpansionToggle: true
|
|
69
|
+
};
|
|
@@ -85,6 +85,6 @@ export const useTreeViewFocus = ({
|
|
|
85
85
|
useTreeViewFocus.getInitialState = () => ({
|
|
86
86
|
focusedNodeId: null
|
|
87
87
|
});
|
|
88
|
-
useTreeViewFocus.
|
|
89
|
-
|
|
90
|
-
}
|
|
88
|
+
useTreeViewFocus.params = {
|
|
89
|
+
onNodeFocus: true
|
|
90
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useTreeViewIcons } from './useTreeViewIcons';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const useTreeViewIcons = ({
|
|
2
|
+
slots,
|
|
3
|
+
slotProps
|
|
4
|
+
}) => {
|
|
5
|
+
return {
|
|
6
|
+
contextValue: {
|
|
7
|
+
icons: {
|
|
8
|
+
slots: {
|
|
9
|
+
collapseIcon: slots.collapseIcon,
|
|
10
|
+
expandIcon: slots.expandIcon,
|
|
11
|
+
endIcon: slots.endIcon
|
|
12
|
+
},
|
|
13
|
+
slotProps: {
|
|
14
|
+
collapseIcon: slotProps.collapseIcon,
|
|
15
|
+
expandIcon: slotProps.expandIcon,
|
|
16
|
+
endIcon: slotProps.endIcon
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
useTreeViewIcons.params = {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js
CHANGED
|
@@ -3,7 +3,7 @@ import { useTheme } from '@mui/material/styles';
|
|
|
3
3
|
import useEventCallback from '@mui/utils/useEventCallback';
|
|
4
4
|
import { getFirstNode, getLastNode, getNextNode, getPreviousNode, populateInstance } from '../../useTreeView/useTreeView.utils';
|
|
5
5
|
function isPrintableCharacter(string) {
|
|
6
|
-
return string && string.length === 1 && string.match(/\S/);
|
|
6
|
+
return !!string && string.length === 1 && !!string.match(/\S/);
|
|
7
7
|
}
|
|
8
8
|
function findNextFirstChar(firstChars, startIndex, char) {
|
|
9
9
|
for (let i = startIndex; i < firstChars.length; i += 1) {
|
|
@@ -19,7 +19,7 @@ export const useTreeViewKeyboardNavigation = ({
|
|
|
19
19
|
state
|
|
20
20
|
}) => {
|
|
21
21
|
const theme = useTheme();
|
|
22
|
-
const
|
|
22
|
+
const isRTL = theme.direction === 'rtl';
|
|
23
23
|
const firstCharMap = React.useRef({});
|
|
24
24
|
const hasFirstCharMapBeenUpdatedImperatively = React.useRef(false);
|
|
25
25
|
const updateFirstCharMap = useEventCallback(callback => {
|
|
@@ -43,32 +43,7 @@ export const useTreeViewKeyboardNavigation = ({
|
|
|
43
43
|
populateInstance(instance, {
|
|
44
44
|
updateFirstCharMap
|
|
45
45
|
});
|
|
46
|
-
const
|
|
47
|
-
if (state.focusedNodeId != null && instance.isNodeExpandable(state.focusedNodeId)) {
|
|
48
|
-
if (instance.isNodeExpanded(state.focusedNodeId)) {
|
|
49
|
-
instance.focusNode(event, getNextNode(instance, state.focusedNodeId));
|
|
50
|
-
} else if (!instance.isNodeDisabled(state.focusedNodeId)) {
|
|
51
|
-
instance.toggleNodeExpansion(event, state.focusedNodeId);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
return true;
|
|
55
|
-
};
|
|
56
|
-
const handlePreviousArrow = event => {
|
|
57
|
-
if (state.focusedNodeId == null) {
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
if (instance.isNodeExpanded(state.focusedNodeId) && !instance.isNodeDisabled(state.focusedNodeId)) {
|
|
61
|
-
instance.toggleNodeExpansion(event, state.focusedNodeId);
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
const parent = instance.getNode(state.focusedNodeId).parentId;
|
|
65
|
-
if (parent) {
|
|
66
|
-
instance.focusNode(event, parent);
|
|
67
|
-
return true;
|
|
68
|
-
}
|
|
69
|
-
return false;
|
|
70
|
-
};
|
|
71
|
-
const focusByFirstCharacter = (event, nodeId, firstChar) => {
|
|
46
|
+
const getFirstMatchingNode = (nodeId, firstChar) => {
|
|
72
47
|
let start;
|
|
73
48
|
let index;
|
|
74
49
|
const lowercaseChar = firstChar.toLowerCase();
|
|
@@ -99,41 +74,35 @@ export const useTreeViewKeyboardNavigation = ({
|
|
|
99
74
|
index = findNextFirstChar(firstChars, 0, lowercaseChar);
|
|
100
75
|
}
|
|
101
76
|
|
|
102
|
-
// If match was found...
|
|
77
|
+
// If a match was found...
|
|
103
78
|
if (index > -1) {
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
};
|
|
107
|
-
const selectNextNode = (event, id) => {
|
|
108
|
-
if (!instance.isNodeDisabled(getNextNode(instance, id))) {
|
|
109
|
-
instance.selectRange(event, {
|
|
110
|
-
end: getNextNode(instance, id),
|
|
111
|
-
current: id
|
|
112
|
-
}, true);
|
|
113
|
-
}
|
|
114
|
-
};
|
|
115
|
-
const selectPreviousNode = (event, nodeId) => {
|
|
116
|
-
if (!instance.isNodeDisabled(getPreviousNode(instance, nodeId))) {
|
|
117
|
-
instance.selectRange(event, {
|
|
118
|
-
end: getPreviousNode(instance, nodeId),
|
|
119
|
-
current: nodeId
|
|
120
|
-
}, true);
|
|
79
|
+
return firstCharIds[index];
|
|
121
80
|
}
|
|
81
|
+
return null;
|
|
122
82
|
};
|
|
83
|
+
const canToggleNodeSelection = nodeId => !params.disableSelection && !instance.isNodeDisabled(nodeId);
|
|
84
|
+
const canToggleNodeExpansion = nodeId => !instance.isNodeDisabled(nodeId) && instance.isNodeExpandable(nodeId);
|
|
85
|
+
|
|
86
|
+
// ARIA specification: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/#keyboardinteraction
|
|
123
87
|
const createHandleKeyDown = otherHandlers => event => {
|
|
124
88
|
otherHandlers.onKeyDown?.(event);
|
|
125
|
-
|
|
126
|
-
|
|
89
|
+
if (event.defaultMuiPrevented) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
127
92
|
|
|
128
93
|
// If the tree is empty there will be no focused node
|
|
129
94
|
if (event.altKey || event.currentTarget !== event.target || state.focusedNodeId == null) {
|
|
130
95
|
return;
|
|
131
96
|
}
|
|
132
97
|
const ctrlPressed = event.ctrlKey || event.metaKey;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
98
|
+
const key = event.key;
|
|
99
|
+
|
|
100
|
+
// eslint-disable-next-line default-case
|
|
101
|
+
switch (true) {
|
|
102
|
+
// Select the node when pressing "Space"
|
|
103
|
+
case key === ' ' && canToggleNodeSelection(state.focusedNodeId):
|
|
104
|
+
{
|
|
105
|
+
event.preventDefault();
|
|
137
106
|
if (params.multiSelect && event.shiftKey) {
|
|
138
107
|
instance.selectRange(event, {
|
|
139
108
|
end: state.focusedNodeId
|
|
@@ -143,85 +112,158 @@ export const useTreeViewKeyboardNavigation = ({
|
|
|
143
112
|
} else {
|
|
144
113
|
instance.selectNode(event, state.focusedNodeId);
|
|
145
114
|
}
|
|
115
|
+
break;
|
|
146
116
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
117
|
+
|
|
118
|
+
// If the focused node has children, we expand it.
|
|
119
|
+
// If the focused node has no children, we select it.
|
|
120
|
+
case key === 'Enter':
|
|
121
|
+
{
|
|
122
|
+
if (canToggleNodeExpansion(state.focusedNodeId)) {
|
|
152
123
|
instance.toggleNodeExpansion(event, state.focusedNodeId);
|
|
153
|
-
|
|
154
|
-
} else if (
|
|
155
|
-
flag = true;
|
|
124
|
+
event.preventDefault();
|
|
125
|
+
} else if (canToggleNodeSelection(state.focusedNodeId)) {
|
|
156
126
|
if (params.multiSelect) {
|
|
127
|
+
event.preventDefault();
|
|
157
128
|
instance.selectNode(event, state.focusedNodeId, true);
|
|
158
|
-
} else {
|
|
129
|
+
} else if (!instance.isNodeSelected(state.focusedNodeId)) {
|
|
159
130
|
instance.selectNode(event, state.focusedNodeId);
|
|
131
|
+
event.preventDefault();
|
|
160
132
|
}
|
|
161
133
|
}
|
|
134
|
+
break;
|
|
162
135
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
case 'ArrowDown':
|
|
166
|
-
|
|
167
|
-
|
|
136
|
+
|
|
137
|
+
// Focus the next focusable node
|
|
138
|
+
case key === 'ArrowDown':
|
|
139
|
+
{
|
|
140
|
+
const nextNode = getNextNode(instance, state.focusedNodeId);
|
|
141
|
+
if (nextNode) {
|
|
142
|
+
event.preventDefault();
|
|
143
|
+
instance.focusNode(event, nextNode);
|
|
144
|
+
|
|
145
|
+
// Multi select behavior when pressing Shift + ArrowDown
|
|
146
|
+
// Toggles the selection state of the next node
|
|
147
|
+
if (params.multiSelect && event.shiftKey && canToggleNodeSelection(nextNode)) {
|
|
148
|
+
instance.selectRange(event, {
|
|
149
|
+
end: nextNode,
|
|
150
|
+
current: state.focusedNodeId
|
|
151
|
+
}, true);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
break;
|
|
168
155
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
156
|
+
|
|
157
|
+
// Focuses the previous focusable node
|
|
158
|
+
case key === 'ArrowUp':
|
|
159
|
+
{
|
|
160
|
+
const previousNode = getPreviousNode(instance, state.focusedNodeId);
|
|
161
|
+
if (previousNode) {
|
|
162
|
+
event.preventDefault();
|
|
163
|
+
instance.focusNode(event, previousNode);
|
|
164
|
+
|
|
165
|
+
// Multi select behavior when pressing Shift + ArrowUp
|
|
166
|
+
// Toggles the selection state of the previous node
|
|
167
|
+
if (params.multiSelect && event.shiftKey && canToggleNodeSelection(previousNode)) {
|
|
168
|
+
instance.selectRange(event, {
|
|
169
|
+
end: previousNode,
|
|
170
|
+
current: state.focusedNodeId
|
|
171
|
+
}, true);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
break;
|
|
175
175
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
case 'ArrowRight':
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
176
|
+
|
|
177
|
+
// If the focused node is expanded, we move the focus to its first child
|
|
178
|
+
// If the focused node is collapsed and has children, we expand it
|
|
179
|
+
case key === 'ArrowRight' && !isRTL || key === 'ArrowLeft' && isRTL:
|
|
180
|
+
{
|
|
181
|
+
if (instance.isNodeExpanded(state.focusedNodeId)) {
|
|
182
|
+
instance.focusNode(event, getNextNode(instance, state.focusedNodeId));
|
|
183
|
+
event.preventDefault();
|
|
184
|
+
} else if (canToggleNodeExpansion(state.focusedNodeId)) {
|
|
185
|
+
instance.toggleNodeExpansion(event, state.focusedNodeId);
|
|
186
|
+
event.preventDefault();
|
|
187
|
+
}
|
|
188
|
+
break;
|
|
184
189
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
190
|
+
|
|
191
|
+
// If the focused node is expanded, we collapse it
|
|
192
|
+
// If the focused node is collapsed and has a parent, we move the focus to this parent
|
|
193
|
+
case key === 'ArrowLeft' && !isRTL || key === 'ArrowRight' && isRTL:
|
|
194
|
+
{
|
|
195
|
+
if (canToggleNodeExpansion(state.focusedNodeId) && instance.isNodeExpanded(state.focusedNodeId)) {
|
|
196
|
+
instance.toggleNodeExpansion(event, state.focusedNodeId);
|
|
197
|
+
event.preventDefault();
|
|
198
|
+
} else {
|
|
199
|
+
const parent = instance.getNode(state.focusedNodeId).parentId;
|
|
200
|
+
if (parent) {
|
|
201
|
+
instance.focusNode(event, parent);
|
|
202
|
+
event.preventDefault();
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
break;
|
|
191
206
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
207
|
+
|
|
208
|
+
// Focuses the first node in the tree
|
|
209
|
+
case key === 'Home':
|
|
210
|
+
{
|
|
211
|
+
instance.focusNode(event, getFirstNode(instance));
|
|
212
|
+
|
|
213
|
+
// Multi select behavior when pressing Ctrl + Shift + Home
|
|
214
|
+
// Selects the focused node and all nodes up to the first node.
|
|
215
|
+
if (canToggleNodeSelection(state.focusedNodeId) && params.multiSelect && ctrlPressed && event.shiftKey) {
|
|
216
|
+
instance.rangeSelectToFirst(event, state.focusedNodeId);
|
|
217
|
+
}
|
|
218
|
+
event.preventDefault();
|
|
219
|
+
break;
|
|
196
220
|
}
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
221
|
+
|
|
222
|
+
// Focuses the last node in the tree
|
|
223
|
+
case key === 'End':
|
|
224
|
+
{
|
|
225
|
+
instance.focusNode(event, getLastNode(instance));
|
|
226
|
+
|
|
227
|
+
// Multi select behavior when pressing Ctrl + Shirt + End
|
|
228
|
+
// Selects the focused node and all the nodes down to the last node.
|
|
229
|
+
if (canToggleNodeSelection(state.focusedNodeId) && params.multiSelect && ctrlPressed && event.shiftKey) {
|
|
230
|
+
instance.rangeSelectToLast(event, state.focusedNodeId);
|
|
231
|
+
}
|
|
232
|
+
event.preventDefault();
|
|
233
|
+
break;
|
|
203
234
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
if (key === '*') {
|
|
235
|
+
|
|
236
|
+
// Expand all siblings that are at the same level as the focused node
|
|
237
|
+
case key === '*':
|
|
238
|
+
{
|
|
209
239
|
instance.expandAllSiblings(event, state.focusedNodeId);
|
|
210
|
-
|
|
211
|
-
|
|
240
|
+
event.preventDefault();
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Multi select behavior when pressing Ctrl + a
|
|
245
|
+
// Selects all the nodes
|
|
246
|
+
case key === 'a' && ctrlPressed && params.multiSelect && !params.disableSelection:
|
|
247
|
+
{
|
|
212
248
|
instance.selectRange(event, {
|
|
213
249
|
start: getFirstNode(instance),
|
|
214
250
|
end: getLastNode(instance)
|
|
215
251
|
});
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
252
|
+
event.preventDefault();
|
|
253
|
+
break;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Type-ahead
|
|
257
|
+
// TODO: Support typing multiple characters
|
|
258
|
+
case !ctrlPressed && !event.shiftKey && isPrintableCharacter(key):
|
|
259
|
+
{
|
|
260
|
+
const matchingNode = getFirstMatchingNode(state.focusedNodeId, key);
|
|
261
|
+
if (matchingNode != null) {
|
|
262
|
+
instance.focusNode(event, matchingNode);
|
|
263
|
+
event.preventDefault();
|
|
264
|
+
}
|
|
265
|
+
break;
|
|
220
266
|
}
|
|
221
|
-
}
|
|
222
|
-
if (flag) {
|
|
223
|
-
event.preventDefault();
|
|
224
|
-
event.stopPropagation();
|
|
225
267
|
}
|
|
226
268
|
};
|
|
227
269
|
return {
|
|
@@ -229,4 +271,5 @@ export const useTreeViewKeyboardNavigation = ({
|
|
|
229
271
|
onKeyDown: createHandleKeyDown(otherHandlers)
|
|
230
272
|
})
|
|
231
273
|
};
|
|
232
|
-
};
|
|
274
|
+
};
|
|
275
|
+
useTreeViewKeyboardNavigation.params = {};
|
|
@@ -13,11 +13,11 @@ const updateState = ({
|
|
|
13
13
|
const processItem = (item, index, parentId) => {
|
|
14
14
|
const id = getItemId ? getItemId(item) : item.id;
|
|
15
15
|
if (id == null) {
|
|
16
|
-
throw new Error(['MUI: 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'));
|
|
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'));
|
|
17
17
|
}
|
|
18
18
|
const label = getItemLabel ? getItemLabel(item) : item.label;
|
|
19
19
|
if (label == null) {
|
|
20
|
-
throw new Error(['MUI: The Tree View component requires all items to have a `label` property.', 'Alternatively, you can use the `getItemLabel` prop to specify a custom label for each item.', 'An item was provided without label in the `items` prop:', JSON.stringify(item)].join('\n'));
|
|
20
|
+
throw new Error(['MUI X: The Tree View component requires all items to have a `label` property.', 'Alternatively, you can use the `getItemLabel` prop to specify a custom label for each item.', 'An item was provided without label in the `items` prop:', JSON.stringify(item)].join('\n'));
|
|
21
21
|
}
|
|
22
22
|
nodeMap[id] = {
|
|
23
23
|
id,
|
|
@@ -115,10 +115,25 @@ export const useTreeViewNodes = ({
|
|
|
115
115
|
getNavigableChildrenIds,
|
|
116
116
|
isNodeDisabled
|
|
117
117
|
});
|
|
118
|
+
return {
|
|
119
|
+
contextValue: {
|
|
120
|
+
disabledItemsFocusable: params.disabledItemsFocusable
|
|
121
|
+
}
|
|
122
|
+
};
|
|
118
123
|
};
|
|
119
124
|
useTreeViewNodes.getInitialState = params => updateState({
|
|
120
125
|
items: params.items,
|
|
121
126
|
isItemDisabled: params.isItemDisabled,
|
|
122
127
|
getItemId: params.getItemId,
|
|
123
128
|
getItemLabel: params.getItemLabel
|
|
124
|
-
});
|
|
129
|
+
});
|
|
130
|
+
useTreeViewNodes.getDefaultizedParams = params => _extends({}, params, {
|
|
131
|
+
disabledItemsFocusable: params.disabledItemsFocusable ?? false
|
|
132
|
+
});
|
|
133
|
+
useTreeViewNodes.params = {
|
|
134
|
+
disabledItemsFocusable: true,
|
|
135
|
+
items: true,
|
|
136
|
+
isItemDisabled: true,
|
|
137
|
+
getItemLabel: true,
|
|
138
|
+
getItemId: true
|
|
139
|
+
};
|