@mui/x-tree-view 7.5.1 → 7.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/CHANGELOG.md +112 -1
  2. package/RichTreeView/RichTreeView.js +14 -0
  3. package/RichTreeView/RichTreeView.types.d.ts +7 -1
  4. package/SimpleTreeView/SimpleTreeView.js +14 -0
  5. package/SimpleTreeView/SimpleTreeView.types.d.ts +7 -1
  6. package/TreeItem/TreeItem.js +35 -7
  7. package/TreeItem/TreeItem.types.d.ts +1 -0
  8. package/TreeItem2/TreeItem2.d.ts +12 -6
  9. package/TreeItem2/TreeItem2.js +21 -10
  10. package/TreeItem2Provider/TreeItem2Provider.js +4 -2
  11. package/TreeView/TreeView.js +14 -0
  12. package/index.js +1 -1
  13. package/internals/TreeViewItemDepthContext/TreeViewItemDepthContext.d.ts +3 -0
  14. package/internals/TreeViewItemDepthContext/TreeViewItemDepthContext.js +5 -0
  15. package/internals/TreeViewItemDepthContext/index.d.ts +1 -0
  16. package/internals/TreeViewItemDepthContext/index.js +1 -0
  17. package/internals/TreeViewProvider/TreeViewContext.d.ts +2 -2
  18. package/internals/TreeViewProvider/TreeViewProvider.types.d.ts +2 -2
  19. package/internals/index.d.ts +1 -1
  20. package/internals/models/helpers.d.ts +1 -0
  21. package/internals/models/plugin.d.ts +12 -5
  22. package/internals/models/treeView.d.ts +8 -1
  23. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +28 -4
  24. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +11 -26
  25. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +20 -5
  26. package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +10 -1
  27. package/internals/plugins/useTreeViewItems/useTreeViewItems.js +29 -8
  28. package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +50 -7
  29. package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +34 -25
  30. package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.types.d.ts +22 -4
  31. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +14 -1
  32. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +5 -0
  33. package/internals/useTreeView/useTreeView.js +8 -3
  34. package/internals/useTreeView/useTreeView.types.d.ts +2 -1
  35. package/internals/utils/extractPluginParamsFromProps.d.ts +3 -2
  36. package/internals/utils/extractPluginParamsFromProps.js +4 -2
  37. package/internals/utils/tree.js +18 -1
  38. package/modern/RichTreeView/RichTreeView.js +14 -0
  39. package/modern/SimpleTreeView/SimpleTreeView.js +14 -0
  40. package/modern/TreeItem/TreeItem.js +35 -7
  41. package/modern/TreeItem2/TreeItem2.js +21 -10
  42. package/modern/TreeItem2Provider/TreeItem2Provider.js +4 -2
  43. package/modern/TreeView/TreeView.js +14 -0
  44. package/modern/index.js +1 -1
  45. package/modern/internals/TreeViewItemDepthContext/TreeViewItemDepthContext.js +5 -0
  46. package/modern/internals/TreeViewItemDepthContext/index.js +1 -0
  47. package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +11 -26
  48. package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.js +29 -8
  49. package/modern/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +34 -25
  50. package/modern/internals/useTreeView/useTreeView.js +8 -3
  51. package/modern/internals/utils/extractPluginParamsFromProps.js +4 -2
  52. package/modern/internals/utils/tree.js +18 -1
  53. package/modern/useTreeItem2/useTreeItem2.js +20 -3
  54. package/node/RichTreeView/RichTreeView.js +14 -0
  55. package/node/SimpleTreeView/SimpleTreeView.js +14 -0
  56. package/node/TreeItem/TreeItem.js +35 -7
  57. package/node/TreeItem2/TreeItem2.js +20 -9
  58. package/node/TreeItem2Provider/TreeItem2Provider.js +4 -2
  59. package/node/TreeView/TreeView.js +14 -0
  60. package/node/index.js +1 -1
  61. package/node/internals/TreeViewItemDepthContext/TreeViewItemDepthContext.js +13 -0
  62. package/node/internals/TreeViewItemDepthContext/index.js +12 -0
  63. package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +11 -26
  64. package/node/internals/plugins/useTreeViewItems/useTreeViewItems.js +29 -8
  65. package/node/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +34 -25
  66. package/node/internals/useTreeView/useTreeView.js +8 -3
  67. package/node/internals/utils/extractPluginParamsFromProps.js +4 -2
  68. package/node/internals/utils/tree.js +18 -1
  69. package/node/useTreeItem2/useTreeItem2.js +20 -3
  70. package/package.json +3 -3
  71. package/useTreeItem2/useTreeItem2.js +20 -3
  72. package/useTreeItem2/useTreeItem2.types.d.ts +12 -0
