@@ -46,6 +46,8 @@ const RESOLVE_DELAY = 20;
4646let resolved = false ;
4747let stillComposing = false ;
4848let domObserver = null ;
49+ let beforeInputData = null ;
50+ let compositionEndData = null ;
4951
5052function startDOMObserver ( editor : DraftEditor ) {
5153 if ( ! domObserver ) {
@@ -55,11 +57,14 @@ function startDOMObserver(editor: DraftEditor) {
5557}
5658
5759const DraftEditorCompositionHandler = {
60+ onBeforeInput ( _editor : DraftEditor , e : SyntheticInputEvent < > ) : void {
61+ beforeInputData = ( beforeInputData || '' ) + e . data ;
62+ } ,
5863 /**
5964 * A `compositionstart` event has fired while we're still in composition
6065 * mode. Continue the current composition session to prevent a re-render.
6166 */
62- onCompositionStart : function ( editor : DraftEditor ) : void {
67+ onCompositionStart ( editor : DraftEditor ) : void {
6368 stillComposing = true ;
6469 startDOMObserver ( editor ) ;
6570 } ,
@@ -78,9 +83,13 @@ const DraftEditorCompositionHandler = {
7883 * twice could break the DOM, we only use the first event. Example: Arabic
7984 * Google Input Tools on Windows 8.1 fires `compositionend` three times.
8085 */
81- onCompositionEnd : function ( editor : DraftEditor ) : void {
86+ onCompositionEnd ( editor : DraftEditor , e : SyntheticInputEvent < > ) : void {
8287 resolved = false ;
8388 stillComposing = false ;
89+
90+ // Use e.data from the first compositionend event seen
91+ compositionEndData = compositionEndData ?? e ?. data ?? null ;
92+
8493 setTimeout ( ( ) => {
8594 if ( ! resolved ) {
8695 DraftEditorCompositionHandler . resolveComposition ( editor ) ;
@@ -95,7 +104,7 @@ const DraftEditorCompositionHandler = {
95104 * the arrow keys are used to commit, prevent default so that the cursor
96105 * doesn't move, otherwise it will jump back noticeably on re-render.
97106 */
98- onKeyDown : function ( editor : DraftEditor , e : SyntheticKeyboardEvent < > ) : void {
107+ onKeyDown ( editor : DraftEditor , e : SyntheticKeyboardEvent < > ) : void {
99108 if ( ! stillComposing ) {
100109 // If a keydown event is received after compositionend but before the
101110 // 20ms timer expires (ex: type option-E then backspace, or type A then
@@ -116,7 +125,7 @@ const DraftEditorCompositionHandler = {
116125 * characters that we do not want. `preventDefault` allows the composition
117126 * to be committed while preventing the extra characters.
118127 */
119- onKeyPress : function ( editor : DraftEditor , e : SyntheticKeyboardEvent < > ) : void {
128+ onKeyPress ( _editor : DraftEditor , e : SyntheticKeyboardEvent < > ) : void {
120129 if ( e . which === Keys . RETURN ) {
121130 e . preventDefault ( ) ;
122131 }
@@ -137,7 +146,7 @@ const DraftEditorCompositionHandler = {
137146 * Resetting innerHTML will move focus to the beginning of the editor,
138147 * so we update to force it back to the correct place.
139148 */
140- resolveComposition : function ( editor : DraftEditor ) : void {
149+ resolveComposition ( editor : DraftEditor ) : void {
141150 if ( stillComposing ) {
142151 return ;
143152 }
@@ -146,12 +155,36 @@ const DraftEditorCompositionHandler = {
146155 domObserver = null ;
147156 resolved = true ;
148157
158+ const composedChars = beforeInputData ?? compositionEndData ;
159+ beforeInputData = null ;
160+ compositionEndData = null ;
161+
149162 let editorState = EditorState . set ( editor . _latestEditorState , {
150163 inCompositionMode : false ,
151164 } ) ;
152165
153166 editor . exitCurrentMode ( ) ;
154167
168+ if ( composedChars != null ) {
169+ const currentStyle = editorState . getCurrentInlineStyle ( ) ;
170+ const entityKey = getEntityKeyForSelection (
171+ editorState . getCurrentContent ( ) ,
172+ editorState . getSelection ( ) ,
173+ ) ;
174+ // If characters have been composed, re-rendering with the update
175+ // is sufficient to reset the editor.
176+ const contentState = DraftModifier . replaceText (
177+ editorState . getCurrentContent ( ) ,
178+ editorState . getSelection ( ) ,
179+ composedChars ,
180+ currentStyle ,
181+ entityKey ,
182+ ) ;
183+ editor . update (
184+ EditorState . push ( editorState , contentState , 'insert-characters' ) ,
185+ ) ;
186+ }
187+
155188 if ( ! mutations . size ) {
156189 editor . update ( editorState ) ;
157190 return ;
0 commit comments