@mui/x-tree-view 7.1.1 → 7.3.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 (77) hide show
  1. package/CHANGELOG.md +211 -0
  2. package/RichTreeView/RichTreeView.types.d.ts +3 -3
  3. package/TreeItem/TreeItem.js +1 -1
  4. package/TreeItem2/TreeItem2.d.ts +5 -1
  5. package/TreeItem2/TreeItem2.js +0 -1
  6. package/index.js +1 -1
  7. package/internals/TreeViewProvider/TreeViewChildrenItemProvider.d.ts +16 -0
  8. package/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +57 -0
  9. package/internals/TreeViewProvider/TreeViewContext.d.ts +2 -0
  10. package/internals/TreeViewProvider/TreeViewProvider.js +2 -3
  11. package/internals/TreeViewProvider/TreeViewProvider.types.d.ts +3 -1
  12. package/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +7 -8
  13. package/internals/models/plugin.d.ts +13 -5
  14. package/internals/models/treeView.d.ts +1 -2
  15. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +15 -15
  16. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +31 -28
  17. package/internals/plugins/useTreeViewId/useTreeViewId.js +5 -7
  18. package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +1 -1
  19. package/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -50
  20. package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +19 -15
  21. package/internals/plugins/useTreeViewItems/useTreeViewItems.utils.d.ts +4 -0
  22. package/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +8 -0
  23. package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +73 -48
  24. package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.types.d.ts +3 -2
  25. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -18
  26. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +11 -22
  27. package/internals/useTreeView/useTreeView.js +21 -3
  28. package/internals/utils/tree.d.ts +8 -0
  29. package/internals/utils/tree.js +137 -0
  30. package/modern/TreeItem/TreeItem.js +1 -1
  31. package/modern/TreeItem2/TreeItem2.js +0 -1
  32. package/modern/index.js +1 -1
  33. package/modern/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +57 -0
  34. package/modern/internals/TreeViewProvider/TreeViewProvider.js +2 -3
  35. package/modern/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +7 -8
  36. package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +15 -15
  37. package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +31 -28
  38. package/modern/internals/plugins/useTreeViewId/useTreeViewId.js +5 -7
  39. package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -50
  40. package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +8 -0
  41. package/modern/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +73 -48
  42. package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -18
  43. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +11 -22
  44. package/modern/internals/useTreeView/useTreeView.js +21 -3
  45. package/modern/internals/utils/tree.js +137 -0
  46. package/modern/useTreeItem2/useTreeItem2.js +1 -1
  47. package/node/TreeItem/TreeItem.js +1 -1
  48. package/node/TreeItem2/TreeItem2.js +0 -1
  49. package/node/index.js +1 -1
  50. package/node/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +67 -0
  51. package/node/internals/TreeViewProvider/TreeViewProvider.js +2 -3
  52. package/node/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +7 -8
  53. package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +15 -15
  54. package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +31 -28
  55. package/node/internals/plugins/useTreeViewId/useTreeViewId.js +5 -7
  56. package/node/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -50
  57. package/node/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +15 -0
  58. package/node/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +73 -48
  59. package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -18
  60. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +11 -22
  61. package/node/internals/useTreeView/useTreeView.js +21 -3
  62. package/node/internals/utils/tree.js +148 -0
  63. package/node/useTreeItem2/useTreeItem2.js +1 -1
  64. package/package.json +1 -1
  65. package/useTreeItem2/useTreeItem2.js +1 -1
  66. package/internals/TreeViewProvider/DescendantProvider.d.ts +0 -38
  67. package/internals/TreeViewProvider/DescendantProvider.js +0 -176
  68. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.d.ts +0 -17
  69. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +0 -55
  70. package/internals/useTreeView/useTreeView.utils.d.ts +0 -9
  71. package/internals/useTreeView/useTreeView.utils.js +0 -46
  72. package/modern/internals/TreeViewProvider/DescendantProvider.js +0 -176
  73. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +0 -55
  74. package/modern/internals/useTreeView/useTreeView.utils.js +0 -46
  75. package/node/internals/TreeViewProvider/DescendantProvider.js +0 -185
  76. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +0 -62
  77. package/node/internals/useTreeView/useTreeView.utils.js +0 -58
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { useTheme } from '@mui/material/styles';
3
3
  import useEventCallback from '@mui/utils/useEventCallback';
