返回 presentation-ai
image-source-selector.tsx
根目录 / src / components / ui / image-source-selector.tsx
1 "use client";
2
3 import { Clapperboard, Image, Wand2 } from "lucide-react";
4 import { useSession } from "next-auth/react";
5
6 import { Label } from "@/components/ui/label";
7 import {
8 Select,
9 SelectContent,
10 SelectGroup,
11 SelectItem,
12 SelectLabel,
13 SelectTrigger,
14 SelectValue,
15 } from "@/components/ui/select";
16 import {
17 DEFAULT_IMAGE_MODEL,
18 getAvailableImageModels,
19 type ImageModelList,
20 } from "@/constants/image-models";
21 import { type PresentationStockImageProvider } from "@/states/presentation-state";
22
23 interface ImageSourceSelectorProps {
24 imageSource: "automatic" | "ai" | "stock" | "gif";
25 imageModel: ImageModelList;
26 stockImageProvider: PresentationStockImageProvider;
27 onImageSourceChange: (source: "automatic" | "ai" | "stock" | "gif") => void;
28 onImageModelChange: (model: ImageModelList) => void;
29 onStockImageProviderChange: (
30 provider: PresentationStockImageProvider,
31 ) => void;
32 className?: string;
33 showLabel?: boolean;
34 }
35
36 export function ImageSourceSelector({
37 imageSource,
38 imageModel,
39 stockImageProvider,
40 onImageSourceChange,
41 onImageModelChange,
42 onStockImageProviderChange,
43 className,
44 showLabel = true,
45 }: ImageSourceSelectorProps) {
46 const { data: session } = useSession();
47 const imageModels = getAvailableImageModels(session?.user?.isAdmin === true);
48
49 return (
50 <div className={className}>
51 {showLabel && (
52 <Label className="mb-2 block text-sm font-medium">Image Source</Label>
53 )}
54 <Select
55 value={
56 imageSource === "ai"
57 ? imageModel || DEFAULT_IMAGE_MODEL
58 : imageSource === "stock"
59 ? `stock-${stockImageProvider}`
60 : imageSource === "gif"
61 ? "gif"
62 : "automatic"
63 }
64 onValueChange={(value) => {
65 if (value === "automatic") {
66 onImageSourceChange("automatic");
67 } else if (value === "gif") {
68 onImageSourceChange("gif");
69 } else if (value.startsWith("stock-")) {
70 // Handle stock image selection
71 const provider = value.replace(
72 "stock-",
73 "",
74 ) as PresentationStockImageProvider;
75 onImageSourceChange("stock");
76 onStockImageProviderChange(provider);
77 } else {
78 // Handle AI model selection
79 onImageSourceChange("ai");
80 onImageModelChange(value as ImageModelList);
81 }
82 }}
83 >
84 <SelectTrigger>
85 <SelectValue placeholder="Select image generation method" />
86 </SelectTrigger>
87 <SelectContent>
88 <SelectGroup>
89 <SelectItem value="automatic" className="font-medium">
90 Automatic
91 </SelectItem>
92 </SelectGroup>
93 <SelectGroup>
94 <SelectLabel className="flex items-center gap-1 text-primary/80">
95 <Wand2 size={10} />
96 AI Generation
97 </SelectLabel>
98 {imageModels.map((model) => (
99 <SelectItem key={model.value} value={model.value}>
100 {model.label}
101 </SelectItem>
102 ))}
103 </SelectGroup>
104 <SelectGroup>
105 <SelectLabel className="flex items-center gap-1 text-primary/80">
106 <Image size={10} />
107 Stock & Web Images
108 </SelectLabel>
109 <SelectItem value="stock-unsplash">Unsplash</SelectItem>
110 <SelectItem value="stock-pixabay">Pixabay</SelectItem>
111 <SelectItem value="stock-google">Web Search</SelectItem>
112 </SelectGroup>
113 <SelectGroup>
114 <SelectLabel className="flex items-center gap-1 text-primary/80">
115 <Clapperboard size={10} />
116 Animated
117 </SelectLabel>
118 <SelectItem value="gif">GIFs from Giphy</SelectItem>
119 </SelectGroup>
120 </SelectContent>
121 </Select>
122 </div>
123 );
124 }
125
125 lines Plain Text