file-tree-draggable-preview-layer.js 2.0 KB

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