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

Add ReactEditor.isComposing(editor) #4981

Merged
merged 2 commits into from
May 2, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 5 additions & 0 deletions .changeset/odd-cats-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'slate-react': patch
---

Add `ReactEditor.isComposing(editor)` to get the current `isComposing` state
4 changes: 4 additions & 0 deletions docs/libraries/slate-react.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ Get the current editor object from the React context. A version of useSlate that

A React and DOM-specific version of the `Editor` interface. All about translating between the DOM and Slate.

### `isComposing(editor: ReactEditor)`

Check if the user is currently composing inside the editor.

### `findKey(editor: ReactEditor, node: Node)`

Find a key for a Slate node.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { ReactEditor } from '../../plugin/react-editor'
import { Editor, Range, Transforms, Text } from 'slate'
import {
IS_COMPOSING,
IS_ON_COMPOSITION_END,
EDITOR_ON_COMPOSITION_TEXT,
} from '../../utils/weak-maps'
Expand Down Expand Up @@ -113,7 +112,7 @@ export class AndroidInputManager {
// If it is in composing or after `onCompositionend`, set `EDITOR_ON_COMPOSITION_TEXT` and return.
// Text will be inserted on compositionend event.
if (
IS_COMPOSING.get(this.editor) ||
ReactEditor.isComposing(this.editor) ||
IS_ON_COMPOSITION_END.get(this.editor)
) {
EDITOR_ON_COMPOSITION_TEXT.set(this.editor, insertedText)
Expand Down
39 changes: 26 additions & 13 deletions packages/slate-react/src/components/editable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import {
PLACEHOLDER_SYMBOL,
EDITOR_TO_WINDOW,
EDITOR_TO_USER_SELECTION,
IS_COMPOSING,
} from '../utils/weak-maps'
import { TRIPLE_CLICK } from '../utils/constants'

Expand Down Expand Up @@ -141,7 +142,6 @@ export const Editable = (props: EditableProps) => {
// Keep track of some state for the event handler logic.
const state = useMemo(
() => ({
isComposing: false,
hasInsertPrefixInCompositon: false,
isDraggingInternally: false,
isUpdatingSelection: false,
Expand All @@ -168,7 +168,11 @@ export const Editable = (props: EditableProps) => {
const root = ReactEditor.findDocumentOrShadowRoot(editor)
const domSelection = root.getSelection()

if (state.isComposing || !domSelection || !ReactEditor.isFocused(editor)) {
if (
ReactEditor.isComposing(editor) ||
!domSelection ||
!ReactEditor.isFocused(editor)
) {
return
}

Expand Down Expand Up @@ -268,7 +272,7 @@ export const Editable = (props: EditableProps) => {
const onDOMSelectionChange = useCallback(
throttle(() => {
if (
!state.isComposing &&
!ReactEditor.isComposing(editor) &&
!state.isUpdatingSelection &&
!state.isDraggingInternally
) {
Expand Down Expand Up @@ -516,8 +520,10 @@ export const Editable = (props: EditableProps) => {
// then we will abort because we're still composing and the selection
// won't be updated properly.
// https://www.w3.org/TR/input-events-2/
state.isComposing && setIsComposing(false)
state.isComposing = false
if (ReactEditor.isComposing(editor)) {
setIsComposing(false)
IS_COMPOSING.set(editor, false)
}
}

// use a weak comparison instead of 'instanceof' to allow
Expand Down Expand Up @@ -674,7 +680,7 @@ export const Editable = (props: EditableProps) => {
hasEditableTarget(editor, event.target)
) {
event.preventDefault()
if (!state.isComposing) {
if (!ReactEditor.isComposing(editor)) {
const text = (event as any).data as string
Editor.insertText(editor, text)
}
Expand Down Expand Up @@ -822,8 +828,10 @@ export const Editable = (props: EditableProps) => {
hasEditableTarget(editor, event.target) &&
!isEventHandled(event, attributes.onCompositionEnd)
) {
state.isComposing && setIsComposing(false)
state.isComposing = false
if (ReactEditor.isComposing(editor)) {
setIsComposing(false)
IS_COMPOSING.set(editor, false)
}

// COMPAT: In Chrome, `beforeinput` events for compositions
// aren't correct and never fire the "insertFromComposition"
Expand Down Expand Up @@ -867,8 +875,10 @@ export const Editable = (props: EditableProps) => {
hasEditableTarget(editor, event.target) &&
!isEventHandled(event, attributes.onCompositionUpdate)
) {
!state.isComposing && setIsComposing(true)
state.isComposing = true
if (!ReactEditor.isComposing(editor)) {
setIsComposing(true)
IS_COMPOSING.set(editor, true)
}
}
},
[attributes.onCompositionUpdate]
Expand Down Expand Up @@ -1096,14 +1106,17 @@ export const Editable = (props: EditableProps) => {
// COMPAT: The composition end event isn't fired reliably in all browsers,
// so we sometimes might end up stuck in a composition state even though we
// aren't composing any more.
if (state.isComposing && nativeEvent.isComposing === false) {
state.isComposing = false
if (
ReactEditor.isComposing(editor) &&
nativeEvent.isComposing === false
) {
IS_COMPOSING.set(editor, false)
setIsComposing(false)
}

if (
isEventHandled(event, attributes.onKeyDown) ||
state.isComposing
ReactEditor.isComposing(editor)
) {
return
}
Expand Down
9 changes: 9 additions & 0 deletions packages/slate-react/src/plugin/react-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
NODE_TO_PARENT,
EDITOR_TO_WINDOW,
EDITOR_TO_KEY_TO_ELEMENT,
IS_COMPOSING,
} from '../utils/weak-maps'
import {
DOMElement,
Expand Down Expand Up @@ -42,6 +43,14 @@ export interface ReactEditor extends BaseEditor {
}

export const ReactEditor = {
/**
* Check if the user is currently composing inside the editor.
*/

isComposing(editor: ReactEditor): boolean {
return !!IS_COMPOSING.get(editor)
},

/**
* Return the host window of the current editor.
*/
Expand Down