@mui/x-tree-view 7.1.1 → 7.2.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 (77) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/RichTreeView/RichTreeView.types.d.ts +3 -3
  3. package/TreeItem/TreeItem.js +1 -1
  4. package/TreeItem2/TreeItem2.d.ts +5 -1
  5. package/TreeItem2/TreeItem2.js +0 -1
  6. package/index.js +1 -1
  7. package/internals/TreeViewProvider/TreeViewChildrenItemProvider.d.ts +16 -0
  8. package/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +57 -0
  9. package/internals/TreeViewProvider/TreeViewContext.d.ts +2 -0
  10. package/internals/TreeViewProvider/TreeViewProvider.js +2 -3
  11. package/internals/TreeViewProvider/TreeViewProvider.types.d.ts +3 -1
  12. package/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +7 -8
  13. package/internals/models/plugin.d.ts +13 -5
  14. package/internals/models/treeView.d.ts +1 -2
  15. package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +15 -15
  16. package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +25 -26
  17. package/internals/plugins/useTreeViewId/useTreeViewId.js +5 -7
  18. package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +1 -1
  19. package/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -50
  20. package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +19 -15
  21. package/internals/plugins/useTreeViewItems/useTreeViewItems.utils.d.ts +4 -0
  22. package/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +8 -0
  23. package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +66 -41
  24. package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.types.d.ts +3 -2
  25. package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -18
  26. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +11 -22
  27. package/internals/useTreeView/useTreeView.js +21 -3
  28. package/internals/utils/tree.d.ts +8 -0
  29. package/internals/utils/tree.js +137 -0
  30. package/modern/TreeItem/TreeItem.js +1 -1
  31. package/modern/TreeItem2/TreeItem2.js +0 -1
  32. package/modern/index.js +1 -1
  33. package/modern/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +57 -0
  34. package/modern/internals/TreeViewProvider/TreeViewProvider.js +2 -3
  35. package/modern/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +7 -8
  36. package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +15 -15
  37. package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +25 -26
  38. package/modern/internals/plugins/useTreeViewId/useTreeViewId.js +5 -7
  39. package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -50
  40. package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +8 -0
  41. package/modern/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +66 -41
  42. package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -18
  43. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +11 -22
  44. package/modern/internals/useTreeView/useTreeView.js +21 -3
  45. package/modern/internals/utils/tree.js +137 -0
  46. package/modern/useTreeItem2/useTreeItem2.js +1 -1
  47. package/node/TreeItem/TreeItem.js +1 -1
  48. package/node/TreeItem2/TreeItem2.js +0 -1
  49. package/node/index.js +1 -1
  50. package/node/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +67 -0
  51. package/node/internals/TreeViewProvider/TreeViewProvider.js +2 -3
  52. package/node/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +7 -8
  53. package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +15 -15
  54. package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +25 -26
  55. package/node/internals/plugins/useTreeViewId/useTreeViewId.js +5 -7
  56. package/node/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -50
  57. package/node/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +15 -0
  58. package/node/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +66 -41
  59. package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -18
  60. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +11 -22
  61. package/node/internals/useTreeView/useTreeView.js +21 -3
  62. package/node/internals/utils/tree.js +148 -0
  63. package/node/useTreeItem2/useTreeItem2.js +1 -1
  64. package/package.json +1 -1
  65. package/useTreeItem2/useTreeItem2.js +1 -1
  66. package/internals/TreeViewProvider/DescendantProvider.d.ts +0 -38
  67. package/internals/TreeViewProvider/DescendantProvider.js +0 -176
  68. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.d.ts +0 -17
  69. package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +0 -55
  70. package/internals/useTreeView/useTreeView.utils.d.ts +0 -9
  71. package/internals/useTreeView/useTreeView.utils.js +0 -46
  72. package/modern/internals/TreeViewProvider/DescendantProvider.js +0 -176
  73. package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +0 -55
  74. package/modern/internals/useTreeView/useTreeView.utils.js +0 -46
  75. package/node/internals/TreeViewProvider/DescendantProvider.js +0 -185
  76. package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +0 -62
  77. package/node/internals/useTreeView/useTreeView.utils.js +0 -58
