{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "pagination",
  "type": "registry:ui",
  "title": "Pagination",
  "description": "صفحه‌بندی با ارقام فارسی؛ صفحهٔ فعلی با aria-current=\"page\"",
  "dependencies": [
    "@kashi-ui/persian@^1.8.0"
  ],
  "registryDependencies": [
    "https://kashi.sepantapouya.com/r/cx.json",
    "https://kashi.sepantapouya.com/r/kashi-provider.json"
  ],
  "files": [
    {
      "path": "registry/kashi/Pagination.tsx",
      "type": "registry:ui",
      "target": "components/kashi/Pagination.tsx",
      "content": "\"use client\";\n\nimport { useState, type ReactNode } from \"react\";\nimport { toFaDigits } from \"@kashi-ui/persian\";\nimport { cx } from \"./cx\";\nimport { useKashi } from \"./KashiProvider\";\n\n/** صفحه‌هایی که نمایش داده می‌شوند؛ null یعنی «…» */\nexport function pageRange(page: number, total: number, siblings = 1): (number | null)[] {\n  const out: (number | null)[] = [];\n  const from = Math.max(2, page - siblings);\n  const to = Math.min(total - 1, page + siblings);\n  out.push(1);\n  if (from > 2) out.push(from === 3 ? 2 : null);\n  for (let p = from; p <= to; p++) out.push(p);\n  if (to < total - 1) out.push(to === total - 2 ? total - 1 : null);\n  if (total > 1) out.push(total);\n  return out;\n}\n\nexport interface PaginationProps {\n  page: number;\n  total: number;\n  onChange?: (page: number) => void;\n  /** برای صفحه‌بندی با لینک (بهتر برای SEO)؛ در این حالت onChange لازم نیست */\n  getHref?: (page: number) => string;\n  /** تعداد صفحه‌های کنار صفحهٔ فعلی @default 1 */\n  siblings?: number;\n  /** متن خلاصه، مثل «نمایش ۱ تا ۱۰ از ۹۷» */\n  summary?: ReactNode;\n  /** @default \"fa\" */\n  digits?: \"fa\" | \"latin\";\n  /** تعداد ردیف در هر صفحه؛ با onPageSizeChange فهرست انتخاب نمایش داده می‌شود */\n  pageSize?: number;\n  /** @default [10, 20, 50, 100] */\n  pageSizes?: number[];\n  onPageSizeChange?: (size: number) => void;\n  /** فیلد «برو به صفحه» برای فهرست‌های طولانی */\n  jumper?: boolean;\n  labels?: { nav?: string; prev?: string; next?: string; page?: (n: string) => string; perPage?: string; jump?: string };\n  className?: string;\n}\n\nconst Chevron = ({ dir }: { dir: \"prev\" | \"next\" }) => (\n  <svg data-k-mirror=\"\" viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.7} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\">\n    <path d={dir === \"prev\" ? \"m12 5-5 5 5 5\" : \"m8 5 5 5-5 5\"} />\n  </svg>\n);\n\n/** صفحه‌بندی با ارقام فارسی؛ صفحهٔ فعلی با aria-current=\"page\" */\nexport function Pagination({\n  page, total, onChange, getHref, siblings = 1, summary, digits, pageSize, pageSizes = [10, 20, 50, 100], onPageSizeChange, jumper, labels = {}, className,\n}: PaginationProps) {\n  const { messages: M, digits: D } = useKashi();\n  digits ??= D;\n  const n = (v: number) => (digits === \"fa\" ? toFaDigits(v) : String(v));\n  const { nav = M.pagination.nav, prev = M.common.prev, next = M.common.next, page: pageLabel = (x: string) => M.pagination.page(x), perPage = M.pagination.perPage, jump = M.pagination.jump } = labels;\n  const [jumpText, setJumpText] = useState(\"\");\n  // تابع معمولی، نه کامپوننت: تا دکمه‌ها با هر رندر دوباره ساخته نشوند و فوکوس کیبورد حفظ شود\n  const item = ({ to, children, current, disabled, aria, className: c }: { to: number; children: ReactNode; current?: boolean; disabled?: boolean; aria?: string; className: string }) =>\n    getHref && !disabled ? (\n      <a className={c} href={getHref(to)} aria-current={current ? \"page\" : undefined} aria-label={aria}>{children}</a>\n    ) : (\n      <button type=\"button\" className={c} disabled={disabled} aria-current={current ? \"page\" : undefined} aria-label={aria} onClick={() => onChange?.(to)}>{children}</button>\n    );\n  return (\n    <nav className={cx(\"k-pagination\", className)} aria-label={nav}>\n      {item({ to: page - 1, disabled: page <= 1, className: \"k-btn k-btn--secondary k-btn--sm\", children: <><Chevron dir=\"prev\" />{prev}</> })}\n      {summary && <span className=\"k-pagination__summary\">{summary}</span>}\n      <ul className=\"k-pagination__pages\" role=\"list\">\n        {pageRange(page, total, siblings).map((p, i) => (\n          <li key={i}>\n            {p === null ? (\n              <span className=\"k-pagination__ellipsis\" aria-hidden=\"true\">…</span>\n            ) : (\n              item({ to: p, current: p === page, aria: pageLabel(n(p)), className: \"k-pagination__page\", children: n(p) })\n            )}\n          </li>\n        ))}\n      </ul>\n      {item({ to: page + 1, disabled: page >= total, className: \"k-btn k-btn--secondary k-btn--sm\", children: <>{next}<Chevron dir=\"next\" /></> })}\n      {(onPageSizeChange || (jumper && onChange)) && (\n        <div className=\"k-pagination__tools\">\n          {onPageSizeChange && (\n            <label className=\"k-pagination__tool\">\n              <span className=\"k-select k-select--sm\">\n                <select className=\"k-select__control\" value={pageSize} onChange={(e) => onPageSizeChange(Number(e.target.value))}>\n                  {pageSizes.map((sz) => <option key={sz} value={sz}>{n(sz)}</option>)}\n                </select>\n              </span>\n              <span>{perPage}</span>\n            </label>\n          )}\n          {jumper && onChange && (\n            <form\n              className=\"k-pagination__tool\"\n              onSubmit={(e) => {\n                e.preventDefault();\n                const to = Number(jumpText.replace(/[۰-۹]/g, (d) => String(\"۰۱۲۳۴۵۶۷۸۹\".indexOf(d))).replace(/\\D/g, \"\"));\n                if (to >= 1 && to <= total) onChange(to);\n                setJumpText(\"\");\n              }}\n            >\n              <label className=\"k-pagination__tool\">\n                <span>{jump}</span>\n                <span className=\"k-input k-input--sm k-pagination__jump\"><input className=\"k-input__control\" inputMode=\"numeric\" dir=\"ltr\" value={jumpText} placeholder={n(page)} aria-label={M.pagination.jumpRange(jump, n(1), n(total))} onChange={(e) => setJumpText(e.target.value)} /></span>\n              </label>\n            </form>\n          )}\n        </div>\n      )}\n    </nav>\n  );\n}\n"
    }
  ]
}