@@ -5,15 +5,18 @@ import { MouseDoubleClickEvent, MouseClickEvent } from '../events'
55type GlobalState = {
66 activeElements : Map < HTMLInputElement , TreeNode >
77 requestTimer : any
8+ isComposition : boolean
89}
910
10- function placeCaretAtEnd ( el : HTMLInputElement ) {
11+ function placeCaretAtEnd ( el : HTMLInputElement , isCollapse : boolean ) {
1112 const currentSelection = window . getSelection ( )
1213 if ( currentSelection . containsNode ( el ) ) return
1314 el . focus ( )
1415 const range = document . createRange ( )
1516 range . selectNodeContents ( el )
16- range . collapse ( false )
17+ if ( ! isCollapse ) {
18+ range . collapse ( false )
19+ }
1720 const sel = window . getSelection ( )
1821 sel . removeAllRanges ( )
1922 sel . addRange ( range )
@@ -23,6 +26,7 @@ export const useContentEditableEffect = (engine: Engine) => {
2326 const globalState : GlobalState = {
2427 activeElements : new Map ( ) ,
2528 requestTimer : null ,
29+ isComposition : false ,
2630 }
2731
2832 function onKeyDownHandler ( event : KeyboardEvent ) {
@@ -40,18 +44,35 @@ export const useContentEditableEffect = (engine: Engine) => {
4044 const target = event . target as Element
4145 clearTimeout ( globalState . requestTimer )
4246 globalState . requestTimer = setTimeout ( ( ) => {
47+ if ( globalState . isComposition ) return
4348 Path . setIn (
4449 node . props ,
4550 this . getAttribute ( engine . props . contentEditableAttrName ) ,
4651 target ?. textContent
4752 )
4853 setTimeout ( ( ) => {
49- placeCaretAtEnd ( this )
54+ placeCaretAtEnd ( this , window . getSelection ( ) . isCollapsed )
5055 } , 16 )
51- } , 300 )
56+ } , 1000 )
57+ }
58+ }
59+
60+ function onCompositionHandler ( event : CompositionEvent ) {
61+ if ( event . type === 'compositionend' ) {
62+ globalState . isComposition = false
63+ onInputHandler ( event as any )
64+ } else {
65+ clearTimeout ( globalState . requestTimer )
66+ globalState . isComposition = true
5267 }
5368 }
5469
70+ function onPastHandler ( event : ClipboardEvent ) {
71+ event . preventDefault ( )
72+ const text = event . clipboardData . getData ( 'text' )
73+ this . textContent = text
74+ }
75+
5576 function findTargetNodeId ( element : Element ) {
5677 if ( ! element ) return
5778 const nodeId = element . getAttribute (
@@ -76,6 +97,10 @@ export const useContentEditableEffect = (engine: Engine) => {
7697 globalState . activeElements . delete ( element )
7798 element . setAttribute ( 'contenteditable' , 'false' )
7899 element . removeEventListener ( 'input' , onInputHandler )
100+ element . removeEventListener ( 'compositionstart' , onCompositionHandler )
101+ element . removeEventListener ( 'compositionupdate' , onCompositionHandler )
102+ element . removeEventListener ( 'compositionend' , onCompositionHandler )
103+ element . removeEventListener ( 'past' , onPastHandler )
79104 } )
80105 } )
81106
@@ -97,8 +122,21 @@ export const useContentEditableEffect = (engine: Engine) => {
97122 editableElement . setAttribute ( 'contenteditable' , 'true' )
98123 editableElement . focus ( )
99124 editableElement . addEventListener ( 'input' , onInputHandler )
125+ editableElement . addEventListener (
126+ 'compositionstart' ,
127+ onCompositionHandler
128+ )
129+ editableElement . addEventListener (
130+ 'compositionupdate' ,
131+ onCompositionHandler
132+ )
133+ editableElement . addEventListener (
134+ 'compositionend' ,
135+ onCompositionHandler
136+ )
100137 editableElement . addEventListener ( 'keydown' , onKeyDownHandler )
101- placeCaretAtEnd ( editableElement )
138+ editableElement . addEventListener ( 'paste' , onPastHandler )
139+ placeCaretAtEnd ( editableElement , false )
102140 }
103141 }
104142 }
0 commit comments