@mui/x-tree-view 7.0.0-alpha.7 → 7.0.0-alpha.8

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.
Files changed (73) hide show
  1. package/CHANGELOG.md +175 -49
  2. package/RichTreeView/RichTreeView.js +18 -57
  3. package/SimpleTreeView/SimpleTreeView.js +20 -53
  4. package/TreeView/TreeView.js +1 -1
  5. package/index.js +1 -1
  6. package/internals/TreeViewProvider/useTreeViewContext.js +1 -1
  7. package/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +2 -1
  8. package/internals/models/MuiCancellableEvent.d.ts +4 -0
  9. package/internals/models/MuiCancellableEvent.js +1 -0
  10. package/internals/models/plugin.d.ts +1 -0
  11. package/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.js +6 -0
  12. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +6 -0
  13. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +3 -0
  14. package/internals/plugins/useTreeViewId/useTreeViewId.js +3 -0
  15. package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +2 -1
  16. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +155 -112
  17. package/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +10 -3
  18. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +8 -0
  19. package/internals/useTreeView/useTreeViewModels.js +2 -2
  20. package/internals/utils/extractPluginParamsFromProps.d.ts +13 -0
  21. package/internals/utils/extractPluginParamsFromProps.js +27 -0
  22. package/legacy/RichTreeView/RichTreeView.js +17 -55
  23. package/legacy/SimpleTreeView/SimpleTreeView.js +15 -47
  24. package/legacy/TreeView/TreeView.js +1 -1
  25. package/legacy/index.js +1 -1
  26. package/legacy/internals/TreeViewProvider/useTreeViewContext.js +1 -1
  27. package/legacy/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +2 -1
  28. package/legacy/internals/models/MuiCancellableEvent.js +1 -0
  29. package/legacy/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.js +6 -0
  30. package/legacy/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +6 -0
  31. package/legacy/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +3 -0
  32. package/legacy/internals/plugins/useTreeViewId/useTreeViewId.js +3 -0
  33. package/legacy/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +2 -1
  34. package/legacy/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +157 -110
  35. package/legacy/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +9 -2
  36. package/legacy/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +8 -0
  37. package/legacy/internals/useTreeView/useTreeViewModels.js +2 -2
  38. package/legacy/internals/utils/extractPluginParamsFromProps.js +27 -0
  39. package/modern/RichTreeView/RichTreeView.js +18 -57
  40. package/modern/SimpleTreeView/SimpleTreeView.js +20 -53
  41. package/modern/TreeView/TreeView.js +1 -1
  42. package/modern/index.js +1 -1
  43. package/modern/internals/TreeViewProvider/useTreeViewContext.js +1 -1
  44. package/modern/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +2 -1
  45. package/modern/internals/models/MuiCancellableEvent.js +1 -0
  46. package/modern/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.js +6 -0
  47. package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +7 -1
  48. package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +4 -1
  49. package/modern/internals/plugins/useTreeViewId/useTreeViewId.js +3 -0
  50. package/modern/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +2 -1
  51. package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +155 -112
  52. package/modern/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +10 -3
  53. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +9 -1
  54. package/modern/internals/useTreeView/useTreeViewModels.js +2 -2
  55. package/modern/internals/utils/extractPluginParamsFromProps.js +27 -0
  56. package/node/RichTreeView/RichTreeView.js +18 -57
  57. package/node/SimpleTreeView/SimpleTreeView.js +20 -53
  58. package/node/TreeView/TreeView.js +1 -1
  59. package/node/index.js +1 -1
  60. package/node/internals/TreeViewProvider/useTreeViewContext.js +1 -1
  61. package/node/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +2 -1
  62. package/node/internals/models/MuiCancellableEvent.js +5 -0
  63. package/node/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.js +7 -1
  64. package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +7 -1
  65. package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +4 -1
  66. package/node/internals/plugins/useTreeViewId/useTreeViewId.js +4 -1
  67. package/node/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +2 -1
  68. package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +155 -112
  69. package/node/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +10 -3
  70. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +9 -1
  71. package/node/internals/useTreeView/useTreeViewModels.js +2 -2
  72. package/node/internals/utils/extractPluginParamsFromProps.js +34 -0
  73. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
