import { useRef, useCallback, MouseEvent } from 'react'; const DRAG_THRESHOLD = 5; export default function useDragScroll() { const ref = useRef(null); const isDragging = useRef(false); const hasMoved = useRef(false); const startX = useRef(0); const scrollLeft = useRef(0); const onMouseDown = useCallback((e: MouseEvent) => { const el = ref.current; if (!el) return; e.preventDefault(); isDragging.current = true; hasMoved.current = false; startX.current = e.pageX - el.offsetLeft; scrollLeft.current = el.scrollLeft; el.style.cursor = 'grabbing'; }, []); const onMouseMove = useCallback((e: MouseEvent) => { if (!isDragging.current) return; const el = ref.current; if (!el) return; const x = e.pageX - el.offsetLeft; const walk = x - startX.current; if (!hasMoved.current && Math.abs(walk) > DRAG_THRESHOLD) { hasMoved.current = true; el.style.pointerEvents = 'auto'; for (const child of el.children) { (child as HTMLElement).style.pointerEvents = 'none'; } } e.preventDefault(); el.scrollLeft = scrollLeft.current - walk; }, []); const resetState = useCallback(() => { isDragging.current = false; const el = ref.current; if (!el) return; el.style.cursor = 'grab'; if (hasMoved.current) { for (const child of el.children) { (child as HTMLElement).style.pointerEvents = ''; } } hasMoved.current = false; }, []); const onMouseUp = useCallback(() => resetState(), [resetState]); const onMouseLeave = useCallback(() => resetState(), [resetState]); return { ref, onMouseDown, onMouseMove, onMouseUp, onMouseLeave, }; }