import { useMemo, useCallback } from "react"; import type { ViewPrefsHandle } from "./useViewPrefs.js"; /** * Manages manual drag-to-reorder row ordering for a table. * * - When a column sort is active (sortField !== null), row order is suppressed — * the sorted rows are returned unchanged and dragging is disabled. * - When no column sort is active and a saved rowOrder exists, rows are sorted * by their position in rowOrder; rows without a saved position go to the end. * - Calling reorder() saves the new order and clears any active column sort. * * Each user's rowOrder is persisted independently via useViewPrefs. */ export function useRowOrder( rows: T[], prefs: Pick, activeSortField: string | null, resetSort: () => void, ) { const { rowOrder, setRowOrder } = prefs; const orderedRows = useMemo((): T[] => { // Column sort takes precedence — ignore manual order while sorting if (activeSortField !== null) return rows; if (rowOrder.length === 0) return rows; const indexMap = new Map(rowOrder.map((id, i) => [id, i])); return [...rows].sort((a, b) => { const ai = indexMap.get(a.id) ?? Infinity; const bi = indexMap.get(b.id) ?? Infinity; return ai - bi; }); }, [rows, rowOrder, activeSortField]); const reorder = useCallback( (draggedId: string, targetId: string) => { if (draggedId === targetId) return; // Build current ordered ID list from the current orderedRows snapshot // (works correctly even when rowOrder is empty / partial) const currentIds = orderedRows.map((r) => r.id); const fromIdx = currentIds.indexOf(draggedId); const toIdx = currentIds.indexOf(targetId); if (fromIdx === -1 || toIdx === -1) return; const next = [...currentIds]; next.splice(fromIdx, 1); next.splice(toIdx, 0, draggedId); // Clear any active column sort (mutual exclusion) resetSort(); setRowOrder(next); }, [orderedRows, resetSort, setRowOrder], ); const resetOrder = useCallback(() => { setRowOrder([]); }, [setRowOrder]); const isCustomOrder = rowOrder.length > 0 && activeSortField === null; return { orderedRows, reorder, isCustomOrder, resetOrder }; }