| import { useRef, useState, type KeyboardEvent } from "react"; |
| import { ArrowUp, Square } from "lucide-react"; |
| import { cn } from "@/lib/utils"; |
|
|
| export function ChatInput({ |
| onSend, |
| onStop, |
| busy, |
| disabled, |
| placeholder, |
| }: { |
| onSend: (text: string) => void; |
| onStop?: () => void; |
| busy?: boolean; |
| disabled?: boolean; |
| placeholder?: string; |
| }) { |
| const [text, setText] = useState(""); |
| const ref = useRef<HTMLTextAreaElement>(null); |
|
|
| const submit = () => { |
| const t = text.trim(); |
| if (!t || busy || disabled) return; |
| onSend(t); |
| setText(""); |
| if (ref.current) ref.current.style.height = "auto"; |
| }; |
|
|
| const onKey = (e: KeyboardEvent<HTMLTextAreaElement>) => { |
| if (e.key === "Enter" && !e.shiftKey) { |
| e.preventDefault(); |
| submit(); |
| } |
| }; |
|
|
| return ( |
| <div |
| className={cn( |
| "flex items-end gap-2 rounded-2xl border border-border bg-card p-2 shadow-sm transition-colors focus-within:border-primary/60", |
| disabled && "opacity-60", |
| )} |
| > |
| <textarea |
| ref={ref} |
| value={text} |
| rows={1} |
| disabled={disabled} |
| placeholder={placeholder ?? "Ask a question…"} |
| onChange={(e) => { |
| setText(e.target.value); |
| e.target.style.height = "auto"; |
| e.target.style.height = Math.min(e.target.scrollHeight, 200) + "px"; |
| }} |
| onKeyDown={onKey} |
| className="max-h-[200px] flex-1 resize-none bg-transparent px-3 py-2 text-sm outline-none placeholder:text-muted-foreground" |
| /> |
| {busy ? ( |
| <button |
| onClick={onStop} |
| className="flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-muted text-foreground hover:bg-accent" |
| title="Stop" |
| > |
| <Square className="h-4 w-4" /> |
| </button> |
| ) : ( |
| <button |
| onClick={submit} |
| disabled={!text.trim() || disabled} |
| className="flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-primary text-primary-foreground transition-opacity hover:opacity-90 disabled:opacity-40" |
| title="Send" |
| > |
| <ArrowUp className="h-4 w-4" /> |
| </button> |
| )} |
| </div> |
| ); |
| } |
|
|