From 787fd3eae04965c3980b2d184590c483d883d8c5 Mon Sep 17 00:00:00 2001 From: Omar Alshaker Date: Fri, 5 Nov 2021 19:51:38 +0100 Subject: [PATCH] Keep a copy of anchor ref to preserve highlighted text selection (#36263) * Keep a copy of anchor ref to preserve selection * Update native files as well --- packages/block-editor/README.md | 12 +++++++++++ packages/block-editor/src/hooks/index.js | 1 + .../block-editor/src/hooks/index.native.js | 1 + .../src/hooks/use-cached-truthy.js | 20 +++++++++++++++++++ packages/block-editor/src/index.js | 1 + .../format-library/src/text-color/inline.js | 13 +++++++++++- 6 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 packages/block-editor/src/hooks/use-cached-truthy.js diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 5c8f30a5802ce5..0b015bac1bf41a 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -680,6 +680,18 @@ _Returns_ - `Object`: Props to pass to the element to mark as a block. +### useCachedTruthy + +Keeps an up-to-date copy of the passed value and returns it. If value becomes falsy, it will return the last truthy copy. + +_Parameters_ + +- _value_ `any`: + +_Returns_ + +- `any`: value + ### useInnerBlocksProps This hook is used to lightly mark an element as an inner blocks wrapper diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 1307af959c2c76..708dae62a39714 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -18,3 +18,4 @@ export { useCustomSides } from './dimensions'; export { getBorderClassesAndStyles, useBorderProps } from './use-border-props'; export { getColorClassesAndStyles, useColorProps } from './use-color-props'; export { getSpacingClassesAndStyles } from './use-spacing-props'; +export { useCachedTruthy } from './use-cached-truthy'; diff --git a/packages/block-editor/src/hooks/index.native.js b/packages/block-editor/src/hooks/index.native.js index 82312c905ce551..06ea26e2e157c4 100644 --- a/packages/block-editor/src/hooks/index.native.js +++ b/packages/block-editor/src/hooks/index.native.js @@ -13,3 +13,4 @@ import './font-size'; export { getBorderClassesAndStyles, useBorderProps } from './use-border-props'; export { getColorClassesAndStyles, useColorProps } from './use-color-props'; export { getSpacingClassesAndStyles } from './use-spacing-props'; +export { useCachedTruthy } from './use-cached-truthy'; diff --git a/packages/block-editor/src/hooks/use-cached-truthy.js b/packages/block-editor/src/hooks/use-cached-truthy.js new file mode 100644 index 00000000000000..9650a3039f2291 --- /dev/null +++ b/packages/block-editor/src/hooks/use-cached-truthy.js @@ -0,0 +1,20 @@ +/** + * WordPress dependencies + */ +import { useState, useEffect } from '@wordpress/element'; + +/** + * Keeps an up-to-date copy of the passed value and returns it. If value becomes falsy, it will return the last truthy copy. + * + * @param {any} value + * @return {any} value + */ +export function useCachedTruthy( value ) { + const [ cachedValue, setCachedValue ] = useState( value ); + useEffect( () => { + if ( value ) { + setCachedValue( value ); + } + }, [ value ] ); + return cachedValue; +} diff --git a/packages/block-editor/src/index.js b/packages/block-editor/src/index.js index 2720c2cd4c9588..0672b0c0fbfddf 100644 --- a/packages/block-editor/src/index.js +++ b/packages/block-editor/src/index.js @@ -9,6 +9,7 @@ export { useColorProps as __experimentalUseColorProps, useCustomSides as __experimentalUseCustomSides, getSpacingClassesAndStyles as __experimentalGetSpacingClassesAndStyles, + useCachedTruthy, } from './hooks'; export * from './components'; export * from './utils'; diff --git a/packages/format-library/src/text-color/inline.js b/packages/format-library/src/text-color/inline.js index fcb0a19589d8ce..abe1f2162bb856 100644 --- a/packages/format-library/src/text-color/inline.js +++ b/packages/format-library/src/text-color/inline.js @@ -20,6 +20,7 @@ import { getColorObjectByColorValue, getColorObjectByAttributeValues, store as blockEditorStore, + useCachedTruthy, } from '@wordpress/block-editor'; import { Popover, TabPanel } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; @@ -139,7 +140,17 @@ export default function InlineColorUI( { onClose, contentRef, } ) { - const anchorRef = useAnchorRef( { ref: contentRef, value, settings } ); + /* + As you change the text color by typing a HEX value into a field, + the return value of document.getSelection jumps to the field you're editing, + not the highlighted text. Given that useAnchorRef uses document.getSelection, + it will return null, since it can't find the element within the HEX input. + This caches the last truthy value of the selection anchor reference. + */ + const anchorRef = useCachedTruthy( + useAnchorRef( { ref: contentRef, value, settings } ) + ); + return (