From 35c115e354acae4f357b8c5f39c358b9cb1406b7 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Mon, 23 Feb 2026 17:19:16 +0800 Subject: [PATCH] Fix block editing modes not recomputing when isolated editor value changes --- packages/block-editor/src/store/reducer.js | 10 +- .../block-editor/src/store/test/reducer.js | 172 +++++++++++++++++- 2 files changed, 178 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 994cfa3886bd71..43850fda91a56d 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -3064,15 +3064,19 @@ export function withDerivedBlockEditingModes( reducer ) { break; } case 'UPDATE_SETTINGS': { - // Recompute the entire tree if the section root or - // the effective disableContentOnlyForUnsyncedPatterns value changes. + // Recompute the entire tree if the section root, + // the effective disableContentOnlyForUnsyncedPatterns value, + // or the isIsolatedEditor value changes. + // These are all values that affect the computation. if ( state?.settings?.[ sectionRootClientIdKey ] !== nextState?.settings?.[ sectionRootClientIdKey ] || !! state?.settings ?.disableContentOnlyForUnsyncedPatterns !== !! nextState?.settings - ?.disableContentOnlyForUnsyncedPatterns + ?.disableContentOnlyForUnsyncedPatterns || + !! state?.settings?.[ isIsolatedEditorKey ] !== + !! nextState?.settings?.[ isIsolatedEditorKey ] ) { return { ...nextState, diff --git a/packages/block-editor/src/store/test/reducer.js b/packages/block-editor/src/store/test/reducer.js index c8f2aa81e006d5..ea4802586b6dc2 100644 --- a/packages/block-editor/src/store/test/reducer.js +++ b/packages/block-editor/src/store/test/reducer.js @@ -46,7 +46,7 @@ import { } from '../reducer'; import { unlock } from '../../lock-unlock'; -import { sectionRootClientIdKey } from '.././private-keys'; +import { sectionRootClientIdKey, isIsolatedEditorKey } from '.././private-keys'; const { isContentBlock } = unlock( privateApis ); @@ -4699,6 +4699,176 @@ describe( 'state', () => { } ); } ); + describe( 'isIsolatedEditor setting', () => { + let stateWithUnsyncedPatternAndTemplatePart; + beforeAll( () => { + // Set up a state with both an unsynced pattern and a template part. + stateWithUnsyncedPatternAndTemplatePart = dispatchActions( + [ + { + type: 'RESET_BLOCKS', + blocks: [ + { + name: 'core/group', + clientId: 'unsynced-pattern', + attributes: { + metadata: { + patternName: 'test-pattern', + }, + }, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: 'pattern-paragraph', + attributes: {}, + innerBlocks: [], + }, + ], + }, + { + name: 'core/template-part', + clientId: 'template-part', + attributes: {}, + innerBlocks: [], + }, + ], + }, + { + type: 'SET_HAS_CONTROLLED_INNER_BLOCKS', + clientId: 'template-part', + hasControlledInnerBlocks: true, + }, + { + type: 'REPLACE_INNER_BLOCKS', + rootClientId: 'template-part', + blocks: [ + { + name: 'core/paragraph', + clientId: 'template-part-paragraph', + attributes: {}, + innerBlocks: [], + }, + ], + }, + ], + testReducer + ); + } ); + + it( 'applies contentOnly modes to unsynced patterns and template parts when isIsolatedEditor is false', () => { + expect( + stateWithUnsyncedPatternAndTemplatePart.derivedBlockEditingModes + ).toEqual( + new Map( + Object.entries( { + 'pattern-paragraph': 'contentOnly', + 'template-part-paragraph': 'contentOnly', + } ) + ) + ); + } ); + + it( 'clears contentOnly modes when isIsolatedEditor changes to true', () => { + const { derivedBlockEditingModes } = dispatchActions( + [ + { + type: 'UPDATE_SETTINGS', + settings: { + [ isIsolatedEditorKey ]: true, + }, + }, + ], + testReducer, + stateWithUnsyncedPatternAndTemplatePart + ); + + expect( derivedBlockEditingModes ).toEqual( new Map() ); + } ); + + it( 'recomputes contentOnly modes when isIsolatedEditor changes from true to false', () => { + const stateWithIsolatedEditor = dispatchActions( + [ + { + type: 'UPDATE_SETTINGS', + settings: { + [ isIsolatedEditorKey ]: true, + }, + }, + ], + testReducer, + stateWithUnsyncedPatternAndTemplatePart + ); + + // Verify that no derived modes exist with isIsolatedEditor enabled. + expect( + stateWithIsolatedEditor.derivedBlockEditingModes + ).toEqual( new Map() ); + + // Now disable isIsolatedEditor and verify modes are recomputed. + const { derivedBlockEditingModes } = dispatchActions( + [ + { + type: 'UPDATE_SETTINGS', + settings: { + [ isIsolatedEditorKey ]: false, + }, + }, + ], + testReducer, + stateWithIsolatedEditor + ); + + expect( derivedBlockEditingModes ).toEqual( + new Map( + Object.entries( { + 'pattern-paragraph': 'contentOnly', + 'template-part-paragraph': 'contentOnly', + } ) + ) + ); + } ); + + it( 'returns no derived editing modes for unsynced patterns when isIsolatedEditor is initially true', () => { + const stateWithIsolatedEditorFromStart = dispatchActions( + [ + { + type: 'UPDATE_SETTINGS', + settings: { + [ isIsolatedEditorKey ]: true, + }, + }, + { + type: 'RESET_BLOCKS', + blocks: [ + { + name: 'core/group', + clientId: 'group-1', + attributes: { + metadata: { + patternName: 'test-pattern', + }, + }, + innerBlocks: [ + { + name: 'core/paragraph', + clientId: 'paragraph-1', + attributes: {}, + innerBlocks: [], + }, + ], + }, + ], + }, + ], + testReducer + ); + + expect( + stateWithIsolatedEditorFromStart.derivedBlockEditingModes + ).toEqual( new Map() ); + } ); + } ); + describe( 'template parts', () => { let initialState; beforeAll( () => {