{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "radio",
  "type": "registry:ui",
  "title": "RadioGroup، Radio",
  "description": "گروه رادیو با fieldset و legend؛ پیمایش با کلیدهای جهت‌دار را مرورگر انجام می‌دهد",
  "registryDependencies": [
    "https://kashi.sepantapouya.com/r/cx.json",
    "https://kashi.sepantapouya.com/r/utils.json"
  ],
  "files": [
    {
      "path": "registry/kashi/Radio.tsx",
      "type": "registry:ui",
      "target": "components/kashi/Radio.tsx",
      "content": "\"use client\";\n\nimport { createContext, forwardRef, useContext, useId, useState, type InputHTMLAttributes, type ReactNode } from \"react\";\nimport { cx } from \"./cx\";\nimport { isDev } from \"./utils\";\n\ninterface Ctx { name: string; value: string | undefined; setValue: (v: string) => void; invalid?: boolean; disabled?: boolean }\nconst RadioCtx = createContext<Ctx | null>(null);\n\nexport interface RadioGroupProps {\n  /** عنوان گروه (legend) */\n  label: ReactNode;\n  /** نام فیلد فرم؛ پیش‌فرض خودکار */\n  name?: string;\n  value?: string;\n  defaultValue?: string;\n  onChange?: (value: string) => void;\n  /** «list» (پیش‌فرض)، «inline» افقی، «cards» کارت‌های قابل‌انتخاب */\n  variant?: \"list\" | \"inline\" | \"cards\";\n  hint?: ReactNode;\n  error?: ReactNode;\n  required?: boolean;\n  disabled?: boolean;\n  className?: string;\n  children: ReactNode;\n}\n\n/** گروه رادیو با fieldset و legend؛ پیمایش با کلیدهای جهت‌دار را مرورگر انجام می‌دهد */\nexport function RadioGroup({\n  label, name, value, defaultValue, onChange, variant = \"list\", hint, error, required, disabled, className, children,\n}: RadioGroupProps) {\n  const id = useId();\n  const [inner, setInner] = useState(defaultValue);\n  const current = value !== undefined ? value : inner;\n  const describedBy = [error && `${id}-error`, hint && `${id}-hint`].filter(Boolean).join(\" \") || undefined;\n  return (\n    <fieldset\n      className={cx(\"k-radio-group\", variant !== \"list\" && `k-radio-group--${variant}`, className)}\n      aria-describedby={describedBy}\n      aria-required={required || undefined}\n      aria-invalid={error ? true : undefined}\n      disabled={disabled}\n    >\n      <legend className=\"k-label\">\n        {label}\n        {required && <span className=\"k-label__required\" aria-hidden=\"true\">*</span>}\n      </legend>\n      <RadioCtx.Provider\n        value={{\n          name: name ?? id,\n          value: current,\n          invalid: !!error,\n          disabled,\n          setValue: (v) => {\n            if (value === undefined) setInner(v);\n            onChange?.(v);\n          },\n        }}\n      >\n        {children}\n      </RadioCtx.Provider>\n      {error && <p className=\"k-hint k-hint--error\" id={`${id}-error`}>{error}</p>}\n      {hint && <p className=\"k-hint\" id={`${id}-hint`}>{hint}</p>}\n    </fieldset>\n  );\n}\n\nexport interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, \"type\" | \"value\"> {\n  value: string;\n  label: ReactNode;\n  description?: ReactNode;\n  /** نشان کنار عنوان، مثل «پیشنهادی»؛ متن ساده به نشان برند تبدیل می‌شود. بیشتر برای variant=\"cards\" */\n  badge?: ReactNode;\n  /** قیمت یا اطلاعات کوتاه در انتهای کارت، مثل «۴۹۰ هزار تومان / سال». بیشتر برای variant=\"cards\" */\n  meta?: ReactNode;\n}\n\nexport const Radio = forwardRef<HTMLInputElement, RadioProps>(function Radio({ value, label, description, badge, meta, id, className, disabled, name, ...rest }, ref) {\n  const ctx = useContext(RadioCtx);\n  // بدون name مشترک، مرورگر رادیوها را یک گروه نمی‌داند و چند گزینه هم‌زمان انتخاب می‌شود\n  if (!ctx && !name && isDev()) {\n    console.warn(\"[kashi] <Radio> باید داخل <RadioGroup> باشد یا name داشته باشد؛ وگرنه چند گزینه هم‌زمان قابل‌انتخاب است.\");\n  }\n  const autoId = useId();\n  const inputId = id ?? autoId;\n  return (\n    <label className={cx(\"k-check\", className)} htmlFor={inputId}>\n      <input\n        ref={ref}\n        type=\"radio\"\n        className=\"k-radio\"\n        id={inputId}\n        name={ctx?.name ?? name}\n        value={value}\n        checked={ctx ? ctx.value === value : undefined}\n        onChange={() => ctx?.setValue(value)}\n        disabled={disabled}\n        aria-describedby={description ? `${inputId}-desc` : undefined}\n        {...rest}\n      />\n      <span className=\"k-check__text\">\n        {badge != null && badge !== false ? (\n          <span className=\"k-check__head\">\n            <span className=\"k-check__label\">{label}</span>\n            {typeof badge === \"string\" ? <span className=\"k-badge k-badge--brand k-badge--sm\">{badge}</span> : badge}\n          </span>\n        ) : (\n          <span className=\"k-check__label\">{label}</span>\n        )}\n        {description && <span className=\"k-check__description\" id={`${inputId}-desc`}>{description}</span>}\n      </span>\n      {meta != null && meta !== false && <span className=\"k-check__meta\">{meta}</span>}\n    </label>\n  );\n});\n"
    }
  ]
}