{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "glass-pagination",
  "title": "Glass Pagination",
  "description": "Numbered pages with previous and next, folding long runs into an ellipsis.",
  "dependencies": [
    "clsx"
  ],
  "registryDependencies": [
    "@glassyui/glass-provider"
  ],
  "files": [
    {
      "path": "registry/glassyui/glass-pagination.tsx",
      "content": "'use client';\n\nimport clsx from 'clsx';\nimport { forwardRef } from 'react';\nimport type { HTMLAttributes } from 'react';\n\nexport type GlassPaginationProps = Omit<HTMLAttributes<HTMLElement>, 'onChange'> & {\n  /** Pages always shown at each end. Defaults to 1. */\n  boundaryCount?: number;\n  nextLabel?: string;\n  onPageChange: (page: number) => void;\n  /** The current page, counting from 1. */\n  page: number;\n  pageCount: number;\n  previousLabel?: string;\n  /** Pages shown either side of the current one. Defaults to 1. */\n  siblingCount?: number;\n};\n\ntype PageItem = { gap: 'start' | 'end'; page?: undefined } | { gap?: undefined; page: number };\n\nfunction range(start: number, end: number) {\n  return Array.from({ length: Math.max(0, end - start + 1) }, (_, index) => start + index);\n}\n\n/** The numbers to show: both ends and the neighbourhood of the current page, with gaps folded. */\nfunction pageItems(page: number, pageCount: number, boundaryCount: number, siblingCount: number) {\n  const startPages = range(1, Math.min(boundaryCount, pageCount));\n  const endPages = range(Math.max(pageCount - boundaryCount + 1, boundaryCount + 1), pageCount);\n\n  const siblingsStart = Math.max(\n    Math.min(page - siblingCount, pageCount - boundaryCount - siblingCount * 2 - 1),\n    boundaryCount + 2,\n  );\n\n  const siblingsEnd = Math.min(\n    Math.max(page + siblingCount, boundaryCount + siblingCount * 2 + 2),\n    endPages.length > 0 ? endPages[0] - 2 : pageCount - 1,\n  );\n\n  // A gap of one page shows that page instead of an ellipsis.\n  const beforeSiblings: PageItem[] =\n    siblingsStart > boundaryCount + 2\n      ? [{ gap: 'start' }]\n      : boundaryCount + 1 < pageCount - boundaryCount\n        ? [{ page: boundaryCount + 1 }]\n        : [];\n\n  const afterSiblings: PageItem[] =\n    siblingsEnd < pageCount - boundaryCount - 1\n      ? [{ gap: 'end' }]\n      : pageCount - boundaryCount > boundaryCount\n        ? [{ page: pageCount - boundaryCount }]\n        : [];\n\n  return [\n    ...startPages.map((number): PageItem => ({ page: number })),\n    ...beforeSiblings,\n    ...range(siblingsStart, siblingsEnd).map((number): PageItem => ({ page: number })),\n    ...afterSiblings,\n    ...endPages.map((number): PageItem => ({ page: number })),\n  ];\n}\n\nfunction Chevron({ direction }: { direction: 'previous' | 'next' }) {\n  return (\n    <svg aria-hidden viewBox=\"0 0 20 20\">\n      <path\n        d={direction === 'previous' ? 'M12.5 4.5 7 10l5.5 5.5' : 'M7.5 4.5 13 10l-5.5 5.5'}\n        fill=\"none\"\n        stroke=\"currentColor\"\n        strokeLinecap=\"round\"\n        strokeLinejoin=\"round\"\n        strokeWidth=\"1.7\"\n      />\n    </svg>\n  );\n}\n\n/** Numbered pages with previous and next, folding long runs into an ellipsis. */\nexport const GlassPagination = forwardRef<HTMLElement, GlassPaginationProps>(\n  (\n    {\n      boundaryCount = 1,\n      className,\n      nextLabel = 'Next page',\n      onPageChange,\n      page,\n      pageCount,\n      previousLabel = 'Previous page',\n      siblingCount = 1,\n      ...props\n    },\n    forwardedRef,\n  ) => {\n    const current = Math.min(Math.max(1, page), Math.max(1, pageCount));\n\n    return (\n      <nav\n        aria-label=\"Pagination\"\n        {...props}\n        ref={forwardedRef}\n        className={clsx('lg-pagination', className)}\n      >\n        <ul className=\"lg-pagination-list\">\n          <li>\n            <button\n              aria-label={previousLabel}\n              className=\"lg-page\"\n              disabled={current <= 1}\n              onClick={() => onPageChange(current - 1)}\n              type=\"button\"\n            >\n              <Chevron direction=\"previous\" />\n            </button>\n          </li>\n          {pageItems(current, pageCount, boundaryCount, siblingCount).map((item) =>\n            item.page === undefined ? (\n              <li aria-hidden className=\"lg-page-gap\" key={item.gap}>\n                …\n              </li>\n            ) : (\n              <li key={item.page}>\n                <button\n                  aria-current={item.page === current ? 'page' : undefined}\n                  aria-label={`Page ${item.page}`}\n                  className=\"lg-page\"\n                  data-current={item.page === current ? '' : undefined}\n                  onClick={() => onPageChange(item.page)}\n                  type=\"button\"\n                >\n                  {item.page}\n                </button>\n              </li>\n            ),\n          )}\n          <li>\n            <button\n              aria-label={nextLabel}\n              className=\"lg-page\"\n              disabled={current >= pageCount}\n              onClick={() => onPageChange(current + 1)}\n              type=\"button\"\n            >\n              <Chevron direction=\"next\" />\n            </button>\n          </li>\n        </ul>\n      </nav>\n    );\n  },\n);\n\nGlassPagination.displayName = 'GlassPagination';\n",
      "type": "registry:ui",
      "target": "components/glassyui/glass-pagination.tsx"
    }
  ],
  "meta": {
    "sourceModules": [
      "pagination"
    ]
  },
  "type": "registry:ui"
}