@mui/x-tree-view 7.0.0 → 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 (95) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/RichTreeView/RichTreeView.js +4 -4
  3. package/SimpleTreeView/SimpleTreeView.plugins.d.ts +1 -1
  4. package/SimpleTreeView/SimpleTreeView.plugins.js +2 -2
  5. package/TreeItem/TreeItem.js +4 -4
  6. package/TreeItem/treeItemClasses.d.ts +1 -1
  7. package/TreeItem/useTreeItemState.js +9 -9
  8. package/TreeItem2Icon/TreeItem2Icon.types.d.ts +4 -4
  9. package/hooks/useTreeItem2Utils/useTreeItem2Utils.js +8 -8
  10. package/hooks/useTreeViewApiRef.d.ts +1 -1
  11. package/index.js +1 -1
  12. package/internals/TreeViewProvider/DescendantProvider.d.ts +1 -1
  13. package/internals/TreeViewProvider/DescendantProvider.js +1 -1
  14. package/internals/index.d.ts +2 -2
  15. package/internals/plugins/defaultPlugins.d.ts +3 -3
  16. package/internals/plugins/defaultPlugins.js +2 -2
  17. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +9 -9
  18. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +5 -5
  19. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +35 -33
  20. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +6 -6
  21. package/internals/plugins/useTreeViewIcons/useTreeViewIcons.types.d.ts +6 -6
  22. package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +1 -1
  23. package/internals/plugins/useTreeViewItems/index.d.ts +2 -0
  24. package/internals/plugins/useTreeViewItems/index.js +1 -0
  25. package/internals/plugins/useTreeViewItems/useTreeViewItems.d.ts +3 -0
  26. package/internals/plugins/{useTreeViewNodes/useTreeViewNodes.js → useTreeViewItems/useTreeViewItems.js} +42 -32
  27. package/internals/plugins/{useTreeViewNodes/useTreeViewNodes.types.d.ts → useTreeViewItems/useTreeViewItems.types.d.ts} +32 -21
  28. package/internals/plugins/useTreeViewJSXItems/index.d.ts +2 -0
  29. package/internals/plugins/useTreeViewJSXItems/index.js +1 -0
  30. package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.d.ts +3 -0
  31. package/{modern/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js → internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js} +26 -25
  32. package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.types.d.ts +18 -0
  33. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +40 -44
  34. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +2 -2
  35. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +34 -34
  36. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +6 -6
  37. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.d.ts +7 -7
  38. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +5 -5
  39. package/internals/useTreeView/useTreeView.utils.d.ts +5 -5
  40. package/internals/useTreeView/useTreeView.utils.js +15 -15
  41. package/modern/RichTreeView/RichTreeView.js +4 -4
  42. package/modern/SimpleTreeView/SimpleTreeView.plugins.js +2 -2
  43. package/modern/TreeItem/TreeItem.js +4 -4
  44. package/modern/TreeItem/useTreeItemState.js +9 -9
  45. package/modern/hooks/useTreeItem2Utils/useTreeItem2Utils.js +8 -8
  46. package/modern/index.js +1 -1
  47. package/modern/internals/TreeViewProvider/DescendantProvider.js +1 -1
  48. package/modern/internals/plugins/defaultPlugins.js +2 -2
  49. package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +9 -9
  50. package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +35 -33
  51. package/modern/internals/plugins/useTreeViewItems/index.js +1 -0
  52. package/modern/internals/plugins/{useTreeViewNodes/useTreeViewNodes.js → useTreeViewItems/useTreeViewItems.js} +42 -32
  53. package/modern/internals/plugins/useTreeViewJSXItems/index.js +1 -0
  54. package/{internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js → modern/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js} +26 -25
  55. package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +40 -44
  56. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +34 -34
  57. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +5 -5
  58. package/modern/internals/useTreeView/useTreeView.utils.js +15 -15
  59. package/node/RichTreeView/RichTreeView.js +4 -4
  60. package/node/SimpleTreeView/SimpleTreeView.plugins.js +2 -2
  61. package/node/TreeItem/TreeItem.js +4 -4
  62. package/node/TreeItem/useTreeItemState.js +9 -9
  63. package/node/hooks/useTreeItem2Utils/useTreeItem2Utils.js +8 -8
  64. package/node/index.js +1 -1
  65. package/node/internals/TreeViewProvider/DescendantProvider.js +1 -1
  66. package/node/internals/plugins/defaultPlugins.js +2 -2
  67. package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +9 -9
  68. package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +35 -33
  69. package/node/internals/plugins/useTreeViewItems/index.js +12 -0
  70. package/node/internals/plugins/{useTreeViewNodes/useTreeViewNodes.js → useTreeViewItems/useTreeViewItems.js} +44 -34
  71. package/node/internals/plugins/useTreeViewJSXItems/index.js +12 -0
  72. package/node/internals/plugins/{useTreeViewJSXNodes/useTreeViewJSXNodes.js → useTreeViewJSXItems/useTreeViewJSXItems.js} +28 -27
  73. package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +39 -43
  74. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +33 -33
  75. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +5 -5
  76. package/node/internals/useTreeView/useTreeView.utils.js +20 -20
  77. package/package.json +1 -1
  78. package/useTreeItem2/useTreeItem2.d.ts +1 -1
  79. package/internals/plugins/useTreeViewJSXNodes/index.d.ts +0 -2
  80. package/internals/plugins/useTreeViewJSXNodes/index.js +0 -1
  81. package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.d.ts +0 -3
  82. package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.types.d.ts +0 -18
  83. package/internals/plugins/useTreeViewNodes/index.d.ts +0 -2
  84. package/internals/plugins/useTreeViewNodes/index.js +0 -1
  85. package/internals/plugins/useTreeViewNodes/useTreeViewNodes.d.ts +0 -3
  86. package/modern/internals/plugins/useTreeViewJSXNodes/index.js +0 -1
  87. package/modern/internals/plugins/useTreeViewNodes/index.js +0 -1
  88. package/node/internals/plugins/useTreeViewJSXNodes/index.js +0 -12
  89. package/node/internals/plugins/useTreeViewNodes/index.js +0 -12
  90. /package/internals/plugins/{useTreeViewJSXNodes/useTreeViewJSXNodes.types.js → useTreeViewItems/useTreeViewItems.types.js} +0 -0
  91. /package/internals/plugins/{useTreeViewNodes/useTreeViewNodes.types.js → useTreeViewJSXItems/useTreeViewJSXItems.types.js} +0 -0
  92. /package/modern/internals/plugins/{useTreeViewJSXNodes/useTreeViewJSXNodes.types.js → useTreeViewItems/useTreeViewItems.types.js} +0 -0
  93. /package/modern/internals/plugins/{useTreeViewNodes/useTreeViewNodes.types.js → useTreeViewJSXItems/useTreeViewJSXItems.types.js} +0 -0
  94. /package/node/internals/plugins/{useTreeViewJSXNodes/useTreeViewJSXNodes.types.js → useTreeViewItems/useTreeViewItems.types.js} +0 -0
  95. /package/node/internals/plugins/{useTreeViewNodes/useTreeViewNodes.types.js → useTreeViewJSXItems/useTreeViewJSXItems.types.js} +0 -0
