"use client"; import { useEffect, useRef, useState, useCallback } from "react"; interface UseScrollAnimationOptions { threshold?: number; rootMargin?: string; triggerOnce?: boolean; } export function useScrollAnimation( options: UseScrollAnimationOptions = {}, ) { const { threshold = 0.1, rootMargin = "0px", triggerOnce = true } = options; const ref = useRef(null); const [isVisible, setIsVisible] = useState(false); const [hasTriggered, setHasTriggered] = useState(false); useEffect(() => { if (typeof window === "undefined") return; // extra safety const element = ref.current; if (!element) return; const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { setIsVisible(true); if (triggerOnce) { setHasTriggered(true); observer.unobserve(element); } } else if (!triggerOnce) { setIsVisible(false); } }, { threshold, rootMargin }, ); observer.observe(element); return () => observer.disconnect(); }, [threshold, rootMargin, triggerOnce]); const reset = useCallback(() => { setIsVisible(false); setHasTriggered(false); }, []); return { ref, isVisible: triggerOnce ? isVisible || hasTriggered : isVisible, reset, }; }