import React, { Dispatch, SetStateAction, useCallback, useMemo } from 'react'; import { usePaginationContext } from './pagination-context'; import { PaginationEllipsis } from './pagination-ellipsis'; import { PaginationItem } from './pagination-item'; type Props = { limit: number; count: number; current: number; setPage: Dispatch>; }; export const PaginationPages: React.FC = ({ limit, count, current, setPage }) => { const { resolveUrl } = usePaginationContext(); const showPages = useMemo(() => { const oddLimit = limit % 2 === 0 ? limit - 1 : limit; return oddLimit - 2; }, [limit]); const middleNumber = (showPages + 1) / 2; const [showBeforeEllipsis, showAfterEllipsis] = useMemo((): [boolean, boolean] => { const showEllipsis = count > limit; return [ showEllipsis && current > middleNumber + 1, showEllipsis && current < count - middleNumber, ]; }, [current, middleNumber, count, limit]); const pagesArray = useMemo(() => [...new Array(showPages)], [showPages]); const renderItem = useCallback((value: number, active: number) => ( setPage(value)} href={resolveUrl(value)} > {value} ), [setPage]); const renderStartItems = pagesArray.map((_, index) => { const value = index + 2; return renderItem(value, current); }); const renderMiddleItems = pagesArray.map((_, index) => { const middleIndexNumber = middleNumber - (index + 1); const value = current - middleIndexNumber; return ( setPage(value)} href={resolveUrl(value)} > {value} ); }); const renderEndItems = pagesArray.map((_, index) => { const value = count - (showPages - index); return renderItem(value, current); }); if (count <= limit) { /* eslint-disable react/jsx-no-useless-fragment */ return ( <> {[...new Array(count)].map((_, index) => { const value = index + 1; return ( setPage(value)} href={resolveUrl(value)} > {value} ); })} ); /* eslint-enable */ } return ( <> {renderItem(1, current)} {showBeforeEllipsis && ( setPage(last => (last - 5 >= 1 ? last - 5 : 1))} /> )} {showBeforeEllipsis && showAfterEllipsis ? renderMiddleItems : (showBeforeEllipsis ? renderEndItems : renderStartItems) } {showAfterEllipsis && ( setPage(last => (last + 5 <= count ? last + 5 : count))} /> )} {renderItem(count, current)} ); }; PaginationPages.displayName = 'PaginationPages';