@@ -0,0 +1,3 @@
1
+ import { TreeViewPlugin } from '../../models';
2
+ import { UseTreeViewItemsSignature } from './useTreeViewItems.types';
3
+ export declare const useTreeViewItems: TreeViewPlugin<UseTreeViewItemsSignature>;
@@ -2,7 +2,7 @@ import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
3
  import { populateInstance, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
4
4
  import { publishTreeViewEvent } from '../../utils/publishTreeViewEvent';
5
- const updateNodesState = ({
5
+ const updateItemsState = ({
6
6
  items,
7
7
  isItemDisabled,
8
8
  getItemLabel,
@@ -44,86 +44,96 @@ const updateNodesState = ({
44
44
  itemMap
45
45
  };
46
46
  };
47
- export const useTreeViewNodes = ({
47
+ export const useTreeViewItems = ({
48
48
  instance,
49
49
  publicAPI,
50
50
  params,
51
51
  state,
52
52
  setState
53
53
  }) => {
54
- const getNode = React.useCallback(itemId => state.nodes.nodeMap[itemId], [state.nodes.nodeMap]);
55
- const getItem = React.useCallback(itemId => state.nodes.itemMap[itemId], [state.nodes.itemMap]);
56
- const isNodeDisabled = React.useCallback(itemId => {
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
57
  if (itemId == null) {
58
58
  return false;
59
59
  }
60
- let item = instance.getNode(itemId);
60
+ let node = instance.getNode(itemId);
61
61
 
62
- // This can be called before the item has been added to the node map.
63
- if (!item) {
62
+ // This can be called before the item has been added to the item map.
63
+ if (!node) {
64
64
  return false;
65
65
  }
66
- if (item.disabled) {
66
+ if (node.disabled) {
67
67
  return true;
68
68
  }
69
- while (item.parentId != null) {
70
- item = instance.getNode(item.parentId);
71
- if (item.disabled) {
69
+ while (node.parentId != null) {
70
+ node = instance.getNode(node.parentId);
71
+ if (node.disabled) {
72
72
  return true;
73
73
  }
74
74
  }
75
75
  return false;
76
76
  }, [instance]);
77
- const getChildrenIds = React.useCallback(itemId => Object.values(state.nodes.nodeMap).filter(item => item.parentId === itemId).sort((a, b) => a.index - b.index).map(child => child.id), [state.nodes.nodeMap]);
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
78
  const getNavigableChildrenIds = itemId => {
79
79
  let childrenIds = instance.getChildrenIds(itemId);
80
80
  if (!params.disabledItemsFocusable) {
81
- childrenIds = childrenIds.filter(item => !instance.isNodeDisabled(item));
81
+ childrenIds = childrenIds.filter(item => !instance.isItemDisabled(item));
82
82
  }
83
83
  return childrenIds;
84
84
  };
85
+ const areItemUpdatesPreventedRef = React.useRef(false);
86
+ const preventItemUpdates = React.useCallback(() => {
87
+ areItemUpdatesPreventedRef.current = true;
88
+ }, []);
89
+ const areItemUpdatesPrevented = React.useCallback(() => areItemUpdatesPreventedRef.current, []);
85
90
  React.useEffect(() => {
91
+ if (instance.areItemUpdatesPrevented()) {
92
+ return;
93
+ }
86
94
  setState(prevState => {
87
- const newState = updateNodesState({
95
+ const newState = updateItemsState({
88
96
  items: params.items,
89
97
  isItemDisabled: params.isItemDisabled,
90
98
  getItemId: params.getItemId,
91
99
  getItemLabel: params.getItemLabel
92
100
  });
93
- Object.values(prevState.nodes.nodeMap).forEach(node => {
94
- if (!newState.nodeMap[node.id]) {
95
- publishTreeViewEvent(instance, 'removeNode', {
96
- 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
97
105
  });
98
106
  }
99
107
  });
100
108
  return _extends({}, prevState, {
101
- nodes: newState
109
+ items: newState
102
110
  });
103
111
  });
104
112
  }, [instance, setState, params.items, params.isItemDisabled, params.getItemId, params.getItemLabel]);
105
- const getNodesToRender = () => {
113
+ const getItemsToRender = () => {
106
114
  const getPropsFromItemId = ({
107
115
  id,
108
116
  children
109
117
  }) => {
110
- const node = state.nodes.nodeMap[id];
118
+ const item = state.items.nodeMap[id];
111
119
  return {
112
- label: node.label,
113
- itemId: node.id,
114
- id: node.idAttribute,
120
+ label: item.label,
121
+ itemId: item.id,
122
+ id: item.idAttribute,
115
123
  children: children?.map(getPropsFromItemId)
116
124
  };
117
125
  };
118
- return state.nodes.nodeTree.map(getPropsFromItemId);
126
+ return state.items.nodeTree.map(getPropsFromItemId);
119
127
  };
120
128
  populateInstance(instance, {
121
129
  getNode,
122
130
  getItem,
123
- getNodesToRender,
131
+ getItemsToRender,
124
132
  getChildrenIds,
125
133
  getNavigableChildrenIds,
126
- isNodeDisabled
134
+ isItemDisabled,
135
+ preventItemUpdates,
136
+ areItemUpdatesPrevented
127
137
  });
128
138
  populatePublicAPI(publicAPI, {
129
139
  getItem
@@ -134,18 +144,18 @@ export const useTreeViewNodes = ({
134
144
  }
135
145
  };
136
146
  };
137
- useTreeViewNodes.getInitialState = params => ({
138
- nodes: updateNodesState({
147
+ useTreeViewItems.getInitialState = params => ({
148
+ items: updateItemsState({
139
149
  items: params.items,
140
150
  isItemDisabled: params.isItemDisabled,
141
151
  getItemId: params.getItemId,
142
152
  getItemLabel: params.getItemLabel
143
153
  })
144
154
  });
145
- useTreeViewNodes.getDefaultizedParams = params => _extends({}, params, {
155
+ useTreeViewItems.getDefaultizedParams = params => _extends({}, params, {
146
156
  disabledItemsFocusable: params.disabledItemsFocusable ?? false
147
157
  });
148
- useTreeViewNodes.params = {
158
+ useTreeViewItems.params = {
149
159
  disabledItemsFocusable: true,
150
160
  items: true,
151
161
  isItemDisabled: true,
@@ -1,22 +1,33 @@
1
1
  import { TreeViewNode, DefaultizedProps, TreeViewPluginSignature } from '../../models';
2
2
  import { TreeViewItemId } from '../../../models';
3
- interface TreeViewNodeProps {
3
+ interface TreeViewItemProps {
4
4
  label: string;
5
5
  itemId: string;
6
6
  id: string | undefined;
7
- children?: TreeViewNodeProps[];
7
+ children?: TreeViewItemProps[];
8
8
  }
9
- export interface UseTreeViewNodesInstance<R extends {}> {
9
+ export interface UseTreeViewItemsInstance<R extends {}> {
10
10
  getNode: (itemId: string) => TreeViewNode;
11
11
  getItem: (itemId: string) => R;
12
- getNodesToRender: () => TreeViewNodeProps[];
12
+ getItemsToRender: () => TreeViewItemProps[];
13
13
  getChildrenIds: (itemId: string | null) => string[];
14
14
  getNavigableChildrenIds: (itemId: string | null) => string[];
15
- isNodeDisabled: (itemId: string | null) => itemId is string;
15
+ isItemDisabled: (itemId: string | null) => itemId is string;
16
+ /**
17
+ * Freeze any future update to the state based on the `items` prop.
18
+ * This is useful when `useTreeViewJSXNodes` is used to avoid having conflicting sources of truth.
19
+ */
20
+ preventItemUpdates: () => void;
21
+ /**
22
+ * Check if the updates to the state based on the `items` prop are prevented.
23
+ * This is useful when `useTreeViewJSXNodes` is used to avoid having conflicting sources of truth.
24
+ * @returns {boolean} `true` if the updates to the state based on the `items` prop are prevented.
25
+ */
26
+ areItemUpdatesPrevented: () => boolean;
16
27
  }
17
- export interface UseTreeViewNodesPublicAPI<R extends {}> extends Pick<UseTreeViewNodesInstance<R>, 'getItem'> {
28
+ export interface UseTreeViewItemsPublicAPI<R extends {}> extends Pick<UseTreeViewItemsInstance<R>, 'getItem'> {
18
29
  }
19
- export interface UseTreeViewNodesParameters<R extends {}> {
30
+ export interface UseTreeViewItemsParameters<R extends {}> {
20
31
  /**
21
32
  * If `true`, will allow focus on disabled items.
22
33
  * @default false
@@ -49,9 +60,9 @@ export interface UseTreeViewNodesParameters<R extends {}> {
49
60
  */
50
61
  getItemId?: (item: R) => TreeViewItemId;
51
62
  }
52
- export type UseTreeViewNodesDefaultizedParameters<R extends {}> = DefaultizedProps<UseTreeViewNodesParameters<R>, 'disabledItemsFocusable'>;
53
- interface UseTreeViewNodesEventLookup {
54
- removeNode: {
63
+ export type UseTreeViewItemsDefaultizedParameters<R extends {}> = DefaultizedProps<UseTreeViewItemsParameters<R>, 'disabledItemsFocusable'>;
64
+ interface UseTreeViewItemsEventLookup {
65
+ removeItem: {
55
66
  params: {
56
67
  id: string;
57
68
  };
@@ -61,23 +72,23 @@ export interface TreeViewItemIdAndChildren {
61
72
  id: TreeViewItemId;
62
73
  children?: TreeViewItemIdAndChildren[];
63
74
  }
64
- export interface UseTreeViewNodesState<R extends {}> {
65
- nodes: {
75
+ export interface UseTreeViewItemsState<R extends {}> {
76
+ items: {
66
77
  nodeTree: TreeViewItemIdAndChildren[];
67
78
  nodeMap: TreeViewNodeMap;
68
79
  itemMap: TreeViewItemMap<R>;
69
80
  };
70
81
  }
71
- interface UseTreeViewNodesContextValue extends Pick<UseTreeViewNodesDefaultizedParameters<any>, 'disabledItemsFocusable'> {
82
+ interface UseTreeViewItemsContextValue extends Pick<UseTreeViewItemsDefaultizedParameters<any>, 'disabledItemsFocusable'> {
72
83
  }
73
- export type UseTreeViewNodesSignature = TreeViewPluginSignature<{
74
- params: UseTreeViewNodesParameters<any>;
75
- defaultizedParams: UseTreeViewNodesDefaultizedParameters<any>;
76
- instance: UseTreeViewNodesInstance<any>;
77
- publicAPI: UseTreeViewNodesPublicAPI<any>;
78
- events: UseTreeViewNodesEventLookup;
79
- state: UseTreeViewNodesState<any>;
80
- contextValue: UseTreeViewNodesContextValue;
84
+ export type UseTreeViewItemsSignature = TreeViewPluginSignature<{
85
+ params: UseTreeViewItemsParameters<any>;
86
+ defaultizedParams: UseTreeViewItemsDefaultizedParameters<any>;
87
+ instance: UseTreeViewItemsInstance<any>;
88
+ publicAPI: UseTreeViewItemsPublicAPI<any>;
89
+ events: UseTreeViewItemsEventLookup;
90
+ state: UseTreeViewItemsState<any>;
91
+ contextValue: UseTreeViewItemsContextValue;
81
92
  }>;
82
93
  export type TreeViewNodeMap = {
83
94
  [itemId: string]: TreeViewNode;
@@ -0,0 +1,2 @@
1
+ export { useTreeViewJSXItems } from './useTreeViewJSXItems';
2
+ export type { UseTreeViewJSXItemsSignature, UseTreeViewItemsParameters, UseTreeViewItemsDefaultizedParameters, } from './useTreeViewJSXItems.types';
@@ -0,0 +1 @@
1
+ export { useTreeViewJSXItems } from './useTreeViewJSXItems';
@@ -0,0 +1,3 @@
1
+ import { TreeViewPlugin } from '../../models';
2
+ import { UseTreeViewJSXItemsSignature } from './useTreeViewJSXItems.types';
3
+ export declare const useTreeViewJSXItems: TreeViewPlugin<UseTreeViewJSXItemsSignature>;
@@ -7,45 +7,46 @@ 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(itemId => {
36
+ const removeJSXItem = useEventCallback(itemId => {
36
37
  setState(prevState => {
37
- const newNodeMap = _extends({}, prevState.nodes.nodeMap);
38
- const newItemMap = _extends({}, prevState.nodes.itemMap);
38
+ const newNodeMap = _extends({}, prevState.items.nodeMap);
39
+ const newItemMap = _extends({}, prevState.items.itemMap);
39
40
  delete newNodeMap[itemId];
40
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
+ publishTreeViewEvent(instance, 'removeItem', {
49
50
  id: itemId
50
51
  });
51
52
  });
@@ -63,12 +64,12 @@ export const useTreeViewJSXNodes = ({
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
@@ -103,9 +104,9 @@ const useTreeViewJSXNodesItemPlugin = ({
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
+ instance.insertJSXItem({
109
110
  id: itemId,
110
111
  idAttribute: id,
111
112
  index,
@@ -113,7 +114,7 @@ const useTreeViewJSXNodesItemPlugin = ({
113
114
  expandable,
114
115
  disabled
115
116
  });
116
- return () => instance.removeJSXNode(itemId);
117
+ return () => instance.removeJSXItem(itemId);
117
118
  }
118
119
  return undefined;
119
120
  }, [instance, parentId, index, itemId, expandable, disabled, id]);
@@ -128,12 +129,12 @@ const useTreeViewJSXNodesItemPlugin = ({
128
129
  rootRef: handleRootRef
129
130
  };
130
131
  };
131
- useTreeViewJSXNodes.itemPlugin = useTreeViewJSXNodesItemPlugin;
132
- useTreeViewJSXNodes.wrapItem = ({
132
+ useTreeViewJSXItems.itemPlugin = useTreeViewJSXItemsItemPlugin;
133
+ useTreeViewJSXItems.wrapItem = ({
133
134
  children,
134
135
  itemId
135
136
  }) => /*#__PURE__*/_jsx(DescendantProvider, {
136
137
  id: itemId,
137
138
  children: children
138
139
  });
139
- useTreeViewJSXNodes.params = {};
140
+ useTreeViewJSXItems.params = {};
@@ -0,0 +1,18 @@
1
+ import { TreeViewNode, TreeViewPluginSignature } from '../../models';
2
+ import { UseTreeViewItemsSignature } from '../useTreeViewItems';
3
+ import { UseTreeViewKeyboardNavigationSignature } from '../useTreeViewKeyboardNavigation';
4
+ export interface UseTreeViewItemsInstance {
5
+ insertJSXItem: (item: TreeViewNode) => void;
6
+ removeJSXItem: (itemId: string) => void;
7
+ mapFirstCharFromJSX: (itemId: string, firstChar: string) => () => void;
8
+ }
9
+ export interface UseTreeViewItemsParameters {
10
+ }
11
+ export interface UseTreeViewItemsDefaultizedParameters {
12
+ }
13
+ export type UseTreeViewJSXItemsSignature = TreeViewPluginSignature<{
14
+ params: UseTreeViewItemsParameters;
15
+ defaultizedParams: UseTreeViewItemsDefaultizedParameters;
16
+ instance: UseTreeViewItemsInstance;
17
+ dependantPlugins: [UseTreeViewItemsSignature, UseTreeViewKeyboardNavigationSignature];
18
+ }>;
@@ -1,7 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { useTheme } from '@mui/material/styles';
3
3
  import useEventCallback from '@mui/utils/useEventCallback';
4
- import { getFirstNode, getLastNode, getNextNode, getPreviousNode, populateInstance } from '../../useTreeView/useTreeView.utils';
4
+ import { getFirstItem, getLastItem, getNextItem, getPreviousItem, populateInstance } from '../../useTreeView/useTreeView.utils';
5
5
  function isPrintableCharacter(string) {
6
6
  return !!string && string.length === 1 && !!string.match(/\S/);
7
7
  }
@@ -15,30 +15,26 @@ function findNextFirstChar(firstChars, startIndex, char) {
15
15
  }
16
16
  export const useTreeViewKeyboardNavigation = ({
17
17
  instance,
18
- params
18
+ params,
19
+ state
19
20
  }) => {
20
21
  const theme = useTheme();
21
22
  const isRTL = theme.direction === 'rtl';
22
23
  const firstCharMap = React.useRef({});
23
- const hasFirstCharMapBeenUpdatedImperatively = React.useRef(false);
24
24
  const updateFirstCharMap = useEventCallback(callback => {
25
- hasFirstCharMapBeenUpdatedImperatively.current = true;
26
25
  firstCharMap.current = callback(firstCharMap.current);
27
26
  });
28
27
  React.useEffect(() => {
29
- if (hasFirstCharMapBeenUpdatedImperatively.current) {
28
+ if (instance.areItemUpdatesPrevented()) {
30
29
  return;
31
30
  }
32
31
  const newFirstCharMap = {};
33
- const processItem = item => {
34
- const getItemId = params.getItemId;
35
- const itemId = getItemId ? getItemId(item) : item.id;
36
- newFirstCharMap[itemId] = instance.getNode(itemId).label.substring(0, 1).toLowerCase();
37
- item.children?.forEach(processItem);
32
+ const processItem = node => {
33
+ newFirstCharMap[node.id] = node.label.substring(0, 1).toLowerCase();
38
34
  };
39
- params.items.forEach(processItem);
35
+ Object.values(state.items.nodeMap).forEach(processItem);
40
36
  firstCharMap.current = newFirstCharMap;
41
- }, [params.items, params.getItemId, instance]);
37
+ }, [state.items.nodeMap, params.getItemId, instance]);
42
38
  const getFirstMatchingItem = (itemId, firstChar) => {
43
39
  let start;
44
40
  let index;
@@ -48,8 +44,8 @@ export const useTreeViewKeyboardNavigation = ({
48
44
  // This really only works since the ids are strings
49
45
  Object.keys(firstCharMap.current).forEach(mapItemId => {
50
46
  const map = instance.getNode(mapItemId);
51
- const visible = map.parentId ? instance.isNodeExpanded(map.parentId) : true;
52
- const shouldBeSkipped = params.disabledItemsFocusable ? false : instance.isNodeDisabled(mapItemId);
47
+ const visible = map.parentId ? instance.isItemExpanded(map.parentId) : true;
48
+ const shouldBeSkipped = params.disabledItemsFocusable ? false : instance.isItemDisabled(mapItemId);
53
49
  if (visible && !shouldBeSkipped) {
54
50
  firstCharIds.push(mapItemId);
55
51
  firstChars.push(firstCharMap.current[mapItemId]);
@@ -76,9 +72,9 @@ export const useTreeViewKeyboardNavigation = ({
76
72
  }
77
73
  return null;
78
74
  };
79
- const canToggleItemSelection = itemId => !params.disableSelection && !instance.isNodeDisabled(itemId);
75
+ const canToggleItemSelection = itemId => !params.disableSelection && !instance.isItemDisabled(itemId);
80
76
  const canToggleItemExpansion = itemId => {
81
- return !instance.isNodeDisabled(itemId) && instance.isNodeExpandable(itemId);
77
+ return !instance.isItemDisabled(itemId) && instance.isItemExpandable(itemId);
82
78
  };
83
79
 
84
80
  // ARIA specification: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/#keyboardinteraction
@@ -94,7 +90,7 @@ export const useTreeViewKeyboardNavigation = ({
94
90
 
95
91
  // eslint-disable-next-line default-case
96
92
  switch (true) {
97
- // Select the node when pressing "Space"
93
+ // Select the item when pressing "Space"
98
94
  case key === ' ' && canToggleItemSelection(itemId):
99
95
  {
100
96
  event.preventDefault();
@@ -103,26 +99,26 @@ export const useTreeViewKeyboardNavigation = ({
103
99
  end: itemId
104
100
  });
105
101
  } else if (params.multiSelect) {
106
- instance.selectNode(event, itemId, true);
102
+ instance.selectItem(event, itemId, true);
107
103
  } else {
108
- instance.selectNode(event, itemId);
104
+ instance.selectItem(event, itemId);
109
105
  }
110
106
  break;
111
107
  }
112
108
 
113
- // If the focused node has children, we expand it.
114
- // If the focused node has no children, we select it.
109
+ // If the focused item has children, we expand it.
110
+ // If the focused item has no children, we select it.
115
111
  case key === 'Enter':
116
112
  {
117
113
  if (canToggleItemExpansion(itemId)) {
118
- instance.toggleNodeExpansion(event, itemId);
114
+ instance.toggleItemExpansion(event, itemId);
119
115
  event.preventDefault();
120
116
  } else if (canToggleItemSelection(itemId)) {
121
117
  if (params.multiSelect) {
122
118
  event.preventDefault();
123
- instance.selectNode(event, itemId, true);
124
- } else if (!instance.isNodeSelected(itemId)) {
125
- instance.selectNode(event, itemId);
119
+ instance.selectItem(event, itemId, true);
120
+ } else if (!instance.isItemSelected(itemId)) {
121
+ instance.selectItem(event, itemId);
126
122
  event.preventDefault();
127
123
  }
128
124
  }
@@ -132,7 +128,7 @@ export const useTreeViewKeyboardNavigation = ({
132
128
  // Focus the next focusable item
133
129
  case key === 'ArrowDown':
134
130
  {
135
- const nextItem = getNextNode(instance, itemId);
131
+ const nextItem = getNextItem(instance, itemId);
136
132
  if (nextItem) {
137
133
  event.preventDefault();
138
134
  instance.focusItem(event, nextItem);
@@ -152,7 +148,7 @@ export const useTreeViewKeyboardNavigation = ({
152
148
  // Focuses the previous focusable item
153
149
  case key === 'ArrowUp':
154
150
  {
155
- const previousItem = getPreviousNode(instance, itemId);
151
+ const previousItem = getPreviousItem(instance, itemId);
156
152
  if (previousItem) {
157
153
  event.preventDefault();
158
154
  instance.focusItem(event, previousItem);
@@ -173,14 +169,14 @@ export const useTreeViewKeyboardNavigation = ({
173
169
  // If the focused item is collapsed and has children, we expand it
174
170
  case key === 'ArrowRight' && !isRTL || key === 'ArrowLeft' && isRTL:
175
171
  {
176
- if (instance.isNodeExpanded(itemId)) {
177
- const nextNodeId = getNextNode(instance, itemId);
178
- if (nextNodeId) {
179
- instance.focusItem(event, nextNodeId);
172
+ if (instance.isItemExpanded(itemId)) {
173
+ const nextItemId = getNextItem(instance, itemId);
174
+ if (nextItemId) {
175
+ instance.focusItem(event, nextItemId);
180
176
  event.preventDefault();
181
177
  }
182
178
  } else if (canToggleItemExpansion(itemId)) {
183
- instance.toggleNodeExpansion(event, itemId);
179
+ instance.toggleItemExpansion(event, itemId);
184
180
  event.preventDefault();
185
181
  }
186
182
  break;
@@ -190,8 +186,8 @@ export const useTreeViewKeyboardNavigation = ({
190
186
  // If the focused item is collapsed and has a parent, we move the focus to this parent
191
187
  case key === 'ArrowLeft' && !isRTL || key === 'ArrowRight' && isRTL:
192
188
  {
193
- if (canToggleItemExpansion(itemId) && instance.isNodeExpanded(itemId)) {
194
- instance.toggleNodeExpansion(event, itemId);
189
+ if (canToggleItemExpansion(itemId) && instance.isItemExpanded(itemId)) {
190
+ instance.toggleItemExpansion(event, itemId);
195
191
  event.preventDefault();
196
192
  } else {
197
193
  const parent = instance.getNode(itemId).parentId;
@@ -203,13 +199,13 @@ export const useTreeViewKeyboardNavigation = ({
203
199
  break;
204
200
  }
205
201
 
206
- // Focuses the first node in the tree
202
+ // Focuses the first item in the tree
207
203
  case key === 'Home':
208
204
  {
209
- instance.focusItem(event, getFirstNode(instance));
205
+ instance.focusItem(event, getFirstItem(instance));
210
206
 
211
207
  // Multi select behavior when pressing Ctrl + Shift + Home
212
- // Selects the focused node and all nodes up to the first node.
208
+ // Selects the focused item and all items up to the first item.
213
209
  if (canToggleItemSelection(itemId) && params.multiSelect && ctrlPressed && event.shiftKey) {
214
210
  instance.rangeSelectToFirst(event, itemId);
215
211
  }
@@ -220,7 +216,7 @@ export const useTreeViewKeyboardNavigation = ({
220
216
  // Focuses the last item in the tree
221
217
  case key === 'End':
222
218
  {
223
- instance.focusItem(event, getLastNode(instance));
219
+ instance.focusItem(event, getLastItem(instance));
224
220
 
225
221
  // Multi select behavior when pressing Ctrl + Shirt + End
226
222
  // Selects the focused item and all the items down to the last item.
@@ -240,12 +236,12 @@ export const useTreeViewKeyboardNavigation = ({
240
236
  }
241
237
 
242
238
  // Multi select behavior when pressing Ctrl + a
243
- // Selects all the nodes
239
+ // Selects all the items
244
240
  case key === 'a' && ctrlPressed && params.multiSelect && !params.disableSelection:
245
241
  {
246
242
  instance.selectRange(event, {
247
- start: getFirstNode(instance),
248
- end: getLastNode(instance)
243
+ start: getFirstItem(instance),
244
+ end: getLastItem(instance)
249
245
  });
250
246
  event.preventDefault();
251
247
  break;
@@ -255,9 +251,9 @@ export const useTreeViewKeyboardNavigation = ({
255
251
  // TODO: Support typing multiple characters
256
252
  case !ctrlPressed && !event.shiftKey && isPrintableCharacter(key):
257
253
  {
258
- const matchingNode = getFirstMatchingItem(itemId, key);
259
- if (matchingNode != null) {
260
- instance.focusItem(event, matchingNode);
254
+ const matchingItem = getFirstMatchingItem(itemId, key);
255
+ if (matchingItem != null) {
256
+ instance.focusItem(event, matchingItem);
261
257
  event.preventDefault();
262
258
  }
263
259
  break;
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
  import { TreeViewPluginSignature } from '../../models';
3
- import { UseTreeViewNodesSignature } from '../useTreeViewNodes';
3
+ import { UseTreeViewItemsSignature } from '../useTreeViewItems';
4
4
  import { UseTreeViewSelectionSignature } from '../useTreeViewSelection';
5
5
  import { UseTreeViewFocusSignature } from '../useTreeViewFocus';
6
6
  import { UseTreeViewExpansionSignature } from '../useTreeViewExpansion';
@@ -12,7 +12,7 @@ export interface UseTreeViewKeyboardNavigationInstance {
12
12
  export type UseTreeViewKeyboardNavigationSignature = TreeViewPluginSignature<{
13
13
  instance: UseTreeViewKeyboardNavigationInstance;
14
14
  dependantPlugins: [
15
- UseTreeViewNodesSignature,
15
+ UseTreeViewItemsSignature,
16
16
  UseTreeViewSelectionSignature,
17
17
  UseTreeViewFocusSignature,
18
18
  UseTreeViewExpansionSignature