{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "toggle-switch",
  "title": "方条开关",
  "description": "整条可点的开关，打开时铺上淡色、圆形手柄滑到右端，与数值滑块同一套高度。",
  "dependencies": [
    "@base-ui/react",
    "class-variance-authority"
  ],
  "registryDependencies": [
    "https://yiui.dev/r/flow-tone.json"
  ],
  "files": [
    {
      "path": "src/registry/ui/toggle-switch/toggle-switch.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Switch } from \"@base-ui/react/switch\"\nimport { cva } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\nimport { flowToneStyle, type FlowTone } from \"@/lib/flow-tone\"\n\n/**\n * 整条方条都是开关：左侧标签，右侧一个胶囊轨道和圆形手柄。\n * 打开时整条从左往右铺上淡色，轨道变成实色，手柄滑到右端。\n * 高度表与数值滑块一致（bar 28 / 32 / 36px，compact 18 / 22 / 24px）。\n */\nconst toggleSwitchVariants = cva(\n  \"group/toggle-switch relative flex h-(--toggle-switch-height) w-full min-w-0 cursor-pointer items-center justify-between gap-3 overflow-hidden rounded-md border border-edge bg-muted/60 px-3 text-start text-muted-foreground outline-none select-none transition-colors hover:text-foreground focus-visible:ring-3 focus-visible:ring-ring/50 data-[checked]:text-foreground data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40\",\n  {\n    variants: {\n      size: {\n        sm: \"text-xs\",\n        default: \"text-sm\",\n        lg: \"text-sm\",\n      },\n      variant: {\n        bar: \"\",\n        compact: \"text-xs\",\n      },\n    },\n    compoundVariants: [\n      {\n        variant: \"bar\",\n        size: \"sm\",\n        class:\n          \"[--toggle-switch-height:1.75rem] pointer-coarse:[--toggle-switch-height:2.25rem] [--toggle-switch-knob:0.75rem]\",\n      },\n      {\n        variant: \"bar\",\n        size: \"default\",\n        class:\n          \"[--toggle-switch-height:2rem] pointer-coarse:[--toggle-switch-height:2.5rem] [--toggle-switch-knob:0.875rem]\",\n      },\n      {\n        variant: \"bar\",\n        size: \"lg\",\n        class:\n          \"[--toggle-switch-height:2.25rem] pointer-coarse:[--toggle-switch-height:2.75rem] [--toggle-switch-knob:1rem]\",\n      },\n      {\n        variant: \"compact\",\n        size: \"sm\",\n        class:\n          \"[--toggle-switch-height:1.125rem] [--toggle-switch-knob:0.5rem]\",\n      },\n      {\n        variant: \"compact\",\n        size: \"default\",\n        class:\n          \"[--toggle-switch-height:1.375rem] [--toggle-switch-knob:0.625rem]\",\n      },\n      {\n        variant: \"compact\",\n        size: \"lg\",\n        class: \"[--toggle-switch-height:1.5rem] [--toggle-switch-knob:0.75rem]\",\n      },\n    ],\n    defaultVariants: {\n      size: \"default\",\n      variant: \"bar\",\n    },\n  },\n)\n\ntype ToggleSwitchSize = \"sm\" | \"default\" | \"lg\"\ntype ToggleSwitchVariant = \"bar\" | \"compact\"\n\ntype ToggleSwitchProps = Omit<\n  Switch.Root.Props,\n  \"render\" | \"nativeButton\" | \"children\"\n> & {\n  /** 标签，也是开关的可访问名称 */\n  label: React.ReactNode\n  /** 标签右侧的补充说明（如当前状态「已开启」）；不传时不显示 */\n  description?: React.ReactNode\n  /**\n   * 高度档：`bar` 与数值滑块默认同高，`compact` 是面板里用的中等高度\n   * @default \"bar\"\n   */\n  variant?: ToggleSwitchVariant\n  /**\n   * 尺寸档\n   * @default \"default\"\n   */\n  size?: ToggleSwitchSize\n  /** 色调：打开时的铺色与手柄取 `--flow-tone`；不传时用前景色 */\n  tone?: FlowTone\n  /**\n   * 标记为「已改动」：标签改用前景色，根元素带 `data-modified`\n   * @default false\n   */\n  modified?: boolean\n}\n\n/** 方条开关：基于 Base UI Switch，渲染为原生 `button`，带 `role=\"switch\"`。 */\nfunction ToggleSwitch({\n  label,\n  description,\n  variant = \"bar\",\n  size = \"default\",\n  tone,\n  modified = false,\n  className,\n  style,\n  ...props\n}: ToggleSwitchProps) {\n  const hasTone = tone !== undefined\n\n  return (\n    <Switch.Root\n      {...props}\n      nativeButton\n      render={<button type=\"button\" />}\n      data-slot=\"toggle-switch\"\n      data-variant={variant}\n      data-modified={modified ? \"\" : undefined}\n      className={cn(\n        toggleSwitchVariants({ size, variant }),\n        \"data-[modified]:text-foreground\",\n        className,\n      )}\n      style={{ ...flowToneStyle(tone), ...style }}\n    >\n      {/* 打开时的铺色：从左往右展开，和滑块的已选填充同一种淡色 */}\n      <span\n        aria-hidden=\"true\"\n        data-slot=\"toggle-switch-fill\"\n        className={cn(\n          \"absolute inset-0 origin-left scale-x-0 transition-transform duration-200 ease-out group-data-[checked]/toggle-switch:scale-x-100 motion-reduce:transition-none rtl:origin-right\",\n          hasTone\n            ? \"bg-(--flow-tone)/15 dark:bg-(--flow-tone)/25\"\n            : \"bg-foreground/5 dark:bg-foreground/10\",\n        )}\n      />\n      <span\n        data-slot=\"toggle-switch-label\"\n        className=\"relative flex min-w-0 items-baseline gap-2 font-medium\"\n      >\n        <span className=\"truncate\">{label}</span>\n        {description !== undefined ? (\n          <span\n            data-slot=\"toggle-switch-description\"\n            className=\"truncate font-normal text-muted-foreground\"\n          >\n            {description}\n          </span>\n        ) : null}\n      </span>\n      {/* 胶囊轨道 + 圆形手柄：最容易一眼读懂的开关形态；打开时轨道换成实色，手柄滑到另一端 */}\n      <span\n        aria-hidden=\"true\"\n        data-slot=\"toggle-switch-track\"\n        className={cn(\n          \"relative flex h-[calc(var(--toggle-switch-knob)+4px)] w-[calc(var(--toggle-switch-knob)*2+4px)] shrink-0 items-center rounded-full bg-foreground/15 p-0.5 transition-colors duration-200 motion-reduce:transition-none dark:bg-foreground/20\",\n          hasTone\n            ? \"group-data-[checked]/toggle-switch:bg-(--flow-tone) dark:group-data-[checked]/toggle-switch:bg-(--flow-tone)\"\n            : \"group-data-[checked]/toggle-switch:bg-foreground dark:group-data-[checked]/toggle-switch:bg-foreground\",\n        )}\n      >\n        <Switch.Thumb\n          data-slot=\"toggle-switch-thumb\"\n          className=\"size-(--toggle-switch-knob) rounded-full bg-background shadow-sm transition-transform duration-200 ease-out data-[checked]:translate-x-(--toggle-switch-knob) motion-reduce:transition-none rtl:data-[checked]:-translate-x-(--toggle-switch-knob)\"\n        />\n      </span>\n    </Switch.Root>\n  )\n}\n\nexport { ToggleSwitch, toggleSwitchVariants }\nexport type { ToggleSwitchProps, ToggleSwitchSize, ToggleSwitchVariant }\n",
      "type": "registry:ui",
      "target": "@ui/toggle-switch/toggle-switch.tsx"
    }
  ],
  "cssVars": {
    "theme": {
      "color-edge": "var(--edge)"
    },
    "light": {
      "edge": "color-mix(in oklch, var(--foreground) 12%, transparent)"
    },
    "dark": {
      "edge": "color-mix(in oklch, var(--foreground) 18%, transparent)"
    }
  },
  "type": "registry:ui"
}
