fix: don’t initialize tippy on requestAnimationFrame to avoid race conditions (#1820)

Instead of initializting tippy when
the bubble menu and floating menu plugins are initialized,
defer the initialization of tippy to the moment when
the the editor should display the floating or bubble menu

Co-authored-by: Enrique Alcantara <ealcantara@gitlab.com>
This commit is contained in:
Enrique
2021-09-07 14:46:45 -04:00
committed by GitHub
parent 67ce72a9ee
commit ca3763d3c2
2 changed files with 56 additions and 36 deletions

View File

@@ -31,6 +31,8 @@ export class FloatingMenuView {
public tippy: Instance | undefined
public tippyOptions?: Partial<Props>
public shouldShow: Exclude<FloatingMenuPluginProps['shouldShow'], null> = ({ state }) => {
const { selection } = state
const { $anchor, empty } = selection
@@ -50,7 +52,7 @@ export class FloatingMenuView {
editor,
element,
view,
tippyOptions,
tippyOptions = {},
shouldShow,
}: FloatingMenuViewProps) {
this.editor = editor
@@ -64,13 +66,10 @@ export class FloatingMenuView {
this.element.addEventListener('mousedown', this.mousedownHandler, { capture: true })
this.editor.on('focus', this.focusHandler)
this.editor.on('blur', this.blurHandler)
this.tippyOptions = tippyOptions
// Detaches menu content from its current parent
this.element.remove()
this.element.style.visibility = 'visible'
// We create tippy asynchronously to make sure that `editor.options.element`
// has already been moved to the right position in the DOM
requestAnimationFrame(() => {
this.createTooltip(tippyOptions)
})
}
mousedownHandler = () => {
@@ -99,17 +98,26 @@ export class FloatingMenuView {
this.hide()
}
createTooltip(options: Partial<Props> = {}) {
this.tippy = tippy(this.editor.options.element, {
duration: 0,
getReferenceClientRect: null,
content: this.element,
interactive: true,
trigger: 'manual',
placement: 'right',
hideOnClick: 'toggle',
...options,
})
createTooltip() {
if (this.tippy) {
return
}
const { element: editorElement } = this.editor.options
// Wait until editor element is attached to the document
if (editorElement.parentElement) {
this.tippy = tippy(editorElement, {
duration: 0,
getReferenceClientRect: null,
content: this.element,
interactive: true,
trigger: 'manual',
placement: 'right',
hideOnClick: 'toggle',
...this.tippyOptions,
})
}
}
update(view: EditorView, oldState?: EditorState) {
@@ -122,6 +130,8 @@ export class FloatingMenuView {
return
}
this.createTooltip()
const shouldShow = this.shouldShow?.({
editor: this.editor,
view,