@mui/x-tree-view 7.8.0 → 7.9.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 (36) hide show
  1. package/CHANGELOG.md +66 -0
  2. package/RichTreeView/RichTreeView.js +7 -5
  3. package/SimpleTreeView/SimpleTreeView.js +7 -5
  4. package/TreeItem/useTreeItemState.js +16 -3
  5. package/TreeView/TreeView.js +7 -5
  6. package/hooks/useTreeItem2Utils/useTreeItem2Utils.js +16 -3
  7. package/index.js +1 -1
  8. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +7 -7
  9. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +1 -2
  10. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +2 -2
  11. package/internals/plugins/useTreeViewItems/useTreeViewItems.js +10 -1
  12. package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +7 -1
  13. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +15 -5
  14. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +12 -4
  15. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +25 -16
  16. package/modern/RichTreeView/RichTreeView.js +7 -5
  17. package/modern/SimpleTreeView/SimpleTreeView.js +7 -5
  18. package/modern/TreeItem/useTreeItemState.js +16 -3
  19. package/modern/TreeView/TreeView.js +7 -5
  20. package/modern/hooks/useTreeItem2Utils/useTreeItem2Utils.js +16 -3
  21. package/modern/index.js +1 -1
  22. package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +1 -2
  23. package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.js +10 -1
  24. package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +15 -5
  25. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +12 -4
  26. package/node/RichTreeView/RichTreeView.js +7 -5
  27. package/node/SimpleTreeView/SimpleTreeView.js +7 -5
  28. package/node/TreeItem/useTreeItemState.js +16 -3
  29. package/node/TreeView/TreeView.js +7 -5
  30. package/node/hooks/useTreeItem2Utils/useTreeItem2Utils.js +16 -3
  31. package/node/index.js +1 -1
  32. package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +1 -2
  33. package/node/internals/plugins/useTreeViewItems/useTreeViewItems.js +10 -1
  34. package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +15 -5
  35. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +12 -4
  36. package/package.json +3 -3
@@ -95,6 +95,8 @@ process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
95
95
  current: PropTypes.shape({
96
96
  focusItem: PropTypes.func.isRequired,
97
97
  getItem: PropTypes.func.isRequired,
98
+ getItemDOMElement: PropTypes.func.isRequired,
99
+ selectItem: PropTypes.func.isRequired,
98
100
  setItemExpansion: PropTypes.func.isRequired
99
101
  })
100
102
  }),
@@ -170,34 +172,34 @@ process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
170
172
  multiSelect: PropTypes.bool,
171
173
  /**
172
174
  * Callback fired when tree items are expanded/collapsed.
173
- * @param {React.SyntheticEvent} event The event source of the callback.
175
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
174
176
  * @param {array} itemIds The ids of the expanded items.
175
177
  */
176
178
  onExpandedItemsChange: PropTypes.func,
177
179
  /**
178
180
  * Callback fired when a tree item is expanded or collapsed.
179
- * @param {React.SyntheticEvent} event The event source of the callback.
181
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
180
182
  * @param {array} itemId The itemId of the modified item.
181
183
  * @param {array} isExpanded `true` if the item has just been expanded, `false` if it has just been collapsed.
182
184
  */
183
185
  onItemExpansionToggle: PropTypes.func,
184
186
  /**
185
187
  * Callback fired when tree items are focused.
186
- * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event.
188
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change. **Warning**: This is a generic event not a focus event.
187
189
  * @param {string} itemId The id of the focused item.
188
190
  * @param {string} value of the focused item.
189
191
  */
190
192
  onItemFocus: PropTypes.func,
191
193
  /**
192
194
  * Callback fired when a tree item is selected or deselected.
193
- * @param {React.SyntheticEvent} event The event source of the callback.
195
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
194
196
  * @param {array} itemId The itemId of the modified item.
195
197
  * @param {array} isSelected `true` if the item has just been selected, `false` if it has just been deselected.
196
198
  */
197
199
  onItemSelectionToggle: PropTypes.func,
198
200
  /**
199
201
  * Callback fired when tree items are selected/deselected.
200
- * @param {React.SyntheticEvent} event The event source of the callback
202
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
201
203
  * @param {string[] | string} itemIds The ids of the selected items.
202
204
  * When `multiSelect` is `true`, this is an array of strings; when false (default) a string.
203
205
  */
