@mui/x-tree-view 7.1.1 → 7.2.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 +86 -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 +25 -26
  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 +66 -41
  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 +25 -26
  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 +66 -41
  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 +25 -26
  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 +66 -41
  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
@@ -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.2.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: {
@@ -2,13 +2,13 @@ import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
3
  import useEventCallback from '@mui/utils/useEventCallback';
4
4
  import ownerDocument from '@mui/utils/ownerDocument';
5
- import { populateInstance, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
6
5
  import { useInstanceEventHandler } from '../../hooks/useInstanceEventHandler';
7
6
  import { getActiveElement } from '../../utils/utils';
7
+ import { getFirstNavigableItem } from '../../utils/tree';
8
8
  const useTabbableItemId = (instance, selectedItems) => {
9
9
  const isItemVisible = itemId => {
10
- const node = instance.getNode(itemId);
11
- return node && (node.parentId == null || instance.isItemExpanded(node.parentId));
10
+ const itemMeta = instance.getItemMeta(itemId);
11
+ return itemMeta && (itemMeta.parentId == null || instance.isItemExpanded(itemMeta.parentId));
12
12
  };
13
13
  let tabbableItemId;
14
14
  if (Array.isArray(selectedItems)) {
@@ -17,13 +17,12 @@ const useTabbableItemId = (instance, selectedItems) => {
17
17
  tabbableItemId = selectedItems;
18
18
  }
19
19
  if (tabbableItemId == null) {
20
- tabbableItemId = instance.getNavigableChildrenIds(null)[0];
20
+ tabbableItemId = getFirstNavigableItem(instance);
21
21
  }
22
22
  return tabbableItemId;
23
23
  };
24
24
  export const useTreeViewFocus = ({
25
25
  instance,
26
- publicAPI,
27
26
  params,
28
27
  state,
29
28
  setState,
@@ -42,12 +41,12 @@ export const useTreeViewFocus = ({
42
41
  const isTreeViewFocused = React.useCallback(() => !!rootRef.current && rootRef.current.contains(getActiveElement(ownerDocument(rootRef.current))), [rootRef]);
43
42
  const isItemFocused = React.useCallback(itemId => state.focusedItemId === itemId && isTreeViewFocused(), [state.focusedItemId, isTreeViewFocused]);
44
43
  const isItemVisible = itemId => {
45
- const node = instance.getNode(itemId);
46
- return node && (node.parentId == null || instance.isItemExpanded(node.parentId));
44
+ const itemMeta = instance.getItemMeta(itemId);
45
+ return itemMeta && (itemMeta.parentId == null || instance.isItemExpanded(itemMeta.parentId));
47
46
  };
48
47
  const innerFocusItem = (event, itemId) => {
49
- const node = instance.getNode(itemId);
50
- const itemElement = document.getElementById(instance.getTreeItemId(itemId, node.idAttribute));
48
+ const itemMeta = instance.getItemMeta(itemId);
49
+ const itemElement = document.getElementById(instance.getTreeItemIdAttribute(itemId, itemMeta.idAttribute));
51
50
  if (itemElement) {
52
51
  itemElement.focus();
53
52
  }
@@ -70,7 +69,7 @@ export const useTreeViewFocus = ({
70
69
  itemToFocusId = models.selectedItems.value;
71
70
  }
72
71
  if (itemToFocusId == null) {
73
- itemToFocusId = instance.getNavigableChildrenIds(null)[0];
72
+ itemToFocusId = getFirstNavigableItem(instance);
74
73
  }
75
74
  innerFocusItem(event, itemToFocusId);
76
75
  });
@@ -78,9 +77,9 @@ export const useTreeViewFocus = ({
78
77
  if (state.focusedItemId == null) {
79
78
  return;
80
79
  }
81
- const node = instance.getNode(state.focusedItemId);
82
- if (node) {
83
- const itemElement = document.getElementById(instance.getTreeItemId(state.focusedItemId, node.idAttribute));
80
+ const itemMeta = instance.getItemMeta(state.focusedItemId);
81
+ if (itemMeta) {
82
+ const itemElement = document.getElementById(instance.getTreeItemIdAttribute(state.focusedItemId, itemMeta.idAttribute));
84
83
  if (itemElement) {
85
84
  itemElement.blur();
86
85
  }
@@ -88,16 +87,6 @@ export const useTreeViewFocus = ({
88
87
  setFocusedItemId(null);
89
88
  });
90
89
  const canItemBeTabbed = itemId => itemId === tabbableItemId;
91
- populateInstance(instance, {
92
- isItemFocused,
93
- canItemBeTabbed,
94
- focusItem,
95
- focusDefaultItem,
96
- removeFocusedItem
97
- });
98
- populatePublicAPI(publicAPI, {
99
- focusItem
100
- });
101
90
  useInstanceEventHandler(instance, 'removeItem', ({
102
91
  id
103
92
  }) => {
@@ -112,13 +101,23 @@ export const useTreeViewFocus = ({
112
101
  instance.focusDefaultItem(event);
113
102
  }
114
103
  };
115
- const focusedItem = instance.getNode(state.focusedItemId);
116
- const activeDescendant = focusedItem ? instance.getTreeItemId(focusedItem.id, focusedItem.idAttribute) : null;
104
+ const focusedItem = instance.getItemMeta(state.focusedItemId);
105
+ const activeDescendant = focusedItem ? instance.getTreeItemIdAttribute(focusedItem.id, focusedItem.idAttribute) : null;
117
106
  return {
118
107
  getRootProps: otherHandlers => ({
119
108
  onFocus: createHandleFocus(otherHandlers),
120
109
  'aria-activedescendant': activeDescendant ?? undefined
121
- })
110
+ }),
111
+ publicAPI: {
112
+ focusItem
113
+ },
114
+ instance: {
115
+ isItemFocused,
116
+ canItemBeTabbed,
117
+ focusItem,
118
+ focusDefaultItem,
119
+ removeFocusedItem
120
+ }
122
121
  };
123
122
  };
124
123
  useTreeViewFocus.getInitialState = () => ({
@@ -1,19 +1,17 @@
1
1
  import * as React from 'react';
2
2
  import useId from '@mui/utils/useId';
3
- import { populateInstance } from '../../useTreeView/useTreeView.utils';
4
3
  export const useTreeViewId = ({
5
- instance,
6
4
  params
7
5
  }) => {
8
6
  const treeId = useId(params.id);
9
- const getTreeItemId = React.useCallback((itemId, idAttribute) => idAttribute ?? `${treeId}-${itemId}`, [treeId]);
10
- populateInstance(instance, {
11
- getTreeItemId
12
- });
7
+ const getTreeItemIdAttribute = React.useCallback((itemId, idAttribute) => idAttribute ?? `${treeId}-${itemId}`, [treeId]);
13
8
  return {
14
9
  getRootProps: () => ({
15
10
  id: treeId
16
- })
11
+ }),
12
+ instance: {
13
+ getTreeItemIdAttribute
14
+ }
17
15
  };
18
16
  };
19
17
  useTreeViewId.params = {