From 87390b924e91ce1ee2de5d38020e826f2dc87a33 Mon Sep 17 00:00:00 2001 From: Steven DeMartini Date: Fri, 16 Jun 2023 11:26:52 -0700 Subject: [PATCH] Fix link bubble menu state when clicking out or changing selection This avoids a focus-jump when clicking away from the "Edit" form, by ensuring the bubble menu state is kept in sync. An extra precautionary fallback to `?? ""` is added for the `currentHref` just in case the menu renders when unexpected and no `href` is available, since this can cause a crash (though that scenario is likely resolved by our more deliberate menu-closing, and handled here just as a defensive precaution). --- src/LinkBubbleMenu/ViewLinkMenuContent.tsx | 3 ++- src/extensions/LinkBubbleMenuHandler.ts | 23 +++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/LinkBubbleMenu/ViewLinkMenuContent.tsx b/src/LinkBubbleMenu/ViewLinkMenuContent.tsx index 7825292..1a64127 100644 --- a/src/LinkBubbleMenu/ViewLinkMenuContent.tsx +++ b/src/LinkBubbleMenu/ViewLinkMenuContent.tsx @@ -34,7 +34,8 @@ export default function ViewLinkMenuContent({ ? editor.state.doc.textBetween(linkRange.from, linkRange.to) : ""; - const currentHref = editor.getAttributes("link").href as string; + const currentHref = + (editor.getAttributes("link").href as string | undefined) ?? ""; // If the user presses escape, we should cancel useKeyDown("Escape", onCancel); diff --git a/src/extensions/LinkBubbleMenuHandler.ts b/src/extensions/LinkBubbleMenuHandler.ts index 689ace1..490864b 100644 --- a/src/extensions/LinkBubbleMenuHandler.ts +++ b/src/extensions/LinkBubbleMenuHandler.ts @@ -132,13 +132,22 @@ const LinkBubbleMenuHandler = Extension.create< }, onSelectionUpdate() { - // To ensure we maintain the proper bubble menu state, if someone is viewing - // an existing link but moves off of it (e.g. with their keyboard), we'll - // close the bubble menu. Note that we only do this for "view" (and not - // "edit"), since when adding a new link, there is not yet a link at the - // current position and the user's focus will be in the edit form anyway, - // where clicking out would already close the menu. - if ( + // To ensure we maintain the proper bubble menu state, if someone is + // viewing/editing a link but moves off of it (e.g. with their keyboard + // arrow keys, or by clicking out, or by typing over the currently selected + // link), we'll close the bubble menu. Note that when in "view" mode (and + // not "edit") for an existing link, we only close if the state shows the + // user is not on an active link anymore, since the selection can be updated + // via `openLinkBubbleMenu` (and we don't want to immediately close it upon + // initial opening of the bubble menu). By contrast in "edit" mode, the the + // user's focus should be in the edit form and selection shouldn't + // automatically update during opening or otherwise, so clicking out (i.e. + // changing selection) definitively indicates cancellation. + // onSelectionUpdate runs before handleClick, so we need to promptly close + // in that scenario. + if (this.storage.state === LinkMenuState.EDIT_LINK) { + this.editor.commands.closeLinkBubbleMenu(); + } else if ( this.storage.state === LinkMenuState.VIEW_LINK_DETAILS && !this.editor.isActive("link") ) {