import { useEffect, useCallback } from 'react'; import { cn } from '@/lib/utils'; import type { ImetaEntry } from '@/lib/imeta'; interface ImageGalleryProps { images: string[]; /** Max images to show in the grid before "+ more" overflow. */ maxVisible?: number; maxGridHeight?: string; /** imeta metadata keyed by URL (dim, blurhash, etc.). Unused in this stub. */ imetaMap?: Map; lightboxIndex?: number | null; onLightboxOpen?: (index: number) => void; onLightboxClose?: () => void; className?: string; } /** * Minimal image gallery grid. * * Ditto's richer `ImageGallery` uses `imetaMap` for precise aspect ratios, * blurhash placeholders, CSS-grid masonry, pinch-to-zoom on mobile, and * keyboard navigation. Replace this stub with a richer gallery as needed. */ export function ImageGallery({ images, maxVisible = 4, maxGridHeight, lightboxIndex, onLightboxOpen, onLightboxClose, className, }: ImageGalleryProps) { const shown = images.slice(0, maxVisible); const extra = Math.max(0, images.length - maxVisible); // Two-column grid for 2+ images const gridCols = shown.length === 1 ? 'grid-cols-1' : 'grid-cols-2'; return ( <>
{shown.map((url, idx) => ( ))}
{lightboxIndex !== null && lightboxIndex !== undefined && ( { /* noop */ })} /> )} ); } interface LightboxProps { images: string[]; currentIndex: number; onClose: () => void; onNext?: () => void; onPrev?: () => void; } /** * Minimal fullscreen lightbox — click-outside-to-close, arrow-key navigation. * * Ditto's richer `Lightbox` supports pinch-zoom, swipe gestures, download, * and alt-text overlays. Replace this stub with a richer viewer as needed. */ export function Lightbox({ images, currentIndex, onClose, onNext, onPrev }: LightboxProps) { const handleKey = useCallback( (e: KeyboardEvent) => { if (e.key === 'Escape') onClose(); else if (e.key === 'ArrowRight') onNext?.(); else if (e.key === 'ArrowLeft') onPrev?.(); }, [onClose, onNext, onPrev], ); useEffect(() => { window.addEventListener('keydown', handleKey); return () => window.removeEventListener('keydown', handleKey); }, [handleKey]); const url = images[currentIndex]; if (!url) return null; return (
{onPrev && images.length > 1 && ( )} {onNext && images.length > 1 && ( )} e.stopPropagation()} />
); }