import { type ClipboardEventHandler, type KeyboardEvent, useLayoutEffect, useRef, } from 'react'; const DRAFT_MIN_HEIGHT_PX = 40; const DRAFT_MAX_HEIGHT_PX = 128; // for fallback on some browser function supportsNativeFieldSizing() { return ( typeof CSS !== 'undefined' && typeof CSS.supports === 'function' && CSS.supports('field-sizing', 'content') ); } function resizeFallbackTextarea(textarea: HTMLTextAreaElement) { textarea.style.height = 'auto'; const contentHeight = textarea.scrollHeight; const borderHeight = Math.max( 0, textarea.offsetHeight - textarea.clientHeight, ); const borderBoxContentHeight = contentHeight + borderHeight; const nextHeight = Math.min( Math.max(borderBoxContentHeight, DRAFT_MIN_HEIGHT_PX), DRAFT_MAX_HEIGHT_PX, ); textarea.style.height = `${nextHeight}px`; textarea.style.overflowY = borderBoxContentHeight > DRAFT_MAX_HEIGHT_PX ? 'auto' : 'hidden'; } export function EditorAgentDraftTextarea({ value, onChange, onPaste, }: { value: string; onChange: (value: string) => void; onPaste?: ClipboardEventHandler; }) { const textareaRef = useRef(null); useLayoutEffect(() => { const textarea = textareaRef.current; if (!textarea || supportsNativeFieldSizing()) { return; } resizeFallbackTextarea(textarea); }, [value]); useLayoutEffect(() => { const textarea = textareaRef.current; if (!textarea || supportsNativeFieldSizing()) { return undefined; } let previousWidth = textarea.getBoundingClientRect().width; const resizeWhenWidthChanges = (nextWidth: number) => { if (Math.abs(nextWidth - previousWidth) < 0.5) { return; } previousWidth = nextWidth; resizeFallbackTextarea(textarea); }; if (typeof ResizeObserver !== 'undefined') { const observer = new ResizeObserver((entries) => { const entry = entries[0]; if (entry) { resizeWhenWidthChanges(entry.contentRect.width); } }); observer.observe(textarea); return () => observer.disconnect(); } const handleWindowResize = () => { resizeWhenWidthChanges(textarea.getBoundingClientRect().width); }; window.addEventListener('resize', handleWindowResize); return () => window.removeEventListener('resize', handleWindowResize); }, []); const handleKeyDown = (event: KeyboardEvent) => { if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); event.currentTarget.form?.requestSubmit(); } }; return (