diff --git a/packages/editor/src/hooks/pattern-overrides.js b/packages/editor/src/hooks/pattern-overrides.js index 442ce70a2bf71c..a7b465980f609c 100644 --- a/packages/editor/src/hooks/pattern-overrides.js +++ b/packages/editor/src/hooks/pattern-overrides.js @@ -4,8 +4,13 @@ import { addFilter } from '@wordpress/hooks'; import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; import { createHigherOrderComponent } from '@wordpress/compose'; -import { useBlockEditingMode } from '@wordpress/block-editor'; +import { + useBlockEditingMode, + InspectorControls, +} from '@wordpress/block-editor'; import { useSelect } from '@wordpress/data'; +import { CheckboxControl } from '@wordpress/components'; +import { __, sprintf, _n } from '@wordpress/i18n'; /** * Internal dependencies @@ -23,7 +28,11 @@ const { /** * Override the default edit UI to include a new block inspector control for * assigning a partial syncing controls to supported blocks in the pattern editor. - * Currently, only the `core/paragraph` block is supported. + * Currently, only the following `core` namespaced blocks are supported: + * - Paragraph + * - Heading + * - Image + * - Button * * @param {Component} BlockEdit Original component. * @@ -39,6 +48,9 @@ const withPatternOverrideControls = createHigherOrderComponent( <> { isSupportedBlock && } + { props.isSelected && isSupportedBlock && ( + + ) } { props.isSelected && isSupportedBlock && ( ) } @@ -47,6 +59,105 @@ const withPatternOverrideControls = createHigherOrderComponent( } ); +function removeBindings( bindings, syncedAttributes ) { + let updatedBindings = {}; + for ( const attributeName of syncedAttributes ) { + // Omit any pattern override bindings from the `updatedBindings` object. + if ( + bindings?.[ attributeName ]?.source !== 'core/pattern-overrides' && + bindings?.[ attributeName ]?.source !== undefined + ) { + updatedBindings[ attributeName ] = bindings[ attributeName ]; + } + } + if ( ! Object.keys( updatedBindings ).length ) { + updatedBindings = undefined; + } + return updatedBindings; +} + +function addBindings( bindings, syncedAttributes ) { + const updatedBindings = { ...bindings }; + for ( const attributeName of syncedAttributes ) { + if ( ! bindings?.[ attributeName ] ) { + updatedBindings[ attributeName ] = { + source: 'core/pattern-overrides', + }; + } + } + return updatedBindings; +} + +function BindingsResetControl( { name, attributes, setAttributes } ) { + const blockEditingMode = useBlockEditingMode(); + const isEditingPattern = useSelect( + ( select ) => + select( editorStore ).getCurrentPostType() === PATTERN_TYPES.user, + [] + ); + + const metadata = attributes?.metadata; + const bindings = metadata?.bindings; + + const syncedAttributes = PARTIAL_SYNCING_SUPPORTED_BLOCKS[ name ]; + const shouldShowResetRemoveBindingsControl = + isEditingPattern && + !! metadata?.name && + blockEditingMode !== 'disabled'; + + if ( ! shouldShowResetRemoveBindingsControl ) { + return null; + } + + // If one of the syncedAttributes is in the bindings, then we should show the reset control. + const hasBindings = syncedAttributes.some( + ( attributeName ) => bindings?.[ attributeName ] + ); + + const attributeCount = syncedAttributes.length; + const helpText = sprintf( + // Translators: %1$s is a list of attributes, %2$s is the count of attributes. + __( 'Disables overrides on the %1$s %2$s on a per instance basis.' ), + syncedAttributes.join( ', ' ), + _n( 'attribute', 'attributes', attributeCount ) + ); + + return ( + + { + if ( isChecked ) { + const updatedBindings = removeBindings( + bindings, + syncedAttributes + ); + setAttributes( { + metadata: { + ...attributes.metadata, + bindings: updatedBindings, + }, + } ); + } else if ( attributes.metadata.name ) { + const updatedBindings = addBindings( + bindings, + syncedAttributes + ); + setAttributes( { + metadata: { + ...attributes.metadata, + bindings: updatedBindings, + }, + } ); + } + } } + help={ helpText } + /> + + ); +} + function BindingUpdater( props ) { const postType = useSelect( ( select ) => select( editorStore ).getCurrentPostType(),