{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "toggle",
  "title": "Toggle",
  "description": "눌림 유지 버튼 — pressed 상태(aria-pressed), default/outline 변형 × default/sm/lg 크기. toggle-group의 기본 부품.",
  "dependencies": [
    "@unikit-bridge/ui",
    "class-variance-authority",
    "clsx",
    "tailwind-merge",
    "tailwindcss"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/ui/toggle.tsx",
      "content": "// Toggle — shadcn/ui new-york-v4 toggle을 UniKit UI 브리지로 이식.\n// 포팅 판단:\n// - radix Toggle 제거 — 눌림 상태는 React state（제어/비제어）로 관리.\n// - 원본의 data-state=on 셀렉터 → pressed 조건부 클래스（bg-accent·text-accent-foreground）.\n// - ［&_svg］:* 규칙은 아이콘 없는 글리프 구조（내부 Text）에서 대상이 없어 제외.\n// - 이중 지정 원칙（§0.5）: 눌림 배경은 Pressable, 전경색（hover 포함）은 내부 Text에\n//   명시（네이티브는 컨테이너 색이 자식 Text로 상속되지 않는다）.\n// - 원본 base의 aria-invalid:border-destructive·ring-destructive/20은 v0.1 API에\n//   invalid 상태가 없어 미지원 — 로드맵.\nimport { forwardRef, useState, type ReactNode } from \"react\";\nimport {\n  Pressable,\n  Text,\n  type BridgePressableRef,\n  type PressableProps,\n} from \"@unikit-bridge/ui/primitives\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\n// 컨테이너（Pressable） — 원본 base의 hover:bg-muted（기본 변형 호버）를 포함.\n// outline 변형의 hover:bg-accent는 변형 클래스가 뒤에 오므로 twMerge가 대체한다.\nconst toggleVariants = cva(\n  \"flex flex-row items-center justify-center gap-2 rounded-md web:whitespace-nowrap web:transition-all web:outline-none web:hover:bg-muted web:focus-visible:border-ring web:focus-visible:ring-3 web:focus-visible:ring-ring/50\",\n  {\n    variants: {\n      variant: {\n        default: \"bg-transparent\",\n        outline:\n          \"border border-input bg-transparent web:hover:bg-accent\",\n      },\n      size: {\n        default: \"h-9 min-w-9 px-2\",\n        sm: \"h-8 min-w-8 px-1.5\",\n        lg: \"h-10 min-w-10 px-2.5\",\n      },\n    },\n    defaultVariants: {\n      variant: \"default\",\n      size: \"default\",\n    },\n  },\n);\n\n// 내부 Text — 변형별 hover 전경색（원본 base의 hover:text-muted-foreground와\n// outline 변형의 hover:text-accent-foreground 대응）. pressed 오버라이드\n// （text-accent-foreground）는 렌더 시 조건부로 뒤에 합성한다.\nconst toggleTextVariants = cva(\"font-sans text-sm font-medium\", {\n  variants: {\n    variant: {\n      default: \"text-foreground web:hover:text-muted-foreground\",\n      outline: \"text-foreground web:hover:text-accent-foreground\",\n    },\n  },\n  defaultVariants: {\n    variant: \"default\",\n  },\n});\n\n// 터치 타깃 44px 보정 — h-9/h-8/h-10（button.tsx 관례와 동일 스케일）.\nconst HIT_SLOP = { default: 4, sm: 4, lg: 0 } as const;\n\nexport type ToggleProps = Omit<PressableProps, \"onPress\" | \"aria-pressed\"> &\n  VariantProps<typeof toggleVariants> & {\n    /** 제어형 눌림 상태（지정 시 내부 state를 대체） */\n    pressed?: boolean;\n    /** 비제어형 초기 눌림 상태 */\n    defaultPressed?: boolean;\n    /** 눌림 전환 콜백 */\n    onPressedChange?: (pressed: boolean) => void;\n    children?: ReactNode;\n  };\n\nconst Toggle = forwardRef<BridgePressableRef, ToggleProps>(\n  (\n    {\n      className,\n      variant,\n      size,\n      pressed,\n      defaultPressed = false,\n      onPressedChange,\n      disabled,\n      hitSlop,\n      children,\n      ...props\n    },\n    ref,\n  ) => {\n    // 제어/비제어 통합 — toggle-group이 pressed를 주입할 때도 이 경로로 제어된다.\n    const [uncontrolled, setUncontrolled] = useState(defaultPressed);\n    const isControlled = pressed !== undefined;\n    const isPressed = isControlled ? pressed : uncontrolled;\n    const resolvedSize = size ?? \"default\";\n\n    const handlePress = () => {\n      const next = !isPressed;\n      if (!isControlled) setUncontrolled(next);\n      onPressedChange?.(next);\n    };\n\n    return (\n      <Pressable\n        ref={ref}\n        accessibilityRole=\"button\"\n        aria-pressed={isPressed}\n        aria-disabled={disabled ? true : undefined}\n        disabled={disabled}\n        hitSlop={hitSlop ?? HIT_SLOP[resolvedSize]}\n        onPress={handlePress}\n        className={cn(\n          toggleVariants({ variant, size }),\n          // 원본의 on 상태 bg-accent 전개 — bg-transparent를 twMerge가 대체.\n          isPressed && \"bg-accent\",\n          disabled && \"web:pointer-events-none opacity-50\",\n          className,\n        )}\n        {...props}\n      >\n        <Text\n          className={cn(\n            toggleTextVariants({ variant }),\n            isPressed && \"text-accent-foreground\",\n          )}\n        >\n          {children}\n        </Text>\n      </Pressable>\n    );\n  },\n);\nToggle.displayName = \"Toggle\";\n\nexport { Toggle, toggleVariants, toggleTextVariants };\n",
      "type": "registry:ui",
      "target": "components/unikit/toggle.tsx"
    }
  ],
  "type": "registry:ui"
}
