46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
"use client";
|
|
|
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
|
|
export function Pagination({
|
|
page,
|
|
pageSize,
|
|
total,
|
|
label = "分页",
|
|
onPageChange
|
|
}: {
|
|
page: number;
|
|
pageSize: number;
|
|
total: number;
|
|
label?: string;
|
|
onPageChange: (page: number) => void;
|
|
}) {
|
|
const totalPages = pageCount(total, pageSize);
|
|
if (totalPages <= 1) return null;
|
|
const current = clampPage(page, total, pageSize);
|
|
return (
|
|
<nav className="pagination" aria-label={label}>
|
|
<button className="icon-button" type="button" title="上一页" disabled={current <= 1} onClick={() => onPageChange(current - 1)}>
|
|
<ChevronLeft size={17} />
|
|
</button>
|
|
<span className="pager-meta">{current} / {totalPages}</span>
|
|
<button className="icon-button" type="button" title="下一页" disabled={current >= totalPages} onClick={() => onPageChange(current + 1)}>
|
|
<ChevronRight size={17} />
|
|
</button>
|
|
</nav>
|
|
);
|
|
}
|
|
|
|
export function clampPage(page: number, total: number, pageSize: number) {
|
|
return Math.min(Math.max(1, page), pageCount(total, pageSize));
|
|
}
|
|
|
|
export function pageItems<T>(items: T[], page: number, pageSize: number) {
|
|
const current = clampPage(page, items.length, pageSize);
|
|
return items.slice((current - 1) * pageSize, current * pageSize);
|
|
}
|
|
|
|
function pageCount(total: number, pageSize: number) {
|
|
return Math.max(1, Math.ceil(total / pageSize));
|
|
}
|