diff --git a/packages/ui/src/components/Pagination/Pagination.test.tsx b/packages/ui/src/components/Pagination/Pagination.test.tsx index 8367cd51c..5f6e2d27a 100644 --- a/packages/ui/src/components/Pagination/Pagination.test.tsx +++ b/packages/ui/src/components/Pagination/Pagination.test.tsx @@ -176,6 +176,11 @@ describe("Pagination", () => { expect(pages()).toHaveLength(0); }); + it("should render page 1 when totalPages is 1", () => { + render( undefined} />); + expect(pages()).toHaveLength(1); + expect(pages()[0]).toBe(1); + }); it("should change previous and next text when provided", () => { render( diff --git a/packages/ui/src/components/Pagination/Pagination.tsx b/packages/ui/src/components/Pagination/Pagination.tsx index a4fd4c9ee..eb573573b 100644 --- a/packages/ui/src/components/Pagination/Pagination.tsx +++ b/packages/ui/src/components/Pagination/Pagination.tsx @@ -66,11 +66,24 @@ export interface TablePaginationProps extends BasePaginationProps { export type PaginationProps = DefaultPaginationProps | TablePaginationProps; +/** + * Top-level Pagination component. Switches between Default and Table variants + * based on the `layout` prop. + * @param props - Discriminated union of DefaultPaginationProps and TablePaginationProps. + * @param ref - Ref forwarded to the underlying nav element. + * @returns The rendered pagination navigation. + */ export const Pagination = forwardRef((props, ref) => { if (props.layout === "table") return ; return ; }); +/** + * Default pagination component. + * @param props - Pagination props (currentPage, totalPages, layout, etc.) + * @param ref - Ref to the nav element. + * @returns The rendered navigation component. + */ const DefaultPagination = forwardRef((props, ref) => { const provider = useThemeProvider(); const theme = useResolveTheme( @@ -102,6 +115,7 @@ const DefaultPagination = forwardRef((props const lastPage = Math.min(Math.max(layout === "pagination" ? currentPage + 2 : currentPage + 4, 5), totalPages); const firstPage = Math.max(1, lastPage - 4); + const lastPageInRange = Math.max(lastPage, firstPage); function goToNextPage() { onPageChange(Math.min(currentPage + 1, totalPages)); @@ -125,16 +139,27 @@ const DefaultPagination = forwardRef((props {layout === "pagination" && - range(firstPage, lastPage).map((page: number) => ( -
  • - {renderPaginationButton({ - className: twMerge(theme.pages.selector.base, currentPage === page && theme.pages.selector.active), - active: page === currentPage, - onClick: () => onPageChange(page), - children: page, - })} -
  • - ))} + (totalPages <= 5 + ? Array.from({ length: totalPages }, (_, i) => i + 1).map((page: number) => ( +
  • + {renderPaginationButton({ + className: twMerge(theme.pages.selector.base, currentPage === page && theme.pages.selector.active), + active: page === currentPage, + onClick: () => onPageChange(page), + children: page, + })} +
  • + )) + : range(firstPage, lastPageInRange).map((page: number) => ( +
  • + {renderPaginationButton({ + className: twMerge(theme.pages.selector.base, currentPage === page && theme.pages.selector.active), + active: page === currentPage, + onClick: () => onPageChange(page), + children: page, + })} +
  • + )))}
  • ((props ); }); +/** + * Table pagination component. + * @param props - Pagination props (currentPage, itemsPerPage, totalItems, etc.) + * @param ref - Ref to the nav element. + * @returns The rendered navigation component. + */ const TablePagination = forwardRef((props, ref) => { const provider = useThemeProvider(); const theme = useResolveTheme(