{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ink/progress-circle",
  "title": "Progress Circle",
  "description": "Circular progress indicator using Unicode braille",
  "dependencies": [
    "ink"
  ],
  "registryDependencies": [
    "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/progress-circle.tsx",
      "content": "import { Box, Text } from \"ink\";\n\nimport { useTheme } from \"@/hooks/use-theme\";\nimport { useUnicode } from \"@/hooks/use-unicode\";\nimport { resolveTerminalSymbol } from \"@/lib/terminal-symbols\";\n\nexport type ProgressCircleSize = \"sm\" | \"md\" | \"lg\";\n\nexport interface ProgressCircleProps {\n  value: number;\n  size?: ProgressCircleSize;\n  color?: string;\n  label?: string;\n  showPercent?: boolean;\n  \"aria-label\"?: string;\n}\n\nconst BRAILLE_CHARS = [\"○\", \"◔\", \"◑\", \"◕\", \"●\", \"◉\", \"⬤\", \"●\"];\n\nconst _MD_TOP = [\"▄▄▄\", \"▄██▄\"];\nconst _MD_MID_EMPTY = \"█   █\";\nconst _MD_MID_FILL = \"█████\";\nconst _MD_BOT = [\"▀▀▀\", \"▀██▀\"];\n\nconst getSmChar = (value: number): string => {\n  const clamped = Math.max(0, Math.min(100, value));\n  const step = Math.floor((clamped / 100) * 7);\n  return BRAILLE_CHARS[step];\n};\n\nexport const ProgressCircle = ({\n  value,\n  size = \"sm\",\n  color,\n  label,\n  showPercent = false,\n  \"aria-label\": ariaLabel,\n}: ProgressCircleProps) => {\n  const theme = useTheme();\n  const unicode = useUnicode();\n  const clamped = Math.max(0, Math.min(100, value));\n  const resolvedColor = color ?? theme.colors.primary;\n\n  if (size === \"sm\") {\n    let char = clamped > 0 ? \"#\" : \"o\";\n    if (unicode) {\n      char = getSmChar(clamped);\n    }\n    return (\n      <Box\n        flexDirection=\"column\"\n        alignItems=\"flex-start\"\n        aria-role=\"progressbar\"\n        aria-label={\n          ariaLabel ?? `${label ?? \"Progress\"}: ${Math.round(clamped)}%`\n        }\n        aria-state={{ busy: clamped < 100 }}\n      >\n        <Box flexDirection=\"row\" gap={1}>\n          <Text color={resolvedColor}>{char}</Text>\n          {showPercent && (\n            <Text color={theme.colors.muted}>{Math.round(clamped)}%</Text>\n          )}\n        </Box>\n        {label && <Text color={theme.colors.muted}>{label}</Text>}\n      </Box>\n    );\n  }\n\n  const percentLabel = `${Math.round(clamped)}%`;\n\n  if (size === \"md\") {\n    return (\n      <Box\n        flexDirection=\"column\"\n        alignItems=\"flex-start\"\n        aria-role=\"progressbar\"\n        aria-label={ariaLabel ?? `${label ?? \"Progress\"}: ${percentLabel}`}\n        aria-state={{ busy: clamped < 100 }}\n      >\n        <Box flexDirection=\"row\">\n          <Text color={resolvedColor}>\n            {resolveTerminalSymbol(unicode, \"⟨\", \"[\")}\n          </Text>\n          <Text color={resolvedColor} bold>\n            {percentLabel}\n          </Text>\n          <Text color={resolvedColor}>\n            {resolveTerminalSymbol(unicode, \"⟩\", \"]\")}\n          </Text>\n        </Box>\n        {label && <Text color={theme.colors.muted}>{label}</Text>}\n      </Box>\n    );\n  }\n\n  const fillLevel = clamped / 100;\n  const topArc = resolveTerminalSymbol(unicode, \" ▄█▄\", \"+---+\");\n  const midLeft = resolveTerminalSymbol(unicode, \"█\", \"|\");\n  const midRight = resolveTerminalSymbol(unicode, \"█\", \"|\");\n  const midInner =\n    fillLevel >= 0.5 ? resolveTerminalSymbol(unicode, \"███\", \"###\") : \"   \";\n  const botArc = resolveTerminalSymbol(unicode, \" ▀█▀\", \"+---+\");\n\n  return (\n    <Box\n      flexDirection=\"column\"\n      alignItems=\"flex-start\"\n      aria-role=\"progressbar\"\n      aria-label={ariaLabel ?? `${label ?? \"Progress\"}: ${percentLabel}`}\n      aria-state={{ busy: clamped < 100 }}\n    >\n      <Text color={resolvedColor}>{topArc}</Text>\n      <Box flexDirection=\"row\">\n        <Text color={resolvedColor}>{midLeft}</Text>\n        <Text color={fillLevel > 0 ? resolvedColor : theme.colors.muted}>\n          {midInner}\n        </Text>\n        <Text color={resolvedColor}>{midRight}</Text>\n      </Box>\n      <Text color={resolvedColor}>{botArc}</Text>\n      {showPercent && <Text color={theme.colors.muted}>{percentLabel}</Text>}\n      {label && <Text color={theme.colors.muted}>{label}</Text>}\n    </Box>\n  );\n};\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "feedback"
  ],
  "type": "registry:ui"
}