{
  "name": "thinking-indicator",
  "dependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "thinking-indicator.tsx",
      "content": "\"use client\";\r\n\r\nimport { css, keyframes, themeVars as theme } from \"@yugnex/core\";\r\nimport type { HTMLAttributes, ReactNode } from \"react\";\r\n\r\nconst bounce = keyframes({\r\n  \"0%, 80%, 100%\": { transform: \"translateY(0)\", opacity: 0.4 },\r\n  \"40%\": { transform: \"translateY(-4px)\", opacity: 1 },\r\n});\r\n\r\nconst shimmer = keyframes({\r\n  \"0%\": { backgroundPosition: \"200% 0\" },\r\n  \"100%\": { backgroundPosition: \"-200% 0\" },\r\n});\r\n\r\nconst rootClass = css({\r\n  display: \"inline-flex\",\r\n  alignItems: \"center\",\r\n  gap: theme.space[2],\r\n  fontFamily: theme.fontFamily.sans,\r\n  fontSize: theme.fontSize.sm,\r\n});\r\n\r\nconst dotsClass = css({\r\n  display: \"inline-flex\",\r\n  gap: \"3px\",\r\n  alignItems: \"center\",\r\n});\r\n\r\nconst dotClass = css({\r\n  width: \"6px\",\r\n  height: \"6px\",\r\n  borderRadius: \"9999px\",\r\n  backgroundColor: \"currentColor\",\r\n  animation: `${bounce} 1.2s ease-in-out infinite`,\r\n});\r\n\r\nconst labelClass = css({\r\n  // A moving highlight over the label reads as \"working\" even when the dots\r\n  // are stilled by prefers-reduced-motion (the global reduce rule collapses\r\n  // animation duration, leaving the text legible rather than blank).\r\n  background: `linear-gradient(90deg, ${theme.color.mutedForeground} 0%, ${theme.color.foreground} 50%, ${theme.color.mutedForeground} 100%)`,\r\n  backgroundSize: \"200% 100%\",\r\n  backgroundClip: \"text\",\r\n  WebkitBackgroundClip: \"text\",\r\n  color: \"transparent\",\r\n  animation: `${shimmer} 2s linear infinite`,\r\n});\r\n\r\nconst plainLabelClass = css({ color: theme.color.mutedForeground });\r\n\r\nexport interface ThinkingIndicatorProps extends HTMLAttributes<HTMLSpanElement> {\r\n  /** Text shown next to the dots. Pass `null` for dots only. */\r\n  label?: ReactNode;\r\n  /** Animate the label with a moving highlight. */\r\n  shimmerLabel?: boolean;\r\n}\r\n\r\n/** The \"model is working\" state: three bouncing dots with an optional shimmering label. */\r\nexport function ThinkingIndicator({\r\n  label = \"Thinking\",\r\n  shimmerLabel = true,\r\n  className,\r\n  ...props\r\n}: ThinkingIndicatorProps) {\r\n  return (\r\n    <span\r\n      role=\"status\"\r\n      aria-live=\"polite\"\r\n      className={className ? `${rootClass} ${className}` : rootClass}\r\n      {...props}\r\n    >\r\n      <span className={dotsClass} aria-hidden=\"true\">\r\n        <span className={dotClass} />\r\n        <span className={dotClass} style={{ animationDelay: \"0.15s\" }} />\r\n        <span className={dotClass} style={{ animationDelay: \"0.3s\" }} />\r\n      </span>\r\n      {label ? <span className={shimmerLabel ? labelClass : plainLabelClass}>{label}</span> : null}\r\n    </span>\r\n  );\r\n}\r\n",
      "type": "registry:component"
    }
  ]
}