'use client'; import { useState, useRef, useCallback, useImperativeHandle, forwardRef } from 'react'; import { Send, Image as ImageIcon, X, Loader2 } from 'lucide-react'; import { clsx } from 'clsx'; interface MessageInputProps { onSend: (message: string, imageUrl?: string, imageBase64?: string) => void; isLoading: boolean; placeholder?: string; } export interface MessageInputRef { setContent: (text: string, imageUrl?: string) => void; clear: () => void; } export const MessageInput = forwardRef( function MessageInput( { onSend, isLoading, placeholder = 'Ask about quantum computing, Qiskit, or upload a circuit diagram...', }, ref ) { const [message, setMessage] = useState(''); const [imageBase64, setImageBase64] = useState(null); const [imageUrl, setImageUrl] = useState(null); const [imagePreview, setImagePreview] = useState(null); const fileInputRef = useRef(null); const textareaRef = useRef(null); useImperativeHandle(ref, () => ({ setContent: (text: string, url?: string) => { setMessage(text); if (url) { setImageUrl(url); setImagePreview(url); setImageBase64(null); } if (textareaRef.current) { textareaRef.current.style.height = 'auto'; setTimeout(() => { if (textareaRef.current) { textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 200)}px`; } }, 0); } }, clear: () => { setMessage(''); setImageBase64(null); setImageUrl(null); setImagePreview(null); if (textareaRef.current) { textareaRef.current.style.height = 'auto'; } }, })); const handleSubmit = useCallback(() => { if ((!message.trim() && !imageBase64 && !imageUrl) || isLoading) return; onSend(message.trim(), imageUrl || undefined, imageBase64 || undefined); setMessage(''); setImageBase64(null); setImageUrl(null); setImagePreview(null); if (textareaRef.current) { textareaRef.current.style.height = 'auto'; } }, [message, imageBase64, imageUrl, isLoading, onSend]); const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSubmit(); } }; const handleImageUpload = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; if (!file.type.startsWith('image/')) { alert('Please upload an image file'); return; } const reader = new FileReader(); reader.onload = (event) => { const result = event.target?.result as string; const base64 = result.split(',')[1]; setImageBase64(base64); setImageUrl(null); setImagePreview(result); }; reader.readAsDataURL(file); }; const removeImage = () => { setImageBase64(null); setImageUrl(null); setImagePreview(null); if (fileInputRef.current) { fileInputRef.current.value = ''; } }; const adjustTextareaHeight = (e: React.ChangeEvent) => { const textarea = e.target; textarea.style.height = 'auto'; textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`; setMessage(textarea.value); }; const hasContent = message.trim() || imageBase64 || imageUrl; return (
{imagePreview && (
Upload preview
)}