返回 presentation-ai
ImageSlideStatic.tsx
1 "use client";
2
3 import Image from "next/image";
4
5 import { Spinner } from "@/components/ui/spinner";
6 import { cn } from "@/lib/utils";
7 import { usePresentationState } from "@/states/presentation-state";
8 import { type RootImage } from "../../../utils/parser";
9
10 interface ImageSlideStaticProps {
11 image: RootImage;
12 slideId: string;
13 }
14
15 export default function ImageSlideStatic({
16 image,
17 slideId,
18 }: ImageSlideStaticProps) {
19 const rootImageGeneration = usePresentationState(
20 (s) => s.rootImageGeneration,
21 );
22 const rawComputedGen = rootImageGeneration[slideId];
23 const imageQuery = image.query.trim();
24 const computedGen =
25 rawComputedGen &&
26 (!imageQuery || rawComputedGen.query.trim() === imageQuery)
27 ? rawComputedGen
28 : undefined;
29 const computedImageUrl = computedGen?.url ?? image.url;
30 const isGenerating =
31 image.isQueryStreaming ||
32 computedGen?.status === "queued" ||
33 computedGen?.status === "generating";
34
35 return (
36 <div
37 className={cn(
38 "flex aspect-video w-full items-center justify-center",
39 "relative overflow-hidden",
40 )}
41 data-slide-id={slideId}
42 >
43 {isGenerating ? (
44 <div className="absolute inset-0 z-10 flex h-full w-full flex-col items-center justify-center gap-3 bg-muted/30 p-4 text-center">
45 <Spinner className="size-8" />
46 <div className="space-y-1">
47 <p className="text-sm font-medium text-foreground">
48 Generating image
49 </p>
50 <p className="text-xs text-muted-foreground">
51 This can take a moment.
52 </p>
53 </div>
54 </div>
55 ) : computedImageUrl ? (
56 <Image
57 unoptimized
58 width={400}
59 height={300}
60 src={computedImageUrl}
61 alt={image.query}
62 className="h-full w-full"
63 style={{
64 objectFit: image.cropSettings?.objectFit ?? "cover",
65 objectPosition: image.cropSettings?.objectPosition
66 ? `${image.cropSettings.objectPosition.x}% ${image.cropSettings.objectPosition.y}%`
67 : "center",
68 }}
69 />
70 ) : (
71 <div className="flex items-center justify-center text-muted-foreground">
72 <span>
73 {computedGen?.status === "error" ? "Image not found" : "No image"}
74 </span>
75 </div>
76 )}
77 </div>
78 );
79 }
80
80 lines Plain Text