@mui/x-tree-view 7.0.0-beta.7 → 7.1.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 (136) hide show
  1. package/CHANGELOG.md +266 -12
  2. package/README.md +1 -1
  3. package/RichTreeView/RichTreeView.js +15 -17
  4. package/RichTreeView/RichTreeView.types.d.ts +1 -1
  5. package/SimpleTreeView/SimpleTreeView.js +3 -4
  6. package/SimpleTreeView/SimpleTreeView.plugins.d.ts +1 -1
  7. package/SimpleTreeView/SimpleTreeView.plugins.js +2 -2
  8. package/TreeItem/TreeItem.js +43 -35
  9. package/TreeItem/TreeItem.types.d.ts +3 -3
  10. package/TreeItem/TreeItemContent.d.ts +7 -7
  11. package/TreeItem/TreeItemContent.js +10 -10
  12. package/TreeItem/treeItemClasses.d.ts +1 -1
  13. package/TreeItem/useTreeItemState.d.ts +1 -1
  14. package/TreeItem/useTreeItemState.js +13 -13
  15. package/TreeItem2/TreeItem2.js +16 -17
  16. package/TreeItem2Icon/TreeItem2Icon.js +5 -6
  17. package/TreeItem2Icon/TreeItem2Icon.types.d.ts +4 -4
  18. package/TreeItem2Provider/TreeItem2Provider.js +3 -3
  19. package/TreeItem2Provider/TreeItem2Provider.types.d.ts +1 -1
  20. package/TreeView/TreeView.d.ts +1 -1
  21. package/TreeView/TreeView.js +1 -1
  22. package/hooks/useTreeItem2Utils/useTreeItem2Utils.d.ts +2 -2
  23. package/hooks/useTreeItem2Utils/useTreeItem2Utils.js +12 -12
  24. package/hooks/useTreeViewApiRef.d.ts +1 -1
  25. package/index.js +1 -1
  26. package/internals/TreeViewProvider/DescendantProvider.d.ts +1 -1
  27. package/internals/TreeViewProvider/DescendantProvider.js +1 -1
  28. package/internals/hooks/useInstanceEventHandler.js +5 -10
  29. package/internals/index.d.ts +2 -2
  30. package/internals/models/plugin.d.ts +1 -1
  31. package/internals/plugins/defaultPlugins.d.ts +3 -3
  32. package/internals/plugins/defaultPlugins.js +2 -2
  33. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +17 -24
  34. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +6 -6
  35. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +76 -58
  36. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +9 -8
  37. package/internals/plugins/useTreeViewIcons/useTreeViewIcons.types.d.ts +6 -6
  38. package/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
  39. package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +2 -2
  40. package/internals/plugins/useTreeViewItems/index.d.ts +2 -0
  41. package/internals/plugins/useTreeViewItems/index.js +1 -0
  42. package/internals/plugins/useTreeViewItems/useTreeViewItems.d.ts +3 -0
  43. package/{modern/internals/plugins/useTreeViewNodes/useTreeViewNodes.js → internals/plugins/useTreeViewItems/useTreeViewItems.js} +42 -33
  44. package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +99 -0
  45. package/internals/plugins/useTreeViewJSXItems/index.d.ts +2 -0
  46. package/internals/plugins/useTreeViewJSXItems/index.js +1 -0
  47. package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.d.ts +3 -0
  48. package/{modern/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js → internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js} +41 -40
  49. package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.types.d.ts +18 -0
  50. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +85 -96
  51. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +6 -3
  52. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +44 -47
  53. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +8 -8
  54. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.d.ts +7 -7
  55. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +5 -5
  56. package/internals/useTreeView/useTreeView.js +5 -6
  57. package/internals/useTreeView/useTreeView.utils.d.ts +5 -5
  58. package/internals/useTreeView/useTreeView.utils.js +18 -18
  59. package/internals/utils/extractPluginParamsFromProps.js +2 -2
  60. package/internals/utils/utils.js +1 -0
  61. package/modern/RichTreeView/RichTreeView.js +11 -11
  62. package/modern/SimpleTreeView/SimpleTreeView.js +1 -1
  63. package/modern/SimpleTreeView/SimpleTreeView.plugins.js +2 -2
  64. package/modern/TreeItem/TreeItem.js +31 -22
  65. package/modern/TreeItem/TreeItemContent.js +10 -10
  66. package/modern/TreeItem/useTreeItemState.js +13 -13
  67. package/modern/TreeItem2/TreeItem2.js +11 -11
  68. package/modern/TreeItem2Provider/TreeItem2Provider.js +3 -3
  69. package/modern/TreeView/TreeView.js +1 -1
  70. package/modern/hooks/useTreeItem2Utils/useTreeItem2Utils.js +12 -12
  71. package/modern/index.js +1 -1
  72. package/modern/internals/TreeViewProvider/DescendantProvider.js +1 -1
  73. package/modern/internals/plugins/defaultPlugins.js +2 -2
  74. package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +14 -14
  75. package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +74 -53
  76. package/modern/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
  77. package/modern/internals/plugins/useTreeViewItems/index.js +1 -0
  78. package/{internals/plugins/useTreeViewNodes/useTreeViewNodes.js → modern/internals/plugins/useTreeViewItems/useTreeViewItems.js} +46 -41
  79. package/modern/internals/plugins/useTreeViewJSXItems/index.js +1 -0
  80. package/{internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js → modern/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js} +41 -41
  81. package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +85 -94
  82. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +40 -40
  83. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +5 -5
  84. package/modern/internals/useTreeView/useTreeView.js +3 -4
  85. package/modern/internals/useTreeView/useTreeView.utils.js +18 -18
  86. package/modern/internals/utils/utils.js +1 -0
  87. package/modern/useTreeItem2/useTreeItem2.js +23 -12
  88. package/node/RichTreeView/RichTreeView.js +11 -11
  89. package/node/SimpleTreeView/SimpleTreeView.js +1 -1
  90. package/node/SimpleTreeView/SimpleTreeView.plugins.js +2 -2
  91. package/node/TreeItem/TreeItem.js +31 -22
  92. package/node/TreeItem/TreeItemContent.js +10 -10
  93. package/node/TreeItem/useTreeItemState.js +13 -13
  94. package/node/TreeItem2/TreeItem2.js +11 -11
  95. package/node/TreeItem2Provider/TreeItem2Provider.js +3 -3
  96. package/node/TreeView/TreeView.js +1 -1
  97. package/node/hooks/useTreeItem2Utils/useTreeItem2Utils.js +12 -12
  98. package/node/index.js +1 -1
  99. package/node/internals/TreeViewProvider/DescendantProvider.js +1 -1
  100. package/node/internals/plugins/defaultPlugins.js +2 -2
  101. package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +14 -14
  102. package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +74 -53
  103. package/node/internals/plugins/useTreeViewId/useTreeViewId.js +1 -1
  104. package/node/internals/plugins/useTreeViewItems/index.js +12 -0
  105. package/node/internals/plugins/{useTreeViewNodes/useTreeViewNodes.js → useTreeViewItems/useTreeViewItems.js} +44 -35
  106. package/node/internals/plugins/useTreeViewJSXItems/index.js +12 -0
  107. package/node/internals/plugins/{useTreeViewJSXNodes/useTreeViewJSXNodes.js → useTreeViewJSXItems/useTreeViewJSXItems.js} +43 -42
  108. package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +84 -93
  109. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +39 -39
  110. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +5 -5
  111. package/node/internals/useTreeView/useTreeView.js +3 -4
  112. package/node/internals/useTreeView/useTreeView.utils.js +23 -23
  113. package/node/internals/utils/utils.js +1 -0
  114. package/node/useTreeItem2/useTreeItem2.js +23 -12
  115. package/package.json +5 -5
  116. package/useTreeItem2/useTreeItem2.d.ts +1 -1
  117. package/useTreeItem2/useTreeItem2.js +26 -18
  118. package/useTreeItem2/useTreeItem2.types.d.ts +9 -7
  119. package/internals/plugins/useTreeViewJSXNodes/index.d.ts +0 -2
  120. package/internals/plugins/useTreeViewJSXNodes/index.js +0 -1
  121. package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.d.ts +0 -3
  122. package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.types.d.ts +0 -18
  123. package/internals/plugins/useTreeViewNodes/index.d.ts +0 -2
  124. package/internals/plugins/useTreeViewNodes/index.js +0 -1
  125. package/internals/plugins/useTreeViewNodes/useTreeViewNodes.d.ts +0 -3
  126. package/internals/plugins/useTreeViewNodes/useTreeViewNodes.types.d.ts +0 -88
  127. package/modern/internals/plugins/useTreeViewJSXNodes/index.js +0 -1
  128. package/modern/internals/plugins/useTreeViewNodes/index.js +0 -1
  129. package/node/internals/plugins/useTreeViewJSXNodes/index.js +0 -12
  130. package/node/internals/plugins/useTreeViewNodes/index.js +0 -12
  131. /package/internals/plugins/{useTreeViewJSXNodes/useTreeViewJSXNodes.types.js → useTreeViewItems/useTreeViewItems.types.js} +0 -0
  132. /package/internals/plugins/{useTreeViewNodes/useTreeViewNodes.types.js → useTreeViewJSXItems/useTreeViewJSXItems.types.js} +0 -0
  133. /package/modern/internals/plugins/{useTreeViewJSXNodes/useTreeViewJSXNodes.types.js → useTreeViewItems/useTreeViewItems.types.js} +0 -0
  134. /package/modern/internals/plugins/{useTreeViewNodes/useTreeViewNodes.types.js → useTreeViewJSXItems/useTreeViewJSXItems.types.js} +0 -0
  135. /package/node/internals/plugins/{useTreeViewJSXNodes/useTreeViewJSXNodes.types.js → useTreeViewItems/useTreeViewItems.types.js} +0 -0
  136. /package/node/internals/plugins/{useTreeViewNodes/useTreeViewNodes.types.js → useTreeViewJSXItems/useTreeViewJSXItems.types.js} +0 -0
