{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "scroll-reveal-image",
  "title": "Scroll Reveal Image",
  "description": "Scroll-driven image reveal with spring-physics width expansion, zoom-out, and border radius animation.",
  "dependencies": [
    "framer-motion",
    "next"
  ],
  "files": [
    {
      "path": "registry/components/unlumen/scroll-reveal-image/index.tsx",
      "content": "\"use client\";\n\nimport Image from \"next/image\";\nimport { useRef } from \"react\";\nimport { motion, useScroll, useTransform, useSpring } from \"framer-motion\";\n\nexport interface ScrollRevealImageProps {\n  // Image\n  src: string;\n  alt: string;\n  quality?: number;\n  priority?: boolean;\n\n  // Container\n  height?: string;\n  fromWidth?: string;\n  toWidth?: string;\n  fromRadius?: string;\n  toRadius?: string;\n  /** Scroll progress (0–1) at which border radius starts animating */\n  radiusStart?: number;\n\n  // Inner image — wider than container to allow the zoom effect\n  innerWidth?: string;\n  fromScale?: number;\n  toScale?: number;\n\n  // Spring physics\n  stiffness?: number;\n  damping?: number;\n\n  // Scroll offset (framer-motion OffsetPoint tuple)\n  scrollOffset?: NonNullable<Parameters<typeof useScroll>[0]>[\"offset\"];\n\n  /** Optional scrollable ancestor ref (defaults to viewport) */\n  container?: React.RefObject<HTMLElement | null>;\n\n  // Layout\n  className?: string;\n  imageClassName?: string;\n}\n\nexport default function ScrollRevealImage({\n  src,\n  alt,\n  quality = 100,\n  priority = false,\n  height = \"80vh\",\n  fromWidth = \"40vw\",\n  toWidth = \"95vw\",\n  fromRadius = \"0px\",\n  toRadius = \"22px\",\n  radiusStart = 0.5,\n  innerWidth = \"95vw\",\n  fromScale = 1.6,\n  toScale = 1,\n  stiffness = 120,\n  damping = 80,\n  scrollOffset = [\"start end\", \"start start\"] as const,\n  container,\n  className,\n  imageClassName,\n}: ScrollRevealImageProps) {\n  const containerRef = useRef<HTMLDivElement>(null);\n\n  const { scrollYProgress } = useScroll({\n    target: containerRef,\n    container,\n    offset: scrollOffset,\n  });\n\n  const width = useTransform(scrollYProgress, [0, 1], [fromWidth, toWidth]);\n  const scale = useTransform(scrollYProgress, [0, 1], [fromScale, toScale]);\n  const radius = useTransform(\n    scrollYProgress,\n    [radiusStart, 1],\n    [fromRadius, toRadius],\n  );\n\n  const smoothWidth = useSpring(width, { stiffness, damping });\n  const smoothScale = useSpring(scale, { stiffness, damping });\n  const smoothRadius = useSpring(radius, { stiffness, damping });\n\n  return (\n    <motion.div\n      ref={containerRef}\n      className={className}\n      style={{\n        width: smoothWidth,\n        position: \"relative\",\n        height,\n        borderRadius: smoothRadius,\n        overflow: \"hidden\",\n        margin: \"0 auto\",\n      }}\n    >\n      <motion.div\n        style={{\n          position: \"absolute\",\n          left: \"50%\",\n          x: \"-50%\",\n          width: innerWidth,\n          height: \"100%\",\n          scale: smoothScale,\n          originX: 0.5,\n          originY: 0.5,\n        }}\n      >\n        <Image\n          src={src}\n          alt={alt}\n          fill\n          quality={quality}\n          priority={priority}\n          className={`object-cover${imageClassName ? ` ${imageClassName}` : \"\"}`}\n        />\n      </motion.div>\n    </motion.div>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/unlumen-ui/scroll-reveal-image.tsx"
    }
  ],
  "type": "registry:ui"
}