{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "loaders-orbital",
  "title": "Orbital loaders",
  "description": "Styled loaders: the Orbital set. 5 decorative loaders variations (SolarLoader, BinaryLoader, CometLoader, SatelliteLoader, GyroLoader) on the ai2 token system, powered by framer-motion, reduced-motion aware and sized sm to xl. Part of the free styled layer.",
  "dependencies": [
    "motion@^12.42.2"
  ],
  "registryDependencies": [
    "@ai2/tokens"
  ],
  "files": [
    {
      "path": "registry/ai2/styled/loaders-orbital.tsx",
      "content": "\"use client\"\n\nimport type * as React from \"react\"\nimport { motion, useReducedMotion } from \"motion/react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/* Orbital loader family: 5 decorative indicators on an orbit and rotation theme. Colour comes ONLY from tokens (currentColor / bg-current). Size = the box scale (aligned with the base spinner). DELIBERATE: a loader's rotation is INFORMATION; it keeps turning under reduced-motion too (a stopped loader reads as \"hung\"). The delays and angles are fixed and index-derived, nothing random. */\n\nexport type StyledSize = \"sm\" | \"md\" | \"lg\" | \"xl\"\n\nconst box: Record<StyledSize, string> = {\n  sm: \"size-4\",\n  md: \"size-5\",\n  lg: \"size-6\",\n  xl: \"size-8\",\n}\n\ntype Props = React.ComponentProps<\"div\"> & { size?: StyledSize; label?: string }\n\n/* Solar: a dot orbits around a central core. */\nexport function SolarLoader({ className, size = \"md\", label = \"Loading\", ...props }: Props) {\n  return (\n    <div\n      data-slot=\"styled-loader\"\n      role=\"status\"\n      aria-label={label}\n      className={cn(\"relative inline-block text-primary\", box[size], className)}\n      {...props}\n    >\n      <span className=\"absolute inset-[35%] rounded-full bg-current\" />\n      <motion.span\n        className=\"absolute inset-0\"\n        animate={{ rotate: 360 }}\n        transition={{ duration: 1.4, ease: \"linear\", repeat: Infinity }}\n      >\n        <span className=\"absolute left-1/2 top-0 size-1/5 -translate-x-1/2 rounded-full bg-current\" />\n      </motion.span>\n    </div>\n  )\n}\n\n/* Binary: iki nokta ortak merkez etrafinda 180 derece karsilikli doner. */\nexport function BinaryLoader({ className, size = \"md\", label = \"Loading\", ...props }: Props) {\n  return (\n    <div\n      data-slot=\"styled-loader\"\n      role=\"status\"\n      aria-label={label}\n      className={cn(\"relative inline-block text-info\", box[size], className)}\n      {...props}\n    >\n      <motion.span\n        className=\"absolute inset-0\"\n        animate={{ rotate: 360 }}\n        transition={{ duration: 1.1, ease: \"linear\", repeat: Infinity }}\n      >\n        <span className=\"absolute left-1/2 top-0 size-1/4 -translate-x-1/2 rounded-full bg-current\" />\n        <span className=\"absolute bottom-0 left-1/2 size-1/5 -translate-x-1/2 rounded-full bg-current/60\" />\n      </motion.span>\n    </div>\n  )\n}\n\n/* Comet: yorunge yapan nokta + sonuk kuculen kuyruk noktalari. */\nexport function CometLoader({ className, size = \"md\", label = \"Loading\", ...props }: Props) {\n  const tail = [0, 1, 2, 3]\n  return (\n    <div\n      data-slot=\"styled-loader\"\n      role=\"status\"\n      aria-label={label}\n      className={cn(\"relative inline-block text-brand\", box[size], className)}\n      {...props}\n    >\n      {tail.map((i) => (\n        <motion.span\n          key={i}\n          className=\"absolute inset-0\"\n          animate={{ rotate: 360 }}\n          transition={{ duration: 1.2, ease: \"linear\", repeat: Infinity, delay: i * -0.08 }}\n        >\n          <span\n            className=\"absolute left-1/2 top-0 -translate-x-1/2 rounded-full bg-current\"\n            style={{\n              width: `${28 - i * 5}%`,\n              height: `${28 - i * 5}%`,\n              opacity: 1 - i * 0.22,\n            }}\n          />\n        </motion.span>\n      ))}\n    </div>\n  )\n}\n\n/* Satellite: ic halka bir yone, dis nokta ters yone doner. */\nexport function SatelliteLoader({ className, size = \"md\", label = \"Loading\", ...props }: Props) {\n  return (\n    <div\n      data-slot=\"styled-loader\"\n      role=\"status\"\n      aria-label={label}\n      className={cn(\"relative inline-block text-success\", box[size], className)}\n      {...props}\n    >\n      <motion.span\n        className=\"absolute inset-[28%] rounded-full border-2 border-current/25 border-t-current\"\n        animate={{ rotate: 360 }}\n        transition={{ duration: 1, ease: \"linear\", repeat: Infinity }}\n      />\n      <motion.span\n        className=\"absolute inset-0\"\n        animate={{ rotate: -360 }}\n        transition={{ duration: 1.6, ease: \"linear\", repeat: Infinity }}\n      >\n        <span className=\"absolute left-1/2 top-0 size-1/5 -translate-x-1/2 rounded-full bg-current\" />\n      </motion.span>\n    </div>\n  )\n}\n\n/* Gyro: 3 nested rings rotate at different speeds/axes. */\nexport function GyroLoader({ className, size = \"md\", label = \"Loading\", ...props }: Props) {\n  const reduce = useReducedMotion()\n  return (\n    <div\n      data-slot=\"styled-loader\"\n      role=\"status\"\n      aria-label={label}\n      className={cn(\"relative inline-block text-primary\", box[size], className)}\n      {...props}\n    >\n      <motion.span\n        className=\"absolute inset-0 rounded-full border-2 border-transparent border-t-current\"\n        animate={{ rotate: 360 }}\n        transition={{ duration: 1.3, ease: \"linear\", repeat: Infinity }}\n      />\n      <motion.span\n        className=\"absolute inset-[22%] rounded-full border-2 border-transparent border-b-current/70\"\n        animate={{ rotate: reduce ? 360 : -360 }}\n        transition={{ duration: 1, ease: \"linear\", repeat: Infinity }}\n      />\n      <motion.span\n        className=\"absolute inset-[44%] rounded-full border-2 border-transparent border-l-current/50\"\n        animate={{ rotate: 360 }}\n        transition={{ duration: 0.8, ease: \"linear\", repeat: Infinity }}\n      />\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/loaders-orbital.tsx"
    }
  ],
  "categories": [
    "styled",
    "loaders"
  ],
  "type": "registry:component"
}