@mui/x-tree-view 8.0.0-alpha.0 → 8.0.0-alpha.1

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 (151) hide show
  1. package/CHANGELOG.md +429 -5
  2. package/README.md +2 -2
  3. package/RichTreeView/RichTreeView.js +2 -4
  4. package/RichTreeView/RichTreeView.types.d.ts +3 -16
  5. package/TreeItem/TreeItem.js +4 -4
  6. package/TreeItem/TreeItem.types.d.ts +3 -1
  7. package/TreeItemProvider/TreeItemProvider.js +16 -3
  8. package/TreeItemProvider/TreeItemProvider.types.d.ts +1 -0
  9. package/hooks/index.d.ts +1 -0
  10. package/hooks/index.js +2 -1
  11. package/hooks/useTreeItemModel.d.ts +2 -0
  12. package/hooks/useTreeItemModel.js +11 -0
  13. package/hooks/useTreeItemUtils/useTreeItemUtils.d.ts +2 -1
  14. package/hooks/useTreeItemUtils/useTreeItemUtils.js +31 -15
  15. package/index.js +1 -1
  16. package/internals/TreeViewItemDepthContext/TreeViewItemDepthContext.d.ts +3 -1
  17. package/internals/TreeViewProvider/TreeViewChildrenItemProvider.d.ts +2 -1
  18. package/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +6 -22
  19. package/internals/TreeViewProvider/TreeViewProvider.js +1 -2
  20. package/internals/TreeViewProvider/TreeViewProvider.types.d.ts +4 -2
  21. package/internals/components/RichTreeViewItems.d.ts +2 -4
  22. package/internals/components/RichTreeViewItems.js +42 -30
  23. package/internals/corePlugins/useTreeViewId/useTreeViewId.js +10 -11
  24. package/internals/corePlugins/useTreeViewId/useTreeViewId.selectors.d.ts +36 -0
  25. package/internals/corePlugins/useTreeViewId/useTreeViewId.selectors.js +9 -0
  26. package/internals/corePlugins/useTreeViewId/useTreeViewId.types.d.ts +1 -5
  27. package/internals/hooks/useSelector.d.ts +4 -0
  28. package/internals/hooks/useSelector.js +6 -0
  29. package/internals/index.d.ts +6 -1
  30. package/internals/index.js +5 -1
  31. package/internals/models/itemPlugin.d.ts +4 -4
  32. package/internals/models/plugin.d.ts +19 -7
  33. package/internals/models/treeView.d.ts +6 -0
  34. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +36 -24
  35. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.selectors.d.ts +124 -0
  36. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.selectors.js +17 -0
  37. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +6 -14
  38. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.utils.d.ts +1 -0
  39. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.utils.js +7 -0
  40. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +62 -40
  41. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.selectors.d.ts +182 -0
  42. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.selectors.js +34 -0
  43. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +4 -16
  44. package/internals/plugins/useTreeViewIcons/useTreeViewIcons.js +15 -13
  45. package/internals/plugins/useTreeViewItems/index.d.ts +1 -1
  46. package/internals/plugins/useTreeViewItems/useTreeViewItems.js +58 -98
  47. package/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.d.ts +718 -0
  48. package/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js +103 -0
  49. package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +15 -52
  50. package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +29 -26
  51. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +27 -18
  52. package/internals/plugins/useTreeViewLabel/useTreeViewLabel.itemPlugin.js +13 -5
  53. package/internals/plugins/useTreeViewLabel/useTreeViewLabel.js +19 -30
  54. package/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.d.ts +74 -0
  55. package/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.js +26 -0
  56. package/internals/plugins/useTreeViewLabel/useTreeViewLabel.types.d.ts +7 -24
  57. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.itemPlugin.js +8 -6
  58. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +45 -34
  59. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.d.ts +32 -0
  60. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.js +9 -0
  61. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +6 -6
  62. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.d.ts +6 -6
  63. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +23 -13
  64. package/internals/useTreeView/useTreeView.js +30 -17
  65. package/internals/useTreeView/useTreeView.types.d.ts +1 -2
  66. package/internals/useTreeView/useTreeViewBuildContext.d.ts +3 -1
  67. package/internals/useTreeView/useTreeViewBuildContext.js +24 -18
  68. package/internals/utils/TreeViewStore.d.ts +12 -0
  69. package/internals/utils/TreeViewStore.js +24 -0
  70. package/internals/utils/selectors.d.ts +9 -0
  71. package/internals/utils/selectors.js +37 -0
  72. package/internals/utils/tree.d.ts +8 -8
  73. package/internals/utils/tree.js +51 -43
  74. package/models/items.d.ts +3 -2
  75. package/modern/RichTreeView/RichTreeView.js +2 -4
  76. package/modern/TreeItem/TreeItem.js +4 -4
  77. package/modern/TreeItemProvider/TreeItemProvider.js +16 -3
  78. package/modern/hooks/index.js +2 -1
  79. package/modern/hooks/useTreeItemModel.js +11 -0
  80. package/modern/hooks/useTreeItemUtils/useTreeItemUtils.js +31 -15
  81. package/modern/index.js +1 -1
  82. package/modern/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +6 -22
  83. package/modern/internals/TreeViewProvider/TreeViewProvider.js +1 -2
  84. package/modern/internals/components/RichTreeViewItems.js +42 -30
  85. package/modern/internals/corePlugins/useTreeViewId/useTreeViewId.js +10 -11
  86. package/modern/internals/corePlugins/useTreeViewId/useTreeViewId.selectors.js +9 -0
  87. package/modern/internals/hooks/useSelector.js +6 -0
  88. package/modern/internals/index.js +5 -1
  89. package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +36 -24
  90. package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.selectors.js +17 -0
  91. package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.utils.js +7 -0
  92. package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +62 -40
  93. package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.selectors.js +34 -0
  94. package/modern/internals/plugins/useTreeViewIcons/useTreeViewIcons.js +15 -13
  95. package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.js +58 -98
  96. package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js +103 -0
  97. package/modern/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +29 -26
  98. package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +27 -18
  99. package/modern/internals/plugins/useTreeViewLabel/useTreeViewLabel.itemPlugin.js +13 -5
  100. package/modern/internals/plugins/useTreeViewLabel/useTreeViewLabel.js +19 -30
  101. package/modern/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.js +26 -0
  102. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.itemPlugin.js +8 -6
  103. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +45 -34
  104. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.js +9 -0
  105. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +23 -13
  106. package/modern/internals/useTreeView/useTreeView.js +30 -17
  107. package/modern/internals/useTreeView/useTreeViewBuildContext.js +24 -18
  108. package/modern/internals/utils/TreeViewStore.js +24 -0
  109. package/modern/internals/utils/selectors.js +37 -0
  110. package/modern/internals/utils/tree.js +51 -43
  111. package/modern/useTreeItem/useTreeItem.js +26 -11
  112. package/node/RichTreeView/RichTreeView.js +2 -4
  113. package/node/TreeItem/TreeItem.js +4 -4
  114. package/node/TreeItemProvider/TreeItemProvider.js +16 -3
  115. package/node/hooks/index.js +8 -1
  116. package/node/hooks/useTreeItemModel.js +17 -0
  117. package/node/hooks/useTreeItemUtils/useTreeItemUtils.js +32 -15
  118. package/node/index.js +1 -1
  119. package/node/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +6 -22
  120. package/node/internals/TreeViewProvider/TreeViewProvider.js +1 -2
  121. package/node/internals/components/RichTreeViewItems.js +42 -30
  122. package/node/internals/corePlugins/useTreeViewId/useTreeViewId.js +12 -13
  123. package/node/internals/corePlugins/useTreeViewId/useTreeViewId.selectors.js +15 -0
  124. package/node/internals/hooks/useSelector.js +13 -0
  125. package/node/internals/index.js +47 -1
  126. package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +36 -24
  127. package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.selectors.js +23 -0
  128. package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.utils.js +14 -0
  129. package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +62 -40
  130. package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.selectors.js +40 -0
  131. package/node/internals/plugins/useTreeViewIcons/useTreeViewIcons.js +16 -13
  132. package/node/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -100
  133. package/node/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js +109 -0
  134. package/node/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +30 -27
  135. package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +27 -18
  136. package/node/internals/plugins/useTreeViewLabel/useTreeViewLabel.itemPlugin.js +13 -5
  137. package/node/internals/plugins/useTreeViewLabel/useTreeViewLabel.js +19 -30
  138. package/node/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.js +32 -0
  139. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.itemPlugin.js +8 -6
  140. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +46 -35
  141. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.js +15 -0
  142. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +24 -14
  143. package/node/internals/useTreeView/useTreeView.js +30 -17
  144. package/node/internals/useTreeView/useTreeViewBuildContext.js +25 -18
  145. package/node/internals/utils/TreeViewStore.js +31 -0
  146. package/node/internals/utils/selectors.js +44 -0
  147. package/node/internals/utils/tree.js +51 -43
  148. package/node/useTreeItem/useTreeItem.js +26 -11
  149. package/package.json +6 -4
  150. package/useTreeItem/useTreeItem.js +26 -11
  151. package/useTreeItem/useTreeItem.types.d.ts +9 -0
