"use client"; import { useEffect, useState } from "react"; import { createPortal } from "react-dom"; function ChevronIcon({ direction, className }: { direction: "prev" | "next"; className?: string }) { const d = direction === "prev" ? "M14.5 6.5 9 12l5.5 5.5" : "M9.5 6.5 15 12l-5.5 5.5"; return ( ); } function CloseIcon({ className }: { className?: string }) { return ( ); } function Lightbox({ images, alt, index, onIndexChange, onClose, }: { images: string[]; alt: string; index: number; onIndexChange: (i: number) => void; onClose: () => void; }) { const hasMultiple = images.length > 1; useEffect(() => { document.body.style.overflow = "hidden"; const onKeyDown = (event: KeyboardEvent) => { if (event.key === "Escape") onClose(); if (event.key === "ArrowLeft") onIndexChange((index + 1) % images.length); if (event.key === "ArrowRight") onIndexChange((index - 1 + images.length) % images.length); }; document.addEventListener("keydown", onKeyDown); return () => { document.body.style.overflow = ""; document.removeEventListener("keydown", onKeyDown); }; }, [index, images.length, onClose, onIndexChange]); return createPortal(
e.stopPropagation()}> {/* eslint-disable-next-line @next/next/no-img-element */} {alt} {hasMultiple && ( <> )}
{hasMultiple && (
e.stopPropagation()} > {images.map((img, i) => ( ))}
)}
, document.body, ); } export function ProductGallery({ images, alt }: { images: string[]; alt: string }) { const [index, setIndex] = useState(0); const [zoomed, setZoomed] = useState(false); const [origin, setOrigin] = useState({ x: 50, y: 50 }); const [lightboxOpen, setLightboxOpen] = useState(false); const list = images.length > 0 ? images : ["/images/placeholder.svg"]; const hasMultiple = list.length > 1; const go = (delta: number) => { setIndex((prev) => (prev + delta + list.length) % list.length); }; return (
{ const rect = event.currentTarget.getBoundingClientRect(); setOrigin({ x: ((event.clientX - rect.left) / rect.width) * 100, y: ((event.clientY - rect.top) / rect.height) * 100, }); }} onMouseEnter={() => setZoomed(true)} onMouseLeave={() => setZoomed(false)} > {/* eslint-disable-next-line @next/next/no-img-element */} {alt} setLightboxOpen(true)} className="h-full w-full object-contain transition-transform duration-200 ease-out" style={{ transform: zoomed ? "scale(2)" : "scale(1)", transformOrigin: `${origin.x}% ${origin.y}%`, cursor: zoomed ? "zoom-in" : "zoom-in", }} /> {hasMultiple && ( <> )}
{hasMultiple && (
{list.map((img, i) => ( ))}
)} {lightboxOpen && ( setLightboxOpen(false)} /> )}
); }