@mui/x-tree-view-pro 7.22.1 → 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 +486 -11
- package/README.md +4 -4
- package/RichTreeViewPro/RichTreeViewPro.js +22 -5
- package/RichTreeViewPro/RichTreeViewPro.types.d.ts +3 -17
- package/index.d.ts +5 -7
- package/index.js +6 -8
- package/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.d.ts +1 -2
- package/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.js +12 -14
- package/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.js +34 -32
- package/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.d.ts +159 -0
- package/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.js +35 -0
- package/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.types.d.ts +11 -10
- package/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.utils.d.ts +4 -6
- package/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.utils.js +25 -17
- package/internals/utils/releaseInfo.js +1 -1
- package/modern/RichTreeViewPro/RichTreeViewPro.js +22 -5
- package/modern/index.js +6 -8
- package/modern/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.js +12 -14
- package/modern/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.js +34 -32
- package/modern/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.js +35 -0
- package/modern/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.utils.js +25 -17
- package/modern/internals/utils/releaseInfo.js +1 -1
- package/node/RichTreeViewPro/RichTreeViewPro.js +22 -5
- package/node/index.js +18 -42
- package/node/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.js +11 -13
- package/node/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.js +34 -32
- package/node/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.js +42 -0
- package/node/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.utils.js +24 -16
- package/node/internals/utils/releaseInfo.js +1 -1
- package/package.json +9 -7
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
|
-
import { buildSiblingIndexes, TREE_VIEW_ROOT_PARENT_ID } from '@mui/x-tree-view/internals';
|
|
2
|
+
import { buildSiblingIndexes, TREE_VIEW_ROOT_PARENT_ID, selectorItemMeta } from '@mui/x-tree-view/internals';
|
|
3
3
|
/**
|
|
4
4
|
* Checks if the item with the id itemIdB is an ancestor of the item with the id itemIdA.
|
|
5
5
|
*/
|
|
6
|
-
export const isAncestor = (
|
|
7
|
-
const itemMetaA =
|
|
6
|
+
export const isAncestor = (store, itemIdA, itemIdB) => {
|
|
7
|
+
const itemMetaA = selectorItemMeta(store.value, itemIdA);
|
|
8
8
|
if (itemMetaA.parentId === itemIdB) {
|
|
9
9
|
return true;
|
|
10
10
|
}
|
|
11
11
|
if (itemMetaA.parentId == null) {
|
|
12
12
|
return false;
|
|
13
13
|
}
|
|
14
|
-
return isAncestor(
|
|
14
|
+
return isAncestor(store, itemMetaA.parentId, itemIdB);
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -88,12 +88,12 @@ export const moveItemInTree = ({
|
|
|
88
88
|
newPosition,
|
|
89
89
|
prevState
|
|
90
90
|
}) => {
|
|
91
|
-
const itemToMoveMeta = prevState.
|
|
91
|
+
const itemToMoveMeta = prevState.itemMetaLookup[itemToMoveId];
|
|
92
92
|
const oldParentId = oldPosition.parentId ?? TREE_VIEW_ROOT_PARENT_ID;
|
|
93
93
|
const newParentId = newPosition.parentId ?? TREE_VIEW_ROOT_PARENT_ID;
|
|
94
94
|
|
|
95
95
|
// 1. Update the `itemOrderedChildrenIds`.
|
|
96
|
-
const itemOrderedChildrenIds = _extends({}, prevState.
|
|
96
|
+
const itemOrderedChildrenIds = _extends({}, prevState.itemOrderedChildrenIdsLookup);
|
|
97
97
|
if (oldParentId === newParentId) {
|
|
98
98
|
const updatedChildren = [...itemOrderedChildrenIds[oldParentId]];
|
|
99
99
|
updatedChildren.splice(oldPosition.index, 1);
|
|
@@ -109,42 +109,50 @@ export const moveItemInTree = ({
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
// 2. Update the `itemChildrenIndexes`
|
|
112
|
-
const itemChildrenIndexes = _extends({}, prevState.
|
|
112
|
+
const itemChildrenIndexes = _extends({}, prevState.itemChildrenIndexesLookup);
|
|
113
113
|
itemChildrenIndexes[oldParentId] = buildSiblingIndexes(itemOrderedChildrenIds[oldParentId]);
|
|
114
114
|
if (newParentId !== oldParentId) {
|
|
115
115
|
itemChildrenIndexes[newParentId] = buildSiblingIndexes(itemOrderedChildrenIds[newParentId]);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
// 3. Update the `
|
|
119
|
-
const
|
|
118
|
+
// 3. Update the `itemMetaLookup`
|
|
119
|
+
const itemMetaLookup = _extends({}, prevState.itemMetaLookup);
|
|
120
120
|
|
|
121
121
|
// 3.1 Update the `expandable` property of the old and the new parent
|
|
122
|
+
function updateExpandable(itemId) {
|
|
123
|
+
const isExpandable = itemOrderedChildrenIds[itemId].length > 0;
|
|
124
|
+
if (itemMetaLookup[itemId].expandable !== isExpandable) {
|
|
125
|
+
itemMetaLookup[itemId] = _extends({}, itemMetaLookup[itemId], {
|
|
126
|
+
expandable: isExpandable
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
122
130
|
if (oldParentId !== TREE_VIEW_ROOT_PARENT_ID && oldParentId !== newParentId) {
|
|
123
|
-
|
|
131
|
+
updateExpandable(oldParentId);
|
|
124
132
|
}
|
|
125
133
|
if (newParentId !== TREE_VIEW_ROOT_PARENT_ID && newParentId !== oldParentId) {
|
|
126
|
-
|
|
134
|
+
updateExpandable(newParentId);
|
|
127
135
|
}
|
|
128
136
|
|
|
129
137
|
// 3.2 Update the `parentId` and `depth` properties of the item to move
|
|
130
138
|
// The depth is always defined because drag&drop is only usable with Rich Tree View components.
|
|
131
|
-
const itemToMoveDepth = newPosition.parentId == null ? 0 :
|
|
132
|
-
|
|
139
|
+
const itemToMoveDepth = newPosition.parentId == null ? 0 : itemMetaLookup[newParentId].depth + 1;
|
|
140
|
+
itemMetaLookup[itemToMoveId] = _extends({}, itemToMoveMeta, {
|
|
133
141
|
parentId: newPosition.parentId,
|
|
134
142
|
depth: itemToMoveDepth
|
|
135
143
|
});
|
|
136
144
|
|
|
137
145
|
// 3.3 Update the depth of all the children of the item to move
|
|
138
146
|
const updateItemDepth = (itemId, depth) => {
|
|
139
|
-
|
|
147
|
+
itemMetaLookup[itemId] = _extends({}, itemMetaLookup[itemId], {
|
|
140
148
|
depth
|
|
141
149
|
});
|
|
142
150
|
itemOrderedChildrenIds[itemId]?.forEach(childId => updateItemDepth(childId, depth + 1));
|
|
143
151
|
};
|
|
144
152
|
itemOrderedChildrenIds[itemToMoveId]?.forEach(childId => updateItemDepth(childId, itemToMoveDepth + 1));
|
|
145
153
|
return _extends({}, prevState, {
|
|
146
|
-
itemOrderedChildrenIds,
|
|
147
|
-
itemChildrenIndexes,
|
|
148
|
-
|
|
154
|
+
itemOrderedChildrenIdsLookup: itemOrderedChildrenIds,
|
|
155
|
+
itemChildrenIndexesLookup: itemChildrenIndexes,
|
|
156
|
+
itemMetaLookup
|
|
149
157
|
});
|
|
150
158
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ponyfillGlobal } from '@mui/utils';
|
|
2
2
|
export const getReleaseInfo = () => {
|
|
3
|
-
const releaseInfo = "
|
|
3
|
+
const releaseInfo = "MTczMjIzMDAwMDAwMA==";
|
|
4
4
|
if (process.env.NODE_ENV !== 'production') {
|
|
5
5
|
// A simple hack to set the value in the test environment (has no build step).
|
|
6
6
|
// eslint-disable-next-line no-useless-concat
|
|
@@ -59,8 +59,7 @@ const RichTreeViewPro = /*#__PURE__*/React.forwardRef(function RichTreeViewPro(i
|
|
|
59
59
|
}
|
|
60
60
|
const {
|
|
61
61
|
getRootProps,
|
|
62
|
-
contextValue
|
|
63
|
-
instance
|
|
62
|
+
contextValue
|
|
64
63
|
} = useTreeView({
|
|
65
64
|
plugins: RICH_TREE_VIEW_PRO_PLUGINS,
|
|
66
65
|
rootRef: ref,
|
|
@@ -84,8 +83,7 @@ const RichTreeViewPro = /*#__PURE__*/React.forwardRef(function RichTreeViewPro(i
|
|
|
84
83
|
children: /*#__PURE__*/_jsxs(Root, _extends({}, rootProps, {
|
|
85
84
|
children: [/*#__PURE__*/_jsx(RichTreeViewItems, {
|
|
86
85
|
slots: slots,
|
|
87
|
-
slotProps: slotProps
|
|
88
|
-
itemsToRender: instance.getItemsToRender()
|
|
86
|
+
slotProps: slotProps
|
|
89
87
|
}), /*#__PURE__*/_jsx(Watermark, {
|
|
90
88
|
packageName: "x-tree-view-pro",
|
|
91
89
|
releaseInfo: releaseInfo
|
|
@@ -170,7 +168,6 @@ process.env.NODE_ENV !== "production" ? RichTreeViewPro.propTypes = {
|
|
|
170
168
|
* the feature will be fully disabled and any property / method call will not have any effect.
|
|
171
169
|
*/
|
|
172
170
|
experimentalFeatures: PropTypes.shape({
|
|
173
|
-
indentationAtItemLevel: PropTypes.bool,
|
|
174
171
|
itemsReordering: PropTypes.bool,
|
|
175
172
|
labelEditing: PropTypes.bool
|
|
176
173
|
}),
|
|
@@ -298,6 +295,26 @@ process.env.NODE_ENV !== "production" ? RichTreeViewPro.propTypes = {
|
|
|
298
295
|
* When `multiSelect` is true this takes an array of strings; when false (default) a string.
|
|
299
296
|
*/
|
|
300
297
|
selectedItems: PropTypes.any,
|
|
298
|
+
/**
|
|
299
|
+
* When `selectionPropagation.descendants` is set to `true`.
|
|
300
|
+
*
|
|
301
|
+
* - Selecting a parent selects all its descendants automatically.
|
|
302
|
+
* - Deselecting a parent deselects all its descendants automatically.
|
|
303
|
+
*
|
|
304
|
+
* When `selectionPropagation.parents` is set to `true`.
|
|
305
|
+
*
|
|
306
|
+
* - Selecting all the descendants of a parent selects the parent automatically.
|
|
307
|
+
* - Deselecting a descendant of a selected parent deselects the parent automatically.
|
|
308
|
+
*
|
|
309
|
+
* Only works when `multiSelect` is `true`.
|
|
310
|
+
* On the <SimpleTreeView />, only the expanded items are considered (since the collapsed item are not passed to the Tree View component at all)
|
|
311
|
+
*
|
|
312
|
+
* @default { parents: false, descendants: false }
|
|
313
|
+
*/
|
|
314
|
+
selectionPropagation: PropTypes.shape({
|
|
315
|
+
descendants: PropTypes.bool,
|
|
316
|
+
parents: PropTypes.bool
|
|
317
|
+
}),
|
|
301
318
|
/**
|
|
302
319
|
* The props used for each component slot.
|
|
303
320
|
* @default {}
|
package/modern/index.js
CHANGED
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @mui/x-tree-view-pro
|
|
2
|
+
* @mui/x-tree-view-pro v8.0.0-alpha.1
|
|
3
3
|
*
|
|
4
4
|
* @license MUI X Commercial
|
|
5
5
|
* This source code is licensed under the commercial license found in the
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
// Tree View
|
|
9
|
-
export * from '@mui/x-tree-view/TreeView';
|
|
10
9
|
export * from '@mui/x-tree-view/SimpleTreeView';
|
|
11
10
|
export * from "./RichTreeViewPro/index.js";
|
|
12
11
|
|
|
13
12
|
// Tree Item
|
|
14
13
|
export * from '@mui/x-tree-view/TreeItem';
|
|
15
|
-
export * from '@mui/x-tree-view/
|
|
16
|
-
export * from '@mui/x-tree-view/
|
|
17
|
-
export * from '@mui/x-tree-view/
|
|
18
|
-
export * from '@mui/x-tree-view/
|
|
19
|
-
export * from '@mui/x-tree-view/
|
|
20
|
-
export * from '@mui/x-tree-view/TreeItem2LabelInput';
|
|
14
|
+
export * from '@mui/x-tree-view/useTreeItem';
|
|
15
|
+
export * from '@mui/x-tree-view/TreeItemIcon';
|
|
16
|
+
export * from '@mui/x-tree-view/TreeItemProvider';
|
|
17
|
+
export * from '@mui/x-tree-view/TreeItemDragAndDropOverlay';
|
|
18
|
+
export * from '@mui/x-tree-view/TreeItemLabelInput';
|
|
21
19
|
export { unstable_resetCleanupTracking } from '@mui/x-tree-view/internals';
|
|
22
20
|
export * from '@mui/x-tree-view/models';
|
|
23
21
|
export * from '@mui/x-tree-view/icons';
|
package/modern/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.js
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import { useTreeViewContext, isTargetInDescendants } from '@mui/x-tree-view/internals';
|
|
2
|
+
import { useTreeViewContext, isTargetInDescendants, useSelector } from '@mui/x-tree-view/internals';
|
|
3
|
+
import { selectorItemsReorderingDraggedItemProperties, selectorItemsReorderingIsValidTarget } from "./useTreeViewItemsReordering.selectors.js";
|
|
3
4
|
export const isAndroid = () => navigator.userAgent.toLowerCase().includes('android');
|
|
4
5
|
export const useTreeViewItemsReorderingItemPlugin = ({
|
|
5
6
|
props
|
|
6
7
|
}) => {
|
|
7
8
|
const {
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
instance,
|
|
10
|
+
store,
|
|
11
|
+
itemsReordering
|
|
10
12
|
} = useTreeViewContext();
|
|
11
13
|
const {
|
|
12
14
|
itemId
|
|
13
15
|
} = props;
|
|
14
16
|
const validActionsRef = React.useRef(null);
|
|
17
|
+
const draggedItemProperties = useSelector(store, selectorItemsReorderingDraggedItemProperties, itemId);
|
|
18
|
+
const isValidTarget = useSelector(store, selectorItemsReorderingIsValidTarget, itemId);
|
|
15
19
|
return {
|
|
16
20
|
propsEnhancers: {
|
|
17
21
|
root: ({
|
|
@@ -19,8 +23,7 @@ export const useTreeViewItemsReorderingItemPlugin = ({
|
|
|
19
23
|
contentRefObject,
|
|
20
24
|
externalEventHandlers
|
|
21
25
|
}) => {
|
|
22
|
-
|
|
23
|
-
if (!draggable) {
|
|
26
|
+
if (!itemsReordering.enabled || itemsReordering.isItemReorderable && !itemsReordering.isItemReorderable(itemId)) {
|
|
24
27
|
return {};
|
|
25
28
|
}
|
|
26
29
|
const handleDragStart = event => {
|
|
@@ -75,8 +78,7 @@ export const useTreeViewItemsReorderingItemPlugin = ({
|
|
|
75
78
|
externalEventHandlers,
|
|
76
79
|
contentRefObject
|
|
77
80
|
}) => {
|
|
78
|
-
|
|
79
|
-
if (!currentDrag || currentDrag.draggedItemId === itemId) {
|
|
81
|
+
if (!isValidTarget) {
|
|
80
82
|
return {};
|
|
81
83
|
}
|
|
82
84
|
const handleDragOver = event => {
|
|
@@ -109,17 +111,13 @@ export const useTreeViewItemsReorderingItemPlugin = ({
|
|
|
109
111
|
};
|
|
110
112
|
},
|
|
111
113
|
dragAndDropOverlay: () => {
|
|
112
|
-
|
|
113
|
-
if (!currentDrag || currentDrag.targetItemId !== itemId || currentDrag.action == null) {
|
|
114
|
+
if (!draggedItemProperties) {
|
|
114
115
|
return {};
|
|
115
116
|
}
|
|
116
|
-
const targetDepth = currentDrag.newPosition?.parentId == null ? 0 :
|
|
117
|
-
// The depth is always defined because drag&drop is only usable with Rich Tree View components.
|
|
118
|
-
instance.getItemMeta(currentDrag.newPosition.parentId).depth + 1;
|
|
119
117
|
return {
|
|
120
|
-
action:
|
|
118
|
+
action: draggedItemProperties.action,
|
|
121
119
|
style: {
|
|
122
|
-
'--TreeView-targetDepth': targetDepth
|
|
120
|
+
'--TreeView-targetDepth': draggedItemProperties.targetDepth
|
|
123
121
|
}
|
|
124
122
|
};
|
|
125
123
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import { selectorItemIndex, selectorItemMeta, selectorItemOrderedChildrenIds } from '@mui/x-tree-view/internals';
|
|
3
4
|
import { warnOnce } from '@mui/x-internals/warning';
|
|
4
5
|
import { chooseActionToApply, isAncestor, moveItemInTree } from "./useTreeViewItemsReordering.utils.js";
|
|
5
6
|
import { useTreeViewItemsReorderingItemPlugin } from "./useTreeViewItemsReordering.itemPlugin.js";
|
|
7
|
+
import { selectorItemsReordering } from "./useTreeViewItemsReordering.selectors.js";
|
|
6
8
|
export const useTreeViewItemsReordering = ({
|
|
7
9
|
params,
|
|
8
|
-
|
|
9
|
-
state,
|
|
10
|
-
setState
|
|
10
|
+
store
|
|
11
11
|
}) => {
|
|
12
12
|
const canItemBeDragged = React.useCallback(itemId => {
|
|
13
13
|
if (!params.itemsReordering) {
|
|
@@ -20,7 +20,7 @@ export const useTreeViewItemsReordering = ({
|
|
|
20
20
|
return true;
|
|
21
21
|
}, [params.itemsReordering, params.isItemReorderable]);
|
|
22
22
|
const getDroppingTargetValidActions = React.useCallback(itemId => {
|
|
23
|
-
const itemsReordering =
|
|
23
|
+
const itemsReordering = selectorItemsReordering(store.value);
|
|
24
24
|
if (!itemsReordering) {
|
|
25
25
|
throw new Error('There is no ongoing reordering.');
|
|
26
26
|
}
|
|
@@ -28,10 +28,10 @@ export const useTreeViewItemsReordering = ({
|
|
|
28
28
|
return {};
|
|
29
29
|
}
|
|
30
30
|
const canMoveItemToNewPosition = params.canMoveItemToNewPosition;
|
|
31
|
-
const targetItemMeta =
|
|
32
|
-
const targetItemIndex =
|
|
33
|
-
const draggedItemMeta =
|
|
34
|
-
const draggedItemIndex =
|
|
31
|
+
const targetItemMeta = selectorItemMeta(store.value, itemId);
|
|
32
|
+
const targetItemIndex = selectorItemIndex(store.value, targetItemMeta.id);
|
|
33
|
+
const draggedItemMeta = selectorItemMeta(store.value, itemsReordering.draggedItemId);
|
|
34
|
+
const draggedItemIndex = selectorItemIndex(store.value, draggedItemMeta.id);
|
|
35
35
|
const oldPosition = {
|
|
36
36
|
parentId: draggedItemMeta.parentId,
|
|
37
37
|
index: draggedItemIndex
|
|
@@ -67,7 +67,7 @@ export const useTreeViewItemsReordering = ({
|
|
|
67
67
|
},
|
|
68
68
|
'move-to-parent': targetItemMeta.parentId == null ? null : {
|
|
69
69
|
parentId: targetItemMeta.parentId,
|
|
70
|
-
index:
|
|
70
|
+
index: selectorItemOrderedChildrenIds(store.value, targetItemMeta.parentId).length
|
|
71
71
|
}
|
|
72
72
|
};
|
|
73
73
|
const validActions = {};
|
|
@@ -78,9 +78,9 @@ export const useTreeViewItemsReordering = ({
|
|
|
78
78
|
}
|
|
79
79
|
});
|
|
80
80
|
return validActions;
|
|
81
|
-
}, [
|
|
81
|
+
}, [store, params.canMoveItemToNewPosition]);
|
|
82
82
|
const startDraggingItem = React.useCallback(itemId => {
|
|
83
|
-
|
|
83
|
+
store.update(prevState => _extends({}, prevState, {
|
|
84
84
|
itemsReordering: {
|
|
85
85
|
targetItemId: itemId,
|
|
86
86
|
draggedItemId: itemId,
|
|
@@ -88,24 +88,25 @@ export const useTreeViewItemsReordering = ({
|
|
|
88
88
|
newPosition: null
|
|
89
89
|
}
|
|
90
90
|
}));
|
|
91
|
-
}, [
|
|
91
|
+
}, [store]);
|
|
92
92
|
const stopDraggingItem = React.useCallback(itemId => {
|
|
93
|
-
|
|
93
|
+
const itemsReordering = selectorItemsReordering(store.value);
|
|
94
|
+
if (itemsReordering == null || itemsReordering.draggedItemId !== itemId) {
|
|
94
95
|
return;
|
|
95
96
|
}
|
|
96
|
-
if (
|
|
97
|
-
|
|
97
|
+
if (itemsReordering.draggedItemId === itemsReordering.targetItemId || itemsReordering.action == null || itemsReordering.newPosition == null) {
|
|
98
|
+
store.update(prevState => _extends({}, prevState, {
|
|
98
99
|
itemsReordering: null
|
|
99
100
|
}));
|
|
100
101
|
return;
|
|
101
102
|
}
|
|
102
|
-
const draggedItemMeta =
|
|
103
|
+
const draggedItemMeta = selectorItemMeta(store.value, itemsReordering.draggedItemId);
|
|
103
104
|
const oldPosition = {
|
|
104
105
|
parentId: draggedItemMeta.parentId,
|
|
105
|
-
index:
|
|
106
|
+
index: selectorItemIndex(store.value, draggedItemMeta.id)
|
|
106
107
|
};
|
|
107
|
-
const newPosition =
|
|
108
|
-
|
|
108
|
+
const newPosition = itemsReordering.newPosition;
|
|
109
|
+
store.update(prevState => _extends({}, prevState, {
|
|
109
110
|
itemsReordering: null,
|
|
110
111
|
items: moveItemInTree({
|
|
111
112
|
itemToMoveId: itemId,
|
|
@@ -120,7 +121,7 @@ export const useTreeViewItemsReordering = ({
|
|
|
120
121
|
newPosition,
|
|
121
122
|
oldPosition
|
|
122
123
|
});
|
|
123
|
-
}, [
|
|
124
|
+
}, [store, params.onItemPositionChange]);
|
|
124
125
|
const setDragTargetItem = React.useCallback(({
|
|
125
126
|
itemId,
|
|
126
127
|
validActions,
|
|
@@ -129,16 +130,16 @@ export const useTreeViewItemsReordering = ({
|
|
|
129
130
|
cursorX,
|
|
130
131
|
contentElement
|
|
131
132
|
}) => {
|
|
132
|
-
|
|
133
|
+
store.update(prevState => {
|
|
133
134
|
const prevSubState = prevState.itemsReordering;
|
|
134
|
-
if (prevSubState == null || isAncestor(
|
|
135
|
+
if (prevSubState == null || isAncestor(store, itemId, prevSubState.draggedItemId)) {
|
|
135
136
|
return prevState;
|
|
136
137
|
}
|
|
137
138
|
const action = chooseActionToApply({
|
|
138
139
|
itemChildrenIndentation: params.itemChildrenIndentation,
|
|
139
140
|
validActions,
|
|
140
141
|
targetHeight,
|
|
141
|
-
targetDepth: prevState.items.
|
|
142
|
+
targetDepth: prevState.items.itemMetaLookup[itemId].depth,
|
|
142
143
|
cursorY,
|
|
143
144
|
cursorX,
|
|
144
145
|
contentElement
|
|
@@ -155,7 +156,13 @@ export const useTreeViewItemsReordering = ({
|
|
|
155
156
|
})
|
|
156
157
|
});
|
|
157
158
|
});
|
|
158
|
-
}, [
|
|
159
|
+
}, [store, params.itemChildrenIndentation]);
|
|
160
|
+
const pluginContextValue = React.useMemo(() => ({
|
|
161
|
+
itemsReordering: {
|
|
162
|
+
enabled: params.itemsReordering,
|
|
163
|
+
isItemReorderable: params.isItemReorderable
|
|
164
|
+
}
|
|
165
|
+
}), [params.itemsReordering, params.isItemReorderable]);
|
|
159
166
|
return {
|
|
160
167
|
instance: {
|
|
161
168
|
canItemBeDragged,
|
|
@@ -164,12 +171,7 @@ export const useTreeViewItemsReordering = ({
|
|
|
164
171
|
stopDraggingItem,
|
|
165
172
|
setDragTargetItem
|
|
166
173
|
},
|
|
167
|
-
contextValue:
|
|
168
|
-
itemsReordering: {
|
|
169
|
-
enabled: params.itemsReordering,
|
|
170
|
-
currentDrag: state.itemsReordering
|
|
171
|
-
}
|
|
172
|
-
}
|
|
174
|
+
contextValue: pluginContextValue
|
|
173
175
|
};
|
|
174
176
|
};
|
|
175
177
|
useTreeViewItemsReordering.itemPlugin = useTreeViewItemsReorderingItemPlugin;
|
|
@@ -177,10 +179,10 @@ useTreeViewItemsReordering.getDefaultizedParams = ({
|
|
|
177
179
|
params,
|
|
178
180
|
experimentalFeatures
|
|
179
181
|
}) => {
|
|
180
|
-
const canUseFeature = experimentalFeatures?.
|
|
182
|
+
const canUseFeature = experimentalFeatures?.itemsReordering;
|
|
181
183
|
if (process.env.NODE_ENV !== 'production') {
|
|
182
184
|
if (params.itemsReordering && !canUseFeature) {
|
|
183
|
-
warnOnce(['MUI X: The items reordering feature requires the `
|
|
185
|
+
warnOnce(['MUI X: The items reordering feature requires the `itemsReordering` experimental feature to be enabled.', 'You can do it by passing `experimentalFeatures={{ itemsReordering: true }}` to the `<RichTreeViewPro />`component.', 'Check the documentation for more details: https://mui.com/x/react-tree-view/rich-tree-view/items/']);
|
|
184
186
|
}
|
|
185
187
|
}
|
|
186
188
|
return _extends({}, params, {
|
package/modern/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createSelector, selectorItemMetaLookup } from '@mui/x-tree-view/internals';
|
|
2
|
+
/**
|
|
3
|
+
* Get the items reordering state.
|
|
4
|
+
* @param {TreeViewState<[UseTreeViewItemsReorderingSignature]>} state The state of the tree view.
|
|
5
|
+
* @returns {TreeViewItemsReorderingState | null} The items reordering state.
|
|
6
|
+
*/
|
|
7
|
+
export const selectorItemsReordering = state => state.itemsReordering;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Get the properties of the dragged item.
|
|
11
|
+
* @param {TreeViewState<[UseTreeViewItemsSignature, UseTreeViewItemsReorderingSignature]>} state The state of the tree view.
|
|
12
|
+
* @param {string} itemId The id of the item.
|
|
13
|
+
* @returns {TreeViewItemDraggedItemProperties | null} The properties of the dragged item if the current item is being dragged, `null` otherwise.
|
|
14
|
+
*/
|
|
15
|
+
export const selectorItemsReorderingDraggedItemProperties = createSelector([selectorItemsReordering, selectorItemMetaLookup, (_, itemId) => itemId], (itemsReordering, itemMetaLookup, itemId) => {
|
|
16
|
+
if (!itemsReordering || itemsReordering.targetItemId !== itemId || itemsReordering.action == null) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const targetDepth = itemsReordering.newPosition?.parentId == null ? 0 :
|
|
20
|
+
// The depth is always defined because drag&drop is only usable with Rich Tree View components.
|
|
21
|
+
itemMetaLookup[itemId].depth + 1;
|
|
22
|
+
return {
|
|
23
|
+
newPosition: itemsReordering.newPosition,
|
|
24
|
+
action: itemsReordering.action,
|
|
25
|
+
targetDepth
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Check if the current item is a valid target for the dragged item.
|
|
31
|
+
* @param {TreeViewState<[UseTreeViewItemsReorderingSignature]>} state The state of the tree view.
|
|
32
|
+
* @param {string} itemId The id of the item.
|
|
33
|
+
* @returns {boolean} `true` if the current item is a valid target for the dragged item, `false` otherwise.
|
|
34
|
+
*/
|
|
35
|
+
export const selectorItemsReorderingIsValidTarget = createSelector([selectorItemsReordering, (_, itemId) => itemId], (itemsReordering, itemId) => itemsReordering && itemsReordering.draggedItemId !== itemId);
|
package/modern/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.utils.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
|
-
import { buildSiblingIndexes, TREE_VIEW_ROOT_PARENT_ID } from '@mui/x-tree-view/internals';
|
|
2
|
+
import { buildSiblingIndexes, TREE_VIEW_ROOT_PARENT_ID, selectorItemMeta } from '@mui/x-tree-view/internals';
|
|
3
3
|
/**
|
|
4
4
|
* Checks if the item with the id itemIdB is an ancestor of the item with the id itemIdA.
|
|
5
5
|
*/
|
|
6
|
-
export const isAncestor = (
|
|
7
|
-
const itemMetaA =
|
|
6
|
+
export const isAncestor = (store, itemIdA, itemIdB) => {
|
|
7
|
+
const itemMetaA = selectorItemMeta(store.value, itemIdA);
|
|
8
8
|
if (itemMetaA.parentId === itemIdB) {
|
|
9
9
|
return true;
|
|
10
10
|
}
|
|
11
11
|
if (itemMetaA.parentId == null) {
|
|
12
12
|
return false;
|
|
13
13
|
}
|
|
14
|
-
return isAncestor(
|
|
14
|
+
return isAncestor(store, itemMetaA.parentId, itemIdB);
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
/**
|
|
@@ -88,12 +88,12 @@ export const moveItemInTree = ({
|
|
|
88
88
|
newPosition,
|
|
89
89
|
prevState
|
|
90
90
|
}) => {
|
|
91
|
-
const itemToMoveMeta = prevState.
|
|
91
|
+
const itemToMoveMeta = prevState.itemMetaLookup[itemToMoveId];
|
|
92
92
|
const oldParentId = oldPosition.parentId ?? TREE_VIEW_ROOT_PARENT_ID;
|
|
93
93
|
const newParentId = newPosition.parentId ?? TREE_VIEW_ROOT_PARENT_ID;
|
|
94
94
|
|
|
95
95
|
// 1. Update the `itemOrderedChildrenIds`.
|
|
96
|
-
const itemOrderedChildrenIds = _extends({}, prevState.
|
|
96
|
+
const itemOrderedChildrenIds = _extends({}, prevState.itemOrderedChildrenIdsLookup);
|
|
97
97
|
if (oldParentId === newParentId) {
|
|
98
98
|
const updatedChildren = [...itemOrderedChildrenIds[oldParentId]];
|
|
99
99
|
updatedChildren.splice(oldPosition.index, 1);
|
|
@@ -109,42 +109,50 @@ export const moveItemInTree = ({
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
// 2. Update the `itemChildrenIndexes`
|
|
112
|
-
const itemChildrenIndexes = _extends({}, prevState.
|
|
112
|
+
const itemChildrenIndexes = _extends({}, prevState.itemChildrenIndexesLookup);
|
|
113
113
|
itemChildrenIndexes[oldParentId] = buildSiblingIndexes(itemOrderedChildrenIds[oldParentId]);
|
|
114
114
|
if (newParentId !== oldParentId) {
|
|
115
115
|
itemChildrenIndexes[newParentId] = buildSiblingIndexes(itemOrderedChildrenIds[newParentId]);
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
// 3. Update the `
|
|
119
|
-
const
|
|
118
|
+
// 3. Update the `itemMetaLookup`
|
|
119
|
+
const itemMetaLookup = _extends({}, prevState.itemMetaLookup);
|
|
120
120
|
|
|
121
121
|
// 3.1 Update the `expandable` property of the old and the new parent
|
|
122
|
+
function updateExpandable(itemId) {
|
|
123
|
+
const isExpandable = itemOrderedChildrenIds[itemId].length > 0;
|
|
124
|
+
if (itemMetaLookup[itemId].expandable !== isExpandable) {
|
|
125
|
+
itemMetaLookup[itemId] = _extends({}, itemMetaLookup[itemId], {
|
|
126
|
+
expandable: isExpandable
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
122
130
|
if (oldParentId !== TREE_VIEW_ROOT_PARENT_ID && oldParentId !== newParentId) {
|
|
123
|
-
|
|
131
|
+
updateExpandable(oldParentId);
|
|
124
132
|
}
|
|
125
133
|
if (newParentId !== TREE_VIEW_ROOT_PARENT_ID && newParentId !== oldParentId) {
|
|
126
|
-
|
|
134
|
+
updateExpandable(newParentId);
|
|
127
135
|
}
|
|
128
136
|
|
|
129
137
|
// 3.2 Update the `parentId` and `depth` properties of the item to move
|
|
130
138
|
// The depth is always defined because drag&drop is only usable with Rich Tree View components.
|
|
131
|
-
const itemToMoveDepth = newPosition.parentId == null ? 0 :
|
|
132
|
-
|
|
139
|
+
const itemToMoveDepth = newPosition.parentId == null ? 0 : itemMetaLookup[newParentId].depth + 1;
|
|
140
|
+
itemMetaLookup[itemToMoveId] = _extends({}, itemToMoveMeta, {
|
|
133
141
|
parentId: newPosition.parentId,
|
|
134
142
|
depth: itemToMoveDepth
|
|
135
143
|
});
|
|
136
144
|
|
|
137
145
|
// 3.3 Update the depth of all the children of the item to move
|
|
138
146
|
const updateItemDepth = (itemId, depth) => {
|
|
139
|
-
|
|
147
|
+
itemMetaLookup[itemId] = _extends({}, itemMetaLookup[itemId], {
|
|
140
148
|
depth
|
|
141
149
|
});
|
|
142
150
|
itemOrderedChildrenIds[itemId]?.forEach(childId => updateItemDepth(childId, depth + 1));
|
|
143
151
|
};
|
|
144
152
|
itemOrderedChildrenIds[itemToMoveId]?.forEach(childId => updateItemDepth(childId, itemToMoveDepth + 1));
|
|
145
153
|
return _extends({}, prevState, {
|
|
146
|
-
itemOrderedChildrenIds,
|
|
147
|
-
itemChildrenIndexes,
|
|
148
|
-
|
|
154
|
+
itemOrderedChildrenIdsLookup: itemOrderedChildrenIds,
|
|
155
|
+
itemChildrenIndexesLookup: itemChildrenIndexes,
|
|
156
|
+
itemMetaLookup
|
|
149
157
|
});
|
|
150
158
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ponyfillGlobal } from '@mui/utils';
|
|
2
2
|
export const getReleaseInfo = () => {
|
|
3
|
-
const releaseInfo = "
|
|
3
|
+
const releaseInfo = "MTczMjIzMDAwMDAwMA==";
|
|
4
4
|
if (process.env.NODE_ENV !== 'production') {
|
|
5
5
|
// A simple hack to set the value in the test environment (has no build step).
|
|
6
6
|
// eslint-disable-next-line no-useless-concat
|
|
@@ -66,8 +66,7 @@ const RichTreeViewPro = exports.RichTreeViewPro = /*#__PURE__*/React.forwardRef(
|
|
|
66
66
|
}
|
|
67
67
|
const {
|
|
68
68
|
getRootProps,
|
|
69
|
-
contextValue
|
|
70
|
-
instance
|
|
69
|
+
contextValue
|
|
71
70
|
} = (0, _internals.useTreeView)({
|
|
72
71
|
plugins: _RichTreeViewPro.RICH_TREE_VIEW_PRO_PLUGINS,
|
|
73
72
|
rootRef: ref,
|
|
@@ -91,8 +90,7 @@ const RichTreeViewPro = exports.RichTreeViewPro = /*#__PURE__*/React.forwardRef(
|
|
|
91
90
|
children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(Root, (0, _extends2.default)({}, rootProps, {
|
|
92
91
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_internals.RichTreeViewItems, {
|
|
93
92
|
slots: slots,
|
|
94
|
-
slotProps: slotProps
|
|
95
|
-
itemsToRender: instance.getItemsToRender()
|
|
93
|
+
slotProps: slotProps
|
|
96
94
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_xLicense.Watermark, {
|
|
97
95
|
packageName: "x-tree-view-pro",
|
|
98
96
|
releaseInfo: releaseInfo
|
|
@@ -177,7 +175,6 @@ process.env.NODE_ENV !== "production" ? RichTreeViewPro.propTypes = {
|
|
|
177
175
|
* the feature will be fully disabled and any property / method call will not have any effect.
|
|
178
176
|
*/
|
|
179
177
|
experimentalFeatures: _propTypes.default.shape({
|
|
180
|
-
indentationAtItemLevel: _propTypes.default.bool,
|
|
181
178
|
itemsReordering: _propTypes.default.bool,
|
|
182
179
|
labelEditing: _propTypes.default.bool
|
|
183
180
|
}),
|
|
@@ -305,6 +302,26 @@ process.env.NODE_ENV !== "production" ? RichTreeViewPro.propTypes = {
|
|
|
305
302
|
* When `multiSelect` is true this takes an array of strings; when false (default) a string.
|
|
306
303
|
*/
|
|
307
304
|
selectedItems: _propTypes.default.any,
|
|
305
|
+
/**
|
|
306
|
+
* When `selectionPropagation.descendants` is set to `true`.
|
|
307
|
+
*
|
|
308
|
+
* - Selecting a parent selects all its descendants automatically.
|
|
309
|
+
* - Deselecting a parent deselects all its descendants automatically.
|
|
310
|
+
*
|
|
311
|
+
* When `selectionPropagation.parents` is set to `true`.
|
|
312
|
+
*
|
|
313
|
+
* - Selecting all the descendants of a parent selects the parent automatically.
|
|
314
|
+
* - Deselecting a descendant of a selected parent deselects the parent automatically.
|
|
315
|
+
*
|
|
316
|
+
* Only works when `multiSelect` is `true`.
|
|
317
|
+
* On the <SimpleTreeView />, only the expanded items are considered (since the collapsed item are not passed to the Tree View component at all)
|
|
318
|
+
*
|
|
319
|
+
* @default { parents: false, descendants: false }
|
|
320
|
+
*/
|
|
321
|
+
selectionPropagation: _propTypes.default.shape({
|
|
322
|
+
descendants: _propTypes.default.bool,
|
|
323
|
+
parents: _propTypes.default.bool
|
|
324
|
+
}),
|
|
308
325
|
/**
|
|
309
326
|
* The props used for each component slot.
|
|
310
327
|
* @default {}
|