@mui/x-tree-view 7.12.1 → 7.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/CHANGELOG.md +162 -1
  2. package/RichTreeView/RichTreeView.js +20 -2
  3. package/RichTreeView/RichTreeView.plugins.d.ts +3 -2
  4. package/RichTreeView/RichTreeView.plugins.js +2 -1
  5. package/TreeItem/TreeItem.js +24 -0
  6. package/TreeItem/TreeItemContent.d.ts +8 -0
  7. package/TreeItem/TreeItemContent.js +48 -8
  8. package/TreeItem/treeItemClasses.d.ts +6 -0
  9. package/TreeItem/treeItemClasses.js +1 -1
  10. package/TreeItem/useTreeItemState.d.ts +6 -0
  11. package/TreeItem/useTreeItemState.js +46 -1
  12. package/TreeItem2/TreeItem2.d.ts +3 -1
  13. package/TreeItem2/TreeItem2.js +29 -5
  14. package/TreeItem2/TreeItem2.types.d.ts +6 -0
  15. package/TreeItem2DragAndDropOverlay/TreeItem2DragAndDropOverlay.js +9 -9
  16. package/TreeItem2Icon/TreeItem2Icon.js +2 -0
  17. package/TreeItem2LabelInput/TreeItem2LabelInput.d.ts +2 -0
  18. package/TreeItem2LabelInput/TreeItem2LabelInput.js +20 -0
  19. package/TreeItem2LabelInput/TreeItem2LabelInput.types.d.ts +8 -0
  20. package/TreeItem2LabelInput/TreeItem2LabelInput.types.js +1 -0
  21. package/TreeItem2LabelInput/index.d.ts +2 -0
  22. package/TreeItem2LabelInput/index.js +1 -0
  23. package/TreeItem2LabelInput/package.json +6 -0
  24. package/hooks/useTreeItem2Utils/useTreeItem2Utils.d.ts +5 -1
  25. package/hooks/useTreeItem2Utils/useTreeItem2Utils.js +45 -2
  26. package/hooks/useTreeViewApiRef.d.ts +1 -1
  27. package/index.js +1 -1
  28. package/internals/index.d.ts +2 -0
  29. package/internals/index.js +1 -0
  30. package/internals/models/itemPlugin.d.ts +2 -1
  31. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +4 -1
  32. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +2 -0
  33. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +5 -1
  34. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +2 -0
  35. package/internals/plugins/useTreeViewLabel/index.d.ts +2 -0
  36. package/internals/plugins/useTreeViewLabel/index.js +1 -0
  37. package/internals/plugins/useTreeViewLabel/useTreeViewLabel.d.ts +3 -0
  38. package/internals/plugins/useTreeViewLabel/useTreeViewLabel.itemPlugin.d.ts +3 -0
  39. package/internals/plugins/useTreeViewLabel/useTreeViewLabel.itemPlugin.js +44 -0
  40. package/internals/plugins/useTreeViewLabel/useTreeViewLabel.js +81 -0
  41. package/internals/plugins/useTreeViewLabel/useTreeViewLabel.types.d.ts +75 -0
  42. package/internals/plugins/useTreeViewLabel/useTreeViewLabel.types.js +1 -0
  43. package/modern/RichTreeView/RichTreeView.js +20 -2
  44. package/modern/RichTreeView/RichTreeView.plugins.js +2 -1
  45. package/modern/TreeItem/TreeItem.js +24 -0
  46. package/modern/TreeItem/TreeItemContent.js +48 -8
  47. package/modern/TreeItem/treeItemClasses.js +1 -1
  48. package/modern/TreeItem/useTreeItemState.js +46 -1
  49. package/modern/TreeItem2/TreeItem2.js +29 -5
  50. package/modern/TreeItem2DragAndDropOverlay/TreeItem2DragAndDropOverlay.js +9 -9
  51. package/modern/TreeItem2Icon/TreeItem2Icon.js +2 -0
  52. package/modern/TreeItem2LabelInput/TreeItem2LabelInput.js +20 -0
  53. package/modern/TreeItem2LabelInput/TreeItem2LabelInput.types.js +1 -0
  54. package/modern/TreeItem2LabelInput/index.js +1 -0
  55. package/modern/hooks/useTreeItem2Utils/useTreeItem2Utils.js +45 -2
  56. package/modern/index.js +1 -1
  57. package/modern/internals/index.js +1 -0
  58. package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +4 -1
  59. package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +5 -1
  60. package/modern/internals/plugins/useTreeViewLabel/index.js +1 -0
  61. package/modern/internals/plugins/useTreeViewLabel/useTreeViewLabel.itemPlugin.js +44 -0
  62. package/modern/internals/plugins/useTreeViewLabel/useTreeViewLabel.js +81 -0
  63. package/modern/internals/plugins/useTreeViewLabel/useTreeViewLabel.types.js +1 -0
  64. package/modern/useTreeItem2/useTreeItem2.js +65 -4
  65. package/node/RichTreeView/RichTreeView.js +20 -2
  66. package/node/RichTreeView/RichTreeView.plugins.js +2 -1
  67. package/node/TreeItem/TreeItem.js +24 -0
  68. package/node/TreeItem/TreeItemContent.js +48 -8
  69. package/node/TreeItem/treeItemClasses.js +1 -1
  70. package/node/TreeItem/useTreeItemState.js +46 -1
  71. package/node/TreeItem2/TreeItem2.js +29 -5
  72. package/node/TreeItem2DragAndDropOverlay/TreeItem2DragAndDropOverlay.js +9 -9
  73. package/node/TreeItem2Icon/TreeItem2Icon.js +2 -0
  74. package/node/TreeItem2LabelInput/TreeItem2LabelInput.js +26 -0
  75. package/node/TreeItem2LabelInput/TreeItem2LabelInput.types.js +5 -0
  76. package/node/TreeItem2LabelInput/index.js +12 -0
  77. package/node/hooks/useTreeItem2Utils/useTreeItem2Utils.js +45 -2
  78. package/node/index.js +1 -1
  79. package/node/internals/index.js +7 -0
  80. package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +4 -1
  81. package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +5 -1
  82. package/node/internals/plugins/useTreeViewLabel/index.js +12 -0
  83. package/node/internals/plugins/useTreeViewLabel/useTreeViewLabel.itemPlugin.js +54 -0
  84. package/node/internals/plugins/useTreeViewLabel/useTreeViewLabel.js +91 -0
  85. package/node/internals/plugins/useTreeViewLabel/useTreeViewLabel.types.js +5 -0
  86. package/node/useTreeItem2/useTreeItem2.js +65 -4
  87. package/package.json +5 -5
  88. package/useTreeItem2/index.d.ts +1 -1
  89. package/useTreeItem2/useTreeItem2.js +65 -4
  90. package/useTreeItem2/useTreeItem2.types.d.ts +35 -15
