1import Link from 'next/link';2import { cn } from '@/lib/format';34/** URL-driven pagination: keeps every other search param. */5export function Pagination({ page, pageSize, total, basePath, params, className }: { page: number; pageSize: number; total: number; basePath: string; params: Record<string, string | undefined>; className?: string }) {6 const pages = Math.max(1, Math.ceil(total / pageSize));7 if (pages <= 1) return null;8 const href = (p: number) => {9 const sp = new URLSearchParams();10 for (const [k, v] of Object.entries(params)) if (v) sp.set(k, v);11 if (p > 1) sp.set('page', String(p));12 else sp.delete('page');13 const qs = sp.toString();14 return qs ? `${basePath}?${qs}` : basePath;15 };16 const from = (page - 1) * pageSize + 1;17 const to = Math.min(total, page * pageSize);18 const btn = 'inline-flex h-8 items-center rounded-md border border-border px-2.5 text-xs font-medium hover:bg-inset aria-disabled:pointer-events-none aria-disabled:opacity-40';19 return (20 <nav className={cn('mt-4 flex items-center justify-between gap-3 text-xs text-muted', className)} aria-label="Pagination">21 <span className="num">22 {from.toLocaleString('en-US')}–{to.toLocaleString('en-US')} of {total.toLocaleString('en-US')}23 </span>24 <div className="flex items-center gap-1.5">25 <Link href={href(Math.max(1, page - 1))} aria-disabled={page <= 1} className={btn}>26 Previous27 </Link>28 <span className="num px-2">29 {page} / {pages}30 </span>31 <Link href={href(Math.min(pages, page + 1))} aria-disabled={page >= pages} className={btn}>32 Next33 </Link>34 </div>35 </nav>36 );37}38