{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "swatch-group",
  "type": "registry:ui",
  "title": "SwatchGroup",
  "description": "انتخاب رنگ از میان نمونه‌ها (فیلتر رنگ کالا)؛ روی چک‌باکس یا رادیوی بومی، پس صفحه‌کلید و فرم خودکار کار می‌کنند",
  "registryDependencies": [
    "https://kashi.sepantapouya.com/r/cx.json",
    "https://kashi.sepantapouya.com/r/kashi-provider.json"
  ],
  "files": [
    {
      "path": "registry/kashi/SwatchGroup.tsx",
      "type": "registry:ui",
      "target": "components/kashi/SwatchGroup.tsx",
      "content": "\"use client\";\n\nimport { useId, useState, type CSSProperties, type ReactNode } from \"react\";\nimport { cx } from \"./cx\";\nimport { useKashi } from \"./KashiProvider\";\n\nexport interface SwatchOption {\n  value: string;\n  label: ReactNode;\n  /** رنگ نمونه؛ هر مقدار CSS برای background: رنگ، گرادیان یا تصویر */\n  color: string;\n  disabled?: boolean;\n}\n\nexport interface SwatchGroupProps {\n  options: SwatchOption[];\n  /** مقدارهای انتخاب‌شده */\n  value?: string[];\n  defaultValue?: string[];\n  onChange?: (value: string[]) => void;\n  /** فقط یک انتخاب (مثل رنگ کالا در صفحهٔ خرید)؛ پیش‌فرض چندانتخابی برای فیلتر */\n  single?: boolean;\n  /** عنوان گروه، مثل «رنگ» */\n  label?: ReactNode;\n  /** اندازهٔ نمونه‌ها @default \"md\" */\n  size?: \"sm\" | \"md\" | \"lg\";\n  /** با name، مقدارهای انتخاب‌شده در فرم ارسال می‌شوند */\n  name?: string;\n  /** فقط‌خواندنی: انتخاب‌ها دیده می‌شوند ولی عوض نمی‌شوند */\n  readOnly?: boolean;\n  className?: string;\n}\n\n/** انتخاب رنگ از میان نمونه‌ها (فیلتر رنگ کالا)؛ روی چک‌باکس یا رادیوی بومی، پس صفحه‌کلید و فرم خودکار کار می‌کنند */\nexport function SwatchGroup({ options, value, defaultValue, onChange, single = false, label, size = \"md\", name, readOnly, className }: SwatchGroupProps) {\n  const { messages: M } = useKashi();\n  const id = useId();\n  const [inner, setInner] = useState<string[]>(defaultValue ?? []);\n  const selected = value ?? inner;\n\n  const toggle = (v: string) => {\n    if (readOnly) return;\n    const next = single ? (selected[0] === v ? [] : [v]) : selected.includes(v) ? selected.filter((x) => x !== v) : [...selected, v];\n    if (value === undefined) setInner(next);\n    onChange?.(next);\n  };\n\n  return (\n    <fieldset className={cx(\"k-swatches\", size !== \"md\" && `k-swatches--${size}`, className)} aria-readonly={readOnly || undefined} data-readonly={readOnly || undefined}>\n      {label && <legend className=\"k-label k-swatches__legend\">{label}</legend>}\n      <div className=\"k-swatches__grid\" role={single ? \"radiogroup\" : undefined}>\n        {options.map((o) => {\n          const on = selected.includes(o.value);\n          return (\n            <label key={o.value} className=\"k-swatch\" data-disabled={o.disabled || undefined}>\n              <input\n                type={single ? \"radio\" : \"checkbox\"}\n                className=\"k-sr-only\"\n                name={name ?? (single ? id : undefined)}\n                value={o.value}\n                checked={on}\n                disabled={o.disabled}\n                onChange={() => toggle(o.value)}\n                onClick={(e) => { if (readOnly) { e.preventDefault(); return; } if (single && on) { e.preventDefault(); toggle(o.value); } }}\n              />\n              <span className=\"k-swatch__color\" style={{ \"--_c\": o.color } as CSSProperties} aria-hidden=\"true\">\n                <svg className=\"k-swatch__check\" viewBox=\"0 0 20 20\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"m5 10.5 3.2 3L15 7\" /></svg>\n              </span>\n              <span className=\"k-swatch__label\">{o.label}{on && <span className=\"k-sr-only\">، {M.swatch.selected}</span>}</span>\n            </label>\n          );\n        })}\n      </div>\n    </fieldset>\n  );\n}\n"
    }
  ]
}