UNPKG

react-advanced-gallery

Version:

A customizable React image gallery component with Bootstrap styling, fullscreen mode, animations, and support for various media types

92 lines (91 loc) 8.07 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import { useState, useEffect, useRef } from 'react'; export function FullscreenViewer({ isOpen, currentImage, images, currentIndex, zoomLevel, onClose, onPrev, onNext, onFavoriteToggle, onImageRemove, onZoomIn, onZoomOut, onThumbnailClick }) { var _a, _b, _c, _d; const [dragPosition, setDragPosition] = useState({ x: 0, y: 0 }); const containerRef = useRef(null); // Reset drag position when changing images or zoom level useEffect(() => { setDragPosition({ x: 0, y: 0 }); }, [currentIndex, zoomLevel]); const handleDownload = () => { if (!currentImage) return; const link = document.createElement('a'); link.href = currentImage.src; link.download = currentImage.title || 'image'; document.body.appendChild(link); link.click(); document.body.removeChild(link); }; const handleFullScreen = () => { if (!containerRef.current) return; if (!document.fullscreenElement) { containerRef.current.requestFullscreen().catch(err => { console.error(`Error attempting to enable fullscreen: ${err.message}`); }); } else { document.exitFullscreen(); } }; // Handle touch and mouse drag for panning when zoomed const dragConstraints = zoomLevel > 1 ? { top: -((((_a = containerRef.current) === null || _a === void 0 ? void 0 : _a.clientHeight) || 0) * (zoomLevel - 1) / 2), left: -((((_b = containerRef.current) === null || _b === void 0 ? void 0 : _b.clientWidth) || 0) * (zoomLevel - 1) / 2), right: ((((_c = containerRef.current) === null || _c === void 0 ? void 0 : _c.clientWidth) || 0) * (zoomLevel - 1) / 2), bottom: ((((_d = containerRef.current) === null || _d === void 0 ? void 0 : _d.clientHeight) || 0) * (zoomLevel - 1) / 2) } : { top: 0, left: 0, right: 0, bottom: 0 }; if (!isOpen || !currentImage) return null; // Format the date for the metadata display const formatDate = (dateString) => { if (!dateString) return ''; try { return new Date(dateString).toLocaleDateString(); } catch (e) { return ''; } }; return (_jsxs("div", { ref: containerRef, className: "rag-fullscreen", children: [_jsxs("div", { className: "rag-fullscreen-header", children: [_jsxs("div", { className: "rag-fullscreen-title", children: [_jsx("button", { className: "rag-fullscreen-btn", onClick: onClose, "aria-label": "Close fullscreen view", children: _jsx("span", { className: "rag-material-icons", children: "close" }) }), _jsx("h3", { children: currentImage.title })] }), _jsxs("div", { className: "rag-fullscreen-actions", children: [_jsx("button", { className: "rag-fullscreen-btn", onClick: () => onFavoriteToggle(currentImage), "aria-label": currentImage.isFavorite ? "Remove from favorites" : "Add to favorites", children: _jsx("span", { className: `rag-material-icons ${currentImage.isFavorite ? 'active' : ''}`, children: currentImage.isFavorite ? 'star' : 'star_border' }) }), _jsx("button", { className: "rag-fullscreen-btn", onClick: () => onImageRemove(currentImage), "aria-label": "Delete image", children: _jsx("span", { className: "rag-material-icons", children: "delete" }) }), _jsx("button", { className: "rag-fullscreen-btn", onClick: handleDownload, "aria-label": "Download image", children: _jsx("span", { className: "rag-material-icons", children: "download" }) })] })] }), _jsxs("div", { className: "rag-fullscreen-content", children: [_jsx("button", { className: "rag-fullscreen-nav-prev", onClick: onPrev, "aria-label": "Previous image", children: _jsx("span", { className: "rag-material-icons", children: "chevron_left" }) }), currentImage.type === 'video' ? (_jsx("video", { src: currentImage.src, poster: currentImage.thumbnail, controls: true, className: "rag-fullscreen-image" })) : (_jsx("img", { src: currentImage.src, alt: currentImage.alt, className: `rag-fullscreen-image ${zoomLevel > 1 ? 'zoomed' : ''}`, style: { transform: `scale(${zoomLevel})`, position: 'relative', left: `${dragPosition.x}px`, top: `${dragPosition.y}px`, }, draggable: false, onMouseDown: (e) => { if (zoomLevel <= 1) return; const startX = e.clientX; const startY = e.clientY; const startDragX = dragPosition.x; const startDragY = dragPosition.y; const onMouseMove = (e) => { const dx = e.clientX - startX; const dy = e.clientY - startY; const newX = Math.min(Math.max(startDragX + dx, -dragConstraints.right), dragConstraints.right); const newY = Math.min(Math.max(startDragY + dy, -dragConstraints.bottom), dragConstraints.bottom); setDragPosition({ x: newX, y: newY }); }; const onMouseUp = () => { document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', onMouseUp); }; document.addEventListener('mousemove', onMouseMove); document.addEventListener('mouseup', onMouseUp); } })), _jsx("button", { className: "rag-fullscreen-nav-next", onClick: onNext, "aria-label": "Next image", children: _jsx("span", { className: "rag-material-icons", children: "chevron_right" }) }), _jsxs("div", { className: "rag-fullscreen-zoom-controls", children: [_jsx("button", { className: "rag-fullscreen-btn", onClick: onZoomOut, "aria-label": "Zoom out", disabled: zoomLevel <= 0.5, children: _jsx("span", { className: "rag-material-icons", children: "zoom_out" }) }), _jsx("button", { className: "rag-fullscreen-btn", onClick: onZoomIn, "aria-label": "Zoom in", disabled: zoomLevel >= 3, children: _jsx("span", { className: "rag-material-icons", children: "zoom_in" }) }), _jsx("button", { className: "rag-fullscreen-btn", onClick: handleFullScreen, "aria-label": "Toggle fullscreen", children: _jsx("span", { className: "rag-material-icons", children: "fullscreen" }) })] })] }), _jsxs("div", { className: "rag-fullscreen-footer", children: [_jsx("div", { className: "rag-fullscreen-thumbnails", children: images.map((image, index) => (_jsx("div", { className: `rag-fullscreen-thumbnail ${index === currentIndex ? 'active' : ''}`, onClick: () => onThumbnailClick(index), children: _jsx("img", { src: image.thumbnail, alt: `${image.alt} thumbnail`, loading: "lazy" }) }, image.id))) }), currentImage.metadata && (_jsxs("div", { className: "rag-fullscreen-metadata", children: [_jsx("p", { children: [ currentImage.metadata.camera && `Shot on ${currentImage.metadata.camera}`, currentImage.metadata.aperture, currentImage.metadata.shutterSpeed, currentImage.metadata.iso && `ISO ${currentImage.metadata.iso}`, currentImage.metadata.focalLength ].filter(Boolean).join(' • ') }), _jsx("p", { children: [ currentImage.metadata.dateTaken && `Uploaded ${formatDate(currentImage.metadata.dateTaken)}`, currentImage.metadata.fileSize, currentImage.metadata.dimensions ].filter(Boolean).join(' • ') })] }))] })] })); }