@@ -457,6 +457,7 @@ interface ChatEphemeralState {
457457 searchOpen : boolean ;
458458 searchQuery : string ;
459459 pinnedExpanded : boolean ;
460+ composerComposing : boolean ;
460461 historyRenderSessionKey : string | null ;
461462 historyRenderMessagesRef : unknown [ ] | null ;
462463 historyRenderMessageCount : number ;
@@ -482,6 +483,7 @@ function createChatEphemeralState(): ChatEphemeralState {
482483 searchOpen : false ,
483484 searchQuery : "" ,
484485 pinnedExpanded : false ,
486+ composerComposing : false ,
485487 historyRenderSessionKey : null ,
486488 historyRenderMessagesRef : null ,
487489 historyRenderMessageCount : 0 ,
@@ -1933,12 +1935,19 @@ export function renderChat(props: ChatProps) {
19331935 }
19341936 } ;
19351937
1936- const handleInput = ( e : Event ) => {
1937- const target = e . target as HTMLTextAreaElement ;
1938+ const syncComposerValue = (
1939+ target : HTMLTextAreaElement ,
1940+ options : { forceCommit ?: boolean } = { } ,
1941+ ) => {
19381942 adjustTextareaHeight ( target ) ;
19391943 draftMirror . value = target . value ;
19401944 const hostDraftNeeded = isBusy || showAbortableUi || props . queue . length > 0 ;
1941- if ( hostDraftNeeded || target . value . startsWith ( "/" ) || hasVisibleSlashMenuState ( ) ) {
1945+ if (
1946+ options . forceCommit ||
1947+ hostDraftNeeded ||
1948+ target . value . startsWith ( "/" ) ||
1949+ hasVisibleSlashMenuState ( )
1950+ ) {
19421951 commitComposerDraft ( props , target . value ) ;
19431952 }
19441953 updateSlashMenu ( target . value , requestUpdate ) ;
@@ -1952,6 +1961,21 @@ export function renderChat(props: ChatProps) {
19521961 props . onSend ( ) ;
19531962 syncComposerDraftAfterSend ( composerTextarea ) ;
19541963 } ;
1964+
1965+ const handleInput = ( e : InputEvent ) => {
1966+ const target = e . target as HTMLTextAreaElement ;
1967+ if ( vs . composerComposing || e . isComposing ) {
1968+ adjustTextareaHeight ( target ) ;
1969+ draftMirror . value = target . value ;
1970+ return ;
1971+ }
1972+ syncComposerValue ( target ) ;
1973+ } ;
1974+
1975+ const handleCompositionEnd = ( e : CompositionEvent ) => {
1976+ vs . composerComposing = false ;
1977+ syncComposerValue ( e . target as HTMLTextAreaElement , { forceCommit : true } ) ;
1978+ } ;
19551979 const slashMenuVisible = isSlashMenuVisible ( ) ;
19561980 const activeSlashMenuOptionId = getActiveSlashMenuOptionId ( ) ;
19571981 const activeSlashMenuOptionLabel = getActiveSlashMenuOptionLabel ( ) ;
@@ -2114,6 +2138,10 @@ export function renderChat(props: ChatProps) {
21142138 aria-describedby=${ SLASH_MENU_ACTIVE_ANNOUNCEMENT_ID }
21152139 @keydown=${ handleKeyDown }
21162140 @input=${ handleInput }
2141+ @compositionstart=${ ( ) => {
2142+ vs . composerComposing = true ;
2143+ } }
2144+ @compositionend=${ handleCompositionEnd }
21172145 @blur=${ handleBlur }
21182146 @paste=${ ( e : ClipboardEvent ) => handlePaste ( e , props ) }
21192147 placeholder=${ placeholder }
0 commit comments