Spaces:
No application file
No application file
| "use client" | |
| import type React from "react" | |
| import { useState, useRef, type KeyboardEvent } from "react" | |
| import { Button } from "@/components/ui/button" | |
| import { Textarea } from "@/components/ui/textarea" | |
| import { Send, Trash2, Paperclip } from "lucide-react" | |
| interface ChatInputProps { | |
| onSend: (message: string, file?: File) => void | |
| isLoading: boolean | |
| onClear: () => void | |
| } | |
| export function ChatInput({ onSend, isLoading, onClear }: ChatInputProps) { | |
| const [message, setMessage] = useState("") | |
| const [file, setFile] = useState<File | null>(null) | |
| const fileInputRef = useRef<HTMLInputElement>(null) | |
| const handleSend = () => { | |
| if (message.trim() || file) { | |
| onSend(message.trim(), file || undefined) | |
| setMessage("") | |
| setFile(null) | |
| } | |
| } | |
| const handleKeyPress = (e: KeyboardEvent) => { | |
| if (e.key === "Enter" && !e.shiftKey) { | |
| e.preventDefault() | |
| handleSend() | |
| } | |
| } | |
| const handleFileSelect = (e: React.ChangeEvent<HTMLInputElement>) => { | |
| const selectedFile = e.target.files?.[0] | |
| if (selectedFile) { | |
| setFile(selectedFile) | |
| } | |
| } | |
| return ( | |
| <div className="space-y-2"> | |
| {file && ( | |
| <div className="flex items-center gap-2 p-2 bg-muted rounded-md"> | |
| <Paperclip className="h-4 w-4" /> | |
| <span className="text-sm">{file.name}</span> | |
| <Button variant="ghost" size="sm" onClick={() => setFile(null)}> | |
| × | |
| </Button> | |
| </div> | |
| )} | |
| <div className="flex gap-2"> | |
| <div className="flex-1 relative"> | |
| <Textarea | |
| value={message} | |
| onChange={(e) => setMessage(e.target.value)} | |
| onKeyPress={handleKeyPress} | |
| placeholder="Type your message... (Shift+Enter for new line)" | |
| className="min-h-[60px] resize-none pr-12" | |
| disabled={isLoading} | |
| /> | |
| <input | |
| ref={fileInputRef} | |
| type="file" | |
| className="hidden" | |
| onChange={handleFileSelect} | |
| accept=".txt,.json,.md,.pdf" | |
| /> | |
| <Button | |
| variant="ghost" | |
| size="sm" | |
| className="absolute right-2 top-2 h-8 w-8 p-0" | |
| onClick={() => fileInputRef.current?.click()} | |
| > | |
| <Paperclip className="h-4 w-4" /> | |
| </Button> | |
| </div> | |
| <div className="flex flex-col gap-2"> | |
| <Button onClick={handleSend} disabled={isLoading || (!message.trim() && !file)} size="sm"> | |
| <Send className="h-4 w-4" /> | |
| </Button> | |
| <Button variant="outline" onClick={onClear} size="sm"> | |
| <Trash2 className="h-4 w-4" /> | |
| </Button> | |
| </div> | |
| </div> | |
| </div> | |
| ) | |
| } | |