import { useCallback, useMemo } from '@wordpress/element';
import clsx from 'clsx';
export interface PaginationProps {
total: number;
page: number;
pageSize?: number;
onPageChange: (page: number) => void;
}
interface PaginationNumIconProps {
page: number;
number: number;
onClick: (page: number) => void;
}
const PREFIX = 'lks-pagination';
const SHOW_MIDDLE_PAGE_NUM = 5;
const SHOW_MORE_ICON_NUM = SHOW_MIDDLE_PAGE_NUM - 2;
export const PaginationNumIcon = ({
number,
page,
onClick,
}: PaginationNumIconProps) => (
onClick(number)}
className={clsx(
`${PREFIX}__btn`,
`${PREFIX}__btn--number`,
`${PREFIX}__btn--${number}`,
{
[`${PREFIX}__btn--active`]: page === number,
},
)}
>
{number}
);
export const Pagination = ({
total,
page,
pageSize = 10,
onPageChange,
}: PaginationProps) => {
const pageTotal = useMemo(
() => Math.ceil(total / pageSize),
[total, pageSize],
);
const pageNumberList = useMemo(
() => new Array(pageTotal).fill(1).map((num, index) => num + index),
[pageTotal],
);
const previousDisabled = useMemo(() => page <= 1, [page]);
const nextDisabled = useMemo(
() => !pageTotal || page >= pageTotal,
[page, pageTotal],
);
const showMorePreviousIcon = useMemo(
() => !!page && page - SHOW_MORE_ICON_NUM > 1,
[page],
);
const showMoreNextIcon = useMemo(
() => !!pageTotal && pageTotal - SHOW_MORE_ICON_NUM > page,
[page, pageTotal],
);
const shownPageNumberList = useMemo(() => {
const numberList = [...pageNumberList];
const startNum = numberList.shift() || 1;
const endNum = numberList.pop();
const middleAverage = Math.floor(SHOW_MIDDLE_PAGE_NUM / 2);
const middleRangeStartIndex = Math.min(
Math.max(page - SHOW_MIDDLE_PAGE_NUM + 1, 0),
pageTotal - SHOW_MIDDLE_PAGE_NUM - 1,
);
const middleRangeEndIndex = Math.max(
Math.min(page + middleAverage - 1, numberList.length),
SHOW_MIDDLE_PAGE_NUM - 1,
);
const middleNumberList = numberList.slice(
middleRangeStartIndex,
middleRangeEndIndex,
);
return {
startNum,
endNum,
middleNumberList,
};
}, [page, pageTotal, pageNumberList]);
const handleChangePage = useCallback(
(pageValue: number) => {
const nextPage = Math.max(1, Math.min(pageValue, pageTotal));
onPageChange?.(nextPage);
},
[pageTotal, onPageChange],
);
return (
- handleChangePage(page - 1)}
className={clsx(`${PREFIX}__btn`, `${PREFIX}__btn__left`, {
[`${PREFIX}__btn--disabled`]: previousDisabled,
})}
>
{'<'}
{showMorePreviousIcon && (
- handleChangePage(page - SHOW_MIDDLE_PAGE_NUM)}
className={clsx(`${PREFIX}__btn`, `${PREFIX}__btn__more-previous`)}
>
{'<<'}
)}
{shownPageNumberList.middleNumberList.map(number => (
))}
{showMoreNextIcon && (
- handleChangePage(page + SHOW_MIDDLE_PAGE_NUM)}
className={clsx(`${PREFIX}__btn`, `${PREFIX}__btn__more-next`)}
>
{'>>'}
)}
{shownPageNumberList.endNum && (
)}
- handleChangePage(page + 1)}
className={clsx(`${PREFIX}__btn`, `${PREFIX}__btn__left`, {
[`${PREFIX}__btn--disabled`]: nextDisabled,
})}
>
{'>'}
);
};