{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "orbiting-circles",
  "type": "registry:component",
  "title": "Orbiting circles",
  "description": "Icons orbit a central hub on hairline rings for integration sections. Set radius, speed and direction per ring; icons stay upright while they travel.",
  "dependencies": [
    "lucide-react",
    "motion"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/premium/orbiting-circles.tsx",
      "type": "registry:ui",
      "target": "components/ui/orbiting-circles.tsx",
      "content": "\"use client\"\nimport * as React from \"react\"\nimport { useReducedMotion } from \"motion/react\"\nimport { BotIcon, CloudIcon, CreditCardIcon, DatabaseIcon, GitBranchIcon, MailIcon, MessageSquareIcon, WebhookIcon, ZapIcon, type LucideIcon } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\n\n/**\n * Icons orbiting a centre on hairline rings, for \"works with everything\"\n * integration sections. Each ring sets its own radius, speed and direction;\n * icons stay upright as they travel. Static for reduced motion.\n */\ntype Ring = { radius: number; duration: number; reverse?: boolean; icons: LucideIcon[] }\n\ntype OrbitingCirclesProps = {\n  rings?: Ring[]\n  center?: React.ReactNode\n  /** Box size in pixels. */\n  size?: number\n  className?: string\n}\n\nconst DEFAULT: Ring[] = [\n  { radius: 78, duration: 18, icons: [GitBranchIcon, MessageSquareIcon, MailIcon] },\n  { radius: 150, duration: 30, reverse: true, icons: [DatabaseIcon, CreditCardIcon, BotIcon, CloudIcon, WebhookIcon] },\n]\n\nfunction OrbitingCircles({ rings = DEFAULT, center, size = 340, className }: OrbitingCirclesProps) {\n  const reduce = useReducedMotion()\n  return (\n    <div data-slot=\"orbiting-circles\" className={cn(\"relative grid place-items-center\", className)} style={{ width: size, height: size }}>\n      {rings.map((r, ri) => (\n        <React.Fragment key={ri}>\n          <span aria-hidden className=\"absolute rounded-full border border-border\" style={{ width: r.radius * 2, height: r.radius * 2 }} />\n          {r.icons.map((Icon, i) => {\n            const start = (360 / r.icons.length) * i\n            const spin = reduce ? undefined : `orbit-${r.reverse ? \"rev\" : \"fwd\"} ${r.duration}s linear infinite`\n            return (\n              <span\n                key={i}\n                aria-hidden\n                className=\"absolute top-1/2 left-1/2 size-0\"\n                style={{ transform: `rotate(${start}deg)` }}\n              >\n                <span className=\"absolute size-0\" style={{ animation: spin }}>\n                  <span className=\"absolute\" style={{ transform: `translate(${r.radius}px, 0) rotate(${-start}deg)` }}>\n                    <span\n                      className=\"grid size-10 -translate-x-1/2 -translate-y-1/2 place-items-center rounded-xl border border-border bg-raised text-fg shadow-raised\"\n                      style={{ animation: spin ? `orbit-${r.reverse ? \"fwd\" : \"rev\"} ${r.duration}s linear infinite` : undefined }}\n                    >\n                      <Icon className=\"size-[18px]\" strokeWidth={1.75} />\n                    </span>\n                  </span>\n                </span>\n              </span>\n            )\n          })}\n        </React.Fragment>\n      ))}\n      <div className=\"relative grid size-16 place-items-center rounded-2xl bg-ink text-on-ink shadow-ink\">\n        {center ?? <ZapIcon className=\"size-6\" strokeWidth={1.75} />}\n      </div>\n      <style>{`@keyframes orbit-fwd{to{transform:rotate(360deg)}}@keyframes orbit-rev{to{transform:rotate(-360deg)}}`}</style>\n    </div>\n  )\n}\n\nexport { OrbitingCircles }\nexport type { OrbitingCirclesProps }\n"
    }
  ]
}
