openpanel/documentation/src/hooks/use-pagination.ts
2024-02-05 10:23:04 +01:00

64 lines
1.8 KiB
TypeScript

import { useMemo } from "react";
export const DOTS = "...";
const range = (start: number, end: number) => {
const length = end - start + 1;
return Array.from({ length }, (_, idx) => idx + start);
};
type UsePaginationProps = {
totalPages: number;
currentPage: number;
siblingCount?: number;
};
export const usePagination = ({
totalPages,
siblingCount = 1,
currentPage,
}: UsePaginationProps) => {
const paginationRange = useMemo(() => {
const totalPageNumbers = siblingCount + 5;
if (totalPageNumbers >= totalPages) {
return range(1, totalPages);
}
const leftSiblingIndex = Math.max(currentPage - siblingCount, 1);
const rightSiblingIndex = Math.min(
currentPage + siblingCount,
totalPages,
);
const shouldShowLeftDots = leftSiblingIndex > 2;
const shouldShowRightDots = rightSiblingIndex < totalPages - 2;
const firstPageIndex = 1;
const lastPageIndex = totalPages;
if (!shouldShowLeftDots && shouldShowRightDots) {
const leftItemCount = 3 + 2 * siblingCount;
const leftRange = range(1, leftItemCount);
return [...leftRange, DOTS, totalPages];
}
if (shouldShowLeftDots && !shouldShowRightDots) {
const rightItemCount = 3 + 2 * siblingCount;
const rightRange = range(
totalPages - rightItemCount + 1,
totalPages,
);
return [firstPageIndex, DOTS, ...rightRange];
}
if (shouldShowLeftDots && shouldShowRightDots) {
const middleRange = range(leftSiblingIndex, rightSiblingIndex);
return [firstPageIndex, DOTS, ...middleRange, DOTS, lastPageIndex];
}
}, [siblingCount, currentPage]);
return paginationRange;
};