import { Button, Combobox } from "@tailor-platform/app-shell"; import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from "lucide-react"; import { useState } from "react"; /** * Client-side pagination state for editable line tables that must keep every * row in memory (e.g. forms that diff against the full set, drag-reorder, or * CSV full-replace) but still page the display like the list DataTables. * * The page is clamped during render (rows may be added/removed) rather than * synced back through an effect, so all state changes stay user-driven. */ export function useClientPagination(total: number, defaultPageSize = 100) { const [page, setPage] = useState(0); const [pageSize, setPageSize] = useState(defaultPageSize); const pageCount = Math.max(1, Math.ceil(total / pageSize)); const safePage = Math.min(Math.max(0, page), pageCount - 1); return { page: safePage, pageSize, pageCount, start: safePage * pageSize, end: safePage * pageSize + pageSize, setPage, setPageSize: (size: number) => { setPageSize(size); setPage(0); }, }; } interface SizeOption { value: number; } /** * Pagination footer for the editable line tables. The real app-shell * `DataTable.Pagination` can't host these forms' editable / dnd-kit rows, so * this mirrors its markup, labels, and controls (row count, "Rows per page" * selector, "Page r / n", First/Prev/Next/Last outline icon buttons) so it * reads as the same control as the list pages. */ export function LinesFooter({ total, page, pageSize, pageSizeOptions = [10, 25, 50, 100], onPageChange, onPageSizeChange, }: { total: number; page: number; pageSize: number; pageSizeOptions?: number[]; onPageChange: (page: number) => void; onPageSizeChange: (size: number) => void; }) { const pageCount = Math.max(1, Math.ceil(total / pageSize)); const hasPrev = page > 0; const hasNext = page < pageCount - 1; const sizeOptions: SizeOption[] = pageSizeOptions.map((value) => ({ value })); return (
{total} row(s)
Rows per page ({ label: String(o.value), key: String(o.value) })} value={sizeOptions.find((o) => o.value === pageSize) ?? null} onValueChange={(o: SizeOption | null) => o && onPageSizeChange(o.value)} className="w-[4.5rem]" />
Page {page + 1} / {pageCount}
); }