mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 17:31:13 -05:00
81 lines
1.9 KiB
TypeScript
81 lines
1.9 KiB
TypeScript
/**
|
|
* LazyImage Component
|
|
* Implements lazy loading for images using Intersection Observer
|
|
* Only loads images when they're scrolled into view
|
|
*/
|
|
|
|
import { useState, useEffect, useRef } from 'react';
|
|
|
|
interface LazyImageProps {
|
|
src: string;
|
|
alt: string;
|
|
className?: string;
|
|
onLoad?: () => void;
|
|
onError?: (e: React.SyntheticEvent<HTMLImageElement, Event>) => void;
|
|
}
|
|
|
|
export function LazyImage({
|
|
src,
|
|
alt,
|
|
className = '',
|
|
onLoad,
|
|
onError
|
|
}: LazyImageProps) {
|
|
const [isLoaded, setIsLoaded] = useState(false);
|
|
const [isInView, setIsInView] = useState(false);
|
|
const [hasError, setHasError] = useState(false);
|
|
const imgRef = useRef<HTMLDivElement>(null);
|
|
|
|
useEffect(() => {
|
|
if (!imgRef.current) return;
|
|
|
|
const observer = new IntersectionObserver(
|
|
([entry]) => {
|
|
if (entry.isIntersecting) {
|
|
setIsInView(true);
|
|
observer.disconnect();
|
|
}
|
|
},
|
|
{
|
|
rootMargin: '100px', // Start loading 100px before visible
|
|
threshold: 0.01,
|
|
}
|
|
);
|
|
|
|
observer.observe(imgRef.current);
|
|
|
|
return () => observer.disconnect();
|
|
}, []);
|
|
|
|
const handleLoad = () => {
|
|
setIsLoaded(true);
|
|
onLoad?.();
|
|
};
|
|
|
|
const handleError = (e: React.SyntheticEvent<HTMLImageElement, Event>) => {
|
|
setHasError(true);
|
|
onError?.(e);
|
|
};
|
|
|
|
return (
|
|
<div ref={imgRef} className={`relative ${className}`}>
|
|
{!isInView || hasError ? (
|
|
// Loading skeleton or error state
|
|
<div className="w-full h-full bg-muted animate-pulse rounded" />
|
|
) : (
|
|
<img
|
|
src={src}
|
|
alt={alt}
|
|
onLoad={handleLoad}
|
|
onError={handleError}
|
|
className={`w-full h-full object-cover transition-opacity duration-300 ${
|
|
isLoaded ? 'opacity-100' : 'opacity-0'
|
|
}`}
|
|
/>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
LazyImage.displayName = 'LazyImage';
|