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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/CHANGELOG.md +252 -50
  2. package/RichTreeView/RichTreeView.js +23 -22
  3. package/RichTreeView/RichTreeView.types.d.ts +2 -1
  4. package/SimpleTreeView/SimpleTreeView.js +23 -22
  5. package/TreeItem/TreeItem.js +79 -79
  6. package/TreeItem/TreeItem.types.d.ts +17 -19
  7. package/TreeItem/treeItemClasses.d.ts +1 -1
  8. package/TreeItem/treeItemClasses.js +1 -1
  9. package/TreeItem/useTreeItemState.js +2 -2
  10. package/TreeItem2/TreeItem2.d.ts +18 -0
  11. package/TreeItem2/TreeItem2.js +301 -0
  12. package/TreeItem2/TreeItem2.types.d.ts +64 -0
  13. package/TreeItem2/TreeItem2.types.js +1 -0
  14. package/TreeItem2/index.d.ts +2 -0
  15. package/TreeItem2/index.js +1 -0
  16. package/TreeItem2/package.json +6 -0
  17. package/TreeItem2Icon/TreeItem2Icon.d.ts +7 -0
  18. package/TreeItem2Icon/TreeItem2Icon.js +68 -0
  19. package/TreeItem2Icon/TreeItem2Icon.types.d.ts +40 -0
  20. package/TreeItem2Icon/TreeItem2Icon.types.js +1 -0
  21. package/TreeItem2Icon/index.d.ts +2 -0
  22. package/TreeItem2Icon/index.js +1 -0
  23. package/TreeItem2Icon/package.json +6 -0
  24. package/TreeItem2Provider/TreeItem2Provider.d.ts +7 -0
  25. package/TreeItem2Provider/TreeItem2Provider.js +24 -0
  26. package/TreeItem2Provider/TreeItem2Provider.types.d.ts +6 -0
  27. package/TreeItem2Provider/TreeItem2Provider.types.js +1 -0
  28. package/TreeItem2Provider/index.d.ts +2 -0
  29. package/TreeItem2Provider/index.js +1 -0
  30. package/TreeItem2Provider/package.json +6 -0
  31. package/TreeView/TreeView.js +23 -22
  32. package/hooks/index.d.ts +1 -0
  33. package/hooks/index.js +2 -1
  34. package/hooks/useTreeItem2Utils/index.d.ts +1 -0
  35. package/hooks/useTreeItem2Utils/index.js +1 -0
  36. package/hooks/useTreeItem2Utils/useTreeItem2Utils.d.ts +15 -0
  37. package/hooks/useTreeItem2Utils/useTreeItem2Utils.js +61 -0
  38. package/hooks/useTreeViewApiRef.d.ts +2 -2
  39. package/index.d.ts +5 -1
  40. package/index.js +9 -2
  41. package/internals/TreeViewProvider/TreeViewContext.d.ts +3 -1
  42. package/internals/TreeViewProvider/TreeViewProvider.types.d.ts +4 -2
  43. package/internals/hooks/useLazyRef.d.ts +1 -2
  44. package/internals/hooks/useLazyRef.js +1 -11
  45. package/internals/hooks/useOnMount.d.ts +1 -2
  46. package/internals/hooks/useOnMount.js +1 -7
  47. package/internals/hooks/useTimeout.d.ts +1 -11
  48. package/internals/hooks/useTimeout.js +1 -36
  49. package/internals/models/helpers.d.ts +1 -0
  50. package/internals/models/plugin.d.ts +19 -16
  51. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +25 -25
  52. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +11 -11
  53. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +12 -12
  54. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +5 -6
  55. package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +37 -23
  56. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +11 -9
  57. package/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +31 -18
  58. package/internals/plugins/useTreeViewNodes/useTreeViewNodes.types.d.ts +16 -6
  59. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +34 -34
  60. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +11 -11
  61. package/internals/useTreeView/useTreeView.js +27 -25
  62. package/modern/RichTreeView/RichTreeView.js +23 -22
  63. package/modern/SimpleTreeView/SimpleTreeView.js +23 -22
  64. package/modern/TreeItem/TreeItem.js +78 -78
  65. package/modern/TreeItem/treeItemClasses.js +1 -1
  66. package/modern/TreeItem/useTreeItemState.js +2 -2
  67. package/modern/TreeItem2/TreeItem2.js +300 -0
  68. package/modern/TreeItem2/TreeItem2.types.js +1 -0
  69. package/modern/TreeItem2/index.js +1 -0
  70. package/modern/TreeItem2Icon/TreeItem2Icon.js +67 -0
  71. package/modern/TreeItem2Icon/TreeItem2Icon.types.js +1 -0
  72. package/modern/TreeItem2Icon/index.js +1 -0
  73. package/modern/TreeItem2Provider/TreeItem2Provider.js +24 -0
  74. package/modern/TreeItem2Provider/TreeItem2Provider.types.js +1 -0
  75. package/modern/TreeItem2Provider/index.js +1 -0
  76. package/modern/TreeView/TreeView.js +23 -22
  77. package/modern/hooks/index.js +2 -1
  78. package/modern/hooks/useTreeItem2Utils/index.js +1 -0
  79. package/modern/hooks/useTreeItem2Utils/useTreeItem2Utils.js +61 -0
  80. package/modern/index.js +9 -2
  81. package/modern/internals/hooks/useLazyRef.js +1 -11
  82. package/modern/internals/hooks/useOnMount.js +1 -7
  83. package/modern/internals/hooks/useTimeout.js +1 -36
  84. package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +24 -24
  85. package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +12 -12
  86. package/modern/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +36 -22
  87. package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +11 -9
  88. package/modern/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +31 -18
  89. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +34 -34
  90. package/modern/internals/useTreeView/useTreeView.js +27 -25
  91. package/modern/useTreeItem2/index.js +1 -0
  92. package/modern/useTreeItem2/useTreeItem2.js +135 -0
  93. package/modern/useTreeItem2/useTreeItem2.types.js +1 -0
  94. package/node/RichTreeView/RichTreeView.js +23 -22
  95. package/node/SimpleTreeView/SimpleTreeView.js +23 -22
  96. package/node/TreeItem/TreeItem.js +78 -78
  97. package/node/TreeItem/treeItemClasses.js +1 -1
  98. package/node/TreeItem/useTreeItemState.js +2 -2
  99. package/node/TreeItem2/TreeItem2.js +308 -0
  100. package/node/TreeItem2/TreeItem2.types.js +5 -0
  101. package/node/TreeItem2/index.js +42 -0
  102. package/node/TreeItem2Icon/TreeItem2Icon.js +75 -0
  103. package/node/TreeItem2Icon/TreeItem2Icon.types.js +5 -0
  104. package/node/TreeItem2Icon/index.js +12 -0
  105. package/node/TreeItem2Provider/TreeItem2Provider.js +30 -0
  106. package/node/TreeItem2Provider/TreeItem2Provider.types.js +5 -0
  107. package/node/TreeItem2Provider/index.js +12 -0
  108. package/node/TreeView/TreeView.js +23 -22
  109. package/node/hooks/index.js +8 -1
  110. package/node/hooks/useTreeItem2Utils/index.js +12 -0
  111. package/node/hooks/useTreeItem2Utils/useTreeItem2Utils.js +68 -0
  112. package/node/index.js +61 -13
  113. package/node/internals/hooks/useLazyRef.js +7 -13
  114. package/node/internals/hooks/useOnMount.js +8 -10
  115. package/node/internals/hooks/useTimeout.js +7 -37
  116. package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +24 -24
  117. package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +12 -12
  118. package/node/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +36 -22
  119. package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +11 -9
  120. package/node/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +30 -17
  121. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +34 -34
  122. package/node/internals/useTreeView/useTreeView.js +27 -25
  123. package/node/useTreeItem2/index.js +12 -0
  124. package/node/useTreeItem2/useTreeItem2.js +143 -0
  125. package/node/useTreeItem2/useTreeItem2.types.js +5 -0
  126. package/package.json +2 -2
  127. package/themeAugmentation/components.d.ts +5 -0
  128. package/themeAugmentation/overrides.d.ts +1 -0
  129. package/themeAugmentation/props.d.ts +2 -0
  130. package/useTreeItem2/index.d.ts +2 -0
  131. package/useTreeItem2/index.js +1 -0
  132. package/useTreeItem2/package.json +6 -0
  133. package/useTreeItem2/useTreeItem2.d.ts +2 -0
  134. package/useTreeItem2/useTreeItem2.js +138 -0
  135. package/useTreeItem2/useTreeItem2.types.d.ts +113 -0
  136. package/useTreeItem2/useTreeItem2.types.js +1 -0
