1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-01-29 19:27:43 +01:00

Restore user selection after beforeinput with target range (#4919)

* Restore user selection after beforeinput with target range

* Add changeset
This commit is contained in:
Eric Meier 2022-03-31 12:18:23 +01:00 committed by GitHub
parent ce63a08c8e
commit 7de7cdcf56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 18 deletions

View File

@ -0,0 +1,5 @@
---
'slate-react': patch
---
Restore user selection after applying beforeinput with target range

View File

@ -8,6 +8,7 @@ import {
Text,
Transforms,
Path,
RangeRef,
} from 'slate'
import getDirection from 'direction'
import debounce from 'lodash/debounce'
@ -51,6 +52,7 @@ import {
IS_FOCUSED,
PLACEHOLDER_SYMBOL,
EDITOR_TO_WINDOW,
EDITOR_TO_USER_SELECTION,
} from '../utils/weak-maps'
type DeferredOperation = () => void
@ -399,7 +401,14 @@ export const Editable = (props: EditableProps) => {
})
if (!selection || !Range.equals(selection, range)) {
const selectionRef =
editor.selection && Editor.rangeRef(editor, editor.selection)
Transforms.select(editor, range)
if (selectionRef) {
EDITOR_TO_USER_SELECTION.set(editor, selectionRef)
}
}
}
}
@ -523,6 +532,17 @@ export const Editable = (props: EditableProps) => {
break
}
}
// Restore the actual user section if nothing manually set it.
const toRestore = EDITOR_TO_USER_SELECTION.get(editor)?.unref()
EDITOR_TO_USER_SELECTION.delete(editor)
if (
toRestore &&
(!editor.selection || !Range.equals(editor.selection, toRestore))
) {
Transforms.select(editor, toRestore)
}
}
},
[readOnly, propsOnDOMBeforeInput]
@ -1385,23 +1405,6 @@ const defaultScrollSelectionIntoView = (
}
}
/**
* Check if two DOM range objects are equal.
*/
export const isRangeEqual = (a: DOMRange, b: DOMRange) => {
return (
(a.startContainer === b.startContainer &&
a.startOffset === b.startOffset &&
a.endContainer === b.endContainer &&
a.endOffset === b.endOffset) ||
(a.startContainer === b.endContainer &&
a.startOffset === b.endOffset &&
a.endContainer === b.startContainer &&
a.endOffset === b.startOffset)
)
}
/**
* Check if the target is in the editor.
*/

View File

@ -7,6 +7,7 @@ import {
EDITOR_TO_KEY_TO_ELEMENT,
EDITOR_TO_ON_CHANGE,
NODE_TO_KEY,
EDITOR_TO_USER_SELECTION,
} from '../utils/weak-maps'
import {
isDOMText,
@ -74,6 +75,13 @@ export const withReact = <T extends Editor>(editor: T) => {
break
}
case 'set_selection': {
// Selection was manually set, don't restore the user selection after the change.
EDITOR_TO_USER_SELECTION.get(editor)?.unref()
EDITOR_TO_USER_SELECTION.delete(editor)
break
}
case 'insert_node':
case 'remove_node': {
matches.push(...getMatches(e, Path.parent(op.path)))

View File

@ -1,4 +1,4 @@
import { Ancestor, Editor, Node } from 'slate'
import { Ancestor, Editor, Node, RangeRef } from 'slate'
import { Key } from './key'
import { TextInsertion } from '../components/android/diff-text'
@ -36,6 +36,8 @@ export const IS_CLICKING: WeakMap<Editor, boolean> = new WeakMap()
export const IS_COMPOSING: WeakMap<Editor, boolean> = new WeakMap()
export const IS_ON_COMPOSITION_END: WeakMap<Editor, boolean> = new WeakMap()
export const EDITOR_TO_USER_SELECTION: WeakMap<Editor, RangeRef> = new WeakMap()
/**
* Weak maps for saving text on composition stage.
*/