@@ -0,0 +1,11 @@
1
+ 'use client';
2
+
3
+ import { useTreeViewContext } from "../internals/TreeViewProvider/index.js";
4
+ import { useSelector } from "../internals/hooks/useSelector.js";
5
+ import { selectorItemModel } from "../internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js";
6
+ export const useTreeItemModel = itemId => {
7
+ const {
8
+ store
9
+ } = useTreeViewContext();
10
+ return useSelector(store, selectorItemModel, itemId);
11
+ };
@@ -35,8 +35,9 @@ interface UseTreeItemUtilsReturnValue<TSignatures extends UseTreeItemUtilsMinima
35
35
  */
36
36
  publicAPI: TreeViewPublicAPI<TSignatures, TOptionalSignatures>;
37
37
  }
38
+ export declare const isItemExpandable: (reactChildren: React.ReactNode) => boolean;
38
39
  export declare const useTreeItemUtils: <TSignatures extends UseTreeItemUtilsMinimalPlugins = UseTreeItemUtilsMinimalPlugins, TOptionalSignatures extends UseTreeItemUtilsOptionalPlugins = UseTreeItemUtilsOptionalPlugins>({ itemId, children, }: {
39
40
  itemId: string;
40
- children: React.ReactNode;
41
+ children?: React.ReactNode;
41
42
  }) => UseTreeItemUtilsReturnValue<TSignatures, TOptionalSignatures>;