@@ -23,6 +23,7 @@ var _TreeItem = require("../TreeItem");
23
23
  var _TreeItem2Icon = require("../TreeItem2Icon");
24
24
  var _TreeItem2DragAndDropOverlay = require("../TreeItem2DragAndDropOverlay");
25
25
  var _TreeItem2Provider = require("../TreeItem2Provider");
26
+ var _TreeItem2LabelInput = require("../TreeItem2LabelInput");
26
27
  var _jsxRuntime = require("react/jsx-runtime");
27
28
  const _excluded = ["visible"],
28
29
  _excluded2 = ["id", "itemId", "label", "disabled", "children", "slots", "slotProps"];
@@ -113,7 +114,8 @@ const TreeItem2Content = exports.TreeItem2Content = (0, _zeroStyled.styled)('div
113
114
  const TreeItem2Label = exports.TreeItem2Label = (0, _zeroStyled.styled)('div', {
114
115
  name: 'MuiTreeItem2',
115
116
  slot: 'Label',
116
- overridesResolver: (props, styles) => styles.label
117
+ overridesResolver: (props, styles) => styles.label,
118
+ shouldForwardProp: prop => (0, _createStyled.shouldForwardProp)(prop) && prop !== 'editable'
117
119
  })(({
118
120
  theme
119
121
  }) => (0, _extends2.default)({
@@ -122,8 +124,18 @@ const TreeItem2Label = exports.TreeItem2Label = (0, _zeroStyled.styled)('div', {
122
124
  // prevent width + padding to overflow
123
125
  // fixes overflow - see https://github.com/mui/material-ui/issues/27372
124
126
  minWidth: 0,
125
- position: 'relative'
126
- }, theme.typography.body1));
127
+ position: 'relative',
128
+ overflow: 'hidden'
129
+ }, theme.typography.body1, {
130
+ variants: [{
131
+ props: ({
132
+ editable
133
+ }) => editable,
134
+ style: {
135
+ paddingLeft: '2px'
136
+ }
137
+ }]
138
+ }));
127
139
  const TreeItem2IconContainer = exports.TreeItem2IconContainer = (0, _zeroStyled.styled)('div', {
128
140
  name: 'MuiTreeItem2',
129
141
  slot: 'IconContainer',
@@ -181,6 +193,8 @@ const useUtilityClasses = ownerState => {
181
193
  root: ['root'],
182
194
  content: ['content'],
183
195
  expanded: ['expanded'],
196
+ editing: ['editing'],
197
+ editable: ['editable'],
184
198
  selected: ['selected'],
185
199
  focused: ['focused'],
186
200
  disabled: ['disabled'],
@@ -188,6 +202,7 @@ const useUtilityClasses = ownerState => {
188
202
  checkbox: ['checkbox'],
189
203
  label: ['label'],
190
204
  groupTransition: ['groupTransition'],
205
+ labelInput: ['labelInput'],
191
206
  dragAndDropOverlay: ['dragAndDropOverlay']
192
207
  };
193
208
  return (0, _composeClasses.default)(slots, _TreeItem.getTreeItemUtilityClass, classes);
@@ -224,6 +239,7 @@ const TreeItem2 = exports.TreeItem2 = /*#__PURE__*/React.forwardRef(function Tre
224
239
  getCheckboxProps,
225
240
  getLabelProps,
226
241
  getGroupTransitionProps,
242
+ getLabelInputProps,
227
243
  getDragAndDropOverlayProps,
228
244
  status
229
245
  } = (0, _useTreeItem.unstable_useTreeItem2)({
@@ -253,7 +269,7 @@ const TreeItem2 = exports.TreeItem2 = /*#__PURE__*/React.forwardRef(function Tre
253
269
  getSlotProps: getContentProps,
254
270
  externalSlotProps: slotProps.content,
255
271
  ownerState: {},
256
- className: (0, _clsx.default)(classes.content, status.expanded && classes.expanded, status.selected && classes.selected, status.focused && classes.focused, status.disabled && classes.disabled)
272
+ className: (0, _clsx.default)(classes.content, status.expanded && classes.expanded, status.selected && classes.selected, status.focused && classes.focused, status.disabled && classes.disabled, status.editing && classes.editing, status.editable && classes.editable)
257
273
  });
258
274
  const IconContainer = slots.iconContainer ?? TreeItem2IconContainer;
259
275
  const iconContainerProps = (0, _useSlotProps.default)({
@@ -287,6 +303,14 @@ const TreeItem2 = exports.TreeItem2 = /*#__PURE__*/React.forwardRef(function Tre
287
303
  ownerState: {},
288
304
  className: classes.groupTransition
289
305
  });
306
+ const LabelInput = slots.labelInput ?? _TreeItem2LabelInput.TreeItem2LabelInput;
307
+ const labelInputProps = (0, _useSlotProps.default)({
308
+ elementType: LabelInput,
309
+ getSlotProps: getLabelInputProps,
310
+ externalSlotProps: slotProps.labelInput,
311
+ ownerState: {},
312
+ className: classes.labelInput
313
+ });
290
314
  const DragAndDropOverlay = slots.dragAndDropOverlay ?? _TreeItem2DragAndDropOverlay.TreeItem2DragAndDropOverlay;
291
315
  const dragAndDropOverlayProps = (0, _useSlotProps.default)({
292
316
  elementType: DragAndDropOverlay,
@@ -305,7 +329,7 @@ const TreeItem2 = exports.TreeItem2 = /*#__PURE__*/React.forwardRef(function Tre
305
329
  slots: slots,
306
330
  slotProps: slotProps
307
331
  })
308
- })), /*#__PURE__*/(0, _jsxRuntime.jsx)(Checkbox, (0, _extends2.default)({}, checkboxProps)), /*#__PURE__*/(0, _jsxRuntime.jsx)(Label, (0, _extends2.default)({}, labelProps)), /*#__PURE__*/(0, _jsxRuntime.jsx)(DragAndDropOverlay, (0, _extends2.default)({}, dragAndDropOverlayProps))]
332
+ })), /*#__PURE__*/(0, _jsxRuntime.jsx)(Checkbox, (0, _extends2.default)({}, checkboxProps)), status.editing ? /*#__PURE__*/(0, _jsxRuntime.jsx)(LabelInput, (0, _extends2.default)({}, labelInputProps)) : /*#__PURE__*/(0, _jsxRuntime.jsx)(Label, (0, _extends2.default)({}, labelProps)), /*#__PURE__*/(0, _jsxRuntime.jsx)(DragAndDropOverlay, (0, _extends2.default)({}, dragAndDropOverlayProps))]
309
333
  })), children && /*#__PURE__*/(0, _jsxRuntime.jsx)(TreeItem2GroupTransition, (0, _extends2.default)({
310
334
  as: GroupTransition
311
335
  }, groupTransitionProps))]
