@mui/x-tree-view 7.0.0-beta.5 → 7.0.0-beta.6

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 (32) hide show
  1. package/CHANGELOG.md +135 -49
  2. package/RichTreeView/RichTreeView.js +2 -1
  3. package/SimpleTreeView/SimpleTreeView.js +2 -1
  4. package/TreeItem/TreeItem.js +24 -28
  5. package/TreeItem/TreeItem.types.d.ts +7 -11
  6. package/TreeItem/treeItemClasses.d.ts +1 -1
  7. package/TreeItem/treeItemClasses.js +1 -1
  8. package/TreeView/TreeView.js +2 -1
  9. package/hooks/useTreeViewApiRef.d.ts +2 -2
  10. package/index.js +1 -1
  11. package/internals/models/helpers.d.ts +1 -0
  12. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +1 -2
  13. package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +20 -6
  14. package/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +29 -16
  15. package/internals/plugins/useTreeViewNodes/useTreeViewNodes.types.d.ts +16 -6
  16. package/modern/RichTreeView/RichTreeView.js +2 -1
  17. package/modern/SimpleTreeView/SimpleTreeView.js +2 -1
  18. package/modern/TreeItem/TreeItem.js +23 -27
  19. package/modern/TreeItem/treeItemClasses.js +1 -1
  20. package/modern/TreeView/TreeView.js +2 -1
  21. package/modern/index.js +1 -1
  22. package/modern/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +20 -6
  23. package/modern/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +29 -16
  24. package/node/RichTreeView/RichTreeView.js +2 -1
  25. package/node/SimpleTreeView/SimpleTreeView.js +2 -1
  26. package/node/TreeItem/TreeItem.js +23 -27
  27. package/node/TreeItem/treeItemClasses.js +1 -1
  28. package/node/TreeView/TreeView.js +2 -1
  29. package/node/index.js +1 -1
  30. package/node/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +20 -6
  31. package/node/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +28 -15
  32. package/package.json +2 -2
