diff --git a/WebExample/__tests__/utils.ts b/WebExample/__tests__/utils.ts index 2085afad..dfc97bd8 100644 --- a/WebExample/__tests__/utils.ts +++ b/WebExample/__tests__/utils.ts @@ -11,7 +11,13 @@ const setupInput = async (page: Page, action?: 'clear' | 'reset') => { }; const getCursorPosition = async (elementHandle: Locator) => { - const inputSelectionHandle = await elementHandle.evaluateHandle((div: HTMLInputElement) => ({start: div.selectionStart, end: div.selectionEnd})); + const inputSelectionHandle = await elementHandle.evaluateHandle( + ( + div: HTMLInputElement & { + selection: {start: number; end: number}; + }, + ) => div.selection, + ); const selection = await inputSelectionHandle.jsonValue(); return selection; }; diff --git a/src/MarkdownTextInput.web.tsx b/src/MarkdownTextInput.web.tsx index 01de8eb1..cb1bac2d 100644 --- a/src/MarkdownTextInput.web.tsx +++ b/src/MarkdownTextInput.web.tsx @@ -57,6 +57,7 @@ let focusTimeout: NodeJS.Timeout | null = null; type MarkdownTextInputElement = HTMLDivElement & HTMLInputElement & { tree: TreeNode; + selection: Selection; }; type HTMLMarkdownElement = HTMLElement & { @@ -233,14 +234,15 @@ const MarkdownTextInput = React.forwardRef( ); const updateRefSelectionVariables = useCallback((newSelection: Selection) => { + if (!divRef.current) { + return; + } const {start, end} = newSelection; - const markdownHTMLInput = divRef.current as HTMLInputElement; - markdownHTMLInput.selectionStart = start; - markdownHTMLInput.selectionEnd = end; + divRef.current.selection = {start, end}; }, []); const updateSelection = useCallback( - (e: SyntheticEvent | null = null, predefinedSelection: Selection | null = null) => { + (e: SyntheticEvent, predefinedSelection: Selection | null = null) => { if (!divRef.current) { return; } @@ -250,9 +252,7 @@ const MarkdownTextInput = React.forwardRef( updateRefSelectionVariables(newSelection); contentSelection.current = newSelection; - if (e) { - handleSelectionChange(e); - } + handleSelectionChange(e); } }, [handleSelectionChange, updateRefSelectionVariables], @@ -382,9 +382,8 @@ const MarkdownTextInput = React.forwardRef( (e.nativeEvent as MarkdownNativeEvent).inputType = 'pasteText'; handleOnChangeText(e); - updateSelection(e); }, - [handleOnChangeText, updateSelection], + [handleOnChangeText], ); const handleKeyPress = useCallback( @@ -421,8 +420,6 @@ const MarkdownTextInput = React.forwardRef( onKeyPress(event); } - updateSelection(event as unknown as SyntheticEvent); - if ( e.key === 'Enter' && // Do not call submit if composition is occuring. @@ -443,7 +440,7 @@ const MarkdownTextInput = React.forwardRef( } } }, - [multiline, blurOnSubmit, setEventProps, onKeyPress, updateSelection, handleOnChangeText, onSubmitEditing, insertText], + [multiline, blurOnSubmit, setEventProps, onKeyPress, handleOnChangeText, onSubmitEditing, insertText], ); const handleFocus: FocusEventHandler = useCallback( @@ -459,7 +456,6 @@ const MarkdownTextInput = React.forwardRef( const valueLength = value ? value.length : divRef.current.value.length; setCursorPosition(divRef.current, valueLength, null); } - updateSelection(event, contentSelection.current); } if (onFocus) { @@ -485,7 +481,7 @@ const MarkdownTextInput = React.forwardRef( } } }, - [clearTextOnFocus, onFocus, selectTextOnFocus, setEventProps, updateSelection, value], + [clearTextOnFocus, onFocus, selectTextOnFocus, setEventProps, value], ); const handleBlur: FocusEventHandler = useCallback( @@ -503,14 +499,13 @@ const MarkdownTextInput = React.forwardRef( const handleClick = useCallback( (e: MouseEvent) => { - updateSelection(e); if (!onClick || !divRef.current) { return; } (e.target as HTMLInputElement).value = divRef.current.value; onClick(e); }, - [onClick, updateSelection], + [onClick], ); const handleCopy: ClipboardEventHandler = useCallback((e) => { @@ -660,7 +655,6 @@ const MarkdownTextInput = React.forwardRef( onKeyDown={handleKeyPress} onCompositionStart={startComposition} onCompositionEnd={endComposition} - onKeyUp={updateSelection} onInput={handleOnChangeText} onClick={handleClick} onFocus={handleFocus} @@ -672,6 +666,7 @@ const MarkdownTextInput = React.forwardRef( spellCheck={spellCheck} dir={dir} inputMode={inputMode} + onSelect={updateSelection} /> ); }, diff --git a/src/web/utils/cursorUtils.ts b/src/web/utils/cursorUtils.ts index e0b4e23b..9ad986c9 100644 --- a/src/web/utils/cursorUtils.ts +++ b/src/web/utils/cursorUtils.ts @@ -45,6 +45,10 @@ function setCursorPosition(target: MarkdownTextInputElement, startIndex: number, selection.setBaseAndExtent(range.startContainer, range.startOffset, range.endContainer, range.endOffset); } + // Update the focused elements zIndex to make sure they are on top and the cursor is beeing set correctly + startTreeNode.element.style.zIndex = '1'; + endTreeNode.element.style.zIndex = '1'; + scrollIntoView(startTreeNode); }