"use client"; import { ToolUIPart } from "ai"; import equal from "lib/equal"; import { cn } from "lib/utils"; import { ImagesIcon } from "lucide-react"; import { memo, useMemo } from "react"; import { TextShimmer } from "ui/text-shimmer"; import LetterGlitch from "ui/letter-glitch"; interface ImageGeneratorToolInvocationProps { part: ToolUIPart; } interface ImageGenerationResult { images: { url: string; mimeType?: string; }[]; mode?: "create" | "edit" | "composite"; model: string; } function PureImageGeneratorToolInvocation({ part, }: ImageGeneratorToolInvocationProps) { const isGenerating = useMemo(() => { return !part.state.startsWith("output"); }, [part.state]); const result = useMemo(() => { if (!part.state.startsWith("output")) return null; return part.output as ImageGenerationResult; }, [part.state, part.output]); const images = useMemo(() => { return result?.images || []; }, [result]); const mode = useMemo(() => { return result?.mode || "create"; }, [result]); const hasError = useMemo(() => { return ( part.state === "output-error" || (part.state === "output-available" && result?.images.length === 0) ); }, [part.state, result]); // Get mode-specific text const getModeText = (mode: string) => { switch (mode) { case "edit": return "Editing image..."; case "composite": return "Compositing images..."; default: return "Generating image..."; } }; const getModeHeader = (mode: string) => { switch (mode) { case "edit": return "Image edited"; case "composite": return "Images composited"; default: return "Image generated"; } }; // Simple loading state like web-search if (isGenerating) { return (
{getModeText(mode)}

Image generation may take up to 1 minute.

); } return (
{!hasError && } {hasError ? "Image generation failed" : getModeHeader(mode)} {result?.model}
{hasError ? (
{part.errorText ?? (result?.images.length === 0 ? "No images generated" : "Failed to generate image. Please try again.")}
) : ( <>
{images.map((image, index) => (
{/* eslint-disable-next-line @next/next/no-img-element */} {`Generated {/* Hover overlay */}
Open
))}
)}
); } export const ImageGeneratorToolInvocation = memo( PureImageGeneratorToolInvocation, (prev, next) => { return equal(prev.part, next.part); }, );