From 160f4d3c46bae1f24b89dc4473e754b36c5c6622 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Fri, 12 Jan 2024 14:49:38 +0000 Subject: [PATCH] Fix anchor position using standardised method --- packages/format-library/src/link/inline.js | 31 +++++++++++----------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/packages/format-library/src/link/inline.js b/packages/format-library/src/link/inline.js index 1fd5dd2cc3172..9cc1e97e905bc 100644 --- a/packages/format-library/src/link/inline.js +++ b/packages/format-library/src/link/inline.js @@ -16,11 +16,12 @@ import { replace, split, concat, - privateApis as richTextPrivateApis, + useAnchor, } from '@wordpress/rich-text'; import { __experimentalLinkControl as LinkControl, store as blockEditorStore, + useCachedTruthy, } from '@wordpress/block-editor'; import { useSelect } from '@wordpress/data'; @@ -29,9 +30,6 @@ import { useSelect } from '@wordpress/data'; */ import { createLinkFormat, isValidHref, getFormatBoundary } from './utils'; import { link as settings } from './index'; -import { unlock } from '../lock-unlock'; - -const { useAnchorWithUpdate } = unlock( richTextPrivateApis ); const LINK_SETTINGS = [ ...LinkControl.DEFAULT_LINK_SETTINGS, @@ -180,13 +178,6 @@ function InlineLinkUI( { newValue.start = newValue.end; onChange( newValue ); - - // Force update the anchor reference to ensure the Popover is positioned correctly/ - // Incorrect positioning can happen on the initial creation of a link because the - // anchor changes from a rich text selection to a link format element (e.g. ). - // however the Popover is not repositioned to account for this change because the - // dependencies of `useAnchor` do not change. - updatePopoverAnchor(); } // Focus should only be returned to the rich text on submit if this link is not @@ -212,11 +203,19 @@ function InlineLinkUI( { } } - const { anchor: popoverAnchor, update: updatePopoverAnchor } = - useAnchorWithUpdate( { - editableContentElement: contentRef.current, - settings, - } ); + const popoverAnchor = useAnchor( { + editableContentElement: contentRef.current, + settings, + } ); + + // As you change the link by interacting with the Link UI + // the return value of document.getSelection jumps to the field you're editing, + // not the highlighted text. Given that useAnchor uses document.getSelection, + // it will return null, since it can't find the element within the Link UI. + // This caches the last truthy value of the selection anchor reference. + // + const cachedRect = useCachedTruthy( popoverAnchor.getBoundingClientRect() ); + popoverAnchor.getBoundingClientRect = () => cachedRect; // Focus should only be moved into the Popover when the Link is being created or edited. // When the Link is in "preview" mode focus should remain on the rich text because at