import { cn } from "@/lib/utils"; import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, } from "@/components/ui/pagination"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "@/components/ui/select"; import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react"; import { useListPaginationContext, Translate, useTranslate } from "ra-core"; /** * A pagination component with page numbers and rows per page selector. * * Displays pagination controls with previous/next buttons, page numbers with ellipsis for long lists, * and a dropdown to change items per page. Works with List context. * * @see {@link https://marmelab.com/shadcn-admin-kit/docs/listpagination/ ListPagination documentation} * * @example * import { List, ListPagination } from '@/components/admin'; * * const PostListPagination = () => ( * * ); * * export const PostList = () => ( * }> * // ... * * ); */ export const ListPagination = ({ rowsPerPageOptions = [5, 10, 25, 50], className, }: { rowsPerPageOptions?: number[]; className?: string; }) => { const translate = useTranslate(); const { hasPreviousPage, hasNextPage, page, perPage, setPerPage, total, setPage, } = useListPaginationContext(); const pageStart = (page - 1) * perPage + 1; const pageEnd = hasNextPage ? page * perPage : total; const boundaryCount = 1; const siblingCount = 1; const count = total ? Math.ceil(total / perPage) : 1; const range = (start: number, end: number) => { const length = end - start + 1; return Array.from({ length }, (_, i) => start + i); }; const startPages = range(1, Math.min(boundaryCount, count)); const endPages = range( Math.max(count - boundaryCount + 1, boundaryCount + 1), count, ); const siblingsStart = Math.max( Math.min( // Natural start page - siblingCount, // Lower boundary when page is high count - boundaryCount - siblingCount * 2 - 1, ), // Greater than startPages boundaryCount + 2, ); const siblingsEnd = Math.min( Math.max( // Natural end page + siblingCount, // Upper boundary when page is low boundaryCount + siblingCount * 2 + 2, ), // Less than endPages count - boundaryCount - 1, ); const siblingPages = range(siblingsStart, siblingsEnd); const pageChangeHandler = (newPage: number) => { return (event: React.MouseEvent) => { event.preventDefault(); setPage(newPage); }; }; return (

Rows per page

{total != null ? `${pageStart}-${pageEnd} of ${total === -1 ? pageEnd : total}` : null}
{startPages.map((pageNumber) => ( {pageNumber} ))} {siblingsStart > boundaryCount + 2 ? ( ) : boundaryCount + 1 < count - boundaryCount ? ( {boundaryCount + 1} ) : null} {siblingPages.map((pageNumber) => ( {pageNumber} ))} {siblingsEnd < count - boundaryCount - 1 ? ( ) : count - boundaryCount > boundaryCount ? ( {count - boundaryCount} ) : null} {endPages.map((pageNumber) => ( {pageNumber} ))}
); };