"use client"; import { useCallback, useRef } from "react"; import { useBuilderState } from "./useBuilderState"; interface DragState { id: string; startX: number; startY: number; origX: number; origY: number; origW: number; origH: number; mode: "move" | "resize"; } /** * 블록 드래그(이동)/리사이즈 훅. * mousedown → mousemove → mouseup 패턴. * Shift 키: 8px 스냅. */ export function useBlockDrag() { const dragRef = useRef(null); const moveBlock = useBuilderState((s) => s.moveBlock); const resizeBlock = useBuilderState((s) => s.resizeBlock); const selectBlock = useBuilderState((s) => s.selectBlock); const startDrag = useCallback( (e: React.MouseEvent, id: string, origX: number, origY: number, origW: number, origH: number) => { e.preventDefault(); e.stopPropagation(); selectBlock(id); dragRef.current = { id, startX: e.clientX, startY: e.clientY, origX, origY, origW, origH, mode: "move" }; document.body.style.cursor = "grabbing"; document.body.style.userSelect = "none"; const onMove = (ev: MouseEvent) => { const d = dragRef.current; if (!d || d.mode !== "move") return; let nx = d.origX + (ev.clientX - d.startX); let ny = d.origY + (ev.clientY - d.startY); if (ev.shiftKey) { nx = Math.round(nx / 8) * 8; ny = Math.round(ny / 8) * 8; } moveBlock(d.id, Math.round(nx), Math.round(ny)); }; const onUp = () => { dragRef.current = null; document.body.style.cursor = ""; document.body.style.userSelect = ""; document.removeEventListener("mousemove", onMove); document.removeEventListener("mouseup", onUp); }; document.addEventListener("mousemove", onMove); document.addEventListener("mouseup", onUp); }, [moveBlock, selectBlock] ); const startResize = useCallback( (e: React.MouseEvent, id: string, origX: number, origY: number, origW: number, origH: number) => { e.preventDefault(); e.stopPropagation(); dragRef.current = { id, startX: e.clientX, startY: e.clientY, origX, origY, origW, origH, mode: "resize" }; document.body.style.cursor = "nwse-resize"; document.body.style.userSelect = "none"; const onMove = (ev: MouseEvent) => { const d = dragRef.current; if (!d || d.mode !== "resize") return; let nw = d.origW + (ev.clientX - d.startX); let nh = d.origH + (ev.clientY - d.startY); if (ev.shiftKey) { nw = Math.round(nw / 8) * 8; nh = Math.round(nh / 8) * 8; } resizeBlock(d.id, Math.round(nw), Math.round(nh)); }; const onUp = () => { dragRef.current = null; document.body.style.cursor = ""; document.body.style.userSelect = ""; document.removeEventListener("mousemove", onMove); document.removeEventListener("mouseup", onUp); }; document.addEventListener("mousemove", onMove); document.addEventListener("mouseup", onUp); }, [resizeBlock] ); return { startDrag, startResize }; }