Skip to content

Commit 6d1057c

Browse files
psychedelicioushipsterusername
authored andcommitted
fix(ui): skip firing collision detection on dnd when droppable scrolled out
Requires some additional logic in the collision detection algorithm. Closes #4621
1 parent b479000 commit 6d1057c

File tree

3 files changed

+41
-3
lines changed

3 files changed

+41
-3
lines changed

invokeai/frontend/web/src/common/components/IAIDroppable.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const IAIDroppable = (props: IAIDroppableProps) => {
3131
insetInlineStart={0}
3232
w="full"
3333
h="full"
34-
pointerEvents="none"
34+
pointerEvents={active ? 'auto' : 'none'}
3535
>
3636
<AnimatePresence>
3737
{isValidDrop(data, active) && (

invokeai/frontend/web/src/features/dnd/components/AppDndContext.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import {
22
DragOverlay,
33
MouseSensor,
44
TouchSensor,
5-
pointerWithin,
65
useSensor,
76
useSensors,
87
} from '@dnd-kit/core';
@@ -14,6 +13,7 @@ import { AnimatePresence, motion } from 'framer-motion';
1413
import { PropsWithChildren, memo, useCallback, useState } from 'react';
1514
import { useScaledModifer } from '../hooks/useScaledCenteredModifer';
1615
import { DragEndEvent, DragStartEvent, TypesafeDraggableData } from '../types';
16+
import { customPointerWithin } from '../util/customPointerWithin';
1717
import { DndContextTypesafe } from './DndContextTypesafe';
1818
import DragPreview from './DragPreview';
1919

@@ -77,7 +77,7 @@ const AppDndContext = (props: PropsWithChildren) => {
7777
onDragStart={handleDragStart}
7878
onDragEnd={handleDragEnd}
7979
sensors={sensors}
80-
collisionDetection={pointerWithin}
80+
collisionDetection={customPointerWithin}
8181
autoScroll={false}
8282
>
8383
{props.children}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { CollisionDetection, pointerWithin } from '@dnd-kit/core';
2+
3+
/**
4+
* Filters out droppable elements that are overflowed, then applies the pointerWithin collision detection.
5+
*
6+
* Fixes collision detection firing on droppables that are not visible, having been scrolled out of view.
7+
*
8+
* See https://github.com/clauderic/dnd-kit/issues/1198
9+
*/
10+
export const customPointerWithin: CollisionDetection = (arg) => {
11+
if (!arg.pointerCoordinates) {
12+
// sanity check
13+
return [];
14+
}
15+
16+
// Get all elements at the pointer coordinates. This excludes elements which are overflowed,
17+
// so it won't include the droppable elements that are scrolled out of view.
18+
const targetElements = document.elementsFromPoint(
19+
arg.pointerCoordinates.x,
20+
arg.pointerCoordinates.y
21+
);
22+
23+
const filteredDroppableContainers = arg.droppableContainers.filter(
24+
(container) => {
25+
if (!container.node.current) {
26+
return false;
27+
}
28+
// Only include droppable elements that are in the list of elements at the pointer coordinates.
29+
return targetElements.includes(container.node.current);
30+
}
31+
);
32+
33+
// Run the provided collision detection with the filtered droppable elements.
34+
return pointerWithin({
35+
...arg,
36+
droppableContainers: filteredDroppableContainers,
37+
});
38+
};

0 commit comments

Comments
 (0)