{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ink/timer",
  "title": "Timer",
  "description": "Countdown timer with pause/resume and auto-start",
  "dependencies": [
    "ink"
  ],
  "registryDependencies": [
    "https://termcn.dev/r/ink/interaction.json",
    "https://termcn.dev/r/ink/use-interval.json",
    "https://termcn.dev/r/ink/use-theme.json",
    "https://termcn.dev/r/ink/use-unicode.json"
  ],
  "files": [
    {
      "path": "registry/ui/timer.tsx",
      "content": "import { Box, Text } from \"ink\";\nimport React, { useState, useCallback } from \"react\";\n\nimport { useInteraction } from \"@/hooks/use-interaction\";\nimport type { InteractionProps } from \"@/hooks/use-interaction\";\nimport { useInterval } from \"@/hooks/use-interval\";\nimport { useTheme } from \"@/hooks/use-theme\";\nimport { useUnicode } from \"@/hooks/use-unicode\";\n\nexport interface TimerProps extends InteractionProps {\n  duration: number;\n  onComplete?: () => void;\n  autoStart?: boolean;\n  format?: \"hms\" | \"ms\" | \"s\";\n  color?: string;\n  label?: string;\n  \"aria-label\"?: string;\n}\n\nconst padNum = (n: number) => String(n).padStart(2, \"0\");\n\nconst formatTime = (seconds: number, format: \"hms\" | \"ms\" | \"s\"): string => {\n  const h = Math.floor(seconds / 3600);\n  const m = Math.floor((seconds % 3600) / 60);\n  const s = seconds % 60;\n\n  if (format === \"s\") {\n    return `${seconds}s`;\n  }\n  if (format === \"ms\") {\n    return `${padNum(m)}:${padNum(s)}`;\n  }\n  return `${padNum(h)}:${padNum(m)}:${padNum(s)}`;\n};\n\nexport const Timer = ({\n  duration,\n  onComplete,\n  autoStart = false,\n  format = \"hms\",\n  color,\n  label,\n  id,\n  autoFocus,\n  isActive = true,\n  disabled,\n  \"aria-label\": ariaLabel,\n}: TimerProps) => {\n  const theme = useTheme();\n  const unicode = useUnicode();\n  const resolvedColor = color ?? theme.colors.primary;\n\n  const [remaining, setRemaining] = useState(duration);\n  const [running, setRunning] = useState(autoStart);\n  const [completed, setCompleted] = useState(false);\n\n  const tick = useCallback(() => {\n    setRemaining((prev) => {\n      if (prev <= 1) {\n        setRunning(false);\n        setCompleted(true);\n        onComplete?.();\n        return 0;\n      }\n      return prev - 1;\n    });\n  }, [onComplete]);\n\n  useInterval(tick, running ? 1000 : null, { isActive });\n\n  const { isFocused } = useInteraction(\n    (input) => {\n      if (input === \" \") {\n        if (!completed) {\n          setRunning((r) => !r);\n        }\n      } else if (input === \"r\") {\n        setRemaining(duration);\n        setRunning(false);\n        setCompleted(false);\n      }\n    },\n    { autoFocus, disabled, id, isActive }\n  );\n\n  const runningStatus = running ? \"Running\" : \"Paused\";\n  const status = completed ? \"Done!\" : runningStatus;\n  const runningStatusColor = running\n    ? resolvedColor\n    : theme.colors.mutedForeground;\n  const statusColor = completed ? theme.colors.success : runningStatusColor;\n\n  return (\n    <Box\n      flexDirection=\"column\"\n      gap={0}\n      aria-role=\"timer\"\n      aria-label={\n        ariaLabel ??\n        `${label ? `${label}. ` : \"\"}${formatTime(remaining, format)} remaining. ${status}.`\n      }\n      aria-state={{ busy: running, disabled: disabled || undefined }}\n    >\n      {label && <Text color={theme.colors.mutedForeground}>{label}</Text>}\n      <Box gap={2} alignItems=\"center\">\n        <Text color={resolvedColor} bold>\n          {formatTime(remaining, format)}\n        </Text>\n        <Text color={statusColor}>[{status}]</Text>\n      </Box>\n      <Text aria-hidden color={theme.colors.mutedForeground} dimColor>\n        {completed\n          ? \"r to reset\"\n          : unicode\n            ? \"space pause/resume · r reset\"\n            : \"space pause/resume - r reset\"}\n      </Text>\n      {isFocused && <Text aria-hidden>Focused</Text>}\n    </Box>\n  );\n};\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "utility"
  ],
  "type": "registry:ui"
}