@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.
- package/CHANGELOG.md +86 -0
- package/RichTreeView/RichTreeView.types.d.ts +3 -3
- package/TreeItem/TreeItem.js +1 -1
- package/TreeItem2/TreeItem2.d.ts +5 -1
- package/TreeItem2/TreeItem2.js +0 -1
- package/index.js +1 -1
- package/internals/TreeViewProvider/TreeViewChildrenItemProvider.d.ts +16 -0
- package/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +57 -0
- package/internals/TreeViewProvider/TreeViewContext.d.ts +2 -0
- package/internals/TreeViewProvider/TreeViewProvider.js +2 -3
- package/internals/TreeViewProvider/TreeViewProvider.types.d.ts +3 -1
- package/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +7 -8
- package/internals/models/plugin.d.ts +13 -5
- package/internals/models/treeView.d.ts +1 -2
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +15 -15
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +25 -26
- package/internals/plugins/useTreeViewId/useTreeViewId.js +5 -7
- package/internals/plugins/useTreeViewId/useTreeViewId.types.d.ts +1 -1
- package/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -50
- package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +19 -15
- package/internals/plugins/useTreeViewItems/useTreeViewItems.utils.d.ts +4 -0
- package/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +8 -0
- package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +66 -41
- package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.types.d.ts +3 -2
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -18
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +11 -22
- package/internals/useTreeView/useTreeView.js +21 -3
- package/internals/utils/tree.d.ts +8 -0
- package/internals/utils/tree.js +137 -0
- package/modern/TreeItem/TreeItem.js +1 -1
- package/modern/TreeItem2/TreeItem2.js +0 -1
- package/modern/index.js +1 -1
- package/modern/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +57 -0
- package/modern/internals/TreeViewProvider/TreeViewProvider.js +2 -3
- package/modern/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +7 -8
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +15 -15
- package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +25 -26
- package/modern/internals/plugins/useTreeViewId/useTreeViewId.js +5 -7
- package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -50
- package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +8 -0
- package/modern/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +66 -41
- package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -18
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +11 -22
- package/modern/internals/useTreeView/useTreeView.js +21 -3
- package/modern/internals/utils/tree.js +137 -0
- package/modern/useTreeItem2/useTreeItem2.js +1 -1
- package/node/TreeItem/TreeItem.js +1 -1
- package/node/TreeItem2/TreeItem2.js +0 -1
- package/node/index.js +1 -1
- package/node/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +67 -0
- package/node/internals/TreeViewProvider/TreeViewProvider.js +2 -3
- package/node/internals/corePlugins/useTreeViewInstanceEvents/useTreeViewInstanceEvents.js +7 -8
- package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +15 -15
- package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +25 -26
- package/node/internals/plugins/useTreeViewId/useTreeViewId.js +5 -7
- package/node/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -50
- package/node/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +15 -0
- package/node/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +66 -41
- package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +20 -18
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +11 -22
- package/node/internals/useTreeView/useTreeView.js +21 -3
- package/node/internals/utils/tree.js +148 -0
- package/node/useTreeItem2/useTreeItem2.js +1 -1
- package/package.json +1 -1
- package/useTreeItem2/useTreeItem2.js +1 -1
- package/internals/TreeViewProvider/DescendantProvider.d.ts +0 -38
- package/internals/TreeViewProvider/DescendantProvider.js +0 -176
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.d.ts +0 -17
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +0 -55
- package/internals/useTreeView/useTreeView.utils.d.ts +0 -9
- package/internals/useTreeView/useTreeView.utils.js +0 -46
- package/modern/internals/TreeViewProvider/DescendantProvider.js +0 -176
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +0 -55
- package/modern/internals/useTreeView/useTreeView.utils.js +0 -46
- package/node/internals/TreeViewProvider/DescendantProvider.js +0 -185
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +0 -62
- 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` [](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` [](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` [](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 {
|
|
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?:
|
|
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> {
|
package/TreeItem/TreeItem.js
CHANGED
|
@@ -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.
|
|
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,
|
package/TreeItem2/TreeItem2.d.ts
CHANGED
|
@@ -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:
|
|
21
|
+
export declare const TreeItem2: TreeItem2Component;
|
|
22
|
+
export {};
|
package/TreeItem2/TreeItem2.js
CHANGED
package/index.js
CHANGED
|
@@ -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:
|
|
18
|
-
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
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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>):
|
|
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 {
|
|
148
|
-
* @returns {React.ReactNode} The wrapped
|
|
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
|
|
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.
|
|
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
|
|
46
|
-
const siblings = instance.
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
|
11
|
-
return
|
|
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
|
|
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
|
|
46
|
-
return
|
|
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
|
|
50
|
-
const itemElement = document.getElementById(instance.
|
|
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
|
|
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
|
|
82
|
-
if (
|
|
83
|
-
const itemElement = document.getElementById(instance.
|
|
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.
|
|
116
|
-
const activeDescendant = focusedItem ? instance.
|
|
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
|
|
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
|
-
|
|
3
|
+
getTreeItemIdAttribute: (itemId: string, idAttribute: string | undefined) => string;
|
|
4
4
|
}
|
|
5
5
|
export interface UseTreeViewIdParameters {
|
|
6
6
|
/**
|