{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "plate-input",
  "type": "registry:ui",
  "title": "PlateInput",
  "description": "فیلد فارسی",
  "dependencies": [
    "@kashi-ui/persian@^1.8.0"
  ],
  "registryDependencies": [
    "https://kashi.sepantapouya.com/r/cx.json",
    "https://kashi.sepantapouya.com/r/field.json",
    "https://kashi.sepantapouya.com/r/kashi-provider.json"
  ],
  "files": [
    {
      "path": "registry/kashi/PlateInput.tsx",
      "type": "registry:ui",
      "target": "components/kashi/PlateInput.tsx",
      "content": "\"use client\";\n\nimport { useId, useRef, useState, type ReactNode } from \"react\";\nimport { PLATE_LETTERS, formatPlate, isValidPlate, onlyDigits, plateType, toFaDigits, type Plate } from \"@kashi-ui/persian\";\nimport { Field, describedBy } from \"./Field\";\nimport { useKashi } from \"./KashiProvider\";\n\nexport interface PlateInputProps {\n  label?: ReactNode;\n  hint?: ReactNode;\n  error?: ReactNode;\n  value?: Plate;\n  defaultValue?: Partial<Plate>;\n  onChange?: (plate: Plate, valid: boolean) => void;\n  /** با name، چهار فیلد پنهان name_first، name_letter، name_middle و name_region */\n  name?: string;\n  disabled?: boolean;\n  id?: string;\n  className?: string;\n  /** @default \"پلاک خودرو معتبر نیست.\" */\n  invalidMessage?: ReactNode;\n  labels?: { first?: string; letter?: string; middle?: string; region?: string };\n}\n\nconst EMPTY: Plate = { first: \"\", letter: \"\", middle: \"\", region: \"\" };\n\n/**\n * پلاک خودروی ایران با ظاهر واقعی: دو رقم، حرف، سه رقم و کد استان.\n * با پر شدن هر بخش فوکوس خودکار به بخش بعد می‌رود و Backspace در بخش خالی به قبلی برمی‌گردد.\n */\nexport function PlateInput({\n  label, hint, error, value, defaultValue, onChange, name, disabled, id, className,\n  invalidMessage, labels = {},\n}: PlateInputProps) {\n  const { messages: M } = useKashi();\n  invalidMessage ??= M.invalid.plate;\n  const autoId = useId();\n  const groupId = id ?? autoId;\n  // برچسب به اولین بخش وصل است تا کلیک روی آن فوکوس بدهد\n  const firstId = `${groupId}-first`;\n  const { first = M.plate.first, letter = M.plate.letter, middle = M.plate.middle, region = M.plate.region } = labels;\n  const [inner, setInner] = useState<Plate>({ ...EMPTY, ...defaultValue });\n  const plate = value ?? inner;\n  const [touched, setTouched] = useState(false);\n  const refs = [useRef<HTMLInputElement>(null), useRef<HTMLSelectElement>(null), useRef<HTMLInputElement>(null), useRef<HTMLInputElement>(null)];\n  const complete = plate.first.length === 2 && plate.letter && plate.middle.length === 3 && plate.region.length === 2;\n  const valid = isValidPlate(plate);\n  const showInvalid = (touched || complete) && Object.values(plate).some(Boolean) && !valid;\n\n  const set = (patch: Partial<Plate>) => {\n    const next = { ...plate, ...patch };\n    if (value === undefined) setInner(next);\n    onChange?.(next, isValidPlate(next));\n  };\n\n  const seg = (key: \"first\" | \"middle\" | \"region\", len: number, idx: number, aria: string, cls = \"\") => (\n    <input\n      ref={refs[idx] as React.RefObject<HTMLInputElement>}\n      id={idx === 0 ? firstId : undefined}\n      className={`k-plate__seg ${cls}`}\n      inputMode=\"numeric\"\n      autoComplete=\"off\"\n      aria-label={aria}\n      disabled={disabled}\n      placeholder={toFaDigits(\"0\".repeat(len))}\n      value={toFaDigits(plate[key])}\n      onChange={(e) => {\n        const all = onlyDigits(e.target.value);\n        const d = all.slice(0, len);\n        // تایپ سریع یا چسباندن: رقم‌های اضافه به بخش عددی بعدی می‌روند\n        if (key === \"middle\" && all.length > len) set({ middle: d, region: (plate.region + all.slice(len)).slice(0, 2) });\n        else set({ [key]: d });\n        if (d.length === len) refs[idx + 1]?.current?.focus();\n      }}\n      onKeyDown={(e) => {\n        if (e.key === \"Backspace\" && !plate[key]) refs[idx - 1]?.current?.focus();\n      }}\n    />\n  );\n\n  return (\n    <Field id={firstId} label={label} hint={hint} error={error ?? (showInvalid ? invalidMessage : undefined)} className={className}>\n      <div\n        className=\"k-plate\"\n        role=\"group\"\n        id={groupId}\n        aria-describedby={describedBy(firstId, hint, error ?? (showInvalid ? invalidMessage : undefined))}\n        aria-label={typeof label === \"string\" ? label : M.plate.label}\n        data-invalid={showInvalid || error ? \"\" : undefined}\n        data-type={plateType(plate.letter)}\n        onBlur={(e) => {\n          if (!e.currentTarget.contains(e.relatedTarget as Node)) setTouched(true);\n        }}\n      >\n        <span className=\"k-plate__flag\" aria-hidden=\"true\"><span className=\"k-plate__flag-colors\" />I.R.<br />IRAN</span>\n        {seg(\"first\", 2, 0, first)}\n        <select\n          ref={refs[1] as React.RefObject<HTMLSelectElement>}\n          className=\"k-plate__letter\"\n          aria-label={letter}\n          disabled={disabled}\n          value={plate.letter}\n          onChange={(e) => {\n            set({ letter: e.target.value });\n            if (e.target.value) refs[2].current?.focus();\n          }}\n        >\n          <option value=\"\">–</option>\n          {PLATE_LETTERS.map((l) => <option key={l} value={l}>{l === \"ه\" ? \"هـ\" : l}</option>)}\n        </select>\n        {seg(\"middle\", 3, 2, middle, \"k-plate__seg--3\")}\n        <span className=\"k-plate__region\">\n          <span className=\"k-plate__region-label\" aria-hidden=\"true\">ایران</span>\n          {seg(\"region\", 2, 3, region)}\n        </span>\n      </div>\n      <span className=\"k-sr-only\" aria-live=\"polite\">{valid ? formatPlate(plate) : \"\"}</span>\n      {name && ([\"first\", \"letter\", \"middle\", \"region\"] as const).map((k) => <input key={k} type=\"hidden\" name={`${name}_${k}`} value={plate[k]} />)}\n    </Field>\n  );\n}\n"
    }
  ]
}