mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-11 09:43:58 +02: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:
5
.changeset/late-monkeys-hug.md
Normal file
5
.changeset/late-monkeys-hug.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'slate-react': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Restore user selection after applying beforeinput with target range
|
@@ -8,6 +8,7 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
Transforms,
|
Transforms,
|
||||||
Path,
|
Path,
|
||||||
|
RangeRef,
|
||||||
} from 'slate'
|
} from 'slate'
|
||||||
import getDirection from 'direction'
|
import getDirection from 'direction'
|
||||||
import debounce from 'lodash/debounce'
|
import debounce from 'lodash/debounce'
|
||||||
@@ -51,6 +52,7 @@ import {
|
|||||||
IS_FOCUSED,
|
IS_FOCUSED,
|
||||||
PLACEHOLDER_SYMBOL,
|
PLACEHOLDER_SYMBOL,
|
||||||
EDITOR_TO_WINDOW,
|
EDITOR_TO_WINDOW,
|
||||||
|
EDITOR_TO_USER_SELECTION,
|
||||||
} from '../utils/weak-maps'
|
} from '../utils/weak-maps'
|
||||||
|
|
||||||
type DeferredOperation = () => void
|
type DeferredOperation = () => void
|
||||||
@@ -399,7 +401,14 @@ export const Editable = (props: EditableProps) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!selection || !Range.equals(selection, range)) {
|
if (!selection || !Range.equals(selection, range)) {
|
||||||
|
const selectionRef =
|
||||||
|
editor.selection && Editor.rangeRef(editor, editor.selection)
|
||||||
|
|
||||||
Transforms.select(editor, range)
|
Transforms.select(editor, range)
|
||||||
|
|
||||||
|
if (selectionRef) {
|
||||||
|
EDITOR_TO_USER_SELECTION.set(editor, selectionRef)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -523,6 +532,17 @@ export const Editable = (props: EditableProps) => {
|
|||||||
break
|
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]
|
[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.
|
* Check if the target is in the editor.
|
||||||
*/
|
*/
|
||||||
|
@@ -7,6 +7,7 @@ import {
|
|||||||
EDITOR_TO_KEY_TO_ELEMENT,
|
EDITOR_TO_KEY_TO_ELEMENT,
|
||||||
EDITOR_TO_ON_CHANGE,
|
EDITOR_TO_ON_CHANGE,
|
||||||
NODE_TO_KEY,
|
NODE_TO_KEY,
|
||||||
|
EDITOR_TO_USER_SELECTION,
|
||||||
} from '../utils/weak-maps'
|
} from '../utils/weak-maps'
|
||||||
import {
|
import {
|
||||||
isDOMText,
|
isDOMText,
|
||||||
@@ -74,6 +75,13 @@ export const withReact = <T extends Editor>(editor: T) => {
|
|||||||
break
|
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 'insert_node':
|
||||||
case 'remove_node': {
|
case 'remove_node': {
|
||||||
matches.push(...getMatches(e, Path.parent(op.path)))
|
matches.push(...getMatches(e, Path.parent(op.path)))
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Ancestor, Editor, Node } from 'slate'
|
import { Ancestor, Editor, Node, RangeRef } from 'slate'
|
||||||
import { Key } from './key'
|
import { Key } from './key'
|
||||||
import { TextInsertion } from '../components/android/diff-text'
|
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_COMPOSING: WeakMap<Editor, boolean> = new WeakMap()
|
||||||
export const IS_ON_COMPOSITION_END: 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.
|
* Weak maps for saving text on composition stage.
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user