3
- var _excluded = ["disabledItemsFocusable", "expandedNodes", "defaultExpandedNodes", "onExpandedNodesChange", "onNodeExpansionToggle", "onNodeFocus", "disableSelection", "defaultSelectedNodes", "selectedNodes", "multiSelect", "onSelectedNodesChange", "onNodeSelectionToggle", "id", "defaultCollapseIcon", "defaultEndIcon", "defaultExpandIcon", "defaultParentIcon", "children", "slots", "slotProps"];
3
+ var _excluded = ["slots", "slotProps"];
4
4
  import * as React from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
  import { styled, useThemeProps } from '@mui/material/styles';
@@ -11,6 +11,7 @@ import { useTreeView } from '../internals/useTreeView';
11
11
  import { TreeViewProvider } from '../internals/TreeViewProvider';
12
12
  import { SIMPLE_TREE_VIEW_PLUGINS } from './SimpleTreeView.plugins';
13
13
  import { buildWarning } from '../internals/utils/warning';
14
+ import { extractPluginParamsFromProps } from '../internals/utils/extractPluginParamsFromProps';
14
15
  import { jsx as _jsx } from "react/jsx-runtime";
15
16
  var useUtilityClasses = function useUtilityClasses(ownerState) {
16
17
  var classes = ownerState.classes;
@@ -32,7 +33,7 @@ export var SimpleTreeViewRoot = styled('ul', {
32
33
  outline: 0
33
34
  });
34
35
  var EMPTY_ITEMS = [];
35
- var itemsPropWarning = buildWarning(['MUI: The `SimpleTreeView` component does not support the `items` prop.', 'If you want to add items, you need to pass them as JSX children.', 'Check the documentation for more details: https://next.mui.com/x/react-tree-view/simple-tree-view/items/']);
36
+ var itemsPropWarning = buildWarning(['MUI X: The `SimpleTreeView` component does not support the `items` prop.', 'If you want to add items, you need to pass them as JSX children.', 'Check the documentation for more details: https://next.mui.com/x/react-tree-view/simple-tree-view/items/']);
36
37
 
37
38
  /**
38
39
  *
@@ -51,55 +52,24 @@ var SimpleTreeView = /*#__PURE__*/React.forwardRef(function SimpleTreeView(inPro
51
52
  name: 'MuiSimpleTreeView'
52
53
  });
53
54
  var ownerState = props;
54
- var _ref = props,
55
- disabledItemsFocusable = _ref.disabledItemsFocusable,
56
- expandedNodes = _ref.expandedNodes,
57
- defaultExpandedNodes = _ref.defaultExpandedNodes,
58
- onExpandedNodesChange = _ref.onExpandedNodesChange,
59
- onNodeExpansionToggle = _ref.onNodeExpansionToggle,
60
- onNodeFocus = _ref.onNodeFocus,
61
- disableSelection = _ref.disableSelection,
62
- defaultSelectedNodes = _ref.defaultSelectedNodes,
63
- selectedNodes = _ref.selectedNodes,
64
- multiSelect = _ref.multiSelect,
65
- onSelectedNodesChange = _ref.onSelectedNodesChange,
66
- onNodeSelectionToggle = _ref.onNodeSelectionToggle,
67
- id = _ref.id,
68
- defaultCollapseIcon = _ref.defaultCollapseIcon,
69
- defaultEndIcon = _ref.defaultEndIcon,
70
- defaultExpandIcon = _ref.defaultExpandIcon,
71
- defaultParentIcon = _ref.defaultParentIcon,
72
- children = _ref.children,
73
- slots = _ref.slots,
74
- slotProps = _ref.slotProps,
75
- other = _objectWithoutProperties(_ref, _excluded);
76
55
  if (process.env.NODE_ENV !== 'production') {
77
56
  if (props.items != null) {
78
57
  itemsPropWarning();
79
58
  }
80
59
  }
81
- var _useTreeView = useTreeView({
82
- disabledItemsFocusable: disabledItemsFocusable,
83
- expandedNodes: expandedNodes,
84
- defaultExpandedNodes: defaultExpandedNodes,
85
- onExpandedNodesChange: onExpandedNodesChange,
86
- onNodeExpansionToggle: onNodeExpansionToggle,
87
- onNodeFocus: onNodeFocus,
88
- disableSelection: disableSelection,
89
- defaultSelectedNodes: defaultSelectedNodes,
90
- selectedNodes: selectedNodes,
91
- multiSelect: multiSelect,
92
- onSelectedNodesChange: onSelectedNodesChange,
93
- onNodeSelectionToggle: onNodeSelectionToggle,
94
- id: id,
95
- defaultCollapseIcon: defaultCollapseIcon,
96
- defaultEndIcon: defaultEndIcon,
97
- defaultExpandIcon: defaultExpandIcon,
98
- defaultParentIcon: defaultParentIcon,
99
- items: EMPTY_ITEMS,
60
+ var _extractPluginParamsF = extractPluginParamsFromProps({
61
+ props: _extends({}, props, {
62
+ items: EMPTY_ITEMS
63
+ }),
100
64
  plugins: SIMPLE_TREE_VIEW_PLUGINS,
101
65
  rootRef: ref
102
66
  }),
67
+ pluginParams = _extractPluginParamsF.pluginParams,
68
+ _extractPluginParamsF2 = _extractPluginParamsF.otherProps,
69
+ slots = _extractPluginParamsF2.slots,
70
+ slotProps = _extractPluginParamsF2.slotProps,
71
+ otherProps = _objectWithoutProperties(_extractPluginParamsF2, _excluded);
72
+ var _useTreeView = useTreeView(pluginParams),
103
73
  getRootProps = _useTreeView.getRootProps,
104
74
  contextValue = _useTreeView.contextValue;
105
75
  var classes = useUtilityClasses(props);
@@ -107,16 +77,14 @@ var SimpleTreeView = /*#__PURE__*/React.forwardRef(function SimpleTreeView(inPro
107
77
  var rootProps = useSlotProps({
108
78
  elementType: Root,
109
79
  externalSlotProps: {},
110
- externalForwardedProps: other,
80
+ externalForwardedProps: otherProps,
111
81
  className: classes.root,
112
82
  getSlotProps: getRootProps,
113
83
  ownerState: ownerState
114
84
  });
115
85
  return /*#__PURE__*/_jsx(TreeViewProvider, {
116
86
  value: contextValue,
117
- children: /*#__PURE__*/_jsx(Root, _extends({}, rootProps, {
118
- children: children
119
- }))
87
+ children: /*#__PURE__*/_jsx(Root, _extends({}, rootProps))
120
88
  });
121
89
  });
122
90
  process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
@@ -23,7 +23,7 @@ var TreeViewRoot = styled(SimpleTreeViewRoot, {
23
23
  var warnedOnce = false;
24
24
  var warn = function 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
  };
package/legacy/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-tree-view v7.0.0-alpha.7
2
+ * @mui/x-tree-view v7.0.0-alpha.8
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -3,7 +3,7 @@ import { TreeViewContext } from './TreeViewContext';
3
3
  export var useTreeViewContext = function useTreeViewContext() {
4
4
  var 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
  };
@@ -36,4 +36,5 @@ export var useTreeViewInstanceEvents = function useTreeViewInstanceEvents(_ref)
36
36
  $$publishEvent: publishEvent,
37
37
  $$subscribeEvent: subscribeEvent
38
38
  });
39
- };
39
+ };
40
+ useTreeViewInstanceEvents.params = {};
@@ -0,0 +1 @@
1
+ export {};
@@ -25,4 +25,10 @@ export var useTreeViewContextValueBuilder = function useTreeViewContextValueBuil
25
25
  }