42
43
  export {};
@@ -3,6 +3,12 @@
3
3
  import { useTreeViewContext } from "../../internals/TreeViewProvider/index.js";
4
4
  import { useTreeViewLabel } from "../../internals/plugins/useTreeViewLabel/index.js";
5
5
  import { hasPlugin } from "../../internals/utils/plugins.js";
6
+ import { useSelector } from "../../internals/hooks/useSelector.js";
7
+ import { selectorIsItemExpanded } from "../../internals/plugins/useTreeViewExpansion/useTreeViewExpansion.selectors.js";
8
+ import { selectorIsItemFocused } from "../../internals/plugins/useTreeViewFocus/useTreeViewFocus.selectors.js";
9
+ import { selectorIsItemDisabled } from "../../internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js";
10
+ import { selectorIsItemSelected } from "../../internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.js";
11
+ import { selectorIsItemBeingEdited, selectorIsItemEditable } from "../../internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.js";
6
12
 
7
13
  /**
8
14
  * Plugins that need to be present in the Tree View in order for `useTreeItemUtils` to work correctly.
@@ -12,7 +18,7 @@ import { hasPlugin } from "../../internals/utils/plugins.js";
12
18
  * Plugins that `useTreeItemUtils` can use if they are present, but are not required.
13
19
  */
14
20
 
