@mui/x-tree-view 8.11.3 → 8.13.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 +296 -6
- package/RichTreeView/RichTreeView.js +5 -5
- package/RichTreeView/RichTreeView.types.d.ts +2 -3
- package/RichTreeView/index.d.ts +1 -1
- package/SimpleTreeView/SimpleTreeView.types.d.ts +2 -3
- package/SimpleTreeView/index.d.ts +1 -1
- package/TreeItemIcon/TreeItemIcon.js +12 -3
- package/TreeItemIcon/TreeItemIcon.types.d.ts +4 -4
- package/esm/RichTreeView/RichTreeView.js +5 -5
- package/esm/RichTreeView/RichTreeView.types.d.ts +2 -3
- package/esm/RichTreeView/index.d.ts +1 -1
- package/esm/SimpleTreeView/SimpleTreeView.types.d.ts +2 -3
- package/esm/SimpleTreeView/index.d.ts +1 -1
- package/esm/TreeItemIcon/TreeItemIcon.js +12 -3
- package/esm/TreeItemIcon/TreeItemIcon.types.d.ts +4 -4
- package/esm/hooks/useApplyPropagationToSelectedItemsOnMount.js +2 -2
- package/esm/index.js +1 -1
- package/esm/internals/TreeViewProvider/TreeViewStyleContext.d.ts +3 -3
- package/esm/internals/index.d.ts +2 -2
- package/esm/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +5 -5
- package/esm/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +1 -1
- package/esm/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +2 -2
- package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.js +79 -158
- package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.d.ts +0 -8
- package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js +0 -8
- package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +12 -26
- package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.utils.d.ts +36 -2
- package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +115 -1
- package/esm/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +6 -6
- package/esm/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +1 -1
- package/esm/internals/plugins/useTreeViewLabel/useTreeViewLabel.js +2 -2
- package/esm/internals/plugins/useTreeViewLazyLoading/index.d.ts +1 -1
- package/esm/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.selectors.d.ts +6 -2
- package/esm/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.selectors.js +7 -2
- package/esm/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.types.d.ts +8 -9
- package/esm/internals/plugins/useTreeViewSelection/useTreeViewSelection.itemPlugin.js +12 -3
- package/esm/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +2 -2
- package/esm/internals/useTreeView/useTreeView.js +2 -2
- package/esm/useTreeItem/useTreeItem.js +3 -3
- package/hooks/useApplyPropagationToSelectedItemsOnMount.js +2 -3
- package/index.js +1 -1
- package/internals/TreeViewProvider/TreeViewStyleContext.d.ts +3 -3
- package/internals/index.d.ts +2 -2
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +9 -9
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +4 -4
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +2 -2
- package/internals/plugins/useTreeViewItems/useTreeViewItems.js +80 -159
- package/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.d.ts +0 -8
- package/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js +0 -8
- package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +12 -26
- package/internals/plugins/useTreeViewItems/useTreeViewItems.utils.d.ts +36 -2
- package/internals/plugins/useTreeViewItems/useTreeViewItems.utils.js +119 -2
- package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +8 -8
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +2 -3
- package/internals/plugins/useTreeViewLabel/useTreeViewLabel.js +2 -2
- package/internals/plugins/useTreeViewLazyLoading/index.d.ts +1 -1
- package/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.selectors.d.ts +6 -2
- package/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.selectors.js +7 -2
- package/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.types.d.ts +8 -9
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.itemPlugin.js +12 -3
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +2 -2
- package/internals/useTreeView/useTreeView.js +2 -2
- package/package.json +3 -3
- package/useTreeItem/useTreeItem.js +3 -3
- package/esm/internals/hooks/useLazyRef.d.ts +0 -1
- package/esm/internals/hooks/useLazyRef.js +0 -1
- package/esm/internals/hooks/useOnMount.d.ts +0 -1
- package/esm/internals/hooks/useOnMount.js +0 -1
- package/esm/internals/hooks/useTimeout.d.ts +0 -1
- package/esm/internals/hooks/useTimeout.js +0 -1
- package/internals/hooks/useLazyRef.d.ts +0 -1
- package/internals/hooks/useLazyRef.js +0 -13
- package/internals/hooks/useOnMount.d.ts +0 -1
- package/internals/hooks/useOnMount.js +0 -13
- package/internals/hooks/useTimeout.d.ts +0 -1
- package/internals/hooks/useTimeout.js +0 -13
|
@@ -28,16 +28,16 @@ export interface TreeViewSlots {
|
|
|
28
28
|
/**
|
|
29
29
|
* The default icon used to collapse the item.
|
|
30
30
|
*/
|
|
31
|
-
collapseIcon?: React.ElementType;
|
|
31
|
+
collapseIcon?: React.ElementType | null;
|
|
32
32
|
/**
|
|
33
33
|
* The default icon used to expand the item.
|
|
34
34
|
*/
|
|
35
|
-
expandIcon?: React.ElementType;
|
|
35
|
+
expandIcon?: React.ElementType | null;
|
|
36
36
|
/**
|
|
37
37
|
* The default icon displayed next to an end item.
|
|
38
38
|
* This is applied to all Tree Items and can be overridden by the TreeItem `icon` slot prop.
|
|
39
39
|
*/
|
|
40
|
-
endIcon?: React.ElementType;
|
|
40
|
+
endIcon?: React.ElementType | null;
|
|
41
41
|
}
|
|
42
42
|
export interface TreeViewSlotProps {
|
|
43
43
|
collapseIcon?: SlotComponentProps<'svg', {}, {}>;
|
package/esm/internals/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ export { TreeViewProvider, useTreeViewContext } from "./TreeViewProvider/index.j
|
|
|
3
3
|
export { RichTreeViewItems } from "./components/RichTreeViewItems.js";
|
|
4
4
|
export type { RichTreeViewItemsSlots, RichTreeViewItemsSlotProps } from "./components/RichTreeViewItems.js";
|
|
5
5
|
export { unstable_resetCleanupTracking, useInstanceEventHandler } from "./hooks/useInstanceEventHandler.js";
|
|
6
|
-
export type { TreeViewPlugin, TreeViewPluginSignature, ConvertPluginsIntoSignatures, MergeSignaturesProperty, TreeViewPublicAPI, TreeViewState, TreeViewItemMeta, TreeViewInstance, TreeViewItemPlugin, TreeViewUsedStore } from "./models/index.js";
|
|
6
|
+
export type { TreeViewPlugin, TreeViewPluginSignature, ConvertPluginsIntoSignatures, MergeSignaturesProperty, TreeViewPublicAPI, TreeViewState, TreeViewItemMeta, TreeViewInstance, TreeViewItemPlugin, TreeViewUsedStore, TreeViewUsedInstance, TreeViewUsedParamsWithDefaults } from "./models/index.js";
|
|
7
7
|
export type { TreeViewCorePluginParameters } from "./corePlugins/index.js";
|
|
8
8
|
export { useTreeViewExpansion, expansionSelectors } from "./plugins/useTreeViewExpansion/index.js";
|
|
9
9
|
export type { UseTreeViewExpansionSignature, UseTreeViewExpansionParameters } from "./plugins/useTreeViewExpansion/index.js";
|
|
@@ -17,7 +17,7 @@ export { useTreeViewItems, buildSiblingIndexes, itemsSelectors, TREE_VIEW_ROOT_P
|
|
|
17
17
|
export type { UseTreeViewItemsSignature, UseTreeViewItemsParameters, UseTreeViewItemsState } from "./plugins/useTreeViewItems/index.js";
|
|
18
18
|
export { useTreeViewLabel, labelSelectors } from "./plugins/useTreeViewLabel/index.js";
|
|
19
19
|
export type { UseTreeViewLabelSignature, UseTreeViewLabelParameters } from "./plugins/useTreeViewLabel/index.js";
|
|
20
|
-
export type { UseTreeViewLazyLoadingSignature, UseTreeViewLazyLoadingParameters, UseTreeViewLazyLoadingInstance } from "./plugins/useTreeViewLazyLoading/index.js";
|
|
20
|
+
export type { UseTreeViewLazyLoadingSignature, UseTreeViewLazyLoadingParameters, UseTreeViewLazyLoadingInstance, DataSource } from "./plugins/useTreeViewLazyLoading/index.js";
|
|
21
21
|
export { lazyLoadingSelectors } from "./plugins/useTreeViewLazyLoading/index.js";
|
|
22
22
|
export { useTreeViewJSXItems } from "./plugins/useTreeViewJSXItems/index.js";
|
|
23
23
|
export type { UseTreeViewJSXItemsSignature, UseTreeViewJSXItemsParameters } from "./plugins/useTreeViewJSXItems/index.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import { useAssertModelConsistency } from '@mui/x-internals/useAssertModelConsistency';
|
|
3
|
-
import useEventCallback from '@
|
|
4
|
-
import
|
|
3
|
+
import { useEventCallback } from '@base-ui-components/utils/useEventCallback';
|
|
4
|
+
import { useIsoLayoutEffect } from '@base-ui-components/utils/useIsoLayoutEffect';
|
|
5
5
|
import { expansionSelectors } from "./useTreeViewExpansion.selectors.js";
|
|
6
6
|
import { getExpansionTrigger } from "./useTreeViewExpansion.utils.js";
|
|
7
7
|
import { itemsSelectors } from "../useTreeViewItems/useTreeViewItems.selectors.js";
|
|
@@ -17,7 +17,7 @@ export const useTreeViewExpansion = ({
|
|
|
17
17
|
controlled: params.expandedItems,
|
|
18
18
|
defaultValue: params.defaultExpandedItems
|
|
19
19
|
});
|
|
20
|
-
|
|
20
|
+
useIsoLayoutEffect(() => {
|
|
21
21
|
const newExpansionTrigger = getExpansionTrigger({
|
|
22
22
|
isItemEditable: params.isItemEditable,
|
|
23
23
|
expansionTrigger: params.expansionTrigger
|
|
@@ -84,7 +84,7 @@ export const useTreeViewExpansion = ({
|
|
|
84
84
|
});
|
|
85
85
|
});
|
|
86
86
|
const isItemExpanded = useEventCallback(itemId => {
|
|
87
|
-
return expansionSelectors.
|
|
87
|
+
return expansionSelectors.isItemExpanded(store.state, itemId);
|
|
88
88
|
});
|
|
89
89
|
const expandAllSiblings = (event, itemId) => {
|
|
90
90
|
const itemMeta = itemsSelectors.itemMeta(store.state, itemId);
|
|
@@ -107,7 +107,7 @@ export const useTreeViewExpansion = ({
|
|
|
107
107
|
/**
|
|
108
108
|
* Update the controlled model when the `expandedItems` prop changes.
|
|
109
109
|
*/
|
|
110
|
-
|
|
110
|
+
useIsoLayoutEffect(() => {
|
|
111
111
|
const expandedItems = params.expandedItems;
|
|
112
112
|
if (expandedItems !== undefined) {
|
|
113
113
|
store.set('expansion', _extends({}, store.state.expansion, {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
|
-
import useEventCallback from '@
|
|
2
|
+
import { useEventCallback } from '@base-ui-components/utils/useEventCallback';
|
|
3
3
|
import { useStoreEffect } from '@mui/x-internals/store';
|
|
4
4
|
import { focusSelectors } from "./useTreeViewFocus.selectors.js";
|
|
5
5
|
import { expansionSelectors } from "../useTreeViewExpansion/useTreeViewExpansion.selectors.js";
|
|
@@ -9,10 +9,10 @@ export interface UseTreeViewFocusPublicAPI {
|
|
|
9
9
|
*
|
|
10
10
|
* If the item is the child of a collapsed item, then this method will do nothing.
|
|
11
11
|
* Make sure to expand the ancestors of the item before calling this method if needed.
|
|
12
|
-
* @param {React.SyntheticEvent} event The DOM event that triggered the change.
|
|
12
|
+
* @param {React.SyntheticEvent | null} event The DOM event that triggered the change.
|
|
13
13
|
* @param {TreeViewItemId} itemId The id of the item to focus.
|
|
14
14
|
*/
|
|
15
|
-
focusItem: (event: React.SyntheticEvent, itemId: string) => void;
|
|
15
|
+
focusItem: (event: React.SyntheticEvent | null, itemId: string) => void;
|
|
16
16
|
}
|
|
17
17
|
export interface UseTreeViewFocusInstance extends UseTreeViewFocusPublicAPI {
|
|
18
18
|
/**
|
|
@@ -2,100 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
4
4
|
import * as React from 'react';
|
|
5
|
-
import useEventCallback from '@
|
|
6
|
-
import {
|
|
5
|
+
import { useEventCallback } from '@base-ui-components/utils/useEventCallback';
|
|
6
|
+
import { buildItemsLookups, buildItemsState, TREE_VIEW_ROOT_PARENT_ID } from "./useTreeViewItems.utils.js";
|
|
7
7
|
import { TreeViewItemDepthContext } from "../../TreeViewItemDepthContext/index.js";
|
|
8
8
|
import { itemsSelectors } from "./useTreeViewItems.selectors.js";
|
|
9
9
|
import { idSelectors } from "../../corePlugins/useTreeViewId/index.js";
|
|
10
10
|
import { generateTreeItemIdAttribute } from "../../corePlugins/useTreeViewId/useTreeViewId.utils.js";
|
|
11
11
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
-
const checkId = (id, item, itemMetaLookup) => {
|
|
13
|
-
if (id == null) {
|
|
14
|
-
throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', 'An item was provided without id in the `items` prop:', JSON.stringify(item)].join('\n'));
|
|
15
|
-
}
|
|
16
|
-
if (itemMetaLookup[id] != null) {
|
|
17
|
-
throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', `Two items were provided with the same id in the \`items\` prop: "${id}"`].join('\n'));
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
const processItemsLookups = ({
|
|
21
|
-
disabledItemsFocusable,
|
|
22
|
-
items,
|
|
23
|
-
isItemDisabled,
|
|
24
|
-
getItemLabel,
|
|
25
|
-
getItemChildren,
|
|
26
|
-
getItemId,
|
|
27
|
-
initialDepth = 0,
|
|
28
|
-
initialParentId = null,
|
|
29
|
-
getChildrenCount,
|
|
30
|
-
ignoreChildren = false
|
|
31
|
-
}) => {
|
|
32
|
-
const itemMetaLookup = {};
|
|
33
|
-
const itemModelLookup = {};
|
|
34
|
-
const itemOrderedChildrenIdsLookup = {
|
|
35
|
-
[TREE_VIEW_ROOT_PARENT_ID]: []
|
|
36
|
-
};
|
|
37
|
-
const processItem = (item, depth, parentId) => {
|
|
38
|
-
const id = getItemId ? getItemId(item) : item.id;
|
|
39
|
-
checkId(id, item, itemMetaLookup);
|
|
40
|
-
const label = getItemLabel ? getItemLabel(item) : item.label;
|
|
41
|
-
if (label == null) {
|
|
42
|
-
throw new Error(['MUI X: 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'));
|
|
43
|
-
}
|
|
44
|
-
const children = getItemChildren ? getItemChildren(item) : item.children;
|
|
45
|
-
itemMetaLookup[id] = {
|
|
46
|
-
id,
|
|
47
|
-
label,
|
|
48
|
-
parentId,
|
|
49
|
-
idAttribute: undefined,
|
|
50
|
-
expandable: getChildrenCount ? getChildrenCount(item) > 0 : !!children?.length,
|
|
51
|
-
disabled: isItemDisabled ? isItemDisabled(item) : false,
|
|
52
|
-
depth
|
|
53
|
-
};
|
|
54
|
-
itemModelLookup[id] = item;
|
|
55
|
-
const parentIdWithDefault = parentId ?? TREE_VIEW_ROOT_PARENT_ID;
|
|
56
|
-
if (!itemOrderedChildrenIdsLookup[parentIdWithDefault]) {
|
|
57
|
-
itemOrderedChildrenIdsLookup[parentIdWithDefault] = [];
|
|
58
|
-
}
|
|
59
|
-
itemOrderedChildrenIdsLookup[parentIdWithDefault].push(id);
|
|
60
|
-
|
|
61
|
-
// if lazy loading is enabled, we don't want to process children passed through the `items` prop
|
|
62
|
-
if (!ignoreChildren) {
|
|
63
|
-
children?.forEach(child => processItem(child, depth + 1, id));
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
items?.forEach(item => processItem(item, initialDepth, initialParentId));
|
|
67
|
-
const itemChildrenIndexesLookup = {};
|
|
68
|
-
Object.keys(itemOrderedChildrenIdsLookup).forEach(parentId => {
|
|
69
|
-
itemChildrenIndexesLookup[parentId] = buildSiblingIndexes(itemOrderedChildrenIdsLookup[parentId]);
|
|
70
|
-
});
|
|
71
|
-
return {
|
|
72
|
-
disabledItemsFocusable,
|
|
73
|
-
itemMetaLookup,
|
|
74
|
-
itemModelLookup,
|
|
75
|
-
itemOrderedChildrenIdsLookup,
|
|
76
|
-
itemChildrenIndexesLookup
|
|
77
|
-
};
|
|
78
|
-
};
|
|
79
12
|
export const useTreeViewItems = ({
|
|
80
13
|
instance,
|
|
81
14
|
params,
|
|
82
15
|
store
|
|
83
16
|
}) => {
|
|
17
|
+
const itemsConfig = React.useMemo(() => ({
|
|
18
|
+
isItemDisabled: params.isItemDisabled,
|
|
19
|
+
getItemLabel: params.getItemLabel,
|
|
20
|
+
getItemChildren: params.getItemChildren,
|
|
21
|
+
getItemId: params.getItemId
|
|
22
|
+
}), [params.isItemDisabled, params.getItemLabel, params.getItemChildren, params.getItemId]);
|
|
84
23
|
const getItem = React.useCallback(itemId => itemsSelectors.itemModel(store.state, itemId), [store]);
|
|
85
24
|
const getParentId = React.useCallback(itemId => {
|
|
86
25
|
const itemMeta = itemsSelectors.itemMeta(store.state, itemId);
|
|
87
26
|
return itemMeta?.parentId || null;
|
|
88
27
|
}, [store]);
|
|
89
|
-
const setTreeViewLoading = useEventCallback(isLoading => {
|
|
90
|
-
store.set('items', _extends({}, store.state.items, {
|
|
91
|
-
loading: isLoading
|
|
92
|
-
}));
|
|
93
|
-
});
|
|
94
|
-
const setTreeViewError = useEventCallback(error => {
|
|
95
|
-
store.set('items', _extends({}, store.state.items, {
|
|
96
|
-
error
|
|
97
|
-
}));
|
|
98
|
-
});
|
|
99
28
|
const setIsItemDisabled = useEventCallback(({
|
|
100
29
|
itemId,
|
|
101
30
|
shouldBeDisabled
|
|
@@ -143,86 +72,81 @@ export const useTreeViewItems = ({
|
|
|
143
72
|
areItemUpdatesPreventedRef.current = true;
|
|
144
73
|
}, []);
|
|
145
74
|
const areItemUpdatesPrevented = React.useCallback(() => areItemUpdatesPreventedRef.current, []);
|
|
146
|
-
const
|
|
75
|
+
const setItemChildren = ({
|
|
147
76
|
items,
|
|
148
77
|
parentId,
|
|
149
|
-
depth,
|
|
150
78
|
getChildrenCount
|
|
151
79
|
}) => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
itemChildrenIndexesLookup: newState.itemChildrenIndexesLookup
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
store.set('items', _extends({}, store.state.items, newItems));
|
|
182
|
-
}
|
|
80
|
+
const parentIdWithDefault = parentId ?? TREE_VIEW_ROOT_PARENT_ID;
|
|
81
|
+
const parentDepth = parentId == null ? -1 : itemsSelectors.itemDepth(store.state, parentId);
|
|
82
|
+
const {
|
|
83
|
+
metaLookup,
|
|
84
|
+
modelLookup,
|
|
85
|
+
orderedChildrenIds,
|
|
86
|
+
childrenIndexes
|
|
87
|
+
} = buildItemsLookups({
|
|
88
|
+
config: itemsConfig,
|
|
89
|
+
items,
|
|
90
|
+
parentId,
|
|
91
|
+
depth: parentDepth + 1,
|
|
92
|
+
isItemExpandable: getChildrenCount ? item => getChildrenCount(item) > 0 : () => false,
|
|
93
|
+
otherItemsMetaLookup: itemsSelectors.itemMetaLookup(store.state)
|
|
94
|
+
});
|
|
95
|
+
const lookups = {
|
|
96
|
+
itemModelLookup: _extends({}, store.state.items.itemModelLookup, modelLookup),
|
|
97
|
+
itemMetaLookup: _extends({}, store.state.items.itemMetaLookup, metaLookup),
|
|
98
|
+
itemOrderedChildrenIdsLookup: _extends({}, store.state.items.itemOrderedChildrenIdsLookup, {
|
|
99
|
+
[parentIdWithDefault]: orderedChildrenIds
|
|
100
|
+
}),
|
|
101
|
+
itemChildrenIndexesLookup: _extends({}, store.state.items.itemChildrenIndexesLookup, {
|
|
102
|
+
[parentIdWithDefault]: childrenIndexes
|
|
103
|
+
})
|
|
104
|
+
};
|
|
105
|
+
store.set('items', _extends({}, store.state.items, lookups));
|
|
183
106
|
};
|
|
184
|
-
const removeChildren = parentId => {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
107
|
+
const removeChildren = useEventCallback(parentId => {
|
|
108
|
+
const newMetaMap = Object.keys(store.state.items.itemMetaLookup).reduce((acc, key) => {
|
|
109
|
+
const item = store.state.items.itemMetaLookup[key];
|
|
110
|
+
if (item.parentId === parentId) {
|
|
111
|
+
return acc;
|
|
112
|
+
}
|
|
113
|
+
return _extends({}, acc, {
|
|
114
|
+
[item.id]: item
|
|
115
|
+
});
|
|
116
|
+
}, {});
|
|
117
|
+
const newItemOrderedChildrenIdsLookup = _extends({}, store.state.items.itemOrderedChildrenIdsLookup);
|
|
118
|
+
const newItemChildrenIndexesLookup = _extends({}, store.state.items.itemChildrenIndexesLookup);
|
|
119
|
+
const cleanId = parentId ?? TREE_VIEW_ROOT_PARENT_ID;
|
|
120
|
+
delete newItemChildrenIndexesLookup[cleanId];
|
|
121
|
+
delete newItemOrderedChildrenIdsLookup[cleanId];
|
|
122
|
+
store.set('items', _extends({}, store.state.items, {
|
|
123
|
+
itemMetaLookup: newMetaMap,
|
|
124
|
+
itemOrderedChildrenIdsLookup: newItemOrderedChildrenIdsLookup,
|
|
125
|
+
itemChildrenIndexesLookup: newItemChildrenIndexesLookup
|
|
126
|
+
}));
|
|
127
|
+
});
|
|
128
|
+
const addExpandableItems = useEventCallback(items => {
|
|
129
|
+
const newItemMetaLookup = _extends({}, store.state.items.itemMetaLookup);
|
|
130
|
+
for (const itemId of items) {
|
|
131
|
+
newItemMetaLookup[itemId] = _extends({}, newItemMetaLookup[itemId], {
|
|
132
|
+
expandable: true
|
|
133
|
+
});
|
|
210
134
|
}
|
|
211
|
-
|
|
135
|
+
store.set('items', _extends({}, store.state.items, {
|
|
136
|
+
itemMetaLookup: newItemMetaLookup
|
|
137
|
+
}));
|
|
138
|
+
});
|
|
212
139
|
React.useEffect(() => {
|
|
213
140
|
if (instance.areItemUpdatesPrevented()) {
|
|
214
141
|
return;
|
|
215
142
|
}
|
|
216
|
-
const newState =
|
|
143
|
+
const newState = buildItemsState({
|
|
217
144
|
disabledItemsFocusable: params.disabledItemsFocusable,
|
|
218
145
|
items: params.items,
|
|
219
|
-
|
|
220
|
-
getItemId: params.getItemId,
|
|
221
|
-
getItemLabel: params.getItemLabel,
|
|
222
|
-
getItemChildren: params.getItemChildren
|
|
146
|
+
config: itemsConfig
|
|
223
147
|
});
|
|
224
148
|
store.set('items', _extends({}, store.state.items, newState));
|
|
225
|
-
}, [instance, store, params.items, params.disabledItemsFocusable,
|
|
149
|
+
}, [instance, store, params.items, params.disabledItemsFocusable, itemsConfig]);
|
|
226
150
|
|
|
227
151
|
// Wrap `props.onItemClick` with `useEventCallback` to prevent unneeded context updates.
|
|
228
152
|
const handleItemClick = useEventCallback((event, itemId) => {
|
|
@@ -248,26 +172,23 @@ export const useTreeViewItems = ({
|
|
|
248
172
|
getItemDOMElement,
|
|
249
173
|
preventItemUpdates,
|
|
250
174
|
areItemUpdatesPrevented,
|
|
251
|
-
|
|
252
|
-
setTreeViewLoading,
|
|
253
|
-
setTreeViewError,
|
|
175
|
+
setItemChildren,
|
|
254
176
|
removeChildren,
|
|
177
|
+
addExpandableItems,
|
|
255
178
|
handleItemClick
|
|
256
179
|
}
|
|
257
180
|
};
|
|
258
181
|
};
|
|
259
182
|
useTreeViewItems.getInitialState = params => ({
|
|
260
|
-
items:
|
|
261
|
-
disabledItemsFocusable: params.disabledItemsFocusable,
|
|
183
|
+
items: buildItemsState({
|
|
262
184
|
items: params.items,
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
domStructure: 'nested'
|
|
185
|
+
disabledItemsFocusable: params.disabledItemsFocusable,
|
|
186
|
+
config: {
|
|
187
|
+
isItemDisabled: params.isItemDisabled,
|
|
188
|
+
getItemId: params.getItemId,
|
|
189
|
+
getItemLabel: params.getItemLabel,
|
|
190
|
+
getItemChildren: params.getItemChildren
|
|
191
|
+
}
|
|
271
192
|
})
|
|
272
193
|
});
|
|
273
194
|
useTreeViewItems.applyDefaultValuesToParams = ({
|
|
@@ -1,14 +1,6 @@
|
|
|
1
1
|
import { TreeViewItemMeta, TreeViewState } from "../../models/index.js";
|
|
2
2
|
import { UseTreeViewItemsSignature } from "./useTreeViewItems.types.js";
|
|
3
3
|
export declare const itemsSelectors: {
|
|
4
|
-
/**
|
|
5
|
-
* Gets the loading state for the Tree View.
|
|
6
|
-
*/
|
|
7
|
-
isLoading: (state: TreeViewState<[UseTreeViewItemsSignature]>) => boolean;
|
|
8
|
-
/**
|
|
9
|
-
* Gets the error state for the Tree View.
|
|
10
|
-
*/
|
|
11
|
-
error: (state: TreeViewState<[UseTreeViewItemsSignature]>) => Error | null;
|
|
12
4
|
/**
|
|
13
5
|
* Gets the DOM structure of the Tree View.
|
|
14
6
|
*/
|
|
@@ -2,14 +2,6 @@ import { createSelector } from '@mui/x-internals/store';
|
|
|
2
2
|
import { isItemDisabled, TREE_VIEW_ROOT_PARENT_ID } from "./useTreeViewItems.utils.js";
|
|
3
3
|
const EMPTY_CHILDREN = [];
|
|
4
4
|
export const itemsSelectors = {
|
|
5
|
-
/**
|
|
6
|
-
* Gets the loading state for the Tree View.
|
|
7
|
-
*/
|
|
8
|
-
isLoading: createSelector(state => state.items.loading),
|
|
9
|
-
/**
|
|
10
|
-
* Gets the error state for the Tree View.
|
|
11
|
-
*/
|
|
12
|
-
error: createSelector(state => state.items.error),
|
|
13
5
|
/**
|
|
14
6
|
* Gets the DOM structure of the Tree View.
|
|
15
7
|
*/
|
|
@@ -2,11 +2,10 @@ import * as React from 'react';
|
|
|
2
2
|
import { DefaultizedProps } from '@mui/x-internals/types';
|
|
3
3
|
import { TreeViewItemMeta, TreeViewPluginSignature } from "../../models/index.js";
|
|
4
4
|
import { TreeViewBaseItem, TreeViewDefaultItemModelProperties, TreeViewItemId } from "../../../models/index.js";
|
|
5
|
-
export type
|
|
5
|
+
export type SetItemChildrenParameters<R> = {
|
|
6
6
|
items: readonly R[];
|
|
7
|
-
parentId
|
|
8
|
-
|
|
9
|
-
getChildrenCount?: (item: R) => number;
|
|
7
|
+
parentId: TreeViewItemId | null;
|
|
8
|
+
getChildrenCount: (item: R) => number;
|
|
10
9
|
};
|
|
11
10
|
export interface UseTreeViewItemsPublicAPI<R extends {}> {
|
|
12
11
|
/**
|
|
@@ -65,30 +64,25 @@ export interface UseTreeViewItemsInstance<R extends {}> extends Pick<UseTreeView
|
|
|
65
64
|
areItemUpdatesPrevented: () => boolean;
|
|
66
65
|
/**
|
|
67
66
|
* Add an array of items to the tree.
|
|
68
|
-
* @param {
|
|
67
|
+
* @param {SetItemChildrenParameters<R>} args The items to add to the tree and information about their ancestors.
|
|
69
68
|
*/
|
|
70
|
-
|
|
69
|
+
setItemChildren: (args: SetItemChildrenParameters<R>) => void;
|
|
71
70
|
/**
|
|
72
71
|
* Remove the children of an item.
|
|
73
|
-
* @param {TreeViewItemId} parentId The id of the item to remove the children of.
|
|
72
|
+
* @param {TreeViewItemId | null} parentId The id of the item to remove the children of.
|
|
74
73
|
*/
|
|
75
|
-
removeChildren: (parentId
|
|
76
|
-
/**
|
|
77
|
-
* Set the loading state of the tree.
|
|
78
|
-
* @param {boolean} loading True if the tree view is loading.
|
|
79
|
-
*/
|
|
80
|
-
setTreeViewLoading: (loading: boolean) => void;
|
|
81
|
-
/**
|
|
82
|
-
* Set the error state of the tree.
|
|
83
|
-
* @param {Error | null} error The error on the tree view.
|
|
84
|
-
*/
|
|
85
|
-
setTreeViewError: (error: Error | null) => void;
|
|
74
|
+
removeChildren: (parentId: TreeViewItemId | null) => void;
|
|
86
75
|
/**
|
|
87
76
|
* Event handler to fire when the `content` slot of a given Tree Item is clicked.
|
|
88
77
|
* @param {React.MouseEvent} event The DOM event that triggered the change.
|
|
89
78
|
* @param {TreeViewItemId} itemId The id of the item being clicked.
|
|
90
79
|
*/
|
|
91
80
|
handleItemClick: (event: React.MouseEvent, itemId: TreeViewItemId) => void;
|
|
81
|
+
/**
|
|
82
|
+
* Mark a list of items as expandable.
|
|
83
|
+
* @param {TreeViewItemId[]} items The ids of the items to mark as expandable.
|
|
84
|
+
*/
|
|
85
|
+
addExpandableItems: (items: TreeViewItemId[]) => void;
|
|
92
86
|
}
|
|
93
87
|
export interface UseTreeViewItemsParameters<R extends {
|
|
94
88
|
children?: R[];
|
|
@@ -186,14 +180,6 @@ export interface UseTreeViewItemsState<R extends {}> {
|
|
|
186
180
|
[itemId: string]: number;
|
|
187
181
|
};
|
|
188
182
|
};
|
|
189
|
-
/**
|
|
190
|
-
* The loading state of the tree.
|
|
191
|
-
*/
|
|
192
|
-
loading: boolean;
|
|
193
|
-
/**
|
|
194
|
-
* The error state of the tree.
|
|
195
|
-
*/
|
|
196
|
-
error: Error | null;
|
|
197
183
|
/**
|
|
198
184
|
* When equal to 'flat', the tree is rendered as a flat list (children are rendered as siblings of their parents).
|
|
199
185
|
* When equal to 'nested', the tree is rendered with nested children (children are rendered inside the groupTransition slot of their children).
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { TreeViewItemId } from "../../../models/index.js";
|
|
1
|
+
import { TreeViewBaseItem, TreeViewItemId } from "../../../models/index.js";
|
|
2
2
|
import { TreeViewItemMeta } from "../../models/index.js";
|
|
3
|
+
import { UseTreeViewItemsParametersWithDefaults, UseTreeViewItemsState } from "./useTreeViewItems.types.js";
|
|
3
4
|
export declare const TREE_VIEW_ROOT_PARENT_ID = "__TREE_VIEW_ROOT_PARENT_ID__";
|
|
4
5
|
export declare const buildSiblingIndexes: (siblings: string[]) => {
|
|
5
6
|
[itemId: string]: number;
|
|
@@ -12,4 +13,37 @@ export declare const buildSiblingIndexes: (siblings: string[]) => {
|
|
|
12
13
|
*/
|
|
13
14
|
export declare const isItemDisabled: (itemMetaLookup: {
|
|
14
15
|
[itemId: string]: TreeViewItemMeta;
|
|
15
|
-
}, itemId: TreeViewItemId) => boolean;
|
|
16
|
+
}, itemId: TreeViewItemId) => boolean;
|
|
17
|
+
type State = UseTreeViewItemsState<any>['items'];
|
|
18
|
+
export declare function buildItemsState(parameters: BuildItemsStateParameters): State;
|
|
19
|
+
interface BuildItemsStateParameters extends Pick<BuildItemsLookupsParameters, 'items' | 'config'> {
|
|
20
|
+
disabledItemsFocusable: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare function buildItemsLookups(parameters: BuildItemsLookupsParameters): {
|
|
23
|
+
metaLookup: {
|
|
24
|
+
[itemId: string]: TreeViewItemMeta;
|
|
25
|
+
};
|
|
26
|
+
modelLookup: {
|
|
27
|
+
[itemId: string]: any;
|
|
28
|
+
};
|
|
29
|
+
orderedChildrenIds: string[];
|
|
30
|
+
childrenIndexes: {
|
|
31
|
+
[itemId: string]: number;
|
|
32
|
+
};
|
|
33
|
+
itemsChildren: {
|
|
34
|
+
id: string | null;
|
|
35
|
+
children: TreeViewBaseItem[];
|
|
36
|
+
}[];
|
|
37
|
+
};
|
|
38
|
+
interface BuildItemsLookupsParameters {
|
|
39
|
+
items: readonly TreeViewBaseItem[];
|
|
40
|
+
config: BuildItemsLookupConfig;
|
|
41
|
+
parentId: string | null;
|
|
42
|
+
depth: number;
|
|
43
|
+
isItemExpandable: (item: TreeViewBaseItem, children: TreeViewBaseItem[] | undefined) => boolean;
|
|
44
|
+
otherItemsMetaLookup: {
|
|
45
|
+
[itemId: string]: TreeViewItemMeta;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export interface BuildItemsLookupConfig extends Pick<UseTreeViewItemsParametersWithDefaults<TreeViewBaseItem>, 'isItemDisabled' | 'getItemLabel' | 'getItemChildren' | 'getItemId'> {}
|
|
49
|
+
export {};
|
|
@@ -36,4 +36,118 @@ export const isItemDisabled = (itemMetaLookup, itemId) => {
|
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
return false;
|
|
39
|
-
};
|
|
39
|
+
};
|
|
40
|
+
export function buildItemsState(parameters) {
|
|
41
|
+
const {
|
|
42
|
+
config,
|
|
43
|
+
items: itemsParam,
|
|
44
|
+
disabledItemsFocusable
|
|
45
|
+
} = parameters;
|
|
46
|
+
const itemMetaLookup = {};
|
|
47
|
+
const itemModelLookup = {};
|
|
48
|
+
const itemOrderedChildrenIdsLookup = {};
|
|
49
|
+
const itemChildrenIndexesLookup = {};
|
|
50
|
+
function processSiblings(items, parentId, depth) {
|
|
51
|
+
const parentIdWithDefault = parentId ?? TREE_VIEW_ROOT_PARENT_ID;
|
|
52
|
+
const {
|
|
53
|
+
metaLookup,
|
|
54
|
+
modelLookup,
|
|
55
|
+
orderedChildrenIds,
|
|
56
|
+
childrenIndexes,
|
|
57
|
+
itemsChildren
|
|
58
|
+
} = buildItemsLookups({
|
|
59
|
+
config,
|
|
60
|
+
items,
|
|
61
|
+
parentId,
|
|
62
|
+
depth,
|
|
63
|
+
isItemExpandable: (item, children) => !!children && children.length > 0,
|
|
64
|
+
otherItemsMetaLookup: itemMetaLookup
|
|
65
|
+
});
|
|
66
|
+
Object.assign(itemMetaLookup, metaLookup);
|
|
67
|
+
Object.assign(itemModelLookup, modelLookup);
|
|
68
|
+
itemOrderedChildrenIdsLookup[parentIdWithDefault] = orderedChildrenIds;
|
|
69
|
+
itemChildrenIndexesLookup[parentIdWithDefault] = childrenIndexes;
|
|
70
|
+
for (const item of itemsChildren) {
|
|
71
|
+
processSiblings(item.children || [], item.id, depth + 1);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
processSiblings(itemsParam, null, 0);
|
|
75
|
+
return {
|
|
76
|
+
disabledItemsFocusable,
|
|
77
|
+
itemMetaLookup,
|
|
78
|
+
itemModelLookup,
|
|
79
|
+
itemOrderedChildrenIdsLookup,
|
|
80
|
+
itemChildrenIndexesLookup,
|
|
81
|
+
domStructure: 'nested'
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
export function buildItemsLookups(parameters) {
|
|
85
|
+
const {
|
|
86
|
+
config,
|
|
87
|
+
items,
|
|
88
|
+
parentId,
|
|
89
|
+
depth,
|
|
90
|
+
isItemExpandable,
|
|
91
|
+
otherItemsMetaLookup
|
|
92
|
+
} = parameters;
|
|
93
|
+
const metaLookup = {};
|
|
94
|
+
const modelLookup = {};
|
|
95
|
+
const orderedChildrenIds = [];
|
|
96
|
+
const itemsChildren = [];
|
|
97
|
+
const processItem = item => {
|
|
98
|
+
const id = config.getItemId ? config.getItemId(item) : item.id;
|
|
99
|
+
checkId({
|
|
100
|
+
id,
|
|
101
|
+
parentId,
|
|
102
|
+
item,
|
|
103
|
+
itemMetaLookup: otherItemsMetaLookup,
|
|
104
|
+
siblingsMetaLookup: metaLookup
|
|
105
|
+
});
|
|
106
|
+
const label = config.getItemLabel ? config.getItemLabel(item) : item.label;
|
|
107
|
+
if (label == null) {
|
|
108
|
+
throw new Error(['MUI X: 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'));
|
|
109
|
+
}
|
|
110
|
+
const children = (config.getItemChildren ? config.getItemChildren(item) : item.children) || [];
|
|
111
|
+
itemsChildren.push({
|
|
112
|
+
id,
|
|
113
|
+
children
|
|
114
|
+
});
|
|
115
|
+
modelLookup[id] = item;
|
|
116
|
+
metaLookup[id] = {
|
|
117
|
+
id,
|
|
118
|
+
label,
|
|
119
|
+
parentId,
|
|
120
|
+
idAttribute: undefined,
|
|
121
|
+
expandable: isItemExpandable(item, children),
|
|
122
|
+
disabled: config.isItemDisabled ? config.isItemDisabled(item) : false,
|
|
123
|
+
depth
|
|
124
|
+
};
|
|
125
|
+
orderedChildrenIds.push(id);
|
|
126
|
+
};
|
|
127
|
+
for (const item of items) {
|
|
128
|
+
processItem(item);
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
metaLookup,
|
|
132
|
+
modelLookup,
|
|
133
|
+
orderedChildrenIds,
|
|
134
|
+
childrenIndexes: buildSiblingIndexes(orderedChildrenIds),
|
|
135
|
+
itemsChildren
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function checkId({
|
|
139
|
+
id,
|
|
140
|
+
parentId,
|
|
141
|
+
item,
|
|
142
|
+
itemMetaLookup,
|
|
143
|
+
siblingsMetaLookup
|
|
144
|
+
}) {
|
|
145
|
+
if (id == null) {
|
|
146
|
+
throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', 'An item was provided without id in the `items` prop:', JSON.stringify(item)].join('\n'));
|
|
147
|
+
}
|
|
148
|
+
if (siblingsMetaLookup[id] != null ||
|
|
149
|
+
// Ignore items with the same parent id, because it's the same item from the previous generation.
|
|
150
|
+
itemMetaLookup[id] != null && itemMetaLookup[id].parentId !== parentId) {
|
|
151
|
+
throw new Error(['MUI X: The Tree View component requires all items to have a unique `id` property.', 'Alternatively, you can use the `getItemId` prop to specify a custom id for each item.', `Two items were provided with the same id in the \`items\` prop: "${id}"`].join('\n'));
|
|
152
|
+
}
|
|
153
|
+
}
|