26
26
  }
27
27
  };
28
+ };
29
+ useTreeViewContextValueBuilder.params = {
30
+ defaultCollapseIcon: true,
31
+ defaultEndIcon: true,
32
+ defaultExpandIcon: true,
33
+ defaultParentIcon: true
28
34
  };
@@ -72,4 +72,10 @@ useTreeViewExpansion.getDefaultizedParams = function (params) {
72
72
  return _extends({}, params, {
73
73
  defaultExpandedNodes: (_params$defaultExpand = params.defaultExpandedNodes) != null ? _params$defaultExpand : DEFAULT_EXPANDED_NODES
74
74
  });
75
+ };
76
+ useTreeViewExpansion.params = {
77
+ expandedNodes: true,
78
+ defaultExpandedNodes: true,
79
+ onExpandedNodesChange: true,
80
+ onNodeExpansionToggle: true
75
81
  };
@@ -103,4 +103,7 @@ useTreeViewFocus.getDefaultizedParams = function (params) {
103
103
  return _extends({}, params, {
104
104
  disabledItemsFocusable: (_params$disabledItems = params.disabledItemsFocusable) != null ? _params$disabledItems : false
105
105
  });
106
+ };
107
+ useTreeViewFocus.params = {
108
+ onNodeFocus: true
106
109
  };
