import Image from "next/image"; import { useState, useEffect, useRef } from "react"; import { createPortal } from "react-dom"; import '@/styles/gallery.css'; type Props = { images: string[]; videos?: string[]; title: string; }; export default function SimpleGallery({ images, videos = [], title }: Props) { const [active, setActive] = useState(0); const [isEnlarged, setIsEnlarged] = useState(false); const timerRef = useRef | null>(null); const videoRef = useRef(null); const fsPortalRef = useRef(null); const totalMedia = images.length + videos.length; const isVideo = active >= images.length; const videoIndex = active - images.length; const currentSrc = isVideo ? videos[videoIndex] : images[active]; if (totalMedia === 0) return null; function handleFullscreenClose() { setIsEnlarged(false); } function handleThumbnailClick(index: number) { setActive(index); } function expandButton() { return (
Expand
); } function shrinkButton() { return ( ); } function inlineMedia() { const imageStyle: React.CSSProperties = { width: "100%", borderRadius: 4, objectFit: "cover", maxHeight: 250, display: "block", transition: "all 0.8s ease", zIndex: 1, }; const videoStyle: React.CSSProperties = { width: "100%", borderRadius: 4, maxHeight: 250, display: "block", transition: "all 0.8s ease", }; return (
{isVideo ? (
); } function fullscreenOverlay() { if (!isEnlarged) return null; setTimeout(()=>{ if(!fsPortalRef.current) return fsPortalRef.current.style.opacity = "1" }, 50); return createPortal(
{isVideo ? (
, // portal target document.body ); } function thumbnailStrip() { if (totalMedia <= 1) return null; return (
{images.map((src, i) => ( {`${title} handleThumbnailClick(i)} style={{ width: 48, height: 36, objectFit: "cover", borderRadius: 3, cursor: "pointer", border: `2px solid ${i === active ? "var(--accent)" : "var(--border)"}`, opacity: i === active ? 1 : 0.6, transition: "all 0.15s ease", pointerEvents: "auto", }} /> ))} {videos.map((_, i) => { const mediaIndex = images.length + i; const isActive = mediaIndex === active; return ( ); })}
); } useEffect(() => { return () => { if (timerRef.current) clearTimeout(timerRef.current); }; }, []); // close fullscreen on Escape useEffect(() => { if (!isEnlarged) return; function onKeyDown(e: KeyboardEvent) { if (e.key === "Escape" && isEnlarged) handleFullscreenClose(); } window.addEventListener("keydown", onKeyDown); return () => window.removeEventListener("keydown", onKeyDown); }, [isEnlarged]); return ( <>
{inlineMedia()}
{thumbnailStrip()}
{fullscreenOverlay()} ); }