{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"parallax","type":"registry:component","title":"Scroll Animation Parallax","description":"Wrapper that drifts its children at a speed factor as they cross the viewport, on either axis. Reduced-motion safe.","author":"Saurabh <saurabh10102@gmail.com>","dependencies":["clsx","motion","tailwind-merge"],"registryDependencies":[],"files":[{"path":"components/motion/parallax.tsx","type":"registry:component","target":"@components/motion/parallax.tsx","content":"\"use client\";\n// beui.dev/components/motion/scroll-animation\n\nimport {\n  motion,\n  type MotionStyle,\n  useReducedMotion,\n  useScroll,\n  useSpring,\n  useTransform,\n} from \"motion/react\";\nimport { type ReactNode, type RefObject, useRef } from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\n// Soft follow so the drift trails the scroll smoothly; looser than the UI\n// springs in lib/ease.ts on purpose.\nconst PARALLAX_SPRING = { stiffness: 120, damping: 30, mass: 0.6 };\n\nexport interface ParallaxProps {\n  children: ReactNode;\n  /**\n   * Drift as a fraction of the element's travel through the viewport.\n   * Positive moves with the scroll (foreground), negative against it\n   * (background). ~0.1–0.5 reads best.\n   */\n  speed?: number;\n  axis?: \"x\" | \"y\";\n  /** Scroll container for contained scroll areas. Defaults to the viewport. */\n  container?: RefObject<HTMLElement | null>;\n  /** Spring-smooth the drift. Disabled automatically under reduced motion. */\n  spring?: boolean;\n  className?: string;\n}\n\nexport function Parallax({\n  children,\n  speed = 0.3,\n  axis = \"y\",\n  container,\n  spring = true,\n  className,\n}: ParallaxProps) {\n  const reduce = useReducedMotion();\n  const ref = useRef<HTMLDivElement>(null);\n  const { scrollYProgress } = useScroll({\n    target: ref,\n    container,\n    offset: [\"start end\", \"end start\"],\n    // Run after paint so a container ref defined higher in the tree is hydrated;\n    // otherwise framer falls back to the document and only the page scroll works.\n    layoutEffect: false,\n  });\n\n  // progress 0→1 as the element crosses the viewport; map to a symmetric drift.\n  const travel = speed * 100;\n  const drift = useTransform(scrollYProgress, [0, 1], [travel, -travel]);\n  const smoothed = useSpring(drift, PARALLAX_SPRING);\n  const value = spring && !reduce ? smoothed : drift;\n\n  const style: MotionStyle = reduce ? {} : axis === \"x\" ? { x: value } : { y: value };\n\n  return (\n    <motion.div ref={ref} style={style} className={cn(className)}>\n      {children}\n    </motion.div>\n  );\n}\n"},{"path":"lib/utils.ts","type":"registry:lib","target":"@lib/utils.ts","content":"import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n  return twMerge(clsx(inputs))\n}\n"}]}