15
- const isItemExpandable = reactChildren => {
21
+ export const isItemExpandable = reactChildren => {
16
22
  if (Array.isArray(reactChildren)) {
17
23
  return reactChildren.length > 0 && reactChildren.some(isItemExpandable);
18
24
  }
@@ -24,19 +30,30 @@ export const useTreeItemUtils = ({
24
30
  }) => {
25
31
  const {
26
32
  instance,
33
+ label,
34
+ store,
27
35
  selection: {
28
36
  multiSelect
29
37
  },
30
38
  publicAPI
31
39
  } = useTreeViewContext();
40
+ const isExpanded = useSelector(store, selectorIsItemExpanded, itemId);
41
+ const isFocused = useSelector(store, selectorIsItemFocused, itemId);
42
+ const isSelected = useSelector(store, selectorIsItemSelected, itemId);
43
+ const isDisabled = useSelector(store, selectorIsItemDisabled, itemId);
44
+ const isEditing = useSelector(store, state => label == null ? false : selectorIsItemBeingEdited(state, itemId));
45
+ const isEditable = useSelector(store, state => label == null ? false : selectorIsItemEditable(state, {
46
+ itemId,
47
+ isItemEditable: label.isItemEditable
48
+ }));
32
49
  const status = {
33
50
  expandable: isItemExpandable(children),
34
- expanded: instance.isItemExpanded(itemId),
35
- focused: instance.isItemFocused(itemId),
36
- selected: instance.isItemSelected(itemId),
37
- disabled: instance.isItemDisabled(itemId),
38
- editing: instance?.isItemBeingEdited ? instance?.isItemBeingEdited(itemId) : false,
39
- editable: instance.isItemEditable ? instance.isItemEditable(itemId) : false
51
+ expanded: isExpanded,
52
+ focused: isFocused,
53
+ selected: isSelected,
54
+ disabled: isDisabled,
55
+ editing: isEditing,
56
+ editable: isEditable
40
57
  };
41
58
  const handleExpansion = event => {
42
59
  if (status.disabled) {
@@ -48,7 +65,7 @@ export const useTreeItemUtils = ({
48
65
  const multiple = multiSelect && (event.shiftKey || event.ctrlKey || event.metaKey);
49
66
 
50
67
  // If already expanded and trying to toggle selection don't close
51
- if (status.expandable && !(multiple && instance.isItemExpanded(itemId))) {
68
+ if (status.expandable && !(multiple && selectorIsItemExpanded(store.value, itemId))) {
52
69
  instance.toggleItemExpansion(event, itemId);
53
70
  }
54
71
  };
@@ -95,15 +112,15 @@ export const useTreeItemUtils = ({
95
112
  if (!hasPlugin(instance, useTreeViewLabel)) {
96
113
  return;
97
114
  }
98
- if (instance.isItemEditable(itemId)) {
99
- if (instance.isItemBeingEdited(itemId)) {
115
+ if (isEditable) {
116
+ if (isEditing) {
100
117
  instance.setEditedItemId(null);
101
118
  } else {
102
119
  instance.setEditedItemId(itemId);
103
120
  }
104
121
  }
105
122
  };
106
- const handleSaveItemLabel = (event, label) => {
123
+ const handleSaveItemLabel = (event, newLabel) => {
107
124
  if (!hasPlugin(instance, useTreeViewLabel)) {
108
125
  return;
109
126
  }
@@ -111,9 +128,8 @@ export const useTreeItemUtils = ({
111
128
  // As a side effect of `instance.focusItem` called here and in `handleCancelItemLabelEditing` the `labelInput` is blurred
112
129
  // The `onBlur` event is triggered, which calls `handleSaveItemLabel` again.
113
130
  // To avoid creating an unwanted behavior we need to check if the item is being edited before calling `updateItemLabel`
114
- // using `instance.isItemBeingEditedRef` instead of `instance.isItemBeingEdited` since the state is not yet updated in this point
115
- if (instance.isItemBeingEditedRef(itemId)) {
116
- instance.updateItemLabel(itemId, label);
131
+ if (selectorIsItemBeingEdited(store.value, itemId)) {
132
+ instance.updateItemLabel(itemId, newLabel);
117
133
  toggleItemEditing();
118
134
  instance.focusItem(event, itemId);
119
135
  }
@@ -122,7 +138,7 @@ export const useTreeItemUtils = ({
122
138
  if (!hasPlugin(instance, useTreeViewLabel)) {
123
139
  return;
124
140
  }
125
- if (instance.isItemBeingEditedRef(itemId)) {
141
+ if (selectorIsItemBeingEdited(store.value, itemId)) {
126
142
  toggleItemEditing();
127
143
  instance.focusItem(event, itemId);
128
144
  }
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-tree-view v8.0.0-alpha.0
2
+ * @mui/x-tree-view v8.0.0-alpha.1
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -1,3 +1,5 @@
1
1
  import * as React from 'react';
2
2
  import { TreeViewItemId } from '../../models';
3
- export declare const TreeViewItemDepthContext: React.Context<number | ((itemId: TreeViewItemId) => number)>;
3
+ import { TreeViewState } from '../models';
4
+ import type { UseTreeViewItemsSignature } from '../plugins/useTreeViewItems';
5
+ export declare const TreeViewItemDepthContext: React.Context<number | ((state: TreeViewState<[UseTreeViewItemsSignature]>, itemId: TreeViewItemId) => number)>;
@@ -1,7 +1,8 @@
1
1
  import * as React from 'react';
2
2
  export declare const TreeViewChildrenItemContext: React.Context<TreeViewChildrenItemContextValue | null>;
3
3
  interface TreeViewChildrenItemProviderProps {
4
- itemId?: string;
4
+ itemId: string | null;
5
+ idAttribute: string | null;
5
6
  children: React.ReactNode;
6
7
  }
7
8
  export declare function TreeViewChildrenItemProvider(props: TreeViewChildrenItemProviderProps): React.JSX.Element;
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { useTreeViewContext } from "./useTreeViewContext.js";
4
4
  import { escapeOperandAttributeSelector } from "../utils/utils.js";
5
- import { generateTreeItemIdAttribute } from "../corePlugins/useTreeViewId/useTreeViewId.utils.js";
5
+ import { selectorItemOrderedChildrenIds } from "../plugins/useTreeViewItems/useTreeViewItems.selectors.js";
6
6
  import { jsx as _jsx } from "react/jsx-runtime";
7
7
  export const TreeViewChildrenItemContext = /*#__PURE__*/React.createContext(null);
8
8
  if (process.env.NODE_ENV !== 'production') {
@@ -11,11 +11,12 @@ if (process.env.NODE_ENV !== 'production') {
11
11
  export function TreeViewChildrenItemProvider(props) {
12
12
  const {
13
13
  children,
14
- itemId = null
14
+ itemId = null,
15
+ idAttribute
15
16
  } = props;
16
17
  const {
17
18
  instance,
18
- treeId,
19
+ store,
19
20
  rootRef
20
21
  } = useTreeViewContext();
21
22
  const childrenIdAttrToIdRef = React.useRef(new Map());
@@ -23,25 +24,8 @@ export function TreeViewChildrenItemProvider(props) {
23
24
  if (!rootRef.current) {
24
25
  return;
25
26
  }
26
- let idAttr = null;
27
- if (itemId == null) {
28
- idAttr = rootRef.current.id;
29
- } else {
30
- // Undefined during 1st render
31
- const itemMeta = instance.getItemMeta(itemId);
32
- if (itemMeta !== undefined) {
33
- idAttr = generateTreeItemIdAttribute({
34
- itemId,
35
- treeId,
36
- id: itemMeta.idAttribute
37
- });
38
- }
39
- }
40
- if (idAttr == null) {
41
- return;
42
- }
43
- const previousChildrenIds = instance.getItemOrderedChildrenIds(itemId ?? null) ?? [];
44
- const escapedIdAttr = escapeOperandAttributeSelector(idAttr);
27
+ const previousChildrenIds = selectorItemOrderedChildrenIds(store.value, itemId ?? null) ?? [];
28
+ const escapedIdAttr = escapeOperandAttributeSelector(idAttribute ?? rootRef.current.id);
45
29
  const childrenElements = rootRef.current.querySelectorAll(`${itemId == null ? '' : `*[id="${escapedIdAttr}"] `}[role="treeitem"]:not(*[id="${escapedIdAttr}"] [role="treeitem"] [role="treeitem"])`);
46
30
  const childrenIds = Array.from(childrenElements).map(child => childrenIdAttrToIdRef.current.get(child.id));
47
31
  const hasChanged = childrenIds.length !== previousChildrenIds.length || childrenIds.some((childId, index) => childId !== previousChildrenIds[index]);
@@ -14,8 +14,7 @@ export function TreeViewProvider(props) {
14
14
  return /*#__PURE__*/_jsx(TreeViewContext.Provider, {
15
15
  value: value,
16
16
  children: value.wrapRoot({
17
- children,
18
- instance: value.instance
17
+ children
19
18
  })
20
19
  });
21
20
  }
@@ -1,14 +1,16 @@
1
1
  import * as React from 'react';
2
2
  import { MergeSignaturesProperty, TreeItemWrapper, TreeRootWrapper, TreeViewAnyPluginSignature, TreeViewInstance, TreeViewItemPluginResponse, TreeViewPublicAPI } from '../models';
3
+ import { TreeViewStore } from '../utils/TreeViewStore';
3
4
  import { TreeViewCorePluginSignatures } from '../corePlugins';
4
- import type { TreeItemProps } from '../../TreeItem';
5
+ import type { TreeItemProps } from '../../TreeItem/TreeItem.types';
5
6
  export type TreeViewItemPluginsRunner = (props: TreeItemProps) => Required<TreeViewItemPluginResponse>;
6
7
  export type TreeViewContextValue<TSignatures extends readonly TreeViewAnyPluginSignature[], TOptionalSignatures extends readonly TreeViewAnyPluginSignature[] = []> = MergeSignaturesProperty<[...TreeViewCorePluginSignatures, ...TSignatures], 'contextValue'> & Partial<MergeSignaturesProperty<TOptionalSignatures, 'contextValue'>> & {
7
8
  instance: TreeViewInstance<TSignatures, TOptionalSignatures>;
8
9
  publicAPI: TreeViewPublicAPI<TSignatures, TOptionalSignatures>;
10
+ store: TreeViewStore<TSignatures>;
9
11
  rootRef: React.RefObject<HTMLUListElement>;
10
12
  wrapItem: TreeItemWrapper<TSignatures>;
11
- wrapRoot: TreeRootWrapper<TSignatures>;
13
+ wrapRoot: TreeRootWrapper;
12
14
  runItemPlugins: TreeViewItemPluginsRunner;
13
15
  };
14
16
  export interface TreeViewProviderProps<TSignatures extends readonly TreeViewAnyPluginSignature[]> {
@@ -2,14 +2,14 @@ import * as React from 'react';
2
2
  import { SlotComponentProps } from '@mui/utils';
3
3
  import { TreeItem, TreeItemProps } from '../../TreeItem';
4
4
  import { TreeViewItemId } from '../../models';
5
- import { TreeViewItemToRenderProps } from '../plugins/useTreeViewItems';
5
+ export declare function RichTreeViewItems(props: RichTreeViewItemsProps): React.JSX.Element;
6
6
  interface RichTreeViewItemsOwnerState {
7
7
  itemId: TreeViewItemId;
8
8
  label: string;
9
9
  }
10
10
  export interface RichTreeViewItemsSlots {
11
11
  /**
12
- * Custom component for the item.
12
+ * Custom component to render a Tree Item.
13
13
  * @default TreeItem.
14
14
  */
15
15
  item?: React.JSXElementConstructor<TreeItemProps>;
@@ -18,7 +18,6 @@ export interface RichTreeViewItemsSlotProps {
18
18
  item?: SlotComponentProps<typeof TreeItem, {}, RichTreeViewItemsOwnerState>;
19
19
  }
20
20
  export interface RichTreeViewItemsProps {
21
- itemsToRender: TreeViewItemToRenderProps[];
22
21
  /**
23
22
  * Overridable component slots.
24
23
  * @default {}
@@ -30,5 +29,4 @@ export interface RichTreeViewItemsProps {
30
29
  */
31
30
  slotProps?: RichTreeViewItemsSlotProps;
32
31
  }
33
- export declare function RichTreeViewItems(props: RichTreeViewItemsProps): React.JSX.Element;
34
32
  export {};
@@ -3,54 +3,66 @@ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWith
3
3
  const _excluded = ["ownerState"];
4
4
  import * as React from 'react';
5
5
  import useSlotProps from '@mui/utils/useSlotProps';
6
+ import { fastObjectShallowCompare } from '@mui/x-internals/fastObjectShallowCompare';
6
7
  import { TreeItem } from "../../TreeItem/index.js";
8
+ import { useSelector } from "../hooks/useSelector.js";
9
+ import { selectorItemMeta, selectorItemOrderedChildrenIds } from "../plugins/useTreeViewItems/useTreeViewItems.selectors.js";
10
+ import { useTreeViewContext } from "../TreeViewProvider/index.js";
7
11
  import { jsx as _jsx } from "react/jsx-runtime";
8
- function WrappedTreeItem({
9
- slots,
10
- slotProps,
11
- label,
12
- id,
13
- itemId,
14
- itemsToRender
12
+ const RichTreeViewItemsContext = /*#__PURE__*/React.createContext(null);
13
+ if (process.env.NODE_ENV !== 'production') {
14
+ RichTreeViewItemsContext.displayName = 'RichTreeViewItemsProvider';
15
+ }
16
+ const WrappedTreeItem = /*#__PURE__*/React.memo(function WrappedTreeItem({
17
+ itemSlot,
18
+ itemSlotProps,
19
+ itemId
15
20
  }) {
16
- const Item = slots?.item ?? TreeItem;
21
+ const renderItemForRichTreeView = React.useContext(RichTreeViewItemsContext);
22
+ const {
23
+ store
24
+ } = useTreeViewContext();
25
+ const itemMeta = useSelector(store, selectorItemMeta, itemId);
26
+ const children = useSelector(store, selectorItemOrderedChildrenIds, itemId);
27
+ const Item = itemSlot ?? TreeItem;
17
28
  const _useSlotProps = useSlotProps({
18
29
  elementType: Item,
19
- externalSlotProps: slotProps?.item,
30
+ externalSlotProps: itemSlotProps,
20
31
  additionalProps: {
21
- itemId,
22
- id,
23
- label
32
+ label: itemMeta?.label,
33
+ id: itemMeta?.idAttribute,
34
+ itemId
24
35
  },
25
36
  ownerState: {
26
37
  itemId,
27
- label
38
+ label: itemMeta?.label
28
39
  }
29
40
  }),
30
41
  itemProps = _objectWithoutPropertiesLoose(_useSlotProps, _excluded);
31
- const children = React.useMemo(() => itemsToRender ? /*#__PURE__*/_jsx(RichTreeViewItems, {
32
- itemsToRender: itemsToRender,
33
- slots: slots,
34
- slotProps: slotProps
35
- }) : null, [itemsToRender, slots, slotProps]);
36
42
  return /*#__PURE__*/_jsx(Item, _extends({}, itemProps, {
37
- children: children
43
+ children: children?.map(renderItemForRichTreeView)
38
44
  }));
39
- }
45
+ }, fastObjectShallowCompare);
40
46
  export function RichTreeViewItems(props) {
41
47
  const {
42
- itemsToRender,
43
48
  slots,
44
49
  slotProps
45
50
  } = props;
46
- return /*#__PURE__*/_jsx(React.Fragment, {
47
- children: itemsToRender.map(item => /*#__PURE__*/_jsx(WrappedTreeItem, {
48
- slots: slots,
49
- slotProps: slotProps,
50
- label: item.label,
51
- id: item.id,
52
- itemId: item.itemId,
53
- itemsToRender: item.children
54
- }, item.itemId))
51
+ const {
52
+ store
53
+ } = useTreeViewContext();
54
+ const itemSlot = slots?.item;
55
+ const itemSlotProps = slotProps?.item;
56
+ const items = useSelector(store, selectorItemOrderedChildrenIds, null);
57
+ const renderItem = React.useCallback(itemId => {
58
+ return /*#__PURE__*/_jsx(WrappedTreeItem, {
59
+ itemSlot: itemSlot,
60
+ itemSlotProps: itemSlotProps,
61
+ itemId: itemId
62
+ }, itemId);
63
+ }, [itemSlot, itemSlotProps]);
64
+ return /*#__PURE__*/_jsx(RichTreeViewItemsContext.Provider, {
65
+ value: renderItem,
66
+ children: items.map(renderItem)
55
67
  });
56
68
  }
@@ -1,14 +1,15 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
+ import { useSelector } from "../../hooks/useSelector.js";
4
+ import { selectorTreeViewId } from "./useTreeViewId.selectors.js";
3
5
  import { createTreeViewDefaultId } from "./useTreeViewId.utils.js";
4
6
  export const useTreeViewId = ({
5
7
  params,
6
- state,
7
- setState
8
+ store
8
9
  }) => {
9
10
  React.useEffect(() => {
10
- setState(prevState => {
11
- if (prevState.id.treeId === params.id && prevState.id.treeId !== undefined) {
11
+ store.update(prevState => {
12
+ if (params.id === prevState.id.providedTreeId && prevState.id.treeId !== undefined) {
12
13
  return prevState;
13
14
  }
14
15
  return _extends({}, prevState, {
@@ -17,15 +18,12 @@ export const useTreeViewId = ({
17
18
  })
18
19
  });
19
20
  });
20
- }, [setState, params.id]);
21
- const treeId = params.id ?? state.id.treeId;
21
+ }, [store, params.id]);
22
+ const treeId = useSelector(store, selectorTreeViewId);
22
23
  return {
23
24
  getRootProps: () => ({
24
25
  id: treeId
25
- }),
26
- contextValue: {
27
- treeId
28
- }
26
+ })
29
27
  };
30
28
  };
31
29
  useTreeViewId.params = {
@@ -35,6 +33,7 @@ useTreeViewId.getInitialState = ({
35
33
  id
36
34
  }) => ({
37
35
  id: {
38
- treeId: id ?? undefined
36
+ treeId: undefined,
37
+ providedTreeId: id
39
38
  }
40
39
  });
@@ -0,0 +1,36 @@
1
+ import { TreeViewRootSelector } from '../../utils/selectors';
2
+ import { UseTreeViewIdSignature } from './useTreeViewId.types';
3
+ /**
4
+ * Get the id attribute of the tree view.
5
+ * @param {TreeViewState<[UseTreeViewIdSignature]>} state The state of the tree view.
6
+ * @returns {string} The id attribute of the tree view.
7
+ */
8
+ export declare const selectorTreeViewId: ((state: import("./useTreeViewId.types").UseTreeViewIdState & Partial<{}> & {
9
+ cacheKey: import("../../models").TreeViewStateCacheKey;
10
+ }) => string | undefined) & {
11
+ clearCache: () => void;
12
+ resultsCount: () => number;
13
+ resetResultsCount: () => void;
14
+ } & {
15
+ resultFunc: (resultFuncArgs_0: {
16
+ treeId: string | undefined;
17
+ providedTreeId: string | undefined;
18
+ }) => string | undefined;
19
+ memoizedResultFunc: ((resultFuncArgs_0: {
20
+ treeId: string | undefined;
21
+ providedTreeId: string | undefined;
22
+ }) => string | undefined) & {
23
+ clearCache: () => void;
24
+ resultsCount: () => number;
25
+ resetResultsCount: () => void;
26
+ };
27
+ lastResult: () => string | undefined;
28
+ dependencies: [TreeViewRootSelector<UseTreeViewIdSignature>];
29
+ recomputations: () => number;
30
+ resetRecomputations: () => void;
31
+ dependencyRecomputations: () => number;
32
+ resetDependencyRecomputations: () => void;
33
+ } & {
34
+ argsMemoize: typeof import("reselect").weakMapMemoize;
35
+ memoize: typeof import("reselect").weakMapMemoize;
36
+ };
@@ -0,0 +1,9 @@
1
+ import { createSelector } from "../../utils/selectors.js";
2
+ const selectorTreeViewIdState = state => state.id;
3
+
4
+ /**
5
+ * Get the id attribute of the tree view.
6
+ * @param {TreeViewState<[UseTreeViewIdSignature]>} state The state of the tree view.
7
+ * @returns {string} The id attribute of the tree view.
8
+ */
9
+ export const selectorTreeViewId = createSelector(selectorTreeViewIdState, idState => idState.treeId);
@@ -10,15 +10,11 @@ export type UseTreeViewIdDefaultizedParameters = UseTreeViewIdParameters;
10
10
  export interface UseTreeViewIdState {
11
11
  id: {
12
12
  treeId: string | undefined;
13
+ providedTreeId: string | undefined;
13
14
  };
14
15
  }
15
- interface UseTreeViewIdContextValue {
16
- treeId: string | undefined;
17
- }
18
16
  export type UseTreeViewIdSignature = TreeViewPluginSignature<{
19
17
  params: UseTreeViewIdParameters;
20
18
  defaultizedParams: UseTreeViewIdDefaultizedParameters;
21
19
  state: UseTreeViewIdState;
22
- contextValue: UseTreeViewIdContextValue;
23
20
  }>;
24
- export {};
@@ -0,0 +1,4 @@
1
+ import { TreeViewAnyPluginSignature, TreeViewState } from '../models';
2
+ import { TreeViewStore } from '../utils/TreeViewStore';
3
+ import { TreeViewSelector } from '../utils/selectors';
4
+ export declare const useSelector: <TSignatures extends readonly TreeViewAnyPluginSignature[], TArgs, TValue>(store: TreeViewStore<TSignatures>, selector: TreeViewSelector<TreeViewState<TSignatures>, TArgs, TValue>, args?: TArgs, equals?: (a: TValue, b: TValue) => boolean) => TValue;
@@ -0,0 +1,6 @@
1
+ import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector';
2
+ const defaultCompare = Object.is;
3
+ export const useSelector = (store, selector, args = undefined, equals = defaultCompare) => {
4
+ const selectorWithArgs = state => selector(state, args);
5
+ return useSyncExternalStoreWithSelector(store.subscribe, store.getSnapshot, store.getSnapshot, selectorWithArgs, equals);
6
+ };
@@ -1,8 +1,10 @@
1
1
  export { useTreeView } from './useTreeView';
2
2
  export { TreeViewProvider, useTreeViewContext } from './TreeViewProvider';
3
3
  export { RichTreeViewItems } from './components/RichTreeViewItems';
4
+ export type { RichTreeViewItemsSlots, RichTreeViewItemsSlotProps, } from './components/RichTreeViewItems';
4
5
  export { unstable_resetCleanupTracking } from './hooks/useInstanceEventHandler';
5
- export type { TreeViewPlugin, TreeViewPluginSignature, ConvertPluginsIntoSignatures, MergeSignaturesProperty, TreeViewPublicAPI, TreeViewExperimentalFeatures, TreeViewItemMeta, TreeViewInstance, TreeViewItemPlugin, } from './models';
6
+ export { useSelector } from './hooks/useSelector';
7
+ export type { TreeViewPlugin, TreeViewPluginSignature, ConvertPluginsIntoSignatures, MergeSignaturesProperty, TreeViewPublicAPI, TreeViewState, TreeViewExperimentalFeatures, TreeViewItemMeta, TreeViewInstance, TreeViewItemPlugin, TreeViewUsedStore, } from './models';
6
8
  export type { TreeViewCorePluginParameters } from './corePlugins';
7
9
  export { useTreeViewExpansion } from './plugins/useTreeViewExpansion';
8
10
  export type { UseTreeViewExpansionSignature, UseTreeViewExpansionParameters, } from './plugins/useTreeViewExpansion';
@@ -15,9 +17,12 @@ export type { UseTreeViewKeyboardNavigationSignature } from './plugins/useTreeVi
15
17
  export { useTreeViewIcons } from './plugins/useTreeViewIcons';
16
18
  export type { UseTreeViewIconsSignature, UseTreeViewIconsParameters, } from './plugins/useTreeViewIcons';
17
19
  export { useTreeViewItems, buildSiblingIndexes, TREE_VIEW_ROOT_PARENT_ID, } from './plugins/useTreeViewItems';
20
+ export { selectorItemMetaLookup, selectorItemMeta, selectorItemIndex, selectorItemOrderedChildrenIds, } from './plugins/useTreeViewItems/useTreeViewItems.selectors';
18
21
  export type { UseTreeViewItemsSignature, UseTreeViewItemsParameters, UseTreeViewItemsState, } from './plugins/useTreeViewItems';
19
22
  export { useTreeViewLabel } from './plugins/useTreeViewLabel';
20
23
  export type { UseTreeViewLabelSignature, UseTreeViewLabelParameters, } from './plugins/useTreeViewLabel';
21
24
  export { useTreeViewJSXItems } from './plugins/useTreeViewJSXItems';
22
25
  export type { UseTreeViewJSXItemsSignature, UseTreeViewJSXItemsParameters, } from './plugins/useTreeViewJSXItems';
26
+ export { createSelector } from './utils/selectors';
23
27
  export { isTargetInDescendants } from './utils/tree';
28
+ export { TreeViewStore } from './utils/TreeViewStore';
@@ -2,6 +2,7 @@ export { useTreeView } from "./useTreeView/index.js";
2
2
  export { TreeViewProvider, useTreeViewContext } from "./TreeViewProvider/index.js";
3
3
  export { RichTreeViewItems } from "./components/RichTreeViewItems.js";
4
4
  export { unstable_resetCleanupTracking } from "./hooks/useInstanceEventHandler.js";
5
+ export { useSelector } from "./hooks/useSelector.js";
5
6
 
6
7
  // Core plugins
7
8
 
@@ -12,6 +13,9 @@ export { useTreeViewFocus } from "./plugins/useTreeViewFocus/index.js";
12
13
  export { useTreeViewKeyboardNavigation } from "./plugins/useTreeViewKeyboardNavigation/index.js";
13
14
  export { useTreeViewIcons } from "./plugins/useTreeViewIcons/index.js";
14
15
  export { useTreeViewItems, buildSiblingIndexes, TREE_VIEW_ROOT_PARENT_ID } from "./plugins/useTreeViewItems/index.js";
16
+ export { selectorItemMetaLookup, selectorItemMeta, selectorItemIndex, selectorItemOrderedChildrenIds } from "./plugins/useTreeViewItems/useTreeViewItems.selectors.js";
15
17
  export { useTreeViewLabel } from "./plugins/useTreeViewLabel/index.js";
16
18
  export { useTreeViewJSXItems } from "./plugins/useTreeViewJSXItems/index.js";
17
- export { isTargetInDescendants } from "./utils/tree.js";
19
+ export { createSelector } from "./utils/selectors.js";
20
+ export { isTargetInDescendants } from "./utils/tree.js";
21
+ export { TreeViewStore } from "./utils/TreeViewStore.js";
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
2
  import { EventHandlers } from '@mui/utils';
3
- import type { TreeItemProps } from '../../TreeItem';
4
3
  import type { UseTreeItemContentSlotOwnProps, UseTreeItemDragAndDropOverlaySlotOwnProps, UseTreeItemLabelInputSlotOwnProps, UseTreeItemRootSlotOwnProps, UseTreeItemCheckboxSlotOwnProps, UseTreeItemStatus } from '../../useTreeItem';
5
4
  import type { UseTreeItemInteractions } from '../../hooks/useTreeItemUtils/useTreeItemUtils';
5
+ import type { TreeItemProps } from '../../TreeItem/TreeItem.types';
6
6
  export interface TreeViewItemPluginSlotPropsEnhancerParams {
7
7
  rootRefObject: React.MutableRefObject<HTMLLIElement | null>;
8
8
  contentRefObject: React.MutableRefObject<HTMLDivElement | null>;
@@ -36,8 +36,8 @@ export interface TreeViewItemPluginResponse {
36
36
  */
37
37
  propsEnhancers?: TreeViewItemPluginSlotPropsEnhancers;
38
38
  }
39
- export interface TreeViewItemPluginOptions<TProps extends {}> extends Omit<TreeViewItemPluginResponse, 'propsEnhancers'> {
40
- props: TProps;
39
+ export interface TreeViewItemPluginOptions extends Omit<TreeViewItemPluginResponse, 'propsEnhancers'> {
40
+ props: TreeItemProps;
41
41
  }
42
- export type TreeViewItemPlugin = (options: TreeViewItemPluginOptions<TreeItemProps>) => void | TreeViewItemPluginResponse;
42
+ export type TreeViewItemPlugin = (options: TreeViewItemPluginOptions) => void | TreeViewItemPluginResponse;
43
43
  export {};