import { useState, useEffect, MouseEvent, useRef, Dispatch, SetStateAction } from 'react'; type Coordinates = { x: number; y: number; } interface DraggableBoxProps { initialX: number; initialY: number; className?: string; children?: React.ReactNode; setter?: Dispatch>; } const DraggableBox = ({ initialX, initialY, className = "", children = "", setter }: DraggableBoxProps) => { const [isDragging, setIsDragging] = useState(false); const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); const [xPosition, setXPosition] = useState(initialX) const [yPosition, setYPosition] = useState(initialY) const dragRef = useRef(null); useEffect(() => { if (!isDragging) return; const handleMouseMove = (e: globalThis.MouseEvent) => { if (!dragRef.current?.parentElement) return; const parent = dragRef.current.parentElement; const parentRect = parent.getBoundingClientRect(); const boxRect = dragRef.current.getBoundingClientRect(); const relativeX = e.clientX - parentRect.left - dragOffset.x; const relativeY = e.clientY - parentRect.top - dragOffset.y; const maxX = parentRect.width - boxRect.width; const maxY = parentRect.height - boxRect.height; let newX = (Math.max(0, Math.min(relativeX, maxX))); let newY = (Math.max(0, Math.min(relativeY, maxY))); setXPosition(newX); setYPosition(newY); if (setter) { setter({ x: newX, y: newY }) } }; const handleMouseUp = () => setIsDragging(false); window.addEventListener('mousemove', handleMouseMove); window.addEventListener('mouseup', handleMouseUp); return () => { window.removeEventListener('mousemove', handleMouseMove); window.removeEventListener('mouseup', handleMouseUp); }; }, [isDragging, dragOffset, xPosition, yPosition, initialX, initialY]); const handleMouseDown = (e: MouseEvent) => { if (!dragRef.current?.parentElement) return; const parentRect = dragRef.current.parentElement.getBoundingClientRect(); setDragOffset({ x: e.clientX - parentRect.left - xPosition, y: e.clientY - parentRect.top - yPosition }); setIsDragging(true); }; return (
{children}
); }; export default DraggableBox;