import React, { useRef, useLayoutEffect, useState } from 'react'; import { ArrowUp, Square } from 'lucide-react'; import { AppState } from '../types'; interface InputSectionProps { query: string; setQuery: (q: string) => void; onRun: () => void; onStop: () => void; appState: AppState; } const InputSection = ({ query, setQuery, onRun, onStop, appState }: InputSectionProps) => { const textareaRef = useRef(null); const [isComposing, setIsComposing] = useState(false); const adjustHeight = () => { if (textareaRef.current) { // Reset height to auto to allow shrinking when text is deleted textareaRef.current.style.height = 'auto'; const scrollHeight = textareaRef.current.scrollHeight; const maxHeight = 200; // Set new height based on scrollHeight, capped at 200px textareaRef.current.style.height = `${Math.min(scrollHeight, maxHeight)}px`; // Only show scrollbar if we hit the max height limit if (scrollHeight > maxHeight) { textareaRef.current.style.overflowY = 'auto'; } else { textareaRef.current.style.overflowY = 'hidden'; } } }; // useLayoutEffect prevents visual flickering by adjusting height before paint useLayoutEffect(() => { adjustHeight(); }, [query]); const handleKeyDown = (e: React.KeyboardEvent) => { // If user presses Enter without Shift if (e.key === 'Enter' && !e.shiftKey) { // robust check for IME composition (e.g. Chinese/Japanese inputs) if (isComposing || (e.nativeEvent as any).isComposing) { return; } e.preventDefault(); if (query.trim() && appState === 'idle') { onRun(); } } }; const isRunning = appState !== 'idle'; return (
{/* Container: Flex items-end ensures button stays at bottom right as text grows */}