diff --git a/packages/block-editor/README.md b/packages/block-editor/README.md index 2d6a5627a52a44..990148cbc855f3 100644 --- a/packages/block-editor/README.md +++ b/packages/block-editor/README.md @@ -867,13 +867,14 @@ function MyBlock( { attributes, setAttributes } ) { } ``` -`mode` can be one of three options: +`mode` can be one of four options: - `'disabled'`: Prevents editing the block entirely, i.e. it cannot be selected. - `'contentOnly'`: Hides all non-content UI, e.g. auxiliary controls in the toolbar, the block movers, block settings. - `'default'`: Allows editing the block as normal. +- `'syncedPattern'`: Restricts editing of synced pattern blocks to only child blocks that have attribute connections set. The mode is inherited by all of the block's inner blocks, unless they have their own mode. diff --git a/packages/block-editor/src/components/block-editing-mode/index.js b/packages/block-editor/src/components/block-editing-mode/index.js index 5d916d9816e606..5a40604d0eaa5a 100644 --- a/packages/block-editor/src/components/block-editing-mode/index.js +++ b/packages/block-editor/src/components/block-editing-mode/index.js @@ -11,7 +11,7 @@ import { store as blockEditorStore } from '../../store'; import { BlockListBlockContext } from '../block-list/block-list-block-context'; /** - * @typedef {'disabled'|'contentOnly'|'default'} BlockEditingMode + * @typedef {'disabled'|'contentOnly'|'default'|'syncedPattern'} BlockEditingMode */ /** @@ -26,13 +26,14 @@ import { BlockListBlockContext } from '../block-list/block-list-block-context'; * } * ``` * - * `mode` can be one of three options: + * `mode` can be one of four options: * * - `'disabled'`: Prevents editing the block entirely, i.e. it cannot be * selected. * - `'contentOnly'`: Hides all non-content UI, e.g. auxiliary controls in the * toolbar, the block movers, block settings. * - `'default'`: Allows editing the block as normal. + * - `'syncedPattern'`: Restricts editing of synced pattern blocks to only child blocks that have attribute connections set. * * The mode is inherited by all of the block's inner blocks, unless they have * their own mode. diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index a95075c6f9b42c..7e2246fff21cd5 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -113,6 +113,8 @@ function BlockListBlock( { ); const { removeBlock } = useDispatch( blockEditorStore ); const onRemove = useCallback( () => removeBlock( clientId ), [ clientId ] ); + const isSyncedPatternChild = + name !== 'core/block' && blockEditingMode === 'syncedPattern'; const parentLayout = useLayout() || {}; @@ -142,7 +144,7 @@ function BlockListBlock( { const blockType = getBlockType( name ); - if ( blockEditingMode === 'disabled' ) { + if ( blockEditingMode === 'disabled' || isSyncedPatternChild ) { wrapperProps = { ...wrapperProps, tabIndex: -1, @@ -216,7 +218,8 @@ function BlockListBlock( { clientId, className: classnames( { - 'is-editing-disabled': blockEditingMode === 'disabled', + 'is-editing-disabled': + blockEditingMode === 'disabled' || isSyncedPatternChild, 'is-content-locked-temporarily-editing-as-blocks': isTemporarilyEditingAsBlocks, }, diff --git a/packages/block-editor/src/components/block-list/use-in-between-inserter.js b/packages/block-editor/src/components/block-list/use-in-between-inserter.js index a60453716ff29c..3effeb6d6b1aac 100644 --- a/packages/block-editor/src/components/block-list/use-in-between-inserter.js +++ b/packages/block-editor/src/components/block-list/use-in-between-inserter.js @@ -75,7 +75,8 @@ export function useInBetweenInserter() { if ( getTemplateLock( rootClientId ) || - getBlockEditingMode( rootClientId ) === 'disabled' + getBlockEditingMode( rootClientId ) === 'disabled' || + getBlockEditingMode( rootClientId ) === 'syncedPattern' ) { return; } diff --git a/packages/block-editor/src/components/block-lock/modal.js b/packages/block-editor/src/components/block-lock/modal.js index cfafa6c031bbd1..c08159faa05fd6 100644 --- a/packages/block-editor/src/components/block-lock/modal.js +++ b/packages/block-editor/src/components/block-lock/modal.js @@ -25,7 +25,7 @@ import useBlockDisplayInformation from '../use-block-display-information'; import { store as blockEditorStore } from '../../store'; // Entity based blocks which allow edit locking -const ALLOWS_EDIT_LOCKING = [ 'core/block', 'core/navigation' ]; +const ALLOWS_EDIT_LOCKING = [ 'core/navigation' ]; function getTemplateLockValue( lock ) { // Prevents all operations. diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 963cd8a475328a..239b677fa04ad6 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -91,6 +91,7 @@ const BlockToolbar = ( { hideDragHandle } ) => { const isSynced = isReusableBlock( blockType ) || isTemplatePart( blockType ); + const isSyncedPattern = isReusableBlock( blockType ); const classes = classnames( 'block-editor-block-toolbar', { 'is-synced': isSynced, } ); @@ -101,7 +102,8 @@ const BlockToolbar = ( { hideDragHandle } ) => { isLargeViewport && blockEditingMode === 'default' && } { ( shouldShowVisualToolbar || isMultiToolbar ) && - blockEditingMode === 'default' && ( + ( blockEditingMode === 'default' || + blockEditingMode === 'syncedPattern' ) && (
@@ -148,7 +150,7 @@ const BlockToolbar = ( { hideDragHandle } ) => { ) } - { blockEditingMode === 'default' && ( + { ( blockEditingMode === 'default' || isSyncedPattern ) && ( ) }
diff --git a/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js b/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js index b24a25ee60ed42..670f2f39bfe5f5 100644 --- a/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js +++ b/packages/block-editor/src/components/block-tools/block-contextual-toolbar.js @@ -70,7 +70,9 @@ export default function BlockContextualToolbar( { const hasAnyBlockControls = useHasAnyBlockControls(); if ( ! isToolbarEnabled || - ( blockEditingMode !== 'default' && ! hasAnyBlockControls ) + ( blockEditingMode !== 'syncedPattern' && + blockEditingMode !== 'default' && + ! hasAnyBlockControls ) ) { return null; } diff --git a/packages/block-editor/src/components/list-view/block.js b/packages/block-editor/src/components/list-view/block.js index 4957f79fa0d481..591057a4de036c 100644 --- a/packages/block-editor/src/components/list-view/block.js +++ b/packages/block-editor/src/components/list-view/block.js @@ -89,7 +89,9 @@ function ListViewBlock( { // List View respects this by also hiding the block settings menu. hasBlockSupport( blockName, '__experimentalToolbar', true ) && // Don't show the settings menu if block is disabled or content only. - blockEditingMode === 'default'; + ( blockEditingMode === 'default' || + ( blockName === 'core/block' && + blockEditingMode === 'syncedPattern' ) ); const instanceId = useInstanceId( ListViewBlock ); const descriptionId = `list-view-block-select-button__${ instanceId }`; const blockPositionDescription = getBlockPositionDescription( @@ -243,7 +245,9 @@ function ListViewBlock( { path={ path } id={ `list-view-${ listViewInstanceId }-block-${ clientId }` } data-block={ clientId } - data-expanded={ canEdit ? isExpanded : undefined } + data-expanded={ + canEdit && blockName !== 'core/block' ? isExpanded : undefined + } ref={ rowRef } > { + const { canUser } = select( coreStore ); + const { getSettings } = select( editorStore ); + + const isBlockTheme = getSettings().__unstableIsBlockBasedTheme; + const defaultUrl = addQueryArgs( 'post.php', { + action: 'edit', + post: ref, + } ); + const siteEditorUrl = addQueryArgs( 'site-editor.php', { + postType: 'wp_block', + postId: ref, + categoryType: 'pattern', + canvas: 'edit', + refererId: postId, + } ); + + // For editing link to the site editor if the theme and user permissions support it. + return canUser( 'read', 'templates' ) && isBlockTheme + ? siteEditorUrl + : defaultUrl; + }, + [ postId, ref ] + ); + useBlockEditingMode( 'syncedPattern' ); const hasAlreadyRendered = useHasRecursion( ref ); const { record, hasResolved } = useEntityRecord( 'postType', @@ -141,6 +177,13 @@ export default function ReusableBlockEdit( { return ( + + + + { __( 'Edit' ) } + + + + ( document.location = `post.php?post=${ refererId }&action=edit` ); + } + return (