'use client' import { memo, useCallback, useMemo, Suspense, lazy } from 'react' import { cn } from '@djangocfg/ui-core/lib' import { useAppT } from '@djangocfg/i18n' import { ImageOff } from 'lucide-react' import { useGallery } from '../hooks/useGallery' import { GalleryGrid } from './preview' import { GalleryCarousel } from './preview' import type { GalleryProps } from '../types' // Lazy load lightbox - only loaded when user opens it const GalleryLightbox = lazy(() => import('./lightbox').then((mod) => ({ default: mod.GalleryLightbox })) ) /** * Gallery - Complete image gallery with carousel/grid preview and lightbox * * Features: * - Two preview modes: carousel (default) or grid * - Smooth slide transitions (embla-carousel) * - Touch/swipe support * - Keyboard navigation * - Fullscreen lightbox * - Dark overlay for controls */ export const Gallery = memo(function Gallery({ images, initialIndex = 0, previewMode = 'carousel', previewCount = 5, showThumbnails = true, showControls = true, showCounter = true, aspectRatio = 16 / 9, enableLightbox = true, enableKeyboard = true, onImageChange, onLightboxOpen, onLightboxClose, emptyState, className, }: GalleryProps) { const t = useAppT() const noImagesText = useMemo(() => t('tools.gallery.noImages'), [t]) const gallery = useGallery({ images, initialIndex, loop: true, onImageChange, }) const { currentIndex, total, hasMultiple, isLightboxOpen, goTo, openLightbox, closeLightbox, setLoading, } = gallery // Lightbox callbacks const handleLightboxOpen = useCallback(() => { openLightbox() onLightboxOpen?.() }, [openLightbox, onLightboxOpen]) const handleLightboxClose = useCallback(() => { closeLightbox() onLightboxClose?.() }, [closeLightbox, onLightboxClose]) // Open lightbox at specific index (for grid mode) const handleGridImageClick = useCallback( (index: number) => { goTo(index) openLightbox() onLightboxOpen?.() }, [goTo, openLightbox, onLightboxOpen] ) // Current image load handler const handleCurrentImageLoad = useCallback(() => { setLoading(false) }, [setLoading]) // Empty state if (images.length === 0) { if (emptyState) { return <>{emptyState}> } return (
{noImagesText}