Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/ui/src/components/Pagination/Pagination.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ describe("Pagination", () => {

expect(pages()).toHaveLength(0);
});
it("should render page 1 when totalPages is 1", () => {
render(<Pagination currentPage={1} totalPages={1} onPageChange={() => undefined} />);
expect(pages()).toHaveLength(1);
expect(pages()[0]).toBe(1);
});

it("should change previous and next text when provided", () => {
render(
Expand Down
51 changes: 41 additions & 10 deletions packages/ui/src/components/Pagination/Pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<HTMLElement, PaginationProps>((props, ref) => {
if (props.layout === "table") return <TablePagination {...props} ref={ref} />;
return <DefaultPagination {...props} ref={ref} />;
});

/**
* 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<HTMLElement, DefaultPaginationProps>((props, ref) => {
const provider = useThemeProvider();
const theme = useResolveTheme(
Expand Down Expand Up @@ -102,6 +115,7 @@ const DefaultPagination = forwardRef<HTMLElement, DefaultPaginationProps>((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));
Expand All @@ -125,16 +139,27 @@ const DefaultPagination = forwardRef<HTMLElement, DefaultPaginationProps>((props
</PaginationNavigation>
</li>
{layout === "pagination" &&
range(firstPage, lastPage).map((page: number) => (
<li aria-current={page === currentPage ? "page" : undefined} key={page}>
{renderPaginationButton({
className: twMerge(theme.pages.selector.base, currentPage === page && theme.pages.selector.active),
active: page === currentPage,
onClick: () => onPageChange(page),
children: page,
})}
</li>
))}
(totalPages <= 5
? Array.from({ length: totalPages }, (_, i) => i + 1).map((page: number) => (
<li aria-current={page === currentPage ? "page" : undefined} key={page}>
{renderPaginationButton({
className: twMerge(theme.pages.selector.base, currentPage === page && theme.pages.selector.active),
active: page === currentPage,
onClick: () => onPageChange(page),
children: page,
})}
</li>
))
: range(firstPage, lastPageInRange).map((page: number) => (
<li aria-current={page === currentPage ? "page" : undefined} key={page}>
{renderPaginationButton({
className: twMerge(theme.pages.selector.base, currentPage === page && theme.pages.selector.active),
active: page === currentPage,
onClick: () => onPageChange(page),
children: page,
})}
</li>
)))}
<li>
<PaginationNavigation
className={twMerge(theme.pages.next.base, showIcon && theme.pages.showIcon)}
Expand All @@ -150,6 +175,12 @@ const DefaultPagination = forwardRef<HTMLElement, DefaultPaginationProps>((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<HTMLElement, TablePaginationProps>((props, ref) => {
const provider = useThemeProvider();
const theme = useResolveTheme(
Expand Down
Loading