import { useCallback, useRef, useState } from "react" export type ResizeEdge = "left" | "right" interface UseSegmentResizeOptions { pixelsPerSecond: number onResize: (index: number, edge: ResizeEdge, deltaSec: number) => void onResizeEnd: (index: number, edge: ResizeEdge) => void } export function useSegmentResize({ pixelsPerSecond, onResize, onResizeEnd, }: UseSegmentResizeOptions) { const [resizingIndex, setResizingIndex] = useState(-1) const [resizingEdge, setResizingEdge] = useState(null) const startXRef = useRef(0) const accDeltaRef = useRef(0) const indexRef = useRef(-1) const edgeRef = useRef("left") const ppsRef = useRef(pixelsPerSecond) ppsRef.current = pixelsPerSecond // Use refs for callbacks to avoid stale closures in event listeners const onResizeRef = useRef(onResize) onResizeRef.current = onResize const onResizeEndRef = useRef(onResizeEnd) onResizeEndRef.current = onResizeEnd const justResizedRef = useRef(false) // Stable references that never change — safe for addEventListener/removeEventListener const moveHandlerRef = useRef<((e: PointerEvent) => void) | null>(null) const upHandlerRef = useRef<((e: PointerEvent) => void) | null>(null) if (!moveHandlerRef.current) { moveHandlerRef.current = (e: PointerEvent) => { const dx = e.clientX - startXRef.current const deltaSec = dx / ppsRef.current const prevDelta = accDeltaRef.current const incrementalDelta = deltaSec - prevDelta accDeltaRef.current = deltaSec onResizeRef.current(indexRef.current, edgeRef.current, incrementalDelta) } } if (!upHandlerRef.current) { upHandlerRef.current = (e: PointerEvent) => { document.removeEventListener("pointermove", moveHandlerRef.current!) document.removeEventListener("pointerup", upHandlerRef.current!) onResizeEndRef.current(indexRef.current, edgeRef.current) setResizingIndex(-1) setResizingEdge(null) justResizedRef.current = true setTimeout(() => { justResizedRef.current = false }, 200) } } const handlePointerDown = useCallback( (e: React.PointerEvent, index: number, edge: ResizeEdge) => { e.stopPropagation() e.preventDefault() startXRef.current = e.clientX accDeltaRef.current = 0 indexRef.current = index edgeRef.current = edge setResizingIndex(index) setResizingEdge(edge) document.addEventListener("pointermove", moveHandlerRef.current!) document.addEventListener("pointerup", upHandlerRef.current!) }, [], ) return { handlePointerDown, resizingIndex, resizingEdge, justResizedRef, } }