{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "loaders-dna",
  "title": "DNA loaders",
  "description": "Styled loaders: the DNA set. 5 decorative loaders variations (HelixLoader, LadderLoader, TwistLoader, CoilLoader, WeaveLoader) 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-dna.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/* DNA loader family: 5 decorative indicators on a helix, braid and wave theme. Colour comes ONLY from tokens (currentColor / bg-current). Size = the box scale (aligned with the base spinner). DELIBERATE: the loader keeps moving under reduced-motion too. The delays and phases are index-derived and deterministic, 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/* Helix: iki dikey nokta serisi sinus fazinda kaymis, DNA sarmali. */\nexport function HelixLoader({ className, size = \"md\", label = \"Loading\", ...props }: Props) {\n  const dots = [0, 1, 2, 3, 4]\n  return (\n    <div\n      data-slot=\"styled-loader\"\n      role=\"status\"\n      aria-label={label}\n      className={cn(\"inline-flex items-center justify-between text-primary\", box[size], className)}\n      {...props}\n    >\n      {dots.map((i) => (\n        <span key={i} className=\"relative flex h-full w-1/6 items-center\">\n          <motion.span\n            className=\"absolute left-0 size-1 rounded-full bg-current\"\n            animate={{ y: [\"-140%\", \"140%\", \"-140%\"] }}\n            transition={{ duration: 1.4, ease: \"easeInOut\", repeat: Infinity, delay: i * 0.14 }}\n          />\n          <motion.span\n            className=\"absolute left-0 size-1 rounded-full bg-current/50\"\n            animate={{ y: [\"140%\", \"-140%\", \"140%\"] }}\n            transition={{ duration: 1.4, ease: \"easeInOut\", repeat: Infinity, delay: i * 0.14 }}\n          />\n        </span>\n      ))}\n    </div>\n  )\n}\n\n/* Ladder: yatay basamaklar sirayla yanar. */\nexport function LadderLoader({ className, size = \"md\", label = \"Loading\", ...props }: Props) {\n  const rungs = [0, 1, 2, 3, 4]\n  return (\n    <div\n      data-slot=\"styled-loader\"\n      role=\"status\"\n      aria-label={label}\n      className={cn(\"inline-flex flex-col items-stretch justify-between text-info\", box[size], className)}\n      {...props}\n    >\n      {rungs.map((i) => (\n        <motion.span\n          key={i}\n          className=\"block h-[12%] w-full rounded-full bg-current\"\n          animate={{ opacity: [0.25, 1, 0.25], scaleX: [0.7, 1, 0.7] }}\n          transition={{ duration: 1.1, ease: \"easeInOut\", repeat: Infinity, delay: i * 0.12 }}\n        />\n      ))}\n    </div>\n  )\n}\n\n/* Twist: donen kesikli halka (conic token). */\nexport function TwistLoader({ 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-brand\", box[size], className)}\n      {...props}\n    >\n      <motion.span\n        className=\"block size-full rounded-full border-2 border-dashed border-current\"\n        animate={{ rotate: 360 }}\n        transition={{ duration: 2.2, ease: \"linear\", repeat: Infinity }}\n      />\n    </div>\n  )\n}\n\n/* Coil: bir sira nokta gezen sinus dalgasinda zipla-in. */\nexport function CoilLoader({ className, size = \"md\", label = \"Loading\", ...props }: Props) {\n  const dots = [0, 1, 2, 3, 4, 5]\n  return (\n    <div\n      data-slot=\"styled-loader\"\n      role=\"status\"\n      aria-label={label}\n      className={cn(\"inline-flex items-center justify-between text-success\", box[size], className)}\n      {...props}\n    >\n      {dots.map((i) => (\n        <motion.span\n          key={i}\n          className=\"size-1 rounded-full bg-current\"\n          animate={{ y: [\"-120%\", \"120%\", \"-120%\"] }}\n          transition={{ duration: 1.2, ease: \"easeInOut\", repeat: Infinity, delay: i * 0.1 }}\n        />\n      ))}\n    </div>\n  )\n}\n\n/* Weave: two rows of dots cross over each other (a weave). */\nexport function WeaveLoader({ className, size = \"md\", label = \"Loading\", ...props }: Props) {\n  const reduce = useReducedMotion()\n  const dots = [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-flex items-center justify-between text-warning\", box[size], className)}\n      {...props}\n    >\n      {dots.map((i) => (\n        <span key={i} className=\"relative flex h-full w-1/5 items-center justify-center\">\n          <motion.span\n            className=\"absolute size-1 rounded-full bg-current\"\n            animate={{ y: reduce ? [\"-90%\", \"90%\", \"-90%\"] : [\"-90%\", \"90%\", \"-90%\"] }}\n            transition={{ duration: 1, ease: \"easeInOut\", repeat: Infinity, delay: i * 0.16 }}\n          />\n          <motion.span\n            className=\"absolute size-1 rounded-full bg-current/50\"\n            animate={{ y: [\"90%\", \"-90%\", \"90%\"] }}\n            transition={{ duration: 1, ease: \"easeInOut\", repeat: Infinity, delay: i * 0.16 }}\n          />\n        </span>\n      ))}\n    </div>\n  )\n}\n",
      "type": "registry:component",
      "target": "components/ui/loaders-dna.tsx"
    }
  ],
  "categories": [
    "styled",
    "loaders"
  ],
  "type": "registry:component"
}