{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "ink/error-retry",
  "title": "Error Retry",
  "description": "Inline error panel with retry, dismiss, and max-retry guard",
  "dependencies": [
    "ink"
  ],
  "registryDependencies": [
    "https://termcn.dev/r/ink/interaction.json",
    "https://termcn.dev/r/ink/terminal-style.json",
    "https://termcn.dev/r/ink/use-theme.json",
    "https://termcn.dev/r/ink/use-unicode.json"
  ],
  "files": [
    {
      "path": "registry/ui/error-retry.tsx",
      "content": "import { useIsScreenReaderEnabled, Box, Text } from \"ink\";\nimport React from \"react\";\n\nimport {\n  isActivationKey,\n  useInteraction,\n} from \"@/hooks/use-interaction\";\nimport type { InteractionProps } from \"@/hooks/use-interaction\";\nimport { useTheme } from \"@/hooks/use-theme\";\nimport { useUnicode } from \"@/hooks/use-unicode\";\nimport { resolveBorderStyle } from \"@/lib/terminal-style\";\n\nexport interface ErrorRetryProps extends InteractionProps {\n  error: Error | string;\n  onRetry?: () => void;\n  onDismiss?: () => void;\n  retryCount?: number;\n  maxRetries?: number;\n  \"aria-label\"?: string;\n}\n\nexport function ErrorRetry({\n  error,\n  onRetry,\n  onDismiss,\n  retryCount = 0,\n  maxRetries = 3,\n  isActive = true,\n  id,\n  autoFocus,\n  disabled,\n  \"aria-label\": ariaLabel,\n}: ErrorRetryProps) {\n  const unicode = useUnicode();\n  const theme = useTheme();\n  const isScreenReaderEnabled = useIsScreenReaderEnabled();\n  const message = typeof error === \"string\" ? error : error.message;\n  const maxReached = retryCount >= maxRetries;\n\n  const { isFocused } = useInteraction(\n    (input, key) => {\n      if (!maxReached && (isActivationKey(input, key) || input === \"r\")) {\n        onRetry?.();\n      } else if (key.escape) {\n        onDismiss?.();\n      }\n    },\n    { autoFocus, disabled, id, isActive }\n  );\n\n  return (\n    <Box\n      flexDirection=\"column\"\n      borderStyle={resolveBorderStyle(\n        isScreenReaderEnabled ? undefined : \"round\",\n        unicode\n      )}\n      borderColor={theme.colors.error ?? \"red\"}\n      paddingX={1}\n      paddingY={0}\n      aria-role=\"button\"\n      aria-label={\n        ariaLabel ??\n        `Error: ${message}. ${maxReached ? \"Maximum retries reached.\" : `Retry ${retryCount} of ${maxRetries}. Press Enter to retry or Escape to dismiss.`}`\n      }\n      aria-state={{ disabled: disabled || undefined }}\n    >\n      <Box gap={1}>\n        <Text aria-hidden color={theme.colors.error ?? \"red\"} bold>\n          {unicode ? \"✗\" : \"x\"}\n        </Text>\n        <Text>{message}</Text>\n      </Box>\n\n      {retryCount > 0 && (\n        <Text dimColor color={theme.colors.mutedForeground}>\n          Retry attempt {retryCount}\n        </Text>\n      )}\n\n      {maxReached ? (\n        <Text dimColor color={theme.colors.mutedForeground}>\n          Max retries reached\n        </Text>\n      ) : (\n        <Text aria-hidden dimColor color={theme.colors.mutedForeground}>\n          {unicode\n            ? \"Enter / r — retry · Esc — dismiss\"\n            : \"Enter / r - retry | Esc - dismiss\"}\n        </Text>\n      )}\n      {isFocused && <Text aria-hidden>[focused]</Text>}\n    </Box>\n  );\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "ai"
  ],
  "type": "registry:ui"
}