{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "typing-indicator",
  "title": "UI Typing Indicator",
  "description": "A continuous typing animation: N dots bounce with a staggered sine wave. A motion atom — it reads the frame and takes color, size, gap, and speed props, defaulting to currentColor so it inherits the bubble it sits in.",
  "dependencies": ["remotion"],
  "registryDependencies": ["@remocn/remocn-ui"],
  "files": [
    {
      "path": "registry/remocn-ui/typing-indicator/index.tsx",
      "content": "\"use client\";\n\nimport { useCurrentFrame, useVideoConfig } from \"remotion\";\n\nexport interface TypingIndicatorProps {\n  dotCount?: number;\n  color?: string;\n  size?: number;\n  gap?: number;\n  amplitude?: number;\n  speed?: number;\n  cyclesPerSecond?: number;\n  className?: string;\n}\n\nexport interface TypingDotOptions {\n  fps: number;\n  dotCount: number;\n  amplitude: number;\n  speed: number;\n  cyclesPerSecond: number;\n}\n\nexport function typingDotOffset(\n  frame: number,\n  index: number,\n  opts: TypingDotOptions,\n): { translateY: number; opacity: number } {\n  const cps = opts.cyclesPerSecond <= 0 ? 1 : opts.cyclesPerSecond;\n  const periodFrames = opts.fps / cps;\n  const stagger = opts.dotCount > 0 ? periodFrames / (opts.dotCount * 2) : 0;\n  const phase =\n    ((frame * opts.speed - index * stagger) / periodFrames) * Math.PI * 2;\n  const wave = (Math.sin(phase) + 1) / 2;\n  return {\n    translateY: -opts.amplitude * wave,\n    opacity: 0.45 + 0.55 * wave,\n  };\n}\n\nexport function TypingIndicator({\n  dotCount = 3,\n  color = \"currentColor\",\n  size = 8,\n  gap = 5,\n  amplitude = 5,\n  speed = 1,\n  cyclesPerSecond = 1.1,\n  className,\n}: TypingIndicatorProps) {\n  const frame = useCurrentFrame();\n  const { fps } = useVideoConfig();\n  const opts: TypingDotOptions = {\n    fps,\n    dotCount,\n    amplitude,\n    speed,\n    cyclesPerSecond,\n  };\n\n  return (\n    <div\n      className={className}\n      style={{\n        display: \"inline-flex\",\n        alignItems: \"center\",\n        gap,\n        height: size + amplitude * 2,\n      }}\n    >\n      {Array.from({ length: dotCount }, (_, i) => {\n        const { translateY, opacity } = typingDotOffset(frame, i, opts);\n        return (\n          <span\n            key={i}\n            style={{\n              display: \"inline-block\",\n              width: size,\n              height: size,\n              borderRadius: \"50%\",\n              background: color,\n              opacity,\n              transform: `translateY(${translateY}px)`,\n            }}\n          />\n        );\n      })}\n    </div>\n  );\n}\n",
      "type": "registry:component",
      "target": "components/remocn/typing-indicator.tsx"
    }
  ],
  "type": "registry:component"
}
