import { useState, useEffect, MouseEvent, useRef, Dispatch, SetStateAction } from 'react'; // Todo // Have selector start at full width and height // dragable icons rotation // drag selector type Coordinates = { x: number; y: number; } interface DraggableBoxProps { position: Coordinates; className?: string; children?: React.ReactNode; coordSetter: Dispatch>; } const DraggableBox = ({ position, className = "", children = "", coordSetter }: DraggableBoxProps) => { const [isDragging, setIsDragging] = useState(false); const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); 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 relativeX = e.clientX - parentRect.left - dragOffset.x; const relativeY = e.clientY - parentRect.top - dragOffset.y; const maxX = parentRect.width; const maxY = parentRect.height; let newX = (Math.max(0, Math.min(relativeX, maxX))); let newY = (Math.max(0, Math.min(relativeY, maxY))); coordSetter({ 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, position.x, position.y]); const handleMouseDown = (e: MouseEvent) => { if (!dragRef.current?.parentElement) return; const parentRect = dragRef.current.parentElement.getBoundingClientRect(); setDragOffset({ x: e.clientX - parentRect.left - position.x, y: e.clientY - parentRect.top - position.y }); setIsDragging(true); }; return (
{children}
); }; export default DraggableBox;