package/CHANGELOG.md CHANGED
@@ -3,6 +3,92 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## 7.2.0
7
+
8
+ _Apr 12, 2024_
9
+
10
+ We'd like to offer a big thanks to the 12 contributors who made this release possible. Here are some highlights ✨:
11
+
12
+ - 🎨 Make grid colors customizable through the MUI themes API
13
+ - 🌍 Improve French (fr-FR), German (de-DE), and Swedish (sv-SE) locales on the Data Grid and Pickers
14
+ - 🐞 Bugfixes
15
+ - 📚 Documentation improvements
16
+
17
+ ### Data Grid
18
+
19
+ #### `@mui/x-data-grid@7.2.0`
20
+
21
+ - [DataGrid] Add missing `api` property to `GridCallbackDetails` (#12742) @sai6855
22
+ - [DataGrid] Do not escape double quotes when copying to clipboard (#12722) @cherniavskii
23
+ - [DataGrid] Fix column vertical border (#12741) @romgrk
24
+ - [DataGrid] Fix invalid date error when filtering `date`/`dateTime` columns (#12709) @cherniavskii
25
+ - [DataGrid] Fix overflow with dynamic row height (#12683) @romgrk
26
+ - [DataGrid] Make colors customizable (#12614) @romgrk
27
+ - [l10n] Improve French (fr-FR) locale (#12755) @derek-0000
28
+ - [l10n] Improve German (de-DE) locale (#12752) @Jens-Schoen
29
+ - [l10n] Improve Swedish (sv-SE) locale (#12731) @pontusdacke
30
+
31
+ #### `@mui/x-data-grid-pro@7.2.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
32
+
33
+ Same changes as in `@mui/x-data-grid@7.2.0`.
34
+
35
+ #### `@mui/x-data-grid-premium@7.2.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
36
+
37
+ Same changes as in `@mui/x-data-grid-pro@7.2.0`, plus:
38
+
39
+ - [DataGridPremium] Fix clipboard paste not working when cell loses focus (#12724) @cherniavskii
40
+
41
+ ### Date and Time Pickers
42
+
43
+ #### `@mui/x-date-pickers@7.2.0`
44
+
45
+ - [fields] Fix field editing after closing the picker (#12675) @LukasTy
46
+ - [l10n] Improve French (fr-FR) locale (#12692) @FaroukBel
47
+ - [l10n] Improve German (de-DE) locale (#12752) @Jens-Schoen
48
+ - [l10n] Improve Swedish (sv-SE) locale (#12731) @pontusdacke
49
+ - [pickers] Fix desktop date time Pickers grid layout (#12748) @LukasTy
50
+
51
+ #### `@mui/x-date-pickers-pro@7.2.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
52
+
53
+ Same changes as in `@mui/x-date-pickers@7.2.0`, plus:
54
+
55
+ - [DateTimeRangePicker] Fix desktop toolbar style (#12760) @LukasTy
56
+
57
+ ### Charts
58
+
59
+ #### `@mui/x-charts@7.2.0`
60
+
61
+ - [charts] Fix Bar chart with empty dataset throwing an error (#12708) @JCQuintas
62
+ - [charts] Fix `tickLabelInterval` not working on `YAxis` (#12746) @JCQuintas
63
+
64
+ ### Tree View
65
+
66
+ #### `@mui/x-tree-view@7.2.0`
67
+
68
+ - [TreeView] Add a new lookup to access an item index without expansive computation (#12729) @flaviendelangle
69
+ - [TreeView] Clean up usage of term "node" in internals (#12655) @noraleonte
70
+ - [TreeView] Improve performance by removing `getNavigableChildrenIds` method (#12713) @flaviendelangle
71
+ - [TreeView] Remove `state.items.itemTree` (#12717) @flaviendelangle
72
+ - [TreeView] Remove remaining occurences of the word "node" in the codebase (#12712) @flaviendelangle
73
+ - [TreeView] Return `instance` and `publicAPI` methods from plugin and populate the main objects inside `useTreeView` (#12650) @flaviendelangle
74
+ - [TreeView] Fix behaviors when the item order changes (#12369) @flaviendelangle
75
+
76
+ ### Docs
77
+
78
+ - [docs] Add `AxisFormatter` documentation for customizing tick/tooltip value formatting (#12700) @JCQuintas
79
+ - [docs] Add file explorer example to rich tree view customization docs (#12707) @noraleonte
80
+ - [docs] Do not use import of depth 3 in the doc (#12716) @flaviendelangle
81
+ - [docs] Explain how to clip plots with composition (#12679) @alexfauquette
82
+ - [docs] Fix typo in Data Grid v7 migration page (#12720) @bfaulk96
83
+ - [docs] Fix typo in Pickers v7 migration page (#12721) @bfaulk96
84
+
85
+ ### Core
86
+
87
+ - [core] Support multiple resolved `l10n` PR packages (#12735) @LukasTy
88
+ - [core] Update Netlify release references in release README (#12687) @LukasTy
89
+ - [core] Use `describeTreeView` for icons tests (#12672) @flaviendelangle
90
+ - [core] Use `describeTreeView` in existing tests for `useTreeViewItems` (#12732) @flaviendelangle
91
+
6
92
  ## 7.1.1
7
93
 
8
94
  _Apr 5, 2024_
@@ -4,10 +4,10 @@ import { SxProps } from '@mui/system';
4
4
  import { SlotComponentProps } from '@mui/base/utils';
5
5
  import { RichTreeViewClasses } from './richTreeViewClasses';
6
6
  import { DefaultTreeViewPluginParameters, DefaultTreeViewPluginSlotProps, DefaultTreeViewPluginSlots, DefaultTreeViewPlugins } from '../internals/plugins/defaultPlugins';
7
- import { TreeItem, TreeItemProps } from '../TreeItem';
7
+ import { TreeItemProps } from '../TreeItem';
8
8
  import { TreeItem2Props } from '../TreeItem2';
9
9
  import { TreeViewItemId } from '../models';
10
- import { TreeViewPublicAPI } from '../internals/models';
10
+ import { SlotComponentPropsFromProps, TreeViewPublicAPI } from '../internals/models';
11
11
  interface RichTreeViewItemSlotOwnerState {
12
12
  itemId: TreeViewItemId;
13
13
  label: string;
@@ -26,7 +26,7 @@ export interface RichTreeViewSlots extends DefaultTreeViewPluginSlots {
26
26
  }
27
27
  export interface RichTreeViewSlotProps<R extends {}, Multiple extends boolean | undefined> extends DefaultTreeViewPluginSlotProps {
28
28
  root?: SlotComponentProps<'ul', {}, RichTreeViewProps<R, Multiple>>;
29
- item?: SlotComponentProps<typeof TreeItem, {}, RichTreeViewItemSlotOwnerState>;
29
+ item?: SlotComponentPropsFromProps<TreeItemProps | TreeItem2Props, {}, RichTreeViewItemSlotOwnerState>;
30
30
  }
31
31
  export type RichTreeViewApiRef = React.MutableRefObject<TreeViewPublicAPI<DefaultTreeViewPlugins> | undefined>;
32
32
  export interface RichTreeViewPropsBase extends React.HTMLAttributes<HTMLUListElement> {
@@ -270,7 +270,7 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
270
270
  onKeyDown?.(event);
271
271
  instance.handleItemKeyDown(event, itemId);
272
272
  };
273
- const idAttribute = instance.getTreeItemId(itemId, id);
273
+ const idAttribute = instance.getTreeItemIdAttribute(itemId, id);
274
274
  const tabIndex = instance.canItemBeTabbed(itemId) ? 0 : -1;
275
275
  return /*#__PURE__*/_jsx(TreeItem2Provider, {
276
276
  itemId: itemId,
@@ -5,6 +5,9 @@ export declare const TreeItem2Content: import("@emotion/styled").StyledComponent
5
5
  export declare const TreeItem2Label: import("@emotion/styled").StyledComponent<import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme>, Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.ClassAttributes<HTMLDivElement> | keyof React.HTMLAttributes<HTMLDivElement>>, {}>;
6
6
  export declare const TreeItem2IconContainer: import("@emotion/styled").StyledComponent<import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme>, Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, keyof React.ClassAttributes<HTMLDivElement> | keyof React.HTMLAttributes<HTMLDivElement>>, {}>;
7
7
  export declare const TreeItem2GroupTransition: import("@emotion/styled").StyledComponent<Pick<import("@mui/material/Collapse").CollapseProps, keyof import("@mui/material/Collapse").CollapseProps> & import("@mui/system").MUIStyledCommonProps<import("@mui/material/styles").Theme>, {}, {}>;
8
+ type TreeItem2Component = ((props: TreeItem2Props & React.RefAttributes<HTMLLIElement>) => React.JSX.Element) & {
9
+ propTypes?: any;
10
+ };
8
11
  /**
9
12
  *
10
13
  * Demos:
@@ -15,4 +18,5 @@ export declare const TreeItem2GroupTransition: import("@emotion/styled").StyledC
15
18
  *
16
19
  * - [TreeItem2 API](https://mui.com/x/api/tree-view/tree-item-2/)
17
20
  */
18
- export declare const TreeItem2: React.ForwardRefExoticComponent<TreeItem2Props & React.RefAttributes<HTMLLIElement>>;
21
+ export declare const TreeItem2: TreeItem2Component;
22
+ export {};
@@ -147,7 +147,6 @@ const useUtilityClasses = ownerState => {
147
147
  };
148
148
  return composeClasses(slots, getTreeItemUtilityClass, classes);
149
149
  };
150
-
151
150
  /**
152
151
  *
153
152
  * Demos:
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-tree-view v7.1.1
2
+ * @mui/x-tree-view v7.2.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ export declare const TreeViewChildrenItemContext: React.Context<TreeViewChildrenItemContextValue | null>;
3
+ interface TreeViewChildrenItemProviderProps {
4
+ itemId?: string;
5
+ children: React.ReactNode;
6
+ }
7
+ export declare function TreeViewChildrenItemProvider(props: TreeViewChildrenItemProviderProps): React.JSX.Element;
8
+ export declare namespace TreeViewChildrenItemProvider {
9
+ var propTypes: any;
10
+ }
11
+ interface TreeViewChildrenItemContextValue {
12
+ registerChild: (idAttribute: string, itemId: string) => void;
13
+ unregisterChild: (idAttribute: string) => void;
14
+ parentId: string | null;
15
+ }
16
+ export {};
@@ -0,0 +1,57 @@
1
+ import * as React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useTreeViewContext } from './useTreeViewContext';
4
+ import { jsx as _jsx } from "react/jsx-runtime";
5
+ export const TreeViewChildrenItemContext = /*#__PURE__*/React.createContext(null);
6
+ if (process.env.NODE_ENV !== 'production') {
7
+ TreeViewChildrenItemContext.displayName = 'TreeViewChildrenItemContext';
8
+ }
9
+ export function TreeViewChildrenItemProvider(props) {
10
+ const {
11
+ children,
12
+ itemId = null
13
+ } = props;
14
+ const {
15
+ instance,
16
+ rootRef
17
+ } = useTreeViewContext();
18
+ const childrenIdAttrToIdRef = React.useRef(new Map());
19
+ React.useEffect(() => {
20
+ if (!rootRef.current) {
21
+ return;
22
+ }
23
+ let idAttr = null;
24
+ if (itemId == null) {
25
+ idAttr = rootRef.current.id;
26
+ } else {
27
+ // Undefined during 1st render
28
+ const itemMeta = instance.getItemMeta(itemId);
29
+ if (itemMeta !== undefined) {
30
+ idAttr = instance.getTreeItemIdAttribute(itemId, itemMeta.idAttribute);
31
+ }
32
+ }
33
+ if (idAttr == null) {
34
+ return;
35
+ }
36
+ const previousChildrenIds = instance.getItemOrderedChildrenIds(itemId ?? null) ?? [];
37
+ const childrenElements = rootRef.current.querySelectorAll(`${itemId == null ? '' : `*[id="${idAttr}"] `}[role="treeitem"]:not(*[id="${idAttr}"] [role="treeitem"] [role="treeitem"])`);
38
+ const childrenIds = Array.from(childrenElements).map(child => childrenIdAttrToIdRef.current.get(child.id));
39
+ const hasChanged = childrenIds.length !== previousChildrenIds.length || childrenIds.some((childId, index) => childId !== previousChildrenIds[index]);
40
+ if (hasChanged) {
41
+ instance.setJSXItemsOrderedChildrenIds(itemId ?? null, childrenIds);
42
+ }
43
+ });
44
+ const value = React.useMemo(() => ({
45
+ registerChild: (childIdAttribute, childItemId) => childrenIdAttrToIdRef.current.set(childIdAttribute, childItemId),
46
+ unregisterChild: childIdAttribute => childrenIdAttrToIdRef.current.delete(childIdAttribute),
47
+ parentId: itemId
48
+ }), [itemId]);
49
+ return /*#__PURE__*/_jsx(TreeViewChildrenItemContext.Provider, {
50
+ value: value,
51
+ children: children
52
+ });
53
+ }
54
+ process.env.NODE_ENV !== "production" ? TreeViewChildrenItemProvider.propTypes = {
55
+ children: PropTypes.node,
56
+ id: PropTypes.string
57
+ } : void 0;
@@ -5,6 +5,8 @@ import * as React from 'react';
5
5
  export declare const TreeViewContext: React.Context<{
6
6
  instance: {};
7
7
  publicAPI: {};
8
+ rootRef: React.RefObject<HTMLUListElement>;
8
9
  wrapItem: import("../models").TreeItemWrapper;
10
+ wrapRoot: import("../models").TreeRootWrapper;
9
11
  runItemPlugins: <TProps extends {}>(props: TProps) => Required<import("../models").TreeViewItemPluginResponse>;
10
12
  } | null>;
@@ -1,6 +1,5 @@
1
1
  import * as React from 'react';
2
2
  import { TreeViewContext } from './TreeViewContext';
3
- import { DescendantProvider } from './DescendantProvider';
4
3
  import { jsx as _jsx } from "react/jsx-runtime";
5
4
  /**
6
5
  * Sets up the contexts for the underlying TreeItem components.
@@ -14,8 +13,8 @@ export function TreeViewProvider(props) {
14
13
  } = props;
15
14
  return /*#__PURE__*/_jsx(TreeViewContext.Provider, {
16
15
  value: value,
17
- children: /*#__PURE__*/_jsx(DescendantProvider, {
18
- children: children
16
+ children: value.wrapRoot({
17
+ children
19
18
  })
20
19
  });
21
20
  }
@@ -1,9 +1,11 @@
1
1
  import * as React from 'react';
2
- import { MergePluginsProperty, TreeItemWrapper, TreeViewAnyPluginSignature, TreeViewInstance, TreeViewItemPluginResponse, TreeViewPublicAPI } from '../models';
2
+ import { MergePluginsProperty, TreeItemWrapper, TreeRootWrapper, TreeViewAnyPluginSignature, TreeViewInstance, TreeViewItemPluginResponse, TreeViewPublicAPI } from '../models';
3
3
  export type TreeViewContextValue<TPlugins extends readonly TreeViewAnyPluginSignature[]> = MergePluginsProperty<TPlugins, 'contextValue'> & {
4
4
  instance: TreeViewInstance<TPlugins>;
5
5
  publicAPI: TreeViewPublicAPI<TPlugins>;
6
+ rootRef: React.RefObject<HTMLUListElement>;
6
7
  wrapItem: TreeItemWrapper;
8
+ wrapRoot: TreeRootWrapper;
7
9
  runItemPlugins: <TProps extends {}>(props: TProps) => Required<TreeViewItemPluginResponse>;
8
10
  };
9
11
  export interface TreeViewProviderProps<TPlugins extends readonly TreeViewAnyPluginSignature[]> {
@@ -1,12 +1,9 @@
1
1
  import * as React from 'react';
2
2
  import { EventManager } from '../../utils/EventManager';
3
- import { populateInstance } from '../../useTreeView/useTreeView.utils';
4
3
  const isSyntheticEvent = event => {
5
4
  return event.isPropagationStopped !== undefined;
6
5
  };
7
- export const useTreeViewInstanceEvents = ({
8
- instance
9
- }) => {
6
+ export const useTreeViewInstanceEvents = () => {
10
7
  const [eventManager] = React.useState(() => new EventManager());
11
8
  const publishEvent = React.useCallback((...args) => {
12
9
  const [name, params, event = {}] = args;
@@ -22,9 +19,11 @@ export const useTreeViewInstanceEvents = ({
22
19
  eventManager.removeListener(event, handler);
23
20
  };
24
21
  }, [eventManager]);
25
- populateInstance(instance, {
26
- $$publishEvent: publishEvent,
27
- $$subscribeEvent: subscribeEvent
28
- });
22
+ return {
23
+ instance: {
24
+ $$publishEvent: publishEvent,
25
+ $$subscribeEvent: subscribeEvent
26
+ }
27
+ };
29
28
  };
30
29
  useTreeViewInstanceEvents.params = {};
@@ -7,7 +7,6 @@ import type { TreeViewCorePluginsSignature } from '../corePlugins';
7
7
  import { TreeViewItemId } from '../../models';
8
8
  export interface TreeViewPluginOptions<TSignature extends TreeViewAnyPluginSignature> {
9
9
  instance: TreeViewUsedInstance<TSignature>;
10
- publicAPI: TreeViewUsedPublicAPI<TSignature>;
11
10
  params: TreeViewUsedDefaultizedParams<TSignature>;
12
11
  state: TreeViewUsedState<TSignature>;
13
12
  slots: TSignature['slots'];
@@ -23,7 +22,7 @@ type TreeViewModelsInitializer<TSignature extends TreeViewAnyPluginSignature> =
23
22
  };
24
23
  type TreeViewResponse<TSignature extends TreeViewAnyPluginSignature> = {
25
24
  getRootProps?: <TOther extends EventHandlers = {}>(otherHandlers: TOther) => React.HTMLAttributes<HTMLUListElement>;
26
- } & OptionalIfEmpty<'contextValue', TSignature['contextValue']>;
25
+ } & OptionalIfEmpty<'publicAPI', TSignature['publicAPI']> & OptionalIfEmpty<'instance', TSignature['instance']> & OptionalIfEmpty<'contextValue', TSignature['contextValue']>;
27
26
  export type TreeViewPluginSignature<T extends {
28
27
  params?: {};
29
28
  defaultizedParams?: {};
@@ -135,8 +134,11 @@ export type TreeItemWrapper = (params: {
135
134
  itemId: TreeViewItemId;
136
135
  children: React.ReactNode;
137
136
  }) => React.ReactNode;
137
+ export type TreeRootWrapper = (params: {
138
+ children: React.ReactNode;
139
+ }) => React.ReactNode;
138
140
  export type TreeViewPlugin<TSignature extends TreeViewAnyPluginSignature> = {
139
- (options: TreeViewPluginOptions<TSignature>): void | TreeViewResponse<TSignature>;
141
+ (options: TreeViewPluginOptions<TSignature>): TreeViewResponse<TSignature>;
140
142
  getDefaultizedParams?: (params: TreeViewUsedParams<TSignature>) => TSignature['defaultizedParams'];
141
143
  getInitialState?: (params: TreeViewUsedDefaultizedParams<TSignature>) => TSignature['state'];
142
144
  models?: TreeViewModelsInitializer<TSignature>;
@@ -144,9 +146,15 @@ export type TreeViewPlugin<TSignature extends TreeViewAnyPluginSignature> = {
144
146
  itemPlugin?: TreeViewItemPlugin<any>;
145
147
  /**
146
148
  * Render function used to add React wrappers around the TreeItem.
147
- * @param {TreeItemWrapperParams} params The params of the item.
148
- * @returns {React.ReactNode} The wrapped items.
149
+ * @param {{ nodeId: TreeViewItemId; children: React.ReactNode; }} params The params of the item.
150
+ * @returns {React.ReactNode} The wrapped item.
149
151
  */
150
152
  wrapItem?: TreeItemWrapper;
153
+ /**
154
+ * Render function used to add React wrappers around the TreeView.
155
+ * @param {{ children: React.ReactNode; }} params The params of the root.
156
+ * @returns {React.ReactNode} The wrapped root.
157
+ */
158
+ wrapRoot?: TreeRootWrapper;
151
159
  };
152
160
  export {};
@@ -1,9 +1,8 @@
1
1
  import type { TreeViewAnyPluginSignature } from './plugin';
2
2
  import type { MergePluginsProperty } from './helpers';
3
- export interface TreeViewNode {
3
+ export interface TreeViewItemMeta {
4
4
  id: string;
5
5
  idAttribute: string | undefined;
6
- index: number;
7
6
  parentId: string | null;
8
7
  expandable: boolean;
9
8
  disabled: boolean;
@@ -1,10 +1,8 @@
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, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
5
4
  export const useTreeViewExpansion = ({
6
5
  instance,
7
- publicAPI,
8
6
  params,
9
7
  models
10
8
  }) => {
@@ -20,7 +18,7 @@ export const useTreeViewExpansion = ({
20
18
  models.expandedItems.setControlledValue(value);
21
19
  };
22
20
  const isItemExpanded = React.useCallback(itemId => expandedItemsMap.has(itemId), [expandedItemsMap]);
23
- const isItemExpandable = React.useCallback(itemId => !!instance.getNode(itemId)?.expandable, [instance]);
21
+ const isItemExpandable = React.useCallback(itemId => !!instance.getItemMeta(itemId)?.expandable, [instance]);
24
22
  const toggleItemExpansion = useEventCallback((event, itemId) => {
25
23
  const isExpandedBefore = instance.isItemExpanded(itemId);
26
24
  instance.setItemExpansion(event, itemId, !isExpandedBefore);
@@ -42,8 +40,8 @@ export const useTreeViewExpansion = ({
42
40
  setExpandedItems(event, newExpanded);
43
41
  });
44
42
  const expandAllSiblings = (event, itemId) => {
45
- const node = instance.getNode(itemId);
46
- const siblings = instance.getChildrenIds(node.parentId);
43
+ const itemMeta = instance.getItemMeta(itemId);
44
+ const siblings = instance.getItemOrderedChildrenIds(itemMeta.parentId);
47
45
  const diff = siblings.filter(child => instance.isItemExpandable(child) && !instance.isItemExpanded(child));
48
46
  const newExpanded = models.expandedItems.value.concat(diff);
49
47
  if (diff.length > 0) {
@@ -55,16 +53,18 @@ export const useTreeViewExpansion = ({
55
53
  setExpandedItems(event, newExpanded);
56
54
  }
57
55
  };
58
- populateInstance(instance, {
59
- isItemExpanded,
60
- isItemExpandable,
61
- setItemExpansion,
62
- toggleItemExpansion,
63
- expandAllSiblings
64
- });
65
- populatePublicAPI(publicAPI, {
66
- setItemExpansion
67
- });
56
+ return {
57
+ publicAPI: {
58
+ setItemExpansion
59
+ },
60
+ instance: {
61
+ isItemExpanded,
62
+ isItemExpandable,
63
+ setItemExpansion,
64
+ toggleItemExpansion,
65
+ expandAllSiblings
66
+ }
67
+ };
68
68
  };
69
69
  useTreeViewExpansion.models = {
70
70
  expandedItems: {
@@ -2,13 +2,13 @@ import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
3
  import useEventCallback from '@mui/utils/useEventCallback';
4
4
  import ownerDocument from '@mui/utils/ownerDocument';
5
- import { populateInstance, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
6
5
  import { useInstanceEventHandler } from '../../hooks/useInstanceEventHandler';
7
6
  import { getActiveElement } from '../../utils/utils';
7
+ import { getFirstNavigableItem } from '../../utils/tree';
8
8
  const useTabbableItemId = (instance, selectedItems) => {
9
9
  const isItemVisible = itemId => {
10
- const node = instance.getNode(itemId);
11
- return node && (node.parentId == null || instance.isItemExpanded(node.parentId));
10
+ const itemMeta = instance.getItemMeta(itemId);
11
+ return itemMeta && (itemMeta.parentId == null || instance.isItemExpanded(itemMeta.parentId));
12
12
  };
13
13
  let tabbableItemId;
14
14
  if (Array.isArray(selectedItems)) {
@@ -17,13 +17,12 @@ const useTabbableItemId = (instance, selectedItems) => {
17
17
  tabbableItemId = selectedItems;
18
18
  }
19
19
  if (tabbableItemId == null) {
20
- tabbableItemId = instance.getNavigableChildrenIds(null)[0];
20
+ tabbableItemId = getFirstNavigableItem(instance);
21
21
  }
22
22
  return tabbableItemId;
23
23
  };
24
24
  export const useTreeViewFocus = ({
25
25
  instance,
26
- publicAPI,
27
26
  params,
28
27
  state,
29
28
  setState,
@@ -42,12 +41,12 @@ export const useTreeViewFocus = ({
42
41
  const isTreeViewFocused = React.useCallback(() => !!rootRef.current && rootRef.current.contains(getActiveElement(ownerDocument(rootRef.current))), [rootRef]);
43
42
  const isItemFocused = React.useCallback(itemId => state.focusedItemId === itemId && isTreeViewFocused(), [state.focusedItemId, isTreeViewFocused]);
44
43
  const isItemVisible = itemId => {
45
- const node = instance.getNode(itemId);
46
- return node && (node.parentId == null || instance.isItemExpanded(node.parentId));
44
+ const itemMeta = instance.getItemMeta(itemId);
45
+ return itemMeta && (itemMeta.parentId == null || instance.isItemExpanded(itemMeta.parentId));
47
46
  };
48
47
  const innerFocusItem = (event, itemId) => {
49
- const node = instance.getNode(itemId);
50
- const itemElement = document.getElementById(instance.getTreeItemId(itemId, node.idAttribute));
48
+ const itemMeta = instance.getItemMeta(itemId);
49
+ const itemElement = document.getElementById(instance.getTreeItemIdAttribute(itemId, itemMeta.idAttribute));
51
50
  if (itemElement) {
52
51
  itemElement.focus();
53
52
  }
@@ -70,7 +69,7 @@ export const useTreeViewFocus = ({
70
69
  itemToFocusId = models.selectedItems.value;
71
70
  }
72
71
  if (itemToFocusId == null) {
73
- itemToFocusId = instance.getNavigableChildrenIds(null)[0];
72
+ itemToFocusId = getFirstNavigableItem(instance);
74
73
  }
75
74
  innerFocusItem(event, itemToFocusId);
76
75
  });
@@ -78,9 +77,9 @@ export const useTreeViewFocus = ({
78
77
  if (state.focusedItemId == null) {
79
78
  return;
80
79
  }
81
- const node = instance.getNode(state.focusedItemId);
82
- if (node) {
83
- const itemElement = document.getElementById(instance.getTreeItemId(state.focusedItemId, node.idAttribute));
80
+ const itemMeta = instance.getItemMeta(state.focusedItemId);
81
+ if (itemMeta) {
82
+ const itemElement = document.getElementById(instance.getTreeItemIdAttribute(state.focusedItemId, itemMeta.idAttribute));
84
83
  if (itemElement) {
85
84
  itemElement.blur();
86
85
  }
@@ -88,16 +87,6 @@ export const useTreeViewFocus = ({
88
87
  setFocusedItemId(null);
89
88
  });
90
89
  const canItemBeTabbed = itemId => itemId === tabbableItemId;
91
- populateInstance(instance, {
92
- isItemFocused,
93
- canItemBeTabbed,
94
- focusItem,
95
- focusDefaultItem,
96
- removeFocusedItem
97
- });
98
- populatePublicAPI(publicAPI, {
99
- focusItem
100
- });
101
90
  useInstanceEventHandler(instance, 'removeItem', ({
102
91
  id
103
92
  }) => {
@@ -112,13 +101,23 @@ export const useTreeViewFocus = ({
112
101
  instance.focusDefaultItem(event);
113
102
  }
114
103
  };
115
- const focusedItem = instance.getNode(state.focusedItemId);
116
- const activeDescendant = focusedItem ? instance.getTreeItemId(focusedItem.id, focusedItem.idAttribute) : null;
104
+ const focusedItem = instance.getItemMeta(state.focusedItemId);
105
+ const activeDescendant = focusedItem ? instance.getTreeItemIdAttribute(focusedItem.id, focusedItem.idAttribute) : null;
117
106
  return {
118
107
  getRootProps: otherHandlers => ({
119
108
  onFocus: createHandleFocus(otherHandlers),
120
109
  'aria-activedescendant': activeDescendant ?? undefined
121
- })
110
+ }),
111
+ publicAPI: {
112
+ focusItem
113
+ },
114
+ instance: {
115
+ isItemFocused,
116
+ canItemBeTabbed,
117
+ focusItem,
118
+ focusDefaultItem,
119
+ removeFocusedItem
120
+ }
122
121
  };
123
122
  };
124
123
  useTreeViewFocus.getInitialState = () => ({
@@ -1,19 +1,17 @@
1
1
  import * as React from 'react';
2
2
  import useId from '@mui/utils/useId';
3
- import { populateInstance } from '../../useTreeView/useTreeView.utils';
4
3
  export const useTreeViewId = ({
5
- instance,
6
4
  params
7
5
  }) => {
8
6
  const treeId = useId(params.id);
9
- const getTreeItemId = React.useCallback((itemId, idAttribute) => idAttribute ?? `${treeId}-${itemId}`, [treeId]);
10
- populateInstance(instance, {
11
- getTreeItemId
12
- });
7
+ const getTreeItemIdAttribute = React.useCallback((itemId, idAttribute) => idAttribute ?? `${treeId}-${itemId}`, [treeId]);
13
8
  return {
14
9
  getRootProps: () => ({
15
10
  id: treeId
16
- })
11
+ }),
12
+ instance: {
13
+ getTreeItemIdAttribute
14
+ }
17
15
  };
18
16
  };
19
17
  useTreeViewId.params = {
@@ -1,6 +1,6 @@
1
1
  import { TreeViewPluginSignature } from '../../models';
2
2
  export interface UseTreeViewIdInstance {
3
- getTreeItemId: (itemId: string, idAttribute: string | undefined) => string;
3
+ getTreeItemIdAttribute: (itemId: string, idAttribute: string | undefined) => string;
4
4
  }
5
5
  export interface UseTreeViewIdParameters {
6
6
  /**