@mui/x-tree-view 8.0.0-alpha.0 → 8.0.0-alpha.1
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 +429 -5
- package/README.md +2 -2
- package/RichTreeView/RichTreeView.js +2 -4
- package/RichTreeView/RichTreeView.types.d.ts +3 -16
- package/TreeItem/TreeItem.js +4 -4
- package/TreeItem/TreeItem.types.d.ts +3 -1
- package/TreeItemProvider/TreeItemProvider.js +16 -3
- package/TreeItemProvider/TreeItemProvider.types.d.ts +1 -0
- package/hooks/index.d.ts +1 -0
- package/hooks/index.js +2 -1
- package/hooks/useTreeItemModel.d.ts +2 -0
- package/hooks/useTreeItemModel.js +11 -0
- package/hooks/useTreeItemUtils/useTreeItemUtils.d.ts +2 -1
- package/hooks/useTreeItemUtils/useTreeItemUtils.js +31 -15
- package/index.js +1 -1
- package/internals/TreeViewItemDepthContext/TreeViewItemDepthContext.d.ts +3 -1
- package/internals/TreeViewProvider/TreeViewChildrenItemProvider.d.ts +2 -1
- package/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +6 -22
- package/internals/TreeViewProvider/TreeViewProvider.js +1 -2
- package/internals/TreeViewProvider/TreeViewProvider.types.d.ts +4 -2
- package/internals/components/RichTreeViewItems.d.ts +2 -4
- package/internals/components/RichTreeViewItems.js +42 -30
- package/internals/corePlugins/useTreeViewId/useTreeViewId.js +10 -11
- package/internals/corePlugins/useTreeViewId/useTreeViewId.selectors.d.ts +36 -0
- package/internals/corePlugins/useTreeViewId/useTreeViewId.selectors.js +9 -0
- package/internals/corePlugins/useTreeViewId/useTreeViewId.types.d.ts +1 -5
- package/internals/hooks/useSelector.d.ts +4 -0
- package/internals/hooks/useSelector.js +6 -0
- package/internals/index.d.ts +6 -1
- package/internals/index.js +5 -1
- package/internals/models/itemPlugin.d.ts +4 -4
- package/internals/models/plugin.d.ts +19 -7
- package/internals/models/treeView.d.ts +6 -0
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +36 -24
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.selectors.d.ts +124 -0
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.selectors.js +17 -0
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.types.d.ts +6 -14
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.utils.d.ts +1 -0
- package/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.utils.js +7 -0
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +62 -40
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.selectors.d.ts +182 -0
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.selectors.js +34 -0
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +4 -16
- package/internals/plugins/useTreeViewIcons/useTreeViewIcons.js +15 -13
- package/internals/plugins/useTreeViewItems/index.d.ts +1 -1
- package/internals/plugins/useTreeViewItems/useTreeViewItems.js +58 -98
- package/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.d.ts +718 -0
- package/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js +103 -0
- package/internals/plugins/useTreeViewItems/useTreeViewItems.types.d.ts +15 -52
- package/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +29 -26
- package/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +27 -18
- package/internals/plugins/useTreeViewLabel/useTreeViewLabel.itemPlugin.js +13 -5
- package/internals/plugins/useTreeViewLabel/useTreeViewLabel.js +19 -30
- package/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.d.ts +74 -0
- package/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.js +26 -0
- package/internals/plugins/useTreeViewLabel/useTreeViewLabel.types.d.ts +7 -24
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.itemPlugin.js +8 -6
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +45 -34
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.d.ts +32 -0
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.js +9 -0
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.types.d.ts +6 -6
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.d.ts +6 -6
- package/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +23 -13
- package/internals/useTreeView/useTreeView.js +30 -17
- package/internals/useTreeView/useTreeView.types.d.ts +1 -2
- package/internals/useTreeView/useTreeViewBuildContext.d.ts +3 -1
- package/internals/useTreeView/useTreeViewBuildContext.js +24 -18
- package/internals/utils/TreeViewStore.d.ts +12 -0
- package/internals/utils/TreeViewStore.js +24 -0
- package/internals/utils/selectors.d.ts +9 -0
- package/internals/utils/selectors.js +37 -0
- package/internals/utils/tree.d.ts +8 -8
- package/internals/utils/tree.js +51 -43
- package/models/items.d.ts +3 -2
- package/modern/RichTreeView/RichTreeView.js +2 -4
- package/modern/TreeItem/TreeItem.js +4 -4
- package/modern/TreeItemProvider/TreeItemProvider.js +16 -3
- package/modern/hooks/index.js +2 -1
- package/modern/hooks/useTreeItemModel.js +11 -0
- package/modern/hooks/useTreeItemUtils/useTreeItemUtils.js +31 -15
- package/modern/index.js +1 -1
- package/modern/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +6 -22
- package/modern/internals/TreeViewProvider/TreeViewProvider.js +1 -2
- package/modern/internals/components/RichTreeViewItems.js +42 -30
- package/modern/internals/corePlugins/useTreeViewId/useTreeViewId.js +10 -11
- package/modern/internals/corePlugins/useTreeViewId/useTreeViewId.selectors.js +9 -0
- package/modern/internals/hooks/useSelector.js +6 -0
- package/modern/internals/index.js +5 -1
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +36 -24
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.selectors.js +17 -0
- package/modern/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.utils.js +7 -0
- package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +62 -40
- package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.selectors.js +34 -0
- package/modern/internals/plugins/useTreeViewIcons/useTreeViewIcons.js +15 -13
- package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.js +58 -98
- package/modern/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js +103 -0
- package/modern/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +29 -26
- package/modern/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +27 -18
- package/modern/internals/plugins/useTreeViewLabel/useTreeViewLabel.itemPlugin.js +13 -5
- package/modern/internals/plugins/useTreeViewLabel/useTreeViewLabel.js +19 -30
- package/modern/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.js +26 -0
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.itemPlugin.js +8 -6
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +45 -34
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.js +9 -0
- package/modern/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +23 -13
- package/modern/internals/useTreeView/useTreeView.js +30 -17
- package/modern/internals/useTreeView/useTreeViewBuildContext.js +24 -18
- package/modern/internals/utils/TreeViewStore.js +24 -0
- package/modern/internals/utils/selectors.js +37 -0
- package/modern/internals/utils/tree.js +51 -43
- package/modern/useTreeItem/useTreeItem.js +26 -11
- package/node/RichTreeView/RichTreeView.js +2 -4
- package/node/TreeItem/TreeItem.js +4 -4
- package/node/TreeItemProvider/TreeItemProvider.js +16 -3
- package/node/hooks/index.js +8 -1
- package/node/hooks/useTreeItemModel.js +17 -0
- package/node/hooks/useTreeItemUtils/useTreeItemUtils.js +32 -15
- package/node/index.js +1 -1
- package/node/internals/TreeViewProvider/TreeViewChildrenItemProvider.js +6 -22
- package/node/internals/TreeViewProvider/TreeViewProvider.js +1 -2
- package/node/internals/components/RichTreeViewItems.js +42 -30
- package/node/internals/corePlugins/useTreeViewId/useTreeViewId.js +12 -13
- package/node/internals/corePlugins/useTreeViewId/useTreeViewId.selectors.js +15 -0
- package/node/internals/hooks/useSelector.js +13 -0
- package/node/internals/index.js +47 -1
- package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.js +36 -24
- package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.selectors.js +23 -0
- package/node/internals/plugins/useTreeViewExpansion/useTreeViewExpansion.utils.js +14 -0
- package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +62 -40
- package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.selectors.js +40 -0
- package/node/internals/plugins/useTreeViewIcons/useTreeViewIcons.js +16 -13
- package/node/internals/plugins/useTreeViewItems/useTreeViewItems.js +60 -100
- package/node/internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js +109 -0
- package/node/internals/plugins/useTreeViewJSXItems/useTreeViewJSXItems.js +30 -27
- package/node/internals/plugins/useTreeViewKeyboardNavigation/useTreeViewKeyboardNavigation.js +27 -18
- package/node/internals/plugins/useTreeViewLabel/useTreeViewLabel.itemPlugin.js +13 -5
- package/node/internals/plugins/useTreeViewLabel/useTreeViewLabel.js +19 -30
- package/node/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.js +32 -0
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.itemPlugin.js +8 -6
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.js +46 -35
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.js +15 -0
- package/node/internals/plugins/useTreeViewSelection/useTreeViewSelection.utils.js +24 -14
- package/node/internals/useTreeView/useTreeView.js +30 -17
- package/node/internals/useTreeView/useTreeViewBuildContext.js +25 -18
- package/node/internals/utils/TreeViewStore.js +31 -0
- package/node/internals/utils/selectors.js +44 -0
- package/node/internals/utils/tree.js +51 -43
- package/node/useTreeItem/useTreeItem.js +26 -11
- package/package.json +6 -4
- package/useTreeItem/useTreeItem.js +26 -11
- package/useTreeItem/useTreeItem.types.d.ts +9 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useTreeViewContext } from "../internals/TreeViewProvider/index.js";
|
|
4
|
+
import { useSelector } from "../internals/hooks/useSelector.js";
|
|
5
|
+
import { selectorItemModel } from "../internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js";
|
|
6
|
+
export const useTreeItemModel = itemId => {
|
|
7
|
+
const {
|
|
8
|
+
store
|
|
9
|
+
} = useTreeViewContext();
|
|
10
|
+
return useSelector(store, selectorItemModel, itemId);
|
|
11
|
+
};
|
|
@@ -35,8 +35,9 @@ interface UseTreeItemUtilsReturnValue<TSignatures extends UseTreeItemUtilsMinima
|
|
|
35
35
|
*/
|
|
36
36
|
publicAPI: TreeViewPublicAPI<TSignatures, TOptionalSignatures>;
|
|
37
37
|
}
|
|
38
|
+
export declare const isItemExpandable: (reactChildren: React.ReactNode) => boolean;
|
|
38
39
|
export declare const useTreeItemUtils: <TSignatures extends UseTreeItemUtilsMinimalPlugins = UseTreeItemUtilsMinimalPlugins, TOptionalSignatures extends UseTreeItemUtilsOptionalPlugins = UseTreeItemUtilsOptionalPlugins>({ itemId, children, }: {
|
|
39
40
|
itemId: string;
|
|
40
|
-
children
|
|
41
|
+
children?: React.ReactNode;
|
|
41
42
|
}) => UseTreeItemUtilsReturnValue<TSignatures, TOptionalSignatures>;
|
|
42
43
|
export {};
|
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
import { useTreeViewContext } from "../../internals/TreeViewProvider/index.js";
|
|
4
4
|
import { useTreeViewLabel } from "../../internals/plugins/useTreeViewLabel/index.js";
|
|
5
5
|
import { hasPlugin } from "../../internals/utils/plugins.js";
|
|
6
|
+
import { useSelector } from "../../internals/hooks/useSelector.js";
|
|
7
|
+
import { selectorIsItemExpanded } from "../../internals/plugins/useTreeViewExpansion/useTreeViewExpansion.selectors.js";
|
|
8
|
+
import { selectorIsItemFocused } from "../../internals/plugins/useTreeViewFocus/useTreeViewFocus.selectors.js";
|
|
9
|
+
import { selectorIsItemDisabled } from "../../internals/plugins/useTreeViewItems/useTreeViewItems.selectors.js";
|
|
10
|
+
import { selectorIsItemSelected } from "../../internals/plugins/useTreeViewSelection/useTreeViewSelection.selectors.js";
|
|
11
|
+
import { selectorIsItemBeingEdited, selectorIsItemEditable } from "../../internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.js";
|
|
6
12
|
|
|
7
13
|
/**
|
|
8
14
|
* Plugins that need to be present in the Tree View in order for `useTreeItemUtils` to work correctly.
|
|
@@ -12,7 +18,7 @@ import { hasPlugin } from "../../internals/utils/plugins.js";
|
|
|
12
18
|
* Plugins that `useTreeItemUtils` can use if they are present, but are not required.
|
|
13
19
|
*/
|
|
14
20
|
|
|
15
|
-
const isItemExpandable = reactChildren => {
|
|
21
|
+
export const isItemExpandable = reactChildren => {
|
|
16
22
|
if (Array.isArray(reactChildren)) {
|
|
17
23
|
return reactChildren.length > 0 && reactChildren.some(isItemExpandable);
|
|
18
24
|
}
|
|
@@ -24,19 +30,30 @@ export const useTreeItemUtils = ({
|
|
|
24
30
|
}) => {
|
|
25
31
|
const {
|
|
26
32
|
instance,
|
|
33
|
+
label,
|
|
34
|
+
store,
|
|
27
35
|
selection: {
|
|
28
36
|
multiSelect
|
|
29
37
|
},
|
|
30
38
|
publicAPI
|
|
31
39
|
} = useTreeViewContext();
|
|
40
|
+
const isExpanded = useSelector(store, selectorIsItemExpanded, itemId);
|
|
41
|
+
const isFocused = useSelector(store, selectorIsItemFocused, itemId);
|
|
42
|
+
const isSelected = useSelector(store, selectorIsItemSelected, itemId);
|
|
43
|
+
const isDisabled = useSelector(store, selectorIsItemDisabled, itemId);
|
|
44
|
+
const isEditing = useSelector(store, state => label == null ? false : selectorIsItemBeingEdited(state, itemId));
|
|
45
|
+
const isEditable = useSelector(store, state => label == null ? false : selectorIsItemEditable(state, {
|
|
46
|
+
itemId,
|
|
47
|
+
isItemEditable: label.isItemEditable
|
|
48
|
+
}));
|
|
32
49
|
const status = {
|
|
33
50
|
expandable: isItemExpandable(children),
|
|
34
|
-
expanded:
|
|
35
|
-
focused:
|
|
36
|
-
selected:
|
|
37
|
-
disabled:
|
|
38
|
-
editing:
|
|
39
|
-
editable:
|
|
51
|
+
expanded: isExpanded,
|
|
52
|
+
focused: isFocused,
|
|
53
|
+
selected: isSelected,
|
|
54
|
+
disabled: isDisabled,
|
|
55
|
+
editing: isEditing,
|
|
56
|
+
editable: isEditable
|
|
40
57
|
};
|
|
41
58
|
const handleExpansion = event => {
|
|
42
59
|
if (status.disabled) {
|
|
@@ -48,7 +65,7 @@ export const useTreeItemUtils = ({
|
|
|
48
65
|
const multiple = multiSelect && (event.shiftKey || event.ctrlKey || event.metaKey);
|
|
49
66
|
|
|
50
67
|
// If already expanded and trying to toggle selection don't close
|
|
51
|
-
if (status.expandable && !(multiple &&
|
|
68
|
+
if (status.expandable && !(multiple && selectorIsItemExpanded(store.value, itemId))) {
|
|
52
69
|
instance.toggleItemExpansion(event, itemId);
|
|
53
70
|
}
|
|
54
71
|
};
|
|
@@ -95,15 +112,15 @@ export const useTreeItemUtils = ({
|
|
|
95
112
|
if (!hasPlugin(instance, useTreeViewLabel)) {
|
|
96
113
|
return;
|
|
97
114
|
}
|
|
98
|
-
if (
|
|
99
|
-
if (
|
|
115
|
+
if (isEditable) {
|
|
116
|
+
if (isEditing) {
|
|
100
117
|
instance.setEditedItemId(null);
|
|
101
118
|
} else {
|
|
102
119
|
instance.setEditedItemId(itemId);
|
|
103
120
|
}
|
|
104
121
|
}
|
|
105
122
|
};
|
|
106
|
-
const handleSaveItemLabel = (event,
|
|
123
|
+
const handleSaveItemLabel = (event, newLabel) => {
|
|
107
124
|
if (!hasPlugin(instance, useTreeViewLabel)) {
|
|
108
125
|
return;
|
|
109
126
|
}
|
|
@@ -111,9 +128,8 @@ export const useTreeItemUtils = ({
|
|
|
111
128
|
// As a side effect of `instance.focusItem` called here and in `handleCancelItemLabelEditing` the `labelInput` is blurred
|
|
112
129
|
// The `onBlur` event is triggered, which calls `handleSaveItemLabel` again.
|
|
113
130
|
// To avoid creating an unwanted behavior we need to check if the item is being edited before calling `updateItemLabel`
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
instance.updateItemLabel(itemId, label);
|
|
131
|
+
if (selectorIsItemBeingEdited(store.value, itemId)) {
|
|
132
|
+
instance.updateItemLabel(itemId, newLabel);
|
|
117
133
|
toggleItemEditing();
|
|
118
134
|
instance.focusItem(event, itemId);
|
|
119
135
|
}
|
|
@@ -122,7 +138,7 @@ export const useTreeItemUtils = ({
|
|
|
122
138
|
if (!hasPlugin(instance, useTreeViewLabel)) {
|
|
123
139
|
return;
|
|
124
140
|
}
|
|
125
|
-
if (
|
|
141
|
+
if (selectorIsItemBeingEdited(store.value, itemId)) {
|
|
126
142
|
toggleItemEditing();
|
|
127
143
|
instance.focusItem(event, itemId);
|
|
128
144
|
}
|
package/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { TreeViewItemId } from '../../models';
|
|
3
|
-
|
|
3
|
+
import { TreeViewState } from '../models';
|
|
4
|
+
import type { UseTreeViewItemsSignature } from '../plugins/useTreeViewItems';
|
|
5
|
+
export declare const TreeViewItemDepthContext: React.Context<number | ((state: TreeViewState<[UseTreeViewItemsSignature]>, itemId: TreeViewItemId) => number)>;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
export declare const TreeViewChildrenItemContext: React.Context<TreeViewChildrenItemContextValue | null>;
|
|
3
3
|
interface TreeViewChildrenItemProviderProps {
|
|
4
|
-
itemId
|
|
4
|
+
itemId: string | null;
|
|
5
|
+
idAttribute: string | null;
|
|
5
6
|
children: React.ReactNode;
|
|
6
7
|
}
|
|
7
8
|
export declare function TreeViewChildrenItemProvider(props: TreeViewChildrenItemProviderProps): React.JSX.Element;
|
|
@@ -2,7 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { useTreeViewContext } from "./useTreeViewContext.js";
|
|
4
4
|
import { escapeOperandAttributeSelector } from "../utils/utils.js";
|
|
5
|
-
import {
|
|
5
|
+
import { selectorItemOrderedChildrenIds } from "../plugins/useTreeViewItems/useTreeViewItems.selectors.js";
|
|
6
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
7
|
export const TreeViewChildrenItemContext = /*#__PURE__*/React.createContext(null);
|
|
8
8
|
if (process.env.NODE_ENV !== 'production') {
|
|
@@ -11,11 +11,12 @@ if (process.env.NODE_ENV !== 'production') {
|
|
|
11
11
|
export function TreeViewChildrenItemProvider(props) {
|
|
12
12
|
const {
|
|
13
13
|
children,
|
|
14
|
-
itemId = null
|
|
14
|
+
itemId = null,
|
|
15
|
+
idAttribute
|
|
15
16
|
} = props;
|
|
16
17
|
const {
|
|
17
18
|
instance,
|
|
18
|
-
|
|
19
|
+
store,
|
|
19
20
|
rootRef
|
|
20
21
|
} = useTreeViewContext();
|
|
21
22
|
const childrenIdAttrToIdRef = React.useRef(new Map());
|
|
@@ -23,25 +24,8 @@ export function TreeViewChildrenItemProvider(props) {
|
|
|
23
24
|
if (!rootRef.current) {
|
|
24
25
|
return;
|
|
25
26
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
idAttr = rootRef.current.id;
|
|
29
|
-
} else {
|
|
30
|
-
// Undefined during 1st render
|
|
31
|
-
const itemMeta = instance.getItemMeta(itemId);
|
|
32
|
-
if (itemMeta !== undefined) {
|
|
33
|
-
idAttr = generateTreeItemIdAttribute({
|
|
34
|
-
itemId,
|
|
35
|
-
treeId,
|
|
36
|
-
id: itemMeta.idAttribute
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
if (idAttr == null) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
const previousChildrenIds = instance.getItemOrderedChildrenIds(itemId ?? null) ?? [];
|
|
44
|
-
const escapedIdAttr = escapeOperandAttributeSelector(idAttr);
|
|
27
|
+
const previousChildrenIds = selectorItemOrderedChildrenIds(store.value, itemId ?? null) ?? [];
|
|
28
|
+
const escapedIdAttr = escapeOperandAttributeSelector(idAttribute ?? rootRef.current.id);
|
|
45
29
|
const childrenElements = rootRef.current.querySelectorAll(`${itemId == null ? '' : `*[id="${escapedIdAttr}"] `}[role="treeitem"]:not(*[id="${escapedIdAttr}"] [role="treeitem"] [role="treeitem"])`);
|
|
46
30
|
const childrenIds = Array.from(childrenElements).map(child => childrenIdAttrToIdRef.current.get(child.id));
|
|
47
31
|
const hasChanged = childrenIds.length !== previousChildrenIds.length || childrenIds.some((childId, index) => childId !== previousChildrenIds[index]);
|
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { MergeSignaturesProperty, TreeItemWrapper, TreeRootWrapper, TreeViewAnyPluginSignature, TreeViewInstance, TreeViewItemPluginResponse, TreeViewPublicAPI } from '../models';
|
|
3
|
+
import { TreeViewStore } from '../utils/TreeViewStore';
|
|
3
4
|
import { TreeViewCorePluginSignatures } from '../corePlugins';
|
|
4
|
-
import type { TreeItemProps } from '../../TreeItem';
|
|
5
|
+
import type { TreeItemProps } from '../../TreeItem/TreeItem.types';
|
|
5
6
|
export type TreeViewItemPluginsRunner = (props: TreeItemProps) => Required<TreeViewItemPluginResponse>;
|
|
6
7
|
export type TreeViewContextValue<TSignatures extends readonly TreeViewAnyPluginSignature[], TOptionalSignatures extends readonly TreeViewAnyPluginSignature[] = []> = MergeSignaturesProperty<[...TreeViewCorePluginSignatures, ...TSignatures], 'contextValue'> & Partial<MergeSignaturesProperty<TOptionalSignatures, 'contextValue'>> & {
|
|
7
8
|
instance: TreeViewInstance<TSignatures, TOptionalSignatures>;
|
|
8
9
|
publicAPI: TreeViewPublicAPI<TSignatures, TOptionalSignatures>;
|
|
10
|
+
store: TreeViewStore<TSignatures>;
|
|
9
11
|
rootRef: React.RefObject<HTMLUListElement>;
|
|
10
12
|
wrapItem: TreeItemWrapper<TSignatures>;
|
|
11
|
-
wrapRoot: TreeRootWrapper
|
|
13
|
+
wrapRoot: TreeRootWrapper;
|
|
12
14
|
runItemPlugins: TreeViewItemPluginsRunner;
|
|
13
15
|
};
|
|
14
16
|
export interface TreeViewProviderProps<TSignatures extends readonly TreeViewAnyPluginSignature[]> {
|
|
@@ -2,14 +2,14 @@ import * as React from 'react';
|
|
|
2
2
|
import { SlotComponentProps } from '@mui/utils';
|
|
3
3
|
import { TreeItem, TreeItemProps } from '../../TreeItem';
|
|
4
4
|
import { TreeViewItemId } from '../../models';
|
|
5
|
-
|
|
5
|
+
export declare function RichTreeViewItems(props: RichTreeViewItemsProps): React.JSX.Element;
|
|
6
6
|
interface RichTreeViewItemsOwnerState {
|
|
7
7
|
itemId: TreeViewItemId;
|
|
8
8
|
label: string;
|
|
9
9
|
}
|
|
10
10
|
export interface RichTreeViewItemsSlots {
|
|
11
11
|
/**
|
|
12
|
-
* Custom component
|
|
12
|
+
* Custom component to render a Tree Item.
|
|
13
13
|
* @default TreeItem.
|
|
14
14
|
*/
|
|
15
15
|
item?: React.JSXElementConstructor<TreeItemProps>;
|
|
@@ -18,7 +18,6 @@ export interface RichTreeViewItemsSlotProps {
|
|
|
18
18
|
item?: SlotComponentProps<typeof TreeItem, {}, RichTreeViewItemsOwnerState>;
|
|
19
19
|
}
|
|
20
20
|
export interface RichTreeViewItemsProps {
|
|
21
|
-
itemsToRender: TreeViewItemToRenderProps[];
|
|
22
21
|
/**
|
|
23
22
|
* Overridable component slots.
|
|
24
23
|
* @default {}
|
|
@@ -30,5 +29,4 @@ export interface RichTreeViewItemsProps {
|
|
|
30
29
|
*/
|
|
31
30
|
slotProps?: RichTreeViewItemsSlotProps;
|
|
32
31
|
}
|
|
33
|
-
export declare function RichTreeViewItems(props: RichTreeViewItemsProps): React.JSX.Element;
|
|
34
32
|
export {};
|
|
@@ -3,54 +3,66 @@ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWith
|
|
|
3
3
|
const _excluded = ["ownerState"];
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import useSlotProps from '@mui/utils/useSlotProps';
|
|
6
|
+
import { fastObjectShallowCompare } from '@mui/x-internals/fastObjectShallowCompare';
|
|
6
7
|
import { TreeItem } from "../../TreeItem/index.js";
|
|
8
|
+
import { useSelector } from "../hooks/useSelector.js";
|
|
9
|
+
import { selectorItemMeta, selectorItemOrderedChildrenIds } from "../plugins/useTreeViewItems/useTreeViewItems.selectors.js";
|
|
10
|
+
import { useTreeViewContext } from "../TreeViewProvider/index.js";
|
|
7
11
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
const RichTreeViewItemsContext = /*#__PURE__*/React.createContext(null);
|
|
13
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
14
|
+
RichTreeViewItemsContext.displayName = 'RichTreeViewItemsProvider';
|
|
15
|
+
}
|
|
16
|
+
const WrappedTreeItem = /*#__PURE__*/React.memo(function WrappedTreeItem({
|
|
17
|
+
itemSlot,
|
|
18
|
+
itemSlotProps,
|
|
19
|
+
itemId
|
|
15
20
|
}) {
|
|
16
|
-
const
|
|
21
|
+
const renderItemForRichTreeView = React.useContext(RichTreeViewItemsContext);
|
|
22
|
+
const {
|
|
23
|
+
store
|
|
24
|
+
} = useTreeViewContext();
|
|
25
|
+
const itemMeta = useSelector(store, selectorItemMeta, itemId);
|
|
26
|
+
const children = useSelector(store, selectorItemOrderedChildrenIds, itemId);
|
|
27
|
+
const Item = itemSlot ?? TreeItem;
|
|
17
28
|
const _useSlotProps = useSlotProps({
|
|
18
29
|
elementType: Item,
|
|
19
|
-
externalSlotProps:
|
|
30
|
+
externalSlotProps: itemSlotProps,
|
|
20
31
|
additionalProps: {
|
|
21
|
-
|
|
22
|
-
id,
|
|
23
|
-
|
|
32
|
+
label: itemMeta?.label,
|
|
33
|
+
id: itemMeta?.idAttribute,
|
|
34
|
+
itemId
|
|
24
35
|
},
|
|
25
36
|
ownerState: {
|
|
26
37
|
itemId,
|
|
27
|
-
label
|
|
38
|
+
label: itemMeta?.label
|
|
28
39
|
}
|
|
29
40
|
}),
|
|
30
41
|
itemProps = _objectWithoutPropertiesLoose(_useSlotProps, _excluded);
|
|
31
|
-
const children = React.useMemo(() => itemsToRender ? /*#__PURE__*/_jsx(RichTreeViewItems, {
|
|
32
|
-
itemsToRender: itemsToRender,
|
|
33
|
-
slots: slots,
|
|
34
|
-
slotProps: slotProps
|
|
35
|
-
}) : null, [itemsToRender, slots, slotProps]);
|
|
36
42
|
return /*#__PURE__*/_jsx(Item, _extends({}, itemProps, {
|
|
37
|
-
children: children
|
|
43
|
+
children: children?.map(renderItemForRichTreeView)
|
|
38
44
|
}));
|
|
39
|
-
}
|
|
45
|
+
}, fastObjectShallowCompare);
|
|
40
46
|
export function RichTreeViewItems(props) {
|
|
41
47
|
const {
|
|
42
|
-
itemsToRender,
|
|
43
48
|
slots,
|
|
44
49
|
slotProps
|
|
45
50
|
} = props;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
const {
|
|
52
|
+
store
|
|
53
|
+
} = useTreeViewContext();
|
|
54
|
+
const itemSlot = slots?.item;
|
|
55
|
+
const itemSlotProps = slotProps?.item;
|
|
56
|
+
const items = useSelector(store, selectorItemOrderedChildrenIds, null);
|
|
57
|
+
const renderItem = React.useCallback(itemId => {
|
|
58
|
+
return /*#__PURE__*/_jsx(WrappedTreeItem, {
|
|
59
|
+
itemSlot: itemSlot,
|
|
60
|
+
itemSlotProps: itemSlotProps,
|
|
61
|
+
itemId: itemId
|
|
62
|
+
}, itemId);
|
|
63
|
+
}, [itemSlot, itemSlotProps]);
|
|
64
|
+
return /*#__PURE__*/_jsx(RichTreeViewItemsContext.Provider, {
|
|
65
|
+
value: renderItem,
|
|
66
|
+
children: items.map(renderItem)
|
|
55
67
|
});
|
|
56
68
|
}
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import { useSelector } from "../../hooks/useSelector.js";
|
|
4
|
+
import { selectorTreeViewId } from "./useTreeViewId.selectors.js";
|
|
3
5
|
import { createTreeViewDefaultId } from "./useTreeViewId.utils.js";
|
|
4
6
|
export const useTreeViewId = ({
|
|
5
7
|
params,
|
|
6
|
-
|
|
7
|
-
setState
|
|
8
|
+
store
|
|
8
9
|
}) => {
|
|
9
10
|
React.useEffect(() => {
|
|
10
|
-
|
|
11
|
-
if (
|
|
11
|
+
store.update(prevState => {
|
|
12
|
+
if (params.id === prevState.id.providedTreeId && prevState.id.treeId !== undefined) {
|
|
12
13
|
return prevState;
|
|
13
14
|
}
|
|
14
15
|
return _extends({}, prevState, {
|
|
@@ -17,15 +18,12 @@ export const useTreeViewId = ({
|
|
|
17
18
|
})
|
|
18
19
|
});
|
|
19
20
|
});
|
|
20
|
-
}, [
|
|
21
|
-
const treeId =
|
|
21
|
+
}, [store, params.id]);
|
|
22
|
+
const treeId = useSelector(store, selectorTreeViewId);
|
|
22
23
|
return {
|
|
23
24
|
getRootProps: () => ({
|
|
24
25
|
id: treeId
|
|
25
|
-
})
|
|
26
|
-
contextValue: {
|
|
27
|
-
treeId
|
|
28
|
-
}
|
|
26
|
+
})
|
|
29
27
|
};
|
|
30
28
|
};
|
|
31
29
|
useTreeViewId.params = {
|
|
@@ -35,6 +33,7 @@ useTreeViewId.getInitialState = ({
|
|
|
35
33
|
id
|
|
36
34
|
}) => ({
|
|
37
35
|
id: {
|
|
38
|
-
treeId:
|
|
36
|
+
treeId: undefined,
|
|
37
|
+
providedTreeId: id
|
|
39
38
|
}
|
|
40
39
|
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { TreeViewRootSelector } from '../../utils/selectors';
|
|
2
|
+
import { UseTreeViewIdSignature } from './useTreeViewId.types';
|
|
3
|
+
/**
|
|
4
|
+
* Get the id attribute of the tree view.
|
|
5
|
+
* @param {TreeViewState<[UseTreeViewIdSignature]>} state The state of the tree view.
|
|
6
|
+
* @returns {string} The id attribute of the tree view.
|
|
7
|
+
*/
|
|
8
|
+
export declare const selectorTreeViewId: ((state: import("./useTreeViewId.types").UseTreeViewIdState & Partial<{}> & {
|
|
9
|
+
cacheKey: import("../../models").TreeViewStateCacheKey;
|
|
10
|
+
}) => string | undefined) & {
|
|
11
|
+
clearCache: () => void;
|
|
12
|
+
resultsCount: () => number;
|
|
13
|
+
resetResultsCount: () => void;
|
|
14
|
+
} & {
|
|
15
|
+
resultFunc: (resultFuncArgs_0: {
|
|
16
|
+
treeId: string | undefined;
|
|
17
|
+
providedTreeId: string | undefined;
|
|
18
|
+
}) => string | undefined;
|
|
19
|
+
memoizedResultFunc: ((resultFuncArgs_0: {
|
|
20
|
+
treeId: string | undefined;
|
|
21
|
+
providedTreeId: string | undefined;
|
|
22
|
+
}) => string | undefined) & {
|
|
23
|
+
clearCache: () => void;
|
|
24
|
+
resultsCount: () => number;
|
|
25
|
+
resetResultsCount: () => void;
|
|
26
|
+
};
|
|
27
|
+
lastResult: () => string | undefined;
|
|
28
|
+
dependencies: [TreeViewRootSelector<UseTreeViewIdSignature>];
|
|
29
|
+
recomputations: () => number;
|
|
30
|
+
resetRecomputations: () => void;
|
|
31
|
+
dependencyRecomputations: () => number;
|
|
32
|
+
resetDependencyRecomputations: () => void;
|
|
33
|
+
} & {
|
|
34
|
+
argsMemoize: typeof import("reselect").weakMapMemoize;
|
|
35
|
+
memoize: typeof import("reselect").weakMapMemoize;
|
|
36
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createSelector } from "../../utils/selectors.js";
|
|
2
|
+
const selectorTreeViewIdState = state => state.id;
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Get the id attribute of the tree view.
|
|
6
|
+
* @param {TreeViewState<[UseTreeViewIdSignature]>} state The state of the tree view.
|
|
7
|
+
* @returns {string} The id attribute of the tree view.
|
|
8
|
+
*/
|
|
9
|
+
export const selectorTreeViewId = createSelector(selectorTreeViewIdState, idState => idState.treeId);
|
|
@@ -10,15 +10,11 @@ export type UseTreeViewIdDefaultizedParameters = UseTreeViewIdParameters;
|
|
|
10
10
|
export interface UseTreeViewIdState {
|
|
11
11
|
id: {
|
|
12
12
|
treeId: string | undefined;
|
|
13
|
+
providedTreeId: string | undefined;
|
|
13
14
|
};
|
|
14
15
|
}
|
|
15
|
-
interface UseTreeViewIdContextValue {
|
|
16
|
-
treeId: string | undefined;
|
|
17
|
-
}
|
|
18
16
|
export type UseTreeViewIdSignature = TreeViewPluginSignature<{
|
|
19
17
|
params: UseTreeViewIdParameters;
|
|
20
18
|
defaultizedParams: UseTreeViewIdDefaultizedParameters;
|
|
21
19
|
state: UseTreeViewIdState;
|
|
22
|
-
contextValue: UseTreeViewIdContextValue;
|
|
23
20
|
}>;
|
|
24
|
-
export {};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { TreeViewAnyPluginSignature, TreeViewState } from '../models';
|
|
2
|
+
import { TreeViewStore } from '../utils/TreeViewStore';
|
|
3
|
+
import { TreeViewSelector } from '../utils/selectors';
|
|
4
|
+
export declare const useSelector: <TSignatures extends readonly TreeViewAnyPluginSignature[], TArgs, TValue>(store: TreeViewStore<TSignatures>, selector: TreeViewSelector<TreeViewState<TSignatures>, TArgs, TValue>, args?: TArgs, equals?: (a: TValue, b: TValue) => boolean) => TValue;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector';
|
|
2
|
+
const defaultCompare = Object.is;
|
|
3
|
+
export const useSelector = (store, selector, args = undefined, equals = defaultCompare) => {
|
|
4
|
+
const selectorWithArgs = state => selector(state, args);
|
|
5
|
+
return useSyncExternalStoreWithSelector(store.subscribe, store.getSnapshot, store.getSnapshot, selectorWithArgs, equals);
|
|
6
|
+
};
|
package/internals/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export { useTreeView } from './useTreeView';
|
|
2
2
|
export { TreeViewProvider, useTreeViewContext } from './TreeViewProvider';
|
|
3
3
|
export { RichTreeViewItems } from './components/RichTreeViewItems';
|
|
4
|
+
export type { RichTreeViewItemsSlots, RichTreeViewItemsSlotProps, } from './components/RichTreeViewItems';
|
|
4
5
|
export { unstable_resetCleanupTracking } from './hooks/useInstanceEventHandler';
|
|
5
|
-
export
|
|
6
|
+
export { useSelector } from './hooks/useSelector';
|
|
7
|
+
export type { TreeViewPlugin, TreeViewPluginSignature, ConvertPluginsIntoSignatures, MergeSignaturesProperty, TreeViewPublicAPI, TreeViewState, TreeViewExperimentalFeatures, TreeViewItemMeta, TreeViewInstance, TreeViewItemPlugin, TreeViewUsedStore, } from './models';
|
|
6
8
|
export type { TreeViewCorePluginParameters } from './corePlugins';
|
|
7
9
|
export { useTreeViewExpansion } from './plugins/useTreeViewExpansion';
|
|
8
10
|
export type { UseTreeViewExpansionSignature, UseTreeViewExpansionParameters, } from './plugins/useTreeViewExpansion';
|
|
@@ -15,9 +17,12 @@ export type { UseTreeViewKeyboardNavigationSignature } from './plugins/useTreeVi
|
|
|
15
17
|
export { useTreeViewIcons } from './plugins/useTreeViewIcons';
|
|
16
18
|
export type { UseTreeViewIconsSignature, UseTreeViewIconsParameters, } from './plugins/useTreeViewIcons';
|
|
17
19
|
export { useTreeViewItems, buildSiblingIndexes, TREE_VIEW_ROOT_PARENT_ID, } from './plugins/useTreeViewItems';
|
|
20
|
+
export { selectorItemMetaLookup, selectorItemMeta, selectorItemIndex, selectorItemOrderedChildrenIds, } from './plugins/useTreeViewItems/useTreeViewItems.selectors';
|
|
18
21
|
export type { UseTreeViewItemsSignature, UseTreeViewItemsParameters, UseTreeViewItemsState, } from './plugins/useTreeViewItems';
|
|
19
22
|
export { useTreeViewLabel } from './plugins/useTreeViewLabel';
|
|
20
23
|
export type { UseTreeViewLabelSignature, UseTreeViewLabelParameters, } from './plugins/useTreeViewLabel';
|
|
21
24
|
export { useTreeViewJSXItems } from './plugins/useTreeViewJSXItems';
|
|
22
25
|
export type { UseTreeViewJSXItemsSignature, UseTreeViewJSXItemsParameters, } from './plugins/useTreeViewJSXItems';
|
|
26
|
+
export { createSelector } from './utils/selectors';
|
|
23
27
|
export { isTargetInDescendants } from './utils/tree';
|
|
28
|
+
export { TreeViewStore } from './utils/TreeViewStore';
|
package/internals/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export { useTreeView } from "./useTreeView/index.js";
|
|
|
2
2
|
export { TreeViewProvider, useTreeViewContext } from "./TreeViewProvider/index.js";
|
|
3
3
|
export { RichTreeViewItems } from "./components/RichTreeViewItems.js";
|
|
4
4
|
export { unstable_resetCleanupTracking } from "./hooks/useInstanceEventHandler.js";
|
|
5
|
+
export { useSelector } from "./hooks/useSelector.js";
|
|
5
6
|
|
|
6
7
|
// Core plugins
|
|
7
8
|
|
|
@@ -12,6 +13,9 @@ export { useTreeViewFocus } from "./plugins/useTreeViewFocus/index.js";
|
|
|
12
13
|
export { useTreeViewKeyboardNavigation } from "./plugins/useTreeViewKeyboardNavigation/index.js";
|
|
13
14
|
export { useTreeViewIcons } from "./plugins/useTreeViewIcons/index.js";
|
|
14
15
|
export { useTreeViewItems, buildSiblingIndexes, TREE_VIEW_ROOT_PARENT_ID } from "./plugins/useTreeViewItems/index.js";
|
|
16
|
+
export { selectorItemMetaLookup, selectorItemMeta, selectorItemIndex, selectorItemOrderedChildrenIds } from "./plugins/useTreeViewItems/useTreeViewItems.selectors.js";
|
|
15
17
|
export { useTreeViewLabel } from "./plugins/useTreeViewLabel/index.js";
|
|
16
18
|
export { useTreeViewJSXItems } from "./plugins/useTreeViewJSXItems/index.js";
|
|
17
|
-
export {
|
|
19
|
+
export { createSelector } from "./utils/selectors.js";
|
|
20
|
+
export { isTargetInDescendants } from "./utils/tree.js";
|
|
21
|
+
export { TreeViewStore } from "./utils/TreeViewStore.js";
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { EventHandlers } from '@mui/utils';
|
|
3
|
-
import type { TreeItemProps } from '../../TreeItem';
|
|
4
3
|
import type { UseTreeItemContentSlotOwnProps, UseTreeItemDragAndDropOverlaySlotOwnProps, UseTreeItemLabelInputSlotOwnProps, UseTreeItemRootSlotOwnProps, UseTreeItemCheckboxSlotOwnProps, UseTreeItemStatus } from '../../useTreeItem';
|
|
5
4
|
import type { UseTreeItemInteractions } from '../../hooks/useTreeItemUtils/useTreeItemUtils';
|
|
5
|
+
import type { TreeItemProps } from '../../TreeItem/TreeItem.types';
|
|
6
6
|
export interface TreeViewItemPluginSlotPropsEnhancerParams {
|
|
7
7
|
rootRefObject: React.MutableRefObject<HTMLLIElement | null>;
|
|
8
8
|
contentRefObject: React.MutableRefObject<HTMLDivElement | null>;
|
|
@@ -36,8 +36,8 @@ export interface TreeViewItemPluginResponse {
|
|
|
36
36
|
*/
|
|
37
37
|
propsEnhancers?: TreeViewItemPluginSlotPropsEnhancers;
|
|
38
38
|
}
|
|
39
|
-
export interface TreeViewItemPluginOptions
|
|
40
|
-
props:
|
|
39
|
+
export interface TreeViewItemPluginOptions extends Omit<TreeViewItemPluginResponse, 'propsEnhancers'> {
|
|
40
|
+
props: TreeItemProps;
|
|
41
41
|
}
|
|
42
|
-
export type TreeViewItemPlugin = (options: TreeViewItemPluginOptions
|
|
42
|
+
export type TreeViewItemPlugin = (options: TreeViewItemPluginOptions) => void | TreeViewItemPluginResponse;
|
|
43
43
|
export {};
|