'use client'; import React, { useState, useRef, useCallback, useEffect } from 'react'; import { Send } from 'lucide-react'; import { cn } from '@/lib/utils'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; type AIProvider = 'claude' | 'openai'; interface ChatComposerProps { /** Callback when a message is sent */ onSend: (message: string, provider?: AIProvider) => void; /** Whether the input is disabled */ disabled?: boolean; /** Whether a response is currently streaming */ isStreaming?: boolean; /** Show provider selector dropdown */ showProviderSelector?: boolean; } /** * ChatComposer - Message input area for the Control Center * * Features auto-resizing textarea, send button, optional provider selector, * and keyboard shortcuts for sending messages. */ export const ChatComposer: React.FC = ({ onSend, disabled = false, isStreaming = false, showProviderSelector = false, }) => { const [message, setMessage] = useState(''); const [provider, setProvider] = useState('claude'); const textareaRef = useRef(null); const isDisabled = disabled || isStreaming; const canSend = message.trim().length > 0 && !isDisabled; // Auto-resize textarea based on content const adjustTextareaHeight = useCallback(() => { const textarea = textareaRef.current; if (textarea) { // Reset height to auto to get the correct scrollHeight textarea.style.height = 'auto'; // Set height to scrollHeight, with min and max constraints const newHeight = Math.min(Math.max(textarea.scrollHeight, 44), 200); textarea.style.height = `${newHeight}px`; } }, []); useEffect(() => { adjustTextareaHeight(); }, [message, adjustTextareaHeight]); const handleSend = useCallback(() => { if (!canSend) return; const trimmedMessage = message.trim(); onSend(trimmedMessage, showProviderSelector ? provider : undefined); setMessage(''); // Reset textarea height after clearing if (textareaRef.current) { textareaRef.current.style.height = '44px'; } }, [canSend, message, onSend, provider, showProviderSelector]); const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { // Ctrl/Cmd + Enter to send if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { e.preventDefault(); handleSend(); } }, [handleSend] ); const handleChange = useCallback( (e: React.ChangeEvent) => { setMessage(e.target.value); }, [] ); return (
{/* Provider selector (optional) */} {showProviderSelector && (
Provider:
)} {/* Main input area */}