import { ChevronLeft, ChevronRight, X } from "lucide-react"; import React, { useEffect, useMemo, useState } from "react"; import MotionPhotoPreview from "@/components/MotionPhotoPreview"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog"; import { VisuallyHidden } from "@/components/ui/visually-hidden"; import useMediaQuery from "@/hooks/useMediaQuery"; import { cn } from "@/lib/utils"; import type { PreviewMediaItem } from "@/utils/media-item"; interface Props { open: boolean; onOpenChange: (open: boolean) => void; imgUrls?: string[]; items?: PreviewMediaItem[]; initialIndex?: number; } function PreviewImageDialog({ open, onOpenChange, imgUrls = [], items, initialIndex = 0 }: Props) { const sm = useMediaQuery("sm"); const [currentIndex, setCurrentIndex] = useState(initialIndex); const previewItems = useMemo( () => items ?? imgUrls.map((url) => ({ id: url, kind: "image" as const, sourceUrl: url, posterUrl: url, filename: "Image" })), [imgUrls, items], ); useEffect(() => { if (open) { setCurrentIndex(initialIndex); } }, [initialIndex, open]); const itemCount = previewItems.length; const safeIndex = Math.max(0, Math.min(currentIndex, itemCount - 1)); const currentItem = previewItems[safeIndex]; const hasMultiple = itemCount > 1; const canGoPrevious = safeIndex > 0; const canGoNext = safeIndex < itemCount - 1; useEffect(() => { const handleKeyDown = (event: KeyboardEvent) => { if (!open) { return; } if (event.key === "Escape") { onOpenChange(false); return; } if (event.key === "ArrowLeft") { setCurrentIndex((prev) => Math.max(prev - 1, 0)); return; } if (event.key === "ArrowRight") { setCurrentIndex((prev) => Math.min(prev + 1, itemCount - 1)); } }; document.addEventListener("keydown", handleKeyDown); return () => document.removeEventListener("keydown", handleKeyDown); }, [itemCount, onOpenChange, open]); if (!itemCount || !currentItem) { return null; } const handleClose = () => onOpenChange(false); const handlePrevious = () => setCurrentIndex((prev) => Math.max(prev - 1, 0)); const handleNext = () => setCurrentIndex((prev) => Math.min(prev + 1, itemCount - 1)); return ( {currentItem.filename || "Attachment preview"}
{currentItem.filename || "Attachment"}
{hasMultiple && (
{safeIndex + 1} / {itemCount}
)}
{ if (event.target === event.currentTarget) { handleClose(); } }} >
event.stopPropagation()}> {currentItem.kind === "video" ? (
{hasMultiple && sm && ( <> } /> } /> )} {hasMultiple && !sm && (
{safeIndex + 1} / {itemCount}
)}
Attachment preview dialog. Press Escape to close and use left or right arrow keys to switch items.
); } interface NavButtonProps { side: "left" | "right"; disabled: boolean; label: string; onClick: () => void; icon: React.ReactNode; } const NavButton = ({ side, disabled, label, onClick, icon }: NavButtonProps) => ( ); export default PreviewImageDialog;