@@ -11,11 +11,11 @@ export const useTreeViewExpansion = ({
11
11
  params.onExpandedItemsChange?.(event, value);
12
12
  models.expandedItems.setControlledValue(value);
13
13
  };
14
- const isNodeExpanded = React.useCallback(nodeId => {
15
- return Array.isArray(models.expandedItems.value) ? models.expandedItems.value.indexOf(nodeId) !== -1 : false;
14
+ const isItemExpanded = React.useCallback(itemId => {
15
+ return Array.isArray(models.expandedItems.value) ? models.expandedItems.value.indexOf(itemId) !== -1 : false;
16
16
  }, [models.expandedItems.value]);
17
- const isNodeExpandable = React.useCallback(nodeId => !!instance.getNode(nodeId)?.expandable, [instance]);
18
- const toggleNodeExpansion = useEventCallback((event, itemId) => {
17
+ const isItemExpandable = React.useCallback(itemId => !!instance.getNode(itemId)?.expandable, [instance]);
18
+ const toggleItemExpansion = useEventCallback((event, itemId) => {
19
19
  if (itemId == null) {
20
20
  return;
21
21
  }
@@ -31,24 +31,24 @@ export const useTreeViewExpansion = ({
31
31
  }
32
32
  setExpandedItems(event, newExpanded);
33
33
  });
34
- const expandAllSiblings = (event, nodeId) => {
35
- const node = instance.getNode(nodeId);
34
+ const expandAllSiblings = (event, itemId) => {
35
+ const node = instance.getNode(itemId);
36
36
  const siblings = instance.getChildrenIds(node.parentId);
37
- const diff = siblings.filter(child => instance.isNodeExpandable(child) && !instance.isNodeExpanded(child));
37
+ const diff = siblings.filter(child => instance.isItemExpandable(child) && !instance.isItemExpanded(child));
38
38
  const newExpanded = models.expandedItems.value.concat(diff);
39
39
  if (diff.length > 0) {
40
40
  if (params.onItemExpansionToggle) {
41
- diff.forEach(newlyExpandedNodeId => {
42
- params.onItemExpansionToggle(event, newlyExpandedNodeId, true);
41
+ diff.forEach(newlyExpandedItemId => {
42
+ params.onItemExpansionToggle(event, newlyExpandedItemId, true);
43
43
  });
44
44
  }
45
45
  setExpandedItems(event, newExpanded);
46
46
  }
47
47
  };
48
48
  populateInstance(instance, {
49
- isNodeExpanded,
50
- isNodeExpandable,
51
- toggleNodeExpansion,
49
+ isItemExpanded,
50
+ isItemExpandable,
51
+ toggleItemExpansion,
52
52
  expandAllSiblings
53
53
  });
54
54
  };
@@ -57,9 +57,9 @@ useTreeViewExpansion.models = {
57
57
  getDefaultValue: params => params.defaultExpandedItems
58
58
  }
59
59
  };
60
- const DEFAULT_EXPANDED_NODES = [];
60
+ const DEFAULT_EXPANDED_ITEMS = [];
61
61
  useTreeViewExpansion.getDefaultizedParams = params => _extends({}, params, {
62
- defaultExpandedItems: params.defaultExpandedItems ?? DEFAULT_EXPANDED_NODES
62
+ defaultExpandedItems: params.defaultExpandedItems ?? DEFAULT_EXPANDED_ITEMS
63
63
  });
64
64
  useTreeViewExpansion.params = {
65
65
  expandedItems: true,
@@ -5,6 +5,22 @@ import ownerDocument from '@mui/utils/ownerDocument';
5
5
  import { populateInstance, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
6
6
  import { useInstanceEventHandler } from '../../hooks/useInstanceEventHandler';
7
7
  import { getActiveElement } from '../../utils/utils';
8
+ const useTabbableItemId = (instance, selectedItems) => {
9
+ const isItemVisible = itemId => {
10
+ const node = instance.getNode(itemId);
11
+ return node && (node.parentId == null || instance.isItemExpanded(node.parentId));
12
+ };
13
+ let tabbableItemId;
14
+ if (Array.isArray(selectedItems)) {
15
+ tabbableItemId = selectedItems.find(isItemVisible);
16
+ } else if (selectedItems != null && isItemVisible(selectedItems)) {
17
+ tabbableItemId = selectedItems;
18
+ }
19
+ if (tabbableItemId == null) {
20
+ tabbableItemId = instance.getNavigableChildrenIds(null)[0];
21
+ }
22
+ return tabbableItemId;
23
+ };
8
24
  export const useTreeViewFocus = ({
9
25
  instance,
10
26
  publicAPI,
@@ -14,94 +30,99 @@ export const useTreeViewFocus = ({
14
30
  models,
15
31
  rootRef
16
32
  }) => {
17
- const setFocusedNodeId = useEventCallback(nodeId => {
18
- const cleanNodeId = typeof nodeId === 'function' ? nodeId(state.focusedNodeId) : nodeId;
19
- if (state.focusedNodeId !== cleanNodeId) {
33
+ const tabbableItemId = useTabbableItemId(instance, models.selectedItems.value);
34
+ const setFocusedItemId = useEventCallback(itemId => {
35
+ const cleanItemId = typeof itemId === 'function' ? itemId(state.focusedItemId) : itemId;
36
+ if (state.focusedItemId !== cleanItemId) {
20
37
  setState(prevState => _extends({}, prevState, {
21
- focusedNodeId: cleanNodeId
38
+ focusedItemId: cleanItemId
22
39
  }));
23
40
  }
24
41
  });
25
- const isTreeViewFocused = React.useCallback(() => !!rootRef.current && rootRef.current === getActiveElement(ownerDocument(rootRef.current)), [rootRef]);
26
- const isNodeFocused = React.useCallback(nodeId => state.focusedNodeId === nodeId && isTreeViewFocused(), [state.focusedNodeId, isTreeViewFocused]);
27
- const isNodeVisible = nodeId => {
28
- const node = instance.getNode(nodeId);
29
- return node && (node.parentId == null || instance.isNodeExpanded(node.parentId));
42
+ const isTreeViewFocused = React.useCallback(() => !!rootRef.current && rootRef.current.contains(getActiveElement(ownerDocument(rootRef.current))), [rootRef]);
43
+ const isItemFocused = React.useCallback(itemId => state.focusedItemId === itemId && isTreeViewFocused(), [state.focusedItemId, isTreeViewFocused]);
44
+ const isItemVisible = itemId => {
45
+ const node = instance.getNode(itemId);
46
+ return node && (node.parentId == null || instance.isItemExpanded(node.parentId));
30
47
  };
31
- const focusItem = useEventCallback((event, nodeId) => {
32
- // if we receive a nodeId, and it is visible, the focus will be set to it
33
- if (nodeId && isNodeVisible(nodeId)) {
34
- if (!isTreeViewFocused()) {
35
- instance.focusRoot();
36
- }
37
- setFocusedNodeId(nodeId);
38
- if (params.onItemFocus) {
39
- params.onItemFocus(event, nodeId);
40
- }
48
+ const innerFocusItem = (event, itemId) => {
49
+ const node = instance.getNode(itemId);
50
+ const itemElement = document.getElementById(instance.getTreeItemId(itemId, node.idAttribute));
51
+ if (itemElement) {
52
+ itemElement.focus();
53
+ }
54
+ setFocusedItemId(itemId);
55
+ if (params.onItemFocus) {
56
+ params.onItemFocus(event, itemId);
57
+ }
58
+ };
59
+ const focusItem = useEventCallback((event, itemId) => {
60
+ // If we receive an itemId, and it is visible, the focus will be set to it
61
+ if (isItemVisible(itemId)) {
62
+ innerFocusItem(event, itemId);
41
63
  }
42
64
  });
43
- const focusDefaultNode = useEventCallback(event => {
44
- let nodeToFocusId;
65
+ const focusDefaultItem = useEventCallback(event => {
66
+ let itemToFocusId;
45
67
  if (Array.isArray(models.selectedItems.value)) {
46
- nodeToFocusId = models.selectedItems.value.find(isNodeVisible);
47
- } else if (models.selectedItems.value != null && isNodeVisible(models.selectedItems.value)) {
48
- nodeToFocusId = models.selectedItems.value;
68
+ itemToFocusId = models.selectedItems.value.find(isItemVisible);
69
+ } else if (models.selectedItems.value != null && isItemVisible(models.selectedItems.value)) {
70
+ itemToFocusId = models.selectedItems.value;
49
71
  }
50
- if (nodeToFocusId == null) {
51
- nodeToFocusId = instance.getNavigableChildrenIds(null)[0];
52
- }
53
- setFocusedNodeId(nodeToFocusId);
54
- if (params.onItemFocus) {
55
- params.onItemFocus(event, nodeToFocusId);
72
+ if (itemToFocusId == null) {
73
+ itemToFocusId = instance.getNavigableChildrenIds(null)[0];
56
74
  }
75
+ innerFocusItem(event, itemToFocusId);
57
76
  });
58
- const focusRoot = useEventCallback(() => {
59
- rootRef.current?.focus({
60
- preventScroll: true
61
- });
77
+ const removeFocusedItem = useEventCallback(() => {
78
+ if (state.focusedItemId == null) {
79
+ return;
80
+ }
81
+ const node = instance.getNode(state.focusedItemId);
82
+ if (node) {
83
+ const itemElement = document.getElementById(instance.getTreeItemId(state.focusedItemId, node.idAttribute));
84
+ if (itemElement) {
85
+ itemElement.blur();
86
+ }
87
+ }
88
+ setFocusedItemId(null);
62
89
  });
90
+ const canItemBeTabbed = itemId => itemId === tabbableItemId;
63
91
  populateInstance(instance, {
64
- isNodeFocused,
92
+ isItemFocused,
93
+ canItemBeTabbed,
65
94
  focusItem,
66
- focusRoot,
67
- focusDefaultNode
95
+ focusDefaultItem,
96
+ removeFocusedItem
68
97
  });
69
98
  populatePublicAPI(publicAPI, {
70
99
  focusItem
71
100
  });
72
- useInstanceEventHandler(instance, 'removeNode', ({
101
+ useInstanceEventHandler(instance, 'removeItem', ({
73
102
  id
74
103
  }) => {
75
- setFocusedNodeId(oldFocusedNodeId => {
76
- if (oldFocusedNodeId === id && rootRef.current === ownerDocument(rootRef.current).activeElement) {
77
- return instance.getChildrenIds(null)[0];
78
- }
79
- return oldFocusedNodeId;
80
- });
104
+ if (state.focusedItemId === id) {
105
+ instance.focusDefaultItem(null);
106
+ }
81
107
  });
82
108
  const createHandleFocus = otherHandlers => event => {
83
109
  otherHandlers.onFocus?.(event);
84
110
  // if the event bubbled (which is React specific) we don't want to steal focus
85
111
  if (event.target === event.currentTarget) {
86
- instance.focusDefaultNode(event);
112
+ instance.focusDefaultItem(event);
87
113
  }
88
114
  };
89
- const createHandleBlur = otherHandlers => event => {
90
- otherHandlers.onBlur?.(event);
91
- setFocusedNodeId(null);
92
- };
93
- const focusedNode = instance.getNode(state.focusedNodeId);
94
- const activeDescendant = focusedNode ? instance.getTreeItemId(focusedNode.id, focusedNode.idAttribute) : null;
115
+ const focusedItem = instance.getNode(state.focusedItemId);
116
+ const activeDescendant = focusedItem ? instance.getTreeItemId(focusedItem.id, focusedItem.idAttribute) : null;
95
117
  return {
96
118
  getRootProps: otherHandlers => ({
97
119
  onFocus: createHandleFocus(otherHandlers),
98
- onBlur: createHandleBlur(otherHandlers),
99
120
  'aria-activedescendant': activeDescendant ?? undefined
100
121
  })
101
122
  };
102
123
  };
103
124
  useTreeViewFocus.getInitialState = () => ({
104
- focusedNodeId: null
125
+ focusedItemId: null
105
126
  });
106
127
  useTreeViewFocus.params = {
107
128
  onItemFocus: true
@@ -6,7 +6,7 @@ export const useTreeViewId = ({
6
6
  params
7
7
  }) => {
8
8
  const treeId = useId(params.id);
9
- const getTreeItemId = React.useCallback((nodeId, idAttribute) => idAttribute ?? `${treeId}-${nodeId}`, [treeId]);
9
+ const getTreeItemId = React.useCallback((itemId, idAttribute) => idAttribute ?? `${treeId}-${itemId}`, [treeId]);
10
10
  populateInstance(instance, {
11
11
  getTreeItemId
12
12
  });
@@ -0,0 +1 @@
1
+ export { useTreeViewItems } from './useTreeViewItems';
@@ -1,9 +1,8 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
- import useEventCallback from '@mui/utils/useEventCallback';
4
3
  import { populateInstance, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
5
4
  import { publishTreeViewEvent } from '../../utils/publishTreeViewEvent';
6
- const updateNodesState = ({
5
+ const updateItemsState = ({
7
6
  items,
8
7
  isItemDisabled,
9
8
  getItemLabel,
@@ -12,7 +11,6 @@ const updateNodesState = ({
12
11
  const nodeMap = {};
13
12
  const itemMap = {};
14
13
  const processItem = (item, index, parentId) => {
15
- var _item$children, _item$children2;
16
14
  const id = getItemId ? getItemId(item) : item.id;
17
15
  if (id == null) {
18
16
  throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', 'An item was provided without id in the `items` prop:', JSON.stringify(item)].join('\n'));
@@ -30,13 +28,13 @@ const updateNodesState = ({
30
28
  index,
31
29
  parentId,
32
30
  idAttribute: undefined,
33
- expandable: !!((_item$children = item.children) != null && _item$children.length),
31
+ expandable: !!item.children?.length,
34
32
  disabled: isItemDisabled ? isItemDisabled(item) : false
35
33
  };
36
34
  itemMap[id] = item;
37
35
  return {
38
36
  id,
39
- children: (_item$children2 = item.children) == null ? void 0 : _item$children2.map((child, childIndex) => processItem(child, childIndex, id))
37
+ children: item.children?.map((child, childIndex) => processItem(child, childIndex, id))
40
38
  };
41
39
  };
42
40
  const nodeTree = items.map((item, itemIndex) => processItem(item, itemIndex, null));
@@ -46,22 +44,22 @@ const updateNodesState = ({
46
44
  itemMap
47
45
  };
48
46
  };
49
- export const useTreeViewNodes = ({
47
+ export const useTreeViewItems = ({
50
48
  instance,
51
49
  publicAPI,
52
50
  params,
53
51
  state,
54
52
  setState
55
53
  }) => {
56
- const getNode = React.useCallback(nodeId => state.nodes.nodeMap[nodeId], [state.nodes.nodeMap]);
57
- const getItem = React.useCallback(nodeId => state.nodes.itemMap[nodeId], [state.nodes.itemMap]);
58
- const isNodeDisabled = React.useCallback(nodeId => {
59
- if (nodeId == null) {
54
+ const getNode = React.useCallback(itemId => state.items.nodeMap[itemId], [state.items.nodeMap]);
55
+ const getItem = React.useCallback(itemId => state.items.itemMap[itemId], [state.items.itemMap]);
56
+ const isItemDisabled = React.useCallback(itemId => {
57
+ if (itemId == null) {
60
58
  return false;
61
59
  }
62
- let node = instance.getNode(nodeId);
60
+ let node = instance.getNode(itemId);
63
61
 
64
- // This can be called before the node has been added to the node map.
62
+ // This can be called before the item has been added to the item map.
65
63
  if (!node) {
66
64
  return false;
67
65
  }
@@ -76,56 +74,66 @@ export const useTreeViewNodes = ({
76
74
  }
77
75
  return false;
78
76
  }, [instance]);
79
- const getChildrenIds = useEventCallback(nodeId => Object.values(state.nodes.nodeMap).filter(node => node.parentId === nodeId).sort((a, b) => a.index - b.index).map(child => child.id));
80
- const getNavigableChildrenIds = nodeId => {
81
- let childrenIds = instance.getChildrenIds(nodeId);
77
+ const getChildrenIds = React.useCallback(itemId => Object.values(state.items.nodeMap).filter(item => item.parentId === itemId).sort((a, b) => a.index - b.index).map(child => child.id), [state.items.nodeMap]);
78
+ const getNavigableChildrenIds = itemId => {
79
+ let childrenIds = instance.getChildrenIds(itemId);
82
80
  if (!params.disabledItemsFocusable) {
83
- childrenIds = childrenIds.filter(node => !instance.isNodeDisabled(node));
81
+ childrenIds = childrenIds.filter(item => !instance.isItemDisabled(item));
84
82
  }
85
83
  return childrenIds;
86
84
  };
85
+ const areItemUpdatesPreventedRef = React.useRef(false);
86
+ const preventItemUpdates = React.useCallback(() => {
87
+ areItemUpdatesPreventedRef.current = true;
88
+ }, []);
89
+ const areItemUpdatesPrevented = React.useCallback(() => areItemUpdatesPreventedRef.current, []);
87
90
  React.useEffect(() => {
91
+ if (instance.areItemUpdatesPrevented()) {
92
+ return;
93
+ }
88
94
  setState(prevState => {
89
- const newState = updateNodesState({
95
+ const newState = updateItemsState({
90
96
  items: params.items,
91
97
  isItemDisabled: params.isItemDisabled,
92
98
  getItemId: params.getItemId,
93
99
  getItemLabel: params.getItemLabel
94
100
  });
95
- Object.values(prevState.nodes.nodeMap).forEach(node => {
96
- if (!newState.nodeMap[node.id]) {
97
- publishTreeViewEvent(instance, 'removeNode', {
98
- id: node.id
101
+ Object.values(prevState.items.nodeMap).forEach(item => {
102
+ if (!newState.nodeMap[item.id]) {
103
+ publishTreeViewEvent(instance, 'removeItem', {
104
+ id: item.id
99
105
  });
100
106
  }
101
107
  });
102
108
  return _extends({}, prevState, {
103
- nodes: newState
109
+ items: newState
104
110
  });
105
111
  });
106
112
  }, [instance, setState, params.items, params.isItemDisabled, params.getItemId, params.getItemLabel]);
107
- const getNodesToRender = () => {
108
- const getPropsFromNodeId = ({
113
+ const getItemsToRender = () => {
114
+ const getPropsFromItemId = ({
109
115
  id,
110
116
  children
111
117
  }) => {
112
- const node = state.nodes.nodeMap[id];
118
+ const item = state.items.nodeMap[id];
113
119
  return {
114
- label: node.label,
115
- nodeId: node.id,
116
- id: node.idAttribute,
117
- children: children == null ? void 0 : children.map(getPropsFromNodeId)
120
+ label: item.label,
121
+ itemId: item.id,
122
+ id: item.idAttribute,
123
+ children: children?.map(getPropsFromItemId)
118
124
  };
119
125
  };
120
- return state.nodes.nodeTree.map(getPropsFromNodeId);
126
+ return state.items.nodeTree.map(getPropsFromItemId);
121
127
  };
122
128
  populateInstance(instance, {
123
129
  getNode,
124
130
  getItem,
125
- getNodesToRender,
131
+ getItemsToRender,
126
132
  getChildrenIds,
127
133
  getNavigableChildrenIds,
128
- isNodeDisabled
134
+ isItemDisabled,
135
+ preventItemUpdates,
136
+ areItemUpdatesPrevented
129
137
  });
130
138
  populatePublicAPI(publicAPI, {
131
139
  getItem
@@ -136,21 +144,18 @@ export const useTreeViewNodes = ({
136
144
  }
137
145
  };
138
146
  };
139
- useTreeViewNodes.getInitialState = params => ({
140
- nodes: updateNodesState({
147
+ useTreeViewItems.getInitialState = params => ({
148
+ items: updateItemsState({
141
149
  items: params.items,
142
150
  isItemDisabled: params.isItemDisabled,
143
151
  getItemId: params.getItemId,
144
152
  getItemLabel: params.getItemLabel
145
153
  })
146
154
  });
147
- useTreeViewNodes.getDefaultizedParams = params => {
148
- var _params$disabledItems;
149
- return _extends({}, params, {
150
- disabledItemsFocusable: (_params$disabledItems = params.disabledItemsFocusable) != null ? _params$disabledItems : false
151
- });
152
- };
153
- useTreeViewNodes.params = {
155
+ useTreeViewItems.getDefaultizedParams = params => _extends({}, params, {
156
+ disabledItemsFocusable: params.disabledItemsFocusable ?? false
157
+ });
158
+ useTreeViewItems.params = {
154
159
  disabledItemsFocusable: true,
155
160
  items: true,
156
161
  isItemDisabled: true,
@@ -0,0 +1 @@
1
+ export { useTreeViewJSXItems } from './useTreeViewJSXItems';
@@ -7,68 +7,69 @@ import { publishTreeViewEvent } from '../../utils/publishTreeViewEvent';
7
7
  import { useTreeViewContext } from '../../TreeViewProvider/useTreeViewContext';
8
8
  import { DescendantProvider, useDescendant } from '../../TreeViewProvider/DescendantProvider';
9
9
  import { jsx as _jsx } from "react/jsx-runtime";
10
- export const useTreeViewJSXNodes = ({
10
+ export const useTreeViewJSXItems = ({
11
11
  instance,
12
12
  setState
13
13
  }) => {
14
- const insertJSXNode = useEventCallback(node => {
14
+ instance.preventItemUpdates();
15
+ const insertJSXItem = useEventCallback(item => {
15
16
  setState(prevState => {
16
- if (prevState.nodes.nodeMap[node.id] != null) {
17
- throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', `Tow items were provided with the same id in the \`items\` prop: "${node.id}"`].join('\n'));
17
+ if (prevState.items.nodeMap[item.id] != null) {
18
+ throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', `Tow items were provided with the same id in the \`items\` prop: "${item.id}"`].join('\n'));
18
19
  }
19
20
  return _extends({}, prevState, {
20
- nodes: _extends({}, prevState.nodes, {
21
- nodeMap: _extends({}, prevState.nodes.nodeMap, {
22
- [node.id]: node
21
+ items: _extends({}, prevState.items, {
22
+ nodeMap: _extends({}, prevState.items.nodeMap, {
23
+ [item.id]: item
23
24
  }),
24
25
  // For `SimpleTreeView`, we don't have a proper `item` object, so we create a very basic one.
25
- itemMap: _extends({}, prevState.nodes.itemMap, {
26
- [node.id]: {
27
- id: node.id,
28
- label: node.label
26
+ itemMap: _extends({}, prevState.items.itemMap, {
27
+ [item.id]: {
28
+ id: item.id,
29
+ label: item.label
29
30
  }
30
31
  })
31
32
  })
32
33
  });
33
34
  });
34
35
  });
35
- const removeJSXNode = useEventCallback(nodeId => {
36
+ const removeJSXItem = useEventCallback(itemId => {
36
37
  setState(prevState => {
37
- const newNodeMap = _extends({}, prevState.nodes.nodeMap);
38
- const newItemMap = _extends({}, prevState.nodes.itemMap);
39
- delete newNodeMap[nodeId];
40
- delete newItemMap[nodeId];
38
+ const newNodeMap = _extends({}, prevState.items.nodeMap);
39
+ const newItemMap = _extends({}, prevState.items.itemMap);
40
+ delete newNodeMap[itemId];
41
+ delete newItemMap[itemId];
41
42
  return _extends({}, prevState, {
42
- nodes: _extends({}, prevState.nodes, {
43
+ items: _extends({}, prevState.items, {
43
44
  nodeMap: newNodeMap,
44
45
  itemMap: newItemMap
45
46
  })
46
47
  });
47
48
  });
48
- publishTreeViewEvent(instance, 'removeNode', {
49
- id: nodeId
49
+ publishTreeViewEvent(instance, 'removeItem', {
50
+ id: itemId
50
51
  });
51
52
  });
52
- const mapFirstCharFromJSX = useEventCallback((nodeId, firstChar) => {
53
+ const mapFirstCharFromJSX = useEventCallback((itemId, firstChar) => {
53
54
  instance.updateFirstCharMap(firstCharMap => {
54
- firstCharMap[nodeId] = firstChar;
55
+ firstCharMap[itemId] = firstChar;
55
56
  return firstCharMap;
56
57
  });
57
58
  return () => {
58
59
  instance.updateFirstCharMap(firstCharMap => {
59
60
  const newMap = _extends({}, firstCharMap);
60
- delete newMap[nodeId];
61
+ delete newMap[itemId];
61
62
  return newMap;
62
63
  });
63
64
  };
64
65
  });
65
66
  populateInstance(instance, {
66
- insertJSXNode,
67
- removeJSXNode,
67
+ insertJSXItem,
68
+ removeJSXItem,
68
69
  mapFirstCharFromJSX
69
70
  });
70
71
  };
71
- const useTreeViewJSXNodesItemPlugin = ({
72
+ const useTreeViewJSXItemsItemPlugin = ({
72
73
  props,
73
74
  rootRef,
74
75
  contentRef
@@ -77,7 +78,7 @@ const useTreeViewJSXNodesItemPlugin = ({
77
78
  children,
78
79
  disabled = false,
79
80
  label,
80
- nodeId,
81
+ itemId,
81
82
  id
82
83
  } = props;
83
84
  const {
@@ -96,45 +97,44 @@ const useTreeViewJSXNodesItemPlugin = ({
96
97
  const handleContentRef = useForkRef(pluginContentRef, contentRef);
97
98
  const descendant = React.useMemo(() => ({
98
99
  element: treeItemElement,
99
- id: nodeId
100
- }), [nodeId, treeItemElement]);
100
+ id: itemId
101
+ }), [itemId, treeItemElement]);
101
102
  const {
102
103
  index,
103
104
  parentId
104
105
  } = useDescendant(descendant);
105
106
  React.useEffect(() => {
106
- // On the first render a node's index will be -1. We want to wait for the real index.
107
+ // On the first render a item's index will be -1. We want to wait for the real index.
107
108
  if (index !== -1) {
108
- instance.insertJSXNode({
109
- id: nodeId,
109
+ instance.insertJSXItem({
110
+ id: itemId,
110
111
  idAttribute: id,
111
112
  index,
112
113
  parentId,
113
114
  expandable,
114
115
  disabled
115
116
  });
116
- return () => instance.removeJSXNode(nodeId);
117
+ return () => instance.removeJSXItem(itemId);
117
118
  }
118
119
  return undefined;
119
- }, [instance, parentId, index, nodeId, expandable, disabled, id]);
120
+ }, [instance, parentId, index, itemId, expandable, disabled, id]);
120
121
  React.useEffect(() => {
121
122
  if (label) {
122
- var _pluginContentRef$cur, _pluginContentRef$cur2;
123
- return instance.mapFirstCharFromJSX(nodeId, ((_pluginContentRef$cur = (_pluginContentRef$cur2 = pluginContentRef.current) == null ? void 0 : _pluginContentRef$cur2.textContent) != null ? _pluginContentRef$cur : '').substring(0, 1).toLowerCase());
123
+ return instance.mapFirstCharFromJSX(itemId, (pluginContentRef.current?.textContent ?? '').substring(0, 1).toLowerCase());
124
124
  }
125
125
  return undefined;
126
- }, [instance, nodeId, label]);
126
+ }, [instance, itemId, label]);
127
127
  return {
128
128
  contentRef: handleContentRef,
129
129
  rootRef: handleRootRef
130
130
  };
131
131
  };
132
- useTreeViewJSXNodes.itemPlugin = useTreeViewJSXNodesItemPlugin;
133
- useTreeViewJSXNodes.wrapItem = ({
132
+ useTreeViewJSXItems.itemPlugin = useTreeViewJSXItemsItemPlugin;
133
+ useTreeViewJSXItems.wrapItem = ({
134
134
  children,
135
- nodeId
135
+ itemId
136
136
  }) => /*#__PURE__*/_jsx(DescendantProvider, {
137
- id: nodeId,
137
+ id: itemId,
138
138
  children: children
139
139
  });
140
- useTreeViewJSXNodes.params = {};
140
+ useTreeViewJSXItems.params = {};