Skip to content

Commit

Permalink
add suppressThrow to ReactEditors toDOMRange and toDOMPoint
Browse files Browse the repository at this point in the history
  • Loading branch information
markacola committed Nov 30, 2023
1 parent 0312531 commit 1eda475
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/twelve-mails-warn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'slate-react': patch
---

Suppressed error throwing on selection processing for externally updated DOM content
8 changes: 7 additions & 1 deletion packages/slate-react/src/components/editable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,13 @@ export const Editable = (props: EditableProps) => {
state.isUpdatingSelection = true

const newDomRange: DOMRange | null =
selection && ReactEditor.toDOMRange(editor, selection)
selection &&
ReactEditor.toDOMRange(editor, selection, {
// Even when we have a selection in Slate, the DOM might have moved
// underneath us, so we have to check that the anchor and focus nodes
// still exist.
suppressThrow: true,
})

if (newDomRange) {
if (ReactEditor.isComposing(editor) && !IS_ANDROID) {
Expand Down
53 changes: 47 additions & 6 deletions packages/slate-react/src/plugin/react-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,11 @@ export interface ReactEditorInterface {
/**
* Find a native DOM selection point from a Slate point.
*/
toDOMPoint: (editor: ReactEditor, point: Point) => DOMPoint
toDOMPoint: <T extends boolean = false>(
editor: ReactEditor,
point: Point,
options?: { suppressThrow: T }
) => T extends true ? DOMPoint | null : DOMPoint

/**
* Find a native DOM range from a Slate `range`.
Expand All @@ -227,7 +231,11 @@ export interface ReactEditorInterface {
* there is no way to create a reverse DOM Range using Range.setStart/setEnd
* according to https://dom.spec.whatwg.org/#concept-range-bp-set.
*/
toDOMRange: (editor: ReactEditor, range: Range) => DOMRange
toDOMRange: <T extends boolean = false>(
editor: ReactEditor,
range: Range,
options?: { suppressThrow: T }
) => T extends true ? DOMRange | null : DOMRange

/**
* Find a Slate node from a native DOM `element`.
Expand Down Expand Up @@ -558,7 +566,11 @@ export const ReactEditor: ReactEditorInterface = {
return domNode
},

toDOMPoint: (editor, point) => {
toDOMPoint: <T extends boolean>(
editor: ReactEditor,
point: Point,
options?: { suppressThrow: T }
) => {
const [node] = Editor.node(editor, point.path)
const el = ReactEditor.toDOMNode(editor, node)
let domPoint: DOMPoint | undefined
Expand Down Expand Up @@ -620,6 +632,10 @@ export const ReactEditor: ReactEditorInterface = {
}

if (!domPoint) {
const suppressThrow = options?.suppressThrow
if (suppressThrow === true) {
return null as T extends true ? DOMPoint | null : DOMPoint
}
throw new Error(
`Cannot resolve a DOM point from Slate point: ${Scrubber.stringify(
point
Expand All @@ -630,13 +646,38 @@ export const ReactEditor: ReactEditorInterface = {
return domPoint
},

toDOMRange: (editor, range) => {
toDOMRange: <T extends boolean>(
editor: ReactEditor,
range: Range,
options?: { suppressThrow: T }
) => {
const { anchor, focus } = range
const isBackward = Range.isBackward(range)
const domAnchor = ReactEditor.toDOMPoint(editor, anchor)
const domAnchor = ReactEditor.toDOMPoint(editor, anchor, options)
if (!domAnchor) {
if (options?.suppressThrow) {
return null as T extends true ? DOMRange | null : DOMRange
}
throw new Error(
`Cannot resolve a DOM range from Slate range: ${Scrubber.stringify(
range
)}`
)
}

const domFocus = Range.isCollapsed(range)
? domAnchor
: ReactEditor.toDOMPoint(editor, focus)
: ReactEditor.toDOMPoint(editor, focus, options)
if (!domFocus) {
if (options?.suppressThrow) {
return null as T extends true ? DOMRange | null : DOMRange
}
throw new Error(
`Cannot resolve a DOM range from Slate range: ${Scrubber.stringify(
range
)}`
)
}

const window = ReactEditor.getWindow(editor)
const domRange = window.document.createRange()
Expand Down

0 comments on commit 1eda475

Please sign in to comment.