{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "loaders-styled",
  "title": "Loaders essentials",
  "description": "Styled loaders: the essentials set. 5 decorative loaders variations (DotsLoader, BarsLoader, RingLoader, PulseLoader, OrbitLoader) 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-styled.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/* Loader family: 5 decorative loading indicators. Colour comes ONLY from tokens (currentColor / bg-primary). Size = the box scale (aligned with the base spinner). DELIBERATE: a loader's rotation is INFORMATION; like the base Spinner exception it keeps turning under reduced-motion too (a stopped loader reads as \"hung\"). Only a slowdown may be applied. */\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/* Dots: uc nokta sirayla zipla-sön. */\nexport function DotsLoader({ 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(\"inline-flex items-center gap-1 text-primary\", box[size], className)}\n      {...props}\n    >\n      {[0, 1, 2].map((i) => (\n        <motion.span\n          key={i}\n          className=\"inline-block size-1/4 rounded-full bg-current\"\n          animate={{ y: [0, -3, 0], opacity: [0.4, 1, 0.4] }}\n          transition={{ duration: 0.7, ease: \"easeInOut\", repeat: Infinity, delay: reduce ? 0 : i * 0.15 }}\n        />\n      ))}\n    </div>\n  )\n}\n\n/* Bars: ses cubugu gibi yukselip alcalan cubuklar. */\nexport function BarsLoader({ 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(\"inline-flex items-end justify-center gap-0.5 text-primary\", box[size], className)}\n      {...props}\n    >\n      {[0, 1, 2, 3].map((i) => (\n        <motion.span\n          key={i}\n          className=\"inline-block w-1/5 rounded-sm bg-current\"\n          animate={{ height: [\"30%\", \"100%\", \"30%\"] }}\n          transition={{ duration: 0.8, ease: \"easeInOut\", repeat: Infinity, delay: i * 0.12 }}\n        />\n      ))}\n    </div>\n  )\n}\n\n/* Ring: token halka surekli doner (klasik). */\nexport function RingLoader({ 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(\"inline-block text-primary\", box[size], className)}\n      {...props}\n    >\n      <motion.span\n        className=\"block size-full rounded-full border-2 border-current/25 border-t-current\"\n        animate={{ rotate: 360 }}\n        transition={{ duration: 0.8, ease: \"linear\", repeat: Infinity }}\n      />\n    </div>\n  )\n}\n\n/* Pulse: dolu token daire nabiz gibi buyuyup soner. */\nexport function PulseLoader({ 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      <motion.span\n        className=\"absolute inset-0 rounded-full bg-current\"\n        animate={{ scale: [0.4, 1], opacity: [0.7, 0] }}\n        transition={{ duration: 1, ease: \"easeOut\", repeat: Infinity }}\n      />\n      <span className=\"absolute inset-[35%] rounded-full bg-current\" />\n    </div>\n  )\n}\n\n/* Orbit: bir nokta token yorunge boyunca doner. */\nexport function OrbitLoader({ 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-[42%] rounded-full bg-current/40\" />\n      <motion.span\n        className=\"absolute inset-0\"\n        animate={{ rotate: 360 }}\n        transition={{ duration: 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      </motion.span>\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/loaders-styled.tsx"
    }
  ],
  "categories": [
    "styled",
    "loaders"
  ],
  "type": "registry:component"
}