56 lines
1.9 KiB
TypeScript
56 lines
1.9 KiB
TypeScript
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
|
import { type Media } from "@/domain/types";
|
|
import { AuthenticatedImage } from "./authenticated-image";
|
|
import { Skeleton } from "../ui/skeleton";
|
|
import {
|
|
ResizablePanelGroup,
|
|
ResizablePanel,
|
|
ResizableHandle,
|
|
} from "@/components/ui/resizable";
|
|
import { MediaDetailsSidebar } from "./media-details-sidebar";
|
|
|
|
type MediaViewerProps = {
|
|
media: Media | null;
|
|
onOpenChange: (open: boolean) => void;
|
|
};
|
|
|
|
export function MediaViewer({ media, onOpenChange }: MediaViewerProps) {
|
|
const isOpen = media !== null;
|
|
|
|
return (
|
|
<Dialog open={isOpen} onOpenChange={onOpenChange}>
|
|
<DialogContent className="min-w-[90vw] max-w-full h-[90vh] p-0 border-0">
|
|
{/* We use a resizable panel group to show the image and sidebar */}
|
|
<ResizablePanelGroup direction="horizontal" className="h-full">
|
|
{/* --- Panel 1: The Image --- */}
|
|
<ResizablePanel defaultSize={75} className="bg-gray-100">
|
|
<div className="flex h-full items-center justify-center overflow-hidden relative p-4">
|
|
{media ? (
|
|
<AuthenticatedImage
|
|
src={media.file_url}
|
|
alt={media.original_filename}
|
|
className="max-w-full max-h-full object-contain"
|
|
/>
|
|
) : (
|
|
<Skeleton className="w-full h-full" />
|
|
)}
|
|
</div>
|
|
</ResizablePanel>
|
|
|
|
{/* --- The Handle --- */}
|
|
<ResizableHandle withHandle />
|
|
|
|
{/* --- Panel 2: The Details Sidebar --- */}
|
|
<ResizablePanel defaultSize={25} minSize={20} maxSize={40}>
|
|
{media ? (
|
|
<MediaDetailsSidebar media={media} />
|
|
) : (
|
|
<Skeleton className="w-full h-full" />
|
|
)}
|
|
</ResizablePanel>
|
|
</ResizablePanelGroup>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|