@@ -44,9 +44,9 @@ const TreeItem2DragAndDropOverlayRoot = (0, _zeroStyled.styled)('div', {
44
44
  style: (0, _extends2.default)({
45
45
  marginLeft: 'calc(var(--TreeView-indentMultiplier) * var(--TreeView-itemDepth))',
46
46
  borderTop: `1px solid ${(0, _styles.alpha)((theme.vars || theme).palette.grey[900], 0.6)}`
47
- }, theme.palette.mode === 'dark' && {
48
- borderTop: `1px solid ${(0, _styles.alpha)((theme.vars || theme).palette.grey[100], 0.6)}`
49
- })
47
+ }, theme.applyStyles('dark', {
48
+ borderTopColor: (0, _styles.alpha)((theme.vars || theme).palette.grey[100], 0.6)
49
+ }))
50
50
  }, {
51
51
  props: {
52
52
  action: 'reorder-below'
@@ -54,9 +54,9 @@ const TreeItem2DragAndDropOverlayRoot = (0, _zeroStyled.styled)('div', {
54
54
  style: (0, _extends2.default)({
55
55
  marginLeft: 'calc(var(--TreeView-indentMultiplier) * var(--TreeView-itemDepth))',
56
56
  borderBottom: `1px solid ${(0, _styles.alpha)((theme.vars || theme).palette.grey[900], 0.6)}`
57
- }, theme.palette.mode === 'dark' && {
58
- borderBottom: `1px solid ${(0, _styles.alpha)((theme.vars || theme).palette.grey[100], 0.6)}`
59
- })
57
+ }, theme.applyStyles('dark', {
58
+ borderBottomColor: (0, _styles.alpha)((theme.vars || theme).palette.grey[100], 0.6)
59
+ }))
60
60
  }, {
61
61
  props: {
62
62
  action: 'move-to-parent'
@@ -64,9 +64,9 @@ const TreeItem2DragAndDropOverlayRoot = (0, _zeroStyled.styled)('div', {
64
64
  style: (0, _extends2.default)({
65
65
  marginLeft: 'calc(var(--TreeView-indentMultiplier) * calc(var(--TreeView-itemDepth) - 1))',
66
66
  borderBottom: `1px solid ${(0, _styles.alpha)((theme.vars || theme).palette.grey[900], 0.6)}`
67
- }, theme.palette.mode === 'dark' && {
68
- borderBottom: `1px solid ${(0, _styles.alpha)((theme.vars || theme).palette.grey[900], 0.6)}`
69
- })
67
+ }, theme.applyStyles('dark', {
68
+ borderBottomColor: (0, _styles.alpha)((theme.vars || theme).palette.grey[900], 0.6)
69
+ }))
70
70
  }]
71
71
  }));
