@mui/x-tree-view 8.0.0-alpha.12 → 8.0.0-alpha.14
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 +430 -0
- package/RichTreeView/RichTreeView.js +24 -5
- package/SimpleTreeView/SimpleTreeView.js +8 -6
- package/TreeItem/TreeItem.d.ts +2 -0
- package/TreeItem/TreeItem.js +46 -5
- package/TreeItem/TreeItem.types.d.ts +14 -0
- package/TreeItemIcon/TreeItemIcon.js +2 -0
- package/esm/RichTreeView/RichTreeView.js +24 -5
- package/esm/SimpleTreeView/SimpleTreeView.js +8 -6
- package/esm/TreeItem/TreeItem.d.ts +2 -0
- package/esm/TreeItem/TreeItem.js +45 -4
- package/esm/TreeItem/TreeItem.types.d.ts +14 -0
- package/esm/TreeItemIcon/TreeItemIcon.js +2 -0
- package/esm/hooks/useTreeItemUtils/useTreeItemUtils.d.ts +3 -2
- package/esm/hooks/useTreeItemUtils/useTreeItemUtils.js +21 -9
- package/esm/hooks/useTreeViewApiRef.d.ts +1 -1
- package/esm/index.js +1 -1
- package/esm/internals/hooks/useSelector.js +4 -1
- package/esm/internals/index.d.ts +6 -1
- package/esm/internals/index.js +4 -1
- package/esm/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +35 -12
- package/esm/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.selectors.d.ts +4 -0
- package/esm/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +40 -16
- package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.js +157 -16
- package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.d.ts +172 -0
- package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js +13 -0
- package/esm/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +49 -0
- package/esm/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +2 -2
- package/esm/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +16 -7
- package/esm/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +2 -1
- package/esm/internals/plugins/useTreeViewLazyLoading/index.d.ts +1 -0
- package/esm/internals/plugins/useTreeViewLazyLoading/index.js +1 -0
- package/esm/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.selectors.d.ts +249 -0
- package/esm/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.selectors.js +27 -0
- package/esm/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.types.d.ts +83 -0
- package/esm/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.types.js +1 -0
- package/esm/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +4 -4
- package/esm/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +12 -12
- package/esm/internals/utils/selectors.d.ts +7 -0
- package/esm/internals/utils/selectors.js +9 -0
- package/esm/useTreeItem/useTreeItem.d.ts +1 -1
- package/esm/useTreeItem/useTreeItem.js +13 -0
- package/esm/useTreeItem/useTreeItem.types.d.ts +21 -0
- package/esm/utils/cache.d.ts +38 -0
- package/esm/utils/cache.js +31 -0
- package/esm/utils/index.d.ts +1 -0
- package/esm/utils/index.js +1 -0
- package/hooks/useTreeItemUtils/useTreeItemUtils.d.ts +3 -2
- package/hooks/useTreeItemUtils/useTreeItemUtils.js +22 -10
- package/hooks/useTreeViewApiRef.d.ts +1 -1
- package/index.js +1 -1
- package/internals/hooks/useSelector.js +5 -1
- package/internals/index.d.ts +6 -1
- package/internals/index.js +33 -0
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +35 -12
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.selectors.d.ts +4 -0
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +40 -16
- package/internals/plugins/useTreeViewItems/useTreeViewItems.js +157 -16
- package/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.d.ts +172 -0
- package/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js +14 -1
- package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +49 -0
- package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +1 -1
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +16 -7
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +2 -1
- package/internals/plugins/useTreeViewLazyLoading/index.d.ts +1 -0
- package/internals/plugins/useTreeViewLazyLoading/index.js +5 -0
- package/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.selectors.d.ts +249 -0
- package/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.selectors.js +33 -0
- package/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.types.d.ts +83 -0
- package/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.types.js +5 -0
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +4 -4
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +12 -12
- package/internals/utils/selectors.d.ts +7 -0
- package/internals/utils/selectors.js +9 -0
- package/modern/RichTreeView/RichTreeView.js +24 -5
- package/modern/SimpleTreeView/SimpleTreeView.js +8 -6
- package/modern/TreeItem/TreeItem.d.ts +2 -0
- package/modern/TreeItem/TreeItem.js +45 -4
- package/modern/TreeItem/TreeItem.types.d.ts +14 -0
- package/modern/TreeItemIcon/TreeItemIcon.js +2 -0
- package/modern/hooks/useTreeItemUtils/useTreeItemUtils.d.ts +3 -2
- package/modern/hooks/useTreeItemUtils/useTreeItemUtils.js +21 -9
- package/modern/hooks/useTreeViewApiRef.d.ts +1 -1
- package/modern/index.js +1 -1
- package/modern/internals/hooks/useSelector.js +4 -1
- package/modern/internals/index.d.ts +6 -1
- package/modern/internals/index.js +4 -1
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +35 -12
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.selectors.d.ts +4 -0
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +40 -16
- package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.js +157 -16
- package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.d.ts +172 -0
- package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js +13 -0
- package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +49 -0
- package/modern/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +2 -2
- package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +16 -7
- package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.types.d.ts +2 -1
- package/modern/internals/plugins/useTreeViewLazyLoading/index.d.ts +1 -0
- package/modern/internals/plugins/useTreeViewLazyLoading/index.js +1 -0
- package/modern/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.selectors.d.ts +249 -0
- package/modern/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.selectors.js +27 -0
- package/modern/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.types.d.ts +83 -0
- package/modern/internals/plugins/useTreeViewLazyLoading/useTreeViewLazyLoading.types.js +1 -0
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +4 -4
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +12 -12
- package/modern/internals/utils/selectors.d.ts +7 -0
- package/modern/internals/utils/selectors.js +9 -0
- package/modern/useTreeItem/useTreeItem.d.ts +1 -1
- package/modern/useTreeItem/useTreeItem.js +13 -0
- package/modern/useTreeItem/useTreeItem.types.d.ts +21 -0
- package/modern/utils/cache.d.ts +38 -0
- package/modern/utils/cache.js +31 -0
- package/modern/utils/index.d.ts +1 -0
- package/modern/utils/index.js +1 -0
- package/package.json +2 -2
- package/tsconfig.build.tsbuildinfo +1 -1
- package/useTreeItem/useTreeItem.d.ts +1 -1
- package/useTreeItem/useTreeItem.js +13 -0
- package/useTreeItem/useTreeItem.types.d.ts +21 -0
- package/utils/cache.d.ts +38 -0
- package/utils/cache.js +38 -0
- package/utils/index.d.ts +1 -0
- package/utils/index.js +16 -0
|
@@ -4,6 +4,7 @@ import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
|
|
|
4
4
|
import { selectorIsItemExpandable, selectorIsItemExpanded } from "./useTreeViewExpansion.selectors.js";
|
|
5
5
|
import { createExpandedItemsMap, getExpansionTrigger } from "./useTreeViewExpansion.utils.js";
|
|
6
6
|
import { selectorItemMeta, selectorItemOrderedChildrenIds } from "../useTreeViewItems/useTreeViewItems.selectors.js";
|
|
7
|
+
import { publishTreeViewEvent } from "../../utils/publishTreeViewEvent.js";
|
|
7
8
|
export const useTreeViewExpansion = ({
|
|
8
9
|
instance,
|
|
9
10
|
store,
|
|
@@ -37,26 +38,48 @@ export const useTreeViewExpansion = ({
|
|
|
37
38
|
params.onExpandedItemsChange?.(event, value);
|
|
38
39
|
models.expandedItems.setControlledValue(value);
|
|
39
40
|
};
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
const isExpandedBefore = selectorIsItemExpanded(store.value, itemId);
|
|
46
|
-
if (isExpandedBefore === isExpanded) {
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
41
|
+
const applyItemExpansion = useEventCallback(({
|
|
42
|
+
itemId,
|
|
43
|
+
event,
|
|
44
|
+
shouldBeExpanded
|
|
45
|
+
}) => {
|
|
49
46
|
let newExpanded;
|
|
50
|
-
if (
|
|
47
|
+
if (shouldBeExpanded) {
|
|
51
48
|
newExpanded = [itemId].concat(models.expandedItems.value);
|
|
52
49
|
} else {
|
|
53
50
|
newExpanded = models.expandedItems.value.filter(id => id !== itemId);
|
|
54
51
|
}
|
|
55
52
|
if (params.onItemExpansionToggle) {
|
|
56
|
-
params.onItemExpansionToggle(event, itemId,
|
|
53
|
+
params.onItemExpansionToggle(event, itemId, shouldBeExpanded);
|
|
57
54
|
}
|
|
58
55
|
setExpandedItems(event, newExpanded);
|
|
59
56
|
});
|
|
57
|
+
const setItemExpansion = useEventCallback(({
|
|
58
|
+
itemId,
|
|
59
|
+
event = null,
|
|
60
|
+
shouldBeExpanded
|
|
61
|
+
}) => {
|
|
62
|
+
const isExpandedBefore = selectorIsItemExpanded(store.value, itemId);
|
|
63
|
+
const cleanShouldBeExpanded = shouldBeExpanded ?? !isExpandedBefore;
|
|
64
|
+
if (isExpandedBefore === cleanShouldBeExpanded) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const eventParameters = {
|
|
68
|
+
isExpansionPrevented: false,
|
|
69
|
+
shouldBeExpanded: cleanShouldBeExpanded,
|
|
70
|
+
event,
|
|
71
|
+
itemId
|
|
72
|
+
};
|
|
73
|
+
publishTreeViewEvent(instance, 'beforeItemToggleExpansion', eventParameters);
|
|
74
|
+
if (eventParameters.isExpansionPrevented) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
instance.applyItemExpansion({
|
|
78
|
+
itemId,
|
|
79
|
+
event,
|
|
80
|
+
shouldBeExpanded: cleanShouldBeExpanded
|
|
81
|
+
});
|
|
82
|
+
});
|
|
60
83
|
const expandAllSiblings = (event, itemId) => {
|
|
61
84
|
const itemMeta = selectorItemMeta(store.value, itemId);
|
|
62
85
|
if (itemMeta == null) {
|
|
@@ -80,7 +103,7 @@ export const useTreeViewExpansion = ({
|
|
|
80
103
|
},
|
|
81
104
|
instance: {
|
|
82
105
|
setItemExpansion,
|
|
83
|
-
|
|
106
|
+
applyItemExpansion,
|
|
84
107
|
expandAllSiblings
|
|
85
108
|
}
|
|
86
109
|
};
|
|
@@ -90,6 +90,8 @@ export declare const selectorIsItemExpandable: ((state: any, itemId: string | nu
|
|
|
90
90
|
[itemId: string]: number;
|
|
91
91
|
};
|
|
92
92
|
};
|
|
93
|
+
loading: boolean;
|
|
94
|
+
error: Error | null;
|
|
93
95
|
}) => {
|
|
94
96
|
[itemId: string]: import("../..").TreeViewItemMeta;
|
|
95
97
|
};
|
|
@@ -109,6 +111,8 @@ export declare const selectorIsItemExpandable: ((state: any, itemId: string | nu
|
|
|
109
111
|
[itemId: string]: number;
|
|
110
112
|
};
|
|
111
113
|
};
|
|
114
|
+
loading: boolean;
|
|
115
|
+
error: Error | null;
|
|
112
116
|
}) => {
|
|
113
117
|
[itemId: string]: import("../..").TreeViewItemMeta;
|
|
114
118
|
}) & {
|
|
@@ -7,26 +7,38 @@ import { UseTreeViewLabelSignature } from "../useTreeViewLabel/index.js";
|
|
|
7
7
|
export interface UseTreeViewExpansionPublicAPI {
|
|
8
8
|
/**
|
|
9
9
|
* Change the expansion status of a given item.
|
|
10
|
-
* @param {
|
|
11
|
-
* @param {string} itemId The id of the item to expand of collapse.
|
|
12
|
-
* @param {
|
|
10
|
+
* @param {object} parameters The parameters of the method.
|
|
11
|
+
* @param {string} parameters.itemId The id of the item to expand of collapse.
|
|
12
|
+
* @param {React.SyntheticEvent} parameters.event The DOM event that triggered the change.
|
|
13
|
+
* @param {boolean} parameters.shouldBeExpanded If `true` the item will be expanded. If `false` the item will be collapsed. If not defined, the item's expansion status will be the toggled.
|
|
13
14
|
*/
|
|
14
|
-
setItemExpansion: (
|
|
15
|
+
setItemExpansion: (parameters: {
|
|
16
|
+
itemId: string;
|
|
17
|
+
event?: React.SyntheticEvent;
|
|
18
|
+
shouldBeExpanded?: boolean;
|
|
19
|
+
}) => void;
|
|
15
20
|
}
|
|
16
21
|
export interface UseTreeViewExpansionInstance extends UseTreeViewExpansionPublicAPI {
|
|
17
|
-
/**
|
|
18
|
-
* Toggle the current expansion of an item.
|
|
19
|
-
* If it is expanded, it will be collapsed, and vice versa.
|
|
20
|
-
* @param {React.SyntheticEvent} event The DOM event that triggered the change.
|
|
21
|
-
* @param {TreeViewItemId} itemId The id of the item to toggle.
|
|
22
|
-
*/
|
|
23
|
-
toggleItemExpansion: (event: React.SyntheticEvent, itemId: TreeViewItemId) => void;
|
|
24
22
|
/**
|
|
25
23
|
* Expand all the siblings (i.e.: the items that have the same parent) of a given item.
|
|
26
24
|
* @param {React.SyntheticEvent} event The DOM event that triggered the change.
|
|
27
25
|
* @param {TreeViewItemId} itemId The id of the item whose siblings will be expanded.
|
|
28
26
|
*/
|
|
29
27
|
expandAllSiblings: (event: React.KeyboardEvent, itemId: TreeViewItemId) => void;
|
|
28
|
+
/**
|
|
29
|
+
* APply the new expansion status of a given item.
|
|
30
|
+
* Is used by the `setItemExpansion` method and by the `useTreeViewLazyLoading` plugin.
|
|
31
|
+
* Unlike `setItemExpansion`, this method does not trigger the lazy loading.
|
|
32
|
+
* @param {object} parameters The parameters of the method.
|
|
33
|
+
* @param {string} parameters.itemId The id of the item to expand of collapse.
|
|
34
|
+
* @param {React.SyntheticEvent | null} parameters.event The DOM event that triggered the change.
|
|
35
|
+
* @param {boolean} parameters.shouldBeExpanded If `true` the item will be expanded. If `false` the item will be collapsed.
|
|
36
|
+
*/
|
|
37
|
+
applyItemExpansion: (parameters: {
|
|
38
|
+
itemId: string;
|
|
39
|
+
event: React.SyntheticEvent | null;
|
|
40
|
+
shouldBeExpanded: boolean;
|
|
41
|
+
}) => void;
|
|
30
42
|
}
|
|
31
43
|
export interface UseTreeViewExpansionParameters {
|
|
32
44
|
/**
|
|
@@ -42,17 +54,17 @@ export interface UseTreeViewExpansionParameters {
|
|
|
42
54
|
defaultExpandedItems?: string[];
|
|
43
55
|
/**
|
|
44
56
|
* Callback fired when Tree Items are expanded/collapsed.
|
|
45
|
-
* @param {React.SyntheticEvent} event The DOM event that triggered the change.
|
|
57
|
+
* @param {React.SyntheticEvent} event The DOM event that triggered the change. Can be null when the change is caused by the `publicAPI.setItemExpansion()` method.
|
|
46
58
|
* @param {array} itemIds The ids of the expanded items.
|
|
47
59
|
*/
|
|
48
|
-
onExpandedItemsChange?: (event: React.SyntheticEvent, itemIds: string[]) => void;
|
|
60
|
+
onExpandedItemsChange?: (event: React.SyntheticEvent | null, itemIds: string[]) => void;
|
|
49
61
|
/**
|
|
50
62
|
* Callback fired when a Tree Item is expanded or collapsed.
|
|
51
|
-
* @param {React.SyntheticEvent} event The DOM event that triggered the change.
|
|
63
|
+
* @param {React.SyntheticEvent | null} event The DOM event that triggered the change. Can be null when the change is caused by the `publicAPI.setItemExpansion()` method.
|
|
52
64
|
* @param {array} itemId The itemId of the modified item.
|
|
53
65
|
* @param {array} isExpanded `true` if the item has just been expanded, `false` if it has just been collapsed.
|
|
54
66
|
*/
|
|
55
|
-
onItemExpansionToggle?: (event: React.SyntheticEvent, itemId: string, isExpanded: boolean) => void;
|
|
67
|
+
onItemExpansionToggle?: (event: React.SyntheticEvent | null, itemId: string, isExpanded: boolean) => void;
|
|
56
68
|
/**
|
|
57
69
|
* The slot that triggers the item's expansion when clicked.
|
|
58
70
|
* @default 'content'
|
|
@@ -66,6 +78,16 @@ export interface UseTreeViewExpansionState {
|
|
|
66
78
|
expansionTrigger: 'content' | 'iconContainer';
|
|
67
79
|
};
|
|
68
80
|
}
|
|
81
|
+
interface UseTreeViewExpansionEventLookup {
|
|
82
|
+
beforeItemToggleExpansion: {
|
|
83
|
+
params: {
|
|
84
|
+
isExpansionPrevented: boolean;
|
|
85
|
+
shouldBeExpanded: boolean;
|
|
86
|
+
event: React.SyntheticEvent | null;
|
|
87
|
+
itemId: TreeViewItemId;
|
|
88
|
+
};
|
|
89
|
+
};
|
|
90
|
+
}
|
|
69
91
|
export type UseTreeViewExpansionSignature = TreeViewPluginSignature<{
|
|
70
92
|
params: UseTreeViewExpansionParameters;
|
|
71
93
|
defaultizedParams: UseTreeViewExpansionDefaultizedParameters;
|
|
@@ -75,4 +97,6 @@ export type UseTreeViewExpansionSignature = TreeViewPluginSignature<{
|
|
|
75
97
|
state: UseTreeViewExpansionState;
|
|
76
98
|
dependencies: [UseTreeViewItemsSignature];
|
|
77
99
|
optionalDependencies: [UseTreeViewLabelSignature];
|
|
78
|
-
|
|
100
|
+
events: UseTreeViewExpansionEventLookup;
|
|
101
|
+
}>;
|
|
102
|
+
export {};
|
|
@@ -8,12 +8,24 @@ import { selectorItemMeta, selectorItemOrderedChildrenIds, selectorItemModel, se
|
|
|
8
8
|
import { selectorTreeViewId } from "../../corePlugins/useTreeViewId/useTreeViewId.selectors.js";
|
|
9
9
|
import { generateTreeItemIdAttribute } from "../../corePlugins/useTreeViewId/useTreeViewId.utils.js";
|
|
10
10
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
-
const
|
|
11
|
+
const checkId = (id, item, itemMetaLookup) => {
|
|
12
|
+
if (id == null) {
|
|
13
|
+
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'));
|
|
14
|
+
}
|
|
15
|
+
if (itemMetaLookup[id] != null) {
|
|
16
|
+
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'));
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const processItemsLookups = ({
|
|
12
20
|
disabledItemsFocusable,
|
|
13
21
|
items,
|
|
14
22
|
isItemDisabled,
|
|
15
23
|
getItemLabel,
|
|
16
|
-
getItemId
|
|
24
|
+
getItemId,
|
|
25
|
+
initialDepth = 0,
|
|
26
|
+
initialParentId = null,
|
|
27
|
+
getChildrenCount,
|
|
28
|
+
ignoreChildren = false
|
|
17
29
|
}) => {
|
|
18
30
|
const itemMetaLookup = {};
|
|
19
31
|
const itemModelLookup = {};
|
|
@@ -22,12 +34,7 @@ const updateItemsState = ({
|
|
|
22
34
|
};
|
|
23
35
|
const processItem = (item, depth, parentId) => {
|
|
24
36
|
const id = getItemId ? getItemId(item) : item.id;
|
|
25
|
-
|
|
26
|
-
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'));
|
|
27
|
-
}
|
|
28
|
-
if (itemMetaLookup[id] != null) {
|
|
29
|
-
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'));
|
|
30
|
-
}
|
|
37
|
+
checkId(id, item, itemMetaLookup);
|
|
31
38
|
const label = getItemLabel ? getItemLabel(item) : item.label;
|
|
32
39
|
if (label == null) {
|
|
33
40
|
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'));
|
|
@@ -37,7 +44,7 @@ const updateItemsState = ({
|
|
|
37
44
|
label,
|
|
38
45
|
parentId,
|
|
39
46
|
idAttribute: undefined,
|
|
40
|
-
expandable: !!item.children?.length,
|
|
47
|
+
expandable: getChildrenCount ? getChildrenCount(item) > 0 : !!item.children?.length,
|
|
41
48
|
disabled: isItemDisabled ? isItemDisabled(item) : false,
|
|
42
49
|
depth
|
|
43
50
|
};
|
|
@@ -47,9 +54,13 @@ const updateItemsState = ({
|
|
|
47
54
|
itemOrderedChildrenIdsLookup[parentIdWithDefault] = [];
|
|
48
55
|
}
|
|
49
56
|
itemOrderedChildrenIdsLookup[parentIdWithDefault].push(id);
|
|
50
|
-
|
|
57
|
+
|
|
58
|
+
// if lazy loading is enabled, we don't want to process children passed through the `items` prop
|
|
59
|
+
if (!ignoreChildren) {
|
|
60
|
+
item.children?.forEach(child => processItem(child, depth + 1, id));
|
|
61
|
+
}
|
|
51
62
|
};
|
|
52
|
-
items
|
|
63
|
+
items?.forEach(item => processItem(item, initialDepth, initialParentId));
|
|
53
64
|
const itemChildrenIndexesLookup = {};
|
|
54
65
|
Object.keys(itemOrderedChildrenIdsLookup).forEach(parentId => {
|
|
55
66
|
itemChildrenIndexesLookup[parentId] = buildSiblingIndexes(itemOrderedChildrenIdsLookup[parentId]);
|
|
@@ -68,6 +79,43 @@ export const useTreeViewItems = ({
|
|
|
68
79
|
store
|
|
69
80
|
}) => {
|
|
70
81
|
const getItem = React.useCallback(itemId => selectorItemModel(store.value, itemId), [store]);
|
|
82
|
+
const getParentId = React.useCallback(itemId => {
|
|
83
|
+
const itemMeta = selectorItemMeta(store.value, itemId);
|
|
84
|
+
return itemMeta?.parentId || null;
|
|
85
|
+
}, [store]);
|
|
86
|
+
const setTreeViewLoading = useEventCallback(isLoading => {
|
|
87
|
+
store.update(prevState => _extends({}, prevState, {
|
|
88
|
+
items: _extends({}, prevState.items, {
|
|
89
|
+
loading: isLoading
|
|
90
|
+
})
|
|
91
|
+
}));
|
|
92
|
+
});
|
|
93
|
+
const setTreeViewError = useEventCallback(error => {
|
|
94
|
+
store.update(prevState => _extends({}, prevState, {
|
|
95
|
+
items: _extends({}, prevState.items, {
|
|
96
|
+
error
|
|
97
|
+
})
|
|
98
|
+
}));
|
|
99
|
+
});
|
|
100
|
+
const setIsItemDisabled = useEventCallback(({
|
|
101
|
+
itemId,
|
|
102
|
+
shouldBeDisabled
|
|
103
|
+
}) => {
|
|
104
|
+
store.update(prevState => {
|
|
105
|
+
if (!prevState.items.itemMetaLookup[itemId]) {
|
|
106
|
+
return prevState;
|
|
107
|
+
}
|
|
108
|
+
const itemMetaLookup = _extends({}, prevState.items.itemMetaLookup);
|
|
109
|
+
itemMetaLookup[itemId] = _extends({}, itemMetaLookup[itemId], {
|
|
110
|
+
disabled: shouldBeDisabled ?? !itemMetaLookup[itemId].disabled
|
|
111
|
+
});
|
|
112
|
+
return _extends({}, prevState, {
|
|
113
|
+
items: _extends({}, prevState.items, {
|
|
114
|
+
itemMetaLookup
|
|
115
|
+
})
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
});
|
|
71
119
|
const getItemTree = React.useCallback(() => {
|
|
72
120
|
const getItemFromItemId = itemId => {
|
|
73
121
|
const item = selectorItemModel(store.value, itemId);
|
|
@@ -99,12 +147,96 @@ export const useTreeViewItems = ({
|
|
|
99
147
|
areItemUpdatesPreventedRef.current = true;
|
|
100
148
|
}, []);
|
|
101
149
|
const areItemUpdatesPrevented = React.useCallback(() => areItemUpdatesPreventedRef.current, []);
|
|
150
|
+
const addItems = ({
|
|
151
|
+
items,
|
|
152
|
+
parentId,
|
|
153
|
+
depth,
|
|
154
|
+
getChildrenCount
|
|
155
|
+
}) => {
|
|
156
|
+
if (items) {
|
|
157
|
+
const newState = processItemsLookups({
|
|
158
|
+
disabledItemsFocusable: params.disabledItemsFocusable,
|
|
159
|
+
items,
|
|
160
|
+
isItemDisabled: params.isItemDisabled,
|
|
161
|
+
getItemId: params.getItemId,
|
|
162
|
+
getItemLabel: params.getItemLabel,
|
|
163
|
+
getChildrenCount,
|
|
164
|
+
initialDepth: depth,
|
|
165
|
+
initialParentId: parentId,
|
|
166
|
+
ignoreChildren: true
|
|
167
|
+
});
|
|
168
|
+
store.update(prevState => {
|
|
169
|
+
let newItems;
|
|
170
|
+
if (parentId) {
|
|
171
|
+
newItems = {
|
|
172
|
+
itemModelLookup: _extends({}, prevState.items.itemModelLookup, newState.itemModelLookup),
|
|
173
|
+
itemMetaLookup: _extends({}, prevState.items.itemMetaLookup, newState.itemMetaLookup),
|
|
174
|
+
itemOrderedChildrenIdsLookup: _extends({}, newState.itemOrderedChildrenIdsLookup, prevState.items.itemOrderedChildrenIdsLookup),
|
|
175
|
+
itemChildrenIndexesLookup: _extends({}, newState.itemChildrenIndexesLookup, prevState.items.itemChildrenIndexesLookup)
|
|
176
|
+
};
|
|
177
|
+
} else {
|
|
178
|
+
newItems = {
|
|
179
|
+
itemModelLookup: newState.itemModelLookup,
|
|
180
|
+
itemMetaLookup: newState.itemMetaLookup,
|
|
181
|
+
itemOrderedChildrenIdsLookup: newState.itemOrderedChildrenIdsLookup,
|
|
182
|
+
itemChildrenIndexesLookup: newState.itemChildrenIndexesLookup
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
Object.values(prevState.items.itemMetaLookup).forEach(item => {
|
|
186
|
+
if (!newState.itemMetaLookup[item.id]) {
|
|
187
|
+
publishTreeViewEvent(instance, 'removeItem', {
|
|
188
|
+
id: item.id
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
return _extends({}, prevState, {
|
|
193
|
+
items: _extends({}, prevState.items, newItems)
|
|
194
|
+
});
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
const removeChildren = parentId => {
|
|
199
|
+
store.update(prevState => {
|
|
200
|
+
if (!parentId) {
|
|
201
|
+
return _extends({}, prevState, {
|
|
202
|
+
items: _extends({}, prevState.items, {
|
|
203
|
+
itemMetaLookup: {},
|
|
204
|
+
itemOrderedChildrenIdsLookup: {},
|
|
205
|
+
itemChildrenIndexesLookup: {}
|
|
206
|
+
})
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
const newMetaMap = Object.keys(prevState.items.itemMetaLookup).reduce((acc, key) => {
|
|
210
|
+
const item = prevState.items.itemMetaLookup[key];
|
|
211
|
+
if (item.parentId === parentId) {
|
|
212
|
+
publishTreeViewEvent(instance, 'removeItem', {
|
|
213
|
+
id: item.id
|
|
214
|
+
});
|
|
215
|
+
return acc;
|
|
216
|
+
}
|
|
217
|
+
return _extends({}, acc, {
|
|
218
|
+
[item.id]: item
|
|
219
|
+
});
|
|
220
|
+
}, {});
|
|
221
|
+
const newItemOrderedChildrenIdsLookup = prevState.items.itemOrderedChildrenIdsLookup;
|
|
222
|
+
const newItemChildrenIndexesLookup = prevState.items.itemChildrenIndexesLookup;
|
|
223
|
+
delete newItemChildrenIndexesLookup[parentId];
|
|
224
|
+
delete newItemOrderedChildrenIdsLookup[parentId];
|
|
225
|
+
return _extends({}, prevState, {
|
|
226
|
+
items: _extends({}, prevState.items, {
|
|
227
|
+
itemMetaLookup: newMetaMap,
|
|
228
|
+
itemOrderedChildrenIdsLookup: newItemOrderedChildrenIdsLookup,
|
|
229
|
+
itemChildrenIndexesLookup: newItemChildrenIndexesLookup
|
|
230
|
+
})
|
|
231
|
+
});
|
|
232
|
+
});
|
|
233
|
+
};
|
|
102
234
|
React.useEffect(() => {
|
|
103
235
|
if (instance.areItemUpdatesPrevented()) {
|
|
104
236
|
return;
|
|
105
237
|
}
|
|
106
238
|
store.update(prevState => {
|
|
107
|
-
const newState =
|
|
239
|
+
const newState = processItemsLookups({
|
|
108
240
|
disabledItemsFocusable: params.disabledItemsFocusable,
|
|
109
241
|
items: params.items,
|
|
110
242
|
isItemDisabled: params.isItemDisabled,
|
|
@@ -119,7 +251,7 @@ export const useTreeViewItems = ({
|
|
|
119
251
|
}
|
|
120
252
|
});
|
|
121
253
|
return _extends({}, prevState, {
|
|
122
|
-
items: newState
|
|
254
|
+
items: _extends({}, prevState.items, newState)
|
|
123
255
|
});
|
|
124
256
|
});
|
|
125
257
|
}, [instance, store, params.items, params.disabledItemsFocusable, params.isItemDisabled, params.getItemId, params.getItemLabel]);
|
|
@@ -145,23 +277,32 @@ export const useTreeViewItems = ({
|
|
|
145
277
|
getItem,
|
|
146
278
|
getItemDOMElement,
|
|
147
279
|
getItemTree,
|
|
148
|
-
getItemOrderedChildrenIds
|
|
280
|
+
getItemOrderedChildrenIds,
|
|
281
|
+
setIsItemDisabled,
|
|
282
|
+
getParentId
|
|
149
283
|
},
|
|
150
284
|
instance: {
|
|
151
285
|
getItemDOMElement,
|
|
152
286
|
preventItemUpdates,
|
|
153
|
-
areItemUpdatesPrevented
|
|
287
|
+
areItemUpdatesPrevented,
|
|
288
|
+
addItems,
|
|
289
|
+
setTreeViewLoading,
|
|
290
|
+
setTreeViewError,
|
|
291
|
+
removeChildren
|
|
154
292
|
},
|
|
155
293
|
contextValue: pluginContextValue
|
|
156
294
|
};
|
|
157
295
|
};
|
|
158
296
|
useTreeViewItems.getInitialState = params => ({
|
|
159
|
-
items:
|
|
297
|
+
items: _extends({}, processItemsLookups({
|
|
160
298
|
disabledItemsFocusable: params.disabledItemsFocusable,
|
|
161
299
|
items: params.items,
|
|
162
300
|
isItemDisabled: params.isItemDisabled,
|
|
163
301
|
getItemId: params.getItemId,
|
|
164
302
|
getItemLabel: params.getItemLabel
|
|
303
|
+
}), {
|
|
304
|
+
loading: false,
|
|
305
|
+
error: null
|
|
165
306
|
})
|
|
166
307
|
});
|
|
167
308
|
useTreeViewItems.getDefaultizedParams = ({
|