From 9079cd3b121aed6fa7d23f20914e4a792dcb63b7 Mon Sep 17 00:00:00 2001 From: matthewlipski Date: Wed, 17 Jul 2024 15:28:04 +0200 Subject: [PATCH 1/3] WIP fix for formatting toolbar appearing on drop --- .../FormattingToolbarPlugin.ts | 6 +++++ .../src/extensions/SideMenu/SideMenuPlugin.ts | 26 ++++++++++++++----- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/packages/core/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts b/packages/core/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts index 0db0daa6bc..56c04c7f97 100644 --- a/packages/core/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +++ b/packages/core/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts @@ -90,6 +90,11 @@ export class FormattingToolbarView implements PluginView { }; update(view: EditorView, oldState?: EditorState) { + // Delays the update to handle edge case with drag and drop, where the view + // is blurred asynchronously and happens only after the state update. + // Wrapping in a setTimeout gives enough time to wait for the blur event to + // occur before updating the toolbar. + // setTimeout(() => { const { state, composing } = view; const { doc, selection } = state; const isSame = @@ -139,6 +144,7 @@ export class FormattingToolbarView implements PluginView { return; } + // }); } destroy() { diff --git a/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts b/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts index 236cbea3f0..acf5614f2c 100644 --- a/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts +++ b/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts @@ -436,19 +436,33 @@ export class SideMenuView< this.isDragging = false; + const evt = new Event("drop") as any; + evt.clientY = event.clientY; + evt.dataTransfer = event.dataTransfer; + // evt.preventDefault = () => event.preventDefault(); + + // Checks if cursor is outside the editor contents if (!pos || pos.inside === -1) { - const evt = new Event("drop", event) as any; + // Creates duplicate event with cursor centered horizontally on the editor const editorBoundingBox = ( this.pmView.dom.firstChild! as HTMLElement ).getBoundingClientRect(); evt.clientX = editorBoundingBox.left + editorBoundingBox.width / 2; - evt.clientY = event.clientY; - evt.dataTransfer = event.dataTransfer; - evt.preventDefault = () => event.preventDefault(); + evt.synthetic = true; // prevent recursion - // console.log("dispatch fake drop"); - this.pmView.dom.dispatchEvent(evt); + } else { + // Creates duplicate event and prevents the original one from firing. + evt.clientX = event.clientX; + + event.preventDefault(); + event.stopPropagation(); } + + // Works + this.pmView.dom.dispatchEvent(evt); + + // Doesn't work + // setTimeout(() => this.pmView.dom.dispatchEvent(evt), 1000); }; /** From 5075d3e8b9942e0c9f7033a91af5fcc251939b5e Mon Sep 17 00:00:00 2001 From: matthewlipski Date: Wed, 17 Jul 2024 16:06:23 +0200 Subject: [PATCH 2/3] Re-added focus event handling for formatting toolbar --- .../FormattingToolbarPlugin.ts | 41 ++++++++++++++++++- .../src/extensions/SideMenu/SideMenuPlugin.ts | 26 +++--------- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/packages/core/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts b/packages/core/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts index 56c04c7f97..d92e1f4ebf 100644 --- a/packages/core/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +++ b/packages/core/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts @@ -58,6 +58,8 @@ export class FormattingToolbarView implements PluginView { pmView.dom.addEventListener("mouseup", this.viewMouseupHandler); pmView.dom.addEventListener("dragstart", this.dragHandler); pmView.dom.addEventListener("dragover", this.dragHandler); + pmView.dom.addEventListener("focus", this.focusHandler); + pmView.dom.addEventListener("blur", this.blurHandler); // Setting capture=true ensures that any parent container of the editor that // gets scrolled will trigger the scroll event. Scroll events do not bubble @@ -65,6 +67,41 @@ export class FormattingToolbarView implements PluginView { pmView.root.addEventListener("scroll", this.scrollHandler, true); } + focusHandler = () => { + this.update(this.pmView); + }; + + blurHandler = (event: FocusEvent) => { + if (this.preventHide) { + this.preventHide = false; + + return; + } + + const editorWrapper = this.pmView.dom.parentElement!; + + // Checks if the focus is moving to an element outside the editor. If it is, + // the toolbar is hidden. + if ( + // An element is clicked. + event && + event.relatedTarget && + // Element is inside the editor. + (editorWrapper === (event.relatedTarget as Node) || + editorWrapper.contains(event.relatedTarget as Node) || + (event.relatedTarget as HTMLElement).matches( + ".bn-ui-container, .bn-ui-container *" + )) + ) { + return; + } + + if (this.state?.show) { + this.state.show = false; + this.emitUpdate(); + } + }; + viewMousedownHandler = () => { this.preventShow = true; }; @@ -94,7 +131,6 @@ export class FormattingToolbarView implements PluginView { // is blurred asynchronously and happens only after the state update. // Wrapping in a setTimeout gives enough time to wait for the blur event to // occur before updating the toolbar. - // setTimeout(() => { const { state, composing } = view; const { doc, selection } = state; const isSame = @@ -144,7 +180,6 @@ export class FormattingToolbarView implements PluginView { return; } - // }); } destroy() { @@ -152,6 +187,8 @@ export class FormattingToolbarView implements PluginView { this.pmView.dom.removeEventListener("mouseup", this.viewMouseupHandler); this.pmView.dom.removeEventListener("dragstart", this.dragHandler); this.pmView.dom.removeEventListener("dragover", this.dragHandler); + this.pmView.dom.removeEventListener("focus", this.focusHandler); + this.pmView.dom.removeEventListener("blur", this.blurHandler); this.pmView.root.removeEventListener("scroll", this.scrollHandler, true); } diff --git a/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts b/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts index acf5614f2c..236cbea3f0 100644 --- a/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts +++ b/packages/core/src/extensions/SideMenu/SideMenuPlugin.ts @@ -436,33 +436,19 @@ export class SideMenuView< this.isDragging = false; - const evt = new Event("drop") as any; - evt.clientY = event.clientY; - evt.dataTransfer = event.dataTransfer; - // evt.preventDefault = () => event.preventDefault(); - - // Checks if cursor is outside the editor contents if (!pos || pos.inside === -1) { - // Creates duplicate event with cursor centered horizontally on the editor + const evt = new Event("drop", event) as any; const editorBoundingBox = ( this.pmView.dom.firstChild! as HTMLElement ).getBoundingClientRect(); evt.clientX = editorBoundingBox.left + editorBoundingBox.width / 2; - + evt.clientY = event.clientY; + evt.dataTransfer = event.dataTransfer; + evt.preventDefault = () => event.preventDefault(); evt.synthetic = true; // prevent recursion - } else { - // Creates duplicate event and prevents the original one from firing. - evt.clientX = event.clientX; - - event.preventDefault(); - event.stopPropagation(); + // console.log("dispatch fake drop"); + this.pmView.dom.dispatchEvent(evt); } - - // Works - this.pmView.dom.dispatchEvent(evt); - - // Doesn't work - // setTimeout(() => this.pmView.dom.dispatchEvent(evt), 1000); }; /** From 2aad14ad24208f9ec85f3d6d511e7abde77226d2 Mon Sep 17 00:00:00 2001 From: matthewlipski Date: Wed, 17 Jul 2024 16:25:24 +0200 Subject: [PATCH 3/3] Removed focus handler --- .../extensions/FormattingToolbar/FormattingToolbarPlugin.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/core/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts b/packages/core/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts index d92e1f4ebf..1a6d59515e 100644 --- a/packages/core/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts +++ b/packages/core/src/extensions/FormattingToolbar/FormattingToolbarPlugin.ts @@ -58,7 +58,6 @@ export class FormattingToolbarView implements PluginView { pmView.dom.addEventListener("mouseup", this.viewMouseupHandler); pmView.dom.addEventListener("dragstart", this.dragHandler); pmView.dom.addEventListener("dragover", this.dragHandler); - pmView.dom.addEventListener("focus", this.focusHandler); pmView.dom.addEventListener("blur", this.blurHandler); // Setting capture=true ensures that any parent container of the editor that @@ -67,10 +66,6 @@ export class FormattingToolbarView implements PluginView { pmView.root.addEventListener("scroll", this.scrollHandler, true); } - focusHandler = () => { - this.update(this.pmView); - }; - blurHandler = (event: FocusEvent) => { if (this.preventHide) { this.preventHide = false; @@ -187,7 +182,6 @@ export class FormattingToolbarView implements PluginView { this.pmView.dom.removeEventListener("mouseup", this.viewMouseupHandler); this.pmView.dom.removeEventListener("dragstart", this.dragHandler); this.pmView.dom.removeEventListener("dragover", this.dragHandler); - this.pmView.dom.removeEventListener("focus", this.focusHandler); this.pmView.dom.removeEventListener("blur", this.blurHandler); this.pmView.root.removeEventListener("scroll", this.scrollHandler, true);