@@ -18,4 +18,7 @@ export var useTreeViewId = function useTreeViewId(_ref) {
18
18
  };
19
19
  }
20
20
  };
21
+ };
22
+ useTreeViewId.params = {
23
+ id: true
21
24
  };
@@ -117,4 +117,5 @@ var useTreeViewJSXNodesItemPlugin = function useTreeViewJSXNodesItemPlugin(_ref2
117
117
  }
118
118
  };
119
119
  };
120
- useTreeViewJSXNodes.itemPlugin = useTreeViewJSXNodesItemPlugin;
120
+ useTreeViewJSXNodes.itemPlugin = useTreeViewJSXNodesItemPlugin;
121
+ useTreeViewJSXNodes.params = {};
@@ -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 (var i = startIndex; i < firstChars.length; i += 1) {
@@ -18,7 +18,7 @@ export var useTreeViewKeyboardNavigation = function useTreeViewKeyboardNavigatio
18
18
  params = _ref.params,
19
19
  state = _ref.state;
20
20
  var theme = useTheme();
21
- var isRtl = theme.direction === 'rtl';
21
+ var isRTL = theme.direction === 'rtl';
22
22
  var firstCharMap = React.useRef({});
23
23
  var hasFirstCharMapBeenUpdatedImperatively = React.useRef(false);
24
24
  var updateFirstCharMap = useEventCallback(function (callback) {
@@ -43,32 +43,7 @@ export var useTreeViewKeyboardNavigation = function useTreeViewKeyboardNavigatio
43
43
  populateInstance(instance, {
44
44
  updateFirstCharMap: updateFirstCharMap
45
45
  });
46
- var handleNextArrow = function handleNextArrow(event) {
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
- var handlePreviousArrow = function 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
- var parent = instance.getNode(state.focusedNodeId).parentId;
65
- if (parent) {
66
- instance.focusNode(event, parent);
67
- return true;
68
- }
69
- return false;
70
- };
71
- var focusByFirstCharacter = function focusByFirstCharacter(event, nodeId, firstChar) {
46
+ var getFirstMatchingNode = function getFirstMatchingNode(nodeId, firstChar) {
72
47
  var start;
73
48
  var index;
74
49
  var lowercaseChar = firstChar.toLowerCase();
@@ -99,43 +74,41 @@ export var useTreeViewKeyboardNavigation = function useTreeViewKeyboardNavigatio
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
- instance.focusNode(event, firstCharIds[index]);
79
+ return firstCharIds[index];
105
80
  }
81
+ return null;
106
82
  };
107
- var selectNextNode = function 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
- }
83
+ var canToggleNodeSelection = function canToggleNodeSelection(nodeId) {
84
+ return !params.disableSelection && !instance.isNodeDisabled(nodeId);
114
85
  };
115
- var selectPreviousNode = function selectPreviousNode(event, nodeId) {
116
- if (!instance.isNodeDisabled(getPreviousNode(instance, nodeId))) {
117
- instance.selectRange(event, {
118
- end: getPreviousNode(instance, nodeId),
119
- current: nodeId
120
- }, true);
121
- }
86
+ var canToggleNodeExpansion = function canToggleNodeExpansion(nodeId) {
87
+ return !instance.isNodeDisabled(nodeId) && instance.isNodeExpandable(nodeId);
122
88
  };
89
+
90
+ // ARIA specification: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/#keyboardinteraction
123
91
  var createHandleKeyDown = function createHandleKeyDown(otherHandlers) {
124
92
  return function (event) {
125
93
  var _otherHandlers$onKeyD;
126
94
  (_otherHandlers$onKeyD = otherHandlers.onKeyDown) == null || _otherHandlers$onKeyD.call(otherHandlers, event);
127
- var flag = false;
128
- var key = event.key;
95
+ if (event.defaultMuiPrevented) {
96
+ return;
97
+ }
129
98
 
130
99
  // If the tree is empty there will be no focused node
131
100
  if (event.altKey || event.currentTarget !== event.target || state.focusedNodeId == null) {
132
101
  return;
133
102
  }
134
103
  var ctrlPressed = event.ctrlKey || event.metaKey;
135
- switch (key) {
136
- case ' ':
137
- if (!params.disableSelection && !instance.isNodeDisabled(state.focusedNodeId)) {
138
- flag = true;
104
+ var key = event.key;
105
+
106
+ // eslint-disable-next-line default-case
107
+ switch (true) {
108
+ // Select the node when pressing "Space"
109
+ case key === ' ' && canToggleNodeSelection(state.focusedNodeId):
110
+ {
111
+ event.preventDefault();
139
112
  if (params.multiSelect && event.shiftKey) {
140
113
  instance.selectRange(event, {
141
114
  end: state.focusedNodeId
@@ -145,85 +118,158 @@ export var useTreeViewKeyboardNavigation = function useTreeViewKeyboardNavigatio
145
118
  } else {
146
119
  instance.selectNode(event, state.focusedNodeId);
147
120
  }
121
+ break;
148
122
  }
149
- event.stopPropagation();
150
- break;
151
- case 'Enter':
152
- if (!instance.isNodeDisabled(state.focusedNodeId)) {
153
- if (instance.isNodeExpandable(state.focusedNodeId)) {
123
+
124
+ // If the focused node has children, we expand it.
125
+ // If the focused node has no children, we select it.
126
+ case key === 'Enter':
127
+ {
128
+ if (canToggleNodeExpansion(state.focusedNodeId)) {
154
129
  instance.toggleNodeExpansion(event, state.focusedNodeId);
155
- flag = true;
156
- } else if (!params.disableSelection) {
157
- flag = true;
130
+ event.preventDefault();
131
+ } else if (canToggleNodeSelection(state.focusedNodeId)) {
158
132
  if (params.multiSelect) {
133
+ event.preventDefault();
159
134
  instance.selectNode(event, state.focusedNodeId, true);
160
- } else {
135
+ } else if (!instance.isNodeSelected(state.focusedNodeId)) {
161
136
  instance.selectNode(event, state.focusedNodeId);
137
+ event.preventDefault();
162
138
  }
163
139
  }
140
+ break;
164
141
  }
165
- event.stopPropagation();
166
- break;
167
- case 'ArrowDown':
168
- if (params.multiSelect && event.shiftKey && !params.disableSelection) {
169
- selectNextNode(event, state.focusedNodeId);
142
+
143
+ // Focus the next focusable node
144
+ case key === 'ArrowDown':
145
+ {
146
+ var nextNode = getNextNode(instance, state.focusedNodeId);
147
+ if (nextNode) {
148
+ event.preventDefault();
149
+ instance.focusNode(event, nextNode);
150
+
151
+ // Multi select behavior when pressing Shift + ArrowDown
152
+ // Toggles the selection state of the next node
153
+ if (params.multiSelect && event.shiftKey && canToggleNodeSelection(nextNode)) {
154
+ instance.selectRange(event, {
155
+ end: nextNode,
156
+ current: state.focusedNodeId
157
+ }, true);
158
+ }
159
+ }
160
+ break;
170
161
  }
171
- instance.focusNode(event, getNextNode(instance, state.focusedNodeId));
172
- flag = true;
173
- break;
174
- case 'ArrowUp':
175
- if (params.multiSelect && event.shiftKey && !params.disableSelection) {
176
- selectPreviousNode(event, state.focusedNodeId);
162
+
163
+ // Focuses the previous focusable node
164
+ case key === 'ArrowUp':
165
+ {
166
+ var previousNode = getPreviousNode(instance, state.focusedNodeId);
167
+ if (previousNode) {
168
+ event.preventDefault();
169
+ instance.focusNode(event, previousNode);
170
+
171
+ // Multi select behavior when pressing Shift + ArrowUp
172
+ // Toggles the selection state of the previous node
173
+ if (params.multiSelect && event.shiftKey && canToggleNodeSelection(previousNode)) {
174
+ instance.selectRange(event, {
175
+ end: previousNode,
176
+ current: state.focusedNodeId
177
+ }, true);
178
+ }
179
+ }
180
+ break;
177
181
  }
178
- instance.focusNode(event, getPreviousNode(instance, state.focusedNodeId));
179
- flag = true;
180
- break;
181
- case 'ArrowRight':
182
- if (isRtl) {
183
- flag = handlePreviousArrow(event);
184
- } else {
185
- flag = handleNextArrow(event);
182
+
183
+ // If the focused node is expanded, we move the focus to its first child
184
+ // If the focused node is collapsed and has children, we expand it
185
+ case key === 'ArrowRight' && !isRTL || key === 'ArrowLeft' && isRTL:
186
+ {
187
+ if (instance.isNodeExpanded(state.focusedNodeId)) {
188
+ instance.focusNode(event, getNextNode(instance, state.focusedNodeId));
189
+ event.preventDefault();
190
+ } else if (canToggleNodeExpansion(state.focusedNodeId)) {
191
+ instance.toggleNodeExpansion(event, state.focusedNodeId);
192
+ event.preventDefault();
193
+ }
194
+ break;
186
195
  }
187
- break;
188
- case 'ArrowLeft':
189
- if (isRtl) {
190
- flag = handleNextArrow(event);
191
- } else {
192
- flag = handlePreviousArrow(event);
196
+
197
+ // If the focused node is expanded, we collapse it
198
+ // If the focused node is collapsed and has a parent, we move the focus to this parent
199
+ case key === 'ArrowLeft' && !isRTL || key === 'ArrowRight' && isRTL:
200
+ {
201
+ if (canToggleNodeExpansion(state.focusedNodeId) && instance.isNodeExpanded(state.focusedNodeId)) {
202
+ instance.toggleNodeExpansion(event, state.focusedNodeId);
203
+ event.preventDefault();
204
+ } else {
205
+ var parent = instance.getNode(state.focusedNodeId).parentId;
206
+ if (parent) {
207
+ instance.focusNode(event, parent);
208
+ event.preventDefault();
209
+ }
210
+ }
211
+ break;
193
212
  }
194
- break;
195
- case 'Home':
196
- if (params.multiSelect && ctrlPressed && event.shiftKey && !params.disableSelection && !instance.isNodeDisabled(state.focusedNodeId)) {
197
- instance.rangeSelectToFirst(event, state.focusedNodeId);
213
+
214
+ // Focuses the first node in the tree
215
+ case key === 'Home':
216
+ {
217
+ instance.focusNode(event, getFirstNode(instance));
218
+
219
+ // Multi select behavior when pressing Ctrl + Shift + Home
220
+ // Selects the focused node and all nodes up to the first node.
221
+ if (canToggleNodeSelection(state.focusedNodeId) && params.multiSelect && ctrlPressed && event.shiftKey) {
222
+ instance.rangeSelectToFirst(event, state.focusedNodeId);
223
+ }
224
+ event.preventDefault();
225
+ break;
198
226
  }
199
- instance.focusNode(event, getFirstNode(instance));
200
- flag = true;
201
- break;
202
- case 'End':
203
- if (params.multiSelect && ctrlPressed && event.shiftKey && !params.disableSelection && !instance.isNodeDisabled(state.focusedNodeId)) {
204
- instance.rangeSelectToLast(event, state.focusedNodeId);
227
+
228
+ // Focuses the last node in the tree
229
+ case key === 'End':
230
+ {
231
+ instance.focusNode(event, getLastNode(instance));
232
+
233
+ // Multi select behavior when pressing Ctrl + Shirt + End
234
+ // Selects the focused node and all the nodes down to the last node.
235
+ if (canToggleNodeSelection(state.focusedNodeId) && params.multiSelect && ctrlPressed && event.shiftKey) {
236
+ instance.rangeSelectToLast(event, state.focusedNodeId);
237
+ }
238
+ event.preventDefault();
239
+ break;
205
240
  }
206
- instance.focusNode(event, getLastNode(instance));
207
- flag = true;
208
- break;
209
- default:
210
- if (key === '*') {
241
+
242
+ // Expand all siblings that are at the same level as the focused node
243
+ case key === '*':
244
+ {
211
245
  instance.expandAllSiblings(event, state.focusedNodeId);
212
- flag = true;
213
- } else if (params.multiSelect && ctrlPressed && key.toLowerCase() === 'a' && !params.disableSelection) {
246
+ event.preventDefault();
247
+ break;
248
+ }
249
+
250
+ // Multi select behavior when pressing Ctrl + a
251
+ // Selects all the nodes
252
+ case key === 'a' && ctrlPressed && params.multiSelect && !params.disableSelection:
253
+ {
214
254
  instance.selectRange(event, {
215
255
  start: getFirstNode(instance),
216
256
  end: getLastNode(instance)
217
257
  });
218
- flag = true;
219
- } else if (!ctrlPressed && !event.shiftKey && isPrintableCharacter(key)) {
220
- focusByFirstCharacter(event, state.focusedNodeId, key);
221
- flag = true;
258
+ event.preventDefault();
259
+ break;
260
+ }
261
+
262
+ // Type-ahead
263
+ // TODO: Support typing multiple characters
264
+ case !ctrlPressed && !event.shiftKey && isPrintableCharacter(key):
265
+ {
266
+ var matchingNode = getFirstMatchingNode(state.focusedNodeId, key);
267
+ if (matchingNode != null) {
268
+ instance.focusNode(event, matchingNode);
269
+ event.preventDefault();
270
+ }
271
+ break;
222
272
  }
223
- }
224
- if (flag) {
225
- event.preventDefault();
226
- event.stopPropagation();
227
273
  }
228
274
  };
229
275
  };
@@ -234,4 +280,5 @@ export var useTreeViewKeyboardNavigation = function useTreeViewKeyboardNavigatio
234
280
  };
235
281
  }
236
282
  };
237
- };
283
+ };
284
+ useTreeViewKeyboardNavigation.params = {};
@@ -13,11 +13,11 @@ var updateState = function updateState(_ref) {
13
13
  var _item$children, _item$children2;
14
14
  var 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
  var 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: id,
@@ -137,4 +137,11 @@ useTreeViewNodes.getInitialState = function (params) {
137
137
  getItemId: params.getItemId,
138
138
  getItemLabel: params.getItemLabel
139
139
  });
140
+ };
141
+ useTreeViewNodes.params = {
142
+ disabledItemsFocusable: true,
143
+ items: true,
144
+ isItemDisabled: true,
145
+ getItemLabel: true,
146
+ getItemId: true
140
147
  };
@@ -202,4 +202,12 @@ useTreeViewSelection.getDefaultizedParams = function (params) {
202
202
  multiSelect: (_params$multiSelect = params.multiSelect) != null ? _params$multiSelect : false,
203
203
  defaultSelectedNodes: (_params$defaultSelect = params.defaultSelectedNodes) != null ? _params$defaultSelect : params.multiSelect ? DEFAULT_SELECTED_NODES : null
204
204
  });
205
+ };
206
+ useTreeViewSelection.params = {
207
+ disableSelection: true,
208
+ multiSelect: true,
209
+ defaultSelectedNodes: true,
210
+ selectedNodes: true,
211
+ onSelectedNodesChange: true,
212
+ onNodeSelectionToggle: true
205
213
  };
@@ -58,14 +58,14 @@ export var useTreeViewModels = function useTreeViewModels(plugins, props) {
58
58
  var defaultProp = props[model.defaultProp];
59
59
  React.useEffect(function () {
60
60
  if (model.isControlled !== (controlled !== undefined)) {
61
- console.error(["MUI: A component is changing the ".concat(model.isControlled ? '' : 'un', "controlled ").concat(modelName, " state of TreeView to be ").concat(model.isControlled ? 'un' : '', "controlled."), 'Elements should not switch from uncontrolled to controlled (or vice versa).', "Decide between using a controlled or uncontrolled ".concat(modelName, " ") + 'element for the lifetime of the component.', "The nature of the state is determined during the first render. It's considered controlled if the value is not `undefined`.", 'More info: https://fb.me/react-controlled-components'].join('\n'));
61
+ console.error(["MUI X: A component is changing the ".concat(model.isControlled ? '' : 'un', "controlled ").concat(modelName, " state of TreeView to be ").concat(model.isControlled ? 'un' : '', "controlled."), 'Elements should not switch from uncontrolled to controlled (or vice versa).', "Decide between using a controlled or uncontrolled ".concat(modelName, " ") + 'element for the lifetime of the component.', "The nature of the state is determined during the first render. It's considered controlled if the value is not `undefined`.", 'More info: https://fb.me/react-controlled-components'].join('\n'));
62
62
  }
63
63
  }, [controlled]);
64
64
  var _React$useRef = React.useRef(defaultProp),
65
65
  defaultValue = _React$useRef.current;
66
66
  React.useEffect(function () {
67
67
  if (!model.isControlled && defaultValue !== defaultProp) {
68
- console.error(["MUI: A component is changing the default ".concat(modelName, " state of an uncontrolled TreeView after being initialized. ") + "To suppress this warning opt to use a controlled TreeView."].join('\n'));
68
+ console.error(["MUI X: A component is changing the default ".concat(modelName, " state of an uncontrolled TreeView after being initialized. ") + "To suppress this warning opt to use a controlled TreeView."].join('\n'));
69
69
  }
70
70
  }, [JSON.stringify(defaultValue)]);
71
71
  });
@@ -0,0 +1,27 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ export var extractPluginParamsFromProps = function extractPluginParamsFromProps(_ref) {
3
+ var props = _ref.props,
4
+ plugins = _ref.plugins,
5
+ rootRef = _ref.rootRef;
6
+ var paramsLookup = {};
7
+ plugins.forEach(function (plugin) {
8
+ _extends(paramsLookup, plugin.params);
9
+ });
10
+ var pluginParams = {
11
+ plugins: plugins,
12
+ rootRef: rootRef
13
+ };
14
+ var otherProps = {};
15
+ Object.keys(props).forEach(function (propName) {
16
+ var prop = props[propName];
17
+ if (paramsLookup[propName]) {
18
+ pluginParams[propName] = prop;
19
+ } else {
20
+ otherProps[propName] = prop;
21
+ }
22
+ });
23
+ return {
24
+ pluginParams: pluginParams,
25
+ otherProps: otherProps
26
+ };
27
+ };