'use client'; import { useEffect, useRef, useState } from 'react'; import { XIcon } from 'lucide-react'; import { AnimatePresence, motion } from 'motion/react'; import { type GeneratedImage, useGeneratedImages } from '@/hooks/useGeneratedImages'; import { cn } from '@/lib/shadcn/utils'; const MotionPanel = motion.create('div'); interface ImageCardProps { image: GeneratedImage; onDismiss: () => void; } function ImageCard({ image, onDismiss }: ImageCardProps) { const src = image.imageUrl; return ( {/* eslint-disable-next-line @next/next/no-img-element */} {image.prompt} {image.prompt && (

{image.prompt}

)}
); } interface GeneratedImagePanelProps { chatOpen?: boolean; } /** * Listens for images generated by the agent and shows the most recent one. * When chat is open, repositions to the top-right corner to avoid covering the transcript. * * HACK HERE: swap for a gallery view, a fullscreen modal, download button, etc. */ export function GeneratedImagePanel({ chatOpen = false }: GeneratedImagePanelProps) { const images = useGeneratedImages(); const [dismissed, setDismissed] = useState>(new Set()); const prevLengthRef = useRef(0); // Auto-scroll to latest image useEffect(() => { if (images.length > prevLengthRef.current) { prevLengthRef.current = images.length; } }, [images]); const visible = images.filter((img) => !dismissed.has(img.id)); const latest = visible.at(-1); const dismiss = (id: string) => { setDismissed((prev) => new Set([...prev, id])); }; return (
{latest && ( dismiss(latest.id)} /> )}
); }