"use client"; import { useEffect, useRef, useState } from "react"; import { motion, useInView, useReducedMotion } from "motion/react"; type BlurEntranceProps = { src: string; alt: string; /** Blur at the start, in pixels. */ blur?: number; /** Seconds the picture takes to come into focus. */ duration?: number; /** Seconds to wait first. Use it to stagger a row. */ delay?: number; /** Play once, or again each time it comes back on screen. */ once?: boolean; /** Set the size here. */ className?: string; }; /* BlurEntrance: the picture waits blurred and slightly enlarged, then settles into sharp focus once it is loaded and on screen. */ export function BlurEntrance({ src, alt, blur = 24, duration = 1.2, delay = 0, once = true, className = "aspect-video" }: BlurEntranceProps) { const reduce = useReducedMotion(); const box = useRef(null); const picture = useRef(null); const seen = useInView(box, { once, amount: 0.3 }); const [ready, setReady] = useState(false); useEffect(() => { let live = true; const done = () => { if (live) setReady(true); }; picture.current?.decode().then(done, done); return () => { live = false; }; }, [src]); const hidden = { filter: `blur(${blur}px)`, scale: 1.12, opacity: 0.4 }; const sharp = reduce || (seen && ready); return (
); }