--- /** * Pagination Component * Page navigation with prev/next and numbered pages. */ import type { HTMLAttributes } from 'astro/types'; import { cn } from '@/lib/cn'; import { paginationItemVariants } from './pagination.variants'; import Icon from '../../primitives/Icon/Icon.astro'; interface Props extends HTMLAttributes<'nav'> { /** Current active page (1-indexed) */ currentPage: number; /** Total number of pages */ totalPages: number; /** Base URL for page links (page number appended) */ baseUrl?: string; /** Maximum number of visible page buttons */ maxVisible?: number; size?: 'sm' | 'md' | 'lg'; } const { currentPage, totalPages, baseUrl = '?page=', maxVisible = 5, size = 'md', class: className, ...attrs } = Astro.props; /** * Build the array of page numbers and ellipsis markers to render. * * @param current - The 1-indexed active page. * @param total - Total number of pages. * @param max - Size of the central sliding window. When `total <= max`, * every page is returned directly. Otherwise a window of * `max` pages is centered around `current`, and first/last * pages plus `'...'` ellipsis markers are added outside the * window as needed — so the returned array can contain more * than `max` entries. * @returns An array of page numbers and `'...'` separators. */ function getPageRange(current: number, total: number, max: number): (number | '...')[] { if (total <= max) { return Array.from({ length: total }, (_, i) => i + 1); } const pages: (number | '...')[] = []; const half = Math.floor(max / 2); let start = Math.max(1, current - half); let end = Math.min(total, start + max - 1); if (end - start < max - 1) { start = Math.max(1, end - max + 1); } if (start > 1) { pages.push(1); if (start > 2) pages.push('...'); } for (let i = start; i <= end; i++) { pages.push(i); } if (end < total) { if (end < total - 1) pages.push('...'); pages.push(total); } return pages; } const pages = getPageRange(currentPage, totalPages, maxVisible); const prevUrl = currentPage > 1 ? `${baseUrl}${currentPage - 1}` : undefined; const nextUrl = currentPage < totalPages ? `${baseUrl}${currentPage + 1}` : undefined; ---