mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-18 05:01:17 +02:00
Prioritize using Selection over Range to preserve direction (#3594)
accout for zero-width nodes
This commit is contained in:
@@ -145,13 +145,11 @@ export const Editable = (props: EditableProps) => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const newDomRange = selection && ReactEditor.toDOMRange(editor, selection)
|
|
||||||
|
|
||||||
// If the DOM selection is already correct, we're done.
|
// If the DOM selection is already correct, we're done.
|
||||||
if (
|
if (
|
||||||
hasDomSelection &&
|
hasDomSelection &&
|
||||||
newDomRange &&
|
selection &&
|
||||||
isRangeEqual(domSelection.getRangeAt(0), newDomRange)
|
Range.equals(ReactEditor.toSlateRange(editor, domSelection), selection)
|
||||||
) {
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -161,6 +159,8 @@ export const Editable = (props: EditableProps) => {
|
|||||||
state.isUpdatingSelection = true
|
state.isUpdatingSelection = true
|
||||||
domSelection.removeAllRanges()
|
domSelection.removeAllRanges()
|
||||||
|
|
||||||
|
const newDomRange = selection && ReactEditor.toDOMRange(editor, selection)
|
||||||
|
|
||||||
if (newDomRange) {
|
if (newDomRange) {
|
||||||
domSelection.addRange(newDomRange!)
|
domSelection.addRange(newDomRange!)
|
||||||
const leafEl = newDomRange.startContainer.parentElement!
|
const leafEl = newDomRange.startContainer.parentElement!
|
||||||
@@ -356,10 +356,6 @@ export const Editable = (props: EditableProps) => {
|
|||||||
const { activeElement } = window.document
|
const { activeElement } = window.document
|
||||||
const el = ReactEditor.toDOMNode(editor, editor)
|
const el = ReactEditor.toDOMNode(editor, editor)
|
||||||
const domSelection = window.getSelection()
|
const domSelection = window.getSelection()
|
||||||
const domRange =
|
|
||||||
domSelection &&
|
|
||||||
domSelection.rangeCount > 0 &&
|
|
||||||
domSelection.getRangeAt(0)
|
|
||||||
|
|
||||||
if (activeElement === el) {
|
if (activeElement === el) {
|
||||||
state.latestElement = activeElement
|
state.latestElement = activeElement
|
||||||
@@ -369,11 +365,11 @@ export const Editable = (props: EditableProps) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
domRange &&
|
domSelection &&
|
||||||
hasEditableTarget(editor, domRange.startContainer) &&
|
hasEditableTarget(editor, domSelection.anchorNode) &&
|
||||||
hasEditableTarget(editor, domRange.endContainer)
|
hasEditableTarget(editor, domSelection.focusNode)
|
||||||
) {
|
) {
|
||||||
const range = ReactEditor.toSlateRange(editor, domRange)
|
const range = ReactEditor.toSlateRange(editor, domSelection)
|
||||||
Transforms.select(editor, range)
|
Transforms.select(editor, range)
|
||||||
} else {
|
} else {
|
||||||
Transforms.deselect(editor)
|
Transforms.deselect(editor)
|
||||||
|
@@ -264,16 +264,30 @@ export const ReactEditor = {
|
|||||||
|
|
||||||
toDOMRange(editor: ReactEditor, range: Range): DOMRange {
|
toDOMRange(editor: ReactEditor, range: Range): DOMRange {
|
||||||
const { anchor, focus } = range
|
const { anchor, focus } = range
|
||||||
|
const isBackward = Range.isBackward(range)
|
||||||
const domAnchor = ReactEditor.toDOMPoint(editor, anchor)
|
const domAnchor = ReactEditor.toDOMPoint(editor, anchor)
|
||||||
const domFocus = Range.isCollapsed(range)
|
const domFocus = Range.isCollapsed(range)
|
||||||
? domAnchor
|
? domAnchor
|
||||||
: ReactEditor.toDOMPoint(editor, focus)
|
: ReactEditor.toDOMPoint(editor, focus)
|
||||||
|
|
||||||
const domRange = window.document.createRange()
|
const domRange = window.document.createRange()
|
||||||
const start = Range.isBackward(range) ? domFocus : domAnchor
|
const [startNode, startOffset] = isBackward ? domFocus : domAnchor
|
||||||
const end = Range.isBackward(range) ? domAnchor : domFocus
|
const [endNode, endOffset] = isBackward ? domAnchor : domFocus
|
||||||
domRange.setStart(start[0], start[1])
|
|
||||||
domRange.setEnd(end[0], end[1])
|
// A slate Point at zero-width Leaf always has an offset of 0 but a native DOM selection at
|
||||||
|
// zero-width node has an offset of 1 so we have to check if we are in a zero-width node and
|
||||||
|
// adjust the offset accordingly.
|
||||||
|
const startEl = (isDOMElement(startNode)
|
||||||
|
? startNode
|
||||||
|
: startNode.parentElement) as HTMLElement
|
||||||
|
const isStartAtZeroWidth = !!startEl.getAttribute('data-slate-zero-width')
|
||||||
|
const endEl = (isDOMElement(endNode)
|
||||||
|
? endNode
|
||||||
|
: endNode.parentElement) as HTMLElement
|
||||||
|
const isEndAtZeroWidth = !!endEl.getAttribute('data-slate-zero-width')
|
||||||
|
|
||||||
|
domRange.setStart(startNode, isStartAtZeroWidth ? 1 : startOffset)
|
||||||
|
domRange.setEnd(endNode, isEndAtZeroWidth ? 1 : endOffset)
|
||||||
return domRange
|
return domRange
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user