@mui/x-tree-view 7.0.0-beta.4 → 7.0.0-beta.6
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 +271 -61
- package/RichTreeView/RichTreeView.js +9 -0
- package/RichTreeView/RichTreeView.types.d.ts +7 -1
- package/SimpleTreeView/SimpleTreeView.js +9 -0
- package/SimpleTreeView/SimpleTreeView.types.d.ts +7 -1
- package/TreeItem/TreeItem.js +24 -28
- package/TreeItem/TreeItem.types.d.ts +7 -11
- package/TreeItem/treeItemClasses.d.ts +1 -1
- package/TreeItem/treeItemClasses.js +1 -1
- package/TreeView/TreeView.js +9 -0
- package/hooks/index.d.ts +1 -0
- package/hooks/index.js +1 -0
- package/hooks/package.json +6 -0
- package/hooks/useTreeViewApiRef.d.ts +6 -0
- package/hooks/useTreeViewApiRef.js +5 -0
- package/index.d.ts +1 -0
- package/index.js +3 -2
- package/internals/hooks/useTimeout.d.ts +5 -3
- package/internals/hooks/useTimeout.js +13 -5
- package/internals/models/helpers.d.ts +2 -0
- package/internals/models/plugin.d.ts +12 -0
- package/internals/models/treeView.d.ts +1 -0
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +40 -22
- package/internals/plugins/useTreeViewFocus/useTreeViewFocus.types.d.ts +4 -0
- package/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +20 -6
- package/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +29 -16
- package/internals/plugins/useTreeViewNodes/useTreeViewNodes.types.d.ts +16 -6
- package/internals/useTreeView/useTreeView.d.ts +2 -0
- package/internals/useTreeView/useTreeView.js +12 -0
- package/internals/useTreeView/useTreeView.types.d.ts +2 -1
- package/internals/useTreeView/useTreeView.utils.d.ts +2 -1
- package/internals/useTreeView/useTreeView.utils.js +3 -0
- package/internals/utils/extractPluginParamsFromProps.d.ts +3 -2
- package/internals/utils/extractPluginParamsFromProps.js +5 -3
- package/internals/utils/utils.d.ts +1 -0
- package/internals/utils/utils.js +10 -0
- package/modern/RichTreeView/RichTreeView.js +9 -0
- package/modern/SimpleTreeView/SimpleTreeView.js +9 -0
- package/modern/TreeItem/TreeItem.js +23 -27
- package/modern/TreeItem/treeItemClasses.js +1 -1
- package/modern/TreeView/TreeView.js +9 -0
- package/modern/hooks/index.js +1 -0
- package/modern/hooks/useTreeViewApiRef.js +5 -0
- package/modern/index.js +3 -2
- package/modern/internals/hooks/useTimeout.js +13 -5
- package/modern/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +40 -22
- package/modern/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +20 -6
- package/modern/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +29 -16
- package/modern/internals/useTreeView/useTreeView.js +12 -0
- package/modern/internals/useTreeView/useTreeView.utils.js +3 -0
- package/modern/internals/utils/extractPluginParamsFromProps.js +5 -3
- package/modern/internals/utils/utils.js +10 -0
- package/node/RichTreeView/RichTreeView.js +9 -0
- package/node/SimpleTreeView/SimpleTreeView.js +9 -0
- package/node/TreeItem/TreeItem.js +23 -27
- package/node/TreeItem/treeItemClasses.js +1 -1
- package/node/TreeView/TreeView.js +9 -0
- package/node/hooks/index.js +12 -0
- package/node/hooks/useTreeViewApiRef.js +14 -0
- package/node/index.js +13 -1
- package/node/internals/hooks/useTimeout.js +13 -4
- package/node/internals/plugins/useTreeViewFocus/useTreeViewFocus.js +39 -21
- package/node/internals/plugins/useTreeViewJSXNodes/useTreeViewJSXNodes.js +20 -6
- package/node/internals/plugins/useTreeViewNodes/useTreeViewNodes.js +28 -15
- package/node/internals/useTreeView/useTreeView.js +13 -0
- package/node/internals/useTreeView/useTreeView.utils.js +6 -2
- package/node/internals/utils/extractPluginParamsFromProps.js +5 -3
- package/node/internals/utils/utils.js +17 -0
- package/package.json +2 -2
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import useEventCallback from '@mui/utils/useEventCallback';
|
|
4
|
-
import { populateInstance } from '../../useTreeView/useTreeView.utils';
|
|
4
|
+
import { populateInstance, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
|
|
5
5
|
import { publishTreeViewEvent } from '../../utils/publishTreeViewEvent';
|
|
6
|
-
const
|
|
6
|
+
const updateNodesState = ({
|
|
7
7
|
items,
|
|
8
8
|
isItemDisabled,
|
|
9
9
|
getItemLabel,
|
|
10
10
|
getItemId
|
|
11
11
|
}) => {
|
|
12
12
|
const nodeMap = {};
|
|
13
|
+
const itemMap = {};
|
|
13
14
|
const processItem = (item, index, parentId) => {
|
|
14
15
|
var _item$children, _item$children2;
|
|
15
16
|
const id = getItemId ? getItemId(item) : item.id;
|
|
@@ -28,10 +29,11 @@ const updateState = ({
|
|
|
28
29
|
label,
|
|
29
30
|
index,
|
|
30
31
|
parentId,
|
|
31
|
-
idAttribute:
|
|
32
|
+
idAttribute: undefined,
|
|
32
33
|
expandable: !!((_item$children = item.children) != null && _item$children.length),
|
|
33
34
|
disabled: isItemDisabled ? isItemDisabled(item) : false
|
|
34
35
|
};
|
|
36
|
+
itemMap[id] = item;
|
|
35
37
|
return {
|
|
36
38
|
id,
|
|
37
39
|
children: (_item$children2 = item.children) == null ? void 0 : _item$children2.map((child, childIndex) => processItem(child, childIndex, id))
|
|
@@ -40,16 +42,19 @@ const updateState = ({
|
|
|
40
42
|
const nodeTree = items.map((item, itemIndex) => processItem(item, itemIndex, null));
|
|
41
43
|
return {
|
|
42
44
|
nodeMap,
|
|
43
|
-
nodeTree
|
|
45
|
+
nodeTree,
|
|
46
|
+
itemMap
|
|
44
47
|
};
|
|
45
48
|
};
|
|
46
49
|
export const useTreeViewNodes = ({
|
|
47
50
|
instance,
|
|
51
|
+
publicAPI,
|
|
48
52
|
params,
|
|
49
53
|
state,
|
|
50
54
|
setState
|
|
51
55
|
}) => {
|
|
52
|
-
const getNode = React.useCallback(nodeId => state.nodeMap[nodeId], [state.nodeMap]);
|
|
56
|
+
const getNode = React.useCallback(nodeId => state.nodes.nodeMap[nodeId], [state.nodes.nodeMap]);
|
|
57
|
+
const getItem = React.useCallback(nodeId => state.nodes.itemMap[nodeId], [state.nodes.itemMap]);
|
|
53
58
|
const isNodeDisabled = React.useCallback(nodeId => {
|
|
54
59
|
if (nodeId == null) {
|
|
55
60
|
return false;
|
|
@@ -71,7 +76,7 @@ export const useTreeViewNodes = ({
|
|
|
71
76
|
}
|
|
72
77
|
return false;
|
|
73
78
|
}, [instance]);
|
|
74
|
-
const getChildrenIds = useEventCallback(nodeId => Object.values(state.nodeMap).filter(node => node.parentId === nodeId).sort((a, b) => a.index - b.index).map(child => child.id));
|
|
79
|
+
const getChildrenIds = useEventCallback(nodeId => Object.values(state.nodes.nodeMap).filter(node => node.parentId === nodeId).sort((a, b) => a.index - b.index).map(child => child.id));
|
|
75
80
|
const getNavigableChildrenIds = nodeId => {
|
|
76
81
|
let childrenIds = instance.getChildrenIds(nodeId);
|
|
77
82
|
if (!params.disabledItemsFocusable) {
|
|
@@ -81,20 +86,22 @@ export const useTreeViewNodes = ({
|
|
|
81
86
|
};
|
|
82
87
|
React.useEffect(() => {
|
|
83
88
|
setState(prevState => {
|
|
84
|
-
const newState =
|
|
89
|
+
const newState = updateNodesState({
|
|
85
90
|
items: params.items,
|
|
86
91
|
isItemDisabled: params.isItemDisabled,
|
|
87
92
|
getItemId: params.getItemId,
|
|
88
93
|
getItemLabel: params.getItemLabel
|
|
89
94
|
});
|
|
90
|
-
Object.values(prevState.nodeMap).forEach(node => {
|
|
95
|
+
Object.values(prevState.nodes.nodeMap).forEach(node => {
|
|
91
96
|
if (!newState.nodeMap[node.id]) {
|
|
92
97
|
publishTreeViewEvent(instance, 'removeNode', {
|
|
93
98
|
id: node.id
|
|
94
99
|
});
|
|
95
100
|
}
|
|
96
101
|
});
|
|
97
|
-
return _extends({}, prevState,
|
|
102
|
+
return _extends({}, prevState, {
|
|
103
|
+
nodes: newState
|
|
104
|
+
});
|
|
98
105
|
});
|
|
99
106
|
}, [instance, setState, params.items, params.isItemDisabled, params.getItemId, params.getItemLabel]);
|
|
100
107
|
const getNodesToRender = useEventCallback(() => {
|
|
@@ -102,7 +109,7 @@ export const useTreeViewNodes = ({
|
|
|
102
109
|
id,
|
|
103
110
|
children
|
|
104
111
|
}) => {
|
|
105
|
-
const node = state.nodeMap[id];
|
|
112
|
+
const node = state.nodes.nodeMap[id];
|
|
106
113
|
return {
|
|
107
114
|
label: node.label,
|
|
108
115
|
nodeId: node.id,
|
|
@@ -110,26 +117,32 @@ export const useTreeViewNodes = ({
|
|
|
110
117
|
children: children == null ? void 0 : children.map(getPropsFromNodeId)
|
|
111
118
|
};
|
|
112
119
|
};
|
|
113
|
-
return state.nodeTree.map(getPropsFromNodeId);
|
|
120
|
+
return state.nodes.nodeTree.map(getPropsFromNodeId);
|
|
114
121
|
});
|
|
115
122
|
populateInstance(instance, {
|
|
116
123
|
getNode,
|
|
124
|
+
getItem,
|
|
117
125
|
getNodesToRender,
|
|
118
126
|
getChildrenIds,
|
|
119
127
|
getNavigableChildrenIds,
|
|
120
128
|
isNodeDisabled
|
|
121
129
|
});
|
|
130
|
+
populatePublicAPI(publicAPI, {
|
|
131
|
+
getItem
|
|
132
|
+
});
|
|
122
133
|
return {
|
|
123
134
|
contextValue: {
|
|
124
135
|
disabledItemsFocusable: params.disabledItemsFocusable
|
|
125
136
|
}
|
|
126
137
|
};
|
|
127
138
|
};
|
|
128
|
-
useTreeViewNodes.getInitialState = params =>
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
139
|
+
useTreeViewNodes.getInitialState = params => ({
|
|
140
|
+
nodes: updateNodesState({
|
|
141
|
+
items: params.items,
|
|
142
|
+
isItemDisabled: params.isItemDisabled,
|
|
143
|
+
getItemId: params.getItemId,
|
|
144
|
+
getItemLabel: params.getItemLabel
|
|
145
|
+
})
|
|
133
146
|
});
|
|
134
147
|
useTreeViewNodes.getDefaultizedParams = params => {
|
|
135
148
|
var _params$disabledItems;
|
|
@@ -6,13 +6,16 @@ interface TreeViewNodeProps {
|
|
|
6
6
|
id: string | undefined;
|
|
7
7
|
children?: TreeViewNodeProps[];
|
|
8
8
|
}
|
|
9
|
-
export interface UseTreeViewNodesInstance {
|
|
9
|
+
export interface UseTreeViewNodesInstance<R extends {}> {
|
|
10
10
|
getNode: (nodeId: string) => TreeViewNode;
|
|
11
|
+
getItem: (nodeId: string) => R;
|
|
11
12
|
getNodesToRender: () => TreeViewNodeProps[];
|
|
12
13
|
getChildrenIds: (nodeId: string | null) => string[];
|
|
13
14
|
getNavigableChildrenIds: (nodeId: string | null) => string[];
|
|
14
15
|
isNodeDisabled: (nodeId: string | null) => nodeId is string;
|
|
15
16
|
}
|
|
17
|
+
export interface UseTreeViewNodesPublicAPI<R extends {}> extends Pick<UseTreeViewNodesInstance<R>, 'getItem'> {
|
|
18
|
+
}
|
|
16
19
|
export interface UseTreeViewNodesParameters<R extends {}> {
|
|
17
20
|
/**
|
|
18
21
|
* If `true`, will allow focus on disabled items.
|
|
@@ -58,21 +61,28 @@ export interface TreeViewNodeIdAndChildren {
|
|
|
58
61
|
id: TreeViewItemId;
|
|
59
62
|
children?: TreeViewNodeIdAndChildren[];
|
|
60
63
|
}
|
|
61
|
-
export interface UseTreeViewNodesState {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
+
export interface UseTreeViewNodesState<R extends {}> {
|
|
65
|
+
nodes: {
|
|
66
|
+
nodeTree: TreeViewNodeIdAndChildren[];
|
|
67
|
+
nodeMap: TreeViewNodeMap;
|
|
68
|
+
itemMap: TreeViewItemMap<R>;
|
|
69
|
+
};
|
|
64
70
|
}
|
|
65
71
|
interface UseTreeViewNodesContextValue extends Pick<UseTreeViewNodesDefaultizedParameters<any>, 'disabledItemsFocusable'> {
|
|
66
72
|
}
|
|
67
73
|
export type UseTreeViewNodesSignature = TreeViewPluginSignature<{
|
|
68
74
|
params: UseTreeViewNodesParameters<any>;
|
|
69
75
|
defaultizedParams: UseTreeViewNodesDefaultizedParameters<any>;
|
|
70
|
-
instance: UseTreeViewNodesInstance
|
|
76
|
+
instance: UseTreeViewNodesInstance<any>;
|
|
77
|
+
publicAPI: UseTreeViewNodesPublicAPI<any>;
|
|
71
78
|
events: UseTreeViewNodesEventLookup;
|
|
72
|
-
state: UseTreeViewNodesState
|
|
79
|
+
state: UseTreeViewNodesState<any>;
|
|
73
80
|
contextValue: UseTreeViewNodesContextValue;
|
|
74
81
|
}>;
|
|
75
82
|
export type TreeViewNodeMap = {
|
|
76
83
|
[nodeId: string]: TreeViewNode;
|
|
77
84
|
};
|
|
85
|
+
export type TreeViewItemMap<R extends {}> = {
|
|
86
|
+
[nodeId: string]: R;
|
|
87
|
+
};
|
|
78
88
|
export {};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
1
2
|
import { TreeViewAnyPluginSignature, TreeViewPlugin, ConvertPluginsIntoSignatures } from '../models';
|
|
2
3
|
import { UseTreeViewParameters, UseTreeViewReturnValue } from './useTreeView.types';
|
|
4
|
+
export declare function useTreeViewApiInitialization<T>(inputApiRef: React.MutableRefObject<T> | undefined): T;
|
|
3
5
|
export declare const useTreeView: <Plugins extends readonly TreeViewPlugin<TreeViewAnyPluginSignature>[]>(inParams: UseTreeViewParameters<Plugins>) => UseTreeViewReturnValue<ConvertPluginsIntoSignatures<Plugins>>;
|
|
@@ -3,6 +3,16 @@ import * as React from 'react';
|
|
|
3
3
|
import useForkRef from '@mui/utils/useForkRef';
|
|
4
4
|
import { useTreeViewModels } from './useTreeViewModels';
|
|
5
5
|
import { TREE_VIEW_CORE_PLUGINS } from '../corePlugins';
|
|
6
|
+
export function useTreeViewApiInitialization(inputApiRef) {
|
|
7
|
+
const fallbackPublicApiRef = React.useRef({});
|
|
8
|
+
if (inputApiRef) {
|
|
9
|
+
if (inputApiRef.current == null) {
|
|
10
|
+
inputApiRef.current = {};
|
|
11
|
+
}
|
|
12
|
+
return inputApiRef.current;
|
|
13
|
+
}
|
|
14
|
+
return fallbackPublicApiRef.current;
|
|
15
|
+
}
|
|
6
16
|
export const useTreeView = inParams => {
|
|
7
17
|
const plugins = [...TREE_VIEW_CORE_PLUGINS, ...inParams.plugins];
|
|
8
18
|
const params = plugins.reduce((acc, plugin) => {
|
|
@@ -14,6 +24,7 @@ export const useTreeView = inParams => {
|
|
|
14
24
|
const models = useTreeViewModels(plugins, params);
|
|
15
25
|
const instanceRef = React.useRef({});
|
|
16
26
|
const instance = instanceRef.current;
|
|
27
|
+
const publicAPI = useTreeViewApiInitialization(inParams.apiRef);
|
|
17
28
|
const innerRootRef = React.useRef(null);
|
|
18
29
|
const handleRootRef = useForkRef(innerRootRef, inParams.rootRef);
|
|
19
30
|
const [state, setState] = React.useState(() => {
|
|
@@ -32,6 +43,7 @@ export const useTreeView = inParams => {
|
|
|
32
43
|
const runPlugin = plugin => {
|
|
33
44
|
const pluginResponse = plugin({
|
|
34
45
|
instance,
|
|
46
|
+
publicAPI,
|
|
35
47
|
params,
|
|
36
48
|
slots: params.slots,
|
|
37
49
|
slotProps: params.slotProps,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { EventHandlers } from '@mui/base/utils';
|
|
3
3
|
import type { TreeViewContextValue } from '../TreeViewProvider';
|
|
4
|
-
import { TreeViewAnyPluginSignature, TreeViewPlugin, ConvertPluginsIntoSignatures, MergePluginsProperty, TreeViewInstance } from '../models';
|
|
4
|
+
import { TreeViewAnyPluginSignature, TreeViewPlugin, ConvertPluginsIntoSignatures, MergePluginsProperty, TreeViewInstance, TreeViewPublicAPI } from '../models';
|
|
5
5
|
export type UseTreeViewParameters<TPlugins extends readonly TreeViewPlugin<TreeViewAnyPluginSignature>[]> = UseTreeViewBaseParameters<TPlugins> & MergePluginsProperty<ConvertPluginsIntoSignatures<TPlugins>, 'params'>;
|
|
6
6
|
export interface UseTreeViewBaseParameters<TPlugins extends readonly TreeViewPlugin<TreeViewAnyPluginSignature>[]> {
|
|
7
|
+
apiRef: React.MutableRefObject<TreeViewPublicAPI<ConvertPluginsIntoSignatures<TPlugins>>> | undefined;
|
|
7
8
|
rootRef?: React.Ref<HTMLUListElement> | undefined;
|
|
8
9
|
plugins: TPlugins;
|
|
9
10
|
slots: MergePluginsProperty<ConvertPluginsIntoSignatures<TPlugins>, 'slots'>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TreeViewAnyPluginSignature, TreeViewInstance, TreeViewUsedInstance } from '../models';
|
|
1
|
+
import { TreeViewAnyPluginSignature, TreeViewInstance, TreeViewUsedInstance, TreeViewUsedPublicAPI } from '../models';
|
|
2
2
|
import type { UseTreeViewExpansionSignature } from '../plugins/useTreeViewExpansion';
|
|
3
3
|
import type { UseTreeViewNodesSignature } from '../plugins/useTreeViewNodes';
|
|
4
4
|
export declare const getPreviousNode: (instance: TreeViewInstance<[UseTreeViewNodesSignature, UseTreeViewExpansionSignature]>, nodeId: string) => string | null;
|
|
@@ -6,3 +6,4 @@ export declare const getNextNode: (instance: TreeViewInstance<[UseTreeViewExpans
|
|
|
6
6
|
export declare const getLastNode: (instance: TreeViewInstance<[UseTreeViewExpansionSignature, UseTreeViewNodesSignature]>) => string;
|
|
7
7
|
export declare const getFirstNode: (instance: TreeViewInstance<[UseTreeViewNodesSignature]>) => string;
|
|
8
8
|
export declare const populateInstance: <T extends TreeViewAnyPluginSignature>(instance: TreeViewUsedInstance<T>, methods: T["instance"]) => void;
|
|
9
|
+
export declare const populatePublicAPI: <T extends TreeViewAnyPluginSignature>(publicAPI: TreeViewUsedPublicAPI<T>, methods: T["publicAPI"]) => void;
|
|
@@ -40,4 +40,7 @@ export const getLastNode = instance => {
|
|
|
40
40
|
export const getFirstNode = instance => instance.getNavigableChildrenIds(null)[0];
|
|
41
41
|
export const populateInstance = (instance, methods) => {
|
|
42
42
|
Object.assign(instance, methods);
|
|
43
|
+
};
|
|
44
|
+
export const populatePublicAPI = (publicAPI, methods) => {
|
|
45
|
+
Object.assign(publicAPI, methods);
|
|
43
46
|
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { ConvertPluginsIntoSignatures, MergePluginsProperty, TreeViewPlugin } from '../models';
|
|
2
|
+
import { ConvertPluginsIntoSignatures, MergePluginsProperty, TreeViewPlugin, TreeViewPublicAPI } from '../models';
|
|
3
3
|
import { UseTreeViewBaseParameters } from '../useTreeView/useTreeView.types';
|
|
4
4
|
export declare const extractPluginParamsFromProps: <TPlugins extends readonly TreeViewPlugin<any>[], TSlots extends MergePluginsProperty<TPlugins, "slots">, TSlotProps extends MergePluginsProperty<TPlugins, "slotProps">, TProps extends {
|
|
5
5
|
slots?: TSlots | undefined;
|
|
6
6
|
slotProps?: TSlotProps | undefined;
|
|
7
|
-
|
|
7
|
+
apiRef?: React.MutableRefObject<TreeViewPublicAPI<ConvertPluginsIntoSignatures<TPlugins>> | undefined> | undefined;
|
|
8
|
+
}>({ props: { slots, slotProps, apiRef, ...props }, plugins, rootRef, }: {
|
|
8
9
|
props: TProps;
|
|
9
10
|
plugins: TPlugins;
|
|
10
11
|
rootRef?: React.Ref<HTMLUListElement> | undefined;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
2
|
-
const _excluded = ["slots", "slotProps"];
|
|
2
|
+
const _excluded = ["slots", "slotProps", "apiRef"];
|
|
3
3
|
export const extractPluginParamsFromProps = _ref => {
|
|
4
4
|
let {
|
|
5
5
|
props: {
|
|
6
6
|
slots,
|
|
7
|
-
slotProps
|
|
7
|
+
slotProps,
|
|
8
|
+
apiRef
|
|
8
9
|
},
|
|
9
10
|
plugins,
|
|
10
11
|
rootRef
|
|
@@ -18,7 +19,8 @@ export const extractPluginParamsFromProps = _ref => {
|
|
|
18
19
|
plugins,
|
|
19
20
|
rootRef,
|
|
20
21
|
slots: slots != null ? slots : {},
|
|
21
|
-
slotProps: slotProps != null ? slotProps : {}
|
|
22
|
+
slotProps: slotProps != null ? slotProps : {},
|
|
23
|
+
apiRef
|
|
22
24
|
};
|
|
23
25
|
const otherProps = {};
|
|
24
26
|
Object.keys(props).forEach(propName => {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getActiveElement: (root?: Document | ShadowRoot) => Element | null;
|
|
@@ -132,6 +132,15 @@ process.env.NODE_ENV !== "production" ? RichTreeView.propTypes = {
|
|
|
132
132
|
// | These PropTypes are generated from the TypeScript type definitions |
|
|
133
133
|
// | To update them edit the TypeScript types and run "yarn proptypes" |
|
|
134
134
|
// ----------------------------------------------------------------------
|
|
135
|
+
/**
|
|
136
|
+
* The ref object that allows Tree View manipulation. Can be instantiated with `useTreeViewApiRef()`.
|
|
137
|
+
*/
|
|
138
|
+
apiRef: PropTypes.shape({
|
|
139
|
+
current: PropTypes.shape({
|
|
140
|
+
focusNode: PropTypes.func.isRequired,
|
|
141
|
+
getItem: PropTypes.func.isRequired
|
|
142
|
+
})
|
|
143
|
+
}),
|
|
135
144
|
/**
|
|
136
145
|
* Override or extend the styles applied to the component.
|
|
137
146
|
*/
|
|
@@ -90,6 +90,15 @@ process.env.NODE_ENV !== "production" ? SimpleTreeView.propTypes = {
|
|
|
90
90
|
// | These PropTypes are generated from the TypeScript type definitions |
|
|
91
91
|
// | To update them edit the TypeScript types and run "yarn proptypes" |
|
|
92
92
|
// ----------------------------------------------------------------------
|
|
93
|
+
/**
|
|
94
|
+
* The ref object that allows Tree View manipulation. Can be instantiated with `useTreeViewApiRef()`.
|
|
95
|
+
*/
|
|
96
|
+
apiRef: PropTypes.shape({
|
|
97
|
+
current: PropTypes.shape({
|
|
98
|
+
focusNode: PropTypes.func.isRequired,
|
|
99
|
+
getItem: PropTypes.func.isRequired
|
|
100
|
+
})
|
|
101
|
+
}),
|
|
93
102
|
/**
|
|
94
103
|
* The content of the component.
|
|
95
104
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
2
2
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
3
|
-
const _excluded = ["children", "className", "slots", "slotProps", "ContentComponent", "ContentProps", "nodeId", "id", "label", "onClick", "onMouseDown"
|
|
3
|
+
const _excluded = ["children", "className", "slots", "slotProps", "ContentComponent", "ContentProps", "nodeId", "id", "label", "onClick", "onMouseDown"],
|
|
4
4
|
_excluded2 = ["ownerState"],
|
|
5
5
|
_excluded3 = ["ownerState"],
|
|
6
6
|
_excluded4 = ["ownerState"];
|
|
@@ -32,7 +32,7 @@ const useUtilityClasses = ownerState => {
|
|
|
32
32
|
disabled: ['disabled'],
|
|
33
33
|
iconContainer: ['iconContainer'],
|
|
34
34
|
label: ['label'],
|
|
35
|
-
|
|
35
|
+
groupTransition: ['groupTransition']
|
|
36
36
|
};
|
|
37
37
|
return composeClasses(slots, getTreeItemUtilityClass, classes);
|
|
38
38
|
};
|
|
@@ -116,8 +116,8 @@ const StyledTreeItemContent = styled(TreeItemContent, {
|
|
|
116
116
|
}));
|
|
117
117
|
const TreeItemGroup = styled(Collapse, {
|
|
118
118
|
name: 'MuiTreeItem',
|
|
119
|
-
slot: '
|
|
120
|
-
overridesResolver: (props, styles) => styles.
|
|
119
|
+
slot: 'GroupTransition',
|
|
120
|
+
overridesResolver: (props, styles) => styles.groupTransition
|
|
121
121
|
})({
|
|
122
122
|
margin: 0,
|
|
123
123
|
padding: 0,
|
|
@@ -167,16 +167,15 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
|
|
|
167
167
|
id,
|
|
168
168
|
label,
|
|
169
169
|
onClick,
|
|
170
|
-
onMouseDown
|
|
171
|
-
TransitionComponent = Collapse,
|
|
172
|
-
TransitionProps
|
|
170
|
+
onMouseDown
|
|
173
171
|
} = props,
|
|
174
172
|
other = _objectWithoutPropertiesLoose(props, _excluded);
|
|
175
173
|
const slots = {
|
|
176
174
|
expandIcon: inSlots?.expandIcon ?? contextIcons.slots.expandIcon ?? TreeViewExpandIcon,
|
|
177
175
|
collapseIcon: inSlots?.collapseIcon ?? contextIcons.slots.collapseIcon ?? TreeViewCollapseIcon,
|
|
178
176
|
endIcon: inSlots?.endIcon ?? contextIcons.slots.endIcon,
|
|
179
|
-
icon: inSlots?.icon
|
|
177
|
+
icon: inSlots?.icon,
|
|
178
|
+
groupTransition: inSlots?.groupTransition
|
|
180
179
|
};
|
|
181
180
|
const isExpandable = reactChildren => {
|
|
182
181
|
if (Array.isArray(reactChildren)) {
|
|
@@ -196,6 +195,19 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
|
|
|
196
195
|
disabled
|
|
197
196
|
});
|
|
198
197
|
const classes = useUtilityClasses(ownerState);
|
|
198
|
+
const GroupTransition = slots.groupTransition ?? undefined;
|
|
199
|
+
const groupTransitionProps = useSlotProps({
|
|
200
|
+
elementType: GroupTransition,
|
|
201
|
+
ownerState: {},
|
|
202
|
+
externalSlotProps: inSlotProps?.groupTransition,
|
|
203
|
+
additionalProps: {
|
|
204
|
+
unmountOnExit: true,
|
|
205
|
+
in: expanded,
|
|
206
|
+
component: 'ul',
|
|
207
|
+
role: 'group'
|
|
208
|
+
},
|
|
209
|
+
className: classes.groupTransition
|
|
210
|
+
});
|
|
199
211
|
const ExpansionIcon = expanded ? slots.collapseIcon : slots.expandIcon;
|
|
200
212
|
const _useSlotProps = useSlotProps({
|
|
201
213
|
elementType: ExpansionIcon,
|
|
@@ -285,13 +297,8 @@ export const TreeItem = /*#__PURE__*/React.forwardRef(function TreeItem(inProps,
|
|
|
285
297
|
displayIcon: displayIcon,
|
|
286
298
|
ownerState: ownerState
|
|
287
299
|
}, ContentProps)), children && /*#__PURE__*/_jsx(TreeItemGroup, _extends({
|
|
288
|
-
as:
|
|
289
|
-
|
|
290
|
-
className: classes.group,
|
|
291
|
-
in: expanded,
|
|
292
|
-
component: "ul",
|
|
293
|
-
role: "group"
|
|
294
|
-
}, TransitionProps, {
|
|
300
|
+
as: GroupTransition
|
|
301
|
+
}, groupTransitionProps, {
|
|
295
302
|
children: children
|
|
296
303
|
}))]
|
|
297
304
|
}));
|
|
@@ -351,16 +358,5 @@ TreeItem.propTypes = {
|
|
|
351
358
|
/**
|
|
352
359
|
* The system prop that allows defining system overrides as well as additional CSS styles.
|
|
353
360
|
*/
|
|
354
|
-
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
|
|
355
|
-
/**
|
|
356
|
-
* The component used for the transition.
|
|
357
|
-
* [Follow this guide](/material-ui/transitions/#transitioncomponent-prop) to learn more about the requirements for this component.
|
|
358
|
-
* @default Collapse
|
|
359
|
-
*/
|
|
360
|
-
TransitionComponent: PropTypes.elementType,
|
|
361
|
-
/**
|
|
362
|
-
* Props applied to the transition element.
|
|
363
|
-
* By default, the element is based on this [`Transition`](https://reactcommunity.org/react-transition-group/transition/) component.
|
|
364
|
-
*/
|
|
365
|
-
TransitionProps: PropTypes.object
|
|
361
|
+
sx: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), PropTypes.func, PropTypes.object])
|
|
366
362
|
};
|
|
@@ -3,4 +3,4 @@ import generateUtilityClasses from '@mui/utils/generateUtilityClasses';
|
|
|
3
3
|
export function getTreeItemUtilityClass(slot) {
|
|
4
4
|
return generateUtilityClass('MuiTreeItem', slot);
|
|
5
5
|
}
|
|
6
|
-
export const treeItemClasses = generateUtilityClasses('MuiTreeItem', ['root', '
|
|
6
|
+
export const treeItemClasses = generateUtilityClasses('MuiTreeItem', ['root', 'groupTransition', 'content', 'expanded', 'selected', 'focused', 'disabled', 'iconContainer', 'label']);
|
|
@@ -64,6 +64,15 @@ process.env.NODE_ENV !== "production" ? TreeView.propTypes = {
|
|
|
64
64
|
// | These PropTypes are generated from the TypeScript type definitions |
|
|
65
65
|
// | To update them edit the TypeScript types and run "yarn proptypes" |
|
|
66
66
|
// ----------------------------------------------------------------------
|
|
67
|
+
/**
|
|
68
|
+
* The ref object that allows Tree View manipulation. Can be instantiated with `useTreeViewApiRef()`.
|
|
69
|
+
*/
|
|
70
|
+
apiRef: PropTypes.shape({
|
|
71
|
+
current: PropTypes.shape({
|
|
72
|
+
focusNode: PropTypes.func.isRequired,
|
|
73
|
+
getItem: PropTypes.func.isRequired
|
|
74
|
+
})
|
|
75
|
+
}),
|
|
67
76
|
/**
|
|
68
77
|
* The content of the component.
|
|
69
78
|
*/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useTreeViewApiRef } from './useTreeViewApiRef';
|
package/modern/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @mui/x-tree-view v7.0.0-beta.
|
|
2
|
+
* @mui/x-tree-view v7.0.0-beta.6
|
|
3
3
|
*
|
|
4
4
|
* @license MIT
|
|
5
5
|
* This source code is licensed under the MIT license found in the
|
|
@@ -11,4 +11,5 @@ export * from './SimpleTreeView';
|
|
|
11
11
|
export * from './RichTreeView';
|
|
12
12
|
export { unstable_resetCleanupTracking } from './internals/hooks/useInstanceEventHandler';
|
|
13
13
|
export * from './models';
|
|
14
|
-
export * from './icons';
|
|
14
|
+
export * from './icons';
|
|
15
|
+
export * from './hooks';
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
1
3
|
import { useLazyRef } from './useLazyRef';
|
|
2
4
|
import { useOnMount } from './useOnMount';
|
|
3
|
-
class Timeout {
|
|
5
|
+
export class Timeout {
|
|
4
6
|
constructor() {
|
|
5
|
-
this.currentId =
|
|
7
|
+
this.currentId = null;
|
|
6
8
|
this.clear = () => {
|
|
7
|
-
if (this.currentId !==
|
|
9
|
+
if (this.currentId !== null) {
|
|
8
10
|
clearTimeout(this.currentId);
|
|
9
|
-
this.currentId =
|
|
11
|
+
this.currentId = null;
|
|
10
12
|
}
|
|
11
13
|
};
|
|
12
14
|
this.disposeEffect = () => {
|
|
@@ -16,9 +18,15 @@ class Timeout {
|
|
|
16
18
|
static create() {
|
|
17
19
|
return new Timeout();
|
|
18
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Executes `fn` after `delay`, clearing any previously scheduled call.
|
|
23
|
+
*/
|
|
19
24
|
start(delay, fn) {
|
|
20
25
|
this.clear();
|
|
21
|
-
this.currentId = setTimeout(
|
|
26
|
+
this.currentId = setTimeout(() => {
|
|
27
|
+
this.currentId = null;
|
|
28
|
+
fn();
|
|
29
|
+
}, delay);
|
|
22
30
|
}
|
|
23
31
|
}
|
|
24
32
|
export function useTimeout() {
|
|
@@ -2,10 +2,12 @@ import _extends from "@babel/runtime/helpers/esm/extends";
|
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import useEventCallback from '@mui/utils/useEventCallback';
|
|
4
4
|
import ownerDocument from '@mui/utils/ownerDocument';
|
|
5
|
-
import { populateInstance } from '../../useTreeView/useTreeView.utils';
|
|
5
|
+
import { populateInstance, populatePublicAPI } from '../../useTreeView/useTreeView.utils';
|
|
6
6
|
import { useInstanceEventHandler } from '../../hooks/useInstanceEventHandler';
|
|
7
|
+
import { getActiveElement } from '../../utils/utils';
|
|
7
8
|
export const useTreeViewFocus = ({
|
|
8
9
|
instance,
|
|
10
|
+
publicAPI,
|
|
9
11
|
params,
|
|
10
12
|
state,
|
|
11
13
|
setState,
|
|
@@ -14,19 +16,45 @@ export const useTreeViewFocus = ({
|
|
|
14
16
|
}) => {
|
|
15
17
|
const setFocusedNodeId = useEventCallback(nodeId => {
|
|
16
18
|
const cleanNodeId = typeof nodeId === 'function' ? nodeId(state.focusedNodeId) : nodeId;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
if (state.focusedNodeId !== cleanNodeId) {
|
|
20
|
+
setState(prevState => _extends({}, prevState, {
|
|
21
|
+
focusedNodeId: cleanNodeId
|
|
22
|
+
}));
|
|
23
|
+
}
|
|
20
24
|
});
|
|
21
|
-
const
|
|
25
|
+
const isTreeViewFocused = React.useCallback(() => !!rootRef.current && rootRef.current === getActiveElement(ownerDocument(rootRef.current)), [rootRef]);
|
|
26
|
+
const isNodeFocused = React.useCallback(nodeId => state.focusedNodeId === nodeId && isTreeViewFocused(), [state.focusedNodeId, isTreeViewFocused]);
|
|
27
|
+
const isNodeVisible = nodeId => {
|
|
28
|
+
const node = instance.getNode(nodeId);
|
|
29
|
+
return node && (node.parentId == null || instance.isNodeExpanded(node.parentId));
|
|
30
|
+
};
|
|
22
31
|
const focusNode = useEventCallback((event, nodeId) => {
|
|
23
|
-
if
|
|
32
|
+
// if we receive a nodeId, and it is visible, the focus will be set to it
|
|
33
|
+
if (nodeId && isNodeVisible(nodeId)) {
|
|
34
|
+
if (!isTreeViewFocused()) {
|
|
35
|
+
instance.focusRoot();
|
|
36
|
+
}
|
|
24
37
|
setFocusedNodeId(nodeId);
|
|
25
38
|
if (params.onNodeFocus) {
|
|
26
39
|
params.onNodeFocus(event, nodeId);
|
|
27
40
|
}
|
|
28
41
|
}
|
|
29
42
|
});
|
|
43
|
+
const focusDefaultNode = useEventCallback(event => {
|
|
44
|
+
let nodeToFocusId;
|
|
45
|
+
if (Array.isArray(models.selectedNodes.value)) {
|
|
46
|
+
nodeToFocusId = models.selectedNodes.value.find(isNodeVisible);
|
|
47
|
+
} else if (models.selectedNodes.value != null && isNodeVisible(models.selectedNodes.value)) {
|
|
48
|
+
nodeToFocusId = models.selectedNodes.value;
|
|
49
|
+
}
|
|
50
|
+
if (nodeToFocusId == null) {
|
|
51
|
+
nodeToFocusId = instance.getNavigableChildrenIds(null)[0];
|
|
52
|
+
}
|
|
53
|
+
setFocusedNodeId(nodeToFocusId);
|
|
54
|
+
if (params.onNodeFocus) {
|
|
55
|
+
params.onNodeFocus(event, nodeToFocusId);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
30
58
|
const focusRoot = useEventCallback(() => {
|
|
31
59
|
rootRef.current?.focus({
|
|
32
60
|
preventScroll: true
|
|
@@ -35,7 +63,11 @@ export const useTreeViewFocus = ({
|
|
|
35
63
|
populateInstance(instance, {
|
|
36
64
|
isNodeFocused,
|
|
37
65
|
focusNode,
|
|
38
|
-
focusRoot
|
|
66
|
+
focusRoot,
|
|
67
|
+
focusDefaultNode
|
|
68
|
+
});
|
|
69
|
+
populatePublicAPI(publicAPI, {
|
|
70
|
+
focusNode
|
|
39
71
|
});
|
|
40
72
|
useInstanceEventHandler(instance, 'removeNode', ({
|
|
41
73
|
id
|
|
@@ -49,23 +81,9 @@ export const useTreeViewFocus = ({
|
|
|
49
81
|
});
|
|
50
82
|
const createHandleFocus = otherHandlers => event => {
|
|
51
83
|
otherHandlers.onFocus?.(event);
|
|
52
|
-
|
|
53
84
|
// if the event bubbled (which is React specific) we don't want to steal focus
|
|
54
85
|
if (event.target === event.currentTarget) {
|
|
55
|
-
|
|
56
|
-
const node = instance.getNode(nodeId);
|
|
57
|
-
return node && (node.parentId == null || instance.isNodeExpanded(node.parentId));
|
|
58
|
-
};
|
|
59
|
-
let nodeToFocusId;
|
|
60
|
-
if (Array.isArray(models.selectedNodes.value)) {
|
|
61
|
-
nodeToFocusId = models.selectedNodes.value.find(isNodeVisible);
|
|
62
|
-
} else if (models.selectedNodes.value != null && isNodeVisible(models.selectedNodes.value)) {
|
|
63
|
-
nodeToFocusId = models.selectedNodes.value;
|
|
64
|
-
}
|
|
65
|
-
if (nodeToFocusId == null) {
|
|
66
|
-
nodeToFocusId = instance.getNavigableChildrenIds(null)[0];
|
|
67
|
-
}
|
|
68
|
-
instance.focusNode(event, nodeToFocusId);
|
|
86
|
+
instance.focusDefaultNode(event);
|
|
69
87
|
}
|
|
70
88
|
};
|
|
71
89
|
const createHandleBlur = otherHandlers => event => {
|