{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "pagination", "dependencies": [ "react-aria-components", "lucide-react" ], "registryDependencies": [ "@seamless/utils" ], "files": [ { "path": "src/components/ui/pagination.tsx", "content": "import type * as React from \"react\"\nimport { ChevronLeftIcon, ChevronRightIcon } from \"lucide-react\"\nimport { Button as ButtonPrimitive } from \"react-aria-components\"\n\nimport { cn, type Composed, type Styled } from \"@/lib/utils\"\n\nconst ELLIPSIS = \"ellipsis\"\n\ntype PaginationSlot = number | typeof ELLIPSIS\n\n/**\n * NOTE: the window every list shows — first page, last page, and a run of `siblings * 2 + 1` pages\n * around the current one. The run keeps its width at either end by sliding inward, so the control\n * never narrows just because the list is on page one. Pages are 1-based.\n *\n * INVARIANT: an ellipsis never stands in for a single page — a lone gap is spelled out instead.\n */\nfunction paginationRange({\n page,\n pageCount,\n siblings = 1,\n}: {\n page: number\n pageCount: number\n siblings?: number\n}): PaginationSlot[] {\n if (pageCount < 1) return []\n const runLength = Math.min(siblings * 2 + 1, pageCount)\n const runStart = Math.min(Math.max(page - siblings, 1), pageCount - runLength + 1)\n const anchors = new Set([1, pageCount])\n for (let near = runStart; near < runStart + runLength; near++) anchors.add(near)\n\n const slots: PaginationSlot[] = []\n let previous = 0\n for (const anchor of [...anchors].sort((a, b) => a - b)) {\n const gap = anchor - previous\n if (previous > 0 && gap === 2) slots.push(previous + 1)\n else if (previous > 0 && gap > 2) slots.push(ELLIPSIS)\n slots.push(anchor)\n previous = anchor\n }\n return slots\n}\n\nfunction Pagination({\n className,\n ...props\n}: React.ComponentProps<\"nav\"> & { \"aria-label\": string }) {\n return (\n \n )\n}\n\nfunction PaginationRange({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n \n )\n}\n\nfunction PaginationNav({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n \n )\n}\n\nconst stepClass =\n \"inline-flex h-7 min-w-7 shrink-0 items-center justify-center gap-1 rounded-sm px-2 text-xs font-medium text-ink-2 tabular-nums outline-none transition-colors hover:bg-accent hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-40 aria-[current=page]:bg-secondary aria-[current=page]:font-semibold aria-[current=page]:text-foreground [&_svg]:size-3.5 [&_svg]:shrink-0\"\n\ntype PaginationStepProps = Composed>\n\ntype PaginationButtonProps = Styled> & {\n /** NOTE: the page a list is on is `aria-current`, not a pressed toggle — it names a location. */\n isCurrent?: boolean\n}\n\nfunction PaginationButton({\n className,\n isCurrent = false,\n ...props\n}: PaginationButtonProps) {\n return (\n \n )\n}\n\nfunction PaginationPrevious({\n className,\n children,\n ...props\n}: PaginationStepProps) {\n return (\n \n \n {children}\n \n )\n}\n\nfunction PaginationNext({\n className,\n children,\n ...props\n}: PaginationStepProps) {\n return (\n \n {children}\n \n \n )\n}\n\nfunction PaginationEllipsis({ className, ...props }: React.ComponentProps<\"span\">) {\n return (\n \n …\n \n )\n}\n\nexport {\n Pagination,\n PaginationButton,\n PaginationEllipsis,\n PaginationNav,\n PaginationNext,\n PaginationPrevious,\n PaginationRange,\n paginationRange,\n type PaginationButtonProps,\n type PaginationSlot,\n type PaginationStepProps,\n}\n", "type": "registry:ui" } ], "type": "registry:ui" }