4
- import { getFirstItem, getLastItem, getNextItem, getPreviousItem, populateInstance } from '../../useTreeView/useTreeView.utils';
4
+ import { getFirstNavigableItem, getLastNavigableItem, getNextNavigableItem, getPreviousNavigableItem } from '../../utils/tree';
5
5
  function isPrintableCharacter(string) {
6
6
  return !!string && string.length === 1 && !!string.match(/\S/);
7
7
  }
@@ -29,12 +29,12 @@ export const useTreeViewKeyboardNavigation = ({
29
29
  return;
30
30
  }
31
31
  const newFirstCharMap = {};
32
- const processItem = node => {
33
- newFirstCharMap[node.id] = node.label.substring(0, 1).toLowerCase();
32
+ const processItem = item => {
33
+ newFirstCharMap[item.id] = item.label.substring(0, 1).toLowerCase();
34
34
  };
35
- Object.values(state.items.nodeMap).forEach(processItem);
35
+ Object.values(state.items.itemMetaMap).forEach(processItem);
36
36
  firstCharMap.current = newFirstCharMap;
37
- }, [state.items.nodeMap, params.getItemId, instance]);
37
+ }, [state.items.itemMetaMap, params.getItemId, instance]);
38
38
  const getFirstMatchingItem = (itemId, firstChar) => {
39
39
  let start;
40
40
  let index;
@@ -43,7 +43,7 @@ export const useTreeViewKeyboardNavigation = ({
43
43
  const firstChars = [];
44
44
  // This really only works since the ids are strings
45
45
  Object.keys(firstCharMap.current).forEach(mapItemId => {
46
- const map = instance.getNode(mapItemId);
46
+ const map = instance.getItemMeta(mapItemId);
47
47
  const visible = map.parentId ? instance.isItemExpanded(map.parentId) : true;
48
48
  const shouldBeSkipped = params.disabledItemsFocusable ? false : instance.isItemDisabled(mapItemId);
49
49
  if (visible && !shouldBeSkipped) {
@@ -128,7 +128,7 @@ export const useTreeViewKeyboardNavigation = ({
128
128
  // Focus the next focusable item
129
129
  case key === 'ArrowDown':
130
130
  {
131
- const nextItem = getNextItem(instance, itemId);
131
+ const nextItem = getNextNavigableItem(instance, itemId);
132
132
  if (nextItem) {
133
133
  event.preventDefault();
134
134
  instance.focusItem(event, nextItem);
@@ -148,7 +148,7 @@ export const useTreeViewKeyboardNavigation = ({
148
148
  // Focuses the previous focusable item
149
149
  case key === 'ArrowUp':
150
150
  {
151
- const previousItem = getPreviousItem(instance, itemId);
151
+ const previousItem = getPreviousNavigableItem(instance, itemId);
152
152
  if (previousItem) {
153
153
  event.preventDefault();
154
154
  instance.focusItem(event, previousItem);
@@ -170,7 +170,7 @@ export const useTreeViewKeyboardNavigation = ({
170
170
  case key === 'ArrowRight' && !isRTL || key === 'ArrowLeft' && isRTL:
171
171
  {
172
172
  if (instance.isItemExpanded(itemId)) {
173
- const nextItemId = getNextItem(instance, itemId);
173
+ const nextItemId = getNextNavigableItem(instance, itemId);
174
174
  if (nextItemId) {
175
175
  instance.focusItem(event, nextItemId);
176
176
  event.preventDefault();
@@ -190,7 +190,7 @@ export const useTreeViewKeyboardNavigation = ({
190
190
  instance.toggleItemExpansion(event, itemId);
191
191
  event.preventDefault();
192
192
  } else {
193
- const parent = instance.getNode(itemId).parentId;
193
+ const parent = instance.getItemMeta(itemId).parentId;
194
194
  if (parent) {
195
195
  instance.focusItem(event, parent);
196
196
  event.preventDefault();
@@ -202,7 +202,7 @@ export const useTreeViewKeyboardNavigation = ({
202
202
  // Focuses the first item in the tree
203
203
  case key === 'Home':
204
204
  {
205
- instance.focusItem(event, getFirstItem(instance));
205
+ instance.focusItem(event, getFirstNavigableItem(instance));
206
206
 
207
207
  // Multi select behavior when pressing Ctrl + Shift + Home
208
208
  // Selects the focused item and all items up to the first item.
@@ -216,7 +216,7 @@ export const useTreeViewKeyboardNavigation = ({
216
216
  // Focuses the last item in the tree
217
217
  case key === 'End':
218
218
  {
219
- instance.focusItem(event, getLastItem(instance));
219
+ instance.focusItem(event, getLastNavigableItem(instance));
220
220
 
221
221
  // Multi select behavior when pressing Ctrl + Shirt + End
222
222
  // Selects the focused item and all the items down to the last item.
@@ -240,8 +240,8 @@ export const useTreeViewKeyboardNavigation = ({
240
240
  case key === 'a' && ctrlPressed && params.multiSelect && !params.disableSelection:
241
241
  {
242
242
  instance.selectRange(event, {
243
- start: getFirstItem(instance),
244
- end: getLastItem(instance)
243
+ start: getFirstNavigableItem(instance),
244
+ end: getLastNavigableItem(instance)
245
245
  });
246
246
  event.preventDefault();
247
247
  break;
@@ -260,9 +260,11 @@ export const useTreeViewKeyboardNavigation = ({
260
260
  }
261
261
  }
262
262
  };
263
- populateInstance(instance, {
264
- updateFirstCharMap,
265
- handleItemKeyDown
266
- });
263
+ return {
264
+ instance: {
265
+ updateFirstCharMap,
266
+ handleItemKeyDown
267
+ }
268
+ };
267
269
  };
268
270
  useTreeViewKeyboardNavigation.params = {};
@@ -1,7 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
- import { populateInstance, getNextItem, getFirstItem, getLastItem } from '../../useTreeView/useTreeView.utils';
4
- import { findOrderInTremauxTree } from './useTreeViewSelection.utils';
3
+ import { getFirstNavigableItem, getLastNavigableItem, getNavigableItemsInRange } from '../../utils/tree';
5
4
  export const useTreeViewSelection = ({
6
5
  instance,
7
6
  params,
@@ -58,16 +57,6 @@ export const useTreeViewSelection = ({
58
57
  lastSelectionWasRange.current = false;
59
58
  currentRangeSelection.current = [];
60
59
  };
61
- const getItemsInRange = (itemAId, itemBId) => {
62
- const [first, last] = findOrderInTremauxTree(instance, itemAId, itemBId);
63
- const items = [first];
64
- let current = first;
65
- while (current !== last) {
66
- current = getNextItem(instance, current);
67
- items.push(current);
68
- }
69
- return items;
70
- };
71
60
  const handleRangeArrowSelect = (event, items) => {
72
61
  let base = models.selectedItems.value.slice();
73
62
  const {
@@ -105,7 +94,7 @@ export const useTreeViewSelection = ({
105
94
  if (lastSelectionWasRange.current) {
106
95
  base = base.filter(id => currentRangeSelection.current.indexOf(id) === -1);
107
96
  }
108
- let range = getItemsInRange(start, end);
97
+ let range = getNavigableItemsInRange(instance, start, end);
109
98
  range = range.filter(item => !instance.isItemDisabled(item));
110
99
  currentRangeSelection.current = range;
111
100
  let newSelected = base.concat(range);
@@ -142,7 +131,7 @@ export const useTreeViewSelection = ({
142
131
  const start = lastSelectionWasRange.current ? lastSelectedItem.current : itemId;
143
132
  instance.selectRange(event, {
144
133
  start,
145
- end: getFirstItem(instance)
134
+ end: getFirstNavigableItem(instance)
146
135
  });
147
136
  };
148
137
  const rangeSelectToLast = (event, itemId) => {
@@ -152,20 +141,20 @@ export const useTreeViewSelection = ({
152
141
  const start = lastSelectionWasRange.current ? lastSelectedItem.current : itemId;
153
142
  instance.selectRange(event, {
154
143
  start,
155
- end: getLastItem(instance)
144
+ end: getLastNavigableItem(instance)
156
145
  });
157
146
  };
158
- populateInstance(instance, {
159
- isItemSelected,
160
- selectItem,
161
- selectRange,
162
- rangeSelectToLast,
163
- rangeSelectToFirst
164
- });
165
147
  return {
166
148
  getRootProps: () => ({
167
149
  'aria-multiselectable': params.multiSelect
168
150
  }),
151
+ instance: {
152
+ isItemSelected,
153
+ selectItem,
154
+ selectRange,
155
+ rangeSelectToLast,
156
+ rangeSelectToFirst
157
+ },
169
158
  contextValue: {
170
159
  selection: {
171
160
  multiSelect: params.multiSelect
@@ -39,12 +39,12 @@ export const useTreeView = inParams => {
39
39
  const rootPropsGetters = [];
40
40
  const contextValue = {
41
41
  publicAPI,
42
- instance: instance
42
+ instance: instance,
43
+ rootRef: innerRootRef
43
44
  };
44
45
  const runPlugin = plugin => {
45
46
  const pluginResponse = plugin({
46
47
  instance,
47
- publicAPI,
48
48
  params,
49
49
  slots: params.slots,
50
50
  slotProps: params.slotProps,
@@ -52,10 +52,16 @@ export const useTreeView = inParams => {
52
52
  setState,
53
53
  rootRef: innerRootRef,
54
54
  models
55
- }) || {};
55
+ });
56
56
  if (pluginResponse.getRootProps) {
57
57
  rootPropsGetters.push(pluginResponse.getRootProps);
58
58
  }
59
+ if (pluginResponse.publicAPI) {
60
+ Object.assign(publicAPI, pluginResponse.publicAPI);
61
+ }
62
+ if (pluginResponse.instance) {
63
+ Object.assign(instance, pluginResponse.instance);
64
+ }
59
65
  if (pluginResponse.contextValue) {
60
66
  Object.assign(contextValue, pluginResponse.contextValue);
61
67
  }
@@ -99,6 +105,18 @@ export const useTreeView = inParams => {
99
105
  });
100
106
  return finalChildren;
101
107
  };
108
+ const rootWrappers = plugins.map(plugin => plugin.wrapRoot).filter(wrapRoot => !!wrapRoot);
109
+ contextValue.wrapRoot = ({
110
+ children
111
+ }) => {
112
+ let finalChildren = children;
113
+ rootWrappers.forEach(rootWrapper => {
114
+ finalChildren = rootWrapper({
115
+ children: finalChildren
116
+ });
117
+ });
118
+ return finalChildren;
119
+ };
102
120
  const getRootProps = (otherHandlers = {}) => {
103
121
  const rootProps = _extends({
104
122
  role: 'tree'
@@ -0,0 +1,8 @@
1
+ import { TreeViewInstance } from '../models';
2
+ import type { UseTreeViewExpansionSignature } from '../plugins/useTreeViewExpansion';
3
+ import type { UseTreeViewItemsSignature } from '../plugins/useTreeViewItems';
4
+ export declare const getPreviousNavigableItem: (instance: TreeViewInstance<[UseTreeViewItemsSignature, UseTreeViewExpansionSignature]>, itemId: string) => string | null;
5
+ export declare const getNextNavigableItem: (instance: TreeViewInstance<[UseTreeViewExpansionSignature, UseTreeViewItemsSignature]>, itemId: string) => string | null;
6
+ export declare const getLastNavigableItem: (instance: TreeViewInstance<[UseTreeViewExpansionSignature, UseTreeViewItemsSignature]>) => string;
7
+ export declare const getFirstNavigableItem: (instance: TreeViewInstance<[UseTreeViewItemsSignature]>) => string;
8
+ export declare const getNavigableItemsInRange: (instance: TreeViewInstance<[UseTreeViewItemsSignature, UseTreeViewExpansionSignature]>, itemAId: string, itemBId: string) => string[];
@@ -0,0 +1,137 @@
1
+ const getLastNavigableItemInArray = (instance, items) => {
2
+ // Equivalent to Array.prototype.findLastIndex
3
+ let itemIndex = items.length - 1;
4
+ while (itemIndex >= 0 && !instance.isItemNavigable(items[itemIndex])) {
5
+ itemIndex -= 1;
6
+ }
7
+ if (itemIndex === -1) {
8
+ return undefined;
9
+ }
10
+ return items[itemIndex];
11
+ };
12
+ export const getPreviousNavigableItem = (instance, itemId) => {
13
+ const itemMeta = instance.getItemMeta(itemId);
14
+ const siblings = instance.getItemOrderedChildrenIds(itemMeta.parentId);
15
+ const itemIndex = instance.getItemIndex(itemId);
16
+
17
+ // TODO: What should we do if the parent is not navigable?
18
+ if (itemIndex === 0) {
19
+ return itemMeta.parentId;
20
+ }
21
+ let currentItemId = siblings[itemIndex - 1];
22
+ let lastNavigableChild = getLastNavigableItemInArray(instance, instance.getItemOrderedChildrenIds(currentItemId));
23
+ while (instance.isItemExpanded(currentItemId) && lastNavigableChild != null) {
24
+ currentItemId = lastNavigableChild;
25
+ lastNavigableChild = instance.getItemOrderedChildrenIds(currentItemId).find(instance.isItemNavigable);
26
+ }
27
+ return currentItemId;
28
+ };
29
+ export const getNextNavigableItem = (instance, itemId) => {
30
+ // If the item is expanded and has some navigable children, return the first of them.
31
+ if (instance.isItemExpanded(itemId)) {
32
+ const firstNavigableChild = instance.getItemOrderedChildrenIds(itemId).find(instance.isItemNavigable);
33
+ if (firstNavigableChild != null) {
34
+ return firstNavigableChild;
35
+ }
36
+ }
37
+ let itemMeta = instance.getItemMeta(itemId);
38
+ while (itemMeta != null) {
39
+ // Try to find the first navigable sibling after the current item.
40
+ const siblings = instance.getItemOrderedChildrenIds(itemMeta.parentId);
41
+ const currentItemIndex = instance.getItemIndex(itemMeta.id);
42
+ if (currentItemIndex < siblings.length - 1) {
43
+ let nextItemIndex = currentItemIndex + 1;
44
+ while (!instance.isItemNavigable(siblings[nextItemIndex]) && nextItemIndex < siblings.length - 1) {
45
+ nextItemIndex += 1;
46
+ }
47
+ if (instance.isItemNavigable(siblings[nextItemIndex])) {
48
+ return siblings[nextItemIndex];
49
+ }
50
+ }
51
+
52
+ // If the sibling does not exist, go up a level to the parent and try again.
53
+ itemMeta = instance.getItemMeta(itemMeta.parentId);
54
+ }
55
+ return null;
56
+ };
57
+ export const getLastNavigableItem = instance => {
58
+ let itemId = null;
59
+ while (itemId == null || instance.isItemExpanded(itemId)) {
60
+ const children = instance.getItemOrderedChildrenIds(itemId);
61
+ const lastNavigableChild = getLastNavigableItemInArray(instance, children);
62
+
63
+ // The item has no navigable children.
64
+ if (lastNavigableChild == null) {
65
+ return itemId;
66
+ }
67
+ itemId = lastNavigableChild;
68
+ }
69
+ return itemId;
70
+ };
71
+ export const getFirstNavigableItem = instance => instance.getItemOrderedChildrenIds(null).find(instance.isItemNavigable);
72
+
73
+ /**
74
+ * This is used to determine the start and end of a selection range so
75
+ * we can get the items between the two border items.
76
+ *
77
+ * It finds the items' common ancestor using
78
+ * a naive implementation of a lowest common ancestor algorithm
79
+ * (https://en.wikipedia.org/wiki/Lowest_common_ancestor).
80
+ * Then compares the ancestor's 2 children that are ancestors of itemA and ItemB
81
+ * so we can compare their indexes to work out which item comes first in a depth first search.
82
+ * (https://en.wikipedia.org/wiki/Depth-first_search)
83
+ *
84
+ * Another way to put it is which item is shallower in a trémaux tree
85
+ * https://en.wikipedia.org/wiki/Tr%C3%A9maux_tree
86
+ */
87
+ const findOrderInTremauxTree = (instance, itemAId, itemBId) => {
88
+ if (itemAId === itemBId) {
89
+ return [itemAId, itemBId];
90
+ }
91
+ const itemMetaA = instance.getItemMeta(itemAId);
92
+ const itemMetaB = instance.getItemMeta(itemBId);
93
+ if (itemMetaA.parentId === itemMetaB.id || itemMetaB.parentId === itemMetaA.id) {
94
+ return itemMetaB.parentId === itemMetaA.id ? [itemMetaA.id, itemMetaB.id] : [itemMetaB.id, itemMetaA.id];
95
+ }
96
+ const aFamily = [itemMetaA.id];
97
+ const bFamily = [itemMetaB.id];
98
+ let aAncestor = itemMetaA.parentId;
99
+ let bAncestor = itemMetaB.parentId;
100
+ let aAncestorIsCommon = bFamily.indexOf(aAncestor) !== -1;
101
+ let bAncestorIsCommon = aFamily.indexOf(bAncestor) !== -1;
102
+ let continueA = true;
103
+ let continueB = true;
104
+ while (!bAncestorIsCommon && !aAncestorIsCommon) {
105
+ if (continueA) {
106
+ aFamily.push(aAncestor);
107
+ aAncestorIsCommon = bFamily.indexOf(aAncestor) !== -1;
108
+ continueA = aAncestor !== null;
109
+ if (!aAncestorIsCommon && continueA) {
110
+ aAncestor = instance.getItemMeta(aAncestor).parentId;
111
+ }
112
+ }
113
+ if (continueB && !aAncestorIsCommon) {
114
+ bFamily.push(bAncestor);
115
+ bAncestorIsCommon = aFamily.indexOf(bAncestor) !== -1;
116
+ continueB = bAncestor !== null;
117
+ if (!bAncestorIsCommon && continueB) {
118
+ bAncestor = instance.getItemMeta(bAncestor).parentId;
119
+ }
120
+ }
121
+ }
122
+ const commonAncestor = aAncestorIsCommon ? aAncestor : bAncestor;
123
+ const ancestorFamily = instance.getItemOrderedChildrenIds(commonAncestor);
124
+ const aSide = aFamily[aFamily.indexOf(commonAncestor) - 1];
125
+ const bSide = bFamily[bFamily.indexOf(commonAncestor) - 1];
126
+ return ancestorFamily.indexOf(aSide) < ancestorFamily.indexOf(bSide) ? [itemAId, itemBId] : [itemBId, itemAId];
127
+ };
128
+ export const getNavigableItemsInRange = (instance, itemAId, itemBId) => {
129
+ const [first, last] = findOrderInTremauxTree(instance, itemAId, itemBId);
130
+ const items = [first];
131
+ let current = first;
132
+ while (current !== last) {
133
+ current = getNextNavigableItem(instance, current);
134
+ items.push(current);
135
+ }
136
+ return items;
137
+ };
@@ -270,7 +270,7 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
270
270
  onKeyDown?.(event);
271
271
  instance.handleItemKeyDown(event, itemId);
272
272
  };
273
- const idAttribute = instance.getTreeItemId(itemId, id);
273
+ const idAttribute = instance.getTreeItemIdAttribute(itemId, id);
274
274
  const tabIndex = instance.canItemBeTabbed(itemId) ? 0 : -1;
275
275
  return /*#__PURE__*/_jsx(TreeItem2Provider, {
276
276
  itemId: itemId,
@@ -147,7 +147,6 @@ const useUtilityClasses = ownerState => {
147
147
  };
148
148
  return composeClasses(slots, getTreeItemUtilityClass, classes);
149
149
  };
150
-
151
150
  /**
152
151
  *
153
152
  * Demos:
package/modern/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-tree-view v7.1.1
2
+ * @mui/x-tree-view v7.3.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -0,0 +1,57 @@
1
+ import * as React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useTreeViewContext } from './useTreeViewContext';
4
+ import { jsx as _jsx } from "react/jsx-runtime";
5
+ export const TreeViewChildrenItemContext = /*#__PURE__*/React.createContext(null);
6
+ if (process.env.NODE_ENV !== 'production') {
7
+ TreeViewChildrenItemContext.displayName = 'TreeViewChildrenItemContext';
8
+ }
9
+ export function TreeViewChildrenItemProvider(props) {
10
+ const {
11
+ children,
12
+ itemId = null
13
+ } = props;
14
+ const {
15
+ instance,
16
+ rootRef
17
+ } = useTreeViewContext();
18
+ const childrenIdAttrToIdRef = React.useRef(new Map());
19
+ React.useEffect(() => {
20
+ if (!rootRef.current) {
21
+ return;
22
+ }
23
+ let idAttr = null;
24
+ if (itemId == null) {
25
+ idAttr = rootRef.current.id;
26
+ } else {
27
+ // Undefined during 1st render
28
+ const itemMeta = instance.getItemMeta(itemId);
29
+ if (itemMeta !== undefined) {
30
+ idAttr = instance.getTreeItemIdAttribute(itemId, itemMeta.idAttribute);
31
+ }
32
+ }
33
+ if (idAttr == null) {
34
+ return;
35
+ }
36
+ const previousChildrenIds = instance.getItemOrderedChildrenIds(itemId ?? null) ?? [];
37
+ const childrenElements = rootRef.current.querySelectorAll(`${itemId == null ? '' : `*[id="${idAttr}"] `}[role="treeitem"]:not(*[id="${idAttr}"] [role="treeitem"] [role="treeitem"])`);
38
+ const childrenIds = Array.from(childrenElements).map(child => childrenIdAttrToIdRef.current.get(child.id));
39
+ const hasChanged = childrenIds.length !== previousChildrenIds.length || childrenIds.some((childId, index) => childId !== previousChildrenIds[index]);
40
+ if (hasChanged) {
41
+ instance.setJSXItemsOrderedChildrenIds(itemId ?? null, childrenIds);
42
+ }
43
+ });
44
+ const value = React.useMemo(() => ({
45
+ registerChild: (childIdAttribute, childItemId) => childrenIdAttrToIdRef.current.set(childIdAttribute, childItemId),
46
+ unregisterChild: childIdAttribute => childrenIdAttrToIdRef.current.delete(childIdAttribute),
47
+ parentId: itemId
48
+ }), [itemId]);
49
+ return /*#__PURE__*/_jsx(TreeViewChildrenItemContext.Provider, {
50
+ value: value,
51
+ children: children
52
+ });
53
+ }
54
+ process.env.NODE_ENV !== "production" ? TreeViewChildrenItemProvider.propTypes = {
55
+ children: PropTypes.node,
56
+ id: PropTypes.string
57
+ } : void 0;
@@ -1,6 +1,5 @@
1
1
  import * as React from 'react';
2
2
  import { TreeViewContext } from './TreeViewContext';
3
- import { DescendantProvider } from './DescendantProvider';
4
3
  import { jsx as _jsx } from "react/jsx-runtime";
5
4
  /**
6
5
  * Sets up the contexts for the underlying TreeItem components.
@@ -14,8 +13,8 @@ export function TreeViewProvider(props) {
14
13
  } = props;
15
14
  return /*#__PURE__*/_jsx(TreeViewContext.Provider, {
16
15
  value: value,
17
- children: /*#__PURE__*/_jsx(DescendantProvider, {
18
- children: children
16
+ children: value.wrapRoot({
17
+ children
19
18
  })
20
19
  });
21
20
  }
@@ -1,12 +1,9 @@
1
1
  import * as React from 'react';
2
2
  import { EventManager } from '../../utils/EventManager';
3
- import { populateInstance } from '../../useTreeView/useTreeView.utils';
4
3
  const isSyntheticEvent = event => {
5
4
  return event.isPropagationStopped !== undefined;
6
5
  };
7
- export const useTreeViewInstanceEvents = ({
8
- instance
9
- }) => {
6
+ export const useTreeViewInstanceEvents = () => {
10
7
  const [eventManager] = React.useState(() => new EventManager());
11
8
  const publishEvent = React.useCallback((...args) => {
12
9
  const [name, params, event = {}] = args;
@@ -22,9 +19,11 @@ export const useTreeViewInstanceEvents = ({
22
19
  eventManager.removeListener(event, handler);
23
20
  };
24
21
  }, [eventManager]);
25
- populateInstance(instance, {
26
- $$publishEvent: publishEvent,
27
- $$subscribeEvent: subscribeEvent
28
- });
22
+ return {
23
+ instance: {
24
+ $$publishEvent: publishEvent,
25
+ $$subscribeEvent: subscribeEvent
26
+ }
27
+ };
29
28
  };
30
29
  useTreeViewInstanceEvents.params = {};
@@ -1,10 +1,8 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
3
  import useEventCallback from '@mui/utils/useEventCallback';
4
- import { populateInstance, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
5
4
  export const useTreeViewExpansion = ({
6
5
  instance,
7
- publicAPI,
8
6
  params,
9
7
  models
10
8
  }) => {
@@ -20,7 +18,7 @@ export const useTreeViewExpansion = ({
20
18
  models.expandedItems.setControlledValue(value);
21
19
  };
22
20
  const isItemExpanded = React.useCallback(itemId => expandedItemsMap.has(itemId), [expandedItemsMap]);
23
- const isItemExpandable = React.useCallback(itemId => !!instance.getNode(itemId)?.expandable, [instance]);
21
+ const isItemExpandable = React.useCallback(itemId => !!instance.getItemMeta(itemId)?.expandable, [instance]);
24
22
  const toggleItemExpansion = useEventCallback((event, itemId) => {
25
23
  const isExpandedBefore = instance.isItemExpanded(itemId);
26
24
  instance.setItemExpansion(event, itemId, !isExpandedBefore);
@@ -42,8 +40,8 @@ export const useTreeViewExpansion = ({
42
40
  setExpandedItems(event, newExpanded);
43
41
  });
44
42
  const expandAllSiblings = (event, itemId) => {
45
- const node = instance.getNode(itemId);
46
- const siblings = instance.getChildrenIds(node.parentId);
43
+ const itemMeta = instance.getItemMeta(itemId);
44
+ const siblings = instance.getItemOrderedChildrenIds(itemMeta.parentId);
47
45
  const diff = siblings.filter(child => instance.isItemExpandable(child) && !instance.isItemExpanded(child));
48
46
  const newExpanded = models.expandedItems.value.concat(diff);
49
47
  if (diff.length > 0) {
@@ -55,16 +53,18 @@ export const useTreeViewExpansion = ({
55
53
  setExpandedItems(event, newExpanded);
56
54
  }
57
55
  };
58
- populateInstance(instance, {
59
- isItemExpanded,
60
- isItemExpandable,
61
- setItemExpansion,
62
- toggleItemExpansion,
63
- expandAllSiblings
64
- });
65
- populatePublicAPI(publicAPI, {
66
- setItemExpansion
67
- });
56
+ return {
57
+ publicAPI: {
58
+ setItemExpansion
59
+ },
60
+ instance: {
61
+ isItemExpanded,
62
+ isItemExpandable,
63
+ setItemExpansion,
64
+ toggleItemExpansion,
65
+ expandAllSiblings
66
+ }
67
+ };
68
68
  };
69
69
  useTreeViewExpansion.models = {
70
70
  expandedItems: {