'use client' import PropTypes from 'prop-types' import React, { useCallback, useEffect, useRef } from 'react' export const DraggableComponent = ({ children, moveY = false, moveX = false, minX, minY, maxX, maxY }) => { const elemRef = useRef(null) const dragProps = useRef() useEffect(() => { if (elemRef.current) { elemRef.current.style.left = `${minX | 0}px` elemRef.current.style.top = `${minY | 0}px` } }, [minX, minY]) const initialiseDrag = event => { const { target, clientX, clientY } = event const { offsetTop, offsetLeft } = target const { left, top } = elemRef.current.getBoundingClientRect() dragProps.current = { dragStartLeft: left - offsetLeft, dragStartTop: top - offsetTop, dragStartX: clientX, dragStartY: clientY } window.addEventListener('mousemove', startDragging, false) window.addEventListener('mouseup', stopDragging, false) } const stopDragging = useCallback(() => { window.removeEventListener('mousemove', startDragging, false) window.removeEventListener('mouseup', stopDragging, false) // eslint-disable-next-line react-hooks/exhaustive-deps }, []) const handleChange = ({ touches }) => { const { clientX, clientY } = touches[0] handleValidation({ valueX: clientX, valueY: clientY }) } const startDragging = useCallback(({ clientX, clientY }) => { const valueX = dragProps.current.dragStartLeft + clientX - dragProps.current.dragStartX const valueY = dragProps.current.dragStartTop + clientY - dragProps.current.dragStartY handleValidation({ valueX, valueY }) // eslint-disable-next-line react-hooks/exhaustive-deps }, []) useEffect(() => { return () => { window.removeEventListener('mousemove', startDragging, false) window.removeEventListener('mouseup', stopDragging, false) } // eslint-disable-next-line react-hooks/exhaustive-deps }, []) const handleValidation = useCallback(({ valueX, valueY }) => { if (moveX) { if (maxX && maxX > valueX) { valueX = maxX } else if (minX && minX < valueX) { valueX = minX } elemRef.current.style.left = `${valueX}px` } if (moveY) { if (maxY && maxY > valueY) { valueY = maxY } else if (minY && minY < valueY) { valueY = minY } elemRef.current.style.top = `${valueY}px` } }, [maxX, maxY, minX, minY, moveX, moveY]) return (
{children}
) } DraggableComponent.propTypes = { children: PropTypes.any, maxX: PropTypes.any, maxY: PropTypes.any, minX: PropTypes.number, minY: PropTypes.number, moveX: PropTypes.bool, moveY: PropTypes.bool }