@@ -7,6 +7,7 @@ import { publishTreeViewEvent } from '../../utils/publishTreeViewEvent';
7
7
  import { useTreeViewContext } from '../../TreeViewProvider/useTreeViewContext';
8
8
  import { TreeViewChildrenItemContext, TreeViewChildrenItemProvider } from '../../TreeViewProvider/TreeViewChildrenItemProvider';
9
9
  import { buildSiblingIndexes, TREE_VIEW_ROOT_PARENT_ID } from '../useTreeViewItems/useTreeViewItems.utils';
10
+ import { TreeViewItemDepthContext } from '../../TreeViewItemDepthContext';
10
11
  import { jsx as _jsx } from "react/jsx-runtime";
11
12
  export const useTreeViewJSXItems = ({
12
13
  instance,
@@ -33,6 +34,23 @@ export const useTreeViewJSXItems = ({
33
34
  })
34
35
  });
35
36
  });
37
+ return () => {
38
+ setState(prevState => {
39
+ const newItemMetaMap = _extends({}, prevState.items.itemMetaMap);
40
+ const newItemMap = _extends({}, prevState.items.itemMap);
41
+ delete newItemMetaMap[item.id];
42
+ delete newItemMap[item.id];
43
+ return _extends({}, prevState, {
44
+ items: _extends({}, prevState.items, {
45
+ itemMetaMap: newItemMetaMap,
46
+ itemMap: newItemMap
47
+ })
48
+ });
49
+ });
50
+ publishTreeViewEvent(instance, 'removeItem', {
51
+ id: item.id
52
+ });
53
+ };
36
54
  });
37
55
  const setJSXItemsOrderedChildrenIds = (parentId, orderedChildrenIds) => {
38
56
  const parentIdWithDefault = parentId ?? TREE_VIEW_ROOT_PARENT_ID;
@@ -47,23 +65,6 @@ export const useTreeViewJSXItems = ({
47
65
  })
48
66
  }));
49
67
  };
