diff --git a/packages/block-editor/src/components/rich-text/index.js b/packages/block-editor/src/components/rich-text/index.js index e8fbec1e0b745..732b8dbf2c089 100644 --- a/packages/block-editor/src/components/rich-text/index.js +++ b/packages/block-editor/src/components/rich-text/index.js @@ -20,8 +20,9 @@ import { removeFormat, } from '@wordpress/rich-text'; import { Popover } from '@wordpress/components'; -import { getBlockType, store as blocksStore } from '@wordpress/blocks'; +import { store as blocksStore } from '@wordpress/blocks'; import deprecated from '@wordpress/deprecated'; +import { __, sprintf } from '@wordpress/i18n'; /** * Internal dependencies @@ -163,49 +164,47 @@ export function RichTextWrapper( isBlockSelected, ] ); - const disableBoundBlocks = useSelect( + const { disableBoundBlock, bindingsPlaceholder } = useSelect( ( select ) => { - // Disable Rich Text editing if block bindings specify that. - let _disableBoundBlocks = false; - if ( blockBindings && canBindBlock( blockName ) ) { - const blockTypeAttributes = - getBlockType( blockName ).attributes; - const { getBlockBindingsSource } = unlock( - select( blocksStore ) - ); - for ( const [ attribute, binding ] of Object.entries( - blockBindings - ) ) { - if ( - blockTypeAttributes?.[ attribute ]?.source !== - 'rich-text' - ) { - break; - } - - // If the source is not defined, or if its value of `canUserEditValue` is `false`, disable it. - const blockBindingsSource = getBlockBindingsSource( - binding.source - ); - if ( - ! blockBindingsSource?.canUserEditValue?.( { - select, - context: blockContext, - args: binding.args, - } ) - ) { - _disableBoundBlocks = true; - break; - } - } + if ( + ! blockBindings?.[ identifier ] || + ! canBindBlock( blockName ) + ) { + return {}; } - return _disableBoundBlocks; + const relatedBinding = blockBindings[ identifier ]; + const { getBlockBindingsSource } = unlock( select( blocksStore ) ); + const blockBindingsSource = getBlockBindingsSource( + relatedBinding.source + ); + + const _disableBoundBlock = + ! blockBindingsSource?.canUserEditValue?.( { + select, + context: blockContext, + args: relatedBinding.args, + } ); + + const _bindingsPlaceholder = _disableBoundBlock + ? relatedBinding?.args?.key || blockBindingsSource?.label + : sprintf( + /* translators: %s: source label or key */ + __( 'Add %s' ), + relatedBinding?.args?.key || blockBindingsSource?.label + ); + + return { + disableBoundBlock: _disableBoundBlock, + bindingsPlaceholder: + ( ! adjustedValue || adjustedValue.length === 0 ) && + _bindingsPlaceholder, + }; }, - [ blockBindings, blockName ] + [ blockBindings, identifier, blockName, blockContext, adjustedValue ] ); - const shouldDisableEditing = readOnly || disableBoundBlocks; + const shouldDisableEditing = readOnly || disableBoundBlock; const { getSelectionStart, getSelectionEnd, getBlockRootClientId } = useSelect( blockEditorStore ); @@ -335,7 +334,7 @@ export function RichTextWrapper( selectionStart, selectionEnd, onSelectionChange, - placeholder, + placeholder: bindingsPlaceholder || placeholder, __unstableIsSelected: isSelected, __unstableDisableFormats: disableFormats, preserveWhiteSpace, @@ -404,9 +403,11 @@ export function RichTextWrapper( // Overridable props. role="textbox" aria-multiline={ ! disableLineBreaks } - aria-label={ placeholder } aria-readonly={ shouldDisableEditing } { ...props } + aria-label={ + bindingsPlaceholder || props[ 'aria-label' ] || placeholder + } { ...autocompleteProps } ref={ useMergeRefs( [ // Rich text ref must be first because its focus listener