import { useSearchParams } from '@remix-run/react'; import { useState, useEffect, MouseEvent, useRef } from 'react'; interface DraggableBoxProps { tag: string; initialX: number; initialY: number; className?: string; children?: React.ReactNode; } const DraggableBox = ({ tag, initialX, initialY, className = "", children = "" }: DraggableBoxProps) => { const [isDragging, setIsDragging] = useState(false); const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 }); const [searchParams, setSearchParams] = useSearchParams(); const dragRef = useRef(null); const xParam = `x${tag}`; const yParam = `y${tag}`; useEffect(() => { if (!searchParams.has(xParam) || !searchParams.has(yParam)) { const newParams = new URLSearchParams(searchParams); newParams.set(xParam, initialX.toString()); newParams.set(yParam, initialY.toString()); setSearchParams(newParams, { replace: true }); } 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; const newX = Math.max(0, Math.min(relativeX, maxX)); const newY = Math.max(0, Math.min(relativeY, maxY)); const newParams = new URLSearchParams(searchParams); newParams.set(xParam, newX.toString()); newParams.set(yParam, newY.toString()); setSearchParams(newParams, { replace: true }); }; const handleMouseUp = () => setIsDragging(false); window.addEventListener('mousemove', handleMouseMove); window.addEventListener('mouseup', handleMouseUp); return () => { window.removeEventListener('mousemove', handleMouseMove); window.removeEventListener('mouseup', handleMouseUp); }; }, [isDragging, dragOffset, tag, searchParams, initialX, initialY]); const handleMouseDown = (e: MouseEvent) => { if (!dragRef.current?.parentElement) return; const parentRect = dragRef.current.parentElement.getBoundingClientRect(); const currentX = parseInt(searchParams.get(xParam) || '0'); const currentY = parseInt(searchParams.get(yParam) || '0'); setDragOffset({ x: e.clientX - parentRect.left - currentX, y: e.clientY - parentRect.top - currentY }); setIsDragging(true); }; return (
{children}
); }; export default DraggableBox;