50
- const removeJSXItem = useEventCallback(itemId => {
51
- setState(prevState => {
52
- const newItemMetaMap = _extends({}, prevState.items.itemMetaMap);
53
- const newItemMap = _extends({}, prevState.items.itemMap);
54
- delete newItemMetaMap[itemId];
55
- delete newItemMap[itemId];
56
- return _extends({}, prevState, {
57
- items: _extends({}, prevState.items, {
58
- itemMetaMap: newItemMetaMap,
59
- itemMap: newItemMap
60
- })
61
- });
62
- });
63
- publishTreeViewEvent(instance, 'removeItem', {
64
- id: itemId
65
- });
66
- });
67
68
  const mapFirstCharFromJSX = useEventCallback((itemId, firstChar) => {
68
69
  instance.updateFirstCharMap(firstCharMap => {
69
70
  firstCharMap[itemId] = firstChar;
@@ -80,7 +81,6 @@ export const useTreeViewJSXItems = ({
80
81
  return {
81
82
  instance: {
82
83
  insertJSXItem,
83
- removeJSXItem,
84
84
  setJSXItemsOrderedChildrenIds,
85
85
  mapFirstCharFromJSX
86
86
  }
@@ -129,14 +129,13 @@ const useTreeViewJSXItemsItemPlugin = ({
129
129
  };
130
130
  }, [instance, registerChild, unregisterChild, itemId, id]);
131
131
  React.useEffect(() => {
132
- instance.insertJSXItem({
132
+ return instance.insertJSXItem({
133
133
  id: itemId,
134
134
  idAttribute: id,
135
135
  parentId,
136
136
  expandable,
137
137
  disabled
138
138
  });
139
- return () => instance.removeJSXItem(itemId);
140
139
  }, [instance, parentId, itemId, expandable, disabled, id]);
141
140
  React.useEffect(() => {
142
141
  if (label) {
@@ -153,13 +152,23 @@ useTreeViewJSXItems.itemPlugin = useTreeViewJSXItemsItemPlugin;
153
152
  useTreeViewJSXItems.wrapItem = ({
154
153
  children,
155
154
  itemId
156
- }) => /*#__PURE__*/_jsx(TreeViewChildrenItemProvider, {
157
- itemId: itemId,
158
- children: children
159
- });
155
+ }) => {
156
+ // eslint-disable-next-line react-hooks/rules-of-hooks
157
+ const depthContext = React.useContext(TreeViewItemDepthContext);
158
+ return /*#__PURE__*/_jsx(TreeViewChildrenItemProvider, {
159
+ itemId: itemId,
160
+ children: /*#__PURE__*/_jsx(TreeViewItemDepthContext.Provider, {
161
+ value: depthContext + 1,
162
+ children: children
163
+ })
164
+ });
165
+ };
160
166
  useTreeViewJSXItems.wrapRoot = ({
161
167
  children
162
168
  }) => /*#__PURE__*/_jsx(TreeViewChildrenItemProvider, {
163
- children: children
169
+ children: /*#__PURE__*/_jsx(TreeViewItemDepthContext.Provider, {
170
+ value: 0,
171
+ children: children
172
+ })
164
173
  });
165
174
  useTreeViewJSXItems.params = {};
@@ -48,6 +48,7 @@ export const useTreeView = inParams => {
48
48
  params,
49
49
  slots: params.slots,
50
50
  slotProps: params.slotProps,
51
+ experimentalFeatures: params.experimentalFeatures,
51
52
  state,
52
53
  setState,
53
54
  rootRef: innerRootRef,
@@ -100,19 +101,23 @@ export const useTreeView = inParams => {
100
101
  itemWrappers.forEach(itemWrapper => {
101
102
  finalChildren = itemWrapper({
102
103
  itemId,
103
- children: finalChildren
104
+ children: finalChildren,
105
+ instance
104
106
  });
105
107
  });
106
108
  return finalChildren;
107
109
  };
108
- const rootWrappers = plugins.map(plugin => plugin.wrapRoot).filter(wrapRoot => !!wrapRoot);
110
+ const rootWrappers = plugins.map(plugin => plugin.wrapRoot).filter(wrapRoot => !!wrapRoot)
111
+ // The wrappers are reversed to ensure that the first wrapper is the outermost one.
112
+ .reverse();
109
113
  contextValue.wrapRoot = ({
110
114
  children
111
115
  }) => {
112
116
  let finalChildren = children;
113
117
  rootWrappers.forEach(rootWrapper => {
114
118
  finalChildren = rootWrapper({
115
- children: finalChildren
119
+ children: finalChildren,
120
+ instance
116
121
  });
117
122
  });
118
123
  return finalChildren;
@@ -1,11 +1,12 @@
1
1
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
2
- const _excluded = ["slots", "slotProps", "apiRef"];
2
+ const _excluded = ["slots", "slotProps", "apiRef", "experimentalFeatures"];
3
3
  export const extractPluginParamsFromProps = _ref => {
4
4
  let {
5
5
  props: {
6
6
  slots,
7
7
  slotProps,
8
- apiRef
8
+ apiRef,
9
+ experimentalFeatures
9
10
  },
10
11
  plugins,
11
12
  rootRef
@@ -20,6 +21,7 @@ export const extractPluginParamsFromProps = _ref => {
20
21
  rootRef,
21
22
  slots: slots ?? {},
22
23
  slotProps: slotProps ?? {},
24
+ experimentalFeatures: experimentalFeatures ?? {},
23
25
  apiRef
24
26
  };
25
27
  const otherProps = {};
@@ -18,7 +18,24 @@ export const getPreviousNavigableItem = (instance, itemId) => {
18
18
  if (itemIndex === 0) {
19
19
  return itemMeta.parentId;
20
20
  }
21
- let currentItemId = siblings[itemIndex - 1];
21
+
22
+ // Finds the previous navigable sibling.
23
+ let previousNavigableSiblingIndex = itemIndex - 1;
24
+ while (!instance.isItemNavigable(siblings[previousNavigableSiblingIndex]) && previousNavigableSiblingIndex >= 0) {
25
+ previousNavigableSiblingIndex -= 1;
26
+ }
27
+ if (previousNavigableSiblingIndex === -1) {
28
+ // If we are at depth 0, then it means all the items above the current item are not navigable.
29
+ if (itemMeta.parentId == null) {
30
+ return null;
31
+ }
32
+
33
+ // Otherwise, we can try to go up a level and find the previous navigable item.
34
+ return getPreviousNavigableItem(instance, itemMeta.parentId);
35
+ }
36
+
37
+ // Finds the last navigable ancestor of the previous navigable sibling.
38
+ let currentItemId = siblings[previousNavigableSiblingIndex];
22
39
  let lastNavigableChild = getLastNavigableItemInArray(instance, instance.getItemOrderedChildrenIds(currentItemId));
23
40
  while (instance.isItemExpanded(currentItemId) && lastNavigableChild != null) {
24
41
  currentItemId = lastNavigableChild;
@@ -4,6 +4,7 @@ import { extractEventHandlers } from '@mui/base/utils';
4
4
  import useForkRef from '@mui/utils/useForkRef';
5
5
  import { useTreeViewContext } from '../internals/TreeViewProvider/useTreeViewContext';
6
6
  import { useTreeItem2Utils } from '../hooks/useTreeItem2Utils';
7
+ import { TreeViewItemDepthContext } from '../internals/TreeViewItemDepthContext';
7
8
  export const useTreeItem2 = parameters => {
8
9
  const {
9
10
  runItemPlugins,
@@ -13,9 +14,11 @@ export const useTreeItem2 = parameters => {
13
14
  checkboxSelection
14
15
  },
15
16
  disabledItemsFocusable,
17
+ indentationAtItemLevel,
16
18
  instance,
17
19
  publicAPI
18
20
  } = useTreeViewContext();
21
+ const depthContext = React.useContext(TreeViewItemDepthContext);
19
22
  const {
20
23
  id,
21
24
  itemId,
@@ -106,7 +109,7 @@ export const useTreeItem2 = parameters => {
106
109
  */
107
110
  ariaSelected = true;
108
111
  }
109
- return _extends({}, externalEventHandlers, {
112
+ const response = _extends({}, externalEventHandlers, {
110
113
  ref: handleRootRef,
111
114
  role: 'treeitem',
112
115
  tabIndex: instance.canItemBeTabbed(itemId) ? 0 : -1,
@@ -119,15 +122,25 @@ export const useTreeItem2 = parameters => {
119
122
  onBlur: createRootHandleBlur(externalEventHandlers),
120
123
  onKeyDown: createRootHandleKeyDown(externalEventHandlers)
121
124
  });
125
+ if (indentationAtItemLevel) {
126
+ response.style = {
127
+ '--TreeView-itemDepth': typeof depthContext === 'function' ? depthContext(itemId) : depthContext
128
+ };
129
+ }
130
+ return response;
122
131
  };
123
132
  const getContentProps = (externalProps = {}) => {
124
133
  const externalEventHandlers = extractEventHandlers(externalProps);
125
- return _extends({}, externalEventHandlers, externalProps, {
134
+ const response = _extends({}, externalEventHandlers, externalProps, {
126
135
  ref: contentRef,
127
136
  onClick: createContentHandleClick(externalEventHandlers),
128
137
  onMouseDown: createContentHandleMouseDown(externalEventHandlers),
129
138
  status
130
139
  });
140
+ if (indentationAtItemLevel) {
141
+ response.indentationAtItemLevel = true;
142
+ }
143
+ return response;
131
144
  };
132
145
  const getCheckboxProps = (externalProps = {}) => {
133
146
  const externalEventHandlers = extractEventHandlers(externalProps);
@@ -153,13 +166,17 @@ export const useTreeItem2 = parameters => {
153
166
  };
154
167
  const getGroupTransitionProps = (externalProps = {}) => {
155
168
  const externalEventHandlers = extractEventHandlers(externalProps);
156
- return _extends({}, externalEventHandlers, {
169
+ const response = _extends({}, externalEventHandlers, {
157
170
  unmountOnExit: true,
158
171
  component: 'ul',
159
172
  role: 'group',
160
173
  in: status.expanded,
161
174
  children
162
175
  }, externalProps);
176
+ if (indentationAtItemLevel) {
177
+ response.indentationAtItemLevel = true;
178
+ }
179
+ return response;
163
180
  };
164
181
  return {
165
182
  getRootProps,
@@ -189,6 +189,14 @@ process.env.NODE_ENV !== "production" ? RichTreeView.propTypes = {
189
189
  * Used when the item's expansion is controlled.
190
190
  */
191
191
  expandedItems: _propTypes.default.arrayOf(_propTypes.default.string),
192
+ /**
193
+ * Unstable features, breaking changes might be introduced.
194
+ * For each feature, if the flag is not explicitly set to `true`,
195
+ * the feature will be fully disabled and any property / method call will not have any effect.
196
+ */
197
+ experimentalFeatures: _propTypes.default.shape({
198
+ indentationAtItemLevel: _propTypes.default.bool
199
+ }),
192
200
  /**
193
201
  * Used to determine the id of a given item.
194
202
  *
@@ -219,6 +227,12 @@ process.env.NODE_ENV !== "production" ? RichTreeView.propTypes = {
219
227
  * @returns {boolean} `true` if the item should be disabled.
220
228
  */
221
229
  isItemDisabled: _propTypes.default.func,
230
+ /**
231
+ * Horizontal indentation between an item and its children.
232
+ * Examples: 24, "24px", "2rem", "2em".
233
+ * @default 12px
234
+ */
235
+ itemChildrenIndentation: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
222
236
  items: _propTypes.default.array.isRequired,
223
237
  /**
224
238
  * If `true`, `ctrl` and `shift` will trigger multiselect.
@@ -151,11 +151,25 @@ process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
151
151
  * Used when the item's expansion is controlled.
152
152
  */
153
153
  expandedItems: _propTypes.default.arrayOf(_propTypes.default.string),
154
+ /**
155
+ * Unstable features, breaking changes might be introduced.
156
+ * For each feature, if the flag is not explicitly set to `true`,
157
+ * the feature will be fully disabled and any property / method call will not have any effect.
158
+ */
159
+ experimentalFeatures: _propTypes.default.shape({
160
+ indentationAtItemLevel: _propTypes.default.bool
161
+ }),
154
162
  /**
155
163
  * This prop is used to help implement the accessibility logic.
156
164
  * If you don't provide this prop. It falls back to a randomly generated id.
157
165
  */
158
166
  id: _propTypes.default.string,
167
+ /**
168
+ * Horizontal indentation between an item and its children.
169
+ * Examples: 24, "24px", "2rem", "2em".
170
+ * @default 12px
171
+ */
172
+ itemChildrenIndentation: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
159
173
  /**
160
174
  * If `true`, `ctrl` and `shift` will trigger multiselect.
161
175
  * @default false
@@ -13,6 +13,7 @@ var _clsx = _interopRequireDefault(require("clsx"));
13
13
  var _Collapse = _interopRequireDefault(require("@mui/material/Collapse"));
14
14
  var _utils = require("@mui/base/utils");
15
15
  var _useForkRef = _interopRequireDefault(require("@mui/utils/useForkRef"));
16
+ var _createStyled = require("@mui/system/createStyled");
16
17
  var _styles = require("@mui/material/styles");
17
18
  var _unsupportedProp = _interopRequireDefault(require("@mui/utils/unsupportedProp"));
18
19
  var _elementTypeAcceptingRef = _interopRequireDefault(require("@mui/utils/elementTypeAcceptingRef"));
@@ -22,6 +23,7 @@ var _treeItemClasses = require("./treeItemClasses");
22
23
  var _useTreeViewContext = require("../internals/TreeViewProvider/useTreeViewContext");
23
24
  var _icons = require("../icons");
24
25
  var _TreeItem2Provider = require("../TreeItem2Provider");
26
+ var _TreeViewItemDepthContext = require("../internals/TreeViewItemDepthContext");
25
27
  var _jsxRuntime = require("react/jsx-runtime");
26
28
  const _excluded = ["children", "className", "slots", "slotProps", "ContentComponent", "ContentProps", "itemId", "id", "label", "onClick", "onMouseDown", "onFocus", "onBlur", "onKeyDown"],
27
29
  _excluded2 = ["ownerState"],
@@ -66,7 +68,8 @@ const StyledTreeItemContent = (0, _styles.styled)(_TreeItemContent.TreeItemConte
66
68
  }, styles.label && {
67
69
  [`& .${_treeItemClasses.treeItemClasses.label}`]: styles.label
68
70
  }];
69
- }
71
+ },
72
+ shouldForwardProp: prop => (0, _createStyled.shouldForwardProp)(prop) && prop !== 'indentationAtItemLevel'
70
73
  })(({
71
74
  theme
72
75
  }) => ({
@@ -126,16 +129,33 @@ const StyledTreeItemContent = (0, _styles.styled)(_TreeItemContent.TreeItemConte
126
129
  }, theme.typography.body1),
127
130
  [`& .${_treeItemClasses.treeItemClasses.checkbox}`]: {
128
131
  padding: 0
129
- }
132
+ },
133
+ variants: [{
134
+ props: {
135
+ indentationAtItemLevel: true
136
+ },
137
+ style: {
138
+ paddingLeft: `calc(${theme.spacing(1)} + var(--TreeView-itemChildrenIndentation) * var(--TreeView-itemDepth))`
139
+ }
140
+ }]
130
141
  }));
131
142
  const TreeItemGroup = (0, _styles.styled)(_Collapse.default, {
132
143
  name: 'MuiTreeItem',
133
144
  slot: 'GroupTransition',
134
- overridesResolver: (props, styles) => styles.groupTransition
145
+ overridesResolver: (props, styles) => styles.groupTransition,
146
+ shouldForwardProp: prop => (0, _createStyled.shouldForwardProp)(prop) && prop !== 'indentationAtItemLevel'
135
147
  })({
136
148
  margin: 0,
137
149
  padding: 0,
138
- paddingLeft: 12
150
+ paddingLeft: 'var(--TreeView-itemChildrenIndentation)',
151
+ variants: [{
152
+ props: {
153
+ indentationAtItemLevel: true
154
+ },
155
+ style: {
156
+ paddingLeft: 0
157
+ }
158
+ }]
139
159
  });
140
160
 
141
161
  /**
@@ -156,8 +176,10 @@ const TreeItem = exports.TreeItem = /*#__PURE__*/React.forwardRef(function TreeI
156
176
  multiSelect
157
177
  },
158
178
  disabledItemsFocusable,
179
+ indentationAtItemLevel,
159
180
  instance
160
181
  } = (0, _useTreeViewContext.useTreeViewContext)();
182
+ const depthContext = React.useContext(_TreeViewItemDepthContext.TreeViewItemDepthContext);
161
183
  const props = (0, _styles.useThemeProps)({
162
184
  props: inProps,
163
185
  name: 'MuiTreeItem'
@@ -206,7 +228,8 @@ const TreeItem = exports.TreeItem = /*#__PURE__*/React.forwardRef(function TreeI
206
228
  expanded,
207
229
  focused,
208
230
  selected,
209
- disabled
231
+ disabled,
232
+ indentationAtItemLevel
210
233
  });
211
234
  const classes = useUtilityClasses(ownerState);
212
235
  const GroupTransition = slots.groupTransition ?? undefined;
@@ -214,12 +237,14 @@ const TreeItem = exports.TreeItem = /*#__PURE__*/React.forwardRef(function TreeI
214
237
  elementType: GroupTransition,
215
238
  ownerState: {},
216
239
  externalSlotProps: inSlotProps?.groupTransition,
217
- additionalProps: {
240
+ additionalProps: (0, _extends2.default)({
218
241
  unmountOnExit: true,
219
242
  in: expanded,
220
243
  component: 'ul',
221
244
  role: 'group'
222
- },
245
+ }, indentationAtItemLevel ? {
246
+ indentationAtItemLevel: true
247
+ } : {}),
223
248
  className: classes.groupTransition
224
249
  });
225
250
  const ExpansionIcon = expanded ? slots.collapseIcon : slots.expandIcon;
@@ -300,6 +325,9 @@ const TreeItem = exports.TreeItem = /*#__PURE__*/React.forwardRef(function TreeI
300
325
  onBlur: handleBlur,
301
326
  onKeyDown: handleKeyDown,
302
327
  ref: handleRootRef,
328
+ style: indentationAtItemLevel ? (0, _extends2.default)({}, other.style, {
329
+ '--TreeView-itemDepth': typeof depthContext === 'function' ? depthContext(itemId) : depthContext
330
+ }) : other.style,
303
331
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(StyledTreeItemContent, (0, _extends2.default)({
304
332
  as: ContentComponent,
305
333
  classes: {
@@ -15,7 +15,7 @@ var _styles = require("@mui/material/styles");
15
15
  var _Collapse = _interopRequireDefault(require("@mui/material/Collapse"));
16
16
  var _Checkbox = _interopRequireDefault(require("@mui/material/Checkbox"));
17
17
  var _utils = require("@mui/base/utils");
18
- var _system = require("@mui/system");
18
+ var _createStyled = require("@mui/system/createStyled");
19
19
  var _composeClasses = _interopRequireDefault(require("@mui/utils/composeClasses"));
20
20
  var _useTreeItem = require("../useTreeItem2");
21
21
  var _TreeItem = require("../TreeItem");
@@ -40,7 +40,7 @@ const TreeItem2Content = exports.TreeItem2Content = (0, _styles.styled)('div', {
40
40
  name: 'MuiTreeItem2',
41
41
  slot: 'Content',
42
42
  overridesResolver: (props, styles) => styles.content,
43
- shouldForwardProp: prop => (0, _system.shouldForwardProp)(prop) && prop !== 'status'
43
+ shouldForwardProp: prop => (0, _createStyled.shouldForwardProp)(prop) && prop !== 'status' && prop !== 'indentationAtItemLevel'
44
44
  })(({
45
45
  theme
46
46
  }) => ({
@@ -61,12 +61,14 @@ const TreeItem2Content = exports.TreeItem2Content = (0, _styles.styled)('div', {
61
61
  backgroundColor: 'transparent'
62
62
  }
63
63
  },
64
- [`& .${_TreeItem.treeItemClasses.groupTransition}`]: {
65
- margin: 0,
66
- padding: 0,
67
- paddingLeft: 12
68
- },
69
64
  variants: [{
65
+ props: {
66
+ indentationAtItemLevel: true
67
+ },
68
+ style: {
69
+ paddingLeft: `calc(${theme.spacing(1)} + var(--TreeView-itemChildrenIndentation) * var(--TreeView-itemDepth))`
70
+ }
71
+ }, {
70
72
  props: ({
71
73
  status
72
74
  }) => status.disabled,
@@ -134,11 +136,20 @@ const TreeItem2IconContainer = exports.TreeItem2IconContainer = (0, _styles.styl
134
136
  const TreeItem2GroupTransition = exports.TreeItem2GroupTransition = (0, _styles.styled)(_Collapse.default, {
135
137
  name: 'MuiTreeItem2',
136
138
  slot: 'GroupTransition',
137
- overridesResolver: (props, styles) => styles.groupTransition
139
+ overridesResolver: (props, styles) => styles.groupTransition,
140
+ shouldForwardProp: prop => (0, _createStyled.shouldForwardProp)(prop) && prop !== 'indentationAtItemLevel'
138
141
  })({
139
142
  margin: 0,
140
143
  padding: 0,
141
- paddingLeft: 12
144
+ paddingLeft: 'var(--TreeView-itemChildrenIndentation)',
145
+ variants: [{
146
+ props: {
147
+ indentationAtItemLevel: true
148
+ },
149
+ style: {
150
+ paddingLeft: 0
151
+ }
152
+ }]
142
153
  });
143
154
  const TreeItem2Checkbox = exports.TreeItem2Checkbox = (0, _styles.styled)( /*#__PURE__*/React.forwardRef((props, ref) => {
144
155
  const {
@@ -13,11 +13,13 @@ function TreeItem2Provider(props) {
13
13
  itemId
14
14
  } = props;
15
15
  const {
16
- wrapItem
16
+ wrapItem,
17
+ instance
17
18
  } = (0, _useTreeViewContext.useTreeViewContext)();
18
19
  return wrapItem({
19
20
  children,
20
- itemId
21
+ itemId,
22
+ instance
21
23
  });
22
24
  }
23
25
  TreeItem2Provider.propTypes = {
@@ -124,11 +124,25 @@ process.env.NODE_ENV !== "production" ? TreeView.propTypes = {
124
124
  * Used when the item's expansion is controlled.
125
125
  */
126
126
  expandedItems: _propTypes.default.arrayOf(_propTypes.default.string),
127
+ /**
128
+ * Unstable features, breaking changes might be introduced.
129
+ * For each feature, if the flag is not explicitly set to `true`,
130
+ * the feature will be fully disabled and any property / method call will not have any effect.
131
+ */
132
+ experimentalFeatures: _propTypes.default.shape({
133
+ indentationAtItemLevel: _propTypes.default.bool
134
+ }),
127
135
  /**
128
136
  * This prop is used to help implement the accessibility logic.
129
137
  * If you don't provide this prop. It falls back to a randomly generated id.
130
138
  */
131
139
  id: _propTypes.default.string,
140
+ /**
141
+ * Horizontal indentation between an item and its children.
142
+ * Examples: 24, "24px", "2rem", "2em".
143
+ * @default 12px
144
+ */
145
+ itemChildrenIndentation: _propTypes.default.oneOfType([_propTypes.default.number, _propTypes.default.string]),
132
146
  /**
133
147
  * If `true`, `ctrl` and `shift` will trigger multiselect.
134
148
  * @default false
package/node/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-tree-view v7.5.1
2
+ * @mui/x-tree-view v7.6.1
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.TreeViewItemDepthContext = void 0;
7
+ var React = _interopRequireWildcard(require("react"));
8
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
9
+ function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
10
+ const TreeViewItemDepthContext = exports.TreeViewItemDepthContext = /*#__PURE__*/React.createContext(() => -1);
11
+ if (process.env.NODE_ENV !== 'production') {
12
+ TreeViewItemDepthContext.displayName = 'TreeViewItemDepthContext';
13
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "TreeViewItemDepthContext", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _TreeViewItemDepthContext.TreeViewItemDepthContext;
10
+ }
11
+ });
12
+ var _TreeViewItemDepthContext = require("./TreeViewItemDepthContext");
@@ -12,19 +12,17 @@ var _ownerDocument = _interopRequireDefault(require("@mui/utils/ownerDocument"))
12
12
  var _useInstanceEventHandler = require("../../hooks/useInstanceEventHandler");
13
13
  var _utils = require("../../utils/utils");
14
14
  var _tree = require("../../utils/tree");
15
+ var _useTreeViewSelection = require("../useTreeViewSelection/useTreeViewSelection.utils");
15
16
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
16
17
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
17
- const useTabbableItemId = (instance, selectedItems) => {
18
- const isItemVisible = itemId => {
18
+ const useDefaultFocusableItemId = (instance, selectedItems) => {
19
+ let tabbableItemId = (0, _useTreeViewSelection.convertSelectedItemsToArray)(selectedItems).find(itemId => {
20
+ if (!instance.isItemNavigable(itemId)) {
21
+ return false;
22
+ }
19
23
  const itemMeta = instance.getItemMeta(itemId);
20
24
  return itemMeta && (itemMeta.parentId == null || instance.isItemExpanded(itemMeta.parentId));
21
- };
22
- let tabbableItemId;
23
- if (Array.isArray(selectedItems)) {
24
- tabbableItemId = selectedItems.find(isItemVisible);
25
- } else if (selectedItems != null && isItemVisible(selectedItems)) {
26
- tabbableItemId = selectedItems;
27
- }
25
+ });
28
26
  if (tabbableItemId == null) {
29
27
  tabbableItemId = (0, _tree.getFirstNavigableItem)(instance);
30
28
  }
@@ -38,7 +36,7 @@ const useTreeViewFocus = ({
38
36
  models,
39
37
  rootRef
40
38
  }) => {
41
- const tabbableItemId = useTabbableItemId(instance, models.selectedItems.value);
39
+ const defaultFocusableItemId = useDefaultFocusableItemId(instance, models.selectedItems.value);
42
40
  const setFocusedItemId = (0, _useEventCallback.default)(itemId => {
43
41
  const cleanItemId = typeof itemId === 'function' ? itemId(state.focusedItemId) : itemId;
44
42
  if (state.focusedItemId !== cleanItemId) {
@@ -70,18 +68,6 @@ const useTreeViewFocus = ({
70
68
  innerFocusItem(event, itemId);
71
69
  }
72
70
  });
73
- const focusDefaultItem = (0, _useEventCallback.default)(event => {
74
- let itemToFocusId;
75
- if (Array.isArray(models.selectedItems.value)) {
76
- itemToFocusId = models.selectedItems.value.find(isItemVisible);
77
- } else if (models.selectedItems.value != null && isItemVisible(models.selectedItems.value)) {
78
- itemToFocusId = models.selectedItems.value;
79
- }
80
- if (itemToFocusId == null) {
81
- itemToFocusId = (0, _tree.getFirstNavigableItem)(instance);
82
- }
83
- innerFocusItem(event, itemToFocusId);
84
- });
85
71
  const removeFocusedItem = (0, _useEventCallback.default)(() => {
86
72
  if (state.focusedItemId == null) {
87
73
  return;
@@ -95,12 +81,12 @@ const useTreeViewFocus = ({
95
81
  }
96
82
  setFocusedItemId(null);
97
83
  });
98
- const canItemBeTabbed = itemId => itemId === tabbableItemId;
84
+ const canItemBeTabbed = itemId => itemId === defaultFocusableItemId;
99
85
  (0, _useInstanceEventHandler.useInstanceEventHandler)(instance, 'removeItem', ({
100
86
  id
101
87
  }) => {
102
88
  if (state.focusedItemId === id) {
103
- instance.focusDefaultItem(null);
89
+ innerFocusItem(null, defaultFocusableItemId);
104
90
  }
105
91
  });
106
92
  const createRootHandleFocus = otherHandlers => event => {
@@ -111,7 +97,7 @@ const useTreeViewFocus = ({
111
97
 
112
98
  // if the event bubbled (which is React specific) we don't want to steal focus
113
99
  if (event.target === event.currentTarget) {
114
- instance.focusDefaultItem(event);
100
+ innerFocusItem(event, defaultFocusableItemId);
115
101
  }
116
102
  };
117
103
  return {
@@ -125,7 +111,6 @@ const useTreeViewFocus = ({
125
111
  isItemFocused,
126
112
  canItemBeTabbed,
127
113
  focusItem,
128
- focusDefaultItem,
129
114
  removeFocusedItem
130
115
  }
131
116
  };