"use client"; import { motion, useInView, useReducedMotion } from "motion/react"; import { type ElementType, Fragment, useRef } from "react"; import { cn } from "@/lib/utils"; export interface BlurRiseProps { text: string; by?: "word" | "letter"; as?: ElementType; stagger?: number; maxSpread?: number; delay?: number; once?: boolean; className?: string; } const EASE_OUT = [0.23, 1, 0.32, 1] as const; export function BlurRise({ text, by = "word", as: Tag = "p", stagger, maxSpread = 0.6, delay = 0, once = true, className, }: BlurRiseProps) { const ref = useRef(null); const inView = useInView(ref, { once, amount: 0.4 }); const reduce = useReducedMotion(); const words = text.split(/\s+/).filter(Boolean); const count = by === "letter" ? words.reduce((n, w) => n + [...w].length, 0) : words.length; const wanted = stagger ?? (by === "letter" ? 0.022 : 0.035); const step = count > 1 ? Math.min(wanted, maxSpread / (count - 1)) : 0; let index = 0; const piece = (content: string, key: string) => { const at = delay + index++ * step; return ( {content} ); }; return ( {text} {words.map((word, w) => ( {by === "letter" ? [...word].map((ch, c) => piece(ch, `${w}-${c}`)) : piece(word, `${w}`)} {w < words.length - 1 && " "} ))} ); }