aboutsummaryrefslogtreecommitdiffstats
path: root/apps/web/lib/drag-and-drop.ts
blob: e005a6d0410c16c98d173654ef428ffd9bbe4552 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import React from "react";
import { DraggableData, DraggableEvent } from "react-draggable";

export function useDragAndDrop(
  dragSourceIdAttribute: string,
  dragTargetIdAttribute: string,
  onDragOver: (dragSourceId: string, dragTargetId: string) => void,
) {
  const [dragSourceId, setDragSourceId] = React.useState<string | null>(null);

  const handleDragStart = React.useCallback(
    (_e: DraggableEvent, { node }: DraggableData) => {
      const id = node.getAttribute(dragSourceIdAttribute);
      setDragSourceId(id);
    },
    [],
  );

  const handleDragEnd = React.useCallback(
    (e: DraggableEvent) => {
      const { target } = e;
      const dragTargetId = (target as HTMLElement).getAttribute(
        dragTargetIdAttribute,
      );

      if (dragSourceId && dragTargetId && dragSourceId !== dragTargetId) {
        /*
          As Draggable tries to setState when the 
          component is unmounted, it is needed to
          push onCombine to the event loop queue.
          onCombine would be run after setState on
          Draggable so it would fix the issue until
          they fix it on their end.
      */
        setTimeout(() => {
          onDragOver(dragSourceId, dragTargetId);
        }, 0);
      }
      setDragSourceId(null);
    },
    [dragSourceId, onDragOver],
  );

  return {
    handleDragStart,
    handleDragEnd,
  };
}