import React, { useCallback, useRef, useState } from "react"; // Native HTML5 drag-and-drop reordering — zero dependencies. Pointer users drag; keyboard users use // the up/down buttons the lists also render (the accessible path). Returns per-item props plus the // current drag/over indices so the caller can animate (dragged item dims, drop target shows a line). export function useDragReorder(onReorder: (from: number, to: number) => void) { const [dragIndex, setDragIndex] = useState(null); const [overIndex, setOverIndex] = useState(null); // Drop clears the rendered state before the source receives dragend. const ownsGesture = useRef(false); const reset = useCallback(() => { setDragIndex(null); setOverIndex(null); }, []); const getItemProps = useCallback( (index: number) => ({ draggable: true, onDragStart: (e: React.DragEvent) => { e.stopPropagation(); ownsGesture.current = true; setDragIndex(index); e.dataTransfer.effectAllowed = "move"; // Firefox needs data set for a drag to start. e.dataTransfer.setData("text/plain", String(index)); }, onDragOver: (e: React.DragEvent) => { if (dragIndex === null) return; e.stopPropagation(); e.preventDefault(); e.dataTransfer.dropEffect = "move"; if (overIndex !== index) setOverIndex(index); }, onDrop: (e: React.DragEvent) => { e.preventDefault(); if (dragIndex === null) return; e.stopPropagation(); if (dragIndex !== index) onReorder(dragIndex, index); reset(); }, onDragEnd: (e: React.DragEvent) => { if (ownsGesture.current) e.stopPropagation(); ownsGesture.current = false; reset(); }, }), [dragIndex, overIndex, onReorder, reset], ); return { dragIndex, overIndex, getItemProps }; }