@@ -39,10 +39,18 @@ export function useTreeItemState(itemId) {
39
39
  if (event.shiftKey) {
40
40
  instance.expandSelectionRange(event, itemId);
41
41
  } else {
42
- instance.selectItem(event, itemId, true);
42
+ instance.selectItem({
43
+ event,
44
+ itemId,
45
+ keepExistingSelection: true
46
+ });
43
47
  }
44
48
  } else {
45
- instance.selectItem(event, itemId, false);
49
+ instance.selectItem({
50
+ event,
51
+ itemId,
52
+ shouldBeSelected: true
53
+ });
46
54
  }
47
55
  }
48
56
  };
@@ -54,7 +62,12 @@ export function useTreeItemState(itemId) {
54
62
  if (multiSelect && hasShift) {
55
63
  instance.expandSelectionRange(event, itemId);
56
64
  } else {
57
- instance.selectItem(event, itemId, multiSelect, event.target.checked);
65
+ instance.selectItem({
66
+ event,
67
+ itemId,
68
+ keepExistingSelection: multiSelect,
69
+ shouldBeSelected: event.target.checked
70
+ });
58
71
  }
59
72
  };
60
73
  const preventSelection = event => {
@@ -72,6 +72,8 @@ process.env.NODE_ENV !== "production" ? TreeView.propTypes = {
72
72
  current: PropTypes.shape({
73
73
  focusItem: PropTypes.func.isRequired,
74
74
  getItem: PropTypes.func.isRequired,
75
+ getItemDOMElement: PropTypes.func.isRequired,
76
+ selectItem: PropTypes.func.isRequired,
75
77
  setItemExpansion: PropTypes.func.isRequired
76
78
  })
77
79
  }),
