Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | import { useState, useRef, useCallback } from 'react' interface UseQuadDragOptions { containerRef: React.RefObject<HTMLDivElement | null> } export function useQuadDrag({ containerRef }: UseQuadDragOptions) { const quadRef = useRef<HTMLDivElement>(null) const quadDragRef = useRef<{ startX: number startY: number origX: number origY: number } | null>(null) const [quadOffset, setQuadOffset] = useState({ x: 0, y: 0 }) const [quadDragging, setQuadDragging] = useState(false) const handleQuadPointerDown = useCallback( (e: React.PointerEvent) => { e.preventDefault() e.stopPropagation() const el = e.currentTarget el.setPointerCapture(e.pointerId) quadDragRef.current = { startX: e.clientX, startY: e.clientY, origX: quadOffset.x, origY: quadOffset.y, } setQuadDragging(true) }, [quadOffset] ) const handleQuadPointerMove = useCallback((e: React.PointerEvent) => { const drag = quadDragRef.current if (!drag) return e.preventDefault() const dx = e.clientX - drag.startX const dy = e.clientY - drag.startY let newX = drag.origX + dx let newY = drag.origY + dy // Clamp so the quad stays within the canvas pane bounds. const container = containerRef.current const root = container?.parentElement // euclid-canvas root if (container && root) { const rootW = root.clientWidth const rootH = root.clientHeight const cw = container.clientWidth const ch = container.clientHeight const QUAD_SIZE = 76 const MARGIN = 12 const baseX = cw - MARGIN - QUAD_SIZE const baseY = ch - MARGIN - QUAD_SIZE const quadLeft = baseX + newX const quadTop = baseY + newY const clampedLeft = Math.max(0, Math.min(quadLeft, rootW - QUAD_SIZE)) const clampedTop = Math.max(0, Math.min(quadTop, rootH - QUAD_SIZE)) newX = clampedLeft - baseX newY = clampedTop - baseY } setQuadOffset({ x: newX, y: newY }) }, []) const handleQuadPointerUp = useCallback((e: React.PointerEvent) => { if (!quadDragRef.current) return e.currentTarget.releasePointerCapture(e.pointerId) quadDragRef.current = null setQuadDragging(false) }, []) return { quadRef, quadOffset, quadDragging, handleQuadPointerDown, handleQuadPointerMove, handleQuadPointerUp, } } |