diff --git a/packages/block-editor/src/components/rich-text/use-format-types.js b/packages/block-editor/src/components/rich-text/use-format-types.js index e341c1ee434b9f..ff76cc59dd58d3 100644 --- a/packages/block-editor/src/components/rich-text/use-format-types.js +++ b/packages/block-editor/src/components/rich-text/use-format-types.js @@ -1,12 +1,13 @@ /** - * WordPress dependencies + * External dependencies */ -import { useMemo } from '@wordpress/element'; -import { useSelect, useDispatch } from '@wordpress/data'; +import { mapKeys } from 'lodash'; /** - * Internal dependencies + * WordPress dependencies */ +import { useMemo } from '@wordpress/element'; +import { useSelect, useDispatch } from '@wordpress/data'; import { store as richTextStore } from '@wordpress/rich-text'; function formatTypesSelector( select ) { @@ -32,6 +33,21 @@ const interactiveContentTags = new Set( [ 'video', ] ); +function prefixSelectKeys( selected, prefix ) { + if ( typeof selected !== 'object' ) return { [ prefix ]: selected }; + return mapKeys( selected, ( value, key ) => `${ prefix }.${ key }` ); +} + +function getPrefixedSelectKeys( selected, prefix ) { + if ( selected[ prefix ] ) return selected[ prefix ]; + return Object.keys( selected ) + .filter( ( key ) => key.startsWith( prefix + '.' ) ) + .reduce( ( accumulator, key ) => { + accumulator[ key.slice( prefix.length + 1 ) ] = selected[ key ]; + return accumulator; + }, {} ); +} + /** * This hook provides RichText with the `formatTypes` and its derived props from * experimental format type settings. @@ -68,18 +84,23 @@ export function useFormatTypes( { const keyedSelected = useSelect( ( select ) => formatTypes.reduce( ( accumulator, type ) => { - if ( type.__experimentalGetPropsForEditableTreePreparation ) { - accumulator[ type.name ] = + if ( ! type.__experimentalGetPropsForEditableTreePreparation ) { + return accumulator; + } + + return { + ...accumulator, + ...prefixSelectKeys( type.__experimentalGetPropsForEditableTreePreparation( select, { richTextIdentifier: identifier, blockClientId: clientId, } - ); - } - - return accumulator; + ), + type.name + ), + }; }, {} ), [ formatTypes, clientId, identifier ] ); @@ -89,11 +110,14 @@ export function useFormatTypes( { const changeHandlers = []; const dependencies = []; + for ( const key in keyedSelected ) { + dependencies.push( keyedSelected[ key ] ); + } + formatTypes.forEach( ( type ) => { if ( type.__experimentalCreatePrepareEditableTree ) { - const selected = keyedSelected[ type.name ]; const handler = type.__experimentalCreatePrepareEditableTree( - selected, + getPrefixedSelectKeys( keyedSelected, type.name ), { richTextIdentifier: identifier, blockClientId: clientId, @@ -105,10 +129,6 @@ export function useFormatTypes( { } else { prepareHandlers.push( handler ); } - - for ( const key in selected ) { - dependencies.push( selected[ key ] ); - } } if ( type.__experimentalCreateOnChangeEditableValue ) { @@ -125,10 +145,11 @@ export function useFormatTypes( { ); } + const selected = getPrefixedSelectKeys( keyedSelected, type.name ); changeHandlers.push( type.__experimentalCreateOnChangeEditableValue( { - ...( keyedSelected[ type.name ] || {} ), + ...( typeof selected === 'object' ? selected : {} ), ...dispatchers, }, {