import { useEffect, useRef, useState } from 'react'; interface UseScrollDetectionOptions { targetElementId: string; scrollThreshold?: number; onStateChange?: (state: { isScrollingPastTarget: boolean; isScrollingBack: boolean; scrollProgress: number; }) => void; } interface UseScrollDetectionReturn { isScrollingPastTarget: boolean; isScrollingBack: boolean; scrollProgress: number; } export function useScrollDetection({ targetElementId, scrollThreshold = 0.3, onStateChange, }: UseScrollDetectionOptions): UseScrollDetectionReturn { const [isScrollingPastTarget, setIsScrollingPastTarget] = useState(false); const [isScrollingBack, setIsScrollingBack] = useState(false); const [scrollProgress, setScrollProgress] = useState(0); const lastScrollYRef = useRef(0); const targetElementRef = useRef(null); useEffect(() => { // Get target element targetElementRef.current = document.getElementById(targetElementId); const handleScroll = () => { if (!targetElementRef.current) return; const targetRect = targetElementRef.current.getBoundingClientRect(); const windowHeight = window.innerHeight; const scrollY = window.scrollY; const currentScrollDirection = scrollY > lastScrollYRef.current ? 'down' : 'up'; // Calculate if we've scrolled past the target element const targetTop = targetRect.top + scrollY; const thresholdDistance = window.innerHeight * scrollThreshold; const isPastTarget = scrollY > targetTop - thresholdDistance; // Determine scroll direction const isScrollingBackward = currentScrollDirection === 'up'; // Calculate scroll progress (0 to 1) const progress = Math.min(scrollY / (targetTop + thresholdDistance), 1); setIsScrollingPastTarget(isPastTarget); setIsScrollingBack(isScrollingBackward); setScrollProgress(progress); // Call callback if provided if (onStateChange) { onStateChange({ isScrollingPastTarget: isPastTarget, isScrollingBack: isScrollingBackward, scrollProgress: progress, }); } lastScrollYRef.current = scrollY; }; window.addEventListener('scroll', handleScroll, { passive: true }); return () => window.removeEventListener('scroll', handleScroll); }, [targetElementId, scrollThreshold, onStateChange]); return { isScrollingPastTarget, isScrollingBack, scrollProgress, }; }