Files
memefast/resources/js/components/ui/media-item.jsx
2025-07-15 02:38:23 +08:00

48 lines
1.6 KiB
JavaScript

import { useState } from 'react';
import { MediaItemSkeleton } from './media-item-skeleton';
const MediaItem = ({ src, alt, onClick, isSelected, className = "" }) => {
const [isLoading, setIsLoading] = useState(true);
const [hasError, setHasError] = useState(false);
const handleImageLoad = () => {
setIsLoading(false);
};
const handleImageError = () => {
setIsLoading(false);
setHasError(true);
};
return (
<div className={`relative aspect-[9/16] w-full overflow-hidden rounded-lg bg-muted ${className}`}>
{isLoading && (
<div className="absolute inset-0 z-10">
<MediaItemSkeleton />
</div>
)}
{hasError ? (
<div className="flex h-full w-full items-center justify-center bg-muted text-muted-foreground text-xs p-2 text-center">
Failed to load
</div>
) : (
<img
src={src}
alt={alt}
className={`h-full w-full object-cover cursor-pointer transition-opacity duration-300 ${isLoading ? 'opacity-0' : 'opacity-100'}`}
onLoad={handleImageLoad}
onError={handleImageError}
onClick={onClick}
/>
)}
{/* Selection border overlay */}
{isSelected && !isLoading && (
<div className="absolute inset-0 rounded-lg ring-2 ring-blue-500 pointer-events-none" />
)}
</div>
);
};
export { MediaItem };