DragAndDropWrapper.tsx 1.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. import type { ReactNode } from 'react';
  2. import { useDrag, useDrop } from 'react-dnd';
  3. import type { DragItemDataType } from '~/interfaces/bookmark-info';
  4. type DragAndDropWrapperProps = {
  5. item?: Partial<DragItemDataType>
  6. type: string[]
  7. children: ReactNode
  8. useDragMode?: boolean
  9. useDropMode?: boolean
  10. onDropItem?:(item: DragItemDataType, type: string | null | symbol) => Promise<void>
  11. isDropable?:(item: Partial<DragItemDataType>, type: string | null | symbol) => boolean
  12. }
  13. export const DragAndDropWrapper = (props: DragAndDropWrapperProps): JSX.Element => {
  14. const {
  15. item, children, useDragMode, useDropMode, type, onDropItem, isDropable,
  16. } = props;
  17. const acceptedTypes = type;
  18. const sourcetype: string | symbol = type[0];
  19. const [, dragRef] = useDrag({
  20. type: sourcetype,
  21. item,
  22. collect: monitor => ({
  23. isDragging: monitor.isDragging(),
  24. canDrag: monitor.canDrag(),
  25. }),
  26. });
  27. const [{ isOver }, dropRef] = useDrop(() => ({
  28. accept: acceptedTypes,
  29. drop: (item: DragItemDataType, monitor) => {
  30. const itemType: string | null | symbol = monitor.getItemType();
  31. if (onDropItem != null) {
  32. onDropItem(item, itemType);
  33. }
  34. },
  35. canDrop: (item, monitor) => {
  36. const itemType: string | null | symbol = monitor.getItemType();
  37. if (isDropable != null) {
  38. return isDropable(item, itemType);
  39. }
  40. return false;
  41. },
  42. collect: monitor => ({
  43. isOver: monitor.isOver({ shallow: true }) && monitor.canDrop(),
  44. }),
  45. }));
  46. const getCallback = (c: HTMLDivElement | null) => {
  47. if (useDragMode && useDropMode) {
  48. dragRef(c);
  49. dropRef(c);
  50. }
  51. else if (useDragMode) {
  52. dragRef(c);
  53. }
  54. else if (useDropMode) {
  55. dropRef(c);
  56. }
  57. };
  58. return (
  59. <div ref={getCallback} className={`grw-drag-drop-container ${isOver ? 'grw-accept-drop-item' : ''}`}>
  60. {children}
  61. </div>
  62. );
  63. };