import * as React from 'react';
import { useRange, ELLIPSIS } from './useRange';
import { PaginationItem } from './PaginationItem';
import { ComponentText } from '../shared/constants';
interface UsePaginationItemsProps {
currentPage: number;
totalPages: number;
hasMorePages: boolean;
siblingCount?: number;
currentPageLabel?: string;
pageLabel?: string;
previousLabel?: string;
nextLabel?: string;
onNext?: () => void;
onPrevious?: () => void;
onChange?: (newPageIndex?: number, prevPageIndex?: number) => void;
}
/**
* This hook will be used to get the pagination items to be rendered in the pagination primitive
* @param currentPage current page number
* @param totalPages total number of pages
* @param siblingCount the number of siblings on each side of
* @param onNext callback function triggered when the next-page button is pressed
* @param onPrevious callback function triggered when the prev-page button is pressed
* @param onChange callback function triggered every time the page changes
* @returns an array of pagination items
*/
export const usePaginationItems = ({
currentPage,
totalPages,
hasMorePages,
siblingCount,
currentPageLabel = ComponentText.PaginationItem.currentPageLabel,
pageLabel = ComponentText.PaginationItem.pageLabel,
previousLabel = ComponentText.PaginationItem.previousLabel,
nextLabel = ComponentText.PaginationItem.nextLabel,
onNext,
onPrevious,
onChange,
}: UsePaginationItemsProps): JSX.Element[] => {
const previousItem = (
);
const nextItem = (
= totalPages && !hasMorePages}
ariaLabel={nextLabel}
/>
);
// To get the range of page numbers to be rendered in the pagination primitive
const range = useRange(currentPage, totalPages, siblingCount);
const pageItems = React.useMemo(
() =>
range.map((item, idx) => {
if (item === ELLIPSIS) {
return (
);
}
return (
// Note: Do NOT use index for `key` and instead use page number
// otherwise, react cannot update the component correctly with its diff mechanism
onChange?.(item as number, currentPage)}
/**
* @todo We should consider how we would support interpolation in our string translations.
* This works for "Go to page 31" or "translatedText {s}" as the supplied string
* But for Arabic or Japanese or some other languages the supplied string might look like: "{s} translatedText".
*/
ariaLabel={`${pageLabel} ${item}`}
/>
);
}),
[range, currentPage, currentPageLabel, pageLabel, onChange]
);
return [previousItem, ...pageItems, nextItem];
};