{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "primitive-keyframes",
  "type": "registry:ui",
  "title": "Keyframes",
  "description": "Compose multi-stage keyframes, interpolation, stepped motion, and fill behavior.",
  "dependencies": [
    "motion"
  ],
  "categories": [
    "primitive",
    "sequencing"
  ],
  "docs": "https://motion-lexicon.pages.dev/en/primitives/keyframes/",
  "files": [
    {
      "path": "src/registry/primitives/keyframes.tsx",
      "type": "registry:ui",
      "target": "components/motion-lexicon/primitives/keyframes.tsx",
      "content": "\"use client\";\n\nimport { motion, useReducedMotion, type Transition } from \"motion/react\";\nimport type { ReactNode } from \"react\";\n\nconst EASE_IN_OUT = [0.77, 0, 0.175, 1] as const;\n\nexport type KeyframeMode = \"keyframes\" | \"tween\" | \"steps\";\nexport type KeyframeFill = \"none\" | \"forwards\" | \"both\";\n\nexport type KeyframesPrimitiveProps = {\n  children: ReactNode;\n  mode?: KeyframeMode;\n  steps?: number;\n  fill?: KeyframeFill;\n  duration?: number;\n  easing?: Transition[\"ease\"];\n  distance?: number;\n  className?: string;\n};\n\nexport function KeyframesPrimitive({\n  children,\n  mode = \"keyframes\",\n  steps = 4,\n  fill = \"both\",\n  duration = 0.72,\n  easing = EASE_IN_OUT,\n  distance = 72,\n  className,\n}: KeyframesPrimitiveProps) {\n  const reduceMotion = useReducedMotion();\n  const count = Math.max(2, Math.round(steps));\n  const frames = Array.from({ length: count }, (_, index) => {\n    const progress = index / (count - 1);\n    const x = -distance + distance * 2 * progress;\n    const lift = index === Math.floor((count - 1) / 2) ? -10 : 0;\n    return `translate3d(${x}px, ${lift}px, 0) scale(${index === count - 1 ? 1 : 0.96 + progress * 0.06})`;\n  });\n  const motionFrames = mode === \"steps\"\n    ? frames.flatMap((frame, index) => index === frames.length - 1 ? [frame] : [frame, frame])\n    : mode === \"tween\"\n      ? [frames[0], frames.at(-1)!]\n      : frames;\n  const animate = reduceMotion\n    ? { opacity: 1 }\n    : { opacity: [0.55, 1], transform: motionFrames };\n\n  return (\n    <motion.div\n      className={className}\n      initial={fill === \"none\" || reduceMotion ? false : { opacity: 0.55, transform: frames[0] }}\n      animate={animate}\n      transition={reduceMotion ? { duration: 0.12 } : {\n        duration,\n        ease: mode === \"steps\" ? \"linear\" : easing,\n        times: motionFrames.map((_, index) => index / (motionFrames.length - 1)),\n      }}\n    >\n      {children}\n    </motion.div>\n  );\n}\n"
    }
  ]
}