@@ -147,34 +149,34 @@ process.env.NODE_ENV !== "production" ? TreeView.propTypes = {
147
149
  multiSelect: PropTypes.bool,
148
150
  /**
149
151
  * Callback fired when tree items are expanded/collapsed.
150
- * @param {React.SyntheticEvent} event The event source of the callback.
152
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
151
153
  * @param {array} itemIds The ids of the expanded items.
152
154
  */
153
155
  onExpandedItemsChange: PropTypes.func,
154
156
  /**
155
157
  * Callback fired when a tree item is expanded or collapsed.
156
- * @param {React.SyntheticEvent} event The event source of the callback.
158
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
157
159
  * @param {array} itemId The itemId of the modified item.
158
160
  * @param {array} isExpanded `true` if the item has just been expanded, `false` if it has just been collapsed.
159
161
  */
160
162
  onItemExpansionToggle: PropTypes.func,
161
163
  /**
162
164
  * Callback fired when tree items are focused.
163
- * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event.
165
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change. **Warning**: This is a generic event not a focus event.
164
166
  * @param {string} itemId The id of the focused item.
165
167
  * @param {string} value of the focused item.
166
168
  */
167
169
  onItemFocus: PropTypes.func,
168
170
  /**
169
171
  * Callback fired when a tree item is selected or deselected.
170
- * @param {React.SyntheticEvent} event The event source of the callback.
172
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
171
173
  * @param {array} itemId The itemId of the modified item.
172
174
  * @param {array} isSelected `true` if the item has just been selected, `false` if it has just been deselected.
173
175
  */
174
176
  onItemSelectionToggle: PropTypes.func,
175
177
  /**
176
178
  * Callback fired when tree items are selected/deselected.
177
- * @param {React.SyntheticEvent} event The event source of the callback
179
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
178
180
  * @param {string[] | string} itemIds The ids of the selected items.
179
181
  * When `multiSelect` is `true`, this is an array of strings; when false (default) a string.
180
182
  */
@@ -57,10 +57,18 @@ export const useTreeItem2Utils = ({
57
57
  if (event.shiftKey) {
58
58
  instance.expandSelectionRange(event, itemId);
59
59
  } else {
60
- instance.selectItem(event, itemId, true);
60
+ instance.selectItem({
61
+ event,
62
+ itemId,
63
+ keepExistingSelection: true
64
+ });
61
65
  }
62
66
  } else {
63
- instance.selectItem(event, itemId, false);
67
+ instance.selectItem({
68
+ event,
69
+ itemId,
70
+ shouldBeSelected: true
71
+ });
64
72
  }
65
73
  };
66
74
  const handleCheckboxSelection = event => {
@@ -68,7 +76,12 @@ export const useTreeItem2Utils = ({
68
76
  if (multiSelect && hasShift) {
69
77
  instance.expandSelectionRange(event, itemId);
70
78
  } else {
71
- instance.selectItem(event, itemId, multiSelect, event.target.checked);
79
+ instance.selectItem({
80
+ event,
81
+ itemId,
82
+ keepExistingSelection: multiSelect,
83
+ shouldBeSelected: event.target.checked
84
+ });
72
85
  }
73
86
  };
74
87
  const interactions = {
package/modern/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-tree-view v7.8.0
2
+ * @mui/x-tree-view v7.9.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -43,8 +43,7 @@ export const useTreeViewFocus = ({
43
43
  return itemMeta && (itemMeta.parentId == null || instance.isItemExpanded(itemMeta.parentId));
44
44
  };
45
45
  const innerFocusItem = (event, itemId) => {
46
- const itemMeta = instance.getItemMeta(itemId);
47
- const itemElement = document.getElementById(instance.getTreeItemIdAttribute(itemId, itemMeta.idAttribute));
46
+ const itemElement = instance.getItemDOMElement(itemId);
48
47
  if (itemElement) {
49
48
  itemElement.focus();
50
49
  }
@@ -92,6 +92,13 @@ export const useTreeViewItems = ({
92
92
  return state.items.itemChildrenIndexes[parentId][itemId];
93
93
  }, [instance, state.items.itemChildrenIndexes]);
94
94
  const getItemOrderedChildrenIds = React.useCallback(itemId => state.items.itemOrderedChildrenIds[itemId ?? TREE_VIEW_ROOT_PARENT_ID] ?? [], [state.items.itemOrderedChildrenIds]);
95
+ const getItemDOMElement = itemId => {
96
+ const itemMeta = instance.getItemMeta(itemId);
97
+ if (itemMeta == null) {
98
+ return null;
99
+ }
100
+ return document.getElementById(instance.getTreeItemIdAttribute(itemId, itemMeta.idAttribute));
101
+ };
95
102
  const isItemNavigable = itemId => {
96
103
  if (params.disabledItemsFocusable) {
97
104
  return true;
@@ -145,13 +152,15 @@ export const useTreeViewItems = ({
145
152
  }
146
153
  }),
147
154
  publicAPI: {
148
- getItem
155
+ getItem,
156
+ getItemDOMElement
149
157
  },
150
158
  instance: {
151
159
  getItemMeta,
152
160
  getItem,
153
161
  getItemsToRender,
154
162
  getItemIndex,
163
+ getItemDOMElement,
155
164
  getItemOrderedChildrenIds,
156
165
  isItemDisabled,
157
166
  isItemNavigable,
@@ -74,10 +74,13 @@ export const useTreeViewKeyboardNavigation = ({
74
74
  event.preventDefault();
75
75
  if (params.multiSelect && event.shiftKey) {
76
76
  instance.expandSelectionRange(event, itemId);
77
- } else if (params.multiSelect) {
78
- instance.selectItem(event, itemId, true);
79
77
  } else {
80
- instance.selectItem(event, itemId, false);
78
+ instance.selectItem({
79
+ event,
80
+ itemId,
81
+ keepExistingSelection: params.multiSelect,
82
+ shouldBeSelected: params.multiSelect ? undefined : true
83
+ });
81
84
  }
82
85
  break;
83
86
  }
@@ -92,9 +95,16 @@ export const useTreeViewKeyboardNavigation = ({
92
95
  } else if (canToggleItemSelection(itemId)) {
93
96
  if (params.multiSelect) {
94
97
  event.preventDefault();
95
- instance.selectItem(event, itemId, true);
98
+ instance.selectItem({
99
+ event,
100
+ itemId,
101
+ keepExistingSelection: true
102
+ });
96
103
  } else if (!instance.isItemSelected(itemId)) {
97
- instance.selectItem(event, itemId, false);
104
+ instance.selectItem({
105
+ event,
106
+ itemId
107
+ });
98
108
  event.preventDefault();
99
109
  }
100
110
  }
@@ -46,7 +46,12 @@ export const useTreeViewSelection = ({
46
46
  models.selectedItems.setControlledValue(newSelectedItems);
47
47
  };
48
48
  const isItemSelected = itemId => selectedItemsMap.has(itemId);
49
- const selectItem = (event, itemId, keepExistingSelection, newValue) => {
49
+ const selectItem = ({
50
+ event,
51
+ itemId,
52
+ keepExistingSelection = false,
53
+ shouldBeSelected
54
+ }) => {
50
55
  if (params.disableSelection) {
51
56
  return;
52
57
  }
@@ -54,16 +59,16 @@ export const useTreeViewSelection = ({
54
59
  if (keepExistingSelection) {
55
60
  const cleanSelectedItems = convertSelectedItemsToArray(models.selectedItems.value);
56
61
  const isSelectedBefore = instance.isItemSelected(itemId);
57
- if (isSelectedBefore && (newValue === false || newValue == null)) {
62
+ if (isSelectedBefore && (shouldBeSelected === false || shouldBeSelected == null)) {
58
63
  newSelected = cleanSelectedItems.filter(id => id !== itemId);
59
- } else if (!isSelectedBefore && (newValue === true || newValue == null)) {
64
+ } else if (!isSelectedBefore && (shouldBeSelected === true || shouldBeSelected == null)) {
60
65
  newSelected = [itemId].concat(cleanSelectedItems);
61
66
  } else {
62
67
  newSelected = cleanSelectedItems;
63
68
  }
64
69
  } else {
65
70
  // eslint-disable-next-line no-lonely-if
66
- if (newValue === false) {
71
+ if (shouldBeSelected === false || shouldBeSelected == null && instance.isItemSelected(itemId)) {
67
72
  newSelected = params.multiSelect ? [] : null;
68
73
  } else {
69
74
  newSelected = params.multiSelect ? [itemId] : itemId;
@@ -142,6 +147,9 @@ export const useTreeViewSelection = ({
142
147
  getRootProps: () => ({
143
148
  'aria-multiselectable': params.multiSelect
144
149
  }),
150
+ publicAPI: {
151
+ selectItem
152
+ },
145
153
  instance: {
146
154
  isItemSelected,
147
155
  selectItem,
@@ -146,6 +146,8 @@ process.env.NODE_ENV !== "production" ? RichTreeView.propTypes = {
146
146
  current: _propTypes.default.shape({
147
147
  focusItem: _propTypes.default.func.isRequired,
148
148
  getItem: _propTypes.default.func.isRequired,
149
+ getItemDOMElement: _propTypes.default.func.isRequired,
150
+ selectItem: _propTypes.default.func.isRequired,
149
151
  setItemExpansion: _propTypes.default.func.isRequired
150
152
  })
151
153
  }),
@@ -243,34 +245,34 @@ process.env.NODE_ENV !== "production" ? RichTreeView.propTypes = {
243
245
  multiSelect: _propTypes.default.bool,
244
246
  /**
245
247
  * Callback fired when tree items are expanded/collapsed.
246
- * @param {React.SyntheticEvent} event The event source of the callback.
248
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
247
249
  * @param {array} itemIds The ids of the expanded items.
248
250
  */
249
251
  onExpandedItemsChange: _propTypes.default.func,
250
252
  /**
251
253
  * Callback fired when a tree item is expanded or collapsed.
252
- * @param {React.SyntheticEvent} event The event source of the callback.
254
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
253
255
  * @param {array} itemId The itemId of the modified item.
254
256
  * @param {array} isExpanded `true` if the item has just been expanded, `false` if it has just been collapsed.
255
257
  */
256
258
  onItemExpansionToggle: _propTypes.default.func,
257
259
  /**
258
260
  * Callback fired when tree items are focused.
259
- * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event.
261
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change. **Warning**: This is a generic event not a focus event.
260
262
  * @param {string} itemId The id of the focused item.
261
263
  * @param {string} value of the focused item.
262
264
  */
263
265
  onItemFocus: _propTypes.default.func,
264
266
  /**
265
267
  * Callback fired when a tree item is selected or deselected.
266
- * @param {React.SyntheticEvent} event The event source of the callback.
268
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
267
269
  * @param {array} itemId The itemId of the modified item.
268
270
  * @param {array} isSelected `true` if the item has just been selected, `false` if it has just been deselected.
269
271
  */
270
272
  onItemSelectionToggle: _propTypes.default.func,
271
273
  /**
272
274
  * Callback fired when tree items are selected/deselected.
273
- * @param {React.SyntheticEvent} event The event source of the callback
275
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
274
276
  * @param {string[] | string} itemIds The ids of the selected items.
275
277
  * When `multiSelect` is `true`, this is an array of strings; when false (default) a string.
276
278
  */
@@ -104,6 +104,8 @@ process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
104
104
  current: _propTypes.default.shape({
105
105
  focusItem: _propTypes.default.func.isRequired,
106
106
  getItem: _propTypes.default.func.isRequired,
107
+ getItemDOMElement: _propTypes.default.func.isRequired,
108
+ selectItem: _propTypes.default.func.isRequired,
107
109
  setItemExpansion: _propTypes.default.func.isRequired
108
110
  })
109
111
  }),
@@ -179,34 +181,34 @@ process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
179
181
  multiSelect: _propTypes.default.bool,
180
182
  /**
181
183
  * Callback fired when tree items are expanded/collapsed.
182
- * @param {React.SyntheticEvent} event The event source of the callback.
184
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
183
185
  * @param {array} itemIds The ids of the expanded items.
184
186
  */
185
187
  onExpandedItemsChange: _propTypes.default.func,
186
188
  /**
187
189
  * Callback fired when a tree item is expanded or collapsed.
188
- * @param {React.SyntheticEvent} event The event source of the callback.
190
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
189
191
  * @param {array} itemId The itemId of the modified item.
190
192
  * @param {array} isExpanded `true` if the item has just been expanded, `false` if it has just been collapsed.
191
193
  */
192
194
  onItemExpansionToggle: _propTypes.default.func,
193
195
  /**
194
196
  * Callback fired when tree items are focused.
195
- * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event.
197
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change. **Warning**: This is a generic event not a focus event.
196
198
  * @param {string} itemId The id of the focused item.
197
199
  * @param {string} value of the focused item.
198
200
  */
199
201
  onItemFocus: _propTypes.default.func,
200
202
  /**
201
203
  * Callback fired when a tree item is selected or deselected.
202
- * @param {React.SyntheticEvent} event The event source of the callback.
204
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
203
205
  * @param {array} itemId The itemId of the modified item.
204
206
  * @param {array} isSelected `true` if the item has just been selected, `false` if it has just been deselected.
205
207
  */
206
208
  onItemSelectionToggle: _propTypes.default.func,
207
209
  /**
208
210
  * Callback fired when tree items are selected/deselected.
209
- * @param {React.SyntheticEvent} event The event source of the callback
211
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
210
212
  * @param {string[] | string} itemIds The ids of the selected items.
211
213
  * When `multiSelect` is `true`, this is an array of strings; when false (default) a string.
212
214
  */
@@ -45,10 +45,18 @@ function useTreeItemState(itemId) {
45
45
  if (event.shiftKey) {
46
46
  instance.expandSelectionRange(event, itemId);
47
47
  } else {
48
- instance.selectItem(event, itemId, true);
48
+ instance.selectItem({
49
+ event,
50
+ itemId,
51
+ keepExistingSelection: true
52
+ });
49
53
  }
50
54
  } else {
51
- instance.selectItem(event, itemId, false);
55
+ instance.selectItem({
56
+ event,
57
+ itemId,
58
+ shouldBeSelected: true
59
+ });
52
60
  }
53
61
  }
54
62
  };
@@ -60,7 +68,12 @@ function useTreeItemState(itemId) {
60
68
  if (multiSelect && hasShift) {
61
69
  instance.expandSelectionRange(event, itemId);
62
70
  } else {
63
- instance.selectItem(event, itemId, multiSelect, event.target.checked);
71
+ instance.selectItem({
72
+ event,
73
+ itemId,
74
+ keepExistingSelection: multiSelect,
75
+ shouldBeSelected: event.target.checked
76
+ });
64
77
  }
65
78
  };
66
79
  const preventSelection = event => {
@@ -81,6 +81,8 @@ process.env.NODE_ENV !== "production" ? TreeView.propTypes = {
81
81
  current: _propTypes.default.shape({
82
82
  focusItem: _propTypes.default.func.isRequired,
83
83
  getItem: _propTypes.default.func.isRequired,
84
+ getItemDOMElement: _propTypes.default.func.isRequired,
85
+ selectItem: _propTypes.default.func.isRequired,
84
86
  setItemExpansion: _propTypes.default.func.isRequired
85
87
  })
86
88
  }),
@@ -156,34 +158,34 @@ process.env.NODE_ENV !== "production" ? TreeView.propTypes = {
156
158
  multiSelect: _propTypes.default.bool,
157
159
  /**
158
160
  * Callback fired when tree items are expanded/collapsed.
159
- * @param {React.SyntheticEvent} event The event source of the callback.
161
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
160
162
  * @param {array} itemIds The ids of the expanded items.
161
163
  */
162
164
  onExpandedItemsChange: _propTypes.default.func,
163
165
  /**
164
166
  * Callback fired when a tree item is expanded or collapsed.
165
- * @param {React.SyntheticEvent} event The event source of the callback.
167
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
166
168
  * @param {array} itemId The itemId of the modified item.
167
169
  * @param {array} isExpanded `true` if the item has just been expanded, `false` if it has just been collapsed.
168
170
  */
169
171
  onItemExpansionToggle: _propTypes.default.func,
170
172
  /**
171
173
  * Callback fired when tree items are focused.
172
- * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event.
174
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change. **Warning**: This is a generic event not a focus event.
173
175
  * @param {string} itemId The id of the focused item.
174
176
  * @param {string} value of the focused item.
175
177
  */
176
178
  onItemFocus: _propTypes.default.func,
177
179
  /**
178
180
  * Callback fired when a tree item is selected or deselected.
179
- * @param {React.SyntheticEvent} event The event source of the callback.
181
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
180
182
  * @param {array} itemId The itemId of the modified item.
181
183
  * @param {array} isSelected `true` if the item has just been selected, `false` if it has just been deselected.
182
184
  */
183
185
  onItemSelectionToggle: _propTypes.default.func,
184
186
  /**
185
187
  * Callback fired when tree items are selected/deselected.
186
- * @param {React.SyntheticEvent} event The event source of the callback
188
+ * @param {React.SyntheticEvent} event The DOM event that triggered the change.
187
189
  * @param {string[] | string} itemIds The ids of the selected items.
188
190
  * When `multiSelect` is `true`, this is an array of strings; when false (default) a string.
189
191
  */
@@ -63,10 +63,18 @@ const useTreeItem2Utils = ({
63
63
  if (event.shiftKey) {
64
64
  instance.expandSelectionRange(event, itemId);
65
65
  } else {
66
- instance.selectItem(event, itemId, true);
66
+ instance.selectItem({
67
+ event,
68
+ itemId,
69
+ keepExistingSelection: true
70
+ });
67
71
  }
68
72
  } else {
69
- instance.selectItem(event, itemId, false);
73
+ instance.selectItem({
74
+ event,
75
+ itemId,
76
+ shouldBeSelected: true
77
+ });
70
78
  }
71
79
  };
72
80
  const handleCheckboxSelection = event => {
@@ -74,7 +82,12 @@ const useTreeItem2Utils = ({
74
82
  if (multiSelect && hasShift) {
75
83
  instance.expandSelectionRange(event, itemId);
76
84
  } else {
77
- instance.selectItem(event, itemId, multiSelect, event.target.checked);
85
+ instance.selectItem({
86
+ event,
87
+ itemId,
88
+ keepExistingSelection: multiSelect,
89
+ shouldBeSelected: event.target.checked
90
+ });
78
91
  }
79
92
  };
80
93
  const interactions = {
package/node/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-tree-view v7.8.0
2
+ * @mui/x-tree-view v7.9.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -52,8 +52,7 @@ const useTreeViewFocus = ({
52
52
  return itemMeta && (itemMeta.parentId == null || instance.isItemExpanded(itemMeta.parentId));
53
53
  };
54
54
  const innerFocusItem = (event, itemId) => {
55
- const itemMeta = instance.getItemMeta(itemId);
56
- const itemElement = document.getElementById(instance.getTreeItemIdAttribute(itemId, itemMeta.idAttribute));
55
+ const itemElement = instance.getItemDOMElement(itemId);
57
56
  if (itemElement) {
58
57
  itemElement.focus();
59
58
  }
@@ -101,6 +101,13 @@ const useTreeViewItems = ({
101
101
  return state.items.itemChildrenIndexes[parentId][itemId];
102
102
  }, [instance, state.items.itemChildrenIndexes]);
103
103
  const getItemOrderedChildrenIds = React.useCallback(itemId => state.items.itemOrderedChildrenIds[itemId ?? _useTreeViewItems.TREE_VIEW_ROOT_PARENT_ID] ?? [], [state.items.itemOrderedChildrenIds]);
104
+ const getItemDOMElement = itemId => {
105
+ const itemMeta = instance.getItemMeta(itemId);
106
+ if (itemMeta == null) {
107
+ return null;
108
+ }
109
+ return document.getElementById(instance.getTreeItemIdAttribute(itemId, itemMeta.idAttribute));
110
+ };
104
111
  const isItemNavigable = itemId => {
105
112
  if (params.disabledItemsFocusable) {
106
113
  return true;
@@ -154,13 +161,15 @@ const useTreeViewItems = ({
154
161
  }
155
162
  }),
156
163
  publicAPI: {
157
- getItem
164
+ getItem,
165
+ getItemDOMElement
158
166
  },
159
167
  instance: {
160
168
  getItemMeta,
161
169
  getItem,
162
170
  getItemsToRender,
163
171
  getItemIndex,
172
+ getItemDOMElement,
164
173
  getItemOrderedChildrenIds,
165
174
  isItemDisabled,
166
175
  isItemNavigable,
@@ -83,10 +83,13 @@ const useTreeViewKeyboardNavigation = ({
83
83
  event.preventDefault();
84
84
  if (params.multiSelect && event.shiftKey) {
85
85
  instance.expandSelectionRange(event, itemId);
86
- } else if (params.multiSelect) {
87
- instance.selectItem(event, itemId, true);
88
86
  } else {
89
- instance.selectItem(event, itemId, false);
87
+ instance.selectItem({
88
+ event,
89
+ itemId,
90
+ keepExistingSelection: params.multiSelect,
91
+ shouldBeSelected: params.multiSelect ? undefined : true
92
+ });
90
93
  }
91
94
  break;
92
95
  }
@@ -101,9 +104,16 @@ const useTreeViewKeyboardNavigation = ({
101
104
  } else if (canToggleItemSelection(itemId)) {
102
105
  if (params.multiSelect) {
103
106
  event.preventDefault();
104
- instance.selectItem(event, itemId, true);
107
+ instance.selectItem({
108
+ event,
109
+ itemId,
110
+ keepExistingSelection: true
111
+ });
105
112
  } else if (!instance.isItemSelected(itemId)) {
106
- instance.selectItem(event, itemId, false);
113
+ instance.selectItem({
114
+ event,
115
+ itemId
116
+ });
107
117
  event.preventDefault();
108
118
  }
109
119
  }
@@ -55,7 +55,12 @@ const useTreeViewSelection = ({
55
55
  models.selectedItems.setControlledValue(newSelectedItems);
56
56
  };
57
57
  const isItemSelected = itemId => selectedItemsMap.has(itemId);
58
- const selectItem = (event, itemId, keepExistingSelection, newValue) => {
58
+ const selectItem = ({
59
+ event,
60
+ itemId,
61
+ keepExistingSelection = false,
62
+ shouldBeSelected
63
+ }) => {
59
64
  if (params.disableSelection) {
60
65
  return;
61
66
  }
@@ -63,16 +68,16 @@ const useTreeViewSelection = ({
63
68
  if (keepExistingSelection) {
64
69
  const cleanSelectedItems = (0, _useTreeViewSelection.convertSelectedItemsToArray)(models.selectedItems.value);
65
70
  const isSelectedBefore = instance.isItemSelected(itemId);
66
- if (isSelectedBefore && (newValue === false || newValue == null)) {
71
+ if (isSelectedBefore && (shouldBeSelected === false || shouldBeSelected == null)) {
67
72
  newSelected = cleanSelectedItems.filter(id => id !== itemId);
68
- } else if (!isSelectedBefore && (newValue === true || newValue == null)) {
73
+ } else if (!isSelectedBefore && (shouldBeSelected === true || shouldBeSelected == null)) {
69
74
  newSelected = [itemId].concat(cleanSelectedItems);
70
75
  } else {
71
76
  newSelected = cleanSelectedItems;
72
77
  }
73
78
  } else {
74
79
  // eslint-disable-next-line no-lonely-if
75
- if (newValue === false) {
80
+ if (shouldBeSelected === false || shouldBeSelected == null && instance.isItemSelected(itemId)) {
76
81
  newSelected = params.multiSelect ? [] : null;
77
82
  } else {
78
83
  newSelected = params.multiSelect ? [itemId] : itemId;
@@ -151,6 +156,9 @@ const useTreeViewSelection = ({
151
156
  getRootProps: () => ({
152
157
  'aria-multiselectable': params.multiSelect
153
158
  }),
159
+ publicAPI: {
160
+ selectItem
161
+ },
154
162
  instance: {
155
163
  isItemSelected,
156
164
  selectItem,