72
72
  function TreeItem2DragAndDropOverlay(props) {
@@ -68,6 +68,8 @@ process.env.NODE_ENV !== "production" ? TreeItem2Icon.propTypes = {
68
68
  slots: _propTypes.default.object,
69
69
  status: _propTypes.default.shape({
70
70
  disabled: _propTypes.default.bool.isRequired,
71
+ editable: _propTypes.default.bool.isRequired,
72
+ editing: _propTypes.default.bool.isRequired,
71
73
  expandable: _propTypes.default.bool.isRequired,
72
74
  expanded: _propTypes.default.bool.isRequired,
73
75
  focused: _propTypes.default.bool.isRequired,
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.TreeItem2LabelInput = void 0;
8
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
9
+ var _zeroStyled = require("../internals/zero-styled");
10
+ const TreeItem2LabelInput = exports.TreeItem2LabelInput = (0, _zeroStyled.styled)('input', {
11
+ name: 'MuiTreeItem2',
12
+ slot: 'LabelInput',
13
+ overridesResolver: (props, styles) => styles.labelInput
14
+ })(({
15
+ theme
16
+ }) => (0, _extends2.default)({}, theme.typography.body1, {
17
+ width: '100%',
18
+ backgroundColor: theme.palette.background.paper,
19
+ borderRadius: theme.shape.borderRadius,
20
+ border: 'none',
21
+ padding: '0 2px',
22
+ boxSizing: 'border-box',
23
+ '&:focus': {
24
+ outline: `1px solid ${theme.palette.primary.main}`
25
+ }
26
+ }));
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "TreeItem2LabelInput", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _TreeItem2LabelInput.TreeItem2LabelInput;
10
+ }
11
+ });
12
+ var _TreeItem2LabelInput = require("./TreeItem2LabelInput");
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.useTreeItem2Utils = void 0;
7
7
  var _TreeViewProvider = require("../../internals/TreeViewProvider");
8
+ var _useTreeViewLabel = require("../../internals/plugins/useTreeViewLabel");
9
+ var _plugins = require("../../internals/utils/plugins");
8
10
  const isItemExpandable = reactChildren => {
9
11
  if (Array.isArray(reactChildren)) {
10
12
  return reactChildren.length > 0 && reactChildren.some(isItemExpandable);
@@ -35,7 +37,9 @@ const useTreeItem2Utils = ({
35
37
  expanded: instance.isItemExpanded(itemId),
36
38
  focused: instance.isItemFocused(itemId),
37
39
  selected: instance.isItemSelected(itemId),
38
- disabled: instance.isItemDisabled(itemId)
40
+ disabled: instance.isItemDisabled(itemId),
41
+ editing: instance?.isItemBeingEdited ? instance?.isItemBeingEdited(itemId) : false,
42
+ editable: instance.isItemEditable ? instance.isItemEditable(itemId) : false
39
43
  };
40
44
  const handleExpansion = event => {
41
45
  if (status.disabled) {
@@ -90,10 +94,49 @@ const useTreeItem2Utils = ({
90
94
  });
91
95
  }
92
96
  };
97
+ const toggleItemEditing = () => {
98
+ if (!(0, _plugins.hasPlugin)(instance, _useTreeViewLabel.useTreeViewLabel)) {
99
+ return;
100
+ }
101
+ if (instance.isItemEditable(itemId)) {
102
+ if (instance.isItemBeingEdited(itemId)) {
103
+ instance.setEditedItemId(null);
104
+ } else {
105
+ instance.setEditedItemId(itemId);
106
+ }
107
+ }
108
+ };
109
+ const handleSaveItemLabel = (event, label) => {
110
+ if (!(0, _plugins.hasPlugin)(instance, _useTreeViewLabel.useTreeViewLabel)) {
111
+ return;
112
+ }
113
+
114
+ // As a side effect of `instance.focusItem` called here and in `handleCancelItemLabelEditing` the `labelInput` is blurred
115
+ // The `onBlur` event is triggered, which calls `handleSaveItemLabel` again.
116
+ // To avoid creating an unwanted behavior we need to check if the item is being edited before calling `updateItemLabel`
117
+ // using `instance.isItemBeingEditedRef` instead of `instance.isItemBeingEdited` since the state is not yet updated in this point
118
+ if (instance.isItemBeingEditedRef(itemId)) {
119
+ instance.updateItemLabel(itemId, label);
120
+ toggleItemEditing();
121
+ instance.focusItem(event, itemId);
122
+ }
123
+ };
124
+ const handleCancelItemLabelEditing = event => {
125
+ if (!(0, _plugins.hasPlugin)(instance, _useTreeViewLabel.useTreeViewLabel)) {
126
+ return;
127
+ }
128
+ if (instance.isItemBeingEditedRef(itemId)) {
129
+ toggleItemEditing();
130
+ instance.focusItem(event, itemId);
131
+ }
132
+ };
93
133
  const interactions = {
94
134
  handleExpansion,
95
135
  handleSelection,
96
- handleCheckboxSelection
136
+ handleCheckboxSelection,
137
+ toggleItemEditing,
138
+ handleSaveItemLabel,
139
+ handleCancelItemLabelEditing
97
140
  };
98
141
  return {
99
142
  interactions,
package/node/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-tree-view v7.12.1
2
+ * @mui/x-tree-view v7.14.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -81,6 +81,12 @@ Object.defineProperty(exports, "useTreeViewKeyboardNavigation", {
81
81
  return _useTreeViewKeyboardNavigation.useTreeViewKeyboardNavigation;
82
82
  }
83
83
  });
84
+ Object.defineProperty(exports, "useTreeViewLabel", {
85
+ enumerable: true,
86
+ get: function () {
87
+ return _useTreeViewLabel.useTreeViewLabel;
88
+ }
89
+ });
84
90
  Object.defineProperty(exports, "useTreeViewSelection", {
85
91
  enumerable: true,
86
92
  get: function () {
@@ -102,6 +108,7 @@ var _useTreeViewFocus = require("./plugins/useTreeViewFocus");
102
108
  var _useTreeViewKeyboardNavigation = require("./plugins/useTreeViewKeyboardNavigation");
103
109
  var _useTreeViewIcons = require("./plugins/useTreeViewIcons");
104
110
  var _useTreeViewItems = require("./plugins/useTreeViewItems");
111
+ var _useTreeViewLabel = require("./plugins/useTreeViewLabel");
105
112
  var _useTreeViewJSXItems = require("./plugins/useTreeViewJSXItems");
106
113
  var _tree = require("./utils/tree");
107
114
  var _warning = require("./utils/warning");
@@ -66,8 +66,11 @@ const useTreeViewExpansion = ({
66
66
  if (params.expansionTrigger) {
67
67
  return params.expansionTrigger;
68
68
  }
69
+ if (instance.isTreeViewEditable) {
70
+ return 'iconContainer';
71
+ }
69
72
  return 'content';
70
- }, [params.expansionTrigger]);
73
+ }, [params.expansionTrigger, instance.isTreeViewEditable]);
71
74
  return {
72
75
  publicAPI: {
73
76
  setItemExpansion
@@ -9,6 +9,8 @@ var React = _interopRequireWildcard(require("react"));
9
9
  var _RtlProvider = require("@mui/system/RtlProvider");
10
10
  var _useEventCallback = _interopRequireDefault(require("@mui/utils/useEventCallback"));
11
11
  var _tree = require("../../utils/tree");
12
+ var _plugins = require("../../utils/plugins");
13
+ var _useTreeViewLabel = require("../useTreeViewLabel");
12
14
  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); }
13
15
  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; }
14
16
  function isPrintableCharacter(string) {
@@ -98,7 +100,9 @@ const useTreeViewKeyboardNavigation = ({
98
100
  // If the focused item has no children, we select it.
99
101
  case key === 'Enter':
100
102
  {
101
- if (canToggleItemExpansion(itemId)) {
103
+ if ((0, _plugins.hasPlugin)(instance, _useTreeViewLabel.useTreeViewLabel) && instance.isItemEditable(itemId) && !instance.isItemBeingEdited(itemId)) {
104
+ instance.setEditedItemId(itemId);
105
+ } else if (canToggleItemExpansion(itemId)) {
102
106
  instance.toggleItemExpansion(event, itemId);
103
107
  event.preventDefault();
104
108
  } else if (canToggleItemSelection(itemId)) {
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "useTreeViewLabel", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _useTreeViewLabel.useTreeViewLabel;
10
+ }
11
+ });
12
+ var _useTreeViewLabel = require("./useTreeViewLabel");
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useTreeViewLabelItemPlugin = exports.isAndroid = void 0;
7
+ var React = _interopRequireWildcard(require("react"));
8
+ var _TreeViewProvider = require("../../TreeViewProvider");
9
+ 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); }
10
+ 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; }
11
+ const isAndroid = () => navigator.userAgent.toLowerCase().includes('android');
12
+ exports.isAndroid = isAndroid;
13
+ const useTreeViewLabelItemPlugin = ({
14
+ props
15
+ }) => {
16
+ const {
17
+ instance
18
+ } = (0, _TreeViewProvider.useTreeViewContext)();
19
+ const {
20
+ label,
21
+ itemId
22
+ } = props;
23
+ const [labelInputValue, setLabelInputValue] = React.useState(label);
24
+ const isItemBeingEdited = instance.isItemBeingEdited(itemId);
25
+ React.useEffect(() => {
26
+ if (!isItemBeingEdited) {
27
+ setLabelInputValue(label);
28
+ }
29
+ }, [isItemBeingEdited, label]);
30
+ return {
31
+ propsEnhancers: {
32
+ labelInput: ({
33
+ externalEventHandlers
34
+ }) => {
35
+ const editable = instance.isItemEditable(itemId);
36
+ if (!editable) {
37
+ return {};
38
+ }
39
+ const handleInputChange = event => {
40
+ externalEventHandlers.onChange?.(event);
41
+ setLabelInputValue(event.target.value);
42
+ };
43
+ return {
44
+ value: labelInputValue ?? '',
45
+ 'data-element': 'labelInput',
46
+ onChange: handleInputChange,
47
+ autoFocus: true,
48
+ type: 'text'
49
+ };
50
+ }
51
+ }
52
+ };
53
+ };
54
+ exports.useTreeViewLabelItemPlugin = useTreeViewLabelItemPlugin;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.useTreeViewLabel = void 0;
8
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
9
+ var React = _interopRequireWildcard(require("react"));
10
+ var _warning = require("../../utils/warning");
11
+ var _useTreeViewLabel = require("./useTreeViewLabel.itemPlugin");
12
+ function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
13
+ 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; }
14
+ const useTreeViewLabel = ({
15
+ instance,
16
+ state,
17
+ setState,
18
+ params,
19
+ experimentalFeatures
20
+ }) => {
21
+ if (process.env.NODE_ENV !== 'production') {
22
+ if (params.isItemEditable && !experimentalFeatures?.labelEditing) {
23
+ (0, _warning.warnOnce)(['MUI X: The label editing feature requires the `labelEditing` experimental feature to be enabled.', 'You can do it by passing `experimentalFeatures={{ labelEditing: true}}` to the `RichTreeViewPro` component.', 'Check the documentation for more details: https://mui.com/x/react-tree-view/rich-tree-view/editing/']);
24
+ }
25
+ }
26
+ const editedItemRef = React.useRef(state.editedItemId);
27
+ const isItemBeingEditedRef = itemId => editedItemRef.current === itemId;
28
+ const setEditedItemId = editedItemId => {
29
+ setState(prevState => (0, _extends2.default)({}, prevState, {
30
+ editedItemId
31
+ }));
32
+ editedItemRef.current = editedItemId;
33
+ };
34
+ const isItemBeingEdited = itemId => itemId === state.editedItemId;
35
+ const isTreeViewEditable = Boolean(params.isItemEditable) && !!experimentalFeatures.labelEditing;
36
+ const isItemEditable = itemId => {
37
+ if (itemId == null || !isTreeViewEditable) {
38
+ return false;
39
+ }
40
+ const item = instance.getItem(itemId);
41
+ if (!item) {
42
+ return false;
43
+ }
44
+ return typeof params.isItemEditable === 'function' ? params.isItemEditable(item) : Boolean(params.isItemEditable);
45
+ };
46
+ const updateItemLabel = (itemId, label) => {
47
+ if (!label) {
48
+ throw new Error(['MUI X: The Tree View component requires all items to have a `label` property.', 'The label of an item cannot be empty.', itemId].join('\n'));
49
+ }
50
+ setState(prevState => {
51
+ const item = prevState.items.itemMetaMap[itemId];
52
+ if (item.label !== label) {
53
+ return (0, _extends2.default)({}, prevState, {
54
+ items: (0, _extends2.default)({}, prevState.items, {
55
+ itemMetaMap: (0, _extends2.default)({}, prevState.items.itemMetaMap, {
56
+ [itemId]: (0, _extends2.default)({}, item, {
57
+ label
58
+ })
59
+ })
60
+ })
61
+ });
62
+ }
63
+ return prevState;
64
+ });
65
+ if (params.onItemLabelChange) {
66
+ params.onItemLabelChange(itemId, label);
67
+ }
68
+ };
69
+ return {
70
+ instance: {
71
+ setEditedItemId,
72
+ isItemBeingEdited,
73
+ updateItemLabel,
74
+ isItemEditable,
75
+ isTreeViewEditable,
76
+ isItemBeingEditedRef
77
+ },
78
+ publicAPI: {
79
+ updateItemLabel
80
+ }
81
+ };
82
+ };
83
+ exports.useTreeViewLabel = useTreeViewLabel;
84
+ useTreeViewLabel.itemPlugin = _useTreeViewLabel.useTreeViewLabelItemPlugin;
85
+ useTreeViewLabel.getInitialState = () => ({
86
+ editedItemId: null
87
+ });
88
+ useTreeViewLabel.params = {
89
+ onItemLabelChange: true,
90
+ isItemEditable: true
91
+ };
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
@@ -12,6 +12,7 @@ var _useForkRef = _interopRequireDefault(require("@mui/utils/useForkRef"));
12
12
  var _TreeViewProvider = require("../internals/TreeViewProvider");
13
13
  var _useTreeItem2Utils = require("../hooks/useTreeItem2Utils");
14
14
  var _TreeViewItemDepthContext = require("../internals/TreeViewItemDepthContext");
15
+ var _tree = require("../internals/utils/tree");
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
18
  const useTreeItem2 = parameters => {
@@ -59,6 +60,7 @@ const useTreeItem2 = parameters => {
59
60
  const handleRootRef = (0, _useForkRef.default)(rootRef, pluginRootRef, rootRefObject);
60
61
  const handleContentRef = (0, _useForkRef.default)(contentRef, contentRefObject);
61
62
  const checkboxRef = React.useRef(null);
63
+ const rootTabIndex = instance.canItemBeTabbed(itemId) ? 0 : -1;
62
64
  const createRootHandleFocus = otherHandlers => event => {
63
65
  otherHandlers.onFocus?.(event);
64
66
  if (event.defaultMuiPrevented) {
@@ -74,15 +76,33 @@ const useTreeItem2 = parameters => {
74
76
  if (event.defaultMuiPrevented) {
75
77
  return;
76
78
  }
79
+ const rootElement = instance.getItemDOMElement(itemId);
80
+
81
+ // Don't blur the root when switching to editing mode
82
+ // the input that triggers the root blur can be either the relatedTarget (when entering editing state) or the target (when exiting editing state)
83
+ // when we enter the editing state, we focus the input -> we don't want to remove the focused item from the state
84
+ if (status.editing ||
85
+ // we can exit the editing state by clicking outside the input (within the tree item) or by pressing Enter or Escape -> we don't want to remove the focused item from the state in these cases
86
+ // we can also exit the editing state by clicking on the root itself -> want to remove the focused item from the state in this case
87
+ event.relatedTarget && (0, _tree.isTargetInDescendants)(event.relatedTarget, rootElement) && (event.target && event.target?.dataset?.element === 'labelInput' && (0, _tree.isTargetInDescendants)(event.target, rootElement) || event.relatedTarget?.dataset?.element === 'labelInput')) {
88
+ return;
89
+ }
77
90
  instance.removeFocusedItem();
78
91
  };
79
92
  const createRootHandleKeyDown = otherHandlers => event => {
80
93
  otherHandlers.onKeyDown?.(event);
81
- if (event.defaultMuiPrevented) {
94
+ if (event.defaultMuiPrevented || event.target?.dataset?.element === 'labelInput') {
82
95
  return;
83
96
  }
84
97
  instance.handleItemKeyDown(event, itemId);
85
98
  };
99
+ const createLabelHandleDoubleClick = otherHandlers => event => {
100
+ otherHandlers.onDoubleClick?.(event);
101
+ if (event.defaultMuiPrevented) {
102
+ return;
103
+ }
104
+ interactions.toggleItemEditing();
105
+ };
86
106
  const createContentHandleClick = otherHandlers => event => {
87
107
  otherHandlers.onClick?.(event);
88
108
  onItemClick?.(event, itemId);
@@ -117,6 +137,27 @@ const useTreeItem2 = parameters => {
117
137
  }
118
138
  interactions.handleCheckboxSelection(event);
119
139
  };
140
+ const createInputHandleKeydown = otherHandlers => event => {
141
+ otherHandlers.onKeyDown?.(event);
142
+ if (event.defaultMuiPrevented) {
143
+ return;
144
+ }
145
+ const target = event.target;
146
+ if (event.key === 'Enter' && target.value) {
147
+ interactions.handleSaveItemLabel(event, target.value);
148
+ } else if (event.key === 'Escape') {
149
+ interactions.handleCancelItemLabelEditing(event);
150
+ }
151
+ };
152
+ const createInputHandleBlur = otherHandlers => event => {
153
+ otherHandlers.onBlur?.(event);
154
+ if (event.defaultMuiPrevented) {
155
+ return;
156
+ }
157
+ if (event.target.value) {
158
+ interactions.handleSaveItemLabel(event, event.target.value);
159
+ }
160
+ };
120
161
  const createIconContainerHandleClick = otherHandlers => event => {
121
162
  otherHandlers.onClick?.(event);
122
163
  if (event.defaultMuiPrevented) {
@@ -143,7 +184,7 @@ const useTreeItem2 = parameters => {
143
184
  const props = (0, _extends2.default)({}, externalEventHandlers, {
144
185
  ref: handleRootRef,
145
186
  role: 'treeitem',
146
- tabIndex: instance.canItemBeTabbed(itemId) ? 0 : -1,
187
+ tabIndex: rootTabIndex,
147
188
  id: idAttribute,
148
189
  'aria-expanded': status.expandable ? status.expanded : undefined,
149
190
  'aria-selected': ariaSelected,
@@ -197,9 +238,28 @@ const useTreeItem2 = parameters => {
197
238
  };
198
239
  const getLabelProps = (externalProps = {}) => {
199
240
  const externalEventHandlers = (0, _extends2.default)({}, (0, _extractEventHandlers.default)(externalProps));
200
- return (0, _extends2.default)({}, externalEventHandlers, {
241
+ const props = (0, _extends2.default)({}, externalEventHandlers, {
201
242
  children: label
202
- }, externalProps);
243
+ }, externalProps, {
244
+ onDoubleClick: createLabelHandleDoubleClick(externalEventHandlers)
245
+ });
246
+ if (instance.isTreeViewEditable) {
247
+ props.editable = status.editable;
248
+ }
249
+ return props;
250
+ };
251
+ const getLabelInputProps = (externalProps = {}) => {
252
+ const externalEventHandlers = (0, _extractEventHandlers.default)(externalProps);
253
+ const props = (0, _extends2.default)({}, externalEventHandlers, externalProps, {
254
+ onKeyDown: createInputHandleKeydown(externalEventHandlers),
255
+ onBlur: createInputHandleBlur(externalEventHandlers)
256
+ });
257
+ const enhancedlabelInputProps = propsEnhancers.labelInput?.({
258
+ rootRefObject,
259
+ contentRefObject,
260
+ externalEventHandlers
261
+ }) ?? {};
262
+ return (0, _extends2.default)({}, props, enhancedlabelInputProps);
203
263
  };
204
264
  const getIconContainerProps = (externalProps = {}) => {
205
265
  const externalEventHandlers = (0, _extractEventHandlers.default)(externalProps);
@@ -237,6 +297,7 @@ const useTreeItem2 = parameters => {
237
297
  getIconContainerProps,
238
298
  getCheckboxProps,
239
299
  getLabelProps,
300
+ getLabelInputProps,
240
301
  getDragAndDropOverlayProps,
241
302
  rootRef: handleRootRef,
242
303
  status,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/x-tree-view",
3
- "version": "7.12.1",
3
+ "version": "7.14.0",
4
4
  "description": "The community edition of the Tree View components (MUI X).",
5
5
  "author": "MUI Team",
6
6
  "main": "./node/index.js",
@@ -34,13 +34,13 @@
34
34
  },
35
35
  "dependencies": {
36
36
  "@babel/runtime": "^7.25.0",
37
- "@mui/system": "^5.16.5",
38
- "@mui/utils": "^5.16.5",
39
- "@types/react-transition-group": "^4.4.10",
37
+ "@mui/system": "^5.16.7",
38
+ "@mui/utils": "^5.16.6",
39
+ "@types/react-transition-group": "^4.4.11",
40
40
  "clsx": "^2.1.1",
41
41
  "prop-types": "^15.8.1",
42
42
  "react-transition-group": "^4.4.5",
43
- "@mui/x-internals": "7.12.0"
43
+ "@mui/x-internals": "7.14.0"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@emotion/react": "^11.9.0",
@@ -1,2 +1,2 @@
1
1
  export { useTreeItem2 as unstable_useTreeItem2 } from './useTreeItem2';
2
- export type { UseTreeItem2Parameters, UseTreeItem2ReturnValue, UseTreeItem2Status, UseTreeItem2RootSlotOwnProps, UseTreeItem2ContentSlotOwnProps, UseTreeItem2LabelSlotOwnProps, UseTreeItem2IconContainerSlotOwnProps, UseTreeItem2GroupTransitionSlotOwnProps, UseTreeItem2DragAndDropOverlaySlotOwnProps, } from './useTreeItem2.types';
2
+ export type { UseTreeItem2Parameters, UseTreeItem2ReturnValue, UseTreeItem2Status, UseTreeItem2RootSlotOwnProps, UseTreeItem2ContentSlotOwnProps, UseTreeItem2LabelInputSlotOwnProps, UseTreeItem2LabelSlotOwnProps, UseTreeItem2IconContainerSlotOwnProps, UseTreeItem2GroupTransitionSlotOwnProps, UseTreeItem2DragAndDropOverlaySlotOwnProps, } from './useTreeItem2.types';