import { useState, useRef, useEffect } from 'react'; interface LazyImageProps { src: string; alt: string; width?: number; height?: number; className?: string; placeholder?: string; onLoad?: () => void; onError?: () => void; } export const LazyImage = ({ src, alt, width, height, className = '', placeholder, onLoad, onError }: LazyImageProps) => { const [isLoaded, setIsLoaded] = useState(false); const [isInView, setIsInView] = useState(false); const [hasError, setHasError] = useState(false); const imgRef = useRef(null); useEffect(() => { const observer = new IntersectionObserver( ([entry]) => { if (entry.isIntersecting) { setIsInView(true); observer.disconnect(); } }, { rootMargin: '50px', // Start loading 50px before the image comes into view threshold: 0.1 } ); if (imgRef.current) { observer.observe(imgRef.current); } return () => observer.disconnect(); }, []); const handleLoad = () => { setIsLoaded(true); onLoad?.(); }; const handleError = () => { setHasError(true); onError?.(); }; const defaultPlaceholder = placeholder || import.meta.env.BASE_URL + 'default-thumbnail.png'; return (
{!isLoaded && !hasError && (
)} {isInView && ( {alt} )}
); };