import { useEffect, useRef, useState } from 'react'; import { useInView } from 'framer-motion'; interface UseScrollAnimationOptions { threshold?: number; rootMargin?: string; triggerOnce?: boolean; delay?: number; } export const useScrollAnimation = (options: UseScrollAnimationOptions = {}) => { const ref = useRef(null); const isInView = useInView(ref, { threshold: options.threshold || 0.1, margin: options.rootMargin || '-100px 0px', once: options.triggerOnce !== false, }); const [hasAnimated, setHasAnimated] = useState(false); useEffect(() => { if (isInView && !hasAnimated) { if (options.delay) { setTimeout(() => setHasAnimated(true), options.delay); } else { setHasAnimated(true); } } }, [isInView, hasAnimated, options.delay]); return { ref, inView: isInView, hasAnimated: hasAnimated || isInView, }; }; export const useStaggeredAnimation = (itemCount: number, delay: number = 100) => { const [visibleItems, setVisibleItems] = useState([]); const { ref, inView } = useScrollAnimation(); useEffect(() => { if (inView) { const timeouts: NodeJS.Timeout[] = []; for (let i = 0; i < itemCount; i++) { const timeout = setTimeout(() => { setVisibleItems(prev => [...prev, i]); }, i * delay); timeouts.push(timeout); } return () => { timeouts.forEach(timeout => clearTimeout(timeout)); }; } }, [inView, itemCount, delay]); return { ref, visibleItems, inView, }; }; // Hook for parallax effects export const useParallax = (speed: number = 0.5) => { const [offset, setOffset] = useState(0); const ref = useRef(null); useEffect(() => { const handleScroll = () => { if (ref.current) { const rect = ref.current.getBoundingClientRect(); const scrolled = window.pageYOffset; const rate = scrolled * speed; setOffset(rate); } }; window.addEventListener('scroll', handleScroll); return () => window.removeEventListener('scroll', handleScroll); }, [speed]); return { ref, offset, }; };