file-tree-draggable-preview-layer.tsx 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. import { useRef } from 'react'
  2. import classNames from 'classnames'
  3. import { XYCoord } from 'react-dnd'
  4. // a custom component rendered on top of a draggable area that renders the
  5. // dragged item. See
  6. // https://react-dnd.github.io/react-dnd/examples/drag-around/custom-drag-layer
  7. // for more details.
  8. // Also used to display a container border when hovered.
  9. function FileTreeDraggablePreviewLayer({
  10. isOver,
  11. isDragging,
  12. item,
  13. clientOffset,
  14. }: {
  15. isOver: boolean
  16. isDragging: boolean
  17. item: { title: string }
  18. clientOffset: XYCoord | null
  19. }) {
  20. const ref = useRef<HTMLDivElement>(null)
  21. return (
  22. <div
  23. ref={ref}
  24. className={classNames('dnd-draggable-preview-layer', {
  25. 'dnd-droppable-hover': isOver,
  26. })}
  27. >
  28. {isDragging && item?.title && (
  29. <div
  30. style={getItemStyle(
  31. clientOffset,
  32. ref.current?.getBoundingClientRect()
  33. )}
  34. >
  35. <DraggablePreviewItem title={item.title} />
  36. </div>
  37. )}
  38. </div>
  39. )
  40. }
  41. function DraggablePreviewItem({ title }: { title: string }) {
  42. return <div className="dnd-draggable-preview-item">{title}</div>
  43. }
  44. // makes the preview item follow the cursor.
  45. // See https://react-dnd.github.io/react-dnd/docs/api/drag-layer-monitor
  46. function getItemStyle(
  47. clientOffset: XYCoord | null,
  48. containerOffset: DOMRect | undefined
  49. ) {
  50. if (!containerOffset || !clientOffset) {
  51. return {
  52. display: 'none',
  53. }
  54. }
  55. const { x: containerX, y: containerY } = containerOffset
  56. const { x: clientX, y: clientY } = clientOffset
  57. const posX = clientX - containerX - 15
  58. const posY = clientY - containerY - 15
  59. const transform = `translate(${posX}px, ${posY}px)`
  60. return {
  61. transform,
  62. WebkitTransform: transform,
  63. }
  64. }
  65. export default FileTreeDraggablePreviewLayer