返回 presentation-ai
PromptInput.tsx
1 import { usePresentationState } from "@/states/presentation-state";
2 import { RefreshCw } from "lucide-react";
3 import { toast } from "sonner";
4
5 export function PromptInput() {
6 const {
7 presentationInput,
8 setPresentationInput,
9 startOutlineGeneration,
10 isGeneratingOutline,
11 } = usePresentationState();
12
13 const handleGenerateOutline = () => {
14 if (!presentationInput.trim()) {
15 toast.error("Please enter a presentation topic");
16 return;
17 }
18
19 startOutlineGeneration();
20 };
21
22 return (
23 <div className="rounded-2xl border border-border/60 bg-background/80 p-3 shadow-xs sm:p-4">
24 <div className="mb-3 flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between">
25 <div className="space-y-1">
26 <h3 className="text-sm font-semibold text-foreground">
27 Presentation prompt
28 </h3>
29 <p className="text-sm text-muted-foreground">
30 Refine the topic or regenerate the outline after edits.
31 </p>
32 </div>
33 <button
34 className={`inline-flex h-10 shrink-0 items-center justify-center rounded-xl border border-border bg-muted/40 px-3 transition-colors ${
35 isGeneratingOutline
36 ? "text-indigo-400"
37 : "text-indigo-400 hover:bg-muted hover:text-indigo-500"
38 }`}
39 onClick={handleGenerateOutline}
40 disabled={isGeneratingOutline || !presentationInput.trim()}
41 aria-label="Regenerate outline"
42 >
43 <RefreshCw size={18} />
44 </button>
45 </div>
46
47 <input
48 type="text"
49 value={presentationInput}
50 onChange={(e) => setPresentationInput(e.target.value)}
51 className="w-full rounded-xl border border-border/60 bg-muted/30 px-4 py-3 text-sm text-foreground outline-hidden transition-colors placeholder:text-muted-foreground focus:ring-2 focus:ring-indigo-400 sm:text-base"
52 placeholder="Enter your presentation topic..."
53 disabled={isGeneratingOutline}
54 />
55 </div>
56 );
57 }
58
58 lines Plain Text