@@ -6,21 +6,20 @@ import type { UseTreeViewSelectionSignature } from '../useTreeViewSelection';
6
6
  import { UseTreeViewExpansionSignature } from '../useTreeViewExpansion';
7
7
  export interface UseTreeViewFocusInstance {
8
8
  isNodeFocused: (nodeId: string) => boolean;
9
- focusNode: (event: React.SyntheticEvent, nodeId: string | null) => void;
9
+ focusItem: (event: React.SyntheticEvent, itemId: string | null) => void;
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, 'focusItem'> {
15
14
  }
16
15
  export interface UseTreeViewFocusParameters {
17
16
  /**
18
17
  * Callback fired when tree items are focused.
19
18
  * @param {React.SyntheticEvent} event The event source of the callback **Warning**: This is a generic event not a focus event.
20
- * @param {string} nodeId The id of the node focused.
21
- * @param {string} value of the focused node.
19
+ * @param {string} itemId The id of the focused item.
20
+ * @param {string} value of the focused item.
22
21
  */
23
- onNodeFocus?: (event: React.SyntheticEvent, nodeId: string) => void;
22
+ onItemFocus?: (event: React.SyntheticEvent, itemId: string) => void;
24
23
  }
25
24
  export type UseTreeViewFocusDefaultizedParameters = UseTreeViewFocusParameters;
26
25
  export interface UseTreeViewFocusState {
@@ -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', {
@@ -56,15 +70,15 @@ export const useTreeViewJSXNodes = ({
56
70
  };
57
71
  const useTreeViewJSXNodesItemPlugin = ({
58
72
  props,
59
- ref
73
+ rootRef,
74
+ contentRef
60
75
  }) => {
61
76
  const {
62
77
  children,
63
78
  disabled = false,
64
79
  label,
65
80
  nodeId,
66
- id,
67
- ContentProps: inContentProps
81
+ id
68
82
  } = props;
69
83
  const {
70
84
  instance
@@ -77,8 +91,9 @@ const useTreeViewJSXNodesItemPlugin = ({
77
91
  };
78
92
  const expandable = isExpandable(children);
79
93
  const [treeItemElement, setTreeItemElement] = React.useState(null);
80
- const contentRef = React.useRef(null);
81
- const handleRef = useForkRef(setTreeItemElement, ref);
94
+ const pluginContentRef = React.useRef(null);
95
+ const handleRootRef = useForkRef(setTreeItemElement, rootRef);
96
+ const handleContentRef = useForkRef(pluginContentRef, contentRef);
82
97
  const descendant = React.useMemo(() => ({
83
98
  element: treeItemElement,
84
99
  id: nodeId
@@ -104,23 +119,22 @@ const useTreeViewJSXNodesItemPlugin = ({
104
119
  }, [instance, parentId, index, nodeId, expandable, disabled, id]);
105
120
  React.useEffect(() => {
106
121
  if (label) {
107
- var _contentRef$current$t, _contentRef$current;
108
- return instance.mapFirstCharFromJSX(nodeId, ((_contentRef$current$t = (_contentRef$current = contentRef.current) == null ? void 0 : _contentRef$current.textContent) != null ? _contentRef$current$t : '').substring(0, 1).toLowerCase());
122
+ var _pluginContentRef$cur, _pluginContentRef$cur2;
123
+ return instance.mapFirstCharFromJSX(nodeId, ((_pluginContentRef$cur = (_pluginContentRef$cur2 = pluginContentRef.current) == null ? void 0 : _pluginContentRef$cur2.textContent) != null ? _pluginContentRef$cur : '').substring(0, 1).toLowerCase());
109
124
  }
110
125
  return undefined;
111
126
  }, [instance, nodeId, label]);
112
127
  return {
113
- props: _extends({}, props, {
114
- ContentProps: _extends({}, inContentProps, {
115
- ref: contentRef
116
- })
117
- }),
118
- ref: handleRef,
119
- wrapItem: item => /*#__PURE__*/_jsx(DescendantProvider, {
120
- id: nodeId,
121
- children: item
122
- })
128
+ contentRef: handleContentRef,
129
+ rootRef: handleRootRef
123
130
  };
124
131
  };
125
132
  useTreeViewJSXNodes.itemPlugin = useTreeViewJSXNodesItemPlugin;
133
+ useTreeViewJSXNodes.wrapItem = ({
134
+ children,
135
+ nodeId
136
+ }) => /*#__PURE__*/_jsx(DescendantProvider, {
137
+ id: nodeId,
138
+ children: children
139
+ });
126
140
  useTreeViewJSXNodes.params = {};
@@ -82,7 +82,9 @@ export const useTreeViewKeyboardNavigation = ({
82
82
  return null;
83
83
  };
84
84
  const canToggleNodeSelection = nodeId => !params.disableSelection && !instance.isNodeDisabled(nodeId);
85
- const canToggleNodeExpansion = nodeId => !instance.isNodeDisabled(nodeId) && instance.isNodeExpandable(nodeId);
85
+ const canToggleNodeExpansion = nodeId => {
86
+ return !instance.isNodeDisabled(nodeId) && instance.isNodeExpandable(nodeId);
87
+ };
86
88
 
87
89
  // ARIA specification: https://www.w3.org/WAI/ARIA/apg/patterns/treeview/#keyboardinteraction
88
90
  const createHandleKeyDown = otherHandlers => event => {
@@ -92,7 +94,7 @@ export const useTreeViewKeyboardNavigation = ({
92
94
  return;
93
95
  }
94
96
 
95
- // If the tree is empty there will be no focused node
97
+ // If the tree is empty, there will be no focused node
96
98
  if (event.altKey || event.currentTarget !== event.target || state.focusedNodeId == null) {
97
99
  return;
98
100
  }
@@ -142,7 +144,7 @@ export const useTreeViewKeyboardNavigation = ({
142
144
  const nextNode = getNextNode(instance, state.focusedNodeId);
143
145
  if (nextNode) {
144
146
  event.preventDefault();
145
- instance.focusNode(event, nextNode);
147
+ instance.focusItem(event, nextNode);
146
148
 
147
149
  // Multi select behavior when pressing Shift + ArrowDown
148
150
  // Toggles the selection state of the next node
@@ -162,7 +164,7 @@ export const useTreeViewKeyboardNavigation = ({
162
164
  const previousNode = getPreviousNode(instance, state.focusedNodeId);
163
165
  if (previousNode) {
164
166
  event.preventDefault();
165
- instance.focusNode(event, previousNode);
167
+ instance.focusItem(event, previousNode);
166
168
 
167
169
  // Multi select behavior when pressing Shift + ArrowUp
168
170
  // Toggles the selection state of the previous node
@@ -181,7 +183,7 @@ export const useTreeViewKeyboardNavigation = ({
181
183
  case key === 'ArrowRight' && !isRTL || key === 'ArrowLeft' && isRTL:
182
184
  {
183
185
  if (instance.isNodeExpanded(state.focusedNodeId)) {
184
- instance.focusNode(event, getNextNode(instance, state.focusedNodeId));
186
+ instance.focusItem(event, getNextNode(instance, state.focusedNodeId));
185
187
  event.preventDefault();
186
188
  } else if (canToggleNodeExpansion(state.focusedNodeId)) {
187
189
  instance.toggleNodeExpansion(event, state.focusedNodeId);
@@ -200,7 +202,7 @@ export const useTreeViewKeyboardNavigation = ({
200
202
  } else {
201
203
  const parent = instance.getNode(state.focusedNodeId).parentId;
202
204
  if (parent) {
203
- instance.focusNode(event, parent);
205
+ instance.focusItem(event, parent);
204
206
  event.preventDefault();
205
207
  }
206
208
  }
@@ -210,7 +212,7 @@ export const useTreeViewKeyboardNavigation = ({
210
212
  // Focuses the first node in the tree
211
213
  case key === 'Home':
212
214
  {
213
- instance.focusNode(event, getFirstNode(instance));
215
+ instance.focusItem(event, getFirstNode(instance));
214
216
 
215
217
  // Multi select behavior when pressing Ctrl + Shift + Home
216
218
  // Selects the focused node and all nodes up to the first node.
@@ -224,7 +226,7 @@ export const useTreeViewKeyboardNavigation = ({
224
226
  // Focuses the last node in the tree
225
227
  case key === 'End':
226
228
  {
227
- instance.focusNode(event, getLastNode(instance));
229
+ instance.focusItem(event, getLastNode(instance));
228
230
 
229
231
  // Multi select behavior when pressing Ctrl + Shirt + End
230
232
  // Selects the focused node and all the nodes down to the last node.
@@ -261,7 +263,7 @@ export const useTreeViewKeyboardNavigation = ({
261
263
  {
262
264
  const matchingNode = getFirstMatchingNode(state.focusedNodeId, key);
263
265
  if (matchingNode != null) {
264
- instance.focusNode(event, matchingNode);
266
+ instance.focusItem(event, matchingNode);
265
267
  event.preventDefault();
266
268
  }
267
269
  break;
@@ -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,28 +86,30 @@ 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
- const getNodesToRender = useEventCallback(() => {
107
+ const getNodesToRender = () => {
101
108
  const getPropsFromNodeId = ({
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);
114
- });
120
+ return state.nodes.nodeTree.map(getPropsFromNodeId);
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 {};
@@ -10,49 +10,49 @@ export const useTreeViewSelection = ({
10
10
  const lastSelectedNode = React.useRef(null);
11
11
  const lastSelectionWasRange = React.useRef(false);
12
12
  const currentRangeSelection = React.useRef([]);
13
- const setSelectedNodes = (event, newSelectedNodes) => {
14
- if (params.onNodeSelectionToggle) {
13
+ const setSelectedItems = (event, newSelectedItems) => {
14
+ if (params.onItemSelectionToggle) {
15
15
  if (params.multiSelect) {
16
- const addedNodes = newSelectedNodes.filter(nodeId => !instance.isNodeSelected(nodeId));
17
- const removedNodes = models.selectedNodes.value.filter(nodeId => !newSelectedNodes.includes(nodeId));
18
- addedNodes.forEach(nodeId => {
19
- params.onNodeSelectionToggle(event, nodeId, true);
16
+ const addedItems = newSelectedItems.filter(itemId => !instance.isNodeSelected(itemId));
17
+ const removedItems = models.selectedItems.value.filter(itemId => !newSelectedItems.includes(itemId));
18
+ addedItems.forEach(itemId => {
19
+ params.onItemSelectionToggle(event, itemId, true);
20
20
  });
21
- removedNodes.forEach(nodeId => {
22
- params.onNodeSelectionToggle(event, nodeId, false);
21
+ removedItems.forEach(itemId => {
22
+ params.onItemSelectionToggle(event, itemId, false);
23
23
  });
24
- } else if (newSelectedNodes !== models.selectedNodes.value) {
25
- if (models.selectedNodes.value != null) {
26
- params.onNodeSelectionToggle(event, models.selectedNodes.value, false);
24
+ } else if (newSelectedItems !== models.selectedItems.value) {
25
+ if (models.selectedItems.value != null) {
26
+ params.onItemSelectionToggle(event, models.selectedItems.value, false);
27
27
  }
28
- if (newSelectedNodes != null) {
29
- params.onNodeSelectionToggle(event, newSelectedNodes, true);
28
+ if (newSelectedItems != null) {
29
+ params.onItemSelectionToggle(event, newSelectedItems, true);
30
30
  }
31
31
  }
32
32
  }
33
- if (params.onSelectedNodesChange) {
34
- params.onSelectedNodesChange(event, newSelectedNodes);
33
+ if (params.onSelectedItemsChange) {
34
+ params.onSelectedItemsChange(event, newSelectedItems);
35
35
  }
36
- models.selectedNodes.setControlledValue(newSelectedNodes);
36
+ models.selectedItems.setControlledValue(newSelectedItems);
37
37
  };
38
- const isNodeSelected = nodeId => Array.isArray(models.selectedNodes.value) ? models.selectedNodes.value.indexOf(nodeId) !== -1 : models.selectedNodes.value === nodeId;
38
+ const isNodeSelected = nodeId => Array.isArray(models.selectedItems.value) ? models.selectedItems.value.indexOf(nodeId) !== -1 : models.selectedItems.value === nodeId;
39
39
  const selectNode = (event, nodeId, multiple = false) => {
40
40
  if (params.disableSelection) {
41
41
  return;
42
42
  }
43
43
  if (multiple) {
44
- if (Array.isArray(models.selectedNodes.value)) {
44
+ if (Array.isArray(models.selectedItems.value)) {
45
45
  let newSelected;
46
- if (models.selectedNodes.value.indexOf(nodeId) !== -1) {
47
- newSelected = models.selectedNodes.value.filter(id => id !== nodeId);
46
+ if (models.selectedItems.value.indexOf(nodeId) !== -1) {
47
+ newSelected = models.selectedItems.value.filter(id => id !== nodeId);
48
48
  } else {
49
- newSelected = [nodeId].concat(models.selectedNodes.value);
49
+ newSelected = [nodeId].concat(models.selectedItems.value);
50
50
  }
51
- setSelectedNodes(event, newSelected);
51
+ setSelectedItems(event, newSelected);
52
52
  }
53
53
  } else {
54
54
  const newSelected = params.multiSelect ? [nodeId] : nodeId;
55
- setSelectedNodes(event, newSelected);
55
+ setSelectedItems(event, newSelected);
56
56
  }
57
57
  lastSelectedNode.current = nodeId;
58
58
  lastSelectionWasRange.current = false;
@@ -69,7 +69,7 @@ export const useTreeViewSelection = ({
69
69
  return nodes;
70
70
  };
71
71
  const handleRangeArrowSelect = (event, nodes) => {
72
- let base = models.selectedNodes.value.slice();
72
+ let base = models.selectedItems.value.slice();
73
73
  const {
74
74
  start,
75
75
  next,
@@ -93,10 +93,10 @@ export const useTreeViewSelection = ({
93
93
  base.push(next);
94
94
  currentRangeSelection.current.push(current, next);
95
95
  }
96
- setSelectedNodes(event, base);
96
+ setSelectedItems(event, base);
97
97
  };
98
98
  const handleRangeSelect = (event, nodes) => {
99
- let base = models.selectedNodes.value.slice();
99
+ let base = models.selectedItems.value.slice();
100
100
  const {
101
101
  start,
102
102
  end
@@ -110,7 +110,7 @@ export const useTreeViewSelection = ({
110
110
  currentRangeSelection.current = range;
111
111
  let newSelected = base.concat(range);
112
112
  newSelected = newSelected.filter((id, i) => newSelected.indexOf(id) === i);
113
- setSelectedNodes(event, newSelected);
113
+ setSelectedItems(event, newSelected);
114
114
  };
115
115
  const selectRange = (event, nodes, stacked = false) => {
116
116
  if (params.disableSelection) {
@@ -174,8 +174,8 @@ export const useTreeViewSelection = ({
174
174
  };
175
175
  };
176
176
  useTreeViewSelection.models = {
177
- selectedNodes: {
178
- getDefaultValue: params => params.defaultSelectedNodes
177
+ selectedItems: {
178
+ getDefaultValue: params => params.defaultSelectedItems
179
179
  }
180
180
  };
181
181
  const DEFAULT_SELECTED_NODES = [];
@@ -184,14 +184,14 @@ useTreeViewSelection.getDefaultizedParams = params => {
184
184
  return _extends({}, params, {
185
185
  disableSelection: (_params$disableSelect = params.disableSelection) != null ? _params$disableSelect : false,
186
186
  multiSelect: (_params$multiSelect = params.multiSelect) != null ? _params$multiSelect : false,
187
- defaultSelectedNodes: (_params$defaultSelect = params.defaultSelectedNodes) != null ? _params$defaultSelect : params.multiSelect ? DEFAULT_SELECTED_NODES : null
187
+ defaultSelectedItems: (_params$defaultSelect = params.defaultSelectedItems) != null ? _params$defaultSelect : params.multiSelect ? DEFAULT_SELECTED_NODES : null
188
188
  });
189
189
  };
190
190
  useTreeViewSelection.params = {
191
191
  disableSelection: true,
192
192
  multiSelect: true,
193
- defaultSelectedNodes: true,
194
- selectedNodes: true,
195
- onSelectedNodesChange: true,
196
- onNodeSelectionToggle: true
193
+ defaultSelectedItems: true,
194
+ selectedItems: true,
195
+ onSelectedItemsChange: true,
196
+ onItemSelectionToggle: true
197
197
  };
@@ -17,16 +17,16 @@ export interface UseTreeViewSelectionParameters<Multiple extends boolean | undef
17
17
  */
18
18
  disableSelection?: boolean;
19
19
  /**
20
- * Selected node ids. (Uncontrolled)
20
+ * Selected item ids. (Uncontrolled)
21
21
  * When `multiSelect` is true this takes an array of strings; when false (default) a string.
22
22
  * @default []
23
23
  */
24
- defaultSelectedNodes?: TreeViewSelectionValue<Multiple>;
24
+ defaultSelectedItems?: TreeViewSelectionValue<Multiple>;
25
25
  /**
26
- * Selected node ids. (Controlled)
26
+ * Selected item ids. (Controlled)
27
27
  * When `multiSelect` is true this takes an array of strings; when false (default) a string.
28
28
  */
29
- selectedNodes?: TreeViewSelectionValue<Multiple>;
29
+ selectedItems?: TreeViewSelectionValue<Multiple>;
30
30
  /**
31
31
  * If true `ctrl` and `shift` will trigger multiselect.
32
32
  * @default false
@@ -35,19 +35,19 @@ export interface UseTreeViewSelectionParameters<Multiple extends boolean | undef
35
35
  /**
36
36
  * Callback fired when tree items are selected/deselected.
37
37
  * @param {React.SyntheticEvent} event The event source of the callback
38
- * @param {string[] | string} nodeIds The ids of the selected nodes.
38
+ * @param {string[] | string} itemIds The ids of the selected items.
39
39
  * When `multiSelect` is `true`, this is an array of strings; when false (default) a string.
40
40
  */
41
- onSelectedNodesChange?: (event: React.SyntheticEvent, nodeIds: TreeViewSelectionValue<Multiple>) => void;
41
+ onSelectedItemsChange?: (event: React.SyntheticEvent, itemIds: TreeViewSelectionValue<Multiple>) => void;
42
42
  /**
43
43
  * Callback fired when a tree item is selected or deselected.
44
44
  * @param {React.SyntheticEvent} event The event source of the callback.
45
- * @param {array} nodeId The nodeId of the modified node.
46
- * @param {array} isSelected `true` if the node has just been selected, `false` if it has just been deselected.
45
+ * @param {array} itemId The itemId of the modified item.
46
+ * @param {array} isSelected `true` if the item has just been selected, `false` if it has just been deselected.
47
47
  */
48
- onNodeSelectionToggle?: (event: React.SyntheticEvent, nodeId: string, isSelected: boolean) => void;
48
+ onItemSelectionToggle?: (event: React.SyntheticEvent, itemId: string, isSelected: boolean) => void;
49
49
  }
50
- export type UseTreeViewSelectionDefaultizedParameters<Multiple extends boolean> = DefaultizedProps<UseTreeViewSelectionParameters<Multiple>, 'disableSelection' | 'defaultSelectedNodes' | 'multiSelect'>;
50
+ export type UseTreeViewSelectionDefaultizedParameters<Multiple extends boolean> = DefaultizedProps<UseTreeViewSelectionParameters<Multiple>, 'disableSelection' | 'defaultSelectedItems' | 'multiSelect'>;
51
51
  interface UseTreeViewSelectionContextValue {
52
52
  selection: Pick<UseTreeViewSelectionDefaultizedParameters<boolean>, 'multiSelect'>;
53
53
  }
@@ -56,7 +56,7 @@ export type UseTreeViewSelectionSignature = TreeViewPluginSignature<{
56
56
  defaultizedParams: UseTreeViewSelectionDefaultizedParameters<any>;
57
57
  instance: UseTreeViewSelectionInstance;
58
58
  contextValue: UseTreeViewSelectionContextValue;
59
- modelNames: 'selectedNodes';
59
+ modelNames: 'selectedItems';
60
60
  dependantPlugins: [
61
61
  UseTreeViewNodesSignature,
62
62
  UseTreeViewExpansionSignature,