@mui/x-tree-view 7.0.0-alpha.1 → 7.0.0-alpha.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 (203) hide show
  1. package/CHANGELOG.md +1254 -188
  2. package/README.md +0 -1
  3. package/RichTreeView/RichTreeView.d.ts +20 -0
  4. package/RichTreeView/RichTreeView.js +324 -0
  5. package/RichTreeView/RichTreeView.types.d.ts +55 -0
  6. package/RichTreeView/RichTreeView.types.js +1 -0
  7. package/RichTreeView/index.d.ts +3 -0
  8. package/RichTreeView/index.js +3 -0
  9. package/RichTreeView/package.json +6 -0
  10. package/RichTreeView/richTreeViewClasses.d.ts +7 -0
  11. package/RichTreeView/richTreeViewClasses.js +6 -0
  12. package/SimpleTreeView/SimpleTreeView.d.ts +20 -0
  13. package/SimpleTreeView/SimpleTreeView.js +268 -0
  14. package/SimpleTreeView/SimpleTreeView.plugins.d.ts +6 -0
  15. package/SimpleTreeView/SimpleTreeView.plugins.js +5 -0
  16. package/SimpleTreeView/SimpleTreeView.types.d.ts +38 -0
  17. package/SimpleTreeView/SimpleTreeView.types.js +1 -0
  18. package/SimpleTreeView/index.d.ts +3 -0
  19. package/SimpleTreeView/index.js +3 -0
  20. package/SimpleTreeView/package.json +6 -0
  21. package/SimpleTreeView/simpleTreeViewClasses.d.ts +7 -0
  22. package/SimpleTreeView/simpleTreeViewClasses.js +6 -0
  23. package/TreeItem/TreeItem.js +44 -89
  24. package/TreeItem/TreeItem.types.d.ts +2 -1
  25. package/TreeItem/index.d.ts +2 -2
  26. package/TreeItem/index.js +2 -2
  27. package/TreeItem/useTreeItem.js +5 -5
  28. package/TreeView/TreeView.d.ts +4 -0
  29. package/TreeView/TreeView.js +80 -87
  30. package/TreeView/TreeView.types.d.ts +4 -26
  31. package/TreeView/index.d.ts +1 -1
  32. package/index.d.ts +3 -0
  33. package/index.js +5 -2
  34. package/internals/TreeViewProvider/TreeViewContext.d.ts +1 -2
  35. package/internals/TreeViewProvider/TreeViewContext.js +1 -14
  36. package/internals/TreeViewProvider/TreeViewProvider.types.d.ts +3 -3
  37. package/internals/TreeViewProvider/useTreeViewContext.js +7 -1
  38. package/internals/corePlugins/corePlugins.d.ts +1 -1
  39. package/internals/corePlugins/corePlugins.js +1 -1
  40. package/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.d.ts +0 -5
  41. package/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +0 -6
  42. package/internals/hooks/useLazyRef.d.ts +2 -0
  43. package/internals/hooks/useLazyRef.js +11 -0
  44. package/internals/hooks/useOnMount.d.ts +2 -0
  45. package/internals/hooks/useOnMount.js +7 -0
  46. package/internals/hooks/useTimeout.d.ts +9 -0
  47. package/internals/hooks/useTimeout.js +28 -0
  48. package/internals/models/plugin.d.ts +23 -0
  49. package/internals/models/treeView.d.ts +5 -1
  50. package/internals/plugins/defaultPlugins.d.ts +3 -2
  51. package/internals/plugins/defaultPlugins.js +2 -1
  52. package/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.js +8 -6
  53. package/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.types.d.ts +1 -6
  54. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +26 -17
  55. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +12 -5
  56. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +13 -6
  57. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +4 -1
  58. package/internals/plugins/useTreeViewId/index.d.ts +2 -0
  59. package/internals/plugins/useTreeViewId/index.js +1 -0
  60. package/internals/plugins/useTreeViewId/useTreeViewId.d.ts +3 -0
  61. package/internals/plugins/useTreeViewId/useTreeViewId.js +18 -0
  62. package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +17 -0
  63. package/internals/plugins/useTreeViewId/useTreeViewId.types.js +1 -0
  64. package/internals/plugins/useTreeViewJSXNodes/index.d.ts +2 -0
  65. package/internals/plugins/useTreeViewJSXNodes/index.js +1 -0
  66. package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.d.ts +3 -0
  67. package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +114 -0
  68. package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.types.d.ts +16 -0
  69. package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.types.js +1 -0
  70. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -9
  71. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +5 -2
  72. package/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +83 -18
  73. package/internals/plugins/useTreeViewNodes/useTreeViewNodes.types.d.ts +48 -5
  74. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.d.ts +1 -1
  75. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +41 -28
  76. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +15 -8
  77. package/internals/useTreeView/useTreeView.js +40 -3
  78. package/internals/useTreeView/useTreeView.types.d.ts +2 -1
  79. package/internals/utils/warning.d.ts +1 -0
  80. package/internals/utils/warning.js +14 -0
  81. package/legacy/RichTreeView/RichTreeView.js +317 -0
  82. package/legacy/RichTreeView/RichTreeView.types.js +1 -0
  83. package/legacy/RichTreeView/index.js +3 -0
  84. package/legacy/RichTreeView/richTreeViewClasses.js +6 -0
  85. package/legacy/SimpleTreeView/SimpleTreeView.js +264 -0
  86. package/legacy/SimpleTreeView/SimpleTreeView.plugins.js +6 -0
  87. package/legacy/SimpleTreeView/SimpleTreeView.types.js +1 -0
  88. package/legacy/SimpleTreeView/index.js +3 -0
  89. package/legacy/SimpleTreeView/simpleTreeViewClasses.js +6 -0
  90. package/legacy/TreeItem/TreeItem.js +49 -103
  91. package/legacy/TreeItem/index.js +2 -2
  92. package/legacy/TreeItem/useTreeItem.js +5 -5
  93. package/legacy/TreeView/TreeView.js +80 -82
  94. package/legacy/index.js +5 -2
  95. package/legacy/internals/TreeViewProvider/TreeViewContext.js +1 -14
  96. package/legacy/internals/TreeViewProvider/useTreeViewContext.js +5 -1
  97. package/legacy/internals/corePlugins/corePlugins.js +1 -1
  98. package/legacy/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +0 -6
  99. package/legacy/internals/hooks/useLazyRef.js +11 -0
  100. package/legacy/internals/hooks/useOnMount.js +7 -0
  101. package/legacy/internals/hooks/useTimeout.js +38 -0
  102. package/legacy/internals/plugins/defaultPlugins.js +2 -1
  103. package/legacy/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.js +11 -8
  104. package/legacy/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +26 -17
  105. package/legacy/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +13 -6
  106. package/legacy/internals/plugins/useTreeViewId/index.js +1 -0
  107. package/legacy/internals/plugins/useTreeViewId/useTreeViewId.js +21 -0
  108. package/legacy/internals/plugins/useTreeViewId/useTreeViewId.types.js +1 -0
  109. package/legacy/internals/plugins/useTreeViewJSXNodes/index.js +1 -0
  110. package/legacy/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +120 -0
  111. package/legacy/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.types.js +1 -0
  112. package/legacy/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -9
  113. package/legacy/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +89 -20
  114. package/legacy/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +45 -28
  115. package/legacy/internals/useTreeView/useTreeView.js +39 -3
  116. package/legacy/internals/utils/warning.js +15 -0
  117. package/legacy/models/index.js +1 -0
  118. package/legacy/models/items.js +1 -0
  119. package/models/index.d.ts +1 -0
  120. package/models/index.js +1 -0
  121. package/models/items.d.ts +7 -0
  122. package/models/items.js +1 -0
  123. package/models/package.json +6 -0
  124. package/modern/RichTreeView/RichTreeView.js +322 -0
  125. package/modern/RichTreeView/RichTreeView.types.js +1 -0
  126. package/modern/RichTreeView/index.js +3 -0
  127. package/modern/RichTreeView/richTreeViewClasses.js +6 -0
  128. package/modern/SimpleTreeView/SimpleTreeView.js +267 -0
  129. package/modern/SimpleTreeView/SimpleTreeView.plugins.js +5 -0
  130. package/modern/SimpleTreeView/SimpleTreeView.types.js +1 -0
  131. package/modern/SimpleTreeView/index.js +3 -0
  132. package/modern/SimpleTreeView/simpleTreeViewClasses.js +6 -0
  133. package/modern/TreeItem/TreeItem.js +44 -88
  134. package/modern/TreeItem/index.js +2 -2
  135. package/modern/TreeItem/useTreeItem.js +5 -5
  136. package/modern/TreeView/TreeView.js +80 -87
  137. package/modern/index.js +5 -2
  138. package/modern/internals/TreeViewProvider/TreeViewContext.js +1 -14
  139. package/modern/internals/TreeViewProvider/useTreeViewContext.js +7 -1
  140. package/modern/internals/corePlugins/corePlugins.js +1 -1
  141. package/modern/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +0 -6
  142. package/modern/internals/hooks/useLazyRef.js +11 -0
  143. package/modern/internals/hooks/useOnMount.js +7 -0
  144. package/modern/internals/hooks/useTimeout.js +28 -0
  145. package/modern/internals/plugins/defaultPlugins.js +2 -1
  146. package/modern/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.js +8 -6
  147. package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +26 -17
  148. package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +12 -6
  149. package/modern/internals/plugins/useTreeViewId/index.js +1 -0
  150. package/modern/internals/plugins/useTreeViewId/useTreeViewId.js +18 -0
  151. package/modern/internals/plugins/useTreeViewId/useTreeViewId.types.js +1 -0
  152. package/modern/internals/plugins/useTreeViewJSXNodes/index.js +1 -0
  153. package/modern/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +113 -0
  154. package/modern/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.types.js +1 -0
  155. package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +19 -9
  156. package/modern/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +82 -18
  157. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +41 -28
  158. package/modern/internals/useTreeView/useTreeView.js +40 -3
  159. package/modern/internals/utils/warning.js +14 -0
  160. package/modern/models/index.js +1 -0
  161. package/modern/models/items.js +1 -0
  162. package/node/RichTreeView/RichTreeView.js +330 -0
  163. package/node/RichTreeView/RichTreeView.types.js +5 -0
  164. package/node/RichTreeView/index.js +27 -0
  165. package/node/RichTreeView/richTreeViewClasses.js +14 -0
  166. package/node/SimpleTreeView/SimpleTreeView.js +275 -0
  167. package/node/SimpleTreeView/SimpleTreeView.plugins.js +11 -0
  168. package/node/SimpleTreeView/SimpleTreeView.types.js +5 -0
  169. package/node/SimpleTreeView/index.js +27 -0
  170. package/node/SimpleTreeView/simpleTreeViewClasses.js +14 -0
  171. package/node/TreeItem/TreeItem.js +44 -88
  172. package/node/TreeItem/index.js +11 -15
  173. package/node/TreeItem/useTreeItem.js +5 -5
  174. package/node/TreeView/TreeView.js +80 -87
  175. package/node/index.js +38 -2
  176. package/node/internals/TreeViewProvider/TreeViewContext.js +2 -15
  177. package/node/internals/TreeViewProvider/useTreeViewContext.js +7 -1
  178. package/node/internals/corePlugins/corePlugins.js +1 -1
  179. package/node/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +0 -6
  180. package/node/internals/hooks/useLazyRef.js +19 -0
  181. package/node/internals/hooks/useOnMount.js +15 -0
  182. package/node/internals/hooks/useTimeout.js +34 -0
  183. package/node/internals/plugins/defaultPlugins.js +2 -1
  184. package/node/internals/plugins/useTreeViewContextValueBuilder/useTreeViewContextValueBuilder.js +8 -7
  185. package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +26 -17
  186. package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +12 -6
  187. package/node/internals/plugins/useTreeViewId/index.js +12 -0
  188. package/node/internals/plugins/useTreeViewId/useTreeViewId.js +28 -0
  189. package/node/internals/plugins/useTreeViewId/useTreeViewId.types.js +5 -0
  190. package/node/internals/plugins/useTreeViewJSXNodes/index.js +12 -0
  191. package/node/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +123 -0
  192. package/node/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.types.js +5 -0
  193. package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +19 -9
  194. package/node/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +82 -18
  195. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +41 -28
  196. package/node/internals/useTreeView/useTreeView.js +40 -3
  197. package/node/internals/utils/warning.js +21 -0
  198. package/node/models/index.js +16 -0
  199. package/node/models/items.js +5 -0
  200. package/package.json +8 -7
  201. package/themeAugmentation/components.d.ts +14 -4
  202. package/themeAugmentation/overrides.d.ts +8 -4
  203. package/themeAugmentation/props.d.ts +7 -3
