"use client" import { useLayoutEffect, useRef, useState, type ReactNode, } from "react" import { cn } from "@/lib/utils" interface LandingRevealProps { children: ReactNode className?: string /** Délai (s) appliqué à la transition — pour le stagger. */ delay?: number as?: "div" | "section" | "li" | "span" } function isInRevealViewport(node: HTMLElement, margin = 36): boolean { const rect = node.getBoundingClientRect() return rect.top < window.innerHeight - margin && rect.bottom > margin } /** Révèle son contenu à l'entrée dans le viewport (une seule fois). */ export function LandingReveal({ children, className, delay = 0, as: Tag = "div", }: LandingRevealProps) { const ref = useRef(null) const [mounted, setMounted] = useState(false) const [revealed, setRevealed] = useState(true) useLayoutEffect(() => { setMounted(true) const node = ref.current if (!node) return if (typeof IntersectionObserver === "undefined") { setRevealed(true) return } if (isInRevealViewport(node)) { setRevealed(true) return } setRevealed(false) const observer = new IntersectionObserver( (entries) => { if (entries.some((entry) => entry.isIntersecting)) { setRevealed(true) observer.disconnect() } }, { threshold: 0.12, rootMargin: "0px 0px -36px 0px" } ) observer.observe(node) return () => observer.disconnect() }, []) return ( {children} ) }