@@ -2,7 +2,7 @@ export interface TreeItemClasses {
2
2
  /** Styles applied to the root element. */
3
3
  root: string;
4
4
  /** Styles applied to the transition component. */
5
- group: string;
5
+ groupTransition: string;
6
6
  /** Styles applied to the content element. */
7
7
  content: string;
8
8
  /** State class applied to the content element when expanded. */
@@ -3,4 +3,4 @@ import generateUtilityClasses from '@mui/utils/generateUtilityClasses';
3
3
  export function getTreeItemUtilityClass(slot) {
4
4
  return generateUtilityClass('MuiTreeItem', slot);
5
5
  }
6
- export const treeItemClasses = generateUtilityClasses('MuiTreeItem', ['root', 'group', 'content', 'expanded', 'selected', 'focused', 'disabled', 'iconContainer', 'label']);
6
+ export const treeItemClasses = generateUtilityClasses('MuiTreeItem', ['root', 'groupTransition', 'content', 'expanded', 'selected', 'focused', 'disabled', 'iconContainer', 'label']);
@@ -69,7 +69,8 @@ process.env.NODE_ENV !== "production" ? TreeView.propTypes = {
69
69
  */
70
70
  apiRef: PropTypes.shape({
71
71
  current: PropTypes.shape({
72
- focusNode: PropTypes.func.isRequired
72
+ focusNode: PropTypes.func.isRequired,
73
+ getItem: PropTypes.func.isRequired
73
74
  })
74
75
  }),
75
76
  /**
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
- import { TreeViewAnyPluginSignature, TreeViewUsedPublicAPI } from '../internals/models';
2
+ import { TreeViewAnyPluginSignature, TreeViewPublicAPI } from '../internals/models';
3
3
  /**
4
4
  * Hook that instantiates a [[TreeViewApiRef]].
5
5
  */
6
- export declare const useTreeViewApiRef: <T extends TreeViewAnyPluginSignature, Api extends TreeViewUsedPublicAPI<T>>() => React.MutableRefObject<Api>;
6
+ export declare const useTreeViewApiRef: <TPlugins extends readonly TreeViewAnyPluginSignature[] = [import("../internals").UseTreeViewIdSignature, import("../internals").UseTreeViewNodesSignature, import("../internals").UseTreeViewExpansionSignature, import("../internals").UseTreeViewSelectionSignature, import("../internals").UseTreeViewFocusSignature, import("../internals").UseTreeViewKeyboardNavigationSignature, import("../internals").UseTreeViewIconsSignature]>() => React.MutableRefObject<TreeViewPublicAPI<TPlugins> | undefined>;
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-tree-view v7.0.0-beta.5
2
+ * @mui/x-tree-view v7.0.0-beta.6
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -1,5 +1,6 @@
1
1
  import type { TreeViewAnyPluginSignature, TreeViewPlugin } from './plugin';
2
2
  export type DefaultizedProps<P extends {}, RequiredProps extends keyof P, AdditionalProps extends {} = {}> = Omit<P, RequiredProps | keyof AdditionalProps> & Required<Pick<P, RequiredProps>> & AdditionalProps;
3
+ export type SlotComponentPropsFromProps<TProps extends {}, TOverrides extends {}, TOwnerState extends {}> = (Partial<TProps> & TOverrides) | ((ownerState: TOwnerState) => Partial<TProps> & TOverrides);
3
4
  type IsAny<T> = 0 extends 1 & T ? true : false;
4
5
  export type OptionalIfEmpty<A extends string, B> = keyof B extends never ? Partial<Record<A, B>> : IsAny<B> extends true ? Partial<Record<A, B>> : Record<A, B>;
5
6
  export type MergePluginsProperty<TPlugins extends readonly any[], TProperty extends keyof TreeViewAnyPluginSignature> = TPlugins extends readonly [plugin: infer P, ...otherPlugin: infer R] ? P extends TreeViewAnyPluginSignature ? P[TProperty] & MergePluginsProperty<R, TProperty> : {} : {};
@@ -10,8 +10,7 @@ export interface UseTreeViewFocusInstance {
10
10
  focusDefaultNode: (event: React.SyntheticEvent) => void;
11
11
  focusRoot: () => void;
12
12
  }
13
- export interface UseTreeViewFocusPublicAPI {
14
- focusNode: (event: React.SyntheticEvent, nodeId: string | null) => void;
13
+ export interface UseTreeViewFocusPublicAPI extends Pick<UseTreeViewFocusInstance, 'focusNode'> {
15
14
  }
16
15
  export interface UseTreeViewFocusParameters {
17
16
  /**
@@ -13,22 +13,36 @@ export const useTreeViewJSXNodes = ({
13
13
  }) => {
14
14
  const insertJSXNode = useEventCallback(node => {
15
15
  setState(prevState => {
16
- if (prevState.nodeMap[node.id] != null) {
16
+ if (prevState.nodes.nodeMap[node.id] != null) {
17
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'));
18
18
  }
19
19
  return _extends({}, prevState, {
20
- nodeMap: _extends({}, prevState.nodeMap, {
21
- [node.id]: node
20
+ nodes: _extends({}, prevState.nodes, {
21
+ nodeMap: _extends({}, prevState.nodes.nodeMap, {
22
+ [node.id]: node
23
+ }),
24
+ // 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
29
+ }
30
+ })
22
31
  })
23
32
  });
24
33
  });
25
34
  });
26
35
  const removeJSXNode = useEventCallback(nodeId => {
27
36
  setState(prevState => {
28
- const newMap = _extends({}, prevState.nodeMap);
29
- delete newMap[nodeId];
37
+ const newNodeMap = _extends({}, prevState.nodes.nodeMap);
38
+ const newItemMap = _extends({}, prevState.nodes.itemMap);
39
+ delete newNodeMap[nodeId];
40
+ delete newItemMap[nodeId];
30
41
  return _extends({}, prevState, {
31
- nodeMap: newMap
42
+ nodes: _extends({}, prevState.nodes, {
43
+ nodeMap: newNodeMap,
44
+ itemMap: newItemMap
45
+ })
32
46
  });
33
47
  });
34
48
  publishTreeViewEvent(instance, 'removeNode', {
@@ -1,15 +1,16 @@
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 } from '../../useTreeView/useTreeView.utils';
4
+ import { populateInstance, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
5
5
  import { publishTreeViewEvent } from '../../utils/publishTreeViewEvent';
6
- const updateState = ({
6
+ const updateNodesState = ({
7
7
  items,
8
8
  isItemDisabled,
9
9
  getItemLabel,
10
10
  getItemId
11
11
  }) => {
12
12
  const nodeMap = {};
13
+ const itemMap = {};
13
14
  const processItem = (item, index, parentId) => {
14
15
  var _item$children, _item$children2;
15
16
  const id = getItemId ? getItemId(item) : item.id;
@@ -28,10 +29,11 @@ const updateState = ({
28
29
  label,
29
30
  index,
30
31
  parentId,
31
- idAttribute: id,
32
+ idAttribute: undefined,
32
33
  expandable: !!((_item$children = item.children) != null && _item$children.length),
33
34
  disabled: isItemDisabled ? isItemDisabled(item) : false
34
35
  };
36
+ itemMap[id] = item;
35
37
  return {
36
38
  id,
37
39
  children: (_item$children2 = item.children) == null ? void 0 : _item$children2.map((child, childIndex) => processItem(child, childIndex, id))
@@ -40,16 +42,19 @@ const updateState = ({
40
42
  const nodeTree = items.map((item, itemIndex) => processItem(item, itemIndex, null));
41
43
  return {
42
44
  nodeMap,
43
- nodeTree
45
+ nodeTree,
46
+ itemMap
44
47
  };
45
48
  };
46
49
  export const useTreeViewNodes = ({
47
50
  instance,
51
+ publicAPI,
48
52
  params,
49
53
  state,
50
54
  setState
51
55
  }) => {
52
- const getNode = React.useCallback(nodeId => state.nodeMap[nodeId], [state.nodeMap]);
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]);
53
58
  const isNodeDisabled = React.useCallback(nodeId => {
54
59
  if (nodeId == null) {
55
60
  return false;
@@ -71,7 +76,7 @@ export const useTreeViewNodes = ({
71
76
  }
72
77
  return false;
73
78
  }, [instance]);
74
- const getChildrenIds = useEventCallback(nodeId => Object.values(state.nodeMap).filter(node => node.parentId === nodeId).sort((a, b) => a.index - b.index).map(child => child.id));
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));
75
80
  const getNavigableChildrenIds = nodeId => {
76
81
  let childrenIds = instance.getChildrenIds(nodeId);
77
82
  if (!params.disabledItemsFocusable) {
@@ -81,20 +86,22 @@ export const useTreeViewNodes = ({
81
86
  };
82
87
  React.useEffect(() => {
83
88
  setState(prevState => {
84
- const newState = updateState({
89
+ const newState = updateNodesState({
85
90
  items: params.items,
86
91
  isItemDisabled: params.isItemDisabled,
87
92
  getItemId: params.getItemId,
88
93
  getItemLabel: params.getItemLabel
89
94
  });
90
- Object.values(prevState.nodeMap).forEach(node => {
95
+ Object.values(prevState.nodes.nodeMap).forEach(node => {
91
96
  if (!newState.nodeMap[node.id]) {
92
97
  publishTreeViewEvent(instance, 'removeNode', {
93
98
  id: node.id
94
99
  });
95
100
  }
96
101
  });
97
- return _extends({}, prevState, newState);
102
+ return _extends({}, prevState, {
103
+ nodes: newState
104
+ });
98
105
  });
99
106
  }, [instance, setState, params.items, params.isItemDisabled, params.getItemId, params.getItemLabel]);
100
107
  const getNodesToRender = useEventCallback(() => {
@@ -102,7 +109,7 @@ export const useTreeViewNodes = ({
102
109
  id,
103
110
  children
104
111
  }) => {
105
- const node = state.nodeMap[id];
112
+ const node = state.nodes.nodeMap[id];
106
113
  return {
107
114
  label: node.label,
108
115
  nodeId: node.id,
@@ -110,26 +117,32 @@ export const useTreeViewNodes = ({
110
117
  children: children == null ? void 0 : children.map(getPropsFromNodeId)
111
118
  };
112
119
  };
113
- return state.nodeTree.map(getPropsFromNodeId);
120
+ return state.nodes.nodeTree.map(getPropsFromNodeId);
114
121
  });
115
122
  populateInstance(instance, {
116
123
  getNode,
124
+ getItem,
117
125
  getNodesToRender,
118
126
  getChildrenIds,
119
127
  getNavigableChildrenIds,
120
128
  isNodeDisabled
121
129
  });
130
+ populatePublicAPI(publicAPI, {
131
+ getItem
132
+ });
122
133
  return {
123
134
  contextValue: {
124
135
  disabledItemsFocusable: params.disabledItemsFocusable
125
136
  }
126
137
  };
127
138
  };
128
- useTreeViewNodes.getInitialState = params => updateState({
129
- items: params.items,
130
- isItemDisabled: params.isItemDisabled,
131
- getItemId: params.getItemId,
132
- getItemLabel: params.getItemLabel
139
+ useTreeViewNodes.getInitialState = params => ({
140
+ nodes: updateNodesState({
141
+ items: params.items,
142
+ isItemDisabled: params.isItemDisabled,
143
+ getItemId: params.getItemId,
144
+ getItemLabel: params.getItemLabel
145
+ })
133
146
  });
134
147
  useTreeViewNodes.getDefaultizedParams = params => {
135
148
  var _params$disabledItems;
@@ -6,13 +6,16 @@ interface TreeViewNodeProps {
6
6
  id: string | undefined;
7
7
  children?: TreeViewNodeProps[];
8
8
  }
9
- export interface UseTreeViewNodesInstance {
9
+ export interface UseTreeViewNodesInstance<R extends {}> {
10
10
  getNode: (nodeId: string) => TreeViewNode;
11
+ getItem: (nodeId: string) => R;
11
12
  getNodesToRender: () => TreeViewNodeProps[];
12
13
  getChildrenIds: (nodeId: string | null) => string[];
13
14
  getNavigableChildrenIds: (nodeId: string | null) => string[];
14
15
  isNodeDisabled: (nodeId: string | null) => nodeId is string;
15
16
  }
17
+ export interface UseTreeViewNodesPublicAPI<R extends {}> extends Pick<UseTreeViewNodesInstance<R>, 'getItem'> {
18
+ }
16
19
  export interface UseTreeViewNodesParameters<R extends {}> {
17
20
  /**
18
21
  * If `true`, will allow focus on disabled items.
@@ -58,21 +61,28 @@ export interface TreeViewNodeIdAndChildren {
58
61
  id: TreeViewItemId;
59
62
  children?: TreeViewNodeIdAndChildren[];
60
63
  }
61
- export interface UseTreeViewNodesState {
62
- nodeTree: TreeViewNodeIdAndChildren[];
63
- nodeMap: TreeViewNodeMap;
64
+ export interface UseTreeViewNodesState<R extends {}> {
65
+ nodes: {
66
+ nodeTree: TreeViewNodeIdAndChildren[];
67
+ nodeMap: TreeViewNodeMap;
68
+ itemMap: TreeViewItemMap<R>;
69
+ };
64
70
  }
65
71
  interface UseTreeViewNodesContextValue extends Pick<UseTreeViewNodesDefaultizedParameters<any>, 'disabledItemsFocusable'> {
66
72
  }
67
73
  export type UseTreeViewNodesSignature = TreeViewPluginSignature<{
68
74
  params: UseTreeViewNodesParameters<any>;
69
75
  defaultizedParams: UseTreeViewNodesDefaultizedParameters<any>;
70
- instance: UseTreeViewNodesInstance;
76
+ instance: UseTreeViewNodesInstance<any>;
77
+ publicAPI: UseTreeViewNodesPublicAPI<any>;
71
78
  events: UseTreeViewNodesEventLookup;
72
- state: UseTreeViewNodesState;
79
+ state: UseTreeViewNodesState<any>;
73
80
  contextValue: UseTreeViewNodesContextValue;
74
81
  }>;
75
82
  export type TreeViewNodeMap = {
76
83
  [nodeId: string]: TreeViewNode;
77
84
  };
85
+ export type TreeViewItemMap<R extends {}> = {
86
+ [nodeId: string]: R;
87
+ };
78
88
  export {};
@@ -137,7 +137,8 @@ process.env.NODE_ENV !== "production" ? RichTreeView.propTypes = {
137
137
  */
138
138
  apiRef: PropTypes.shape({
139
139
  current: PropTypes.shape({
140
- focusNode: PropTypes.func.isRequired
140
+ focusNode: PropTypes.func.isRequired,
141
+ getItem: PropTypes.func.isRequired
141
142
  })
142
143
  }),
143
144
  /**
@@ -95,7 +95,8 @@ process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
95
95
  */
96
96
  apiRef: PropTypes.shape({
97
97
  current: PropTypes.shape({
98
- focusNode: PropTypes.func.isRequired
98
+ focusNode: PropTypes.func.isRequired,
99
+ getItem: PropTypes.func.isRequired
99
100
  })
100
101
  }),
101
102
  /**
@@ -1,6 +1,6 @@
1
1
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
2
2
  import _extends from "@babel/runtime/helpers/esm/extends";
3
- const _excluded = ["children", "className", "slots", "slotProps", "ContentComponent", "ContentProps", "nodeId", "id", "label", "onClick", "onMouseDown", "TransitionComponent", "TransitionProps"],
3
+ const _excluded = ["children", "className", "slots", "slotProps", "ContentComponent", "ContentProps", "nodeId", "id", "label", "onClick", "onMouseDown"],
4
4
  _excluded2 = ["ownerState"],
5
5
  _excluded3 = ["ownerState"],
6
6
  _excluded4 = ["ownerState"];
@@ -32,7 +32,7 @@ const useUtilityClasses = ownerState => {
32
32
  disabled: ['disabled'],
33
33
  iconContainer: ['iconContainer'],
34
34
  label: ['label'],
35
- group: ['group']
35
+ groupTransition: ['groupTransition']
36
36
  };
37
37
  return composeClasses(slots, getTreeItemUtilityClass, classes);
38
38
  };
@@ -116,8 +116,8 @@ const StyledTreeItemContent = styled(TreeItemContent, {
116
116
  }));
117
117
  const TreeItemGroup = styled(Collapse, {
118
118
  name: 'MuiTreeItem',
119
- slot: 'Group',
120
- overridesResolver: (props, styles) => styles.group
119
+ slot: 'GroupTransition',
120
+ overridesResolver: (props, styles) => styles.groupTransition
121
121
  })({
122
122
  margin: 0,
123
123
  padding: 0,
@@ -167,16 +167,15 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
167
167
  id,
168
168
  label,
169
169
  onClick,
170
- onMouseDown,
171
- TransitionComponent = Collapse,
172
- TransitionProps
170
+ onMouseDown
173
171
  } = props,
174
172
  other = _objectWithoutPropertiesLoose(props, _excluded);
175
173
  const slots = {
176
174
  expandIcon: inSlots?.expandIcon ?? contextIcons.slots.expandIcon ?? TreeViewExpandIcon,
177
175
  collapseIcon: inSlots?.collapseIcon ?? contextIcons.slots.collapseIcon ?? TreeViewCollapseIcon,
178
176
  endIcon: inSlots?.endIcon ?? contextIcons.slots.endIcon,
179
- icon: inSlots?.icon
177
+ icon: inSlots?.icon,
178
+ groupTransition: inSlots?.groupTransition
180
179
  };
181
180
  const isExpandable = reactChildren => {
182
181
  if (Array.isArray(reactChildren)) {
@@ -196,6 +195,19 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
196
195
  disabled
197
196
  });
198
197
  const classes = useUtilityClasses(ownerState);
198
+ const GroupTransition = slots.groupTransition ?? undefined;
199
+ const groupTransitionProps = useSlotProps({
200
+ elementType: GroupTransition,
201
+ ownerState: {},
202
+ externalSlotProps: inSlotProps?.groupTransition,
203
+ additionalProps: {
204
+ unmountOnExit: true,
205
+ in: expanded,
206
+ component: 'ul',
207
+ role: 'group'
208
+ },
209
+ className: classes.groupTransition
210
+ });
199
211
  const ExpansionIcon = expanded ? slots.collapseIcon : slots.expandIcon;
200
212
  const _useSlotProps = useSlotProps({
201
213
  elementType: ExpansionIcon,
@@ -285,13 +297,8 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
285
297
  displayIcon: displayIcon,
286
298
  ownerState: ownerState
287
299
  }, ContentProps)), children && /*#__PURE__*/_jsx(TreeItemGroup, _extends({
288
- as: TransitionComponent,
289
- unmountOnExit: true,
290
- className: classes.group,
291
- in: expanded,
292
- component: "ul",
293
- role: "group"
294
- }, TransitionProps, {
300
+ as: GroupTransition
301
+ }, groupTransitionProps, {
295
302
  children: children
296
303
  }))]
297
304
  }));
