DragAndDropWrapper.tsx 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import React, { ReactNode } from 'react';
  2. import { useDrag, useDrop } from 'react-dnd';
  3. import { 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 getRef = (c: HTMLDivElement | null) => {
  47. if (useDragMode && useDropMode) {
  48. return [dragRef(c), dropRef(c)];
  49. } if (useDragMode) {
  50. return dragRef(c);
  51. } if (useDropMode) {
  52. return dropRef(c);
  53. }
  54. return null;
  55. };
  56. return (
  57. <div ref={c => getRef(c)} className={`grw-drag-drop-container ${isOver ? 'grw-accept-drop-item' : ''}`}>
  58. {children}
  59. </div>
  60. );
  61. };