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(),