prmbr-image-mksaas/src/ai/image/components/PromptInput.tsx
2025-06-28 22:47:40 +08:00

121 lines
4.2 KiB
TypeScript

import { Textarea } from '@/components/ui/textarea';
import { cn } from '@/lib/utils';
import { ArrowUp, ArrowUpRight, Loader2, RefreshCw } from 'lucide-react';
import { useState } from 'react';
import { type Suggestion, getRandomSuggestions } from '../lib/suggestions';
import { Spinner } from './spinner';
type QualityMode = 'performance' | 'quality';
// showProviders/onToggleProviders/mode/onModeChange are not used yet
interface PromptInputProps {
onSubmit: (prompt: string) => void;
isLoading?: boolean;
showProviders: boolean;
onToggleProviders: () => void;
mode: QualityMode;
onModeChange: (mode: QualityMode) => void;
suggestions: Suggestion[];
}
export function PromptInput({
suggestions: initSuggestions,
isLoading,
onSubmit,
}: PromptInputProps) {
const [input, setInput] = useState('');
const [suggestions, setSuggestions] = useState<Suggestion[]>(initSuggestions);
const updateSuggestions = () => {
setSuggestions(getRandomSuggestions());
};
const handleSuggestionSelect = (prompt: string) => {
setInput(prompt);
// onSubmit(prompt);
};
const handleSubmit = () => {
if (!isLoading && input.trim()) {
onSubmit(input);
}
};
// const handleRefreshSuggestions = () => {
// setCurrentSuggestions(getRandomSuggestions());
// };
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
if (!isLoading && input.trim()) {
onSubmit(input);
}
}
};
return (
<div className="w-full mb-8">
<div className="bg-card rounded-xl p-4">
<div className="flex flex-col gap-3">
<Textarea
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyDown={handleKeyDown}
placeholder="Enter your prompt here"
rows={3}
className="text-base bg-transparent border-muted p-2 resize-none placeholder:text-muted-foreground text-foreground focus-visible:ring-0 focus-visible:ring-offset-0"
/>
<div className="flex items-center justify-between pt-1">
<div className="flex items-center justify-between space-x-2">
{/* refresh suggestions */}
<button
type="button"
onClick={updateSuggestions}
className="flex items-center justify-between cursor-pointer px-2 rounded-lg py-1 bg-background text-sm hover:opacity-70 group transition-opacity duration-200"
>
<RefreshCw className="w-4 h-4 text-muted-foreground group-hover:opacity-70" />
</button>
{/* suggestions */}
{suggestions.map((suggestion, index) => (
<button
type="button"
key={index}
onClick={() => handleSuggestionSelect(suggestion.prompt)}
className={cn(
'flex items-center justify-between cursor-pointer px-2 rounded-lg py-1 bg-background text-sm hover:opacity-70 group transition-opacity duration-200',
index > 2
? 'hidden md:flex'
: index > 1
? 'hidden sm:flex'
: ''
)}
>
<span>
<span className="text-foreground text-xs sm:text-sm">
{suggestion.text.toLowerCase()}
</span>
</span>
<ArrowUpRight className="ml-1 h-2 w-2 sm:h-3 sm:w-3 text-muted-foreground group-hover:opacity-70" />
</button>
))}
</div>
{/* submit prompt */}
<button
type="button"
onClick={handleSubmit}
disabled={isLoading || !input.trim()}
className="h-8 w-8 cursor-pointer rounded-full bg-primary flex items-center justify-center disabled:opacity-50"
>
{isLoading ? (
<Loader2 className="w-3 h-3 text-primary-foreground animate-spin" />
) : (
<ArrowUp className="w-5 h-5 text-primary-foreground" />
)}
</button>
</div>
</div>
</div>
</div>
);
}