UNPKG

@erosnicolau/animated-text

Version:

Advanced React animated text component with comprehensive animation effects

54 lines (53 loc) 2.27 kB
import { useEffect, useRef, useState } from 'react'; export const useVirtualizedIntersectionObserver = (options = {}) => { const [isIntersecting, setIsIntersecting] = useState(false); const [isInViewport, setIsInViewport] = useState(true); // For virtualization const elementRef = useRef(null); const { enableVirtualization = false, virtualizationMargin = '100px', onVirtualize, ...intersectionOptions } = options; // Normalize virtualization margin to ensure valid CSS format const normalizedMargin = virtualizationMargin.includes('px') || virtualizationMargin.includes('%') ? virtualizationMargin : `${virtualizationMargin}px`; useEffect(() => { const element = elementRef.current; if (!element) return; // Animation trigger observer (existing behavior) const animationObserver = new IntersectionObserver(([entry]) => { if (entry && entry.isIntersecting) { setIsIntersecting(true); // Once triggered, disconnect to prevent re-triggering animationObserver.disconnect(); } }, { threshold: 0.1, rootMargin: '0px 0px -100px 0px', ...intersectionOptions }); // Virtualization observer (new optimization) let virtualizationObserver = null; if (enableVirtualization) { virtualizationObserver = new IntersectionObserver(([entry]) => { if (entry) { const isVisible = entry.isIntersecting; setIsInViewport(isVisible); onVirtualize?.(isVisible); } }, { threshold: 0, rootMargin: normalizedMargin // Properly formatted margin }); virtualizationObserver.observe(element); } animationObserver.observe(element); return () => { animationObserver.disconnect(); virtualizationObserver?.disconnect(); }; }, [enableVirtualization, normalizedMargin, onVirtualize, intersectionOptions]); return { elementRef, isIntersecting, isInViewport: enableVirtualization ? isInViewport : true }; };