@@ -26,13 +26,19 @@ const useDragAndDrop: UseDragAndDrop = ({
2626 const [ isDraggingOver , setIsDraggingOver ] = useState ( false ) ;
2727 const { close : closePopover } = useContext ( PopoverContext ) ;
2828
29- const enterTarget = useRef < EventTarget | null > ( null ) ;
29+ const dragCounter = useRef ( 0 ) ;
30+ const debounceTimeoutRef = useRef < NodeJS . Timeout | null > ( null ) ;
3031
3132 useEffect ( ( ) => {
3233 if ( isFocused && ! isDisabled ) {
3334 return ;
3435 }
3536 setIsDraggingOver ( false ) ;
37+ dragCounter . current = 0 ;
38+ if ( debounceTimeoutRef . current ) {
39+ clearTimeout ( debounceTimeoutRef . current ) ;
40+ debounceTimeoutRef . current = null ;
41+ }
3642 } , [ isFocused , isDisabled ] ) ;
3743
3844 const handleDragEvent = useCallback (
@@ -73,30 +79,35 @@ const useDragAndDrop: UseDragAndDrop = ({
7379 event . stopPropagation ( ) ;
7480 }
7581
82+ // Clear any existing debounce timeout
83+ if ( debounceTimeoutRef . current ) {
84+ clearTimeout ( debounceTimeoutRef . current ) ;
85+ debounceTimeoutRef . current = null ;
86+ }
87+
7688 switch ( event . type ) {
7789 case DRAG_OVER_EVENT :
7890 handleDragEvent ( event ) ;
7991 break ;
8092 case DRAG_ENTER_EVENT :
8193 handleDragEvent ( event ) ;
82- enterTarget . current = event . target ;
83- if ( isDraggingOver ) {
84- return ;
94+ dragCounter . current += 1 ;
95+ if ( dragCounter . current === 1 && ! isDraggingOver ) {
96+ setIsDraggingOver ( true ) ;
8597 }
86- setIsDraggingOver ( true ) ;
8798 break ;
8899 case DRAG_LEAVE_EVENT :
89- if ( ! isDraggingOver ) {
90- return ;
100+ dragCounter . current -= 1 ;
101+ if ( dragCounter . current <= 0 ) {
102+ dragCounter . current = 0 ;
103+ // Add small debounce to prevent rapid flickering
104+ debounceTimeoutRef . current = setTimeout ( ( ) => {
105+ setIsDraggingOver ( false ) ;
106+ } , 50 ) ;
91107 }
92- // This is necessary because dragging over children will cause dragleave to execute on the parent.
93- if ( enterTarget . current !== event . target ) {
94- return ;
95- }
96-
97- setIsDraggingOver ( false ) ;
98108 break ;
99109 case DROP_EVENT :
110+ dragCounter . current = 0 ;
100111 setIsDraggingOver ( false ) ;
101112 onDrop ( event ) ;
102113 break ;
0 commit comments