fix(editor): keep toolbar hidden through ime settle
This commit is contained in:
@@ -6,10 +6,31 @@ import type {
|
||||
} from '@blocknote/core'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
const COMPOSITION_SETTLE_MS = 250
|
||||
|
||||
function eventTargetsEditor(editorElement: Element, target: EventTarget | null) {
|
||||
return target instanceof Node && editorElement.contains(target)
|
||||
}
|
||||
|
||||
function focusTargetsEditor(editorElement: Element) {
|
||||
const activeElement = editorElement.ownerDocument.activeElement
|
||||
return activeElement instanceof Node && editorElement.contains(activeElement)
|
||||
}
|
||||
|
||||
function selectionTargetsEditor(editorElement: Element) {
|
||||
const anchorNode = editorElement.ownerDocument.getSelection()?.anchorNode
|
||||
return anchorNode instanceof Node && editorElement.contains(anchorNode)
|
||||
}
|
||||
|
||||
function compositionEventTargetsEditor(
|
||||
editorElement: Element,
|
||||
event: CompositionEvent,
|
||||
) {
|
||||
return eventTargetsEditor(editorElement, event.target)
|
||||
|| focusTargetsEditor(editorElement)
|
||||
|| selectionTargetsEditor(editorElement)
|
||||
}
|
||||
|
||||
export function useEditorComposing<
|
||||
BSchema extends BlockSchema,
|
||||
ISchema extends InlineContentSchema,
|
||||
@@ -17,41 +38,72 @@ export function useEditorComposing<
|
||||
>(editor: BlockNoteEditor<BSchema, ISchema, SSchema>) {
|
||||
const [isComposing, setIsComposing] = useState(false)
|
||||
const composingRef = useRef(false)
|
||||
const settleTimeoutRef = useRef<number | null>(null)
|
||||
const editorElement = editor.domElement ?? null
|
||||
|
||||
useEffect(() => {
|
||||
const clearSettleTimeout = () => {
|
||||
if (settleTimeoutRef.current === null) return
|
||||
window.clearTimeout(settleTimeoutRef.current)
|
||||
settleTimeoutRef.current = null
|
||||
}
|
||||
|
||||
const updateComposing = (nextIsComposing: boolean) => {
|
||||
if (composingRef.current === nextIsComposing) return
|
||||
composingRef.current = nextIsComposing
|
||||
setIsComposing(nextIsComposing)
|
||||
}
|
||||
|
||||
const startComposing = () => {
|
||||
clearSettleTimeout()
|
||||
updateComposing(true)
|
||||
}
|
||||
|
||||
const finishComposing = () => {
|
||||
clearSettleTimeout()
|
||||
settleTimeoutRef.current = window.setTimeout(() => {
|
||||
settleTimeoutRef.current = null
|
||||
updateComposing(false)
|
||||
}, COMPOSITION_SETTLE_MS)
|
||||
}
|
||||
|
||||
clearSettleTimeout()
|
||||
updateComposing(false)
|
||||
|
||||
if (!editorElement) return
|
||||
|
||||
const handleCompositionStart = (event: CompositionEvent) => {
|
||||
if (!eventTargetsEditor(editorElement, event.target)) return
|
||||
updateComposing(true)
|
||||
if (!compositionEventTargetsEditor(editorElement, event)) return
|
||||
startComposing()
|
||||
}
|
||||
|
||||
const handleCompositionUpdate = (event: CompositionEvent) => {
|
||||
if (!compositionEventTargetsEditor(editorElement, event)) return
|
||||
startComposing()
|
||||
}
|
||||
|
||||
const handleCompositionEnd = (event: CompositionEvent) => {
|
||||
if (
|
||||
!composingRef.current
|
||||
&& !eventTargetsEditor(editorElement, event.target)
|
||||
&& !compositionEventTargetsEditor(editorElement, event)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
updateComposing(false)
|
||||
finishComposing()
|
||||
}
|
||||
|
||||
document.addEventListener('compositionstart', handleCompositionStart, true)
|
||||
document.addEventListener('compositionupdate', handleCompositionUpdate, true)
|
||||
document.addEventListener('compositionend', handleCompositionEnd, true)
|
||||
document.addEventListener('compositioncancel', handleCompositionEnd, true)
|
||||
|
||||
return () => {
|
||||
clearSettleTimeout()
|
||||
document.removeEventListener('compositionstart', handleCompositionStart, true)
|
||||
document.removeEventListener('compositionupdate', handleCompositionUpdate, true)
|
||||
document.removeEventListener('compositionend', handleCompositionEnd, true)
|
||||
document.removeEventListener('compositioncancel', handleCompositionEnd, true)
|
||||
}
|
||||
}, [editorElement])
|
||||
|
||||
|
||||
Reference in New Issue
Block a user