Spaces:
Running
Running
| import React, { useRef, useEffect, useState, ReactNode } from 'react'; | |
| import { sampleImageModalState } from '@/components/SampleImageModal'; | |
| import { isVideo } from '@/utils/basic'; | |
| interface SampleImageCardProps { | |
| imageUrl: string; | |
| alt: string; | |
| numSamples: number; | |
| sampleImages: string[]; | |
| children?: ReactNode; | |
| className?: string; | |
| onDelete?: () => void; | |
| } | |
| const SampleImageCard: React.FC<SampleImageCardProps> = ({ | |
| imageUrl, | |
| alt, | |
| numSamples, | |
| sampleImages, | |
| children, | |
| className = '', | |
| }) => { | |
| const cardRef = useRef<HTMLDivElement>(null); | |
| const [isVisible, setIsVisible] = useState<boolean>(false); | |
| const [loaded, setLoaded] = useState<boolean>(false); | |
| useEffect(() => { | |
| // Create intersection observer to check visibility | |
| const observer = new IntersectionObserver( | |
| entries => { | |
| if (entries[0].isIntersecting) { | |
| setIsVisible(true); | |
| observer.disconnect(); | |
| } | |
| }, | |
| { threshold: 0.1 }, | |
| ); | |
| if (cardRef.current) { | |
| observer.observe(cardRef.current); | |
| } | |
| return () => { | |
| observer.disconnect(); | |
| }; | |
| }, []); | |
| const handleLoad = (): void => { | |
| setLoaded(true); | |
| }; | |
| console.log('imgurl',imageUrl.toLowerCase().slice(-4)) | |
| return ( | |
| <div className={`flex flex-col ${className}`}> | |
| {/* Square image container */} | |
| <div | |
| ref={cardRef} | |
| className="relative w-full cursor-pointer" | |
| style={{ paddingBottom: '100%' }} // Make it square | |
| onClick={() => sampleImageModalState.set({ imgPath: imageUrl, numSamples, sampleImages })} | |
| > | |
| <div className="absolute inset-0 rounded-t-lg shadow-md"> | |
| {isVisible && ( | |
| <> | |
| {isVideo(imageUrl) ? ( | |
| <video | |
| src={`/api/img/${encodeURIComponent(imageUrl)}`} | |
| className={`w-full h-full object-cover`} | |
| autoPlay={false} | |
| loop | |
| muted | |
| playsInline | |
| /> | |
| ) : ( | |
| <img | |
| src={`/api/img/${encodeURIComponent(imageUrl)}`} | |
| alt={alt} | |
| onLoad={handleLoad} | |
| className={`w-full h-full object-cover transition-opacity duration-300 ${ | |
| loaded ? 'opacity-100' : 'opacity-0' | |
| }`} | |
| /> | |
| )} | |
| </> | |
| )} | |
| {children && <div className="absolute inset-0 flex items-center justify-center">{children}</div>} | |
| </div> | |
| </div> | |
| </div> | |
| ); | |
| }; | |
| export default SampleImageCard; | |