From 03dc07976e5df63c5672e6ce8147991df6ced267 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 16 Sep 2026 19:01:30 +0000 Subject: [PATCH] fix(rundown): apply the active data fallback to drag over expandOverGroup read the dragged element type straight from dnd-kit, so once the virtualiser unmounted a dragged group the guard stopped matching and dragging over a collapsed group expanded it. canDrop then saw an expanded target and rejected an otherwise valid drop after that group. Both handlers now resolve the active data through the same helper, which falls back to the drag start snapshot. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01TEnUVARPnSqXijiz8KiLiE --- .../features/rundown/hooks/useRundownDnd.ts | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/apps/client/src/features/rundown/hooks/useRundownDnd.ts b/apps/client/src/features/rundown/hooks/useRundownDnd.ts index 21b369e90..dca09ad8b 100644 --- a/apps/client/src/features/rundown/hooks/useRundownDnd.ts +++ b/apps/client/src/features/rundown/hooks/useRundownDnd.ts @@ -1,4 +1,5 @@ import { + type Active, type Data, DragEndEvent, DragOverEvent, @@ -44,6 +45,15 @@ export function useRundownDnd({ const activeDataRef = useRef(null); const [activeId, setActiveId] = useState(null); + /** + * Resolves the data of the dragged element + * If the element was unmounted by the virtualiser, dnd-kit gives us empty data + * in which case we fallback to the snapshot taken on drag start + */ + const getActiveData = useCallback((active: Active): Data | null => { + return active.data.current?.sortable ? active.data.current : activeDataRef.current; + }, []); + /** * Discards any reference to the dragged element, also used as the drag cancel handler */ @@ -59,9 +69,7 @@ export function useRundownDnd({ const handleOnDragEnd = useCallback( (event: DragEndEvent) => { const { active, over } = event; - // if the dragged element was unmounted by the virtualiser, dnd-kit gives us empty data - // in which case we fallback to the snapshot taken on drag start - const activeData = active.data.current?.sortable ? active.data.current : activeDataRef.current; + const activeData = getActiveData(active); clearActive(); if (!over?.id || active.id === over.id) { @@ -131,7 +139,7 @@ export function useRundownDnd({ setSortableData(currentEntries); }); }, - [entries, sortableData, setSortableData, getIsCollapsed, reorderEntry], + [entries, sortableData, setSortableData, getIsCollapsed, reorderEntry, getActiveData, clearActive], ); /** @@ -159,7 +167,8 @@ export function useRundownDnd({ const expandOverGroup = useCallback( (event: DragOverEvent) => { // if we are dragging a group, the drop operation is invalid so we dont expand - if (event.active.data.current?.type === SupportedEntry.Group) { + // expanding the group here would also make an otherwise valid drop after it invalid + if (getActiveData(event.active)?.type === SupportedEntry.Group) { return; } if (event.over?.data.current?.type !== SupportedEntry.Group) { @@ -169,7 +178,7 @@ export function useRundownDnd({ const groupId = event.over?.id as EntryId | undefined; handleCollapseGroup(false, groupId); }, - [handleCollapseGroup], + [handleCollapseGroup, getActiveData], ); return useMemo(