@@ -8,34 +8,43 @@ export const useTreeViewExpansion = ({
8
8
  models
9
9
  }) => {
10
10
  const isNodeExpanded = React.useCallback(nodeId => {
11
- return Array.isArray(models.expanded.value) ? models.expanded.value.indexOf(nodeId) !== -1 : false;
12
- }, [models.expanded.value]);
11
+ return Array.isArray(models.expandedNodes.value) ? models.expandedNodes.value.indexOf(nodeId) !== -1 : false;
12
+ }, [models.expandedNodes.value]);
13
13
  const isNodeExpandable = React.useCallback(nodeId => !!instance.getNode(nodeId)?.expandable, [instance]);
14
14
  const toggleNodeExpansion = useEventCallback((event, nodeId) => {
15
15
  if (nodeId == null) {
16
16
  return;
17
17
  }
18
+ const isExpandedBefore = models.expandedNodes.value.indexOf(nodeId) !== -1;
18
19
  let newExpanded;
19
- if (models.expanded.value.indexOf(nodeId) !== -1) {
20
- newExpanded = models.expanded.value.filter(id => id !== nodeId);
20
+ if (isExpandedBefore) {
21
+ newExpanded = models.expandedNodes.value.filter(id => id !== nodeId);
21
22
  } else {
22
- newExpanded = [nodeId].concat(models.expanded.value);
23
+ newExpanded = [nodeId].concat(models.expandedNodes.value);
23
24
  }
24
- if (params.onNodeToggle) {
25
- params.onNodeToggle(event, newExpanded);
25
+ if (params.onNodeExpansionToggle) {
26
+ params.onNodeExpansionToggle(event, nodeId, !isExpandedBefore);
26
27
  }
27
- models.expanded.setValue(newExpanded);
28
+ if (params.onExpandedNodesChange) {
29
+ params.onExpandedNodesChange(event, newExpanded);
30
+ }
31
+ models.expandedNodes.setValue(newExpanded);
28
32
  });
29
33
  const expandAllSiblings = (event, nodeId) => {
30
34
  const node = instance.getNode(nodeId);
31
35
  const siblings = instance.getChildrenIds(node.parentId);
32
36
  const diff = siblings.filter(child => instance.isNodeExpandable(child) && !instance.isNodeExpanded(child));
33
- const newExpanded = models.expanded.value.concat(diff);
37
+ const newExpanded = models.expandedNodes.value.concat(diff);
34
38
  if (diff.length > 0) {
35
- models.expanded.setValue(newExpanded);
36
- if (params.onNodeToggle) {
37
- params.onNodeToggle(event, newExpanded);
39
+ if (params.onNodeExpansionToggle) {
40
+ diff.forEach(newlyExpandedNodeId => {
41
+ params.onNodeExpansionToggle(event, newlyExpandedNodeId, true);
42
+ });
43
+ }
44
+ if (params.onExpandedNodesChange) {
45
+ params.onExpandedNodesChange(event, newExpanded);
38
46
  }
47
+ models.expandedNodes.setValue(newExpanded);
39
48
  }
40
49
  };
41
50
  populateInstance(instance, {
@@ -46,12 +55,12 @@ export const useTreeViewExpansion = ({
46
55
  });
47
56
  };
48
57
  useTreeViewExpansion.models = {
49
- expanded: {
50
- controlledProp: 'expanded',
51
- defaultProp: 'defaultExpanded'
58
+ expandedNodes: {
59
+ controlledProp: 'expandedNodes',
60
+ defaultProp: 'defaultExpandedNodes'
52
61
  }
53
62
  };
54
- const DEFAULT_EXPANDED = [];
63
+ const DEFAULT_EXPANDED_NODES = [];
55
64
  useTreeViewExpansion.getDefaultizedParams = params => _extends({}, params, {
56
- defaultExpanded: params.defaultExpanded ?? DEFAULT_EXPANDED
65
+ defaultExpandedNodes: params.defaultExpandedNodes ?? DEFAULT_EXPANDED_NODES
57
66
  });
@@ -27,9 +27,15 @@ export const useTreeViewFocus = ({
27
27
  }
28
28
  }
29
29
  });
30
+ const focusRoot = useEventCallback(() => {
31
+ rootRef.current?.focus({
32
+ preventScroll: true
33
+ });
34
+ });
30
35
  populateInstance(instance, {
31
36
  isNodeFocused,
32
- focusNode
37
+ focusNode,
38
+ focusRoot
33
39
  });
34
40
  useInstanceEventHandler(instance, 'removeNode', ({
35
41
  id
@@ -51,10 +57,10 @@ export const useTreeViewFocus = ({
51
57
  return node && (node.parentId == null || instance.isNodeExpanded(node.parentId));
52
58
  };
53
59
  let nodeToFocusId;
54
- if (Array.isArray(models.selected.value)) {
55
- nodeToFocusId = models.selected.value.find(isNodeVisible);
56
- } else if (models.selected.value != null && isNodeVisible(models.selected.value)) {
57
- nodeToFocusId = models.selected.value;
60
+ if (Array.isArray(models.selectedNodes.value)) {
61
+ nodeToFocusId = models.selectedNodes.value.find(isNodeVisible);
62
+ } else if (models.selectedNodes.value != null && isNodeVisible(models.selectedNodes.value)) {
63
+ nodeToFocusId = models.selectedNodes.value;
58
64
  }
59
65
  if (nodeToFocusId == null) {
60
66
  nodeToFocusId = instance.getNavigableChildrenIds(null)[0];
@@ -67,7 +73,7 @@ export const useTreeViewFocus = ({
67
73
  setFocusedNodeId(null);
68
74
  };
69
75
  const focusedNode = instance.getNode(state.focusedNodeId);
70
- const activeDescendant = focusedNode ? focusedNode.idAttribute : null;
76
+ const activeDescendant = focusedNode ? instance.getTreeItemId(focusedNode.id, focusedNode.idAttribute) : null;
71
77
  return {
72
78
  getRootProps: otherHandlers => ({
73
79
  onFocus: createHandleFocus(otherHandlers),
@@ -0,0 +1 @@
1
+ export { useTreeViewId } from './useTreeViewId';
@@ -0,0 +1,18 @@
1
+ import * as React from 'react';
2
+ import useId from '@mui/utils/useId';
3
+ import { populateInstance } from '../../useTreeView/useTreeView.utils';
4
+ export const useTreeViewId = ({
5
+ instance,
6
+ params
7
+ }) => {
8
+ const treeId = useId(params.id);
9
+ const getTreeItemId = React.useCallback((nodeId, idAttribute) => idAttribute ?? `${treeId}-${nodeId}`, [treeId]);
10
+ populateInstance(instance, {
11
+ getTreeItemId
12
+ });
13
+ return {
14
+ getRootProps: () => ({
15
+ id: treeId
16
+ })
17
+ };
18
+ };
@@ -0,0 +1 @@
1
+ export { useTreeViewJSXNodes } from './useTreeViewJSXNodes';
@@ -0,0 +1,113 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import * as React from 'react';
3
+ import useEventCallback from '@mui/utils/useEventCallback';
4
+ import useForkRef from '@mui/utils/useForkRef';
5
+ import { populateInstance } from '../../useTreeView/useTreeView.utils';
6
+ import { publishTreeViewEvent } from '../../utils/publishTreeViewEvent';
7
+ import { useTreeViewContext } from '../../TreeViewProvider/useTreeViewContext';
8
+ import { DescendantProvider, useDescendant } from '../../TreeViewProvider/DescendantProvider';
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
+ export const useTreeViewJSXNodes = ({
11
+ instance,
12
+ setState
13
+ }) => {
14
+ const insertJSXNode = useEventCallback(node => {
15
+ setState(prevState => _extends({}, prevState, {
16
+ nodeMap: _extends({}, prevState.nodeMap, {
17
+ [node.id]: node
18
+ })
19
+ }));
20
+ });
21
+ const removeJSXNode = useEventCallback(nodeId => {
22
+ setState(prevState => {
23
+ const newMap = _extends({}, prevState.nodeMap);
24
+ delete newMap[nodeId];
25
+ return _extends({}, prevState, {
26
+ nodeMap: newMap
27
+ });
28
+ });
29
+ publishTreeViewEvent(instance, 'removeNode', {
30
+ id: nodeId
31
+ });
32
+ });
33
+ const mapFirstCharFromJSX = useEventCallback((nodeId, firstChar) => {
34
+ instance.updateFirstCharMap(firstCharMap => {
35
+ firstCharMap[nodeId] = firstChar;
36
+ return firstCharMap;
37
+ });
38
+ return () => {
39
+ instance.updateFirstCharMap(firstCharMap => {
40
+ const newMap = _extends({}, firstCharMap);
41
+ delete newMap[nodeId];
42
+ return newMap;
43
+ });
44
+ };
45
+ });
46
+ populateInstance(instance, {
47
+ insertJSXNode,
48
+ removeJSXNode,
49
+ mapFirstCharFromJSX
50
+ });
51
+ };
52
+ const useTreeViewJSXNodesItemPlugin = ({
53
+ props,
54
+ ref
55
+ }) => {
56
+ const {
57
+ children,
58
+ disabled = false,
59
+ label,
60
+ nodeId,
61
+ id,
62
+ ContentProps: inContentProps
63
+ } = props;
64
+ const {
65
+ instance
66
+ } = useTreeViewContext();
67
+ const expandable = Boolean(Array.isArray(children) ? children.length : children);
68
+ const [treeItemElement, setTreeItemElement] = React.useState(null);
69
+ const contentRef = React.useRef(null);
70
+ const handleRef = useForkRef(setTreeItemElement, ref);
71
+ const descendant = React.useMemo(() => ({
72
+ element: treeItemElement,
73
+ id: nodeId
74
+ }), [nodeId, treeItemElement]);
75
+ const {
76
+ index,
77
+ parentId
78
+ } = useDescendant(descendant);
79
+ React.useEffect(() => {
80
+ // On the first render a node's index will be -1. We want to wait for the real index.
81
+ if (instance && index !== -1) {
82
+ instance.insertJSXNode({
83
+ id: nodeId,
84
+ idAttribute: id,
85
+ index,
86
+ parentId,
87
+ expandable,
88
+ disabled
89
+ });
90
+ return () => instance.removeJSXNode(nodeId);
91
+ }
92
+ return undefined;
93
+ }, [instance, parentId, index, nodeId, expandable, disabled, id]);
94
+ React.useEffect(() => {
95
+ if (instance && label) {
96
+ return instance.mapFirstCharFromJSX(nodeId, (contentRef.current?.textContent ?? '').substring(0, 1).toLowerCase());
97
+ }
98
+ return undefined;
99
+ }, [instance, nodeId, label]);
100
+ return {
101
+ props: _extends({}, props, {
102
+ ContentProps: _extends({}, inContentProps, {
103
+ ref: contentRef
104
+ })
105
+ }),
106
+ ref: handleRef,
107
+ wrapItem: item => /*#__PURE__*/_jsx(DescendantProvider, {
108
+ id: nodeId,
109
+ children: item
110
+ })
111
+ };
112
+ };
113
+ useTreeViewJSXNodes.itemPlugin = useTreeViewJSXNodesItemPlugin;
@@ -1,4 +1,3 @@
1
- import _extends from "@babel/runtime/helpers/esm/extends";
2
1
  import * as React from 'react';
3
2
  import { useTheme } from '@mui/material/styles';
4
3
  import useEventCallback from '@mui/utils/useEventCallback';
@@ -22,16 +21,27 @@ export const useTreeViewKeyboardNavigation = ({
22
21
  const theme = useTheme();
23
22
  const isRtl = theme.direction === 'rtl';
24
23
  const firstCharMap = React.useRef({});
25
- const mapFirstChar = useEventCallback((nodeId, firstChar) => {
26
- firstCharMap.current[nodeId] = firstChar;
27
- return () => {
28
- const newMap = _extends({}, firstCharMap.current);
29
- delete newMap[nodeId];
30
- firstCharMap.current = newMap;
31
- };
24
+ const hasFirstCharMapBeenUpdatedImperatively = React.useRef(false);
25
+ const updateFirstCharMap = useEventCallback(callback => {
26
+ hasFirstCharMapBeenUpdatedImperatively.current = true;
27
+ firstCharMap.current = callback(firstCharMap.current);
32
28
  });
29
+ React.useEffect(() => {
30
+ if (hasFirstCharMapBeenUpdatedImperatively.current) {
31
+ return;
32
+ }
33
+ const newFirstCharMap = {};
34
+ const processItem = item => {
35
+ const getItemId = params.getItemId;
36
+ const nodeId = getItemId ? getItemId(item) : item.id;
37
+ newFirstCharMap[nodeId] = instance.getNode(nodeId).label.substring(0, 1).toLowerCase();
38
+ item.children?.forEach(processItem);
39
+ };
40
+ params.items.forEach(processItem);
41
+ firstCharMap.current = newFirstCharMap;
42
+ }, [params.items, params.getItemId, instance]);
33
43
  populateInstance(instance, {
34
- mapFirstChar
44
+ updateFirstCharMap
35
45
  });
36
46
  const handleNextArrow = event => {
37
47
  if (state.focusedNodeId != null && instance.isNodeExpandable(state.focusedNodeId)) {
@@ -3,23 +3,49 @@ import * as React from 'react';
3
3
  import useEventCallback from '@mui/utils/useEventCallback';
4
4
  import { populateInstance } from '../../useTreeView/useTreeView.utils';
5
5
  import { publishTreeViewEvent } from '../../utils/publishTreeViewEvent';
6
+ const updateState = ({
7
+ items,
8
+ isItemDisabled,
9
+ getItemLabel,
10
+ getItemId
11
+ }) => {
12
+ const nodeMap = {};
13
+ const processItem = (item, index, parentId) => {
14
+ const id = getItemId ? getItemId(item) : item.id;
15
+ if (id == null) {
16
+ throw new Error(['MUI: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', 'An item was provided without id in the `items` prop:', JSON.stringify(item)].join('\n'));
17
+ }
18
+ const label = getItemLabel ? getItemLabel(item) : item.label;
19
+ if (label == null) {
20
+ throw new Error(['MUI: The Tree View component requires all items to have a `label` property.', 'Alternatively, you can use the `getItemLabel` prop to specify a custom label for each item.', 'An item was provided without label in the `items` prop:', JSON.stringify(item)].join('\n'));
21
+ }
22
+ nodeMap[id] = {
23
+ id,
24
+ label,
25
+ index,
26
+ parentId,
27
+ idAttribute: id,
28
+ expandable: !!item.children?.length,
29
+ disabled: isItemDisabled ? isItemDisabled(item) : false
30
+ };
31
+ return {
32
+ id,
33
+ children: item.children?.map((child, childIndex) => processItem(child, childIndex, id))
34
+ };
35
+ };
36
+ const nodeTree = items.map((item, itemIndex) => processItem(item, itemIndex, null));
37
+ return {
38
+ nodeMap,
39
+ nodeTree
40
+ };
41
+ };
6
42
  export const useTreeViewNodes = ({
7
43
  instance,
8
- params
44
+ params,
45
+ state,
46
+ setState
9
47
  }) => {
10
- const nodeMap = React.useRef({});
11
- const getNode = React.useCallback(nodeId => nodeMap.current[nodeId], []);
12
- const insertNode = React.useCallback(node => {
13
- nodeMap.current[node.id] = node;
14
- }, []);
15
- const removeNode = React.useCallback(nodeId => {
16
- const newMap = _extends({}, nodeMap.current);
17
- delete newMap[nodeId];
18
- nodeMap.current = newMap;
19
- publishTreeViewEvent(instance, 'removeNode', {
20
- id: nodeId
21
- });
22
- }, [instance]);
48
+ const getNode = React.useCallback(nodeId => state.nodeMap[nodeId], [state.nodeMap]);
23
49
  const isNodeDisabled = React.useCallback(nodeId => {
24
50
  if (nodeId == null) {
25
51
  return false;
@@ -41,7 +67,7 @@ export const useTreeViewNodes = ({
41
67
  }
42
68
  return false;
43
69
  }, [instance]);
44
- const getChildrenIds = useEventCallback(nodeId => Object.values(nodeMap.current).filter(node => node.parentId === nodeId).sort((a, b) => a.index - b.index).map(child => child.id));
70
+ const getChildrenIds = useEventCallback(nodeId => Object.values(state.nodeMap).filter(node => node.parentId === nodeId).sort((a, b) => a.index - b.index).map(child => child.id));
45
71
  const getNavigableChildrenIds = nodeId => {
46
72
  let childrenIds = instance.getChildrenIds(nodeId);
47
73
  if (!params.disabledItemsFocusable) {
@@ -49,12 +75,50 @@ export const useTreeViewNodes = ({
49
75
  }
50
76
  return childrenIds;
51
77
  };
78
+ React.useEffect(() => {
79
+ setState(prevState => {
80
+ const newState = updateState({
81
+ items: params.items,
82
+ isItemDisabled: params.isItemDisabled,
83
+ getItemId: params.getItemId,
84
+ getItemLabel: params.getItemLabel
85
+ });
86
+ Object.values(prevState.nodeMap).forEach(node => {
87
+ if (!newState.nodeMap[node.id]) {
88
+ publishTreeViewEvent(instance, 'removeNode', {
89
+ id: node.id
90
+ });
91
+ }
92
+ });
93
+ return _extends({}, prevState, newState);
94
+ });
95
+ }, [instance, setState, params.items, params.isItemDisabled, params.getItemId, params.getItemLabel]);
96
+ const getNodesToRender = useEventCallback(() => {
97
+ const getPropsFromNodeId = ({
98
+ id,
99
+ children
100
+ }) => {
101
+ const node = state.nodeMap[id];
102
+ return {
103
+ label: node.label,
104
+ nodeId: node.id,
105
+ id: node.idAttribute,
106
+ children: children?.map(getPropsFromNodeId)
107
+ };
108
+ };
109
+ return state.nodeTree.map(getPropsFromNodeId);
110
+ });
52
111
  populateInstance(instance, {
53
112
  getNode,
54
- updateNode: insertNode,
55
- removeNode,
113
+ getNodesToRender,
56
114
  getChildrenIds,
57
115
  getNavigableChildrenIds,
58
116
  isNodeDisabled
59
117
  });
60
- };
118
+ };
119
+ useTreeViewNodes.getInitialState = params => updateState({
120
+ items: params.items,
121
+ isItemDisabled: params.isItemDisabled,
122
+ getItemId: params.getItemId,
123
+ getItemLabel: params.getItemLabel
124
+ });
@@ -10,30 +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 isNodeSelected = nodeId => Array.isArray(models.selected.value) ? models.selected.value.indexOf(nodeId) !== -1 : models.selected.value === nodeId;
13
+ const isNodeSelected = nodeId => Array.isArray(models.selectedNodes.value) ? models.selectedNodes.value.indexOf(nodeId) !== -1 : models.selectedNodes.value === nodeId;
14
+ const setSelectedNodes = (event, newSelectedNodes) => {
15
+ if (params.onNodeSelectionToggle) {
16
+ if (params.multiSelect) {
17
+ const addedNodes = newSelectedNodes.filter(nodeId => !instance.isNodeSelected(nodeId));
18
+ const removedNodes = models.selectedNodes.value.filter(nodeId => !newSelectedNodes.includes(nodeId));
19
+ addedNodes.forEach(nodeId => {
20
+ params.onNodeSelectionToggle(event, nodeId, true);
21
+ });
22
+ removedNodes.forEach(nodeId => {
23
+ params.onNodeSelectionToggle(event, nodeId, false);
24
+ });
25
+ } else if (newSelectedNodes !== models.selectedNodes.value) {
26
+ if (models.selectedNodes.value != null) {
27
+ params.onNodeSelectionToggle(event, models.selectedNodes.value, false);
28
+ }
29
+ if (newSelectedNodes != null) {
30
+ params.onNodeSelectionToggle(event, newSelectedNodes, true);
31
+ }
32
+ }
33
+ }
34
+ if (params.onSelectedNodesChange) {
35
+ params.onSelectedNodesChange(event, newSelectedNodes);
36
+ }
37
+ models.selectedNodes.setValue(newSelectedNodes);
38
+ };
14
39
  const selectNode = (event, nodeId, multiple = false) => {
15
40
  if (params.disableSelection) {
16
41
  return;
17
42
  }
18
43
  if (multiple) {
19
- if (Array.isArray(models.selected.value)) {
44
+ if (Array.isArray(models.selectedNodes.value)) {
20
45
  let newSelected;
21
- if (models.selected.value.indexOf(nodeId) !== -1) {
22
- newSelected = models.selected.value.filter(id => id !== nodeId);
46
+ if (models.selectedNodes.value.indexOf(nodeId) !== -1) {
47
+ newSelected = models.selectedNodes.value.filter(id => id !== nodeId);
23
48
  } else {
24
- newSelected = [nodeId].concat(models.selected.value);
25
- }
26
- if (params.onNodeSelect) {
27
- params.onNodeSelect(event, newSelected);
49
+ newSelected = [nodeId].concat(models.selectedNodes.value);
28
50
  }
29
- models.selected.setValue(newSelected);
51
+ setSelectedNodes(event, newSelected);
30
52
  }
31
53
  } else {
32
54
  const newSelected = params.multiSelect ? [nodeId] : nodeId;
33
- if (params.onNodeSelect) {
34
- params.onNodeSelect(event, newSelected);
35
- }
36
- models.selected.setValue(newSelected);
55
+ setSelectedNodes(event, newSelected);
37
56
  }
38
57
  lastSelectedNode.current = nodeId;
39
58
  lastSelectionWasRange.current = false;
@@ -50,7 +69,7 @@ export const useTreeViewSelection = ({
50
69
  return nodes;
51
70
  };
52
71
  const handleRangeArrowSelect = (event, nodes) => {
53
- let base = models.selected.value.slice();
72
+ let base = models.selectedNodes.value.slice();
54
73
  const {
55
74
  start,
56
75
  next,
@@ -74,13 +93,10 @@ export const useTreeViewSelection = ({
74
93
  base.push(next);
75
94
  currentRangeSelection.current.push(current, next);
76
95
  }
77
- if (params.onNodeSelect) {
78
- params.onNodeSelect(event, base);
79
- }
80
- models.selected.setValue(base);
96
+ setSelectedNodes(event, base);
81
97
  };
82
98
  const handleRangeSelect = (event, nodes) => {
83
- let base = models.selected.value.slice();
99
+ let base = models.selectedNodes.value.slice();
84
100
  const {
85
101
  start,
86
102
  end
@@ -94,10 +110,7 @@ export const useTreeViewSelection = ({
94
110
  currentRangeSelection.current = range;
95
111
  let newSelected = base.concat(range);
96
112
  newSelected = newSelected.filter((id, i) => newSelected.indexOf(id) === i);
97
- if (params.onNodeSelect) {
98
- params.onNodeSelect(event, newSelected);
99
- }
100
- models.selected.setValue(newSelected);
113
+ setSelectedNodes(event, newSelected);
101
114
  };
102
115
  const selectRange = (event, nodes, stacked = false) => {
103
116
  if (params.disableSelection) {
@@ -156,14 +169,14 @@ export const useTreeViewSelection = ({
156
169
  };
157
170
  };
158
171
  useTreeViewSelection.models = {
159
- selected: {
160
- controlledProp: 'selected',
161
- defaultProp: 'defaultSelected'
172
+ selectedNodes: {
173
+ controlledProp: 'selectedNodes',
174
+ defaultProp: 'defaultSelectedNodes'
162
175
  }
163
176
  };
164
- const DEFAULT_SELECTED = [];
177
+ const DEFAULT_SELECTED_NODES = [];
165
178
  useTreeViewSelection.getDefaultizedParams = params => _extends({}, params, {
166
179
  disableSelection: params.disableSelection ?? false,
167
180
  multiSelect: params.multiSelect ?? false,
168
- defaultSelected: params.defaultSelected ?? (params.multiSelect ? DEFAULT_SELECTED : null)
181
+ defaultSelectedNodes: params.defaultSelectedNodes ?? (params.multiSelect ? DEFAULT_SELECTED_NODES : null)
169
182
  });
@@ -1,7 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
3
  import useForkRef from '@mui/utils/useForkRef';
4
- import { DEFAULT_TREE_VIEW_CONTEXT_VALUE } from '../TreeViewProvider/TreeViewContext';
5
4
  import { useTreeViewModels } from './useTreeViewModels';
6
5
  import { TREE_VIEW_CORE_PLUGINS } from '../corePlugins';
7
6
  export const useTreeView = inParams => {
@@ -27,7 +26,7 @@ export const useTreeView = inParams => {
27
26
  return temp;
28
27
  });
29
28
  const rootPropsGetters = [];
30
- let contextValue = DEFAULT_TREE_VIEW_CONTEXT_VALUE;
29
+ let contextValue = {};
31
30
  const runPlugin = plugin => {
32
31
  const pluginResponse = plugin({
33
32
  instance,
@@ -45,6 +44,43 @@ export const useTreeView = inParams => {
45
44
  }
46
45
  };
47
46
  plugins.forEach(runPlugin);
47
+ contextValue.runItemPlugins = ({
48
+ props,
49
+ ref
50
+ }) => {
51
+ let finalProps = props;
52
+ let finalRef = ref;
53
+ const itemWrappers = [];
54
+ plugins.forEach(plugin => {
55
+ if (!plugin.itemPlugin) {
56
+ return;
57
+ }
58
+ const itemPluginResponse = plugin.itemPlugin({
59
+ props: finalProps,
60
+ ref: finalRef
61
+ });
62
+ if (itemPluginResponse?.props) {
63
+ finalProps = itemPluginResponse.props;
64
+ }
65
+ if (itemPluginResponse?.ref) {
66
+ finalRef = itemPluginResponse.ref;
67
+ }
68
+ if (itemPluginResponse?.wrapItem) {
69
+ itemWrappers.push(itemPluginResponse.wrapItem);
70
+ }
71
+ });
72
+ return {
73
+ props: finalProps,
74
+ ref: finalRef,
75
+ wrapItem: children => {
76
+ let finalChildren = children;
77
+ itemWrappers.forEach(itemWrapper => {
78
+ finalChildren = itemWrapper(finalChildren);
79
+ });
80
+ return finalChildren;
81
+ }
82
+ };
83
+ };
48
84
  const getRootProps = (otherHandlers = {}) => {
49
85
  const rootProps = _extends({
50
86
  role: 'tree',
@@ -60,6 +96,7 @@ export const useTreeView = inParams => {
60
96
  return {
61
97
  getRootProps,
62
98
  rootRef: handleRootRef,
63
- contextValue
99
+ contextValue,
100
+ instance: instance
64
101
  };
65
102
  };
@@ -0,0 +1,14 @@
1
+ export const buildWarning = (message, gravity = 'warning') => {
2
+ let alreadyWarned = false;
3
+ const cleanMessage = Array.isArray(message) ? message.join('\n') : message;
4
+ return () => {
5
+ if (!alreadyWarned) {
6
+ alreadyWarned = true;
7
+ if (gravity === 'error') {
8
+ console.error(cleanMessage);
9
+ } else {
10
+ console.warn(cleanMessage);
11
+ }
12
+ }
13
+ };
14
+ };
@@ -0,0 +1 @@
1
+ export * from './items';
@@ -0,0 +1 @@
1
+ export {};