import React, { useRef, useEffect, useCallback, forwardRef, useImperativeHandle, useState } from 'react'; interface HubertInputProps { value: string; onChange: (value: string) => void; onSubmit: () => void; disabled?: boolean; placeholder?: string; } export interface HubertInputHandle { focus: () => void; } /** * Auto-resizing textarea input for Hubert chat. * Uses a clean CSS-based approach with proper state management. */ const HubertInput = forwardRef( ({ value, onChange, onSubmit, disabled = false, placeholder = "Type a message..." }, ref) => { const textareaRef = useRef(null); const [isMultiline, setIsMultiline] = useState(false); useImperativeHandle(ref, () => ({ focus: () => textareaRef.current?.focus(), })); // Adjust textarea height based on content const adjustHeight = useCallback(() => { const textarea = textareaRef.current; if (!textarea) return; // Reset to auto to get accurate scrollHeight textarea.style.height = 'auto'; // Get the natural content height const scrollHeight = textarea.scrollHeight; // Clamp between min (44px) and max (200px) const minHeight = 44; const maxHeight = 200; const newHeight = Math.max(minHeight, Math.min(scrollHeight, maxHeight)); textarea.style.height = `${newHeight}px`; // Update multiline state (threshold at ~1.5 lines) setIsMultiline(newHeight > 52); }, []); // Adjust height whenever value changes useEffect(() => { adjustHeight(); }, [value, adjustHeight]); // Also adjust on window resize useEffect(() => { window.addEventListener('resize', adjustHeight); return () => window.removeEventListener('resize', adjustHeight); }, [adjustHeight]); const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); if (!disabled && value.trim()) { onSubmit(); } } }; return (