file-tree-draggable-preview-layer.jsx 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. import { useRef } from 'react'
  2. import PropTypes from 'prop-types'
  3. import classNames from 'classnames'
  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. const ref = useRef()
  16. return (
  17. <div
  18. ref={ref}
  19. className={classNames('dnd-draggable-preview-layer', {
  20. 'dnd-droppable-hover': isOver,
  21. })}
  22. >
  23. {isDragging && item?.title && (
  24. <div
  25. style={getItemStyle(
  26. clientOffset,
  27. ref.current?.getBoundingClientRect()
  28. )}
  29. >
  30. <DraggablePreviewItem title={item.title} />
  31. </div>
  32. )}
  33. </div>
  34. )
  35. }
  36. FileTreeDraggablePreviewLayer.propTypes = {
  37. isOver: PropTypes.bool.isRequired,
  38. isDragging: PropTypes.bool.isRequired,
  39. item: PropTypes.shape({
  40. title: PropTypes.string.isRequired,
  41. }),
  42. clientOffset: PropTypes.shape({
  43. x: PropTypes.number,
  44. y: PropTypes.number,
  45. }),
  46. }
  47. function DraggablePreviewItem({ title }) {
  48. return <div className="dnd-draggable-preview-item">{title}</div>
  49. }
  50. DraggablePreviewItem.propTypes = {
  51. title: PropTypes.string.isRequired,
  52. }
  53. // makes the preview item follow the cursor.
  54. // See https://react-dnd.github.io/react-dnd/docs/api/drag-layer-monitor
  55. function getItemStyle(clientOffset, containerOffset) {
  56. if (!containerOffset || !clientOffset) {
  57. return {
  58. display: 'none',
  59. }
  60. }
  61. const { x: containerX, y: containerY } = containerOffset
  62. const { x: clientX, y: clientY } = clientOffset
  63. const posX = clientX - containerX - 15
  64. const posY = clientY - containerY - 15
  65. const transform = `translate(${posX}px, ${posY}px)`
  66. return {
  67. transform,
  68. WebkitTransform: transform,
  69. }
  70. }
  71. export default FileTreeDraggablePreviewLayer