From 35f955acc08acd3fe6efcc83513a48ab5c05aaa6 Mon Sep 17 00:00:00 2001 From: Kai Hao Date: Tue, 5 Mar 2024 17:00:37 +0800 Subject: [PATCH] Allow opt-out of pattern overrides --- packages/block-editor/src/private-apis.js | 2 + .../editor/src/hooks/pattern-overrides.js | 28 +++++- .../components/pattern-overrides-controls.js | 93 +++++++++++++++++++ .../components/use-set-pattern-bindings.js | 6 +- packages/patterns/src/private-apis.js | 2 + 5 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 packages/patterns/src/components/pattern-overrides-controls.js diff --git a/packages/block-editor/src/private-apis.js b/packages/block-editor/src/private-apis.js index 92da4b8719632..762b3a96a87a9 100644 --- a/packages/block-editor/src/private-apis.js +++ b/packages/block-editor/src/private-apis.js @@ -29,6 +29,7 @@ import { useFlashEditableBlocks } from './components/use-flash-editable-blocks'; import { selectBlockPatternsKey } from './store/private-keys'; import { requiresWrapperOnCopy } from './components/writing-flow/utils'; import { PrivateRichText } from './components/rich-text/'; +import { BlockRenameModal } from './components/block-rename'; /** * Private @wordpress/block-editor APIs. @@ -62,4 +63,5 @@ lock( privateApis, { selectBlockPatternsKey, requiresWrapperOnCopy, PrivateRichText, + BlockRenameModal, } ); diff --git a/packages/editor/src/hooks/pattern-overrides.js b/packages/editor/src/hooks/pattern-overrides.js index 442ce70a2bf71..1d83af1af1853 100644 --- a/packages/editor/src/hooks/pattern-overrides.js +++ b/packages/editor/src/hooks/pattern-overrides.js @@ -6,6 +6,7 @@ import { privateApis as patternsPrivateApis } from '@wordpress/patterns'; import { createHigherOrderComponent } from '@wordpress/compose'; import { useBlockEditingMode } from '@wordpress/block-editor'; import { useSelect } from '@wordpress/data'; +import { store as blocksStore } from '@wordpress/blocks'; /** * Internal dependencies @@ -15,6 +16,7 @@ import { unlock } from '../lock-unlock'; const { useSetPatternBindings, + PatternOverridesControls, ResetOverridesControl, PATTERN_TYPES, PARTIAL_SYNCING_SUPPORTED_BLOCKS, @@ -60,9 +62,20 @@ function BindingUpdater( props ) { // on every block. function ControlsWithStoreSubscription( props ) { const blockEditingMode = useBlockEditingMode(); - const isEditingPattern = useSelect( - ( select ) => - select( editorStore ).getCurrentPostType() === PATTERN_TYPES.user, + const { hasPatternOverridesSource, isEditingPattern } = useSelect( + ( select ) => { + const { getBlockBindingsSource } = unlock( select( blocksStore ) ); + + return { + // For editing link to the site editor if the theme and user permissions support it. + hasPatternOverridesSource: !! getBlockBindingsSource( + 'core/pattern-overrides' + ), + isEditingPattern: + select( editorStore ).getCurrentPostType() === + PATTERN_TYPES.user, + }; + }, [] ); @@ -73,14 +86,23 @@ function ControlsWithStoreSubscription( props ) { ( binding ) => binding.source === 'core/pattern-overrides' ); + const shouldShowPatternOverridesControls = + isEditingPattern && blockEditingMode === 'default'; const shouldShowResetOverridesControl = ! isEditingPattern && !! props.attributes.metadata?.name && blockEditingMode !== 'disabled' && hasPatternBindings; + if ( ! hasPatternOverridesSource ) { + return null; + } + return ( <> + { shouldShowPatternOverridesControls && ( + + ) } { shouldShowResetOverridesControl && ( ) } diff --git a/packages/patterns/src/components/pattern-overrides-controls.js b/packages/patterns/src/components/pattern-overrides-controls.js new file mode 100644 index 0000000000000..c58451775b410 --- /dev/null +++ b/packages/patterns/src/components/pattern-overrides-controls.js @@ -0,0 +1,93 @@ +/** + * WordPress dependencies + */ +import { useState } from '@wordpress/element'; +import { + InspectorControls, + privateApis as blockEditorPrivateApis, +} from '@wordpress/block-editor'; +import { ToggleControl } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import { addBindings } from './use-set-pattern-bindings'; +import { PARTIAL_SYNCING_SUPPORTED_BLOCKS } from '../constants'; +import { unlock } from '../lock-unlock'; + +const { BlockRenameModal } = unlock( blockEditorPrivateApis ); + +function PatternOverridesControls( { attributes, name, setAttributes } ) { + const [ showBlockNameModal, setShowBlockNameModal ] = useState( false ); + + const syncedAttributes = PARTIAL_SYNCING_SUPPORTED_BLOCKS[ name ]; + const attributeSources = syncedAttributes.map( + ( attributeName ) => + attributes.metadata?.bindings?.[ attributeName ]?.source + ); + const isConnectedToOtherSources = attributeSources.every( + ( source ) => source && source !== 'core/pattern-overrides' + ); + + function updateBindings( isChecked, customName ) { + if ( isChecked && ! attributes.metadata?.name && ! customName ) { + setShowBlockNameModal( true ); + return; + } + + const prevBindings = attributes?.metadata?.bindings; + const updatedBindings = isChecked + ? addBindings( prevBindings, syncedAttributes ) + : // Explicitly set to false to disable pattern overrides. + false; + + const updatedMetadata = { + ...attributes.metadata, + bindings: updatedBindings, + }; + + if ( customName ) { + updatedMetadata.name = customName; + } + + setAttributes( { + metadata: updatedMetadata, + } ); + } + + // Avoid overwriting other (e.g. meta) bindings. + if ( isConnectedToOtherSources ) return null; + + return ( + <> + + source === 'core/pattern-overrides' + ) } + help={ __( + 'Allow attributes within this block to be overridden by pattern instances.' + ) } + onChange={ ( isChecked ) => { + updateBindings( isChecked ); + } } + /> + + + { showBlockNameModal && ( + setShowBlockNameModal( false ) } + onSave={ ( newName ) => { + updateBindings( true, newName ); + } } + /> + ) } + + ); +} + +export default PatternOverridesControls; diff --git a/packages/patterns/src/components/use-set-pattern-bindings.js b/packages/patterns/src/components/use-set-pattern-bindings.js index 261187a91088c..7d6f95e261a99 100644 --- a/packages/patterns/src/components/use-set-pattern-bindings.js +++ b/packages/patterns/src/components/use-set-pattern-bindings.js @@ -30,7 +30,7 @@ function removeBindings( bindings, syncedAttributes ) { return updatedBindings; } -function addBindings( bindings, syncedAttributes ) { +export function addBindings( bindings, syncedAttributes ) { const updatedBindings = { ...bindings }; for ( const attributeName of syncedAttributes ) { if ( ! bindings?.[ attributeName ] ) { @@ -64,7 +64,9 @@ export default function useSetPatternBindings( if ( ! hasPatternOverridesSource || currentPostType !== 'wp_block' || - metadataName === prevMetadataName + metadataName === prevMetadataName || + // Don't update the bindings if it's explicitly set to false. + bindings === false ) { return; } diff --git a/packages/patterns/src/private-apis.js b/packages/patterns/src/private-apis.js index 54ad5a4aa47d1..f30aeb244d05a 100644 --- a/packages/patterns/src/private-apis.js +++ b/packages/patterns/src/private-apis.js @@ -14,6 +14,7 @@ import RenamePatternModal from './components/rename-pattern-modal'; import PatternsMenuItems from './components'; import RenamePatternCategoryModal from './components/rename-pattern-category-modal'; import useSetPatternBindings from './components/use-set-pattern-bindings'; +import PatternOverridesControls from './components/pattern-overrides-controls'; import ResetOverridesControl from './components/reset-overrides-control'; import { useAddPatternCategory } from './private-hooks'; import { @@ -35,6 +36,7 @@ lock( privateApis, { PatternsMenuItems, RenamePatternCategoryModal, useSetPatternBindings, + PatternOverridesControls, ResetOverridesControl, useAddPatternCategory, PATTERN_TYPES,