"use client"; import React, { useCallback, useRef, useEffect } from "react"; import { Button } from "@/components/ui/button"; import { Textarea } from "@/components/ui/textarea"; import { Loader2, Send, RotateCcw, Image as ImageIcon, X } from "lucide-react"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; import Image from "next/image"; interface ChatInputProps { input: string; status: "submitted" | "streaming" | "ready" | "error"; onSubmit: (e: React.FormEvent) => void; onChange: (e: React.ChangeEvent) => void; setMessages: (messages: any[]) => void; onDisplayChart: (xml: string) => void; files?: FileList; onFileChange?: (files: FileList | undefined) => void; } export function ChatInput({ input, status, onSubmit, onChange, setMessages, onDisplayChart, files, onFileChange, }: ChatInputProps) { const textareaRef = useRef(null); const fileInputRef = useRef(null); // Auto-resize textarea based on content const adjustTextareaHeight = useCallback(() => { const textarea = textareaRef.current; if (textarea) { textarea.style.height = "auto"; textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`; } }, []); useEffect(() => { adjustTextareaHeight(); }, [input, adjustTextareaHeight]); // Handle clipboard paste events const handlePaste = useCallback( (e: React.ClipboardEvent) => { if (!onFileChange) return; const items = e.clipboardData.items; const imageItems = Array.from(items).filter( (item) => item.type.indexOf("image") !== -1 ); if (imageItems.length > 0) { e.preventDefault(); // Convert clipboard image to File const file = imageItems[0].getAsFile(); if (file) { // Create a new FileList-like object const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); // Pass to the existing file handler onFileChange(dataTransfer.files); } } }, [onFileChange] ); // Handle keyboard shortcuts const handleKeyDown = (e: React.KeyboardEvent) => { if ((e.metaKey || e.ctrlKey) && e.key === "Enter") { e.preventDefault(); const form = e.currentTarget.closest("form"); if (form && input.trim() && status !== "streaming") { form.requestSubmit(); } } }; // Handle file changes const handleFileChange = (e: React.ChangeEvent) => { if (onFileChange) { onFileChange(e.target.files || undefined); } }; // Clear file selection const clearFiles = () => { if (fileInputRef.current) { fileInputRef.current.value = ""; } if (onFileChange) { onFileChange(undefined); } }; // Trigger file input click const triggerFileInput = () => { fileInputRef.current?.click(); }; return (
{/* File preview area */} {files && files.length > 0 && (
{Array.from(files).map((file, index) => (
{file.type.startsWith("image/") ? ( {file.name} ) : (
{file.name}
)}
))}
)}