From 6b37ea34bc8412d920ba173c9e9ee8d95e180e63 Mon Sep 17 00:00:00 2001 From: noraleonte Date: Wed, 27 Nov 2024 19:24:56 +0200 Subject: [PATCH 1/3] fix d&d issue + label editing click --- .../useTreeViewItemsReordering.itemPlugin.ts | 13 +++++++++++-- .../useTreeViewItemsReordering.selectors.ts | 9 +++++++++ .../src/hooks/useTreeItemUtils/useTreeItemUtils.tsx | 2 +- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.ts b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.ts index 1906cef2d7ea8..3fb934466cecb 100644 --- a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.ts +++ b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.ts @@ -7,6 +7,7 @@ import { isTargetInDescendants, useSelector, } from '@mui/x-tree-view/internals'; +import { selectorIsItemBeingEdited } from '@mui/x-tree-view/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors'; import { UseTreeItemDragAndDropOverlaySlotPropsFromItemsReordering, UseTreeItemRootSlotPropsFromItemsReordering, @@ -15,6 +16,7 @@ import { UseTreeItemContentSlotPropsFromItemsReordering, } from './useTreeViewItemsReordering.types'; import { + selectorDraggedItem, selectorItemsReorderingDraggedItemProperties, selectorItemsReorderingIsValidTarget, } from './useTreeViewItemsReordering.selectors'; @@ -34,6 +36,9 @@ export const useTreeViewItemsReorderingItemPlugin: TreeViewItemPlugin = ({ props itemId, ); const isValidTarget = useSelector(store, selectorItemsReorderingIsValidTarget, itemId); + const draggedItemId = useSelector(store, selectorDraggedItem); + + const isBeingEdited = useSelector(store, selectorIsItemBeingEdited, draggedItemId as string); return { propsEnhancers: { @@ -44,7 +49,8 @@ export const useTreeViewItemsReorderingItemPlugin: TreeViewItemPlugin = ({ props }): UseTreeItemRootSlotPropsFromItemsReordering => { if ( !itemsReordering.enabled || - (itemsReordering.isItemReorderable && !itemsReordering.isItemReorderable(itemId)) + (itemsReordering.isItemReorderable && !itemsReordering.isItemReorderable(itemId)) || + isBeingEdited ) { return {}; } @@ -79,6 +85,7 @@ export const useTreeViewItemsReorderingItemPlugin: TreeViewItemPlugin = ({ props const handleRootDragOver = (event: React.DragEvent & TreeViewCancellableEvent) => { externalEventHandlers.onDragOver?.(event); + if (event.defaultMuiPrevented) { return; } @@ -88,6 +95,7 @@ export const useTreeViewItemsReorderingItemPlugin: TreeViewItemPlugin = ({ props const handleRootDragEnd = (event: React.DragEvent & TreeViewCancellableEvent) => { externalEventHandlers.onDragEnd?.(event); + if (event.defaultMuiPrevented) { return; } @@ -106,12 +114,13 @@ export const useTreeViewItemsReorderingItemPlugin: TreeViewItemPlugin = ({ props externalEventHandlers, contentRefObject, }): UseTreeItemContentSlotPropsFromItemsReordering => { - if (!isValidTarget) { + if (!isValidTarget || isBeingEdited) { return {}; } const handleDragOver = (event: React.DragEvent & TreeViewCancellableEvent) => { externalEventHandlers.onDragOver?.(event); + if (event.defaultMuiPrevented || validActionsRef.current == null) { return; } diff --git a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.ts b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.ts index 8e59419f02593..bf45e74738645 100644 --- a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.ts +++ b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.ts @@ -41,6 +41,15 @@ export const selectorItemsReorderingDraggedItemProperties = createSelector( }, ); +/** + * Get the id of the item that is currently being dragged. + * @param {TreeViewState<[UseTreeViewItemsReorderingSignature]>} state The state of the tree view. + * @returns {string} The id of the currently dragged item. + */ +export const selectorDraggedItem = createSelector( + [selectorItemsReordering], + (itemsReordering) => itemsReordering && itemsReordering.draggedItemId, +); /** * Check if the current item is a valid target for the dragged item. * @param {TreeViewState<[UseTreeViewItemsReorderingSignature]>} state The state of the tree view. diff --git a/packages/x-tree-view/src/hooks/useTreeItemUtils/useTreeItemUtils.tsx b/packages/x-tree-view/src/hooks/useTreeItemUtils/useTreeItemUtils.tsx index 623c80a30c050..4973a5449fd7b 100644 --- a/packages/x-tree-view/src/hooks/useTreeItemUtils/useTreeItemUtils.tsx +++ b/packages/x-tree-view/src/hooks/useTreeItemUtils/useTreeItemUtils.tsx @@ -130,7 +130,7 @@ export const useTreeItemUtils = < return; } - if (!status.focused) { + if (!status.focused && !status.editing) { instance.focusItem(event, itemId); } From 4c200fbeb209258115ad0d36a36c246107be545e Mon Sep 17 00:00:00 2001 From: noraleonte Date: Wed, 4 Dec 2024 12:32:16 +0200 Subject: [PATCH 2/3] review - Flavien --- .../useTreeViewItemsReordering.itemPlugin.ts | 4 ++-- .../useTreeViewItemsReordering.selectors.ts | 4 ++-- packages/x-tree-view/src/internals/index.ts | 1 + .../plugins/useTreeViewLabel/useTreeViewLabel.selectors.ts | 4 ++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.ts b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.ts index 3fb934466cecb..084f416115ff7 100644 --- a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.ts +++ b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.ts @@ -6,8 +6,8 @@ import { UseTreeViewItemsSignature, isTargetInDescendants, useSelector, + selectorIsItemBeingEdited, } from '@mui/x-tree-view/internals'; -import { selectorIsItemBeingEdited } from '@mui/x-tree-view/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors'; import { UseTreeItemDragAndDropOverlaySlotPropsFromItemsReordering, UseTreeItemRootSlotPropsFromItemsReordering, @@ -38,7 +38,7 @@ export const useTreeViewItemsReorderingItemPlugin: TreeViewItemPlugin = ({ props const isValidTarget = useSelector(store, selectorItemsReorderingIsValidTarget, itemId); const draggedItemId = useSelector(store, selectorDraggedItem); - const isBeingEdited = useSelector(store, selectorIsItemBeingEdited, draggedItemId as string); + const isBeingEdited = useSelector(store, selectorIsItemBeingEdited, draggedItemId); return { propsEnhancers: { diff --git a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.ts b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.ts index bf45e74738645..e783a9f7b9193 100644 --- a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.ts +++ b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.ts @@ -44,11 +44,11 @@ export const selectorItemsReorderingDraggedItemProperties = createSelector( /** * Get the id of the item that is currently being dragged. * @param {TreeViewState<[UseTreeViewItemsReorderingSignature]>} state The state of the tree view. - * @returns {string} The id of the currently dragged item. + * @returns {string | null} The id of the currently dragged item. */ export const selectorDraggedItem = createSelector( [selectorItemsReordering], - (itemsReordering) => itemsReordering && itemsReordering.draggedItemId, + (itemsReordering) => itemsReordering?.draggedItemId, ); /** * Check if the current item is a valid target for the dragged item. diff --git a/packages/x-tree-view/src/internals/index.ts b/packages/x-tree-view/src/internals/index.ts index 5020622452e05..6fa2e3c93e92c 100644 --- a/packages/x-tree-view/src/internals/index.ts +++ b/packages/x-tree-view/src/internals/index.ts @@ -67,6 +67,7 @@ export type { UseTreeViewItemsState, } from './plugins/useTreeViewItems'; export { useTreeViewLabel } from './plugins/useTreeViewLabel'; +export { selectorIsItemBeingEdited } from './plugins/useTreeViewLabel/useTreeViewLabel.selectors'; export type { UseTreeViewLabelSignature, UseTreeViewLabelParameters, diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.ts index 43c28f9726064..d0bf65ef4b6bd 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.ts @@ -34,6 +34,6 @@ export const selectorIsItemEditable = createSelector( * @returns {boolean} `true` if the item is being edited, `false` otherwise. */ export const selectorIsItemBeingEdited = createSelector( - [selectorTreeViewLabelState, (_, itemId: string) => itemId], - (labelState, itemId) => labelState.editedItemId === itemId, + [selectorTreeViewLabelState, (_, itemId: string | null) => itemId], + (labelState, itemId) => (itemId ? labelState.editedItemId === itemId : false), ); From 6e26f538e3082c5dae295c1451fee87bf1b6de35 Mon Sep 17 00:00:00 2001 From: noraleonte Date: Mon, 16 Dec 2024 17:35:18 +0200 Subject: [PATCH 3/3] disable dnd when editing --- .../useTreeViewItemsReordering.itemPlugin.ts | 15 +++++++------ .../useTreeViewItemsReordering.selectors.ts | 9 -------- .../useTreeViewItemsReordering.ts | 22 +++++++++++-------- packages/x-tree-view/src/internals/index.ts | 5 ++++- .../useTreeViewLabel.selectors.ts | 8 +++++++ 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.ts b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.ts index 084f416115ff7..5211ecbcd9873 100644 --- a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.ts +++ b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.itemPlugin.ts @@ -6,7 +6,8 @@ import { UseTreeViewItemsSignature, isTargetInDescendants, useSelector, - selectorIsItemBeingEdited, + selectorIsAnItemEdited, + UseTreeViewLabelSignature, } from '@mui/x-tree-view/internals'; import { UseTreeItemDragAndDropOverlaySlotPropsFromItemsReordering, @@ -16,7 +17,6 @@ import { UseTreeItemContentSlotPropsFromItemsReordering, } from './useTreeViewItemsReordering.types'; import { - selectorDraggedItem, selectorItemsReorderingDraggedItemProperties, selectorItemsReorderingIsValidTarget, } from './useTreeViewItemsReordering.selectors'; @@ -25,7 +25,9 @@ export const isAndroid = () => navigator.userAgent.toLowerCase().includes('andro export const useTreeViewItemsReorderingItemPlugin: TreeViewItemPlugin = ({ props }) => { const { instance, store, itemsReordering } = - useTreeViewContext<[UseTreeViewItemsSignature, UseTreeViewItemsReorderingSignature]>(); + useTreeViewContext< + [UseTreeViewItemsSignature, UseTreeViewItemsReorderingSignature, UseTreeViewLabelSignature] + >(); const { itemId } = props; const validActionsRef = React.useRef(null); @@ -36,9 +38,8 @@ export const useTreeViewItemsReorderingItemPlugin: TreeViewItemPlugin = ({ props itemId, ); const isValidTarget = useSelector(store, selectorItemsReorderingIsValidTarget, itemId); - const draggedItemId = useSelector(store, selectorDraggedItem); - const isBeingEdited = useSelector(store, selectorIsItemBeingEdited, draggedItemId); + const isEditing = useSelector(store, selectorIsAnItemEdited); return { propsEnhancers: { @@ -50,7 +51,7 @@ export const useTreeViewItemsReorderingItemPlugin: TreeViewItemPlugin = ({ props if ( !itemsReordering.enabled || (itemsReordering.isItemReorderable && !itemsReordering.isItemReorderable(itemId)) || - isBeingEdited + isEditing ) { return {}; } @@ -114,7 +115,7 @@ export const useTreeViewItemsReorderingItemPlugin: TreeViewItemPlugin = ({ props externalEventHandlers, contentRefObject, }): UseTreeItemContentSlotPropsFromItemsReordering => { - if (!isValidTarget || isBeingEdited) { + if (!isValidTarget) { return {}; } diff --git a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.ts b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.ts index e783a9f7b9193..8e59419f02593 100644 --- a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.ts +++ b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.selectors.ts @@ -41,15 +41,6 @@ export const selectorItemsReorderingDraggedItemProperties = createSelector( }, ); -/** - * Get the id of the item that is currently being dragged. - * @param {TreeViewState<[UseTreeViewItemsReorderingSignature]>} state The state of the tree view. - * @returns {string | null} The id of the currently dragged item. - */ -export const selectorDraggedItem = createSelector( - [selectorItemsReordering], - (itemsReordering) => itemsReordering?.draggedItemId, -); /** * Check if the current item is a valid target for the dragged item. * @param {TreeViewState<[UseTreeViewItemsReorderingSignature]>} state The state of the tree view. diff --git a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.ts b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.ts index c096a1320ebd7..f5c44d558529e 100644 --- a/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.ts +++ b/packages/x-tree-view-pro/src/internals/plugins/useTreeViewItemsReordering/useTreeViewItemsReordering.ts @@ -1,6 +1,7 @@ import * as React from 'react'; import { TreeViewPlugin, + selectorIsItemBeingEdited, selectorItemIndex, selectorItemMeta, selectorItemOrderedChildrenIds, @@ -131,15 +132,18 @@ export const useTreeViewItemsReordering: TreeViewPlugin { - store.update((prevState) => ({ - ...prevState, - itemsReordering: { - targetItemId: itemId, - draggedItemId: itemId, - action: null, - newPosition: null, - }, - })); + const itemBeingEdited = selectorIsItemBeingEdited(store.value, itemId); + if (!itemBeingEdited) { + store.update((prevState) => ({ + ...prevState, + itemsReordering: { + targetItemId: itemId, + draggedItemId: itemId, + action: null, + newPosition: null, + }, + })); + } }, [store], ); diff --git a/packages/x-tree-view/src/internals/index.ts b/packages/x-tree-view/src/internals/index.ts index 6fa2e3c93e92c..cdb3b1f472156 100644 --- a/packages/x-tree-view/src/internals/index.ts +++ b/packages/x-tree-view/src/internals/index.ts @@ -67,7 +67,10 @@ export type { UseTreeViewItemsState, } from './plugins/useTreeViewItems'; export { useTreeViewLabel } from './plugins/useTreeViewLabel'; -export { selectorIsItemBeingEdited } from './plugins/useTreeViewLabel/useTreeViewLabel.selectors'; +export { + selectorIsItemBeingEdited, + selectorIsAnItemEdited, +} from './plugins/useTreeViewLabel/useTreeViewLabel.selectors'; export type { UseTreeViewLabelSignature, UseTreeViewLabelParameters, diff --git a/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.ts b/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.ts index d0bf65ef4b6bd..1acad19c233c8 100644 --- a/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.ts +++ b/packages/x-tree-view/src/internals/plugins/useTreeViewLabel/useTreeViewLabel.selectors.ts @@ -37,3 +37,11 @@ export const selectorIsItemBeingEdited = createSelector( [selectorTreeViewLabelState, (_, itemId: string | null) => itemId], (labelState, itemId) => (itemId ? labelState.editedItemId === itemId : false), ); +/** + * Check if an item is being edited. + * @param {TreeViewState<[UseTreeViewLabelSignature]>} state The state of the tree view. + * @returns {boolean} `true` if there is an item that is being edited, `false` otherwise. + */ +export const selectorIsAnItemEdited = createSelector(selectorTreeViewLabelState, (labelState) => + Boolean(labelState?.editedItemId), +);