import React, { useState } from "react"; import { X, Maximize2 } from "lucide-react"; import { cn } from "@/lib/utils"; import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog"; import { motion, AnimatePresence } from "framer-motion"; import { convertFileSrc } from "@tauri-apps/api/core"; interface ImagePreviewProps { /** * Array of image file paths to preview */ images: string[]; /** * Callback to remove an image from the preview */ onRemove: (index: number) => void; /** * Optional className for styling */ className?: string; } /** * ImagePreview component - Shows thumbnail previews of embedded images * * Features: * - Shows up to 10 image thumbnails in a row * - Click on thumbnail to see full-size preview * - Hover to show remove button * - Smooth animations * * @example * console.log('Remove image at', index)} * /> */ export const ImagePreview: React.FC = ({ images, onRemove, className, }) => { const [selectedImageIndex, setSelectedImageIndex] = useState(null); const [hoveredIndex, setHoveredIndex] = useState(null); const [imageErrors, setImageErrors] = useState>(new Set()); // Limit to 10 images const displayImages = images.slice(0, 10); const handleImageError = (index: number) => { setImageErrors(prev => new Set(prev).add(index)); }; const handleRemove = (e: React.MouseEvent, index: number) => { e.stopPropagation(); onRemove(index); }; if (displayImages.length === 0) return null; return ( <>
{displayImages.map((imagePath, index) => ( setHoveredIndex(index)} onMouseLeave={() => setHoveredIndex(null)} >
setSelectedImageIndex(index)} > {imageErrors.has(index) ? (
Error
) : ( {`Preview handleImageError(index)} /> )} {/* Hover overlay with maximize icon */}
{/* Remove button */} {hoveredIndex === index && ( handleRemove(e, index)} > )}
))}
{images.length > 10 && (
+{images.length - 10}
)}
{/* Full-size preview dialog */} !open && setSelectedImageIndex(null)} > Image Preview {selectedImageIndex !== null && (
{`Full handleImageError(selectedImageIndex)} /> {/* Navigation buttons if multiple images */} {displayImages.length > 1 && ( <> )}
)}
); };