{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "month-picker",
  "type": "registry:ui",
  "title": "MonthPicker",
  "description": "انتخاب ماه و سال شمسی، برای گزارش ماهانه یا تاریخ انقضای کارت؛ ↑↓←→ بین ماه‌ها و PageUp/PageDown بین سال‌ها",
  "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/MonthPicker.tsx",
      "type": "registry:ui",
      "target": "components/kashi/MonthPicker.tsx",
      "content": "\"use client\";\n\nimport { useEffect, useRef, useState, type KeyboardEvent } from \"react\";\nimport { JALALI_MONTHS, toFaDigits, toJalali } from \"@kashi-ui/persian\";\nimport { cx } from \"./cx\";\nimport { useKashi } from \"./KashiProvider\";\n\nexport interface JalaliMonth {\n  year: number;\n  /** ۱ تا ۱۲ */\n  month: number;\n}\n\nexport interface MonthPickerProps {\n  value?: JalaliMonth | null;\n  defaultValue?: JalaliMonth | null;\n  onChange?: (value: JalaliMonth) => void;\n  min?: JalaliMonth;\n  max?: JalaliMonth;\n  /** @default \"fa\" */\n  digits?: \"fa\" | \"latin\";\n  /** @default \"انتخاب ماه\" */\n  \"aria-label\"?: string;\n  className?: string;\n  labels?: { prevYear?: string; nextYear?: string };\n}\n\nconst key = (m: JalaliMonth) => m.year * 12 + m.month;\nconst Arrow = ({ next }: { next?: boolean }) => (\n  <svg viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth={1.7} strokeLinecap=\"round\" strokeLinejoin=\"round\" aria-hidden=\"true\" data-k-mirror=\"\">\n    <path d={next ? \"m8 5 5 5-5 5\" : \"m12 5-5 5 5 5\"} />\n  </svg>\n);\n\n/** انتخاب ماه و سال شمسی، برای گزارش ماهانه یا تاریخ انقضای کارت؛ ↑↓←→ بین ماه‌ها و PageUp/PageDown بین سال‌ها */\nexport function MonthPicker({ value, defaultValue = null, onChange, min, max, digits, \"aria-label\": ariaLabel, className, labels = {} }: MonthPickerProps) {\n  const { messages: M, digits: D, months: MONTHS } = useKashi();\n  digits ??= D;\n  ariaLabel ??= M.monthPicker.label;\n  const { prevYear = M.monthPicker.prevYear, nextYear = M.monthPicker.nextYear } = labels;\n  const today = toJalali(new Date());\n  const [inner, setInner] = useState<JalaliMonth | null>(defaultValue);\n  const selected = value !== undefined ? value : inner;\n  const [year, setYear] = useState(selected?.year ?? today.jy);\n  const [focus, setFocus] = useState(selected?.year === year ? selected.month : today.jy === year ? today.jm : 1);\n  const grid = useRef<HTMLDivElement>(null);\n  // پس از رندر سال یا ماه تازه، فوکوس به همان ماه برود (با کیبورد)\n  const pendingFocus = useRef(false);\n  useEffect(() => {\n    if (!pendingFocus.current) return;\n    pendingFocus.current = false;\n    grid.current?.querySelector<HTMLButtonElement>(`[data-month=\"${focus}\"]`)?.focus();\n  }, [year, focus]);\n  const f = (n: number) => (digits === \"fa\" ? toFaDigits(String(n)) : String(n));\n  const out = (m: JalaliMonth) => (min && key(m) < key(min)) || (max && key(m) > key(max));\n\n  const pick = (m: JalaliMonth) => {\n    if (out(m)) return;\n    if (value === undefined) setInner(m);\n    onChange?.(m);\n  };\n\n  const moveTo = (y: number, m: number) => {\n    pendingFocus.current = true;\n    setYear(y);\n    setFocus(m);\n  };\n\n  const onKeyDown = (e: KeyboardEvent) => {\n    const rtl = getComputedStyle(e.currentTarget).direction === \"rtl\";\n    const delta: Record<string, number> = { ArrowRight: rtl ? -1 : 1, ArrowLeft: rtl ? 1 : -1, ArrowDown: 3, ArrowUp: -3 };\n    let idx = year * 12 + focus - 1;\n    if (e.key in delta) idx += delta[e.key];\n    else if (e.key === \"PageUp\") idx -= 12;\n    else if (e.key === \"PageDown\") idx += 12;\n    else if (e.key === \"Home\") idx = year * 12;\n    else if (e.key === \"End\") idx = year * 12 + 11;\n    else return;\n    e.preventDefault();\n    moveTo(Math.floor(idx / 12), (idx % 12) + 1);\n  };\n\n  return (\n    <div className={cx(\"k-monthpicker\", className)} role=\"group\" aria-label={ariaLabel}>\n      <div className=\"k-monthpicker__header\">\n        <button type=\"button\" className=\"k-btn k-btn--tertiary k-btn--icon k-btn--sm\" aria-label={prevYear} onClick={() => setYear(year - 1)} disabled={!!min && year <= min.year}><Arrow /></button>\n        <span className=\"k-monthpicker__year\" aria-live=\"polite\">{f(year)}</span>\n        <button type=\"button\" className=\"k-btn k-btn--tertiary k-btn--icon k-btn--sm\" aria-label={nextYear} onClick={() => setYear(year + 1)} disabled={!!max && year >= max.year}><Arrow next /></button>\n      </div>\n      <div className=\"k-monthpicker__grid\" ref={grid} onKeyDown={onKeyDown}>\n        {MONTHS.map((name, i) => {\n          const m = { year, month: i + 1 };\n          const isSel = selected?.year === year && selected.month === i + 1;\n          return (\n            <button\n              key={name}\n              type=\"button\"\n              data-month={i + 1}\n              className=\"k-monthpicker__month\"\n              tabIndex={focus === i + 1 ? 0 : -1}\n              aria-pressed={isSel}\n              aria-label={`${name} ${f(year)}`}\n              aria-current={today.jy === year && today.jm === i + 1 ? \"date\" : undefined}\n              disabled={!!out(m)}\n              onFocus={() => setFocus(i + 1)}\n              onClick={() => pick(m)}\n            >\n              {name}\n            </button>\n          );\n        })}\n      </div>\n    </div>\n  );\n}\n"
    }
  ]
}