UNPKG

reka-ui

Version:

Vue port for Radix UI Primitives.

94 lines (72 loc) 3.18 kB
// reference https://github.com/chakra-ui/zag/blob/main/packages/machines/pagination/src/pagination.utils.ts type Pages = Array<{ type: 'ellipsis' } | { type: 'page', value: number }> function range(start: number, end: number) { const length = end - start + 1 return Array.from({ length }, (_, idx) => idx + start) } export function transform(items: (string | number)[]): Pages { return items.map((value) => { if (typeof value === 'number') return { type: 'page', value } return { type: 'ellipsis' } }) } const ELLIPSIS = 'ellipsis' export function getRange(currentPage: number, pageCount: number, siblingCount: number, showEdges: boolean) { const firstPageIndex = 1 const lastPageIndex = pageCount const leftSiblingIndex = Math.max(currentPage - siblingCount, firstPageIndex) const rightSiblingIndex = Math.min(currentPage + siblingCount, lastPageIndex) if (showEdges) { /** * `2 * siblingCount + 5` explanation: * 2 * siblingCount for left/right siblings * 5 for 2x left/right ellipsis, 2x first/last page + 1x current page * * For some page counts (e.g. totalPages: 8, siblingCount: 2), * calculated max page is higher than total pages, * so we need to take the minimum of both. */ const totalPageNumbers = Math.min(2 * siblingCount + 5, pageCount) const itemCount = totalPageNumbers - 2 // 2 stands for one ellipsis and either first or last page const showLeftEllipsis // default condition = leftSiblingIndex > firstPageIndex + 2 // if the current page is towards the end of the list && Math.abs(lastPageIndex - itemCount - firstPageIndex + 1) > 2 // if the current page is towards the middle of the list && Math.abs(leftSiblingIndex - firstPageIndex) > 2 const showRightEllipsis // default condition = rightSiblingIndex < lastPageIndex - 2 // if the current page is towards the start of the list && Math.abs(lastPageIndex - itemCount) > 2 // if the current page is towards the middle of the list && Math.abs(lastPageIndex - rightSiblingIndex) > 2 if (!showLeftEllipsis && showRightEllipsis) { const leftRange = range(1, itemCount) return [...leftRange, ELLIPSIS, lastPageIndex] } if (showLeftEllipsis && !showRightEllipsis) { const rightRange = range(lastPageIndex - itemCount + 1, lastPageIndex) return [firstPageIndex, ELLIPSIS, ...rightRange] } if (showLeftEllipsis && showRightEllipsis) { const middleRange = range(leftSiblingIndex, rightSiblingIndex) return [firstPageIndex, ELLIPSIS, ...middleRange, ELLIPSIS, lastPageIndex] } const fullRange = range(firstPageIndex, lastPageIndex) return fullRange } else { const itemCount = siblingCount * 2 + 1 if (pageCount < itemCount) return range(1, lastPageIndex) else if (currentPage <= (siblingCount + 1)) return range(firstPageIndex, itemCount) else if ((pageCount - currentPage) <= siblingCount) return range(pageCount - itemCount + 1, lastPageIndex) else return range(leftSiblingIndex, rightSiblingIndex) } }