diff --git a/src/main/resources/assets/admin/common/js/form2/components/sortable-grid-list/SortableGridList.test.tsx b/src/main/resources/assets/admin/common/js/form2/components/sortable-grid-list/SortableGridList.test.tsx index 5248c305d..e0ec7f405 100644 --- a/src/main/resources/assets/admin/common/js/form2/components/sortable-grid-list/SortableGridList.test.tsx +++ b/src/main/resources/assets/admin/common/js/form2/components/sortable-grid-list/SortableGridList.test.tsx @@ -81,7 +81,8 @@ vi.mock('@dnd-kit/core', () => ({ DndContext: mocks.dndContext, closestCenter: 'closestCenter', KeyboardSensor: 'KeyboardSensor', - PointerSensor: 'PointerSensor', + MouseSensor: 'MouseSensor', + TouchSensor: 'TouchSensor', useSensor: mocks.useSensor, useSensors: mocks.useSensors, })); diff --git a/src/main/resources/assets/admin/common/js/form2/components/sortable-grid-list/SortableGridList.tsx b/src/main/resources/assets/admin/common/js/form2/components/sortable-grid-list/SortableGridList.tsx index c6cff78e8..5af8ab2e2 100644 --- a/src/main/resources/assets/admin/common/js/form2/components/sortable-grid-list/SortableGridList.tsx +++ b/src/main/resources/assets/admin/common/js/form2/components/sortable-grid-list/SortableGridList.tsx @@ -4,7 +4,8 @@ import { type DragEndEvent, type DragStartEvent, KeyboardSensor, - PointerSensor, + MouseSensor, + TouchSensor, useSensor, useSensors, } from '@dnd-kit/core'; @@ -339,7 +340,7 @@ const SortableGridListItem = ({ const rowRef = useRef(null); const {attributes, listeners, setNodeRef, transform, transition, isDragging} = useSortable({ id, - disabled: !isMovable, + disabled: !enabled || !isMovable, }); const handleNodeRef = (node: HTMLDivElement | null) => { @@ -404,7 +405,7 @@ const SortableGridListItem = ({ } } - if (e.target !== e.currentTarget) return; + if (!enabled || e.target !== e.currentTarget) return; (listeners?.onKeyDown as JSX.KeyboardEventHandler)?.(e); }; @@ -412,7 +413,7 @@ const SortableGridListItem = ({ // ? useSortable returns a fresh listeners object each render, so memoizing is a no-op // When fullRowDraggable, dnd-kit listeners must not override the guarded handleKeyDown let rowListenersSafe: Omit, 'onKeyDown'> | undefined; - if (fullRowDraggable && isMovable && listeners != null) { + if (enabled && fullRowDraggable && isMovable && listeners != null) { const {onKeyDown: _ignored, ...rest} = listeners; rowListenersSafe = rest; } @@ -471,7 +472,7 @@ const SortableGridListItem = ({ 'relative flex items-center rounded outline-none', 'focus-visible:ring-2 focus-visible:ring-ring/25 focus-visible:ring-inset', isDragging && 'bg-surface-neutral shadow-[0_2px_8px_2px] shadow-main/10 ring-1 ring-main/5', - fullRowDraggable && isMovable && (isDragging ? 'cursor-grabbing' : 'cursor-grab'), + enabled && fullRowDraggable && isMovable && (isDragging ? 'cursor-grabbing' : 'cursor-grab'), resolvedClassName, )} {...rowListenersSafe} @@ -490,7 +491,7 @@ const SortableGridListItem = ({ tabIndex={-1} disabled={!enabled} aria-label={dragLabel} - {...(fullRowDraggable ? undefined : listeners)} + {...(enabled && !fullRowDraggable ? listeners : undefined)} > @@ -530,7 +531,8 @@ export const SortableGridList = ({ const pendingBlurClearVersionRef = useRef(0); const sensors = useSensors( - useSensor(PointerSensor, {activationConstraint: {distance: 5}}), + useSensor(MouseSensor, {activationConstraint: {distance: 5}}), + useSensor(TouchSensor, {activationConstraint: {delay: 200, tolerance: 5}}), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates, }), diff --git a/src/main/resources/assets/admin/common/js/form2/components/sortable-list/SortableList.tsx b/src/main/resources/assets/admin/common/js/form2/components/sortable-list/SortableList.tsx index 674896e98..456b7fa66 100644 --- a/src/main/resources/assets/admin/common/js/form2/components/sortable-list/SortableList.tsx +++ b/src/main/resources/assets/admin/common/js/form2/components/sortable-list/SortableList.tsx @@ -8,7 +8,8 @@ import { KeyboardSensor, type MeasuringConfiguration, MeasuringStrategy, - PointerSensor, + MouseSensor, + TouchSensor, useSensor, useSensors, } from '@dnd-kit/core'; @@ -221,16 +222,16 @@ const SortableListItem = ({ }); const handleKeyDown: JSX.KeyboardEventHandler = e => { - if (e.target !== e.currentTarget) return; + if (!enabled || e.target !== e.currentTarget) return; (listeners?.onKeyDown as JSX.KeyboardEventHandler)?.(e); }; // When fullRowDraggable, dnd-kit listeners must not override the guarded handleKeyDown const rowListenersSafe = useMemo(() => { - if (!fullRowDraggable || !isMovable || !listeners) return undefined; + if (!enabled || !fullRowDraggable || !isMovable || !listeners) return undefined; const {onKeyDown: _ignored, ...rest} = listeners; return rest; - }, [fullRowDraggable, isMovable, listeners]); + }, [enabled, fullRowDraggable, isMovable, listeners]); const handleFocus = () => setIsFocused(true); @@ -275,7 +276,7 @@ const SortableListItem = ({ tabIndex={-1} disabled={!enabled} aria-label={dragLabel} - {...(fullRowDraggable ? undefined : listeners)} + {...(enabled && !fullRowDraggable ? listeners : undefined)} > @@ -310,8 +311,8 @@ const SortableListItem = ({ isDragging && 'bg-surface-neutral shadow-[0_2px_8px_2px] shadow-main/10 ring-1 ring-main/5', isDragging && !dropAllowed && 'opacity-40', // Full-row drag targets must not turn a press-drag into a text selection. - fullRowDraggable && isMovable && 'touch-none select-none', - fullRowDraggable && isMovable && (isDragging ? 'cursor-grabbing' : 'cursor-grab'), + enabled && fullRowDraggable && isMovable && 'select-none', + enabled && fullRowDraggable && isMovable && (isDragging ? 'cursor-grabbing' : 'cursor-grab'), resolvedClassName, )} {...rowListenersSafe} @@ -357,7 +358,8 @@ export const SortableList = ({ const [drop, setDrop] = useState<{info: SortableDragInfo; hint: SortableDropHint | null} | null>(null); const sensors = useSensors( - useSensor(PointerSensor, {activationConstraint: {distance: 5}}), + useSensor(MouseSensor, {activationConstraint: {distance: 5}}), + useSensor(TouchSensor, {activationConstraint: {delay: 200, tolerance: 5}}), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates, }),