{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "spiral-loader",
  "type": "registry:ui",
  "dependencies": [
    "clsx",
    "lottie-react",
    "next-themes",
    "tailwind-merge"
  ],
  "registryDependencies": [],
  "files": [
    {
      "path": "registry/agent-elements/components/spiral-loader.tsx",
      "content": "\"use client\";\n\nimport dynamic from \"next/dynamic\";\nimport type { ComponentType } from \"react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport type { LottieRefCurrentProps } from \"lottie-react\";\nimport { cn } from \"./utils/cn\";\nimport { spiralFastData, spiralSlowData } from \"./spiral-loader-data\";\nimport { useTheme } from \"next-themes\";\n\nconst Lottie = dynamic(() => import(\"lottie-react\"), {\n  ssr: false,\n}) as ComponentType<any>;\n\nconst FAST_REPEATS = 4;\nconst SLOW_REPEATS = 2;\n\nexport type SpiralLoaderProps = {\n  size?: number;\n  className?: string;\n};\n\nexport function SpiralLoader({ size = 16, className }: SpiralLoaderProps) {\n  const [isMounted, setIsMounted] = useState(false);\n  const [phase, setPhase] = useState<\"fast\" | \"slow\">(\"fast\");\n  const repeatCountRef = useRef(0);\n  const fastRef = useRef<LottieRefCurrentProps | null>(null);\n  const slowRef = useRef<LottieRefCurrentProps | null>(null);\n  const { resolvedTheme } = useTheme();\n\n  useEffect(() => {\n    setIsMounted(true);\n  }, []);\n\n  const startFastPhase = useCallback(() => {\n    repeatCountRef.current = 0;\n    setPhase(\"fast\");\n    slowRef.current?.stop();\n    fastRef.current?.goToAndPlay(0, true);\n  }, []);\n\n  const startSlowPhase = useCallback(() => {\n    repeatCountRef.current = 0;\n    setPhase(\"slow\");\n    fastRef.current?.stop();\n    slowRef.current?.goToAndPlay(0, true);\n  }, []);\n\n  const handleFastComplete = useCallback(() => {\n    repeatCountRef.current += 1;\n    if (repeatCountRef.current < FAST_REPEATS) {\n      fastRef.current?.goToAndPlay(0, true);\n    } else {\n      startSlowPhase();\n    }\n  }, [startSlowPhase]);\n\n  const handleSlowComplete = useCallback(() => {\n    repeatCountRef.current += 1;\n    if (repeatCountRef.current < SLOW_REPEATS) {\n      slowRef.current?.goToAndPlay(0, true);\n    } else {\n      startFastPhase();\n    }\n  }, [startFastPhase]);\n\n  if (!isMounted) return null;\n  const needsInvert = resolvedTheme !== \"dark\";\n\n  return (\n    <div\n      className={cn(\"relative shrink-0\", className)}\n      style={{ width: size, height: size }}\n    >\n      <div\n        className={cn(\n          \"absolute inset-0 transition-opacity duration-75\",\n          needsInvert && \"invert\",\n          phase === \"fast\" ? \"opacity-100\" : \"opacity-0\",\n        )}\n      >\n        <Lottie\n          lottieRef={fastRef}\n          animationData={spiralFastData}\n          loop={false}\n          autoplay={true}\n          onComplete={handleFastComplete}\n          style={{ width: \"100%\", height: \"100%\" }}\n        />\n      </div>\n      <div\n        className={cn(\n          \"absolute inset-0 transition-opacity duration-75\",\n          needsInvert && \"invert\",\n          phase === \"slow\" ? \"opacity-100\" : \"opacity-0\",\n        )}\n      >\n        <Lottie\n          lottieRef={slowRef}\n          animationData={spiralSlowData}\n          loop={false}\n          autoplay={false}\n          onComplete={handleSlowComplete}\n          style={{ width: \"100%\", height: \"100%\" }}\n        />\n      </div>\n    </div>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/agent-elements/spiral-loader.tsx"
    },
    {
      "path": "registry/agent-elements/utils/cn.ts",
      "content": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs));\n}\n",
      "type": "registry:lib",
      "target": "components/agent-elements/utils/cn.ts"
    },
    {
      "path": "registry/agent-elements/components/spiral-loader-data.ts",
      "content": "export const spiralFastData = {\"nm\":\"spiral2\",\"h\":16,\"w\":16,\"meta\":{\"g\":\"@lottiefiles/toolkit-js 0.71.7\"},\"layers\":[{\"ty\":4,\"nm\":\"Vector 5821 copy Outlines\",\"sr\":1,\"st\":0,\"op\":30,\"ip\":0,\"ln\":\"18\",\"hasMask\":false,\"ao\":0,\"ks\":{\"a\":{\"a\":0,\"k\":[12.5,6.5,0]},\"s\":{\"a\":0,\"k\":[100,100,100]},\"p\":{\"a\":1,\"k\":[{\"o\":{\"x\":0.167,\"y\":0.167},\"i\":{\"x\":0.833,\"y\":0.833},\"s\":[12,8,0],\"t\":0},{\"s\":[4,8,0],\"t\":29}]},\"r\":{\"a\":0,\"k\":0},\"sa\":{\"a\":0,\"k\":0},\"o\":{\"a\":0,\"k\":24}},\"shapes\":[{\"ty\":\"gr\",\"nm\":\"Group 1\",\"it\":[{\"ty\":\"sh\",\"nm\":\"Path 1\",\"d\":1,\"ks\":{\"a\":0,\"k\":{\"c\":false,\"i\":[[0,0],[-0.289,3.296],[2.218,0],[-0.23,-2.627],[-4.452,0],[-0.289,3.296],[2.218,0],[-0.23,-2.627],[-4.452,0],[-0.289,3.296],[2.218,0],[-0.232,-2.627],[-4.443,0]],\"o\":[[4.452,0],[0.23,-2.627],[-2.218,0],[0.289,3.296],[4.452,0],[0.23,-2.627],[-2.218,0],[0.289,3.296],[4.452,0],[0.23,-2.627],[-2.218,0],[0.292,3.296],[0,0]],\"v\":[[-12,6],[-4.975,-1.012],[-8,-6],[-11.025,-1.012],[-4,6],[3.025,-1.012],[0,-6],[-3.025,-1.012],[4,6],[11.025,-1.012],[8,-6],[4.98,-1.012],[12,6]]}}},{\"ty\":\"st\",\"nm\":\"Stroke 1\",\"lc\":2,\"lj\":2,\"ml\":4,\"o\":{\"a\":0,\"k\":100},\"w\":{\"a\":0,\"k\":1.4},\"c\":{\"a\":0,\"k\":[1,1,1]}},{\"ty\":\"tr\",\"a\":{\"a\":0,\"k\":[0,0]},\"s\":{\"a\":0,\"k\":[100,100]},\"p\":{\"a\":0,\"k\":[12.5,6.5]},\"r\":{\"a\":0,\"k\":0},\"sa\":{\"a\":0,\"k\":0},\"o\":{\"a\":0,\"k\":100}}]},{\"ty\":\"tm\",\"nm\":\"Trim Paths 1\",\"e\":{\"a\":1,\"k\":[{\"o\":{\"x\":0.341,\"y\":0.488},\"i\":{\"x\":0.269,\"y\":0.75},\"s\":[44],\"t\":0},{\"s\":[77],\"t\":29}]},\"o\":{\"a\":0,\"k\":0},\"s\":{\"a\":1,\"k\":[{\"o\":{\"x\":0.32,\"y\":0.154},\"i\":{\"x\":0.826,\"y\":0.579},\"s\":[23],\"t\":0},{\"s\":[57],\"t\":29}]},\"m\":1}],\"ind\":1}],\"v\":\"5.7.0\",\"fr\":60,\"op\":30,\"ip\":0,\"assets\":[]};\n\nexport const spiralSlowData = {\"nm\":\"spiral1\",\"h\":16,\"w\":16,\"meta\":{\"g\":\"@lottiefiles/toolkit-js 0.71.7\"},\"layers\":[{\"ty\":4,\"nm\":\"Vector 5821 copy Outlines\",\"sr\":1,\"st\":0,\"op\":60,\"ip\":0,\"ln\":\"18\",\"hasMask\":false,\"ao\":0,\"ks\":{\"a\":{\"a\":0,\"k\":[12.5,6.5,0]},\"s\":{\"a\":0,\"k\":[100,100,100]},\"p\":{\"a\":1,\"k\":[{\"o\":{\"x\":0.167,\"y\":0.167},\"i\":{\"x\":0.833,\"y\":0.833},\"s\":[12,8,0],\"t\":0},{\"s\":[4,8,0],\"t\":59}]},\"r\":{\"a\":0,\"k\":0},\"sa\":{\"a\":0,\"k\":0},\"o\":{\"a\":0,\"k\":24}},\"shapes\":[{\"ty\":\"gr\",\"nm\":\"Group 1\",\"it\":[{\"ty\":\"sh\",\"nm\":\"Path 1\",\"d\":1,\"ks\":{\"a\":0,\"k\":{\"c\":false,\"i\":[[0,0],[-0.289,3.296],[2.218,0],[-0.23,-2.627],[-4.452,0],[-0.289,3.296],[2.218,0],[-0.23,-2.627],[-4.452,0],[-0.289,3.296],[2.218,0],[-0.232,-2.627],[-4.443,0]],\"o\":[[4.452,0],[0.23,-2.627],[-2.218,0],[0.289,3.296],[4.452,0],[0.23,-2.627],[-2.218,0],[0.289,3.296],[4.452,0],[0.23,-2.627],[-2.218,0],[0.292,3.296],[0,0]],\"v\":[[-12,6],[-4.975,-1.012],[-8,-6],[-11.025,-1.012],[-4,6],[3.025,-1.012],[0,-6],[-3.025,-1.012],[4,6],[11.025,-1.012],[8,-6],[4.98,-1.012],[12,6]]}}},{\"ty\":\"st\",\"nm\":\"Stroke 1\",\"lc\":2,\"lj\":2,\"ml\":4,\"o\":{\"a\":0,\"k\":100},\"w\":{\"a\":0,\"k\":1.4},\"c\":{\"a\":0,\"k\":[1,1,1]}},{\"ty\":\"tr\",\"a\":{\"a\":0,\"k\":[0,0]},\"s\":{\"a\":0,\"k\":[100,100]},\"p\":{\"a\":0,\"k\":[12.5,6.5]},\"r\":{\"a\":0,\"k\":0},\"sa\":{\"a\":0,\"k\":0},\"o\":{\"a\":0,\"k\":100}}]},{\"ty\":\"tm\",\"nm\":\"Trim Paths 1\",\"e\":{\"a\":1,\"k\":[{\"o\":{\"x\":0.341,\"y\":0.992},\"i\":{\"x\":0.269,\"y\":0.491},\"s\":[44],\"t\":0},{\"s\":[77],\"t\":59}]},\"o\":{\"a\":0,\"k\":0},\"s\":{\"a\":1,\"k\":[{\"o\":{\"x\":0.32,\"y\":0.313},\"i\":{\"x\":0.826,\"y\":0.143},\"s\":[23],\"t\":0},{\"s\":[57],\"t\":59}]},\"m\":1}],\"ind\":1}],\"v\":\"5.7.0\",\"fr\":60,\"op\":60,\"ip\":0,\"assets\":[]};\n",
      "type": "registry:lib",
      "target": "components/agent-elements/spiral-loader-data.ts"
    },
    {
      "path": "registry/agent-elements/agent-ui.css",
      "content": "/* Agent Elements tokens + utilities */\n\n/*\n * AN Agent Chat - CSS Custom Properties\n * These are the default values. Override by redefining these vars in your app CSS.\n */\n:root {\n  /* Geometry — all radii derive from --an-border-radius */\n  --an-border-radius: 16px;\n  --an-message-border-radius: var(--an-border-radius);\n  --an-input-border-radius: var(--an-border-radius);\n  --an-tool-border-radius: 10px;\n  --an-message-radius-inner-offset: 4px;\n  --an-max-width: 420px;\n\n  /* Colors - Light mode defaults */\n  --an-background: #ffffff;\n  --an-background-secondary: #f0f0f0;\n  --an-background-tertiary: #f8f8f8;\n  --an-foreground: #1a1a1a;\n  --an-foreground-muted: #737373;\n  --an-foreground-subtle: #a3a3a3;\n  --an-border-color: #e4e4e7;\n  --an-primary-color: #3b82f6;\n\n  /* User Messages */\n  --an-user-message-bg: #f5f5f5;\n  --an-user-message-text: #1a1a1a;\n\n  /* Input */\n  --an-input-background: #ffffff;\n  --an-input-border-color: #e4e4e7;\n  --an-input-color: #1a1a1a;\n  --an-input-placeholder-color: #a3a3a3;\n  --an-input-focus-outline: transparent;\n  --an-context-padding: 10px;\n\n  /* Send/Stop Buttons */\n  --an-send-button-bg: #3b82f6;\n  --an-send-button-color: #ffffff;\n\n  /* Tools */\n  --an-tool-background: #f5f5f5;\n  --an-tool-border-color: #e4e4e7;\n  --an-tool-color: #1a1a1a;\n  --an-tool-color-muted: #737373;\n\n  /* Code */\n  --an-code-background: #1e1e1e;\n  --an-code-color: #d4d4d4;\n\n  /* Diff colors */\n  --an-diff-added-bg: rgba(34, 197, 94, 0.1);\n  --an-diff-added-border: rgba(34, 197, 94, 0.5);\n  --an-diff-added-text: #15803d;\n  --an-diff-removed-bg: rgba(239, 68, 68, 0.1);\n  --an-diff-removed-border: rgba(239, 68, 68, 0.5);\n  --an-diff-removed-text: #dc2626;\n}\n\n/* Dark mode defaults */\n.dark {\n  --an-background: #0a0a0a;\n  --an-background-secondary: #242424;\n  --an-background-tertiary: #141414;\n  --an-foreground: #fafafa;\n  --an-foreground-muted: #8c8c8c;\n  --an-foreground-subtle: #71717a;\n  --an-border-color: #2a2a2a;\n  --an-primary-color: #60a5fa;\n\n  --an-user-message-bg: #1a1a1a;\n  --an-user-message-text: #fafafa;\n\n  --an-input-background: #0a0a0a;\n  --an-input-border-color: #2a2a2a;\n  --an-input-color: #fafafa;\n  --an-input-placeholder-color: #71717a;\n  --an-input-focus-outline: transparent;\n  --an-context-padding: 12px;\n\n  --an-send-button-bg: #60a5fa;\n  /* Dark mode uses a lighter primary (#60a5fa) — pair it with black text so\n     labels like \"Approve\" / send-arrow have proper contrast instead of\n     low-contrast white-on-light-blue. */\n  --an-send-button-color: #0a0a0a;\n\n  --an-tool-background: #141414;\n  --an-tool-border-color: #2a2a2a;\n  --an-tool-color: #fafafa;\n  --an-tool-color-muted: #8c8c8c;\n\n  --an-code-background: #0a0a0a;\n  --an-code-color: #d4d4d4;\n\n  --an-diff-added-bg: rgba(34, 197, 94, 0.15);\n  --an-diff-added-border: rgba(34, 197, 94, 0.4);\n  --an-diff-added-text: #4ade80;\n  --an-diff-removed-bg: rgba(239, 68, 68, 0.15);\n  --an-diff-removed-border: rgba(239, 68, 68, 0.4);\n  --an-diff-removed-text: #f87171;\n}\n\n@theme inline {\n  --color-an-background: var(--an-background);\n  --color-an-background-secondary: var(--an-background-secondary);\n  --color-an-background-tertiary: var(--an-background-tertiary);\n  --color-an-foreground: var(--an-foreground);\n  --color-an-foreground-muted: var(--an-foreground-muted);\n  --color-an-foreground-subtle: var(--an-foreground-subtle);\n  --color-an-border-color: var(--an-border-color);\n  --color-an-primary-color: var(--an-primary-color);\n  --color-an-user-message-bg: var(--an-user-message-bg);\n  --color-an-user-message-text: var(--an-user-message-text);\n  --color-an-input-background: var(--an-input-background);\n  --color-an-input-border-color: var(--an-input-border-color);\n  --color-an-input-color: var(--an-input-color);\n  --color-an-input-placeholder-color: var(--an-input-placeholder-color);\n  --color-an-input-focus-outline: var(--an-input-focus-outline);\n  --color-an-send-button-bg: var(--an-send-button-bg);\n  --color-an-send-button-color: var(--an-send-button-color);\n  --color-an-tool-background: var(--an-tool-background);\n  --color-an-tool-border-color: var(--an-tool-border-color);\n  --color-an-tool-color: var(--an-tool-color);\n  --color-an-tool-color-muted: var(--an-tool-color-muted);\n  --color-an-code-background: var(--an-code-background);\n  --color-an-code-color: var(--an-code-color);\n  --color-an-diff-added-bg: var(--an-diff-added-bg);\n  --color-an-diff-added-border: var(--an-diff-added-border);\n  --color-an-diff-added-text: var(--an-diff-added-text);\n  --color-an-diff-removed-bg: var(--an-diff-removed-bg);\n  --color-an-diff-removed-border: var(--an-diff-removed-border);\n  --color-an-diff-removed-text: var(--an-diff-removed-text);\n  --radius-an-message: var(--an-message-border-radius);\n  --radius-an-message-inner: calc(\n    var(--an-message-border-radius) - var(--an-message-radius-inner-offset)\n  );\n  --radius-an-input-border-radius: var(--an-input-border-radius);\n  --radius-an-tool-border-radius: var(--an-tool-border-radius);\n  --spacing-an-context-padding: var(--an-context-padding);\n  --max-width-an: var(--an-max-width);\n  --spacing-an-user-message-x: 14px;\n  --spacing-an-user-message-y: 10px;\n}\n\n/* TextShimmer animation */\n@keyframes an-shimmer {\n  from {\n    background-position: 100% center;\n  }\n  to {\n    background-position: 0% center;\n  }\n}\n\n@keyframes an-blink {\n  50% {\n    opacity: 0;\n  }\n}\n\n@keyframes loading-dots {\n  0%,\n  100% {\n    opacity: 0;\n  }\n  50% {\n    opacity: 1;\n  }\n}\n\n@keyframes an-ellipsis {\n  0% {\n    width: 0;\n  }\n  33% {\n    width: 0.33em;\n  }\n  66% {\n    width: 0.66em;\n  }\n  100% {\n    width: 1em;\n  }\n}\n\n.an-text-shimmer {\n  display: inline-block;\n  background-size: 250% 100%;\n  background-clip: text;\n  -webkit-background-clip: text;\n  color: transparent;\n  background-image: linear-gradient(\n    90deg,\n    var(--an-foreground-subtle, #a3a3a3) 0%,\n    var(--an-foreground-subtle, #a3a3a3) 40%,\n    var(--an-foreground-muted, #737373) 50%,\n    var(--an-foreground-subtle, #a3a3a3) 60%,\n    var(--an-foreground-subtle, #a3a3a3) 100%\n  );\n  background-repeat: no-repeat;\n}\n\n.an-text-shimmer--active {\n  animation: an-shimmer var(--an-shimmer-duration, 2s) linear infinite;\n}\n\n.an-ellipsis {\n  display: inline-block;\n  overflow: hidden;\n  width: 0;\n  vertical-align: bottom;\n  animation: an-ellipsis 1.2s steps(1, end) infinite;\n}\n\n.an-markdown pre code {\n  counter-reset: none !important;\n}\n\n.an-markdown pre code > span::before {\n  content: none !important;\n  display: none !important;\n}\n\n.an-markdown pre code > span {\n  padding-left: 0 !important;\n}\n\n/* Diff */\n.an-edit-diff,\n.an-edit-diff pre,\n.an-edit-diff code {\n  font-size: 12px;\n}\n\n.dark .an-edit-tool-card {\n  background-color: #000;\n}\n\n[data-theme=\"dark\"] .an-edit-tool-card {\n  background-color: #000;\n}\n\n.dark .an-edit-tool-card .an-edit-diff,\n.dark .an-edit-tool-card .an-edit-diff pre,\n.dark .an-edit-tool-card .an-edit-diff code {\n  background-color: #000 !important;\n}\n\n[data-theme=\"dark\"] .an-edit-tool-card .an-edit-diff,\n[data-theme=\"dark\"] .an-edit-tool-card .an-edit-diff pre,\n[data-theme=\"dark\"] .an-edit-tool-card .an-edit-diff code {\n  background-color: #000 !important;\n}\n\n/* Markdown Code Block */\n.an-markdown [data-streamdown=\"code-block\"] {\n  padding: 0;\n  border: 1px solid var(--an-border-color);\n  border-radius: var(--an-tool-border-radius);\n  background: transparent;\n  gap: 0;\n}\n\n.an-markdown [data-streamdown=\"code-block-header\"] {\n  padding: 0px 10px 0px 8px;\n  height: auto;\n  font-size: 12px;\n  height: 28px;\n  background: transparent;\n  border-bottom: 1px solid var(--color-an-tool-border-color);\n  background-color: var(--an-tool-background);\n  position: relative;\n}\n\n.an-markdown div:has(> [data-streamdown=\"code-block-actions\"]) {\n  position: absolute;\n  height: auto;\n  margin: 0;\n  top: 0;\n  right: 0;\n  height: 28px;\n  padding-right: 8px;\n}\n\n.an-markdown [data-streamdown=\"code-block-actions\"] {\n  background: transparent;\n  border: none;\n  backdrop-filter: none;\n  padding: 0;\n}\n\n.an-markdown [data-streamdown=\"code-block-actions\"] button > svg {\n  width: 14px;\n  height: 14px;\n}\n\n.an-markdown [data-streamdown=\"code-block-body\"] {\n  margin: 0;\n  padding-top: 8px;\n  padding-bottom: 8px;\n  background: transparent;\n  border: transparent;\n  overflow-x: auto;\n}\n\n.an-markdown [data-streamdown=\"code-block\"] pre,\n.an-markdown [data-streamdown=\"code-block\"] code {\n  font-size: 12px;\n  background: transparent;\n}\n",
      "type": "registry:style",
      "target": "components/agent-elements/agent-ui.css"
    }
  ],
  "css": {
    "@import \"../components/agent-elements/agent-ui.css\"": ""
  }
}