{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "settings-panel",
  "title": "Settings panel",
  "description": "A controlled preference panel with labelled switches, per-option disabled states and optional footer actions.",
  "registryDependencies": [
    "Familis-co/registry/card",
    "Familis-co/registry/field",
    "Familis-co/registry/switch"
  ],
  "files": [
    {
      "path": "registry/familis/blocks/settings-panel/settings-panel.tsx",
      "content": "\"use client\"\n\nimport { Fragment, useId, type ComponentProps, type ReactNode } from \"react\"\nimport {\n  Card,\n  CardContent,\n  CardDescription,\n  CardFooter,\n  CardHeader,\n  CardTitle,\n} from \"@/registry/familis/ui/card\"\nimport {\n  Field,\n  FieldContent,\n  FieldDescription,\n  FieldGroup,\n  FieldLabel,\n  FieldLegend,\n  FieldSeparator,\n  FieldSet,\n} from \"@/registry/familis/ui/field\"\nimport { Switch } from \"@/registry/familis/ui/switch\"\n\nexport interface PreferenceOption {\n  /** A unique, stable identifier within this panel. */\n  id: string\n  label: string\n  description?: string\n  checked: boolean\n  disabled?: boolean\n}\n\nexport interface SettingsPanelProps extends Omit<\n  ComponentProps<typeof Card>,\n  \"title\" | \"children\"\n> {\n  title: string\n  description?: string\n  options: readonly PreferenceOption[]\n  onCheckedChange: (id: string, checked: boolean) => void\n  disabled?: boolean\n  footer?: ReactNode\n}\n\n/** Controlled boolean preferences. Persist changes or render a save action in the consuming app. */\nexport function SettingsPanel({\n  title,\n  description,\n  options,\n  onCheckedChange,\n  disabled = false,\n  footer,\n  ...props\n}: SettingsPanelProps) {\n  const panelId = useId()\n\n  return (\n    <Card {...props}>\n      <CardHeader>\n        <CardTitle>{title}</CardTitle>\n        {description && <CardDescription>{description}</CardDescription>}\n      </CardHeader>\n      <CardContent>\n        <FieldSet disabled={disabled}>\n          <FieldLegend className=\"sr-only\">{title}</FieldLegend>\n          <FieldGroup>\n            {options.map((option, index) => {\n              const id = `${panelId}-${option.id}`\n              const optionDisabled = disabled || option.disabled\n              return (\n                <Fragment key={option.id}>\n                  {index > 0 && <FieldSeparator />}\n                  <Field orientation=\"horizontal\" data-disabled={optionDisabled || undefined}>\n                    <FieldContent>\n                      <FieldLabel htmlFor={id}>{option.label}</FieldLabel>\n                      {option.description && (\n                        <FieldDescription id={`${id}-description`}>\n                          {option.description}\n                        </FieldDescription>\n                      )}\n                    </FieldContent>\n                    <Switch\n                      id={id}\n                      name={option.id}\n                      checked={option.checked}\n                      disabled={optionDisabled}\n                      aria-describedby={option.description ? `${id}-description` : undefined}\n                      onCheckedChange={(checked) => onCheckedChange(option.id, checked)}\n                    />\n                  </Field>\n                </Fragment>\n              )\n            })}\n          </FieldGroup>\n        </FieldSet>\n      </CardContent>\n      {footer != null && <CardFooter>{footer}</CardFooter>}\n    </Card>\n  )\n}\n",
      "type": "registry:component"
    }
  ],
  "meta": {
    "base": "base",
    "storybookId": "ui-blocks-settings-panel--default"
  },
  "type": "registry:block"
}