import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from "lucide-react"; import { PAGE_SIZES } from "~/components/console/use-list-pagination.ts"; import { Button } from "~/components/ui/button.tsx"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "~/components/ui/select.tsx"; import { cn } from "~/lib/utils.ts"; export type PaginationProps = { page: number; pageSize: number; /** With hasMore, total is the loaded count, not a complete total. */ total: number; hasMore?: boolean; busy?: boolean; onPageChange: (page: number) => void; onPageSizeChange?: (size: number) => void; className?: string; /** 一页放得下时整块不显示(卡片网格下面单独一行「共 N 条」显得悬空) */ hideSingle?: boolean; }; export function pageNumbers(page: number, pages: number): (number | "…")[] { const values = new Set([1, pages, page - 1, page, page + 1]); const valid = [...values].filter((n) => n >= 1 && n <= pages).sort((a, b) => a - b); return valid.flatMap((n, i): (number | "…")[] => (i && n - valid[i - 1] > 1 ? ["…", n] : [n])); } /** * 表格、卡片列表与游标列表共用的分页。 * 一页就放得下(只有 1 页、没有更多)时不显示翻页按钮,只留总数;连每页条数也用不上(不超过最小档)时只剩总数; * 没有任何条目时整块不渲染(空态已经说明)。翻页按钮按容器宽度收起(`@container`):窄卡片里不折成两行。 */ export function Pagination({ page, pageSize, total, hasMore = false, busy = false, onPageChange, onPageSizeChange, className, hideSingle = false, }: PaginationProps) { const loadedPages = Math.max(1, Math.ceil(total / pageSize)); const pages = loadedPages + (hasMore ? 1 : 0); const from = total ? (page - 1) * pageSize + 1 : 0; const to = Math.min(page * pageSize, total); if (!total && !hasMore) return null; const single = pages <= 1; const showSize = !!onPageSizeChange && total > PAGE_SIZES[0]; if (single && hideSingle && !showSize) return null; return (