{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ink/checkbox",
  "title": "Checkbox",
  "description": "Checkbox with indeterminate state",
  "dependencies": [
    "ink"
  ],
  "registryDependencies": [
    "https://termcn.dev/r/ink/interaction.json",
    "https://termcn.dev/r/ink/terminal-symbols.json",
    "https://termcn.dev/r/ink/use-theme.json",
    "https://termcn.dev/r/ink/use-unicode.json"
  ],
  "files": [
    {
      "path": "registry/ui/checkbox.tsx",
      "content": "import { Box, Text } from \"ink\";\nimport React, { useState } from \"react\";\n\nimport {\n  isActivationKey,\n  useInteraction,\n} from \"@/hooks/use-interaction\";\nimport { useTheme } from \"@/hooks/use-theme\";\nimport { useUnicode } from \"@/hooks/use-unicode\";\nimport { resolveTerminalSymbol } from \"@/lib/terminal-symbols\";\n\nexport interface CheckboxProps {\n  checked?: boolean;\n  defaultChecked?: boolean;\n  onCheckedChange?: (checked: boolean) => void;\n  onChange?: (checked: boolean) => void;\n  label?: string;\n  indeterminate?: boolean;\n  disabled?: boolean;\n  id?: string;\n  autoFocus?: boolean;\n  isActive?: boolean;\n  \"aria-label\"?: string;\n  checkedIcon?: string;\n  uncheckedIcon?: string;\n  indeterminateIcon?: string;\n}\n\nexport const Checkbox = ({\n  checked: controlledChecked,\n  defaultChecked = false,\n  onCheckedChange,\n  onChange,\n  label,\n  indeterminate = false,\n  disabled = false,\n  id,\n  autoFocus = false,\n  isActive = true,\n  \"aria-label\": ariaLabel,\n  checkedIcon,\n  uncheckedIcon,\n  indeterminateIcon,\n}: CheckboxProps) => {\n  const [internalChecked, setInternalChecked] = useState(defaultChecked);\n  const theme = useTheme();\n  const unicode = useUnicode();\n\n  const checked = controlledChecked ?? internalChecked;\n\n  const { isFocused } = useInteraction(\n    (input, key) => {\n      if (disabled) {\n        return;\n      }\n      if (isActivationKey(input, key)) {\n        const next = !checked;\n        const changeHandler = onCheckedChange ?? onChange;\n        if (changeHandler) {\n          changeHandler(next);\n        } else {\n          setInternalChecked(next);\n        }\n      }\n    },\n    { autoFocus, disabled, id, isActive }\n  );\n\n  const resolvedCheckedIcon =\n    checkedIcon ?? resolveTerminalSymbol(unicode, \"■\", \"[x]\");\n  const resolvedUncheckedIcon =\n    uncheckedIcon ?? resolveTerminalSymbol(unicode, \"□\", \"[ ]\");\n  const resolvedIndeterminateIcon =\n    indeterminateIcon ?? resolveTerminalSymbol(unicode, \"▪\", \"[-]\");\n  const checkedIcon_ = checked ? resolvedCheckedIcon : resolvedUncheckedIcon;\n  const icon = indeterminate ? resolvedIndeterminateIcon : checkedIcon_;\n  const activeColor =\n    checked || indeterminate ? theme.colors.primary : theme.colors.border;\n  const iconColor = disabled ? theme.colors.mutedForeground : activeColor;\n\n  return (\n    <Box\n      aria-label={ariaLabel ?? label ?? \"Checkbox\"}\n      aria-role=\"checkbox\"\n      aria-state={{ checked: checked || indeterminate, disabled }}\n      gap={1}\n    >\n      <Text aria-hidden>{isFocused ? \">\" : \" \"}</Text>\n      <Text\n        aria-hidden\n        color={isFocused ? theme.colors.focusRing : iconColor}\n        bold={isFocused}\n        inverse={isFocused}\n      >\n        {icon}\n      </Text>\n      {label && (\n        <Text\n          aria-hidden\n          color={\n            disabled ? theme.colors.mutedForeground : theme.colors.foreground\n          }\n          dimColor={disabled}\n        >\n          {label}\n        </Text>\n      )}\n    </Box>\n  );\n};\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "selection"
  ],
  "type": "registry:ui"
}