From 42cedd0d588f27251cf96ad3bee58bd4934ca42f Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 21 Feb 2024 16:07:57 +0100 Subject: [PATCH 01/53] Zoom Out: Only enable the zoom-out mode within the main group --- .../data/data-core-block-editor.md | 4 ++ .../block-list/disable-non-main-blocks.js | 61 +++++++++++++++++++ .../src/components/block-list/index.js | 3 + .../src/components/list-view/branch.js | 8 +-- .../src/components/list-view/index.js | 11 +--- packages/block-editor/src/store/selectors.js | 15 ++++- packages/block-library/src/pattern/edit.js | 25 ++------ .../src/components/header-edit-mode/index.js | 4 +- 8 files changed, 94 insertions(+), 37 deletions(-) create mode 100644 packages/block-editor/src/components/block-list/disable-non-main-blocks.js diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index 486fcddfe04ac6..eb1cfb9c495214 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -726,6 +726,10 @@ _Returns_ - `?string`: Adjacent block's client ID, or null if none exists. +### getSectionsContainerClientId + +Undocumented declaration. + ### getSelectedBlock Returns the currently selected block, or null if there is no selected block. diff --git a/packages/block-editor/src/components/block-list/disable-non-main-blocks.js b/packages/block-editor/src/components/block-list/disable-non-main-blocks.js new file mode 100644 index 00000000000000..6583e6878a82e5 --- /dev/null +++ b/packages/block-editor/src/components/block-list/disable-non-main-blocks.js @@ -0,0 +1,61 @@ +/** + * WordPress dependencies + */ +import { useSelect, useDispatch } from '@wordpress/data'; +import { useEffect } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { useBlockEditingMode } from '../block-editing-mode'; +import { store as blockEditorStore } from '../../store'; + +function EnableBlock( { clientId, mode = 'default' } ) { + const { unsetBlockEditingMode, setBlockEditingMode } = + useDispatch( blockEditorStore ); + useEffect( () => { + setBlockEditingMode( clientId, mode ); + + return () => { + unsetBlockEditingMode( clientId ); + }; + }, [ mode, clientId, unsetBlockEditingMode, setBlockEditingMode ] ); +} + +function DisableNonMainBlocks() { + useBlockEditingMode( 'disabled' ); + const { mainBlockClientId, clientIds } = useSelect( ( select ) => { + const { getSectionsContainerClientId, getClientIdsOfDescendants } = + select( blockEditorStore ); + return { + clientIds: getClientIdsOfDescendants( + getSectionsContainerClientId() + ), + mainBlockClientId: getSectionsContainerClientId(), + }; + }, [] ); + + return ( + <> + + { clientIds.map( ( clientId ) => { + return ; + } ) } + + ); +} + +export default function MaybeDisableNonMainBlocks() { + const { isZoomOutMode } = useSelect( ( select ) => { + const { __unstableGetEditorMode } = select( blockEditorStore ); + return { + isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', + }; + }, [] ); + + if ( ! isZoomOutMode ) { + return; + } + + return ; +} diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index f906372bfa8154..3ebd85c0a0b97b 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -40,6 +40,7 @@ import { } from '../block-edit/context'; import { useTypingObserver } from '../observe-typing'; import { unlock } from '../../lock-unlock'; +import DisableNonMainBlocks from './disable-non-main-blocks'; export const IntersectionObserver = createContext(); const pendingBlockVisibilityUpdatesPerRegistry = new WeakMap(); @@ -119,8 +120,10 @@ function Root( { className, ...settings } ) { }, settings ); + return ( +
{ !! temporarilyEditingAsBlocks && ( { - const { - getGlobalBlockCount, - getClientIdsOfDescendants, - __unstableGetEditorMode, - } = select( blockEditorStore ); + const { getGlobalBlockCount, getClientIdsOfDescendants } = + select( blockEditorStore ); const draggedBlockCount = draggedClientIds?.length > 0 ? getClientIdsOfDescendants( draggedClientIds ).length + 1 : 0; return { visibleBlockCount: getGlobalBlockCount() - draggedBlockCount, - shouldShowInnerBlocks: __unstableGetEditorMode() !== 'zoom-out', }; }, [ draggedClientIds ] @@ -397,7 +393,6 @@ function ListViewComponent( fixedListWindow={ fixedListWindow } selectedClientIds={ selectedClientIds } isExpanded={ isExpanded } - shouldShowInnerBlocks={ shouldShowInnerBlocks } showAppender={ showAppender } /> diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 05138464409c11..78a7ecd9ebda84 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2817,7 +2817,8 @@ export function __unstableHasActiveBlockOverlayActive( state, clientId ) { if ( editorMode === 'zoom-out' && clientId && - ! getBlockRootClientId( state, clientId ) + getBlockRootClientId( state, clientId ) === + getSectionsContainerClientId( state ) ) { return true; } @@ -2977,3 +2978,15 @@ export const isGroupable = createRegistrySelector( ); } ); + +export const getSectionsContainerClientId = createRegistrySelector( + ( select ) => ( state ) => { + const { getGroupingBlockName } = select( blocksStore ); + const groupBlocks = getBlocksByName( state, getGroupingBlockName() ); + + return groupBlocks.find( + ( clientId ) => + getBlockAttributes( state, clientId )?.tagName === 'main' + ); + } +); diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index 7b78796aacd54c..7e31c07e47d9ed 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -32,14 +32,8 @@ const PatternEdit = ( { attributes, clientId } ) => { [] ); - const { - replaceBlocks, - setBlockEditingMode, - __unstableMarkNextChangeAsNotPersistent, - } = useDispatch( blockEditorStore ); - const { getBlockRootClientId, getBlockEditingMode } = - useSelect( blockEditorStore ); - + const { replaceBlocks, __unstableMarkNextChangeAsNotPersistent } = + useDispatch( blockEditorStore ); const [ hasRecursionError, setHasRecursionError ] = useState( false ); const parsePatternDependencies = useParsePatternDependencies(); @@ -89,7 +83,6 @@ const PatternEdit = ( { attributes, clientId } ) => { // because nested pattern blocks cannot be inserted if the parent block supports // inner blocks but doesn't have blockSettings in the state. window.queueMicrotask( () => { - const rootClientId = getBlockRootClientId( clientId ); // Clone blocks from the pattern before insertion to ensure they receive // distinct client ids. See https://github.com/WordPress/gutenberg/issues/50628. const clonedBlocks = selectedPattern.blocks.map( ( block ) => @@ -115,29 +108,21 @@ const PatternEdit = ( { attributes, clientId } ) => { }, }; } - const rootEditingMode = getBlockEditingMode( rootClientId ); registry.batch( () => { - // Temporarily set the root block to default mode to allow replacing the pattern. - // This could happen when the page is disabling edits of non-content blocks. - __unstableMarkNextChangeAsNotPersistent(); - setBlockEditingMode( rootClientId, 'default' ); __unstableMarkNextChangeAsNotPersistent(); replaceBlocks( clientId, clonedBlocks ); - // Restore the root block's original mode. - __unstableMarkNextChangeAsNotPersistent(); - setBlockEditingMode( rootClientId, rootEditingMode ); } ); } ); } }, [ + registry, + parsePatternDependencies, clientId, hasRecursionError, selectedPattern, __unstableMarkNextChangeAsNotPersistent, replaceBlocks, - getBlockEditingMode, - setBlockEditingMode, - getBlockRootClientId, + injectThemeAttributeInBlockTemplateContent, ] ); const props = useBlockProps(); diff --git a/packages/edit-site/src/components/header-edit-mode/index.js b/packages/edit-site/src/components/header-edit-mode/index.js index aed1d9584b2ca6..58f158d3fe3bfc 100644 --- a/packages/edit-site/src/components/header-edit-mode/index.js +++ b/packages/edit-site/src/components/header-edit-mode/index.js @@ -84,8 +84,6 @@ export default function HeaderEditMode() { const isFocusMode = FOCUSABLE_ENTITIES.includes( templateType ); - const isZoomedOutView = blockEditorMode === 'zoom-out'; - const [ isBlockToolsCollapsed, setIsBlockToolsCollapsed ] = useState( true ); @@ -189,7 +187,7 @@ export default function HeaderEditMode() {
Date: Wed, 21 Feb 2024 16:45:52 +0100 Subject: [PATCH 02/53] Hide inner blocks if block has active overlay --- .../src/components/list-view/block.js | 5 +- .../src/components/list-view/branch.js | 50 +++++++++++++------ 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/packages/block-editor/src/components/list-view/block.js b/packages/block-editor/src/components/list-view/block.js index 930d0a0f80ef66..115f7cef2f2083 100644 --- a/packages/block-editor/src/components/list-view/block.js +++ b/packages/block-editor/src/components/list-view/block.js @@ -63,6 +63,7 @@ function ListViewBlock( { isExpanded, selectedClientIds, isSyncedBranch, + hideInnerBlocks, } ) { const cellRef = useRef( null ); const rowRef = useRef( null ); @@ -316,7 +317,9 @@ function ListViewBlock( { path={ path } id={ `list-view-${ listViewInstanceId }-block-${ clientId }` } data-block={ clientId } - data-expanded={ canEdit ? isExpanded : undefined } + data-expanded={ + canEdit && ! hideInnerBlocks ? isExpanded : undefined + } ref={ rowRef } > { + return { + getHasOverlay: + select( blockEditorStore ) + .__unstableHasActiveBlockOverlayActive, + isZoomOutMode: + select( blockEditorStore ).__unstableGetEditorMode() === + 'zoom-out', + }; + }, [] ); + const { blockDropPosition, blockDropTargetIndex, @@ -186,6 +197,9 @@ function ListViewBranch( props ) { const isSelectedBranch = isBranchSelected || ( isSelected && hasNestedBlocks ); + const hideInnerBlocks = + isZoomOutMode && getHasOverlay( clientId ); + // To avoid performance issues, we only render blocks that are in view, // or blocks that are selected or dragged. If a block is selected, // it is only counted if it is the first of the block selection. @@ -218,6 +232,7 @@ function ListViewBranch( props ) { displacement={ displacement } isAfterDraggedBlocks={ isAfterDraggedBlocks } isNesting={ isNesting } + hideInnerBlocks={ hideInnerBlocks } /> ) } { ! showBlock && ( @@ -225,22 +240,25 @@ function ListViewBranch( props ) { ) } - { hasNestedBlocks && shouldExpand && ! isDragged && ( - - ) } + { hasNestedBlocks && + shouldExpand && + ! hideInnerBlocks && + ! isDragged && ( + + ) } ); } ) } From 20b540e57f39da27fd09d1f54bc4904d179b49f0 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Sat, 24 Feb 2024 14:20:27 +0100 Subject: [PATCH 03/53] Account for assembling pages by using post content block as section container --- .../block-list/disable-non-main-blocks.js | 7 +++- packages/block-editor/src/store/selectors.js | 34 ++++++++++++++----- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/components/block-list/disable-non-main-blocks.js b/packages/block-editor/src/components/block-list/disable-non-main-blocks.js index 6583e6878a82e5..a8d220a6165dc1 100644 --- a/packages/block-editor/src/components/block-list/disable-non-main-blocks.js +++ b/packages/block-editor/src/components/block-list/disable-non-main-blocks.js @@ -27,11 +27,16 @@ function DisableNonMainBlocks() { const { mainBlockClientId, clientIds } = useSelect( ( select ) => { const { getSectionsContainerClientId, getClientIdsOfDescendants } = select( blockEditorStore ); + + // TODO: We need a better API as using the post type + // in block editor package is not allowed. + const postType = select( 'core/editor' ).getCurrentPostType(); + return { clientIds: getClientIdsOfDescendants( getSectionsContainerClientId() ), - mainBlockClientId: getSectionsContainerClientId(), + mainBlockClientId: getSectionsContainerClientId( postType ), }; }, [] ); diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 78a7ecd9ebda84..7644fd1ea2e04d 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2980,13 +2980,31 @@ export const isGroupable = createRegistrySelector( ); export const getSectionsContainerClientId = createRegistrySelector( - ( select ) => ( state ) => { - const { getGroupingBlockName } = select( blocksStore ); - const groupBlocks = getBlocksByName( state, getGroupingBlockName() ); + ( select ) => + ( state, postType = 'page' ) => { + const CONTENT_TYPES = [ 'post', 'page' ]; - return groupBlocks.find( - ( clientId ) => - getBlockAttributes( state, clientId )?.tagName === 'main' - ); - } + if ( CONTENT_TYPES.includes( postType ) ) { + const postContentBlocks = getBlocksByName( + state, + 'core/post-content' + ); + + if ( postContentBlocks?.length > 0 ) { + return postContentBlocks[ 0 ]; + } + } + + const { getGroupingBlockName } = select( blocksStore ); + + const groupBlocks = getBlocksByName( + state, + getGroupingBlockName() + ); + + return groupBlocks.find( + ( clientId ) => + getBlockAttributes( state, clientId )?.tagName === 'main' + ); + } ); From d191f7a443f6b977b56ebb3e927fbcc6475b399a Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Sat, 24 Feb 2024 14:28:40 +0100 Subject: [PATCH 04/53] use maybedisable as a name for the disabling component --- packages/block-editor/src/components/block-list/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index 3ebd85c0a0b97b..88ca7297764e76 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -40,7 +40,7 @@ import { } from '../block-edit/context'; import { useTypingObserver } from '../observe-typing'; import { unlock } from '../../lock-unlock'; -import DisableNonMainBlocks from './disable-non-main-blocks'; +import MaybeDisableNonMainBlocks from './disable-non-main-blocks'; export const IntersectionObserver = createContext(); const pendingBlockVisibilityUpdatesPerRegistry = new WeakMap(); @@ -123,7 +123,7 @@ function Root( { className, ...settings } ) { return ( - +
{ !! temporarilyEditingAsBlocks && ( Date: Sat, 24 Feb 2024 14:28:03 +0100 Subject: [PATCH 05/53] Refactor components to hooks --- .../block-list/disable-non-main-blocks.js | 66 ------------------ .../src/components/block-list/index.js | 5 +- .../use-zoom-out-block-editing-mode.js | 68 +++++++++++++++++++ 3 files changed, 71 insertions(+), 68 deletions(-) delete mode 100644 packages/block-editor/src/components/block-list/disable-non-main-blocks.js create mode 100644 packages/block-editor/src/components/block-list/use-zoom-out-block-editing-mode.js diff --git a/packages/block-editor/src/components/block-list/disable-non-main-blocks.js b/packages/block-editor/src/components/block-list/disable-non-main-blocks.js deleted file mode 100644 index a8d220a6165dc1..00000000000000 --- a/packages/block-editor/src/components/block-list/disable-non-main-blocks.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect, useDispatch } from '@wordpress/data'; -import { useEffect } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import { useBlockEditingMode } from '../block-editing-mode'; -import { store as blockEditorStore } from '../../store'; - -function EnableBlock( { clientId, mode = 'default' } ) { - const { unsetBlockEditingMode, setBlockEditingMode } = - useDispatch( blockEditorStore ); - useEffect( () => { - setBlockEditingMode( clientId, mode ); - - return () => { - unsetBlockEditingMode( clientId ); - }; - }, [ mode, clientId, unsetBlockEditingMode, setBlockEditingMode ] ); -} - -function DisableNonMainBlocks() { - useBlockEditingMode( 'disabled' ); - const { mainBlockClientId, clientIds } = useSelect( ( select ) => { - const { getSectionsContainerClientId, getClientIdsOfDescendants } = - select( blockEditorStore ); - - // TODO: We need a better API as using the post type - // in block editor package is not allowed. - const postType = select( 'core/editor' ).getCurrentPostType(); - - return { - clientIds: getClientIdsOfDescendants( - getSectionsContainerClientId() - ), - mainBlockClientId: getSectionsContainerClientId( postType ), - }; - }, [] ); - - return ( - <> - - { clientIds.map( ( clientId ) => { - return ; - } ) } - - ); -} - -export default function MaybeDisableNonMainBlocks() { - const { isZoomOutMode } = useSelect( ( select ) => { - const { __unstableGetEditorMode } = select( blockEditorStore ); - return { - isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', - }; - }, [] ); - - if ( ! isZoomOutMode ) { - return; - } - - return ; -} diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index 88ca7297764e76..5a8356acfbcad6 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -40,7 +40,7 @@ import { } from '../block-edit/context'; import { useTypingObserver } from '../observe-typing'; import { unlock } from '../../lock-unlock'; -import MaybeDisableNonMainBlocks from './disable-non-main-blocks'; +import useZoomOutBlockEditingMode from './use-zoom-out-block-editing-mode'; export const IntersectionObserver = createContext(); const pendingBlockVisibilityUpdatesPerRegistry = new WeakMap(); @@ -121,9 +121,10 @@ function Root( { className, ...settings } ) { settings ); + useZoomOutBlockEditingMode(); + return ( -
{ !! temporarilyEditingAsBlocks && ( { + const { + __unstableGetEditorMode, + getSectionsContainerClientId, + getClientIdsOfDescendants, + } = select( blockEditorStore ); + + // TODO: We need a better API as using the post type + // in block editor package is not allowed. + const postType = select( 'core/editor' ).getCurrentPostType(); + + const _sectionsContainerClientId = + getSectionsContainerClientId( postType ); + + return { + isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', + sectionsContainerClientId: _sectionsContainerClientId, + sectionsClientIds: getClientIdsOfDescendants( + _sectionsContainerClientId + ), + }; + }, [] ); + + useEffect( () => { + if ( isZoomOutMode ) { + setBlockEditingMode( rootClientId, 'disabled' ); + setBlockEditingMode( sectionsContainerClientId, 'contentOnly' ); + sectionsClientIds.forEach( ( clientId ) => { + setBlockEditingMode( clientId, 'default' ); + } ); + + return () => { + sectionsClientIds.forEach( ( clientId ) => { + unsetBlockEditingMode( clientId ); + } ); + unsetBlockEditingMode( sectionsContainerClientId ); + unsetBlockEditingMode( rootClientId ); + }; + } + }, [ + isZoomOutMode, + rootClientId, + sectionsContainerClientId, + // eslint-disable-next-line react-hooks/exhaustive-deps + ...sectionsClientIds, + setBlockEditingMode, + unsetBlockEditingMode, + ] ); +} From 83d66808df79c6416a883c1490d86cdcbd25c882 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Fri, 15 Mar 2024 18:14:56 +0200 Subject: [PATCH 06/53] rebase fix missed isZoomedOutView changes in trunk --- packages/edit-site/src/components/header-edit-mode/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/edit-site/src/components/header-edit-mode/index.js b/packages/edit-site/src/components/header-edit-mode/index.js index 58f158d3fe3bfc..aed1d9584b2ca6 100644 --- a/packages/edit-site/src/components/header-edit-mode/index.js +++ b/packages/edit-site/src/components/header-edit-mode/index.js @@ -84,6 +84,8 @@ export default function HeaderEditMode() { const isFocusMode = FOCUSABLE_ENTITIES.includes( templateType ); + const isZoomedOutView = blockEditorMode === 'zoom-out'; + const [ isBlockToolsCollapsed, setIsBlockToolsCollapsed ] = useState( true ); @@ -187,7 +189,7 @@ export default function HeaderEditMode() {
Date: Wed, 27 Mar 2024 11:21:46 +0000 Subject: [PATCH 07/53] don't spread the client ids --- .../components/block-list/use-zoom-out-block-editing-mode.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-list/use-zoom-out-block-editing-mode.js b/packages/block-editor/src/components/block-list/use-zoom-out-block-editing-mode.js index 5d93f635822a6f..70e937fe79a604 100644 --- a/packages/block-editor/src/components/block-list/use-zoom-out-block-editing-mode.js +++ b/packages/block-editor/src/components/block-list/use-zoom-out-block-editing-mode.js @@ -60,8 +60,7 @@ export default function useZoomOutBlockEditingMode() { isZoomOutMode, rootClientId, sectionsContainerClientId, - // eslint-disable-next-line react-hooks/exhaustive-deps - ...sectionsClientIds, + sectionsClientIds, setBlockEditingMode, unsetBlockEditingMode, ] ); From 5869fb8817e9a2e43ac65e66a15ef990c4f9bff1 Mon Sep 17 00:00:00 2001 From: Ben Dwyer Date: Wed, 27 Mar 2024 17:56:26 +0000 Subject: [PATCH 08/53] create a new selector to find the root section block name --- packages/block-editor/src/store/selectors.js | 40 +++++++++---------- packages/block-library/src/index.js | 2 +- packages/blocks/src/store/actions.js | 7 ++++ packages/blocks/src/store/reducer.js | 4 ++ packages/blocks/src/store/selectors.js | 4 ++ .../edit-site/src/components/editor/index.js | 17 ++++++++ 6 files changed, 51 insertions(+), 23 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 7644fd1ea2e04d..e8ae6b5a8d894e 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2980,31 +2980,27 @@ export const isGroupable = createRegistrySelector( ); export const getSectionsContainerClientId = createRegistrySelector( - ( select ) => - ( state, postType = 'page' ) => { - const CONTENT_TYPES = [ 'post', 'page' ]; - - if ( CONTENT_TYPES.includes( postType ) ) { - const postContentBlocks = getBlocksByName( - state, - 'core/post-content' - ); - - if ( postContentBlocks?.length > 0 ) { - return postContentBlocks[ 0 ]; - } - } - - const { getGroupingBlockName } = select( blocksStore ); - - const groupBlocks = getBlocksByName( - state, - getGroupingBlockName() - ); - + ( select ) => ( state ) => { + const sectionRootBlockName = + select( blocksStore ).getSectionRootBlockName(); + + const { getGroupingBlockName } = select( blocksStore ); + const groupingBlockName = getGroupingBlockName(); + if ( sectionRootBlockName === groupingBlockName ) { + const groupBlocks = getBlocksByName( state, groupingBlockName ); return groupBlocks.find( ( clientId ) => getBlockAttributes( state, clientId )?.tagName === 'main' ); } + + const sectionRootBlocks = getBlocksByName( + state, + sectionRootBlockName + ); + + if ( sectionRootBlocks?.length > 0 ) { + return sectionRootBlocks[ 0 ]; + } + } ); diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index e2e0fd9e414ef3..5c7faa1de93ebd 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -300,7 +300,7 @@ export const registerCoreBlocks = ( setFreeformContentHandlerName( classic.name ); } setUnregisteredTypeHandlerName( missing.name ); - setGroupingBlockName( group.name ); + setGroupingBlockName( postContent.name ); }; /** diff --git a/packages/blocks/src/store/actions.js b/packages/blocks/src/store/actions.js index d3bd71c067ebe3..ce13f2b141bc88 100644 --- a/packages/blocks/src/store/actions.js +++ b/packages/blocks/src/store/actions.js @@ -317,3 +317,10 @@ export function removeBlockCollection( namespace ) { namespace, }; } + +export function setSectionRootBlockName( blockName = 'core/group' ) { + return { + type: 'SET_SECTION_ROOT_BLOCK_NAME', + blockName, + }; +} diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index f92fb376b530a7..627f43d98a4397 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -328,6 +328,9 @@ export const unregisteredFallbackBlockName = createBlockNameSetterReducer( export const groupingBlockName = createBlockNameSetterReducer( 'SET_GROUPING_BLOCK_NAME' ); +export const sectionRootBlockName = createBlockNameSetterReducer( + 'SET_SECTION_ROOT_BLOCK_NAME' +); /** * Reducer managing the categories @@ -407,6 +410,7 @@ export default combineReducers( { freeformFallbackBlockName, unregisteredFallbackBlockName, groupingBlockName, + sectionRootBlockName, categories, collections, blockBindingsSources, diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js index a69879809ab1a6..a427e007a16133 100644 --- a/packages/blocks/src/store/selectors.js +++ b/packages/blocks/src/store/selectors.js @@ -514,6 +514,10 @@ export function getGroupingBlockName( state ) { return state.groupingBlockName; } +export function getSectionRootBlockName( state ) { + return state.sectionRootBlockName; +} + /** * Returns an array with the child blocks of a given block. * diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index f5fdd62ba7dc14..8e27790fefe5ae 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -6,6 +6,7 @@ import classnames from 'classnames'; /** * WordPress dependencies */ +import { store as blocksStore } from '@wordpress/blocks'; import { useDispatch, useSelect } from '@wordpress/data'; import { Notice, @@ -17,6 +18,7 @@ import { useViewportMatch, useReducedMotion, } from '@wordpress/compose'; +import { useEffect } from '@wordpress/element'; import { store as preferencesStore } from '@wordpress/preferences'; import { BlockBreadcrumb, @@ -85,6 +87,15 @@ const interfaceLabels = { const ANIMATION_DURATION = 0.25; +function getSectionRootBlockName( postType ) { + const CONTENT_TYPES = [ 'post', 'page' ]; + + if ( CONTENT_TYPES.includes( postType ) ) { + return 'core/post-content'; + } + return 'core/group'; +} + export default function Editor( { isLoading, onClick } ) { const { record: editedPost, @@ -94,6 +105,12 @@ export default function Editor( { isLoading, onClick } ) { const { type: editedPostType } = editedPost; + const { setSectionRootBlockName } = useDispatch( blocksStore ); + // TODO: find the correct post type here... + useEffect( () => { + setSectionRootBlockName( getSectionRootBlockName( editedPostType ) ); + }, [ editedPostType ] ); + const isLargeViewport = useViewportMatch( 'medium' ); const disableMotion = useReducedMotion(); From 1e1db1f1b8014841828b3580e9a99581b7315c25 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Thu, 28 Mar 2024 09:43:43 +0200 Subject: [PATCH 09/53] correct some variable names, remove testing code --- docs/reference-guides/data/data-core-blocks.md | 8 ++++++++ packages/block-editor/src/store/selectors.js | 3 +-- packages/block-library/src/index.js | 2 +- packages/blocks/src/store/actions.js | 4 ++-- packages/edit-site/src/components/editor/index.js | 11 +++++------ 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/docs/reference-guides/data/data-core-blocks.md b/docs/reference-guides/data/data-core-blocks.md index 084c9c1d7a5fbc..d7bbb574451521 100644 --- a/docs/reference-guides/data/data-core-blocks.md +++ b/docs/reference-guides/data/data-core-blocks.md @@ -504,6 +504,10 @@ _Returns_ - `string?`: Name of the block for handling the grouping of blocks. +### getSectionRootBlockName + +Undocumented declaration. + ### getUnregisteredFallbackBlockName Returns the name of the block for handling unregistered blocks. @@ -718,4 +722,8 @@ Signals that all block types should be computed again. It uses stored unprocesse It addresses the issue where third party block filters get registered after third party blocks. A sample sequence: 1. Filter A. 2. Block B. 3. Block C. 4. Filter D. 5. Filter E. 6. Block F. 7. Filter G. In this scenario some filters would not get applied for all blocks because they are registered too late. +### setSectionRootBlockName + +Undocumented declaration. + diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index e8ae6b5a8d894e..48d745e2bd73ab 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2983,11 +2983,10 @@ export const getSectionsContainerClientId = createRegistrySelector( ( select ) => ( state ) => { const sectionRootBlockName = select( blocksStore ).getSectionRootBlockName(); - const { getGroupingBlockName } = select( blocksStore ); const groupingBlockName = getGroupingBlockName(); if ( sectionRootBlockName === groupingBlockName ) { - const groupBlocks = getBlocksByName( state, groupingBlockName ); + const groupBlocks = getBlocksByName( state, sectionRootBlockName ); return groupBlocks.find( ( clientId ) => getBlockAttributes( state, clientId )?.tagName === 'main' diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index 5c7faa1de93ebd..e2e0fd9e414ef3 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -300,7 +300,7 @@ export const registerCoreBlocks = ( setFreeformContentHandlerName( classic.name ); } setUnregisteredTypeHandlerName( missing.name ); - setGroupingBlockName( postContent.name ); + setGroupingBlockName( group.name ); }; /** diff --git a/packages/blocks/src/store/actions.js b/packages/blocks/src/store/actions.js index ce13f2b141bc88..c5f527d574e185 100644 --- a/packages/blocks/src/store/actions.js +++ b/packages/blocks/src/store/actions.js @@ -318,9 +318,9 @@ export function removeBlockCollection( namespace ) { }; } -export function setSectionRootBlockName( blockName = 'core/group' ) { +export function setSectionRootBlockName( name = 'core/group' ) { return { type: 'SET_SECTION_ROOT_BLOCK_NAME', - blockName, + name, }; } diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 8e27790fefe5ae..9a9198e093b60b 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -105,12 +105,6 @@ export default function Editor( { isLoading, onClick } ) { const { type: editedPostType } = editedPost; - const { setSectionRootBlockName } = useDispatch( blocksStore ); - // TODO: find the correct post type here... - useEffect( () => { - setSectionRootBlockName( getSectionRootBlockName( editedPostType ) ); - }, [ editedPostType ] ); - const isLargeViewport = useViewportMatch( 'medium' ); const disableMotion = useReducedMotion(); @@ -169,6 +163,11 @@ export default function Editor( { isLoading, onClick } ) { }; }, [] ); + const { setSectionRootBlockName } = useDispatch( blocksStore ); + useEffect( () => { + setSectionRootBlockName( getSectionRootBlockName( context?.postType ) ); + }, [ context, setSectionRootBlockName ] ); + const isViewMode = canvasMode === 'view'; const isEditMode = canvasMode === 'edit'; const showVisualEditor = isViewMode || editorMode === 'visual'; From 4c49ed76b9d5c63f9f1d2737c18d319188c8dc91 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Thu, 28 Mar 2024 17:54:27 +0200 Subject: [PATCH 10/53] remove useless call to function in the editor package --- .../block-list/use-zoom-out-block-editing-mode.js | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-list/use-zoom-out-block-editing-mode.js b/packages/block-editor/src/components/block-list/use-zoom-out-block-editing-mode.js index 70e937fe79a604..e2127ab8b24354 100644 --- a/packages/block-editor/src/components/block-list/use-zoom-out-block-editing-mode.js +++ b/packages/block-editor/src/components/block-list/use-zoom-out-block-editing-mode.js @@ -24,12 +24,7 @@ export default function useZoomOutBlockEditingMode() { getClientIdsOfDescendants, } = select( blockEditorStore ); - // TODO: We need a better API as using the post type - // in block editor package is not allowed. - const postType = select( 'core/editor' ).getCurrentPostType(); - - const _sectionsContainerClientId = - getSectionsContainerClientId( postType ); + const _sectionsContainerClientId = getSectionsContainerClientId(); return { isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', From 8b924fa8a554534de90533680e7593ce0eafbd64 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Thu, 28 Mar 2024 20:56:57 +0200 Subject: [PATCH 11/53] remove the useEffect in the editor component of edit site, use the action that sets the context to set the section root block too --- .../edit-site/src/components/editor/index.js | 16 --------- packages/edit-site/src/store/actions.js | 36 ++++++++++++++----- 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/packages/edit-site/src/components/editor/index.js b/packages/edit-site/src/components/editor/index.js index 9a9198e093b60b..f5fdd62ba7dc14 100644 --- a/packages/edit-site/src/components/editor/index.js +++ b/packages/edit-site/src/components/editor/index.js @@ -6,7 +6,6 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { store as blocksStore } from '@wordpress/blocks'; import { useDispatch, useSelect } from '@wordpress/data'; import { Notice, @@ -18,7 +17,6 @@ import { useViewportMatch, useReducedMotion, } from '@wordpress/compose'; -import { useEffect } from '@wordpress/element'; import { store as preferencesStore } from '@wordpress/preferences'; import { BlockBreadcrumb, @@ -87,15 +85,6 @@ const interfaceLabels = { const ANIMATION_DURATION = 0.25; -function getSectionRootBlockName( postType ) { - const CONTENT_TYPES = [ 'post', 'page' ]; - - if ( CONTENT_TYPES.includes( postType ) ) { - return 'core/post-content'; - } - return 'core/group'; -} - export default function Editor( { isLoading, onClick } ) { const { record: editedPost, @@ -163,11 +152,6 @@ export default function Editor( { isLoading, onClick } ) { }; }, [] ); - const { setSectionRootBlockName } = useDispatch( blocksStore ); - useEffect( () => { - setSectionRootBlockName( getSectionRootBlockName( context?.postType ) ); - }, [ context, setSectionRootBlockName ] ); - const isViewMode = canvasMode === 'view'; const isEditMode = canvasMode === 'edit'; const showVisualEditor = isViewMode || editorMode === 'visual'; diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index dfe8f81ca21ccf..9af119845b8d20 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -2,7 +2,11 @@ * WordPress dependencies */ import apiFetch from '@wordpress/api-fetch'; -import { parse, __unstableSerializeAndClean } from '@wordpress/blocks'; +import { + store as blocksStore, + parse, + __unstableSerializeAndClean, +} from '@wordpress/blocks'; import deprecated from '@wordpress/deprecated'; import { addQueryArgs } from '@wordpress/url'; import { __ } from '@wordpress/i18n'; @@ -167,6 +171,15 @@ export function setNavigationMenu( navigationMenuId ) { }; } +function getSectionRootBlockName( postType ) { + const CONTENT_TYPES = [ 'post', 'page' ]; + + if ( CONTENT_TYPES.includes( postType ) ) { + return 'core/post-content'; + } + return 'core/group'; +} + /** * Action that sets an edited entity. * @@ -176,14 +189,21 @@ export function setNavigationMenu( navigationMenuId ) { * * @return {Object} Action object. */ -export function setEditedEntity( postType, postId, context ) { - return { - type: 'SET_EDITED_POST', - postType, - id: postId, - context, +export const setEditedEntity = + ( postType, postId, context ) => + ( { registry, dispatch } ) => { + registry + .dispatch( blocksStore ) + .setSectionRootBlockName( + getSectionRootBlockName( context.postType ) + ); + dispatch( { + type: 'SET_EDITED_POST', + postType, + id: postId, + context, + } ); }; -} /** * @deprecated From ada6ff7fa529a256682e02e46d00f619b607c273 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 28 Mar 2024 15:09:27 -0500 Subject: [PATCH 12/53] WIP Refactor hook to store action --- .../src/components/block-list/index.js | 3 - .../use-zoom-out-block-editing-mode.js | 62 --------------- packages/block-editor/src/store/actions.js | 75 +++++++++++++++++++ packages/block-editor/src/store/reducer.js | 9 +++ 4 files changed, 84 insertions(+), 65 deletions(-) delete mode 100644 packages/block-editor/src/components/block-list/use-zoom-out-block-editing-mode.js diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index 5a8356acfbcad6..4e49dd797ff337 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -40,7 +40,6 @@ import { } from '../block-edit/context'; import { useTypingObserver } from '../observe-typing'; import { unlock } from '../../lock-unlock'; -import useZoomOutBlockEditingMode from './use-zoom-out-block-editing-mode'; export const IntersectionObserver = createContext(); const pendingBlockVisibilityUpdatesPerRegistry = new WeakMap(); @@ -121,8 +120,6 @@ function Root( { className, ...settings } ) { settings ); - useZoomOutBlockEditingMode(); - return (
diff --git a/packages/block-editor/src/components/block-list/use-zoom-out-block-editing-mode.js b/packages/block-editor/src/components/block-list/use-zoom-out-block-editing-mode.js deleted file mode 100644 index e2127ab8b24354..00000000000000 --- a/packages/block-editor/src/components/block-list/use-zoom-out-block-editing-mode.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect, useDispatch } from '@wordpress/data'; -import { useEffect } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import { store as blockEditorStore } from '../../store'; -import { useBlockEditContext } from '../block-edit/context'; - -export default function useZoomOutBlockEditingMode() { - const { clientId: rootClientId = '' } = useBlockEditContext(); - - const { unsetBlockEditingMode, setBlockEditingMode } = - useDispatch( blockEditorStore ); - - const { isZoomOutMode, sectionsContainerClientId, sectionsClientIds } = - useSelect( ( select ) => { - const { - __unstableGetEditorMode, - getSectionsContainerClientId, - getClientIdsOfDescendants, - } = select( blockEditorStore ); - - const _sectionsContainerClientId = getSectionsContainerClientId(); - - return { - isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', - sectionsContainerClientId: _sectionsContainerClientId, - sectionsClientIds: getClientIdsOfDescendants( - _sectionsContainerClientId - ), - }; - }, [] ); - - useEffect( () => { - if ( isZoomOutMode ) { - setBlockEditingMode( rootClientId, 'disabled' ); - setBlockEditingMode( sectionsContainerClientId, 'contentOnly' ); - sectionsClientIds.forEach( ( clientId ) => { - setBlockEditingMode( clientId, 'default' ); - } ); - - return () => { - sectionsClientIds.forEach( ( clientId ) => { - unsetBlockEditingMode( clientId ); - } ); - unsetBlockEditingMode( sectionsContainerClientId ); - unsetBlockEditingMode( rootClientId ); - }; - } - }, [ - isZoomOutMode, - rootClientId, - sectionsContainerClientId, - sectionsClientIds, - setBlockEditingMode, - unsetBlockEditingMode, - ] ); -} diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index e9281727804f1c..16adca0f7b3cbd 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1445,6 +1445,36 @@ export const __unstableSetEditorMode = } } + // TODO: Cleanup this for better performance/readability. + // When switching to zoom-out mode, we need to disable editing mode for all blocks except the sections. + const sectionsContainerClientId = select.getSectionsContainerClientId(); + const sectionsClientIds = select.getClientIdsOfDescendants( + sectionsContainerClientId + ); + if ( mode === 'zoom-out' ) { + dispatch( + setBlockEditingModes( [ + [ '' /* rootClientId */, 'disabled' ], + [ sectionsContainerClientId, 'contentOnly' ], + ...sectionsClientIds.map( ( clientId ) => [ + clientId, + 'default', + ] ), + ] ) + ); + } else { + const prevMode = select.__unstableGetEditorMode(); + if ( prevMode === 'zoom-out' ) { + dispatch( + unsetBlockEditingModes( [ + '' /* rootClientId */, + sectionsContainerClientId, + ...sectionsClientIds, + ] ) + ); + } + } + dispatch( { type: 'SET_EDITOR_MODE', mode } ); if ( mode === 'navigation' ) { @@ -1911,6 +1941,35 @@ export function setBlockEditingMode( clientId = '', mode ) { }; } +/** + * @typedef {Iterable.<[string, BlockEditingMode]>} BlockEditingModes + */ + +/** + * Sets the block editing mode for a multiple blocks. + * + * @see useBlockEditingMode + * + * @example + * ```js + * wp.data.dispatch('core/block-editor').setBlockEditingModes([ + * ['block-1', 'disabled'], + * ['block-2', 'contentOnly'], + * ['block-3', 'default'], + * ]); + * ``` + * + * @param {BlockEditingModes} modes Iterable of client ids and block editing modes. + * + * @return {Object} Action object. + */ +export function setBlockEditingModes( modes ) { + return { + type: 'SET_BLOCK_EDITING_MODE', + modes, + }; +} + /** * Clears the block editing mode for a given block. * @@ -1926,3 +1985,19 @@ export function unsetBlockEditingMode( clientId = '' ) { clientId, }; } + +/** + * Clears the block editing mode for a given block. + * + * @see useBlockEditingMode + * + * @param {string[]} clientIds The block client ID, or `''` for the root container. + * + * @return {Object} Action object. + */ +export function unsetBlockEditingModes( clientIds = [] ) { + return { + type: 'UNSET_BLOCK_EDITING_MODE', + clientIds, + }; +} diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 13024d4d2e8fac..0bc3759324720f 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1981,11 +1981,20 @@ export function blockEditingModes( state = new Map(), action ) { switch ( action.type ) { case 'SET_BLOCK_EDITING_MODE': return new Map( state ).set( action.clientId, action.mode ); + case 'SET_BLOCK_EDITING_MODES': + return new Map( ...state, ...action.modes ); case 'UNSET_BLOCK_EDITING_MODE': { const newState = new Map( state ); newState.delete( action.clientId ); return newState; } + case 'UNSET_BLOCK_EDITING_MODES': { + const newState = new Map( state ); + action.clientIds.forEach( ( clientId ) => + newState.delete( clientId ) + ); + return newState; + } case 'RESET_BLOCKS': { return state.has( '' ) ? new Map().set( '', state.get( '' ) ) From 53b2ef13e0a5ea0439d8278177bde2c53458e6f4 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 28 Mar 2024 16:09:29 -0500 Subject: [PATCH 13/53] Fix copy/paste mistake --- packages/block-editor/src/store/actions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 16adca0f7b3cbd..d0df68ab259bff 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1965,7 +1965,7 @@ export function setBlockEditingMode( clientId = '', mode ) { */ export function setBlockEditingModes( modes ) { return { - type: 'SET_BLOCK_EDITING_MODE', + type: 'SET_BLOCK_EDITING_MODES', modes, }; } @@ -1997,7 +1997,7 @@ export function unsetBlockEditingMode( clientId = '' ) { */ export function unsetBlockEditingModes( clientIds = [] ) { return { - type: 'UNSET_BLOCK_EDITING_MODE', + type: 'UNSET_BLOCK_EDITING_MODES', clientIds, }; } From 8906c332e0f703d9e9d8d920d7949e6796275ed2 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Fri, 29 Mar 2024 13:18:13 +0200 Subject: [PATCH 14/53] combine state and modes in the reducer correctly into one iterable --- .../data/data-core-block-editor.md | 42 +++++++++++++++++++ packages/block-editor/src/store/reducer.js | 2 +- 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index eb1cfb9c495214..79e1fe6b43199c 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -1643,6 +1643,32 @@ _Returns_ - `Object`: Action object. +### setBlockEditingModes + +Sets the block editing mode for a multiple blocks. + +_Related_ + +- useBlockEditingMode + +_Usage_ + +```js +wp.data.dispatch( 'core/block-editor' ).setBlockEditingModes( [ + [ 'block-1', 'disabled' ], + [ 'block-2', 'contentOnly' ], + [ 'block-3', 'default' ], +] ); +``` + +_Parameters_ + +- _modes_ `BlockEditingModes`: Iterable of client ids and block editing modes. + +_Returns_ + +- `Object`: Action object. + ### setBlockMovingClientId Action that enables or disables the block moving mode. @@ -1816,6 +1842,22 @@ _Returns_ - `Object`: Action object. +### unsetBlockEditingModes + +Clears the block editing mode for a given block. + +_Related_ + +- useBlockEditingMode + +_Parameters_ + +- _clientIds_ `string[]`: The block client ID, or `''` for the root container. + +_Returns_ + +- `Object`: Action object. + ### updateBlock Action that updates the block with the specified client ID. diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index 0bc3759324720f..f2864ded91179d 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1982,7 +1982,7 @@ export function blockEditingModes( state = new Map(), action ) { case 'SET_BLOCK_EDITING_MODE': return new Map( state ).set( action.clientId, action.mode ); case 'SET_BLOCK_EDITING_MODES': - return new Map( ...state, ...action.modes ); + return new Map( [ ...state, ...action.modes ] ); case 'UNSET_BLOCK_EDITING_MODE': { const newState = new Map( state ); newState.delete( action.clientId ); From d68bb3ad2e28cf8fa245c0f4d5de731164c8678d Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Fri, 29 Mar 2024 16:47:45 +0200 Subject: [PATCH 15/53] enable selection for no root section block --- packages/block-editor/src/store/actions.js | 37 ++++++++++++++------ packages/block-editor/src/store/selectors.js | 13 ++++++- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index d0df68ab259bff..ef4301dfdbc270 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1437,31 +1437,46 @@ export const __unstableSetEditorMode = if ( mode === 'zoom-out' ) { const firstSelectedClientId = select.getBlockSelectionStart(); if ( firstSelectedClientId ) { - dispatch.selectBlock( - select.getBlockHierarchyRootClientId( - firstSelectedClientId - ) + const rootClientId = select.getBlockHierarchyRootClientId( + firstSelectedClientId ); + dispatch.selectBlock( rootClientId ); } } // TODO: Cleanup this for better performance/readability. // When switching to zoom-out mode, we need to disable editing mode for all blocks except the sections. const sectionsContainerClientId = select.getSectionsContainerClientId(); - const sectionsClientIds = select.getClientIdsOfDescendants( - sectionsContainerClientId - ); + let sectionsClientIds = []; + if ( sectionsContainerClientId ) { + sectionsClientIds = select.getClientIdsOfDescendants( + sectionsContainerClientId + ); + } else { + sectionsClientIds = select.getBlockOrder( null ); + } + if ( mode === 'zoom-out' ) { - dispatch( - setBlockEditingModes( [ + let modes = []; + if ( sectionsContainerClientId ) { + modes = [ [ '' /* rootClientId */, 'disabled' ], [ sectionsContainerClientId, 'contentOnly' ], ...sectionsClientIds.map( ( clientId ) => [ clientId, 'default', ] ), - ] ) - ); + ]; + } else { + modes = [ + [ '' /* rootClientId */, 'contentOnly' ], + ...sectionsClientIds.map( ( clientId ) => [ + clientId, + 'contentOnly', + ] ), + ]; + } + dispatch( setBlockEditingModes( modes ) ); } else { const prevMode = select.__unstableGetEditorMode(); if ( prevMode === 'zoom-out' ) { diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 48d745e2bd73ab..88b72783a824b4 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2985,12 +2985,19 @@ export const getSectionsContainerClientId = createRegistrySelector( select( blocksStore ).getSectionRootBlockName(); const { getGroupingBlockName } = select( blocksStore ); const groupingBlockName = getGroupingBlockName(); + if ( sectionRootBlockName === groupingBlockName ) { const groupBlocks = getBlocksByName( state, sectionRootBlockName ); - return groupBlocks.find( + const mainGroup = groupBlocks.find( ( clientId ) => getBlockAttributes( state, clientId )?.tagName === 'main' ); + if ( mainGroup ) { + return mainGroup; + } + // if there is no main group and no other block is specified + // as section root + return null; } const sectionRootBlocks = getBlocksByName( @@ -3001,5 +3008,9 @@ export const getSectionsContainerClientId = createRegistrySelector( if ( sectionRootBlocks?.length > 0 ) { return sectionRootBlocks[ 0 ]; } + + // if other block is specified + // as section root, but its not found + return null; } ); From bb01ba40eae1c19ddf2536ced841832a02f1adf4 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Fri, 29 Mar 2024 18:11:18 +0200 Subject: [PATCH 16/53] enable section selection for sections when there is no root section container --- packages/block-editor/src/store/actions.js | 30 +++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index ef4301dfdbc270..0b8c9f93d87b4c 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1448,12 +1448,32 @@ export const __unstableSetEditorMode = // When switching to zoom-out mode, we need to disable editing mode for all blocks except the sections. const sectionsContainerClientId = select.getSectionsContainerClientId(); let sectionsClientIds = []; + let sectionClientIdsInnerBlocks = []; + let disabledSectionsClientIds = []; if ( sectionsContainerClientId ) { sectionsClientIds = select.getClientIdsOfDescendants( sectionsContainerClientId ); } else { - sectionsClientIds = select.getBlockOrder( null ); + sectionsClientIds = select.getBlockOrder(); + disabledSectionsClientIds = sectionsClientIds + .map( ( clientId ) => { + return select.getBlock( clientId ); + } ) + .filter( ( block ) => block.name === 'core/template-part' ) + .map( ( block ) => block.clientId ); + + sectionClientIdsInnerBlocks = sectionsClientIds.flatMap( + ( clientId ) => { + const block = select.getBlock( clientId ); + if ( block.name === 'core/template-part' ) { + return []; + } + return block.innerBlocks.map( + ( innerBlock ) => innerBlock.clientId + ); + } + ); } if ( mode === 'zoom-out' ) { @@ -1474,6 +1494,14 @@ export const __unstableSetEditorMode = clientId, 'contentOnly', ] ), + ...disabledSectionsClientIds.map( ( clientId ) => [ + clientId, + 'disabled', + ] ), + ...sectionClientIdsInnerBlocks.map( ( clientId ) => [ + clientId, + 'disabled', + ] ), ]; } dispatch( setBlockEditingModes( modes ) ); From 61b90784868d989e977b44adb4f9fd3d481c4e7e Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 1 Apr 2024 11:43:13 -0500 Subject: [PATCH 17/53] Use registry.batch instead --- packages/block-editor/src/store/actions.js | 69 +++++++++++----------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 0b8c9f93d87b4c..ab0455d3538bd1 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1432,7 +1432,7 @@ export const setNavigationMode = */ export const __unstableSetEditorMode = ( mode ) => - ( { dispatch, select } ) => { + ( { dispatch, select, registry } ) => { // When switching to zoom-out mode, we need to select the root block if ( mode === 'zoom-out' ) { const firstSelectedClientId = select.getBlockSelectionStart(); @@ -1477,44 +1477,47 @@ export const __unstableSetEditorMode = } if ( mode === 'zoom-out' ) { - let modes = []; - if ( sectionsContainerClientId ) { - modes = [ - [ '' /* rootClientId */, 'disabled' ], - [ sectionsContainerClientId, 'contentOnly' ], - ...sectionsClientIds.map( ( clientId ) => [ - clientId, - 'default', - ] ), - ]; - } else { - modes = [ - [ '' /* rootClientId */, 'contentOnly' ], - ...sectionsClientIds.map( ( clientId ) => [ - clientId, - 'contentOnly', - ] ), - ...disabledSectionsClientIds.map( ( clientId ) => [ - clientId, - 'disabled', - ] ), - ...sectionClientIdsInnerBlocks.map( ( clientId ) => [ - clientId, - 'disabled', - ] ), - ]; - } - dispatch( setBlockEditingModes( modes ) ); + registry.batch( () => { + const modes = sectionsContainerClientId + ? [ + [ '' /* rootClientId */, 'disabled' ], + [ sectionsContainerClientId, 'contentOnly' ], + ...sectionsClientIds.map( ( clientId ) => [ + clientId, + 'default', + ] ), + ] + : [ + [ '' /* rootClientId */, 'contentOnly' ], + ...sectionsClientIds.map( ( clientId ) => [ + clientId, + 'contentOnly', + ] ), + ...disabledSectionsClientIds.map( ( clientId ) => [ + clientId, + 'disabled', + ] ), + ...sectionClientIdsInnerBlocks.map( + ( clientId ) => [ clientId, 'disabled' ] + ), + ]; + modes.forEach( ( [ clientId, newMode ] ) => { + dispatch( setBlockEditingMode( clientId, newMode ) ); + } ); + } ); } else { const prevMode = select.__unstableGetEditorMode(); if ( prevMode === 'zoom-out' ) { - dispatch( - unsetBlockEditingModes( [ + registry.batch( () => { + const modes = [ '' /* rootClientId */, sectionsContainerClientId, ...sectionsClientIds, - ] ) - ); + ]; + modes.forEach( ( clientId ) => { + dispatch( unsetBlockEditingMode( clientId ) ); + } ); + } ); } } From a828c9cea18722d0732d5d099f038e98b48420c4 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Mon, 1 Apr 2024 12:26:21 -0500 Subject: [PATCH 18/53] Replace bulk actions with registry.batch --- packages/block-editor/src/store/actions.js | 103 +++++---------------- 1 file changed, 25 insertions(+), 78 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index ab0455d3538bd1..251edd489f54c7 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1478,44 +1478,36 @@ export const __unstableSetEditorMode = if ( mode === 'zoom-out' ) { registry.batch( () => { - const modes = sectionsContainerClientId - ? [ - [ '' /* rootClientId */, 'disabled' ], - [ sectionsContainerClientId, 'contentOnly' ], - ...sectionsClientIds.map( ( clientId ) => [ - clientId, - 'default', - ] ), - ] - : [ - [ '' /* rootClientId */, 'contentOnly' ], - ...sectionsClientIds.map( ( clientId ) => [ - clientId, - 'contentOnly', - ] ), - ...disabledSectionsClientIds.map( ( clientId ) => [ - clientId, - 'disabled', - ] ), - ...sectionClientIdsInnerBlocks.map( - ( clientId ) => [ clientId, 'disabled' ] - ), - ]; - modes.forEach( ( [ clientId, newMode ] ) => { - dispatch( setBlockEditingMode( clientId, newMode ) ); - } ); + if ( sectionsContainerClientId ) { + setBlockEditingMode( '' /* rootClientId */, 'disabled' ); + setBlockEditingMode( + sectionsContainerClientId, + 'contentOnly' + ); + sectionsClientIds.forEach( ( clientId ) => + setBlockEditingMode( clientId, 'default' ) + ); + } else { + setBlockEditingMode( '' /* rootClientId */, 'contentOnly' ); + sectionsClientIds.forEach( ( clientId ) => + setBlockEditingMode( clientId, 'contentOnly' ) + ); + disabledSectionsClientIds.forEach( ( clientId ) => + setBlockEditingMode( clientId, 'disabled' ) + ); + sectionClientIdsInnerBlocks.forEach( ( clientId ) => + setBlockEditingMode( clientId, 'disabled' ) + ); + } } ); } else { const prevMode = select.__unstableGetEditorMode(); if ( prevMode === 'zoom-out' ) { registry.batch( () => { - const modes = [ - '' /* rootClientId */, - sectionsContainerClientId, - ...sectionsClientIds, - ]; - modes.forEach( ( clientId ) => { - dispatch( unsetBlockEditingMode( clientId ) ); + unsetBlockEditingMode( '' /* rootClientId */ ); + unsetBlockEditingMode( sectionsContainerClientId ); + sectionsClientIds.forEach( ( clientId ) => { + unsetBlockEditingMode( clientId ); } ); } ); } @@ -1987,35 +1979,6 @@ export function setBlockEditingMode( clientId = '', mode ) { }; } -/** - * @typedef {Iterable.<[string, BlockEditingMode]>} BlockEditingModes - */ - -/** - * Sets the block editing mode for a multiple blocks. - * - * @see useBlockEditingMode - * - * @example - * ```js - * wp.data.dispatch('core/block-editor').setBlockEditingModes([ - * ['block-1', 'disabled'], - * ['block-2', 'contentOnly'], - * ['block-3', 'default'], - * ]); - * ``` - * - * @param {BlockEditingModes} modes Iterable of client ids and block editing modes. - * - * @return {Object} Action object. - */ -export function setBlockEditingModes( modes ) { - return { - type: 'SET_BLOCK_EDITING_MODES', - modes, - }; -} - /** * Clears the block editing mode for a given block. * @@ -2031,19 +1994,3 @@ export function unsetBlockEditingMode( clientId = '' ) { clientId, }; } - -/** - * Clears the block editing mode for a given block. - * - * @see useBlockEditingMode - * - * @param {string[]} clientIds The block client ID, or `''` for the root container. - * - * @return {Object} Action object. - */ -export function unsetBlockEditingModes( clientIds = [] ) { - return { - type: 'UNSET_BLOCK_EDITING_MODES', - clientIds, - }; -} From 212d63850243cf5feec82b8e6c8e24f6102baccf Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Mon, 1 Apr 2024 20:35:35 +0300 Subject: [PATCH 19/53] make section root selector and action private --- .../data/data-core-block-editor.md | 42 ------------------- .../reference-guides/data/data-core-blocks.md | 8 ---- packages/block-editor/src/store/selectors.js | 4 +- packages/blocks/src/store/actions.js | 7 ---- packages/blocks/src/store/private-actions.js | 15 +++++++ .../blocks/src/store/private-selectors.js | 11 +++++ packages/blocks/src/store/selectors.js | 4 -- packages/edit-site/src/store/actions.js | 14 ++++--- 8 files changed, 36 insertions(+), 69 deletions(-) diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index 79e1fe6b43199c..eb1cfb9c495214 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -1643,32 +1643,6 @@ _Returns_ - `Object`: Action object. -### setBlockEditingModes - -Sets the block editing mode for a multiple blocks. - -_Related_ - -- useBlockEditingMode - -_Usage_ - -```js -wp.data.dispatch( 'core/block-editor' ).setBlockEditingModes( [ - [ 'block-1', 'disabled' ], - [ 'block-2', 'contentOnly' ], - [ 'block-3', 'default' ], -] ); -``` - -_Parameters_ - -- _modes_ `BlockEditingModes`: Iterable of client ids and block editing modes. - -_Returns_ - -- `Object`: Action object. - ### setBlockMovingClientId Action that enables or disables the block moving mode. @@ -1842,22 +1816,6 @@ _Returns_ - `Object`: Action object. -### unsetBlockEditingModes - -Clears the block editing mode for a given block. - -_Related_ - -- useBlockEditingMode - -_Parameters_ - -- _clientIds_ `string[]`: The block client ID, or `''` for the root container. - -_Returns_ - -- `Object`: Action object. - ### updateBlock Action that updates the block with the specified client ID. diff --git a/docs/reference-guides/data/data-core-blocks.md b/docs/reference-guides/data/data-core-blocks.md index d7bbb574451521..084c9c1d7a5fbc 100644 --- a/docs/reference-guides/data/data-core-blocks.md +++ b/docs/reference-guides/data/data-core-blocks.md @@ -504,10 +504,6 @@ _Returns_ - `string?`: Name of the block for handling the grouping of blocks. -### getSectionRootBlockName - -Undocumented declaration. - ### getUnregisteredFallbackBlockName Returns the name of the block for handling unregistered blocks. @@ -722,8 +718,4 @@ Signals that all block types should be computed again. It uses stored unprocesse It addresses the issue where third party block filters get registered after third party blocks. A sample sequence: 1. Filter A. 2. Block B. 3. Block C. 4. Filter D. 5. Filter E. 6. Block F. 7. Filter G. In this scenario some filters would not get applied for all blocks because they are registered too late. -### setSectionRootBlockName - -Undocumented declaration. - diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 88b72783a824b4..d43a8e12a957b9 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2981,8 +2981,8 @@ export const isGroupable = createRegistrySelector( export const getSectionsContainerClientId = createRegistrySelector( ( select ) => ( state ) => { - const sectionRootBlockName = - select( blocksStore ).getSectionRootBlockName(); + const { getSectionRootBlockName } = unlock( select( blocksStore ) ); + const sectionRootBlockName = getSectionRootBlockName(); const { getGroupingBlockName } = select( blocksStore ); const groupingBlockName = getGroupingBlockName(); diff --git a/packages/blocks/src/store/actions.js b/packages/blocks/src/store/actions.js index c5f527d574e185..d3bd71c067ebe3 100644 --- a/packages/blocks/src/store/actions.js +++ b/packages/blocks/src/store/actions.js @@ -317,10 +317,3 @@ export function removeBlockCollection( namespace ) { namespace, }; } - -export function setSectionRootBlockName( name = 'core/group' ) { - return { - type: 'SET_SECTION_ROOT_BLOCK_NAME', - name, - }; -} diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index d609f70b91b55d..57345541d78f2d 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -55,3 +55,18 @@ export function registerBlockBindingsSource( source ) { lockAttributesEditing: source.lockAttributesEditing, }; } + +/** + * Returns an action object used to set the name of the block used + * to wrap sections + * + * @param {string} name Block name. + * + * @return {Object} Action object. + */ +export function setSectionRootBlockName( name = 'core/group' ) { + return { + type: 'SET_SECTION_ROOT_BLOCK_NAME', + name, + }; +} diff --git a/packages/blocks/src/store/private-selectors.js b/packages/blocks/src/store/private-selectors.js index 4cded8268ae97c..84cc05de6e6ff1 100644 --- a/packages/blocks/src/store/private-selectors.js +++ b/packages/blocks/src/store/private-selectors.js @@ -209,3 +209,14 @@ export function getAllBlockBindingsSources( state ) { export function getBlockBindingsSource( state, sourceName ) { return state.blockBindingsSources[ sourceName ]; } + +/** + * Returns the name of the block for handling the wrapping of sectios. + * + * @param {Object} state Data state. + * + * @return {string?} Name of the block for handling the grouping of blocks. + */ +export function getSectionRootBlockName( state ) { + return state.sectionRootBlockName; +} diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js index a427e007a16133..a69879809ab1a6 100644 --- a/packages/blocks/src/store/selectors.js +++ b/packages/blocks/src/store/selectors.js @@ -514,10 +514,6 @@ export function getGroupingBlockName( state ) { return state.groupingBlockName; } -export function getSectionRootBlockName( state ) { - return state.sectionRootBlockName; -} - /** * Returns an array with the child blocks of a given block. * diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index 9af119845b8d20..b60dfa5cebb95d 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -28,6 +28,7 @@ import { NAVIGATION_POST_TYPE, } from '../utils/constants'; import { removeTemplates } from './private-actions'; +import { unlock } from '../lock-unlock'; /** * Dispatches an action that toggles a feature flag. @@ -171,7 +172,7 @@ export function setNavigationMenu( navigationMenuId ) { }; } -function getSectionRootBlockName( postType ) { +function getSectionRootBlockNameFromPostType( postType ) { const CONTENT_TYPES = [ 'post', 'page' ]; if ( CONTENT_TYPES.includes( postType ) ) { @@ -192,11 +193,12 @@ function getSectionRootBlockName( postType ) { export const setEditedEntity = ( postType, postId, context ) => ( { registry, dispatch } ) => { - registry - .dispatch( blocksStore ) - .setSectionRootBlockName( - getSectionRootBlockName( context.postType ) - ); + const { setSectionRootBlockName } = unlock( + registry.dispatch( blocksStore ) + ); + setSectionRootBlockName( + getSectionRootBlockNameFromPostType( context.postType ) + ); dispatch( { type: 'SET_EDITED_POST', postType, From 4d8c43cd4057e885f22018bc93c83e10de5fe713 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Tue, 2 Apr 2024 15:13:11 +0300 Subject: [PATCH 20/53] dispatch set block mode action --- packages/block-editor/src/store/actions.js | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 251edd489f54c7..4cbb95a7c51c2d 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1479,24 +1479,30 @@ export const __unstableSetEditorMode = if ( mode === 'zoom-out' ) { registry.batch( () => { if ( sectionsContainerClientId ) { - setBlockEditingMode( '' /* rootClientId */, 'disabled' ); - setBlockEditingMode( + dispatch.setBlockEditingMode( + '' /* rootClientId */, + 'disabled' + ); + dispatch.setBlockEditingMode( sectionsContainerClientId, 'contentOnly' ); sectionsClientIds.forEach( ( clientId ) => - setBlockEditingMode( clientId, 'default' ) + dispatch.setBlockEditingMode( clientId, 'default' ) ); } else { - setBlockEditingMode( '' /* rootClientId */, 'contentOnly' ); + dispatch.setBlockEditingMode( + '' /* rootClientId */, + 'contentOnly' + ); sectionsClientIds.forEach( ( clientId ) => - setBlockEditingMode( clientId, 'contentOnly' ) + dispatch.setBlockEditingMode( clientId, 'contentOnly' ) ); disabledSectionsClientIds.forEach( ( clientId ) => - setBlockEditingMode( clientId, 'disabled' ) + dispatch.setBlockEditingMode( clientId, 'disabled' ) ); sectionClientIdsInnerBlocks.forEach( ( clientId ) => - setBlockEditingMode( clientId, 'disabled' ) + dispatch.setBlockEditingMode( clientId, 'disabled' ) ); } } ); From 207126a20ac00880e23e3f0dc5cd6ec92e5a60d8 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 3 Apr 2024 17:33:31 -0500 Subject: [PATCH 21/53] privatize the section root block client id selector Conflicts: packages/block-editor/src/store/private-selectors.js --- .../data/data-core-block-editor.md | 4 - packages/block-editor/src/store/actions.js | 6 +- .../src/store/private-selectors.js | 47 +++++++ packages/block-editor/src/store/selectors.js | 127 +++++++----------- 4 files changed, 100 insertions(+), 84 deletions(-) diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index eb1cfb9c495214..486fcddfe04ac6 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -726,10 +726,6 @@ _Returns_ - `?string`: Adjacent block's client ID, or null if none exists. -### getSectionsContainerClientId - -Undocumented declaration. - ### getSelectedBlock Returns the currently selected block, or null if there is no selected block. diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 4cbb95a7c51c2d..fbc1dac84d1729 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -31,6 +31,8 @@ import { __experimentalUpdateSettings, privateRemoveBlocks, } from './private-actions'; +import { unlock } from '../lock-unlock'; +import { STORE_NAME } from './constants'; /** @typedef {import('../components/use-on-block-drop/types').WPDropOperation} WPDropOperation */ @@ -1446,7 +1448,9 @@ export const __unstableSetEditorMode = // TODO: Cleanup this for better performance/readability. // When switching to zoom-out mode, we need to disable editing mode for all blocks except the sections. - const sectionsContainerClientId = select.getSectionsContainerClientId(); + const sectionsContainerClientId = unlock( + registry.select( STORE_NAME ) + ).getSectionsContainerClientId(); let sectionsClientIds = []; let sectionClientIdsInnerBlocks = []; let disabledSectionsClientIds = []; diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index bc4a3ba1a797c5..2e83c98f3baefe 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -2,6 +2,7 @@ * WordPress dependencies */ import { createSelector, createRegistrySelector } from '@wordpress/data'; +import { store as blocksStore } from '@wordpress/blocks'; /** * Internal dependencies @@ -12,6 +13,8 @@ import { getBlockEditingMode, getSettings, canInsertBlockType, + getBlocksByName, + getBlockAttributes, } from './selectors'; import { checkAllowListRecursive, @@ -375,3 +378,47 @@ export function isDragging( state ) { export function getExpandedBlock( state ) { return state.expandedBlock; } + +/** + * Retrieves the client id of the section container block. + * + * @param {Object} state Block editor state. + * + * @return {string|null} The client ID of the section container block, + * null if not found. + */ +export const getSectionsContainerClientId = createRegistrySelector( + ( select ) => ( state ) => { + const { getSectionRootBlockName } = unlock( select( blocksStore ) ); + const sectionRootBlockName = getSectionRootBlockName(); + const { getGroupingBlockName } = select( blocksStore ); + const groupingBlockName = getGroupingBlockName(); + + if ( sectionRootBlockName === groupingBlockName ) { + const groupBlocks = getBlocksByName( state, sectionRootBlockName ); + const mainGroup = groupBlocks.find( + ( clientId ) => + getBlockAttributes( state, clientId )?.tagName === 'main' + ); + if ( mainGroup ) { + return mainGroup; + } + // if there is no main group and no other block is specified + // as section root + return null; + } + + const sectionRootBlocks = getBlocksByName( + state, + sectionRootBlockName + ); + + if ( sectionRootBlocks?.length > 0 ) { + return sectionRootBlocks[ 0 ]; + } + + // if other block is specified + // as section root, but its not found + return null; + } +); diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index d43a8e12a957b9..f4f1621449e7cf 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2797,54 +2797,59 @@ export function __unstableGetTemporarilyEditingFocusModeToRevert( state ) { return state.temporarilyEditingFocusModeRevert; } -export function __unstableHasActiveBlockOverlayActive( state, clientId ) { - // Prevent overlay on blocks with a non-default editing mode. If the mdoe is - // 'disabled' then the overlay is redundant since the block can't be - // selected. If the mode is 'contentOnly' then the overlay is redundant - // since there will be no controls to interact with once selected. - if ( getBlockEditingMode( state, clientId ) !== 'default' ) { - return false; - } +export const __unstableHasActiveBlockOverlayActive = createRegistrySelector( + ( select ) => + createSelector( ( state, clientId ) => { + // Prevent overlay on blocks with a non-default editing mode. If the mdoe is + // 'disabled' then the overlay is redundant since the block can't be + // selected. If the mode is 'contentOnly' then the overlay is redundant + // since there will be no controls to interact with once selected. + if ( getBlockEditingMode( state, clientId ) !== 'default' ) { + return false; + } - // If the block editing is locked, the block overlay is always active. - if ( ! canEditBlock( state, clientId ) ) { - return true; - } + // If the block editing is locked, the block overlay is always active. + if ( ! canEditBlock( state, clientId ) ) { + return true; + } - const editorMode = __unstableGetEditorMode( state ); + const editorMode = __unstableGetEditorMode( state ); - // In zoom-out mode, the block overlay is always active for top level blocks. - if ( - editorMode === 'zoom-out' && - clientId && - getBlockRootClientId( state, clientId ) === - getSectionsContainerClientId( state ) - ) { - return true; - } + // In zoom-out mode, the block overlay is always active for top level blocks. + if ( + editorMode === 'zoom-out' && + clientId && + getBlockRootClientId( state, clientId ) === + unlock( select( STORE_NAME ) ).getSectionsContainerClientId( + state + ) + ) { + return true; + } - // In navigation mode, the block overlay is active when the block is not - // selected (and doesn't contain a selected child). The same behavior is - // also enabled in all modes for blocks that have controlled children - // (reusable block, template part, navigation), unless explicitly disabled - // with `supports.__experimentalDisableBlockOverlay`. - const blockSupportDisable = hasBlockSupport( - getBlockName( state, clientId ), - '__experimentalDisableBlockOverlay', - false - ); - const shouldEnableIfUnselected = - editorMode === 'navigation' || - ( blockSupportDisable - ? false - : areInnerBlocksControlled( state, clientId ) ); + // In navigation mode, the block overlay is active when the block is not + // selected (and doesn't contain a selected child). The same behavior is + // also enabled in all modes for blocks that have controlled children + // (reusable block, template part, navigation), unless explicitly disabled + // with `supports.__experimentalDisableBlockOverlay`. + const blockSupportDisable = hasBlockSupport( + getBlockName( state, clientId ), + '__experimentalDisableBlockOverlay', + false + ); + const shouldEnableIfUnselected = + editorMode === 'navigation' || + ( blockSupportDisable + ? false + : areInnerBlocksControlled( state, clientId ) ); - return ( - shouldEnableIfUnselected && - ! isBlockSelected( state, clientId ) && - ! hasSelectedInnerBlock( state, clientId, true ) - ); -} + return ( + shouldEnableIfUnselected && + ! isBlockSelected( state, clientId ) && + ! hasSelectedInnerBlock( state, clientId, true ) + ); + } ) +); export function __unstableIsWithinBlockOverlay( state, clientId ) { let parent = state.blocks.parents.get( clientId ); @@ -2978,39 +2983,3 @@ export const isGroupable = createRegistrySelector( ); } ); - -export const getSectionsContainerClientId = createRegistrySelector( - ( select ) => ( state ) => { - const { getSectionRootBlockName } = unlock( select( blocksStore ) ); - const sectionRootBlockName = getSectionRootBlockName(); - const { getGroupingBlockName } = select( blocksStore ); - const groupingBlockName = getGroupingBlockName(); - - if ( sectionRootBlockName === groupingBlockName ) { - const groupBlocks = getBlocksByName( state, sectionRootBlockName ); - const mainGroup = groupBlocks.find( - ( clientId ) => - getBlockAttributes( state, clientId )?.tagName === 'main' - ); - if ( mainGroup ) { - return mainGroup; - } - // if there is no main group and no other block is specified - // as section root - return null; - } - - const sectionRootBlocks = getBlocksByName( - state, - sectionRootBlockName - ); - - if ( sectionRootBlocks?.length > 0 ) { - return sectionRootBlocks[ 0 ]; - } - - // if other block is specified - // as section root, but its not found - return null; - } -); From 79d8af487075814aa51fe17a93dff84d94818a0f Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Tue, 2 Apr 2024 11:04:39 -0500 Subject: [PATCH 22/53] Remove unused reducers --- packages/block-editor/src/store/reducer.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index f2864ded91179d..13024d4d2e8fac 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1981,20 +1981,11 @@ export function blockEditingModes( state = new Map(), action ) { switch ( action.type ) { case 'SET_BLOCK_EDITING_MODE': return new Map( state ).set( action.clientId, action.mode ); - case 'SET_BLOCK_EDITING_MODES': - return new Map( [ ...state, ...action.modes ] ); case 'UNSET_BLOCK_EDITING_MODE': { const newState = new Map( state ); newState.delete( action.clientId ); return newState; } - case 'UNSET_BLOCK_EDITING_MODES': { - const newState = new Map( state ); - action.clientIds.forEach( ( clientId ) => - newState.delete( clientId ) - ); - return newState; - } case 'RESET_BLOCKS': { return state.has( '' ) ? new Map().set( '', state.get( '' ) ) From 120aa9384c4ae177fb89fc0051881eb979df55ae Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Tue, 2 Apr 2024 18:29:18 -0500 Subject: [PATCH 23/53] Refactor to group by if we have a sectionsContainerClientId --- packages/block-editor/src/store/actions.js | 151 +++++++++++---------- 1 file changed, 76 insertions(+), 75 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index fbc1dac84d1729..e3f3e87be3b341 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1435,54 +1435,31 @@ export const setNavigationMode = export const __unstableSetEditorMode = ( mode ) => ( { dispatch, select, registry } ) => { - // When switching to zoom-out mode, we need to select the root block - if ( mode === 'zoom-out' ) { - const firstSelectedClientId = select.getBlockSelectionStart(); - if ( firstSelectedClientId ) { - const rootClientId = select.getBlockHierarchyRootClientId( - firstSelectedClientId - ); - dispatch.selectBlock( rootClientId ); - } - } - - // TODO: Cleanup this for better performance/readability. - // When switching to zoom-out mode, we need to disable editing mode for all blocks except the sections. - const sectionsContainerClientId = unlock( - registry.select( STORE_NAME ) - ).getSectionsContainerClientId(); - let sectionsClientIds = []; - let sectionClientIdsInnerBlocks = []; - let disabledSectionsClientIds = []; - if ( sectionsContainerClientId ) { - sectionsClientIds = select.getClientIdsOfDescendants( - sectionsContainerClientId - ); - } else { - sectionsClientIds = select.getBlockOrder(); - disabledSectionsClientIds = sectionsClientIds - .map( ( clientId ) => { - return select.getBlock( clientId ); - } ) - .filter( ( block ) => block.name === 'core/template-part' ) - .map( ( block ) => block.clientId ); - - sectionClientIdsInnerBlocks = sectionsClientIds.flatMap( - ( clientId ) => { - const block = select.getBlock( clientId ); - if ( block.name === 'core/template-part' ) { - return []; - } - return block.innerBlocks.map( - ( innerBlock ) => innerBlock.clientId + registry.batch( () => { + dispatch( { type: 'SET_EDITOR_MODE', mode } ); + + // When switching to zoom-out mode, we need to select the root block + if ( mode === 'zoom-out' ) { + const firstSelectedClientId = select.getBlockSelectionStart(); + if ( firstSelectedClientId ) { + const rootClientId = select.getBlockHierarchyRootClientId( + firstSelectedClientId ); + dispatch.selectBlock( rootClientId ); } - ); - } + } - if ( mode === 'zoom-out' ) { - registry.batch( () => { - if ( sectionsContainerClientId ) { + const prevMode = select.__unstableGetEditorMode(); + + const sectionsContainerClientId = unlock( + registry.select( STORE_NAME ) + ).getSectionsContainerClientId(); + + if ( sectionsContainerClientId ) { + const sectionsClientIds = select.getClientIdsOfDescendants( + sectionsContainerClientId + ); + if ( mode === 'zoom-out' ) { dispatch.setBlockEditingMode( '' /* rootClientId */, 'disabled' @@ -1494,7 +1471,33 @@ export const __unstableSetEditorMode = sectionsClientIds.forEach( ( clientId ) => dispatch.setBlockEditingMode( clientId, 'default' ) ); - } else { + } else if ( prevMode === 'zoom-out' ) { + dispatch.unsetBlockEditingMode( '' /* rootClientId */ ); + dispatch.unsetBlockEditingMode( sectionsContainerClientId ); + sectionsClientIds.forEach( ( clientId ) => { + dispatch.unsetBlockEditingMode( clientId ); + } ); + } + } else { + const sectionsClientIds = select.getBlockOrder(); + const disabledSectionsClientIds = sectionsClientIds.filter( + ( clientId ) => { + const block = select.getBlock( clientId ); + return block.name === 'core/template-part'; + } + ); + const sectionClientIdsInnerBlocks = sectionsClientIds.flatMap( + ( clientId ) => { + const block = select.getBlock( clientId ); + if ( block.name === 'core/template-part' ) { + return []; + } + return block.innerBlocks.map( + ( innerBlock ) => innerBlock.clientId + ); + } + ); + if ( mode === 'zoom-out' ) { dispatch.setBlockEditingMode( '' /* rootClientId */, 'contentOnly' @@ -1508,38 +1511,36 @@ export const __unstableSetEditorMode = sectionClientIdsInnerBlocks.forEach( ( clientId ) => dispatch.setBlockEditingMode( clientId, 'disabled' ) ); + } else if ( prevMode === 'zoom-out' ) { + dispatch.unsetBlockEditingMode( '' /* rootClientId */ ); + sectionsClientIds.forEach( ( clientId ) => + dispatch.unsetBlockEditingMode( clientId ) + ); + disabledSectionsClientIds.forEach( ( clientId ) => + dispatch.unsetBlockEditingMode( clientId ) + ); + sectionClientIdsInnerBlocks.forEach( ( clientId ) => + dispatch.unsetBlockEditingMode( clientId ) + ); } - } ); - } else { - const prevMode = select.__unstableGetEditorMode(); - if ( prevMode === 'zoom-out' ) { - registry.batch( () => { - unsetBlockEditingMode( '' /* rootClientId */ ); - unsetBlockEditingMode( sectionsContainerClientId ); - sectionsClientIds.forEach( ( clientId ) => { - unsetBlockEditingMode( clientId ); - } ); - } ); } - } - - dispatch( { type: 'SET_EDITOR_MODE', mode } ); - if ( mode === 'navigation' ) { - speak( - __( - 'You are currently in navigation mode. Navigate blocks using the Tab key and Arrow keys. Use Left and Right Arrow keys to move between nesting levels. To exit navigation mode and edit the selected block, press Enter.' - ) - ); - } else if ( mode === 'edit' ) { - speak( - __( - 'You are currently in edit mode. To return to the navigation mode, press Escape.' - ) - ); - } else if ( mode === 'zoom-out' ) { - speak( __( 'You are currently in zoom-out mode.' ) ); - } + if ( mode === 'navigation' ) { + speak( + __( + 'You are currently in navigation mode. Navigate blocks using the Tab key and Arrow keys. Use Left and Right Arrow keys to move between nesting levels. To exit navigation mode and edit the selected block, press Enter.' + ) + ); + } else if ( mode === 'edit' ) { + speak( + __( + 'You are currently in edit mode. To return to the navigation mode, press Escape.' + ) + ); + } else if ( mode === 'zoom-out' ) { + speak( __( 'You are currently in zoom-out mode.' ) ); + } + } ); }; /** From 206e17d5be7de37fa74f1197741e15d552e73eb2 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Tue, 2 Apr 2024 18:50:11 -0500 Subject: [PATCH 24/53] Add wrapper to prevent running a bunch of loops in non-zoom out modes --- packages/block-editor/src/store/actions.js | 138 +++++++++++---------- 1 file changed, 72 insertions(+), 66 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index e3f3e87be3b341..da4f5df58beeba 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1451,77 +1451,83 @@ export const __unstableSetEditorMode = const prevMode = select.__unstableGetEditorMode(); - const sectionsContainerClientId = unlock( - registry.select( STORE_NAME ) - ).getSectionsContainerClientId(); - - if ( sectionsContainerClientId ) { - const sectionsClientIds = select.getClientIdsOfDescendants( - sectionsContainerClientId - ); - if ( mode === 'zoom-out' ) { - dispatch.setBlockEditingMode( - '' /* rootClientId */, - 'disabled' - ); - dispatch.setBlockEditingMode( - sectionsContainerClientId, - 'contentOnly' - ); - sectionsClientIds.forEach( ( clientId ) => - dispatch.setBlockEditingMode( clientId, 'default' ) + if ( mode === 'zoom-out' || prevMode === 'zoom-out' ) { + const sectionsContainerClientId = unlock( + registry.select( STORE_NAME ) + ).getSectionsContainerClientId(); + + if ( sectionsContainerClientId ) { + const sectionsClientIds = select.getClientIdsOfDescendants( + sectionsContainerClientId ); - } else if ( prevMode === 'zoom-out' ) { - dispatch.unsetBlockEditingMode( '' /* rootClientId */ ); - dispatch.unsetBlockEditingMode( sectionsContainerClientId ); - sectionsClientIds.forEach( ( clientId ) => { - dispatch.unsetBlockEditingMode( clientId ); - } ); - } - } else { - const sectionsClientIds = select.getBlockOrder(); - const disabledSectionsClientIds = sectionsClientIds.filter( - ( clientId ) => { - const block = select.getBlock( clientId ); - return block.name === 'core/template-part'; + if ( mode === 'zoom-out' ) { + dispatch.setBlockEditingMode( + '' /* rootClientId */, + 'disabled' + ); + dispatch.setBlockEditingMode( + sectionsContainerClientId, + 'contentOnly' + ); + sectionsClientIds.forEach( ( clientId ) => + dispatch.setBlockEditingMode( clientId, 'default' ) + ); + } else if ( prevMode === 'zoom-out' ) { + dispatch.unsetBlockEditingMode( '' /* rootClientId */ ); + dispatch.unsetBlockEditingMode( + sectionsContainerClientId + ); + sectionsClientIds.forEach( ( clientId ) => { + dispatch.unsetBlockEditingMode( clientId ); + } ); } - ); - const sectionClientIdsInnerBlocks = sectionsClientIds.flatMap( - ( clientId ) => { - const block = select.getBlock( clientId ); - if ( block.name === 'core/template-part' ) { - return []; + } else { + const sectionsClientIds = select.getBlockOrder(); + const disabledSectionsClientIds = sectionsClientIds.filter( + ( clientId ) => { + const block = select.getBlock( clientId ); + return block.name === 'core/template-part'; } - return block.innerBlocks.map( - ( innerBlock ) => innerBlock.clientId + ); + const sectionClientIdsInnerBlocks = + sectionsClientIds.flatMap( ( clientId ) => { + const block = select.getBlock( clientId ); + if ( block.name === 'core/template-part' ) { + return []; + } + return block.innerBlocks.map( + ( innerBlock ) => innerBlock.clientId + ); + } ); + if ( mode === 'zoom-out' ) { + dispatch.setBlockEditingMode( + '' /* rootClientId */, + 'contentOnly' + ); + sectionsClientIds.forEach( ( clientId ) => + dispatch.setBlockEditingMode( + clientId, + 'contentOnly' + ) + ); + disabledSectionsClientIds.forEach( ( clientId ) => + dispatch.setBlockEditingMode( clientId, 'disabled' ) + ); + sectionClientIdsInnerBlocks.forEach( ( clientId ) => + dispatch.setBlockEditingMode( clientId, 'disabled' ) + ); + } else if ( prevMode === 'zoom-out' ) { + dispatch.unsetBlockEditingMode( '' /* rootClientId */ ); + sectionsClientIds.forEach( ( clientId ) => + dispatch.unsetBlockEditingMode( clientId ) + ); + disabledSectionsClientIds.forEach( ( clientId ) => + dispatch.unsetBlockEditingMode( clientId ) + ); + sectionClientIdsInnerBlocks.forEach( ( clientId ) => + dispatch.unsetBlockEditingMode( clientId ) ); } - ); - if ( mode === 'zoom-out' ) { - dispatch.setBlockEditingMode( - '' /* rootClientId */, - 'contentOnly' - ); - sectionsClientIds.forEach( ( clientId ) => - dispatch.setBlockEditingMode( clientId, 'contentOnly' ) - ); - disabledSectionsClientIds.forEach( ( clientId ) => - dispatch.setBlockEditingMode( clientId, 'disabled' ) - ); - sectionClientIdsInnerBlocks.forEach( ( clientId ) => - dispatch.setBlockEditingMode( clientId, 'disabled' ) - ); - } else if ( prevMode === 'zoom-out' ) { - dispatch.unsetBlockEditingMode( '' /* rootClientId */ ); - sectionsClientIds.forEach( ( clientId ) => - dispatch.unsetBlockEditingMode( clientId ) - ); - disabledSectionsClientIds.forEach( ( clientId ) => - dispatch.unsetBlockEditingMode( clientId ) - ); - sectionClientIdsInnerBlocks.forEach( ( clientId ) => - dispatch.unsetBlockEditingMode( clientId ) - ); } } From 90a46343efdd1bd0d52e7ce83c06b34231f3e98d Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 3 Apr 2024 00:22:01 -0500 Subject: [PATCH 25/53] Move SET_EDITOR_MODE back to the end so prevMode works --- packages/block-editor/src/store/actions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index da4f5df58beeba..eec9dae37f71eb 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1436,8 +1436,6 @@ export const __unstableSetEditorMode = ( mode ) => ( { dispatch, select, registry } ) => { registry.batch( () => { - dispatch( { type: 'SET_EDITOR_MODE', mode } ); - // When switching to zoom-out mode, we need to select the root block if ( mode === 'zoom-out' ) { const firstSelectedClientId = select.getBlockSelectionStart(); @@ -1531,6 +1529,8 @@ export const __unstableSetEditorMode = } } + dispatch( { type: 'SET_EDITOR_MODE', mode } ); + if ( mode === 'navigation' ) { speak( __( From c7a2cc0d6fd5ddd42ece74a79ee7bd7b7233e811 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 3 Apr 2024 00:24:03 -0500 Subject: [PATCH 26/53] Add comments for two main sections --- packages/block-editor/src/store/actions.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index eec9dae37f71eb..37cdc7f0c91e0f 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1455,6 +1455,9 @@ export const __unstableSetEditorMode = ).getSectionsContainerClientId(); if ( sectionsContainerClientId ) { + // If we have a sections container (usually a core/group + //
element), only allow editing of the contents of + // the container. const sectionsClientIds = select.getClientIdsOfDescendants( sectionsContainerClientId ); @@ -1480,6 +1483,8 @@ export const __unstableSetEditorMode = } ); } } else { + // If we don't have a sections container, we get the top-level + // blocks and only allow editing those blocks. const sectionsClientIds = select.getBlockOrder(); const disabledSectionsClientIds = sectionsClientIds.filter( ( clientId ) => { From 9f3d56042fbb32f217cf4081c5fb1f890e633def Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 3 Apr 2024 00:24:32 -0500 Subject: [PATCH 27/53] Use constant instead of random empty string --- packages/block-editor/src/store/actions.js | 32 ++++++++++++++------ packages/block-editor/src/store/constants.js | 2 ++ 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 37cdc7f0c91e0f..479aea016a85e0 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -32,7 +32,7 @@ import { privateRemoveBlocks, } from './private-actions'; import { unlock } from '../lock-unlock'; -import { STORE_NAME } from './constants'; +import { STORE_NAME, ROOT_CONTAINER_CLIENT_ID } from './constants'; /** @typedef {import('../components/use-on-block-drop/types').WPDropOperation} WPDropOperation */ @@ -426,7 +426,12 @@ export const moveBlocksUp = createOnMove( 'MOVE_BLOCKS_UP' ); * @param {number} index The index to move the blocks to. */ export const moveBlocksToPosition = - ( clientIds, fromRootClientId = '', toRootClientId = '', index ) => + ( + clientIds, + fromRootClientId = ROOT_CONTAINER_CLIENT_ID, + toRootClientId = ROOT_CONTAINER_CLIENT_ID, + index + ) => ( { select, dispatch } ) => { const canMoveBlocks = select.canMoveBlocks( clientIds, @@ -481,8 +486,8 @@ export const moveBlocksToPosition = */ export function moveBlockToPosition( clientId, - fromRootClientId = '', - toRootClientId = '', + fromRootClientId = ROOT_CONTAINER_CLIENT_ID, + toRootClientId = ROOT_CONTAINER_CLIENT_ID, index ) { return moveBlocksToPosition( @@ -1463,7 +1468,7 @@ export const __unstableSetEditorMode = ); if ( mode === 'zoom-out' ) { dispatch.setBlockEditingMode( - '' /* rootClientId */, + ROOT_CONTAINER_CLIENT_ID, 'disabled' ); dispatch.setBlockEditingMode( @@ -1474,7 +1479,9 @@ export const __unstableSetEditorMode = dispatch.setBlockEditingMode( clientId, 'default' ) ); } else if ( prevMode === 'zoom-out' ) { - dispatch.unsetBlockEditingMode( '' /* rootClientId */ ); + dispatch.unsetBlockEditingMode( + ROOT_CONTAINER_CLIENT_ID + ); dispatch.unsetBlockEditingMode( sectionsContainerClientId ); @@ -1504,7 +1511,7 @@ export const __unstableSetEditorMode = } ); if ( mode === 'zoom-out' ) { dispatch.setBlockEditingMode( - '' /* rootClientId */, + ROOT_CONTAINER_CLIENT_ID, 'contentOnly' ); sectionsClientIds.forEach( ( clientId ) => @@ -1520,7 +1527,9 @@ export const __unstableSetEditorMode = dispatch.setBlockEditingMode( clientId, 'disabled' ) ); } else if ( prevMode === 'zoom-out' ) { - dispatch.unsetBlockEditingMode( '' /* rootClientId */ ); + dispatch.unsetBlockEditingMode( + ROOT_CONTAINER_CLIENT_ID + ); sectionsClientIds.forEach( ( clientId ) => dispatch.unsetBlockEditingMode( clientId ) ); @@ -1993,7 +2002,10 @@ export const registerInserterMediaCategory = * * @return {Object} Action object. */ -export function setBlockEditingMode( clientId = '', mode ) { +export function setBlockEditingMode( + clientId = ROOT_CONTAINER_CLIENT_ID, + mode +) { return { type: 'SET_BLOCK_EDITING_MODE', clientId, @@ -2010,7 +2022,7 @@ export function setBlockEditingMode( clientId = '', mode ) { * * @return {Object} Action object. */ -export function unsetBlockEditingMode( clientId = '' ) { +export function unsetBlockEditingMode( clientId = ROOT_CONTAINER_CLIENT_ID ) { return { type: 'UNSET_BLOCK_EDITING_MODE', clientId, diff --git a/packages/block-editor/src/store/constants.js b/packages/block-editor/src/store/constants.js index c073d8d653452a..732c4c5502528e 100644 --- a/packages/block-editor/src/store/constants.js +++ b/packages/block-editor/src/store/constants.js @@ -1 +1,3 @@ export const STORE_NAME = 'core/block-editor'; + +export const ROOT_CONTAINER_CLIENT_ID = ''; From b289f6db4c0d693c7976862f7afb4e8e1497aca2 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 3 Apr 2024 00:43:56 -0500 Subject: [PATCH 28/53] Revert remaining block-list changes --- packages/block-editor/src/components/block-list/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index 4e49dd797ff337..f906372bfa8154 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -119,7 +119,6 @@ function Root( { className, ...settings } ) { }, settings ); - return (
From cab518ba0a4b588b26b897906d21f5717f8fccf1 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 3 Apr 2024 11:51:08 -0500 Subject: [PATCH 29/53] Refactor to use select --- packages/block-editor/src/store/selectors.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index f4f1621449e7cf..c33a630fbc4680 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2904,17 +2904,17 @@ export const getBlockEditingMode = createRegistrySelector( if ( ! clientId ) { return 'default'; } - const rootClientId = getBlockRootClientId( state, clientId ); - const templateLock = getTemplateLock( state, rootClientId ); + const rootClientId = select.getBlockRootClientId( clientId ); + const templateLock = select.getTemplateLock( rootClientId ); if ( templateLock === 'contentOnly' ) { - const name = getBlockName( state, clientId ); + const name = select.getBlockName( clientId ); const isContent = select( blocksStore ).__experimentalHasContentRoleAttribute( name ); return isContent ? 'contentOnly' : 'disabled'; } - const parentMode = getBlockEditingMode( state, rootClientId ); + const parentMode = select.getBlockEditingMode( rootClientId ); return parentMode === 'contentOnly' ? 'default' : parentMode; } ); From de412a99366fcbe19de29b32c84e2adbc204731e Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 3 Apr 2024 11:54:04 -0500 Subject: [PATCH 30/53] Refactor to use ROOT_CONTAINER_CLIENT_ID instead of empty string --- packages/block-editor/src/store/selectors.js | 28 +++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index c33a630fbc4680..791142cb05736a 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -28,7 +28,7 @@ import { getInsertBlockTypeDependants, } from './utils'; import { orderBy } from '../utils/sorting'; -import { STORE_NAME } from './constants'; +import { ROOT_CONTAINER_CLIENT_ID, STORE_NAME } from './constants'; import { unlock } from '../lock-unlock'; /** @@ -182,7 +182,7 @@ export const __unstableGetBlockWithoutInnerBlocks = createSelector( export function getBlocks( state, rootClientId ) { const treeKey = ! rootClientId || ! areInnerBlocksControlled( state, rootClientId ) - ? rootClientId || '' + ? rootClientId || ROOT_CONTAINER_CLIENT_ID : 'controlled||' + rootClientId; return state.blocks.tree.get( treeKey )?.innerBlocks || EMPTY_ARRAY; } @@ -228,7 +228,7 @@ export const __unstableGetClientIdWithClientIdsTree = createSelector( * @return {Object[]} Client IDs of the post blocks. */ export const __unstableGetClientIdsTree = createSelector( - ( state, rootClientId = '' ) => { + ( state, rootClientId = ROOT_CONTAINER_CLIENT_ID ) => { deprecated( "wp.data.select( 'core/block-editor' ).__unstableGetClientIdsTree", { @@ -293,7 +293,7 @@ export const getClientIdsOfDescendants = createSelector( * @return {Array} ids of top-level and descendant blocks. */ export const getClientIdsWithDescendants = ( state ) => - getClientIdsOfDescendants( state, '' ); + getClientIdsOfDescendants( state, ROOT_CONTAINER_CLIENT_ID ); /** * Returns the total number of blocks, or the total number of blocks with a specific name in a post. @@ -1185,7 +1185,10 @@ export const __unstableGetSelectedBlocksWithPartialSelection = ( state ) => { * @return {Array} Ordered client IDs of editor blocks. */ export function getBlockOrder( state, rootClientId ) { - return state.blocks.order.get( rootClientId || '' ) || EMPTY_ARRAY; + return ( + state.blocks.order.get( rootClientId || ROOT_CONTAINER_CLIENT_ID ) || + EMPTY_ARRAY + ); } /** @@ -1564,7 +1567,12 @@ const canInsertBlockTypeUnmemoized = ( return false; } - if ( getBlockEditingMode( state, rootClientId ?? '' ) === 'disabled' ) { + if ( + getBlockEditingMode( + state, + rootClientId ?? ROOT_CONTAINER_CLIENT_ID + ) === 'disabled' + ) { return false; } @@ -2888,15 +2896,15 @@ export function __unstableIsWithinBlockOverlay( state, clientId ) { * * @see useBlockEditingMode * - * @param {Object} state Global application state. - * @param {string} clientId The block client ID, or `''` for the root container. + * @param {Object} state Global application state. + * @param {string?} clientId The block client ID or the root container if omitted. * * @return {BlockEditingMode} The block editing mode. One of `'disabled'`, * `'contentOnly'`, or `'default'`. */ export const getBlockEditingMode = createRegistrySelector( ( select ) => - ( state, clientId = '' ) => { + ( state, clientId = ROOT_CONTAINER_CLIENT_ID ) => { const blockEditingMode = state.blockEditingModes.get( clientId ); if ( blockEditingMode ) { return blockEditingMode; @@ -2933,7 +2941,7 @@ export const getBlockEditingMode = createRegistrySelector( */ export const isUngroupable = createRegistrySelector( ( select ) => - ( state, clientId = '' ) => { + ( state, clientId = ROOT_CONTAINER_CLIENT_ID ) => { const _clientId = clientId || getSelectedBlockClientId( state ); if ( ! _clientId ) { return false; From 5162d0c9889bcc990587b948de94e5d26c7ed952 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 3 Apr 2024 11:55:05 -0500 Subject: [PATCH 31/53] Move zoom-out logic to selector instead of action --- packages/block-editor/src/store/actions.js | 94 +------------------- packages/block-editor/src/store/selectors.js | 55 ++++++++++++ 2 files changed, 56 insertions(+), 93 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 479aea016a85e0..ed7f7e6019b7c3 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -31,8 +31,7 @@ import { __experimentalUpdateSettings, privateRemoveBlocks, } from './private-actions'; -import { unlock } from '../lock-unlock'; -import { STORE_NAME, ROOT_CONTAINER_CLIENT_ID } from './constants'; +import { ROOT_CONTAINER_CLIENT_ID } from './constants'; /** @typedef {import('../components/use-on-block-drop/types').WPDropOperation} WPDropOperation */ @@ -1452,97 +1451,6 @@ export const __unstableSetEditorMode = } } - const prevMode = select.__unstableGetEditorMode(); - - if ( mode === 'zoom-out' || prevMode === 'zoom-out' ) { - const sectionsContainerClientId = unlock( - registry.select( STORE_NAME ) - ).getSectionsContainerClientId(); - - if ( sectionsContainerClientId ) { - // If we have a sections container (usually a core/group - //
element), only allow editing of the contents of - // the container. - const sectionsClientIds = select.getClientIdsOfDescendants( - sectionsContainerClientId - ); - if ( mode === 'zoom-out' ) { - dispatch.setBlockEditingMode( - ROOT_CONTAINER_CLIENT_ID, - 'disabled' - ); - dispatch.setBlockEditingMode( - sectionsContainerClientId, - 'contentOnly' - ); - sectionsClientIds.forEach( ( clientId ) => - dispatch.setBlockEditingMode( clientId, 'default' ) - ); - } else if ( prevMode === 'zoom-out' ) { - dispatch.unsetBlockEditingMode( - ROOT_CONTAINER_CLIENT_ID - ); - dispatch.unsetBlockEditingMode( - sectionsContainerClientId - ); - sectionsClientIds.forEach( ( clientId ) => { - dispatch.unsetBlockEditingMode( clientId ); - } ); - } - } else { - // If we don't have a sections container, we get the top-level - // blocks and only allow editing those blocks. - const sectionsClientIds = select.getBlockOrder(); - const disabledSectionsClientIds = sectionsClientIds.filter( - ( clientId ) => { - const block = select.getBlock( clientId ); - return block.name === 'core/template-part'; - } - ); - const sectionClientIdsInnerBlocks = - sectionsClientIds.flatMap( ( clientId ) => { - const block = select.getBlock( clientId ); - if ( block.name === 'core/template-part' ) { - return []; - } - return block.innerBlocks.map( - ( innerBlock ) => innerBlock.clientId - ); - } ); - if ( mode === 'zoom-out' ) { - dispatch.setBlockEditingMode( - ROOT_CONTAINER_CLIENT_ID, - 'contentOnly' - ); - sectionsClientIds.forEach( ( clientId ) => - dispatch.setBlockEditingMode( - clientId, - 'contentOnly' - ) - ); - disabledSectionsClientIds.forEach( ( clientId ) => - dispatch.setBlockEditingMode( clientId, 'disabled' ) - ); - sectionClientIdsInnerBlocks.forEach( ( clientId ) => - dispatch.setBlockEditingMode( clientId, 'disabled' ) - ); - } else if ( prevMode === 'zoom-out' ) { - dispatch.unsetBlockEditingMode( - ROOT_CONTAINER_CLIENT_ID - ); - sectionsClientIds.forEach( ( clientId ) => - dispatch.unsetBlockEditingMode( clientId ) - ); - disabledSectionsClientIds.forEach( ( clientId ) => - dispatch.unsetBlockEditingMode( clientId ) - ); - sectionClientIdsInnerBlocks.forEach( ( clientId ) => - dispatch.unsetBlockEditingMode( clientId ) - ); - } - } - } - dispatch( { type: 'SET_EDITOR_MODE', mode } ); if ( mode === 'navigation' ) { diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 791142cb05736a..8ad73bdd867bac 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2905,6 +2905,61 @@ export function __unstableIsWithinBlockOverlay( state, clientId ) { export const getBlockEditingMode = createRegistrySelector( ( select ) => ( state, clientId = ROOT_CONTAINER_CLIENT_ID ) => { + // In zoom-out mode, override the behavior set by + // __unstableSetBlockEditingMode to only allow editing the top-level + // sections. + const editorMode = select.__unstableGetEditorMode(); + if ( editorMode === 'zoom-out' ) { + const sectionsContainerClientId = unlock( + select( STORE_NAME ) + ).getSectionsContainerClientId(); + + if ( sectionsContainerClientId ) { + // If we have a sections container (usually a core/group + //
element), only allow editing of the contents of + // the container. + const sectionsClientIds = select.getClientIdsOfDescendants( + sectionsContainerClientId + ); + if ( clientId === ROOT_CONTAINER_CLIENT_ID ) { + return 'disabled'; + } else if ( clientId === sectionsContainerClientId ) { + return 'contentOnly'; + } else if ( sectionsClientIds.includes( clientId ) ) { + return 'default'; + } + } else { + // If we don't have a sections container, we get the top-level + // blocks and only allow editing those blocks. + const sectionsClientIds = select.getBlockOrder(); + const block = select.getBlock( clientId ); + + function isSectionChildClientId() { + return sectionsClientIds.some( ( sectionClientId ) => { + const sectionBlock = + select.getBlock( sectionClientId ); + if ( sectionBlock.name === 'core/template-part' ) { + return false; + } + return sectionBlock.innerBlocks.some( + ( innerBlock ) => + innerBlock.clientId === clientId + ); + } ); + } + + if ( clientId === ROOT_CONTAINER_CLIENT_ID ) { + return 'contentOnly'; + } else if ( sectionsClientIds.includes( clientId ) ) { + return 'contentOnly'; + } else if ( block.name === 'core/template-part' ) { + return 'disabled'; + } else if ( isSectionChildClientId() ) { + return 'disabled'; + } + } + } + const blockEditingMode = state.blockEditingModes.get( clientId ); if ( blockEditingMode ) { return blockEditingMode; From 37c477cd2563e588ee051b82acbdbf15d3601b42 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 3 Apr 2024 11:57:04 -0500 Subject: [PATCH 32/53] Remove registry.batch --- packages/block-editor/src/store/actions.js | 54 +++++++++++----------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index ed7f7e6019b7c3..ee92676ece4038 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1438,37 +1438,35 @@ export const setNavigationMode = */ export const __unstableSetEditorMode = ( mode ) => - ( { dispatch, select, registry } ) => { - registry.batch( () => { - // When switching to zoom-out mode, we need to select the root block - if ( mode === 'zoom-out' ) { - const firstSelectedClientId = select.getBlockSelectionStart(); - if ( firstSelectedClientId ) { - const rootClientId = select.getBlockHierarchyRootClientId( - firstSelectedClientId - ); - dispatch.selectBlock( rootClientId ); - } + ( { dispatch, select } ) => { + // When switching to zoom-out mode, we need to select the root block + if ( mode === 'zoom-out' ) { + const firstSelectedClientId = select.getBlockSelectionStart(); + if ( firstSelectedClientId ) { + const rootClientId = select.getBlockHierarchyRootClientId( + firstSelectedClientId + ); + dispatch.selectBlock( rootClientId ); } + } - dispatch( { type: 'SET_EDITOR_MODE', mode } ); + dispatch( { type: 'SET_EDITOR_MODE', mode } ); - if ( mode === 'navigation' ) { - speak( - __( - 'You are currently in navigation mode. Navigate blocks using the Tab key and Arrow keys. Use Left and Right Arrow keys to move between nesting levels. To exit navigation mode and edit the selected block, press Enter.' - ) - ); - } else if ( mode === 'edit' ) { - speak( - __( - 'You are currently in edit mode. To return to the navigation mode, press Escape.' - ) - ); - } else if ( mode === 'zoom-out' ) { - speak( __( 'You are currently in zoom-out mode.' ) ); - } - } ); + if ( mode === 'navigation' ) { + speak( + __( + 'You are currently in navigation mode. Navigate blocks using the Tab key and Arrow keys. Use Left and Right Arrow keys to move between nesting levels. To exit navigation mode and edit the selected block, press Enter.' + ) + ); + } else if ( mode === 'edit' ) { + speak( + __( + 'You are currently in edit mode. To return to the navigation mode, press Escape.' + ) + ); + } else if ( mode === 'zoom-out' ) { + speak( __( 'You are currently in zoom-out mode.' ) ); + } }; /** From 80e67b550c93000c30b368caa6a7eed026713a24 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 3 Apr 2024 12:02:43 -0500 Subject: [PATCH 33/53] Update JSDoc for ROOT_CONTAINER_CLIENT_ID defaults --- packages/block-editor/src/store/actions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index ee92676ece4038..24d76dffcff465 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1902,7 +1902,7 @@ export const registerInserterMediaCategory = * * @see useBlockEditingMode * - * @param {string} clientId The block client ID, or `''` for the root container. + * @param {string} clientId The block client ID or the root container if omitted. * @param {BlockEditingMode} mode The block editing mode. One of `'disabled'`, * `'contentOnly'`, or `'default'`. * @@ -1924,7 +1924,7 @@ export function setBlockEditingMode( * * @see useBlockEditingMode * - * @param {string} clientId The block client ID, or `''` for the root container. + * @param {string} clientId The block client ID, or the root container if omitted. * * @return {Object} Action object. */ From 3a59a1007088edbf9eea4b408f7b74c4f8132ad2 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 3 Apr 2024 12:08:22 -0500 Subject: [PATCH 34/53] Revert pattern edit.js --- packages/block-library/src/pattern/edit.js | 25 +++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/packages/block-library/src/pattern/edit.js b/packages/block-library/src/pattern/edit.js index 7e31c07e47d9ed..7b78796aacd54c 100644 --- a/packages/block-library/src/pattern/edit.js +++ b/packages/block-library/src/pattern/edit.js @@ -32,8 +32,14 @@ const PatternEdit = ( { attributes, clientId } ) => { [] ); - const { replaceBlocks, __unstableMarkNextChangeAsNotPersistent } = - useDispatch( blockEditorStore ); + const { + replaceBlocks, + setBlockEditingMode, + __unstableMarkNextChangeAsNotPersistent, + } = useDispatch( blockEditorStore ); + const { getBlockRootClientId, getBlockEditingMode } = + useSelect( blockEditorStore ); + const [ hasRecursionError, setHasRecursionError ] = useState( false ); const parsePatternDependencies = useParsePatternDependencies(); @@ -83,6 +89,7 @@ const PatternEdit = ( { attributes, clientId } ) => { // because nested pattern blocks cannot be inserted if the parent block supports // inner blocks but doesn't have blockSettings in the state. window.queueMicrotask( () => { + const rootClientId = getBlockRootClientId( clientId ); // Clone blocks from the pattern before insertion to ensure they receive // distinct client ids. See https://github.com/WordPress/gutenberg/issues/50628. const clonedBlocks = selectedPattern.blocks.map( ( block ) => @@ -108,21 +115,29 @@ const PatternEdit = ( { attributes, clientId } ) => { }, }; } + const rootEditingMode = getBlockEditingMode( rootClientId ); registry.batch( () => { + // Temporarily set the root block to default mode to allow replacing the pattern. + // This could happen when the page is disabling edits of non-content blocks. + __unstableMarkNextChangeAsNotPersistent(); + setBlockEditingMode( rootClientId, 'default' ); __unstableMarkNextChangeAsNotPersistent(); replaceBlocks( clientId, clonedBlocks ); + // Restore the root block's original mode. + __unstableMarkNextChangeAsNotPersistent(); + setBlockEditingMode( rootClientId, rootEditingMode ); } ); } ); } }, [ - registry, - parsePatternDependencies, clientId, hasRecursionError, selectedPattern, __unstableMarkNextChangeAsNotPersistent, replaceBlocks, - injectThemeAttributeInBlockTemplateContent, + getBlockEditingMode, + setBlockEditingMode, + getBlockRootClientId, ] ); const props = useBlockProps(); From ebed90c9321e2c55992b8a937eb6a675d75cc5a7 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 3 Apr 2024 13:02:06 -0500 Subject: [PATCH 35/53] Fix selectors in selectors --- packages/block-editor/src/store/selectors.js | 23 +++++++++++--------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 8ad73bdd867bac..3b18676cae0cfe 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2908,7 +2908,7 @@ export const getBlockEditingMode = createRegistrySelector( // In zoom-out mode, override the behavior set by // __unstableSetBlockEditingMode to only allow editing the top-level // sections. - const editorMode = select.__unstableGetEditorMode(); + const editorMode = __unstableGetEditorMode( state ); if ( editorMode === 'zoom-out' ) { const sectionsContainerClientId = unlock( select( STORE_NAME ) @@ -2918,7 +2918,8 @@ export const getBlockEditingMode = createRegistrySelector( // If we have a sections container (usually a core/group //
element), only allow editing of the contents of // the container. - const sectionsClientIds = select.getClientIdsOfDescendants( + const sectionsClientIds = getClientIdsOfDescendants( + state, sectionsContainerClientId ); if ( clientId === ROOT_CONTAINER_CLIENT_ID ) { @@ -2931,13 +2932,15 @@ export const getBlockEditingMode = createRegistrySelector( } else { // If we don't have a sections container, we get the top-level // blocks and only allow editing those blocks. - const sectionsClientIds = select.getBlockOrder(); - const block = select.getBlock( clientId ); + const sectionsClientIds = getBlockOrder( state ); + const block = getBlock( state, clientId ); function isSectionChildClientId() { return sectionsClientIds.some( ( sectionClientId ) => { - const sectionBlock = - select.getBlock( sectionClientId ); + const sectionBlock = getBlock( + state, + sectionClientId + ); if ( sectionBlock.name === 'core/template-part' ) { return false; } @@ -2967,17 +2970,17 @@ export const getBlockEditingMode = createRegistrySelector( if ( ! clientId ) { return 'default'; } - const rootClientId = select.getBlockRootClientId( clientId ); - const templateLock = select.getTemplateLock( rootClientId ); + const rootClientId = getBlockRootClientId( state, clientId ); + const templateLock = getTemplateLock( state, rootClientId ); if ( templateLock === 'contentOnly' ) { - const name = select.getBlockName( clientId ); + const name = getBlockName( state, clientId ); const isContent = select( blocksStore ).__experimentalHasContentRoleAttribute( name ); return isContent ? 'contentOnly' : 'disabled'; } - const parentMode = select.getBlockEditingMode( rootClientId ); + const parentMode = getBlockEditingMode( state, rootClientId ); return parentMode === 'contentOnly' ? 'default' : parentMode; } ); From 2528ce93f71180992c7bf00ad7b8d2590928368f Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 4 Apr 2024 11:25:43 -0500 Subject: [PATCH 36/53] Fix selection when entering zoom-out mode --- packages/block-editor/src/store/actions.js | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 24d76dffcff465..c0c3f539ede5b9 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1438,11 +1438,27 @@ export const setNavigationMode = */ export const __unstableSetEditorMode = ( mode ) => - ( { dispatch, select } ) => { - // When switching to zoom-out mode, we need to select the root block + ( { dispatch, select, registry } ) => { + // When switching to zoom-out mode, we need to select the parent section if ( mode === 'zoom-out' ) { const firstSelectedClientId = select.getBlockSelectionStart(); - if ( firstSelectedClientId ) { + const sectionsContainerClientId = unlock( + registry.select( STORE_NAME ) + ).getSectionsContainerClientId(); + if ( sectionsContainerClientId ) { + const sectionClientIds = select.getBlockOrder( + sectionsContainerClientId + ); + if ( sectionClientIds ) { + const parents = select.getBlockParents( + firstSelectedClientId + ); + const firstSectionClientId = parents.find( ( parent ) => + sectionClientIds.includes( parent ) + ); + dispatch.selectBlock( firstSectionClientId ); + } + } else if ( firstSelectedClientId ) { const rootClientId = select.getBlockHierarchyRootClientId( firstSelectedClientId ); From c5816f270a1fb0ae57279f79758c0cb2c2eacefe Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Thu, 4 Apr 2024 11:38:28 -0500 Subject: [PATCH 37/53] Fix case wher getBlock returns null --- packages/block-editor/src/store/selectors.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 3b18676cae0cfe..1a50a9406f8d00 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2941,10 +2941,10 @@ export const getBlockEditingMode = createRegistrySelector( state, sectionClientId ); - if ( sectionBlock.name === 'core/template-part' ) { + if ( sectionBlock?.name === 'core/template-part' ) { return false; } - return sectionBlock.innerBlocks.some( + return sectionBlock?.innerBlocks.some( ( innerBlock ) => innerBlock.clientId === clientId ); @@ -2955,7 +2955,7 @@ export const getBlockEditingMode = createRegistrySelector( return 'contentOnly'; } else if ( sectionsClientIds.includes( clientId ) ) { return 'contentOnly'; - } else if ( block.name === 'core/template-part' ) { + } else if ( block?.name === 'core/template-part' ) { return 'disabled'; } else if ( isSectionChildClientId() ) { return 'disabled'; From fb41e16e9b98a1ffc283b02f1009bd8fd523c606 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Fri, 5 Apr 2024 10:49:48 -0500 Subject: [PATCH 38/53] Optimize selector some more --- packages/block-editor/src/store/selectors.js | 44 ++++++++++++-------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 1a50a9406f8d00..6035d3890e158f 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2918,25 +2918,42 @@ export const getBlockEditingMode = createRegistrySelector( // If we have a sections container (usually a core/group //
element), only allow editing of the contents of // the container. + + if ( clientId === ROOT_CONTAINER_CLIENT_ID ) { + return 'disabled'; + } + + if ( clientId === sectionsContainerClientId ) { + return 'contentOnly'; + } + const sectionsClientIds = getClientIdsOfDescendants( state, sectionsContainerClientId ); - if ( clientId === ROOT_CONTAINER_CLIENT_ID ) { - return 'disabled'; - } else if ( clientId === sectionsContainerClientId ) { - return 'contentOnly'; - } else if ( sectionsClientIds.includes( clientId ) ) { + if ( sectionsClientIds.includes( clientId ) ) { return 'default'; } } else { // If we don't have a sections container, we get the top-level // blocks and only allow editing those blocks. + + if ( clientId === ROOT_CONTAINER_CLIENT_ID ) { + return 'contentOnly'; + } + const sectionsClientIds = getBlockOrder( state ); + if ( sectionsClientIds.includes( clientId ) ) { + return 'contentOnly'; + } + const block = getBlock( state, clientId ); + if ( block?.name === 'core/template-part' ) { + return 'disabled'; + } - function isSectionChildClientId() { - return sectionsClientIds.some( ( sectionClientId ) => { + const isSectionChildClientId = sectionsClientIds.some( + ( sectionClientId ) => { const sectionBlock = getBlock( state, sectionClientId @@ -2948,16 +2965,9 @@ export const getBlockEditingMode = createRegistrySelector( ( innerBlock ) => innerBlock.clientId === clientId ); - } ); - } - - if ( clientId === ROOT_CONTAINER_CLIENT_ID ) { - return 'contentOnly'; - } else if ( sectionsClientIds.includes( clientId ) ) { - return 'contentOnly'; - } else if ( block?.name === 'core/template-part' ) { - return 'disabled'; - } else if ( isSectionChildClientId() ) { + } + ); + if ( isSectionChildClientId ) { return 'disabled'; } } From b1ccce77adb390af796df65415efd7ad45fd1374 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Fri, 5 Apr 2024 11:03:13 -0500 Subject: [PATCH 39/53] Fix missing imports --- packages/block-editor/src/store/actions.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index c0c3f539ede5b9..236bccab8969e6 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -31,7 +31,8 @@ import { __experimentalUpdateSettings, privateRemoveBlocks, } from './private-actions'; -import { ROOT_CONTAINER_CLIENT_ID } from './constants'; +import { ROOT_CONTAINER_CLIENT_ID, STORE_NAME } from './constants'; +import { unlock } from '../lock-unlock'; /** @typedef {import('../components/use-on-block-drop/types').WPDropOperation} WPDropOperation */ From 5d0a81a665cf097b3e7a139af4089c36faa276af Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Tue, 9 Apr 2024 08:13:48 -0500 Subject: [PATCH 40/53] Revert ROOT_CONTAINER_CLIENT_ID rename --- packages/block-editor/src/store/actions.js | 24 +++++---------- packages/block-editor/src/store/constants.js | 2 -- packages/block-editor/src/store/selectors.js | 32 ++++++++------------ 3 files changed, 20 insertions(+), 38 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index 236bccab8969e6..ad54f4c2ad12e3 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -31,7 +31,7 @@ import { __experimentalUpdateSettings, privateRemoveBlocks, } from './private-actions'; -import { ROOT_CONTAINER_CLIENT_ID, STORE_NAME } from './constants'; +import { STORE_NAME } from './constants'; import { unlock } from '../lock-unlock'; /** @typedef {import('../components/use-on-block-drop/types').WPDropOperation} WPDropOperation */ @@ -426,12 +426,7 @@ export const moveBlocksUp = createOnMove( 'MOVE_BLOCKS_UP' ); * @param {number} index The index to move the blocks to. */ export const moveBlocksToPosition = - ( - clientIds, - fromRootClientId = ROOT_CONTAINER_CLIENT_ID, - toRootClientId = ROOT_CONTAINER_CLIENT_ID, - index - ) => + ( clientIds, fromRootClientId = '', toRootClientId = '', index ) => ( { select, dispatch } ) => { const canMoveBlocks = select.canMoveBlocks( clientIds, @@ -486,8 +481,8 @@ export const moveBlocksToPosition = */ export function moveBlockToPosition( clientId, - fromRootClientId = ROOT_CONTAINER_CLIENT_ID, - toRootClientId = ROOT_CONTAINER_CLIENT_ID, + fromRootClientId = '', + toRootClientId = '', index ) { return moveBlocksToPosition( @@ -1919,16 +1914,13 @@ export const registerInserterMediaCategory = * * @see useBlockEditingMode * - * @param {string} clientId The block client ID or the root container if omitted. + * @param {string} clientId The block client ID, or `''` for the root container. * @param {BlockEditingMode} mode The block editing mode. One of `'disabled'`, * `'contentOnly'`, or `'default'`. * * @return {Object} Action object. */ -export function setBlockEditingMode( - clientId = ROOT_CONTAINER_CLIENT_ID, - mode -) { +export function setBlockEditingMode( clientId = '', mode ) { return { type: 'SET_BLOCK_EDITING_MODE', clientId, @@ -1941,11 +1933,11 @@ export function setBlockEditingMode( * * @see useBlockEditingMode * - * @param {string} clientId The block client ID, or the root container if omitted. + * @param {string} clientId The block client ID, or `''` for the root container. * * @return {Object} Action object. */ -export function unsetBlockEditingMode( clientId = ROOT_CONTAINER_CLIENT_ID ) { +export function unsetBlockEditingMode( clientId = '' ) { return { type: 'UNSET_BLOCK_EDITING_MODE', clientId, diff --git a/packages/block-editor/src/store/constants.js b/packages/block-editor/src/store/constants.js index 732c4c5502528e..c073d8d653452a 100644 --- a/packages/block-editor/src/store/constants.js +++ b/packages/block-editor/src/store/constants.js @@ -1,3 +1 @@ export const STORE_NAME = 'core/block-editor'; - -export const ROOT_CONTAINER_CLIENT_ID = ''; diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 6035d3890e158f..13a923a1a8175e 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -28,7 +28,7 @@ import { getInsertBlockTypeDependants, } from './utils'; import { orderBy } from '../utils/sorting'; -import { ROOT_CONTAINER_CLIENT_ID, STORE_NAME } from './constants'; +import { STORE_NAME } from './constants'; import { unlock } from '../lock-unlock'; /** @@ -182,7 +182,7 @@ export const __unstableGetBlockWithoutInnerBlocks = createSelector( export function getBlocks( state, rootClientId ) { const treeKey = ! rootClientId || ! areInnerBlocksControlled( state, rootClientId ) - ? rootClientId || ROOT_CONTAINER_CLIENT_ID + ? rootClientId || '' : 'controlled||' + rootClientId; return state.blocks.tree.get( treeKey )?.innerBlocks || EMPTY_ARRAY; } @@ -228,7 +228,7 @@ export const __unstableGetClientIdWithClientIdsTree = createSelector( * @return {Object[]} Client IDs of the post blocks. */ export const __unstableGetClientIdsTree = createSelector( - ( state, rootClientId = ROOT_CONTAINER_CLIENT_ID ) => { + ( state, rootClientId = '' ) => { deprecated( "wp.data.select( 'core/block-editor' ).__unstableGetClientIdsTree", { @@ -293,7 +293,7 @@ export const getClientIdsOfDescendants = createSelector( * @return {Array} ids of top-level and descendant blocks. */ export const getClientIdsWithDescendants = ( state ) => - getClientIdsOfDescendants( state, ROOT_CONTAINER_CLIENT_ID ); + getClientIdsOfDescendants( state, '' ); /** * Returns the total number of blocks, or the total number of blocks with a specific name in a post. @@ -1185,10 +1185,7 @@ export const __unstableGetSelectedBlocksWithPartialSelection = ( state ) => { * @return {Array} Ordered client IDs of editor blocks. */ export function getBlockOrder( state, rootClientId ) { - return ( - state.blocks.order.get( rootClientId || ROOT_CONTAINER_CLIENT_ID ) || - EMPTY_ARRAY - ); + return state.blocks.order.get( rootClientId || '' ) || EMPTY_ARRAY; } /** @@ -1567,12 +1564,7 @@ const canInsertBlockTypeUnmemoized = ( return false; } - if ( - getBlockEditingMode( - state, - rootClientId ?? ROOT_CONTAINER_CLIENT_ID - ) === 'disabled' - ) { + if ( getBlockEditingMode( state, rootClientId ?? '' ) === 'disabled' ) { return false; } @@ -2896,15 +2888,15 @@ export function __unstableIsWithinBlockOverlay( state, clientId ) { * * @see useBlockEditingMode * - * @param {Object} state Global application state. - * @param {string?} clientId The block client ID or the root container if omitted. + * @param {Object} state Global application state. + * @param {string} clientId The block client ID, or `''` for the root container. * * @return {BlockEditingMode} The block editing mode. One of `'disabled'`, * `'contentOnly'`, or `'default'`. */ export const getBlockEditingMode = createRegistrySelector( ( select ) => - ( state, clientId = ROOT_CONTAINER_CLIENT_ID ) => { + ( state, clientId = '' ) => { // In zoom-out mode, override the behavior set by // __unstableSetBlockEditingMode to only allow editing the top-level // sections. @@ -2919,7 +2911,7 @@ export const getBlockEditingMode = createRegistrySelector( //
element), only allow editing of the contents of // the container. - if ( clientId === ROOT_CONTAINER_CLIENT_ID ) { + if ( clientId === '' /* ROOT_CONTAINER_CLIENT_ID */ ) { return 'disabled'; } @@ -2938,7 +2930,7 @@ export const getBlockEditingMode = createRegistrySelector( // If we don't have a sections container, we get the top-level // blocks and only allow editing those blocks. - if ( clientId === ROOT_CONTAINER_CLIENT_ID ) { + if ( clientId === '' /* ROOT_CONTAINER_CLIENT_ID */ ) { return 'contentOnly'; } @@ -3009,7 +3001,7 @@ export const getBlockEditingMode = createRegistrySelector( */ export const isUngroupable = createRegistrySelector( ( select ) => - ( state, clientId = ROOT_CONTAINER_CLIENT_ID ) => { + ( state, clientId = '' ) => { const _clientId = clientId || getSelectedBlockClientId( state ); if ( ! _clientId ) { return false; From 9e5640ae2a55221ff948f3af4f7b98dcc7517134 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Tue, 9 Apr 2024 08:19:10 -0500 Subject: [PATCH 41/53] Revert list-view changes --- .../src/components/list-view/block.js | 5 +- .../src/components/list-view/branch.js | 58 +++++++------------ .../src/components/list-view/index.js | 11 +++- 3 files changed, 30 insertions(+), 44 deletions(-) diff --git a/packages/block-editor/src/components/list-view/block.js b/packages/block-editor/src/components/list-view/block.js index 115f7cef2f2083..930d0a0f80ef66 100644 --- a/packages/block-editor/src/components/list-view/block.js +++ b/packages/block-editor/src/components/list-view/block.js @@ -63,7 +63,6 @@ function ListViewBlock( { isExpanded, selectedClientIds, isSyncedBranch, - hideInnerBlocks, } ) { const cellRef = useRef( null ); const rowRef = useRef( null ); @@ -317,9 +316,7 @@ function ListViewBlock( { path={ path } id={ `list-view-${ listViewInstanceId }-block-${ clientId }` } data-block={ clientId } - data-expanded={ - canEdit && ! hideInnerBlocks ? isExpanded : undefined - } + data-expanded={ canEdit ? isExpanded : undefined } ref={ rowRef } > { - return { - getHasOverlay: - select( blockEditorStore ) - .__unstableHasActiveBlockOverlayActive, - isZoomOutMode: - select( blockEditorStore ).__unstableGetEditorMode() === - 'zoom-out', - }; - }, [] ); - const { blockDropPosition, blockDropTargetIndex, @@ -184,9 +174,10 @@ function ListViewBranch( props ) { : `${ position }`; const hasNestedBlocks = !! innerBlocks?.length; - const shouldExpand = hasNestedBlocks - ? expandedState[ clientId ] ?? isExpanded - : undefined; + const shouldExpand = + hasNestedBlocks && shouldShowInnerBlocks + ? expandedState[ clientId ] ?? isExpanded + : undefined; // Make updates to the selected or dragged blocks synchronous, // but asynchronous for any other block. @@ -197,9 +188,6 @@ function ListViewBranch( props ) { const isSelectedBranch = isBranchSelected || ( isSelected && hasNestedBlocks ); - const hideInnerBlocks = - isZoomOutMode && getHasOverlay( clientId ); - // To avoid performance issues, we only render blocks that are in view, // or blocks that are selected or dragged. If a block is selected, // it is only counted if it is the first of the block selection. @@ -232,7 +220,6 @@ function ListViewBranch( props ) { displacement={ displacement } isAfterDraggedBlocks={ isAfterDraggedBlocks } isNesting={ isNesting } - hideInnerBlocks={ hideInnerBlocks } /> ) } { ! showBlock && ( @@ -240,25 +227,22 @@ function ListViewBranch( props ) { ) } - { hasNestedBlocks && - shouldExpand && - ! hideInnerBlocks && - ! isDragged && ( - - ) } + { hasNestedBlocks && shouldExpand && ! isDragged && ( + + ) } ); } ) } diff --git a/packages/block-editor/src/components/list-view/index.js b/packages/block-editor/src/components/list-view/index.js index 37e5d2d355237b..8a696c6f56c241 100644 --- a/packages/block-editor/src/components/list-view/index.js +++ b/packages/block-editor/src/components/list-view/index.js @@ -119,16 +119,20 @@ function ListViewComponent( const blockIndexes = useListViewBlockIndexes( clientIdsTree ); const { getBlock } = useSelect( blockEditorStore ); - const { visibleBlockCount } = useSelect( + const { visibleBlockCount, shouldShowInnerBlocks } = useSelect( ( select ) => { - const { getGlobalBlockCount, getClientIdsOfDescendants } = - select( blockEditorStore ); + const { + getGlobalBlockCount, + getClientIdsOfDescendants, + __unstableGetEditorMode, + } = select( blockEditorStore ); const draggedBlockCount = draggedClientIds?.length > 0 ? getClientIdsOfDescendants( draggedClientIds ).length + 1 : 0; return { visibleBlockCount: getGlobalBlockCount() - draggedBlockCount, + shouldShowInnerBlocks: __unstableGetEditorMode() !== 'zoom-out', }; }, [ draggedClientIds ] @@ -393,6 +397,7 @@ function ListViewComponent( fixedListWindow={ fixedListWindow } selectedClientIds={ selectedClientIds } isExpanded={ isExpanded } + shouldShowInnerBlocks={ shouldShowInnerBlocks } showAppender={ showAppender } /> From dfc8f1e99d2fd7c0e9afa8e3796bf3477202614a Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Tue, 9 Apr 2024 12:12:36 -0500 Subject: [PATCH 42/53] Try moving post type logic into useBlockEditorSettings --- packages/block-editor/src/store/selectors.js | 156 ++++++------------ .../editor/src/components/provider/index.js | 3 +- .../provider/use-block-editor-settings.js | 41 ++++- 3 files changed, 87 insertions(+), 113 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 13a923a1a8175e..b7aeab5d36c4d4 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2797,59 +2797,49 @@ export function __unstableGetTemporarilyEditingFocusModeToRevert( state ) { return state.temporarilyEditingFocusModeRevert; } -export const __unstableHasActiveBlockOverlayActive = createRegistrySelector( - ( select ) => - createSelector( ( state, clientId ) => { - // Prevent overlay on blocks with a non-default editing mode. If the mdoe is - // 'disabled' then the overlay is redundant since the block can't be - // selected. If the mode is 'contentOnly' then the overlay is redundant - // since there will be no controls to interact with once selected. - if ( getBlockEditingMode( state, clientId ) !== 'default' ) { - return false; - } +export function __unstableHasActiveBlockOverlayActive( state, clientId ) { + // Prevent overlay on blocks with a non-default editing mode. If the mdoe is + // 'disabled' then the overlay is redundant since the block can't be + // selected. If the mode is 'contentOnly' then the overlay is redundant + // since there will be no controls to interact with once selected. + if ( getBlockEditingMode( state, clientId ) !== 'default' ) { + return false; + } - // If the block editing is locked, the block overlay is always active. - if ( ! canEditBlock( state, clientId ) ) { - return true; - } + // If the block editing is locked, the block overlay is always active. + if ( ! canEditBlock( state, clientId ) ) { + return true; + } - const editorMode = __unstableGetEditorMode( state ); + const editorMode = __unstableGetEditorMode( state ); - // In zoom-out mode, the block overlay is always active for top level blocks. - if ( - editorMode === 'zoom-out' && - clientId && - getBlockRootClientId( state, clientId ) === - unlock( select( STORE_NAME ) ).getSectionsContainerClientId( - state - ) - ) { - return true; - } + // In zoom-out mode, the block overlay is always active for top level blocks. + if ( editorMode === 'zoom-out' && clientId ) { + return true; + } - // In navigation mode, the block overlay is active when the block is not - // selected (and doesn't contain a selected child). The same behavior is - // also enabled in all modes for blocks that have controlled children - // (reusable block, template part, navigation), unless explicitly disabled - // with `supports.__experimentalDisableBlockOverlay`. - const blockSupportDisable = hasBlockSupport( - getBlockName( state, clientId ), - '__experimentalDisableBlockOverlay', - false - ); - const shouldEnableIfUnselected = - editorMode === 'navigation' || - ( blockSupportDisable - ? false - : areInnerBlocksControlled( state, clientId ) ); + // In navigation mode, the block overlay is active when the block is not + // selected (and doesn't contain a selected child). The same behavior is + // also enabled in all modes for blocks that have controlled children + // (reusable block, template part, navigation), unless explicitly disabled + // with `supports.__experimentalDisableBlockOverlay`. + const blockSupportDisable = hasBlockSupport( + getBlockName( state, clientId ), + '__experimentalDisableBlockOverlay', + false + ); + const shouldEnableIfUnselected = + editorMode === 'navigation' || + ( blockSupportDisable + ? false + : areInnerBlocksControlled( state, clientId ) ); - return ( - shouldEnableIfUnselected && - ! isBlockSelected( state, clientId ) && - ! hasSelectedInnerBlock( state, clientId, true ) - ); - } ) -); + return ( + shouldEnableIfUnselected && + ! isBlockSelected( state, clientId ) && + ! hasSelectedInnerBlock( state, clientId, true ) + ); +} export function __unstableIsWithinBlockOverlay( state, clientId ) { let parent = state.blocks.parents.get( clientId ); @@ -2902,66 +2892,20 @@ export const getBlockEditingMode = createRegistrySelector( // sections. const editorMode = __unstableGetEditorMode( state ); if ( editorMode === 'zoom-out' ) { - const sectionsContainerClientId = unlock( - select( STORE_NAME ) - ).getSectionsContainerClientId(); - - if ( sectionsContainerClientId ) { - // If we have a sections container (usually a core/group - //
element), only allow editing of the contents of - // the container. - - if ( clientId === '' /* ROOT_CONTAINER_CLIENT_ID */ ) { - return 'disabled'; - } - - if ( clientId === sectionsContainerClientId ) { - return 'contentOnly'; - } - - const sectionsClientIds = getClientIdsOfDescendants( - state, - sectionsContainerClientId - ); - if ( sectionsClientIds.includes( clientId ) ) { - return 'default'; - } - } else { - // If we don't have a sections container, we get the top-level - // blocks and only allow editing those blocks. - - if ( clientId === '' /* ROOT_CONTAINER_CLIENT_ID */ ) { - return 'contentOnly'; - } - - const sectionsClientIds = getBlockOrder( state ); - if ( sectionsClientIds.includes( clientId ) ) { - return 'contentOnly'; - } + if ( clientId === '' /* ROOT_CONTAINER_CLIENT_ID */ ) { + return 'disabled'; + } - const block = getBlock( state, clientId ); - if ( block?.name === 'core/template-part' ) { - return 'disabled'; - } + const { + __experimentalSectionRootClientId: sectionRootClientId, + } = getSettings( state ); + if ( clientId === sectionRootClientId ) { + return 'contentOnly'; + } - const isSectionChildClientId = sectionsClientIds.some( - ( sectionClientId ) => { - const sectionBlock = getBlock( - state, - sectionClientId - ); - if ( sectionBlock?.name === 'core/template-part' ) { - return false; - } - return sectionBlock?.innerBlocks.some( - ( innerBlock ) => - innerBlock.clientId === clientId - ); - } - ); - if ( isSectionChildClientId ) { - return 'disabled'; - } + const sectionsClientIds = getBlockOrder( state ); + if ( sectionsClientIds.includes( clientId ) ) { + return 'default'; } } diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 8a65a4ff2cb08b..08397ea6645362 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -167,7 +167,8 @@ export const ExperimentalEditorProvider = withRegistryProvider( const blockEditorSettings = useBlockEditorSettings( editorSettings, type, - id + id, + post.type ); const [ blocks, onInput, onChange ] = useBlockEditorProps( post, diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 2f8bf920a4829d..26940d1dc9daf5 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -12,7 +12,10 @@ import { __ } from '@wordpress/i18n'; import { store as preferencesStore } from '@wordpress/preferences'; import { useViewportMatch } from '@wordpress/compose'; import { store as blocksStore } from '@wordpress/blocks'; -import { privateApis } from '@wordpress/block-editor'; +import { + privateApis, + store as blockEditorStore, +} from '@wordpress/block-editor'; /** * Internal dependencies @@ -85,13 +88,14 @@ const BLOCK_EDITOR_SETTINGS = [ /** * React hook used to compute the block editor settings to use for the post editor. * - * @param {Object} settings EditorProvider settings prop. - * @param {string} postType Editor root level post type. - * @param {string} postId Editor root level post ID. + * @param {Object} settings EditorProvider settings prop. + * @param {string} postType Editor root level post type. + * @param {string} postId Editor root level post ID. + * @param {string} contextPostType The post type of the edited post. * * @return {Object} Block Editor Settings. */ -function useBlockEditorSettings( settings, postType, postId ) { +function useBlockEditorSettings( settings, postType, postId, contextPostType ) { const isLargeViewport = useViewportMatch( 'medium' ); const { allowRightClickOverrides, @@ -108,6 +112,7 @@ function useBlockEditorSettings( settings, postType, postId ) { pageForPosts, userPatternCategories, restBlockPatternCategories, + sectionRootClientId, } = useSelect( ( select ) => { const { @@ -119,10 +124,31 @@ function useBlockEditorSettings( settings, postType, postId ) { } = select( coreStore ); const { get } = select( preferencesStore ); const { getBlockTypes } = select( blocksStore ); + const { getBlocksByName, getBlockAttributes } = + select( blockEditorStore ); const siteSettings = canUser( 'read', 'settings' ) ? getEntityRecord( 'root', 'site' ) : undefined; + function getSectionRootBlock() { + if ( ! contextPostType ) { + return null; + } + + if ( [ 'post', 'page' ].includes( contextPostType ) ) { + return ( + getBlocksByName( 'core/post-content' )?.[ 0 ] ?? null + ); + } + + return ( + getBlocksByName( 'core/group' ).find( + ( clientId ) => + getBlockAttributes( clientId )?.tagName === 'main' + ) ?? null + ); + } + return { allowRightClickOverrides: get( 'core', @@ -146,9 +172,10 @@ function useBlockEditorSettings( settings, postType, postId ) { pageForPosts: siteSettings?.page_for_posts, userPatternCategories: getUserPatternCategories(), restBlockPatternCategories: getBlockPatternCategories(), + sectionRootClientId: getSectionRootBlock(), }; }, - [ postType, postId, isLargeViewport ] + [ postType, postId, isLargeViewport, contextPostType ] ); const settingsBlockPatterns = @@ -278,6 +305,7 @@ function useBlockEditorSettings( settings, postType, postId ) { ? [ [ 'core/navigation', {}, [] ] ] : settings.template, __experimentalSetIsInserterOpened: setIsInserterOpened, + __experimentalSectionRootClientId: sectionRootClientId, } ), [ allowedBlockTypes, @@ -300,6 +328,7 @@ function useBlockEditorSettings( settings, postType, postId ) { pageForPosts, postType, setIsInserterOpened, + sectionRootClientId, ] ); } From d632363c2db66c6bf33ba7787ae300e3998d5822 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Tue, 9 Apr 2024 14:02:08 -0500 Subject: [PATCH 43/53] Try make sectionRootClientId a private setting --- packages/block-editor/src/store/selectors.js | 4 +- .../provider/use-block-editor-settings.js | 58 ++++++++++--------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index b7aeab5d36c4d4..3e5f5fad82fba1 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2896,9 +2896,7 @@ export const getBlockEditingMode = createRegistrySelector( return 'disabled'; } - const { - __experimentalSectionRootClientId: sectionRootClientId, - } = getSettings( state ); + const { sectionRootClientId } = unlock( getSettings( state ) ); if ( clientId === sectionRootClientId ) { return 'contentOnly'; } diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 26940d1dc9daf5..d35085ba0b8878 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -23,7 +23,7 @@ import { import inserterMediaCategories from '../media-categories'; import { mediaUpload } from '../../utils'; import { store as editorStore } from '../../store'; -import { unlock } from '../../lock-unlock'; +import { lock, unlock } from '../../lock-unlock'; const EMPTY_BLOCKS_LIST = []; @@ -257,8 +257,8 @@ function useBlockEditorSettings( settings, postType, postId, contextPostType ) { const forceDisableFocusMode = settings.focusMode === false; - return useMemo( - () => ( { + return useMemo( () => { + const _settings = { ...Object.fromEntries( Object.entries( settings ).filter( ( [ key ] ) => BLOCK_EDITOR_SETTINGS.includes( key ) @@ -305,32 +305,34 @@ function useBlockEditorSettings( settings, postType, postId, contextPostType ) { ? [ [ 'core/navigation', {}, [] ] ] : settings.template, __experimentalSetIsInserterOpened: setIsInserterOpened, - __experimentalSectionRootClientId: sectionRootClientId, - } ), - [ - allowedBlockTypes, - allowRightClickOverrides, - focusMode, - forceDisableFocusMode, - hasFixedToolbar, - isDistractionFree, - keepCaretInsideBlock, - settings, - hasUploadPermissions, - userPatternCategories, - blockPatterns, - blockPatternCategories, - canUseUnfilteredHTML, - undo, - createPageEntity, - userCanCreatePages, - pageOnFront, - pageForPosts, - postType, - setIsInserterOpened, + }; + lock( _settings, { sectionRootClientId, - ] - ); + } ); + return _settings; + }, [ + allowedBlockTypes, + allowRightClickOverrides, + focusMode, + forceDisableFocusMode, + hasFixedToolbar, + isDistractionFree, + keepCaretInsideBlock, + settings, + hasUploadPermissions, + userPatternCategories, + blockPatterns, + blockPatternCategories, + canUseUnfilteredHTML, + undo, + createPageEntity, + userCanCreatePages, + pageOnFront, + pageForPosts, + postType, + setIsInserterOpened, + sectionRootClientId, + ] ); } export default useBlockEditorSettings; From 4febcf8af24a02d8622d76c0e63957fd3fc3e24b Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Tue, 9 Apr 2024 15:09:43 -0500 Subject: [PATCH 44/53] Remove unused code --- .../src/store/private-selectors.js | 47 ------------------- packages/blocks/src/store/private-actions.js | 15 ------ .../blocks/src/store/private-selectors.js | 11 ----- packages/blocks/src/store/reducer.js | 4 -- packages/edit-site/src/store/actions.js | 38 ++++----------- 5 files changed, 8 insertions(+), 107 deletions(-) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 2e83c98f3baefe..bc4a3ba1a797c5 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -2,7 +2,6 @@ * WordPress dependencies */ import { createSelector, createRegistrySelector } from '@wordpress/data'; -import { store as blocksStore } from '@wordpress/blocks'; /** * Internal dependencies @@ -13,8 +12,6 @@ import { getBlockEditingMode, getSettings, canInsertBlockType, - getBlocksByName, - getBlockAttributes, } from './selectors'; import { checkAllowListRecursive, @@ -378,47 +375,3 @@ export function isDragging( state ) { export function getExpandedBlock( state ) { return state.expandedBlock; } - -/** - * Retrieves the client id of the section container block. - * - * @param {Object} state Block editor state. - * - * @return {string|null} The client ID of the section container block, - * null if not found. - */ -export const getSectionsContainerClientId = createRegistrySelector( - ( select ) => ( state ) => { - const { getSectionRootBlockName } = unlock( select( blocksStore ) ); - const sectionRootBlockName = getSectionRootBlockName(); - const { getGroupingBlockName } = select( blocksStore ); - const groupingBlockName = getGroupingBlockName(); - - if ( sectionRootBlockName === groupingBlockName ) { - const groupBlocks = getBlocksByName( state, sectionRootBlockName ); - const mainGroup = groupBlocks.find( - ( clientId ) => - getBlockAttributes( state, clientId )?.tagName === 'main' - ); - if ( mainGroup ) { - return mainGroup; - } - // if there is no main group and no other block is specified - // as section root - return null; - } - - const sectionRootBlocks = getBlocksByName( - state, - sectionRootBlockName - ); - - if ( sectionRootBlocks?.length > 0 ) { - return sectionRootBlocks[ 0 ]; - } - - // if other block is specified - // as section root, but its not found - return null; - } -); diff --git a/packages/blocks/src/store/private-actions.js b/packages/blocks/src/store/private-actions.js index 57345541d78f2d..d609f70b91b55d 100644 --- a/packages/blocks/src/store/private-actions.js +++ b/packages/blocks/src/store/private-actions.js @@ -55,18 +55,3 @@ export function registerBlockBindingsSource( source ) { lockAttributesEditing: source.lockAttributesEditing, }; } - -/** - * Returns an action object used to set the name of the block used - * to wrap sections - * - * @param {string} name Block name. - * - * @return {Object} Action object. - */ -export function setSectionRootBlockName( name = 'core/group' ) { - return { - type: 'SET_SECTION_ROOT_BLOCK_NAME', - name, - }; -} diff --git a/packages/blocks/src/store/private-selectors.js b/packages/blocks/src/store/private-selectors.js index 84cc05de6e6ff1..4cded8268ae97c 100644 --- a/packages/blocks/src/store/private-selectors.js +++ b/packages/blocks/src/store/private-selectors.js @@ -209,14 +209,3 @@ export function getAllBlockBindingsSources( state ) { export function getBlockBindingsSource( state, sourceName ) { return state.blockBindingsSources[ sourceName ]; } - -/** - * Returns the name of the block for handling the wrapping of sectios. - * - * @param {Object} state Data state. - * - * @return {string?} Name of the block for handling the grouping of blocks. - */ -export function getSectionRootBlockName( state ) { - return state.sectionRootBlockName; -} diff --git a/packages/blocks/src/store/reducer.js b/packages/blocks/src/store/reducer.js index 627f43d98a4397..f92fb376b530a7 100644 --- a/packages/blocks/src/store/reducer.js +++ b/packages/blocks/src/store/reducer.js @@ -328,9 +328,6 @@ export const unregisteredFallbackBlockName = createBlockNameSetterReducer( export const groupingBlockName = createBlockNameSetterReducer( 'SET_GROUPING_BLOCK_NAME' ); -export const sectionRootBlockName = createBlockNameSetterReducer( - 'SET_SECTION_ROOT_BLOCK_NAME' -); /** * Reducer managing the categories @@ -410,7 +407,6 @@ export default combineReducers( { freeformFallbackBlockName, unregisteredFallbackBlockName, groupingBlockName, - sectionRootBlockName, categories, collections, blockBindingsSources, diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js index b60dfa5cebb95d..dfe8f81ca21ccf 100644 --- a/packages/edit-site/src/store/actions.js +++ b/packages/edit-site/src/store/actions.js @@ -2,11 +2,7 @@ * WordPress dependencies */ import apiFetch from '@wordpress/api-fetch'; -import { - store as blocksStore, - parse, - __unstableSerializeAndClean, -} from '@wordpress/blocks'; +import { parse, __unstableSerializeAndClean } from '@wordpress/blocks'; import deprecated from '@wordpress/deprecated'; import { addQueryArgs } from '@wordpress/url'; import { __ } from '@wordpress/i18n'; @@ -28,7 +24,6 @@ import { NAVIGATION_POST_TYPE, } from '../utils/constants'; import { removeTemplates } from './private-actions'; -import { unlock } from '../lock-unlock'; /** * Dispatches an action that toggles a feature flag. @@ -172,15 +167,6 @@ export function setNavigationMenu( navigationMenuId ) { }; } -function getSectionRootBlockNameFromPostType( postType ) { - const CONTENT_TYPES = [ 'post', 'page' ]; - - if ( CONTENT_TYPES.includes( postType ) ) { - return 'core/post-content'; - } - return 'core/group'; -} - /** * Action that sets an edited entity. * @@ -190,22 +176,14 @@ function getSectionRootBlockNameFromPostType( postType ) { * * @return {Object} Action object. */ -export const setEditedEntity = - ( postType, postId, context ) => - ( { registry, dispatch } ) => { - const { setSectionRootBlockName } = unlock( - registry.dispatch( blocksStore ) - ); - setSectionRootBlockName( - getSectionRootBlockNameFromPostType( context.postType ) - ); - dispatch( { - type: 'SET_EDITED_POST', - postType, - id: postId, - context, - } ); +export function setEditedEntity( postType, postId, context ) { + return { + type: 'SET_EDITED_POST', + postType, + id: postId, + context, }; +} /** * @deprecated From e5bafcc97bc879f8b64dcd6200af345817e3bd70 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Tue, 9 Apr 2024 15:19:46 -0500 Subject: [PATCH 45/53] Fix selected block in zoom out mode --- packages/block-editor/src/store/actions.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index ad54f4c2ad12e3..f98e4845e91f2f 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1438,13 +1438,12 @@ export const __unstableSetEditorMode = // When switching to zoom-out mode, we need to select the parent section if ( mode === 'zoom-out' ) { const firstSelectedClientId = select.getBlockSelectionStart(); - const sectionsContainerClientId = unlock( - registry.select( STORE_NAME ) - ).getSectionsContainerClientId(); - if ( sectionsContainerClientId ) { - const sectionClientIds = select.getBlockOrder( - sectionsContainerClientId - ); + const { sectionRootClientId } = unlock( + registry.select( STORE_NAME ).getSettings() + ); + if ( sectionRootClientId ) { + const sectionClientIds = + select.getBlockOrder( sectionRootClientId ); if ( sectionClientIds ) { const parents = select.getBlockParents( firstSelectedClientId From 29399fdef5fb0b887efc63b050c8a0c4203ececa Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Tue, 9 Apr 2024 15:36:03 -0500 Subject: [PATCH 46/53] Rename _settings to blockEditorSettings --- .../src/components/provider/use-block-editor-settings.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index d35085ba0b8878..ca02b35d2366ba 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -258,7 +258,7 @@ function useBlockEditorSettings( settings, postType, postId, contextPostType ) { const forceDisableFocusMode = settings.focusMode === false; return useMemo( () => { - const _settings = { + const blockEditorSettings = { ...Object.fromEntries( Object.entries( settings ).filter( ( [ key ] ) => BLOCK_EDITOR_SETTINGS.includes( key ) @@ -306,10 +306,10 @@ function useBlockEditorSettings( settings, postType, postId, contextPostType ) { : settings.template, __experimentalSetIsInserterOpened: setIsInserterOpened, }; - lock( _settings, { + lock( blockEditorSettings, { sectionRootClientId, } ); - return _settings; + return blockEditorSettings; }, [ allowedBlockTypes, allowRightClickOverrides, From 3af69383c541aff1dfb6a4d52d4148c8b16b76c8 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Tue, 9 Apr 2024 15:59:45 -0500 Subject: [PATCH 47/53] Remove destructuing --- packages/editor/src/components/provider/index.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 08397ea6645362..94d3ec0289d7ac 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -163,11 +163,10 @@ export const ExperimentalEditorProvider = withRegistryProvider( }, [] ); - const { id, type } = rootLevelPost; const blockEditorSettings = useBlockEditorSettings( editorSettings, - type, - id, + rootLevelPost.type, + rootLevelPost.id, post.type ); const [ blocks, onInput, onChange ] = useBlockEditorProps( @@ -263,7 +262,7 @@ export const ExperimentalEditorProvider = withRegistryProvider( { mode === 'template-locked' && ( ) } - { type === 'wp_navigation' && ( + { rootLevelPost.type === 'wp_navigation' && ( ) } From a9529ac4569739379283516443918564659dc51e Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Wed, 10 Apr 2024 14:36:19 +0300 Subject: [PATCH 48/53] make templates with no root also work --- packages/block-editor/src/store/selectors.js | 10 ++-------- .../components/provider/use-block-editor-settings.js | 1 + 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 3e5f5fad82fba1..2d29da6101e4dc 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2892,19 +2892,13 @@ export const getBlockEditingMode = createRegistrySelector( // sections. const editorMode = __unstableGetEditorMode( state ); if ( editorMode === 'zoom-out' ) { + const { sectionRootClientId } = unlock( getSettings( state ) ); if ( clientId === '' /* ROOT_CONTAINER_CLIENT_ID */ ) { - return 'disabled'; + return sectionRootClientId ? 'disabled' : 'contentOnly'; } - - const { sectionRootClientId } = unlock( getSettings( state ) ); if ( clientId === sectionRootClientId ) { return 'contentOnly'; } - - const sectionsClientIds = getBlockOrder( state ); - if ( sectionsClientIds.includes( clientId ) ) { - return 'default'; - } } const blockEditingMode = state.blockEditingModes.get( clientId ); diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index ca02b35d2366ba..1e7ed259385737 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -73,6 +73,7 @@ const BLOCK_EDITOR_SETTINGS = [ 'postContentAttributes', 'postsPerPage', 'readOnly', + 'sectionRootClientId', 'styles', 'titlePlaceholder', 'supportsLayout', From cb04e3840b2e644613cb584c8cb8cb5d9dc596d4 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 10 Apr 2024 15:39:00 -0500 Subject: [PATCH 49/53] Check block list for active block overlay --- packages/block-editor/src/store/selectors.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 2d29da6101e4dc..2b49a82b998560 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2813,8 +2813,13 @@ export function __unstableHasActiveBlockOverlayActive( state, clientId ) { const editorMode = __unstableGetEditorMode( state ); - // In zoom-out mode, the block overlay is always active for top level blocks. - if ( editorMode === 'zoom-out' && clientId ) { + // In zoom-out mode, the block overlay is always active for section level blocks. + if ( editorMode === 'zoom-out' ) { + const { sectionRootClientId } = unlock( getSettings( state ) ); + const sectionClientIds = getBlockOrder( state, sectionRootClientId ); + if ( sectionClientIds?.includes( clientId ) ) { + return true; + } return true; } From 6c2b78f8166b331cd18b80e5f693f986015a6b90 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 10 Apr 2024 15:49:55 -0500 Subject: [PATCH 50/53] Pass rendering mode instead of type --- .../editor/src/components/provider/index.js | 9 +++---- .../provider/use-block-editor-settings.js | 24 +++++++------------ 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/packages/editor/src/components/provider/index.js b/packages/editor/src/components/provider/index.js index 94d3ec0289d7ac..5d4b2c0079a741 100644 --- a/packages/editor/src/components/provider/index.js +++ b/packages/editor/src/components/provider/index.js @@ -163,11 +163,12 @@ export const ExperimentalEditorProvider = withRegistryProvider( }, [] ); + const { id, type } = rootLevelPost; const blockEditorSettings = useBlockEditorSettings( editorSettings, - rootLevelPost.type, - rootLevelPost.id, - post.type + type, + id, + mode ); const [ blocks, onInput, onChange ] = useBlockEditorProps( post, @@ -262,7 +263,7 @@ export const ExperimentalEditorProvider = withRegistryProvider( { mode === 'template-locked' && ( ) } - { rootLevelPost.type === 'wp_navigation' && ( + { type === 'wp_navigation' && ( ) } diff --git a/packages/editor/src/components/provider/use-block-editor-settings.js b/packages/editor/src/components/provider/use-block-editor-settings.js index 1e7ed259385737..bcd08856141831 100644 --- a/packages/editor/src/components/provider/use-block-editor-settings.js +++ b/packages/editor/src/components/provider/use-block-editor-settings.js @@ -89,14 +89,14 @@ const BLOCK_EDITOR_SETTINGS = [ /** * React hook used to compute the block editor settings to use for the post editor. * - * @param {Object} settings EditorProvider settings prop. - * @param {string} postType Editor root level post type. - * @param {string} postId Editor root level post ID. - * @param {string} contextPostType The post type of the edited post. + * @param {Object} settings EditorProvider settings prop. + * @param {string} postType Editor root level post type. + * @param {string} postId Editor root level post ID. + * @param {string} renderingMode Editor rendering mode. * * @return {Object} Block Editor Settings. */ -function useBlockEditorSettings( settings, postType, postId, contextPostType ) { +function useBlockEditorSettings( settings, postType, postId, renderingMode ) { const isLargeViewport = useViewportMatch( 'medium' ); const { allowRightClickOverrides, @@ -132,21 +132,15 @@ function useBlockEditorSettings( settings, postType, postId, contextPostType ) { : undefined; function getSectionRootBlock() { - if ( ! contextPostType ) { - return null; - } - - if ( [ 'post', 'page' ].includes( contextPostType ) ) { - return ( - getBlocksByName( 'core/post-content' )?.[ 0 ] ?? null - ); + if ( renderingMode === 'template-locked' ) { + return getBlocksByName( 'core/post-content' )?.[ 0 ] ?? ''; } return ( getBlocksByName( 'core/group' ).find( ( clientId ) => getBlockAttributes( clientId )?.tagName === 'main' - ) ?? null + ) ?? '' ); } @@ -176,7 +170,7 @@ function useBlockEditorSettings( settings, postType, postId, contextPostType ) { sectionRootClientId: getSectionRootBlock(), }; }, - [ postType, postId, isLargeViewport, contextPostType ] + [ postType, postId, isLargeViewport, renderingMode ] ); const settingsBlockPatterns = From 640823fbb49baf313bcb0d806cb10cd450f08984 Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 10 Apr 2024 16:24:32 -0500 Subject: [PATCH 51/53] Fix an issue where some selectors pass null as a default value instead of undefined --- packages/block-editor/src/store/selectors.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 2b49a82b998560..0c1fd2184c8fef 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2892,6 +2892,11 @@ export function __unstableIsWithinBlockOverlay( state, clientId ) { export const getBlockEditingMode = createRegistrySelector( ( select ) => ( state, clientId = '' ) => { + // Some selectors that call this provide `null` as the default + // rootClientId, but the default rootClientId is actually `''`. + if ( clientId === null ) { + clientId = ''; + } // In zoom-out mode, override the behavior set by // __unstableSetBlockEditingMode to only allow editing the top-level // sections. From fd8cf0a8ea26630b74c6b9b8341e2c498a2cad7a Mon Sep 17 00:00:00 2001 From: Alex Lende Date: Wed, 10 Apr 2024 16:32:18 -0500 Subject: [PATCH 52/53] Try disabling all non-children of the sectionRoot --- packages/block-editor/src/store/selectors.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 0c1fd2184c8fef..4612c168db9b90 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2909,6 +2909,13 @@ export const getBlockEditingMode = createRegistrySelector( if ( clientId === sectionRootClientId ) { return 'contentOnly'; } + const sectionsClientIds = getBlockOrder( + state, + sectionRootClientId + ); + if ( ! sectionsClientIds?.includes( clientId ) ) { + return 'disabled'; + } } const blockEditingMode = state.blockEditingModes.get( clientId ); From b96f5a659f0a6be6fe711b4a0c2d953f2a8d6254 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Thu, 11 Apr 2024 14:40:51 +0300 Subject: [PATCH 53/53] don't put overlay on all blocks in zoom out, just root and section children --- packages/block-editor/src/store/selectors.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 4612c168db9b90..ccb4ca8b602ebc 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2816,11 +2816,17 @@ export function __unstableHasActiveBlockOverlayActive( state, clientId ) { // In zoom-out mode, the block overlay is always active for section level blocks. if ( editorMode === 'zoom-out' ) { const { sectionRootClientId } = unlock( getSettings( state ) ); - const sectionClientIds = getBlockOrder( state, sectionRootClientId ); - if ( sectionClientIds?.includes( clientId ) ) { + if ( sectionRootClientId ) { + const sectionClientIds = getBlockOrder( + state, + sectionRootClientId + ); + if ( sectionClientIds?.includes( clientId ) ) { + return true; + } + } else if ( clientId && ! getBlockRootClientId( state, clientId ) ) { return true; } - return true; } // In navigation mode, the block overlay is active when the block is not