{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "pagination",
  "type": "registry:ui",
  "title": "Pagination",
  "description": "Moving through pages of results: page numbers in the switcher's track with previous and next keys; the current page's thumb glides to the chosen page on the part spring.",
  "dependencies": [],
  "registryDependencies": [
    "https://metalui.dev/r/tokens.json"
  ],
  "files": [
    {
      "path": "packages/metalui/src/components/pagination/pagination.tsx",
      "type": "registry:ui",
      "target": "components/metalui/pagination/pagination.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { SlidingIndicator } from '../../motion/indicator';\nimport { trackParts } from '../switcher/switcher';\n\n/* ─────────────────────────────────────────────────────────\n * PAGINATION, moving through pages of results\n *\n *   rest      the switcher's sunk track: previous key, page numbers, next key\n *   current   the switcher's raised thumb under the current page (aria-current=\"page\")\n *   choose    another page: the thumb glides there on the part spring (a track with ends)\n *   long      first and last pages, the current one and its neighbours; quiet ellipses between\n *   ends      the previous or next key is disabled on the first or last page\n *   focus     the switcher's focus ring on each key\n * Reduce Motion: the thumb moves at once.\n * The track, thumb and keys are the switcher recipe; pagination adds the page window.\n * ───────────────────────────────────────────────────────── */\n\nconst { TRACK, THUMB, OPTION } = trackParts;\nconst KEY = `${OPTION.regular} justify-center min-w-pagination-page-min-width tabular-nums`;\nconst GAP = 'mu-pagination-gap inline-grid place-items-center min-w-pagination-page-min-width type-switcher-option text-ink3 select-none';\nconst ARROW = 'size-pagination-arrow-size';\n\nexport interface PaginationProps {\n  /** The page shown, from 1. */\n  page: number;\n  /** How many pages there are. */\n  count: number;\n  onPageChange: (page: number) => void;\n  /** Pages on each side of the current one (1). */\n  siblings?: number;\n  'aria-label'?: string;\n  className?: string;\n}\n\n/** The page numbers to show, with null for a gap. */\nexport function pageWindow(page: number, count: number, siblings = 1): (number | null)[] {\n  const out: (number | null)[] = [];\n  const lo = Math.max(2, page - siblings);\n  const hi = Math.min(count - 1, page + siblings);\n  out.push(1);\n  if (lo > 2) out.push(lo === 3 ? 2 : null);\n  for (let p = lo; p <= hi; p++) out.push(p);\n  if (hi < count - 1) out.push(hi === count - 2 ? count - 1 : null);\n  if (count > 1) out.push(count);\n  return out;\n}\n\nfunction Arrow({ back }: { back?: boolean }) {\n  return (\n    <svg aria-hidden viewBox=\"0 0 10 10\" className={ARROW} fill=\"none\" stroke=\"currentColor\" strokeWidth={1.5} strokeLinecap=\"round\" strokeLinejoin=\"round\">\n      <path d={back ? 'M6.25 2 3.25 5l3 3' : 'M3.75 2 6.75 5l-3 3'} />\n    </svg>\n  );\n}\n\n/** Moving through pages of results. */\nexport function Pagination({ page, count, onPageChange, siblings = 1, className, ...aria }: PaginationProps) {\n  const pages = pageWindow(page, count, siblings);\n  const go = (p: number) => { if (p >= 1 && p <= count && p !== page) onPageChange(p); };\n  return (\n    <nav aria-label={aria['aria-label'] ?? 'Pagination'} className={className ? `mu-pagination ${className}` : 'mu-pagination'}>\n      <div className={`${TRACK} items-center`}>\n        <SlidingIndicator className={THUMB} />\n        <button type=\"button\" className={KEY} aria-label=\"Previous page\" disabled={page <= 1} data-disabled={page <= 1 ? '' : undefined} onClick={() => go(page - 1)}><Arrow back /></button>\n        {pages.map((p, i) => (p == null ? (\n          <span key={`gap-${i}`} aria-hidden className={GAP}>…</span>\n        ) : (\n          <button\n            key={p}\n            type=\"button\"\n            className={KEY}\n            aria-label={`Page ${p}`}\n            aria-current={p === page ? 'page' : undefined}\n            data-checked={p === page ? '' : undefined}\n            onClick={() => go(p)}\n          >\n            {p}\n          </button>\n        )))}\n        <button type=\"button\" className={KEY} aria-label=\"Next page\" disabled={page >= count} data-disabled={page >= count ? '' : undefined} onClick={() => go(page + 1)}><Arrow /></button>\n      </div>\n    </nav>\n  );\n}\n"
    }
  ],
  "docs": "Agent guide: https://metalui.dev/r/pagination.md. SwiftUI: MetalPagination in the MetalUI Swift package."
}