@@ -351,16 +358,5 @@ TreeItem.propTypes = {
351
358
  /**
352
359
  * The system prop that allows defining system overrides as well as additional CSS styles.
353
360
  */
354
- sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object]),
355
- /**
356
- * The component used for the transition.
357
- * [Follow this guide](/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component.
358
- * @default Collapse
359
- */
360
- TransitionComponent: PropTypes.elementType,
361
- /**
362
- * Props applied to the transition element.
363
- * By default, the element is based on this [`Transition`](https://reactcommunity.org/react-transition-group/transition/) component.
364
- */
365
- TransitionProps: PropTypes.object
361
+ sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
366
362
  };
@@ -3,4 +3,4 @@ import generateUtilityClasses from '@mui/utils/generateUtilityClasses';
3
3
  export function getTreeItemUtilityClass(slot) {
4
4
  return generateUtilityClass('MuiTreeItem', slot);
5
5
  }
6
- export const treeItemClasses = generateUtilityClasses('MuiTreeItem', ['root', 'group', 'content', 'expanded', 'selected', 'focused', 'disabled', 'iconContainer', 'label']);
6
+ export const treeItemClasses = generateUtilityClasses('MuiTreeItem', ['root', 'groupTransition', 'content', 'expanded', 'selected', 'focused', 'disabled', 'iconContainer', 'label']);
@@ -69,7 +69,8 @@ process.env.NODE_ENV !== "production" ? TreeView.propTypes = {
69
69
  */
70
70
  apiRef: PropTypes.shape({
71
71
  current: PropTypes.shape({
72
- focusNode: PropTypes.func.isRequired
72
+ focusNode: PropTypes.func.isRequired,
73
+ getItem: PropTypes.func.isRequired
73
74
  })
74
75
  }),
75
76
  /**
package/modern/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-tree-view v7.0.0-beta.5
2
+ * @mui/x-tree-view v7.0.0-beta.6
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -13,22 +13,36 @@ export const useTreeViewJSXNodes = ({
13
13
  }) => {
14
14
  const insertJSXNode = useEventCallback(node => {
15
15
  setState(prevState => {
16
- if (prevState.nodeMap[node.id] != null) {
16
+ if (prevState.nodes.nodeMap[node.id] != null) {
17
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'));
18
18
  }
19
19
  return _extends({}, prevState, {
20
- nodeMap: _extends({}, prevState.nodeMap, {
21
- [node.id]: node
20
+ nodes: _extends({}, prevState.nodes, {
21
+ nodeMap: _extends({}, prevState.nodes.nodeMap, {
22
+ [node.id]: node
23
+ }),
24
+ // 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
29
+ }
30
+ })
22
31
  })
23
32
  });
24
33
  });
25
34
  });
26
35
  const removeJSXNode = useEventCallback(nodeId => {
27
36
  setState(prevState => {
28
- const newMap = _extends({}, prevState.nodeMap);
29
- delete newMap[nodeId];
37
+ const newNodeMap = _extends({}, prevState.nodes.nodeMap);
38
+ const newItemMap = _extends({}, prevState.nodes.itemMap);
39
+ delete newNodeMap[nodeId];
40
+ delete newItemMap[nodeId];
30
41
  return _extends({}, prevState, {
31
- nodeMap: newMap
42
+ nodes: _extends({}, prevState.nodes, {
43
+ nodeMap: newNodeMap,
44
+ itemMap: newItemMap
45
+ })
32
46
  });
33
47
  });
34
48
  publishTreeViewEvent(instance, 'removeNode', {
@@ -1,15 +1,16 @@
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 } from '../../useTreeView/useTreeView.utils';
4
+ import { populateInstance, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
5
5
  import { publishTreeViewEvent } from '../../utils/publishTreeViewEvent';
6
- const updateState = ({
6
+ const updateNodesState = ({
7
7
  items,
8
8
  isItemDisabled,
9
9
  getItemLabel,
10
10
  getItemId
11
11
  }) => {
12
12
  const nodeMap = {};
13
+ const itemMap = {};
13
14
  const processItem = (item, index, parentId) => {
14
15
  const id = getItemId ? getItemId(item) : item.id;
15
16
  if (id == null) {
@@ -27,10 +28,11 @@ const updateState = ({
27
28
  label,
28
29
  index,
29
30
  parentId,
30
- idAttribute: id,
31
+ idAttribute: undefined,
31
32
  expandable: !!item.children?.length,
32
33
  disabled: isItemDisabled ? isItemDisabled(item) : false
33
34
  };
35
+ itemMap[id] = item;
34
36
  return {
35
37
  id,
36
38
  children: item.children?.map((child, childIndex) => processItem(child, childIndex, id))
@@ -39,16 +41,19 @@ const updateState = ({
39
41
  const nodeTree = items.map((item, itemIndex) => processItem(item, itemIndex, null));
40
42
  return {
41
43
  nodeMap,
42
- nodeTree
44
+ nodeTree,
45
+ itemMap
43
46
  };
44
47
  };
45
48
  export const useTreeViewNodes = ({
46
49
  instance,
50
+ publicAPI,
47
51
  params,
48
52
  state,
49
53
  setState
50
54
  }) => {
51
- const getNode = React.useCallback(nodeId => state.nodeMap[nodeId], [state.nodeMap]);
55
+ const getNode = React.useCallback(nodeId => state.nodes.nodeMap[nodeId], [state.nodes.nodeMap]);
56
+ const getItem = React.useCallback(nodeId => state.nodes.itemMap[nodeId], [state.nodes.itemMap]);
52
57
  const isNodeDisabled = React.useCallback(nodeId => {
53
58
  if (nodeId == null) {
54
59
  return false;
@@ -70,7 +75,7 @@ export const useTreeViewNodes = ({
70
75
  }
71
76
  return false;
72
77
  }, [instance]);
73
- const getChildrenIds = useEventCallback(nodeId => Object.values(state.nodeMap).filter(node => node.parentId === nodeId).sort((a, b) => a.index - b.index).map(child => child.id));
78
+ 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));
74
79
  const getNavigableChildrenIds = nodeId => {
75
80
  let childrenIds = instance.getChildrenIds(nodeId);
76
81
  if (!params.disabledItemsFocusable) {
@@ -80,20 +85,22 @@ export const useTreeViewNodes = ({
80
85
  };
81
86
  React.useEffect(() => {
82
87
  setState(prevState => {
83
- const newState = updateState({
88
+ const newState = updateNodesState({
84
89
  items: params.items,
85
90
  isItemDisabled: params.isItemDisabled,
86
91
  getItemId: params.getItemId,
87
92
  getItemLabel: params.getItemLabel
88
93
  });
89
- Object.values(prevState.nodeMap).forEach(node => {
94
+ Object.values(prevState.nodes.nodeMap).forEach(node => {
90
95
  if (!newState.nodeMap[node.id]) {
91
96
  publishTreeViewEvent(instance, 'removeNode', {
92
97
  id: node.id
93
98
  });
94
99
  }
95
100
  });
96
- return _extends({}, prevState, newState);
101
+ return _extends({}, prevState, {
102
+ nodes: newState
103
+ });
97
104
  });
98
105
  }, [instance, setState, params.items, params.isItemDisabled, params.getItemId, params.getItemLabel]);
99
106
  const getNodesToRender = useEventCallback(() => {
@@ -101,7 +108,7 @@ export const useTreeViewNodes = ({
101
108
  id,
102
109
  children
103
110
  }) => {
104
- const node = state.nodeMap[id];
111
+ const node = state.nodes.nodeMap[id];
105
112
  return {
106
113
  label: node.label,
107
114
  nodeId: node.id,
@@ -109,26 +116,32 @@ export const useTreeViewNodes = ({
109
116
  children: children?.map(getPropsFromNodeId)
110
117
  };
111
118
  };
112
- return state.nodeTree.map(getPropsFromNodeId);
119
+ return state.nodes.nodeTree.map(getPropsFromNodeId);
113
120
  });
114
121
  populateInstance(instance, {
115
122
  getNode,
123
+ getItem,
116
124
  getNodesToRender,
117
125
  getChildrenIds,
118
126
  getNavigableChildrenIds,
119
127
  isNodeDisabled
120
128
  });
129
+ populatePublicAPI(publicAPI, {
130
+ getItem
131
+ });
121
132
  return {
122
133
  contextValue: {
123
134
  disabledItemsFocusable: params.disabledItemsFocusable
124
135
  }
125
136
  };
126
137
  };
127
- useTreeViewNodes.getInitialState = params => updateState({
128
- items: params.items,
129
- isItemDisabled: params.isItemDisabled,
130
- getItemId: params.getItemId,
131
- getItemLabel: params.getItemLabel
138
+ useTreeViewNodes.getInitialState = params => ({
139
+ nodes: updateNodesState({
140
+ items: params.items,
141
+ isItemDisabled: params.isItemDisabled,
142
+ getItemId: params.getItemId,
143
+ getItemLabel: params.getItemLabel
144
+ })
132
145
  });
133
146
  useTreeViewNodes.getDefaultizedParams = params => _extends({}, params, {
134
147
  disabledItemsFocusable: params.disabledItemsFocusable ?? false
@@ -146,7 +146,8 @@ process.env.NODE_ENV !== "production" ? RichTreeView.propTypes = {
146
146
  */
147
147
  apiRef: _propTypes.default.shape({
148
148
  current: _propTypes.default.shape({
149
- focusNode: _propTypes.default.func.isRequired
149
+ focusNode: _propTypes.default.func.isRequired,
150
+ getItem: _propTypes.default.func.isRequired
150
151
  })
151
152
  }),
152
153
  /**
@@ -104,7 +104,8 @@ process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
104
104
  */
105
105
  apiRef: _propTypes.default.shape({
106
106
  current: _propTypes.default.shape({
107
- focusNode: _propTypes.default.func.isRequired
107
+ focusNode: _propTypes.default.func.isRequired,
108
+ getItem: _propTypes.default.func.isRequired
108
109
  })
109
110
  }),
110
111
  /**