Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix(editable component): reselect the range created by triple click #4455

Merged
merged 4 commits into from
Aug 28, 2021
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions packages/slate-react/src/plugin/react-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,44 @@ export const ReactEditor = {
anchorOffset = domRange.anchorOffset
focusNode = domRange.focusNode
focusOffset = domRange.focusOffset
// When triple clicking a block, Chrome will return a selection object whose
// focus node is the next element sibling and focusOffset is 0.
// This will highlight the corresponding toolbar button for the sibling
// block even though users just want to target the previous block.
// (2021/08/24)
// Within the context of Slate and Chrome, if anchor and focus nodes don't have
// the same nodeValue and focusOffset is 0, then it's definitely a triple click
// behaviour.
if (
IS_CHROME &&
anchorNode?.nodeValue !== focusNode?.nodeValue &&
domRange.focusOffset === 0
) {
// If an anchorNode is an element node when triple clicked, then the focusNode
// should also be the same as anchorNode when triple clicked.
if (anchorNode!.nodeType === 1) {
focusNode = anchorNode
} else {
// Otherwise, anchorNode is a text node and we need to
// - climb up the DOM tree to get the farthest element node that receives
// triple click. It should have atribute 'data-slate-node' = "element"
// - get the last child of that element node
// - climb down the DOM tree to get the text node of the last child
// - this is also the end of the selection aka the focusNode
const anchorElement = anchorNode!.parentNode as HTMLElement
const tripleClickedBlock = anchorElement.closest(
'[data-slate-node="element"]'
)
const focusElement = tripleClickedBlock!.lastElementChild
// Get the element node that holds the focus text node
const innermostFocusElement = focusElement!.querySelector(
'[data-slate-string]'
)
const lastTextNode = innermostFocusElement!.childNodes[0]
focusNode = lastTextNode
}
}

// COMPAT: There's a bug in chrome that always returns `true` for
// `isCollapsed` for a Selection that comes from a ShadowRoot.
// (2020/08/08)
Expand Down