import { useCallback, useEffect, useRef, useState } from "react"; import { Dialog as DialogPrimitive } from "radix-ui"; import { ChevronLeft, ChevronRight, Download, X } from "lucide-react"; import type { IssueAttachment } from "@paperclipai/shared"; interface ImageGalleryModalProps { images: IssueAttachment[]; initialIndex: number; open: boolean; onOpenChange: (open: boolean) => void; } export function ImageGalleryModal({ images, initialIndex, open, onOpenChange, }: ImageGalleryModalProps) { const [currentIndex, setCurrentIndex] = useState(initialIndex); const imageRef = useRef(null); useEffect(() => { if (open) setCurrentIndex(initialIndex); }, [open, initialIndex]); const goNext = useCallback(() => { setCurrentIndex((i) => (i + 1) % images.length); }, [images.length]); const goPrev = useCallback(() => { setCurrentIndex((i) => (i - 1 + images.length) % images.length); }, [images.length]); useEffect(() => { if (!open) return; const handler = (e: KeyboardEvent) => { if (e.key === "ArrowRight") goNext(); else if (e.key === "ArrowLeft") goPrev(); else if (e.key === "Escape") onOpenChange(false); }; window.addEventListener("keydown", handler); return () => window.removeEventListener("keydown", handler); }, [open, goNext, goPrev, onOpenChange]); /** Close when clicking empty curtain space (not interactive elements or the image) */ const handleBackdropClick = useCallback( (e: React.MouseEvent) => { const target = e.target as HTMLElement; if ( target.closest("button") || target.closest("a") || target === imageRef.current ) return; onOpenChange(false); }, [onOpenChange], ); if (images.length === 0) return null; const current = images[currentIndex]; if (!current) return null; return ( {/* Full-screen curtain */} {/* Top bar */}
{current.originalFilename ?? "Image"}
{currentIndex + 1} / {images.length} e.stopPropagation()} >
{/* Main area: nav buttons outside image */}
{/* Left nav zone */}
{images.length > 1 && ( )}
{/* Image */}
{current.originalFilename
{/* Right nav zone */}
{images.length > 1 && ( )}
{/* Bottom padding for balance */}
); }