From 32b3ed86c21850d3aae6f25032c442ee4bd12820 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 10 Sep 2024 15:23:08 +0200 Subject: [PATCH 01/22] Select Mode: Use the content-only behavior in select mode --- packages/base-styles/_z-index.scss | 5 - .../src/components/block-inspector/index.js | 171 +++++----- .../src/components/block-list/block.js | 8 +- .../src/components/block-list/content.scss | 22 -- .../src/components/block-list/index.js | 32 +- .../block-list/use-block-props/index.js | 2 - .../use-block-props/use-nav-mode-exit.js | 46 --- .../block-tools/block-selection-button.js | 302 ------------------ .../block-tools/block-toolbar-breadcrumb.js | 51 --- .../src/components/block-tools/index.js | 10 - .../src/components/block-tools/style.scss | 82 ----- .../block-tools/use-show-block-tools.js | 14 +- .../src/components/inner-blocks/content.scss | 13 - .../src/components/inner-blocks/index.js | 17 +- packages/block-editor/src/content.scss | 1 - .../src/store/private-selectors.js | 32 +- packages/block-editor/src/store/reducer.js | 5 - packages/block-editor/src/store/selectors.js | 11 +- .../specs/widgets/customizing-widgets.spec.js | 2 +- 19 files changed, 132 insertions(+), 694 deletions(-) delete mode 100644 packages/block-editor/src/components/block-list/use-block-props/use-nav-mode-exit.js delete mode 100644 packages/block-editor/src/components/block-tools/block-selection-button.js delete mode 100644 packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js delete mode 100644 packages/block-editor/src/components/inner-blocks/content.scss diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index cc99df6dbeaaf..77238c6f38608 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -8,7 +8,6 @@ $z-layers: ( ".block-editor-block-switcher__arrow": 1, ".block-editor-block-list__block {core/image aligned wide or fullwide}": 20, ".block-library-classic__toolbar": 31, // When scrolled to top this toolbar needs to sit over block-editor-block-toolbar - ".block-editor-block-list__block-selection-button": 22, ".components-form-toggle__input": 1, ".editor-text-editor__toolbar": 1, @@ -70,10 +69,6 @@ $z-layers: ( // Below the media library backdrop (.media-modal-backdrop), which has a z-index of 159900. ".block-editor-global-styles-background-panel__popover": 159900 - 10, - // Small screen inner blocks overlay must be displayed above drop zone, - // settings menu, and movers. - ".block-editor-block-list__layout.has-overlay::after": 60, - // The toolbar, when contextual, should be above any adjacent nested block click overlays. ".block-editor-block-contextual-toolbar": 61, diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index a18556f2fa5bd..4494941077429 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -40,83 +40,38 @@ function BlockStylesPanel( { clientId } ) { ); } -function BlockInspectorLockedBlocks( { topLevelLockedBlock } ) { - const contentClientIds = useSelect( - ( select ) => { - const { - getClientIdsOfDescendants, - getBlockName, - getBlockEditingMode, - } = select( blockEditorStore ); - return getClientIdsOfDescendants( topLevelLockedBlock ).filter( - ( clientId ) => - getBlockName( clientId ) !== 'core/list-item' && - getBlockEditingMode( clientId ) === 'contentOnly' - ); - }, - [ topLevelLockedBlock ] - ); - const hasBlockStyles = useSelect( - ( select ) => { - const { getBlockName } = select( blockEditorStore ); - const { getBlockStyles } = select( blocksStore ); - return !! getBlockStyles( getBlockName( topLevelLockedBlock ) ) - ?.length; - }, - [ topLevelLockedBlock ] - ); - const blockInformation = useBlockDisplayInformation( topLevelLockedBlock ); - return ( -
- - - { hasBlockStyles && ( - - ) } - { contentClientIds.length > 0 && ( - - - - ) } -
- ); -} - const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { const { count, selectedBlockName, selectedBlockClientId, blockType, - topLevelLockedBlock, + isContentLockingParent, } = useSelect( ( select ) => { const { getSelectedBlockClientId, getSelectedBlockCount, getBlockName, getContentLockingParent, - getTemplateLock, + isContentLockingParent: _isContentLockingParent, } = unlock( select( blockEditorStore ) ); const _selectedBlockClientId = getSelectedBlockClientId(); + const renderedBlockClientId = + getContentLockingParent( _selectedBlockClientId ) || + getSelectedBlockClientId(); const _selectedBlockName = - _selectedBlockClientId && getBlockName( _selectedBlockClientId ); + renderedBlockClientId && getBlockName( renderedBlockClientId ); const _blockType = _selectedBlockName && getBlockType( _selectedBlockName ); return { count: getSelectedBlockCount(), - selectedBlockClientId: _selectedBlockClientId, + selectedBlockClientId: renderedBlockClientId, selectedBlockName: _selectedBlockName, blockType: _blockType, - topLevelLockedBlock: - getContentLockingParent( _selectedBlockClientId ) || - ( getTemplateLock( _selectedBlockClientId ) === 'contentOnly' || - _selectedBlockName === 'core/block' - ? _selectedBlockClientId - : undefined ), + isContentLockingParent: _isContentLockingParent( + renderedBlockClientId + ), }; }, [] ); @@ -136,7 +91,7 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { blockName: selectedBlockName, } ); - if ( count > 1 ) { + if ( count > 1 && ! isContentLockingParent ) { return (
@@ -194,13 +149,6 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { } return null; } - if ( topLevelLockedBlock ) { - return ( - - ); - } return ( { ); @@ -260,9 +209,13 @@ const AnimatedContainer = ( { ); }; -const BlockInspectorSingleBlock = ( { clientId, blockName } ) => { +const BlockInspectorSingleBlock = ( { + clientId, + blockName, + isContentLockingParent, +} ) => { const availableTabs = useInspectorControlsTabs( blockName ); - const showTabs = availableTabs?.length > 1; + const showTabs = ! isContentLockingParent && availableTabs?.length > 1; const hasBlockStyles = useSelect( ( select ) => { @@ -274,6 +227,23 @@ const BlockInspectorSingleBlock = ( { clientId, blockName } ) => { ); const blockInformation = useBlockDisplayInformation( clientId ); const borderPanelLabel = useBorderPanelLabel( { blockName } ); + const contentClientIds = useSelect( + ( select ) => { + const { + getClientIdsOfDescendants, + getBlockName, + getBlockEditingMode, + } = select( blockEditorStore ); + return isContentLockingParent + ? getClientIdsOfDescendants( clientId ).filter( + ( current ) => + getBlockName( current ) !== 'core/list-item' && + getBlockEditingMode( current ) === 'contentOnly' + ) + : undefined; + }, + [ isContentLockingParent, clientId ] + ); return (
@@ -296,35 +266,48 @@ const BlockInspectorSingleBlock = ( { clientId, blockName } ) => { { hasBlockStyles && ( ) } - - - - - - - - - - -
- -
+ + { contentClientIds && contentClientIds?.length > 0 && ( + + + + ) } + + { ! isContentLockingParent && ( + <> + + + + + + + + + + +
+ +
+ + ) } ) } diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index deda4e3b9d089..6f1ba557eed82 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -681,11 +681,9 @@ function BlockListBlockProvider( props ) { hasOverlay: __unstableHasActiveBlockOverlayActive( clientId ) && ! isDragging(), - initialPosition: - _isSelected && - ( editorMode === 'edit' || editorMode === 'zoom-out' ) // Don't recalculate the initialPosition when toggling in/out of zoom-out mode - ? getSelectedBlocksInitialCaretPosition() - : undefined, + initialPosition: _isSelected + ? getSelectedBlocksInitialCaretPosition() + : undefined, isHighlighted: isBlockHighlighted( clientId ), isMultiSelected, isPartiallySelected: diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index 3f4b4c508aeb0..72fd10b163c69 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -80,7 +80,6 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b // since things like border-radius need to be able to be set on the block itself. .block-editor-block-list__block.is-highlighted, .block-editor-block-list__block.is-highlighted ~ .is-multi-selected, - &.is-navigate-mode .block-editor-block-list__block.is-selected, .block-editor-block-list__block:not([contenteditable="true"]):focus { outline: none; @@ -134,14 +133,6 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b } } -.is-block-moving-mode.block-editor-block-list__block-selection-button { - // Should be invisible but not unfocusable. - opacity: 0; - font-size: 1px; - height: 1px; - padding: 0; -} - .block-editor-block-list__layout .block-editor-block-list__block { // With `position: static`, Safari marks a full-width selection rectangle, including margins. // With `position: relative`, Safari marks an inline selection rectangle, similar to that of @@ -223,19 +214,6 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b background-color: transparent; } - // Reusable blocks clickthrough overlays. - &.is-reusable > .block-editor-inner-blocks > .block-editor-block-list__layout.has-overlay { - // Remove only the top click overlay. - &::after { - display: none; - } - - // Restore it for subsequent. - .block-editor-block-list__layout.has-overlay::after { - display: block; - } - } - // Reusable blocks parent border. &.is-reusable.has-child-selected::after { box-shadow: 0 0 0 1px var(--wp-admin-theme-color); diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index ea6128f153464..0e7d35d28c719 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -47,26 +47,17 @@ const pendingBlockVisibilityUpdatesPerRegistry = new WeakMap(); function Root( { className, ...settings } ) { const isLargeViewport = useViewportMatch( 'medium' ); - const { - isOutlineMode, - isFocusMode, - editorMode, - temporarilyEditingAsBlocks, - } = useSelect( ( select ) => { - const { - getSettings, - __unstableGetEditorMode, - getTemporarilyEditingAsBlocks, - isTyping, - } = unlock( select( blockEditorStore ) ); - const { outlineMode, focusMode } = getSettings(); - return { - isOutlineMode: outlineMode && ! isTyping(), - isFocusMode: focusMode, - editorMode: __unstableGetEditorMode(), - temporarilyEditingAsBlocks: getTemporarilyEditingAsBlocks(), - }; - }, [] ); + const { isOutlineMode, isFocusMode, temporarilyEditingAsBlocks } = + useSelect( ( select ) => { + const { getSettings, getTemporarilyEditingAsBlocks, isTyping } = + unlock( select( blockEditorStore ) ); + const { outlineMode, focusMode } = getSettings(); + return { + isOutlineMode: outlineMode && ! isTyping(), + isFocusMode: focusMode, + temporarilyEditingAsBlocks: getTemporarilyEditingAsBlocks(), + }; + }, [] ); const registry = useRegistry(); const { setBlockVisibility } = useDispatch( blockEditorStore ); @@ -115,7 +106,6 @@ function Root( { className, ...settings } ) { className: clsx( 'is-root-container', className, { 'is-outline-mode': isOutlineMode, 'is-focus-mode': isFocusMode && isLargeViewport, - 'is-navigate-mode': editorMode === 'navigation', } ), }, settings diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index c3a279a618b5d..a1b8af90c3d35 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -25,7 +25,6 @@ import { } from '../../block-edit/context'; import { useFocusHandler } from './use-focus-handler'; import { useEventHandlers } from './use-selected-block-event-handlers'; -import { useNavModeExit } from './use-nav-mode-exit'; import { useZoomOutModeExit } from './use-zoom-out-mode-exit'; import { useBlockRefProvider } from './use-block-refs'; import { useIntersectionObserver } from './use-intersection-observer'; @@ -116,7 +115,6 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { useBlockRefProvider( clientId ), useFocusHandler( clientId ), useEventHandlers( { clientId, isSelected } ), - useNavModeExit( clientId ), useZoomOutModeExit( { editorMode } ), useIsHovered( { clientId } ), useIntersectionObserver(), diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-nav-mode-exit.js b/packages/block-editor/src/components/block-list/use-block-props/use-nav-mode-exit.js deleted file mode 100644 index aa9c0a630c5bd..0000000000000 --- a/packages/block-editor/src/components/block-list/use-block-props/use-nav-mode-exit.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect, useDispatch } from '@wordpress/data'; -import { useRefEffect } from '@wordpress/compose'; - -/** - * Internal dependencies - */ -import { store as blockEditorStore } from '../../../store'; - -/** - * Allows navigation mode to be exited by clicking in the selected block. - * - * @param {string} clientId Block client ID. - */ -export function useNavModeExit( clientId ) { - const { isNavigationMode, isBlockSelected } = useSelect( blockEditorStore ); - const { setNavigationMode, selectBlock } = useDispatch( blockEditorStore ); - return useRefEffect( - ( node ) => { - function onMouseDown( event ) { - // Don't select a block if it's already handled by a child - // block. - if ( isNavigationMode() && ! event.defaultPrevented ) { - // Prevent focus from moving to the block. - event.preventDefault(); - - // When clicking on a selected block, exit navigation mode. - if ( isBlockSelected( clientId ) ) { - setNavigationMode( false ); - } else { - selectBlock( clientId ); - } - } - } - - node.addEventListener( 'mousedown', onMouseDown ); - - return () => { - node.removeEventListener( 'mousedown', onMouseDown ); - }; - }, - [ clientId, isNavigationMode, isBlockSelected, setNavigationMode ] - ); -} diff --git a/packages/block-editor/src/components/block-tools/block-selection-button.js b/packages/block-editor/src/components/block-tools/block-selection-button.js deleted file mode 100644 index 9c6c22181ef2a..0000000000000 --- a/packages/block-editor/src/components/block-tools/block-selection-button.js +++ /dev/null @@ -1,302 +0,0 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - -/** - * WordPress dependencies - */ -import { dragHandle } from '@wordpress/icons'; -import { Button, Flex, FlexItem } from '@wordpress/components'; -import { useSelect, useDispatch } from '@wordpress/data'; -import { forwardRef, useEffect } from '@wordpress/element'; -import { - BACKSPACE, - DELETE, - UP, - DOWN, - LEFT, - RIGHT, - TAB, - ESCAPE, - ENTER, - SPACE, -} from '@wordpress/keycodes'; -import { - __experimentalGetAccessibleBlockLabel as getAccessibleBlockLabel, - store as blocksStore, -} from '@wordpress/blocks'; -import { speak } from '@wordpress/a11y'; -import { focus } from '@wordpress/dom'; -import { __ } from '@wordpress/i18n'; - -/** - * Internal dependencies - */ -import BlockTitle from '../block-title'; -import BlockIcon from '../block-icon'; -import { store as blockEditorStore } from '../../store'; -import BlockDraggable from '../block-draggable'; -import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; - -/** - * Block selection button component, displaying the label of the block. If the block - * descends from a root block, a button is displayed enabling the user to select - * the root block. - * - * @param {string} props Component props. - * @param {string} props.clientId Client ID of block. - * @param {Object} ref Reference to the component. - * - * @return {Component} The component to be rendered. - */ -function BlockSelectionButton( { clientId, rootClientId }, ref ) { - const selected = useSelect( - ( select ) => { - const { - getBlock, - getBlockIndex, - hasBlockMovingClientId, - getBlockListSettings, - __unstableGetEditorMode, - getNextBlockClientId, - getPreviousBlockClientId, - canMoveBlock, - } = select( blockEditorStore ); - const { getActiveBlockVariation, getBlockType } = - select( blocksStore ); - const index = getBlockIndex( clientId ); - const { name, attributes } = getBlock( clientId ); - const blockType = getBlockType( name ); - const orientation = - getBlockListSettings( rootClientId )?.orientation; - const match = getActiveBlockVariation( name, attributes ); - - return { - blockMovingMode: hasBlockMovingClientId(), - editorMode: __unstableGetEditorMode(), - icon: match?.icon || blockType.icon, - label: getAccessibleBlockLabel( - blockType, - attributes, - index + 1, - orientation - ), - canMove: canMoveBlock( clientId, rootClientId ), - getNextBlockClientId, - getPreviousBlockClientId, - }; - }, - [ clientId, rootClientId ] - ); - const { label, icon, blockMovingMode, editorMode, canMove } = selected; - const { setNavigationMode, removeBlock } = useDispatch( blockEditorStore ); - - // Focus the breadcrumb in navigation mode. - useEffect( () => { - if ( editorMode === 'navigation' ) { - ref.current.focus(); - speak( label ); - } - }, [ label, editorMode ] ); - const blockElement = useBlockElement( clientId ); - - const { - hasBlockMovingClientId, - getBlockIndex, - getBlockRootClientId, - getClientIdsOfDescendants, - getSelectedBlockClientId, - getMultiSelectedBlocksEndClientId, - getPreviousBlockClientId, - getNextBlockClientId, - } = useSelect( blockEditorStore ); - const { - selectBlock, - clearSelectedBlock, - setBlockMovingClientId, - moveBlockToPosition, - } = useDispatch( blockEditorStore ); - - function onKeyDown( event ) { - const { keyCode } = event; - const isUp = keyCode === UP; - const isDown = keyCode === DOWN; - const isLeft = keyCode === LEFT; - const isRight = keyCode === RIGHT; - const isTab = keyCode === TAB; - const isEscape = keyCode === ESCAPE; - const isEnter = keyCode === ENTER; - const isSpace = keyCode === SPACE; - const isShift = event.shiftKey; - - if ( keyCode === BACKSPACE || keyCode === DELETE ) { - removeBlock( clientId ); - event.preventDefault(); - return; - } - - const selectedBlockClientId = getSelectedBlockClientId(); - const selectionEndClientId = getMultiSelectedBlocksEndClientId(); - const selectionBeforeEndClientId = getPreviousBlockClientId( - selectionEndClientId || selectedBlockClientId - ); - const selectionAfterEndClientId = getNextBlockClientId( - selectionEndClientId || selectedBlockClientId - ); - - const navigateUp = ( isTab && isShift ) || isUp; - const navigateDown = ( isTab && ! isShift ) || isDown; - // Move out of current nesting level (no effect if at root level). - const navigateOut = isLeft; - // Move into next nesting level (no effect if the current block has no innerBlocks). - const navigateIn = isRight; - - let focusedBlockUid; - if ( navigateUp ) { - focusedBlockUid = selectionBeforeEndClientId; - } else if ( navigateDown ) { - focusedBlockUid = selectionAfterEndClientId; - } else if ( navigateOut ) { - focusedBlockUid = - getBlockRootClientId( selectedBlockClientId ) ?? - selectedBlockClientId; - } else if ( navigateIn ) { - focusedBlockUid = - getClientIdsOfDescendants( selectedBlockClientId )[ 0 ] ?? - selectedBlockClientId; - } - const startingBlockClientId = hasBlockMovingClientId(); - if ( isEscape && startingBlockClientId && ! event.defaultPrevented ) { - setBlockMovingClientId( null ); - event.preventDefault(); - } - if ( ( isEnter || isSpace ) && startingBlockClientId ) { - const sourceRoot = getBlockRootClientId( startingBlockClientId ); - const destRoot = getBlockRootClientId( selectedBlockClientId ); - const sourceBlockIndex = getBlockIndex( startingBlockClientId ); - let destinationBlockIndex = getBlockIndex( selectedBlockClientId ); - if ( - sourceBlockIndex < destinationBlockIndex && - sourceRoot === destRoot - ) { - destinationBlockIndex -= 1; - } - moveBlockToPosition( - startingBlockClientId, - sourceRoot, - destRoot, - destinationBlockIndex - ); - selectBlock( startingBlockClientId ); - setBlockMovingClientId( null ); - } - // Prevent the block from being moved into itself. - if ( - startingBlockClientId && - selectedBlockClientId === startingBlockClientId && - navigateIn - ) { - return; - } - if ( navigateDown || navigateUp || navigateOut || navigateIn ) { - if ( focusedBlockUid ) { - event.preventDefault(); - selectBlock( focusedBlockUid ); - } else if ( isTab && selectedBlockClientId ) { - let nextTabbable; - - if ( navigateDown ) { - nextTabbable = blockElement; - do { - nextTabbable = focus.tabbable.findNext( nextTabbable ); - } while ( - nextTabbable && - blockElement.contains( nextTabbable ) - ); - - if ( ! nextTabbable ) { - nextTabbable = - blockElement.ownerDocument.defaultView.frameElement; - nextTabbable = focus.tabbable.findNext( nextTabbable ); - } - } else { - nextTabbable = focus.tabbable.findPrevious( blockElement ); - } - - if ( nextTabbable ) { - event.preventDefault(); - nextTabbable.focus(); - clearSelectedBlock(); - } - } - } - } - - const classNames = clsx( - 'block-editor-block-list__block-selection-button', - { - 'is-block-moving-mode': !! blockMovingMode, - } - ); - - const dragHandleLabel = __( 'Drag' ); - const showBlockDraggable = canMove && editorMode === 'navigation'; - - return ( -
- - - - - { showBlockDraggable && ( - - - { ( draggableProps ) => ( - - - ) } - -
- ); -} - -export default forwardRef( BlockSelectionButton ); diff --git a/packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js b/packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js deleted file mode 100644 index ae03bdb4f5164..0000000000000 --- a/packages/block-editor/src/components/block-tools/block-toolbar-breadcrumb.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * External dependencies - */ -import clsx from 'clsx'; - -/** - * WordPress dependencies - */ -import { forwardRef } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import BlockSelectionButton from './block-selection-button'; -import { PrivateBlockPopover } from '../block-popover'; -import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props'; -import useSelectedBlockToolProps from './use-selected-block-tool-props'; - -function BlockToolbarBreadcrumb( { clientId, __unstableContentRef }, ref ) { - const { - capturingClientId, - isInsertionPointVisible, - lastClientId, - rootClientId, - } = useSelectedBlockToolProps( clientId ); - - const popoverProps = useBlockToolbarPopoverProps( { - contentElement: __unstableContentRef?.current, - clientId, - } ); - - return ( - - - - ); -} - -export default forwardRef( BlockToolbarBreadcrumb ); diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js index 24f60dbbf970a..099323925384b 100644 --- a/packages/block-editor/src/components/block-tools/index.js +++ b/packages/block-editor/src/components/block-tools/index.js @@ -19,7 +19,6 @@ import { default as InsertionPoint, } from './insertion-point'; import BlockToolbarPopover from './block-toolbar-popover'; -import BlockToolbarBreadcrumb from './block-toolbar-breadcrumb'; import ZoomOutPopover from './zoom-out-popover'; import { store as blockEditorStore } from '../../store'; import usePopoverScroll from '../block-popover/use-popover-scroll'; @@ -78,7 +77,6 @@ export default function BlockTools( { const { getGroupingBlockName } = useSelect( blocksStore ); const { showEmptyBlockSideInserter, - showBreadcrumb, showBlockToolbarPopover, showZoomOutToolbar, } = useShowBlockTools(); @@ -223,14 +221,6 @@ export default function BlockTools( { /> ) } - { showBreadcrumb && ( - - ) } - { showZoomOutToolbar && ( .components-flex__item { - margin-right: $grid-unit-15 * 0.5; - } - } - .components-button.has-icon.block-selection-button_drag-handle { - cursor: grab; - padding: 0; - height: $grid-unit-30; - min-width: $grid-unit-30; - margin-left: -2px; - - // Drag handle is smaller than the others. - svg { - min-width: 18px; - min-height: 18px; - } - } - - .block-editor-block-icon { - font-size: $default-font-size; - color: $white; - height: $block-toolbar-height; - } - - // The button here has a special style to appear as a toolbar. - .components-button { - min-width: $button-size; - color: $white; - height: $block-toolbar-height; - - // When button is focused, it receives a box-shadow instead of the border. - &:focus { - box-shadow: none; - border: none; - } - - &:active { - color: $white; - } - - // Make sure the button has no hover style when it's disabled. - &[aria-disabled="true"]:hover { - color: $white; - } - - display: flex; - } - .block-selection-button_select-button.components-button { - padding: 0; - } - - .block-editor-block-mover { - background: unset; - border: none; - } -} - // Hide the popover block editor list while dragging. // Using a hacky animation to delay hiding the element. // It's needed because if we hide the element immediately upon dragging, @@ -178,14 +100,10 @@ .components-popover.block-editor-block-list__block-popover { // Position the block toolbar. - .block-editor-block-list__block-selection-button, .block-editor-block-contextual-toolbar { pointer-events: all; margin-top: $grid-unit-10; margin-bottom: $grid-unit-10; - } - - .block-editor-block-contextual-toolbar { border: $border-width solid $gray-900; border-radius: $radius-small; overflow: visible; // allow the parent selector to be visible diff --git a/packages/block-editor/src/components/block-tools/use-show-block-tools.js b/packages/block-editor/src/components/block-tools/use-show-block-tools.js index 07e0ebd16a64b..02a8f0583bcdd 100644 --- a/packages/block-editor/src/components/block-tools/use-show-block-tools.js +++ b/packages/block-editor/src/components/block-tools/use-show-block-tools.js @@ -22,7 +22,6 @@ export function useShowBlockTools() { getBlock, getBlockMode, getSettings, - hasMultiSelection, __unstableGetEditorMode, isTyping, } = select( blockEditorStore ); @@ -42,29 +41,20 @@ export function useShowBlockTools() { ! isTyping() && editorMode === 'edit' && isEmptyDefaultBlock; - const maybeShowBreadcrumb = - hasSelectedBlock && - ! hasMultiSelection() && - editorMode === 'navigation'; - const isZoomOut = editorMode === 'zoom-out'; const _showZoomOutToolbar = isZoomOut && block?.attributes?.align === 'full' && - ! _showEmptyBlockSideInserter && - ! maybeShowBreadcrumb; + ! _showEmptyBlockSideInserter; const _showBlockToolbarPopover = ! _showZoomOutToolbar && ! getSettings().hasFixedToolbar && ! _showEmptyBlockSideInserter && hasSelectedBlock && - ! isEmptyDefaultBlock && - ! maybeShowBreadcrumb; + ! isEmptyDefaultBlock; return { showEmptyBlockSideInserter: _showEmptyBlockSideInserter, - showBreadcrumb: - ! _showEmptyBlockSideInserter && maybeShowBreadcrumb, showBlockToolbarPopover: _showBlockToolbarPopover, showZoomOutToolbar: _showZoomOutToolbar, }; diff --git a/packages/block-editor/src/components/inner-blocks/content.scss b/packages/block-editor/src/components/inner-blocks/content.scss deleted file mode 100644 index 05259ede35daa..0000000000000 --- a/packages/block-editor/src/components/inner-blocks/content.scss +++ /dev/null @@ -1,13 +0,0 @@ -// Add clickable overlay to blocks with nesting. -// This makes it easy to select all layers of the block. -.block-editor-block-list__layout.has-overlay { - &::after { - content: ""; - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: z-index(".block-editor-block-list__layout.has-overlay::after"); - } -} diff --git a/packages/block-editor/src/components/inner-blocks/index.js b/packages/block-editor/src/components/inner-blocks/index.js index 0d35b459190fe..1583031a8ea18 100644 --- a/packages/block-editor/src/components/inner-blocks/index.js +++ b/packages/block-editor/src/components/inner-blocks/index.js @@ -195,14 +195,11 @@ export function useInnerBlocksProps( props = {}, options = {} ) { ( select ) => { const { getBlockName, - isBlockSelected, - hasSelectedInnerBlock, __unstableGetEditorMode, getTemplateLock, getBlockRootClientId, getBlockEditingMode, getBlockSettings, - isDragging, getSectionRootClientId, } = unlock( select( blockEditorStore ) ); let _isDropZoneDisabled; @@ -213,8 +210,6 @@ export function useInnerBlocksProps( props = {}, options = {} ) { const { hasBlockSupport, getBlockType } = select( blocksStore ); const blockName = getBlockName( clientId ); - const enableClickThrough = - __unstableGetEditorMode() === 'navigation'; const blockEditingMode = getBlockEditingMode( clientId ); const parentClientId = getBlockRootClientId( clientId ); const [ defaultLayout ] = getBlockSettings( clientId, 'layout' ); @@ -236,12 +231,6 @@ export function useInnerBlocksProps( props = {}, options = {} ) { '__experimentalExposeControlsToChildren', false ), - hasOverlay: - blockName !== 'core/template' && - ! isBlockSelected( clientId ) && - ! hasSelectedInnerBlock( clientId, true ) && - enableClickThrough && - ! isDragging(), name: blockName, blockType: getBlockType( blockName ), parentLock: getTemplateLock( parentClientId ), @@ -254,7 +243,6 @@ export function useInnerBlocksProps( props = {}, options = {} ) { ); const { __experimentalCaptureToolbars, - hasOverlay, name, blockType, parentLock, @@ -299,10 +287,7 @@ export function useInnerBlocksProps( props = {}, options = {} ) { className: clsx( props.className, 'block-editor-block-list__layout', - __unstableDisableLayoutClassNames ? '' : layoutClassNames, - { - 'has-overlay': hasOverlay, - } + __unstableDisableLayoutClassNames ? '' : layoutClassNames ), children: clientId ? ( diff --git a/packages/block-editor/src/content.scss b/packages/block-editor/src/content.scss index 36d428dca6b76..1ef4e118fb1bb 100644 --- a/packages/block-editor/src/content.scss +++ b/packages/block-editor/src/content.scss @@ -8,7 +8,6 @@ @import "./components/button-block-appender/content.scss"; @import "./components/default-block-appender/content.scss"; @import "./components/iframe/content.scss"; -@import "./components/inner-blocks/content.scss"; @import "./components/media-placeholder/content.scss"; @import "./components/plain-text/content.scss"; @import "./components/rich-text/content.scss"; diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 01ad8f69febc9..98490c815b599 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -15,6 +15,7 @@ import { getBlockName, getTemplateLock, getClientIdsWithDescendants, + isNavigationMode, } from './selectors'; import { checkAllowListRecursive, @@ -480,16 +481,37 @@ export const getContentLockingParent = createSelector( let current = clientId; let result; while ( ( current = state.blocks.parents.get( current ) ) ) { - if ( - getBlockName( state, current ) === 'core/block' || - getTemplateLock( state, current ) === 'contentOnly' - ) { + if ( isContentLockingParent( state, current ) ) { result = current; } } return result; }, - ( state ) => [ state.blocks.parents, state.blockListSettings ] + ( state ) => [ + state.blocks.parents, + state.blockListSettings, + state.editorMode, + getSectionRootClientId( state ), + ] +); + +export const isContentLockingParent = createSelector( + ( state, clientId ) => { + const sectionRootClientId = getSectionRootClientId( state ); + const sectionClientIds = getBlockOrder( state, sectionRootClientId ); + return ( + getBlockName( state, clientId ) === 'core/block' || + getTemplateLock( state, clientId ) === 'contentOnly' || + ( isNavigationMode( state ) && + sectionClientIds.includes( clientId ) ) + ); + }, + ( state ) => [ + state.blocks.parents, + state.blockListSettings, + state.editorMode, + getSectionRootClientId( state ), + ] ); /** diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index cd4569c45e580..d820f3f4a68ae 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1795,11 +1795,6 @@ export const blockListSettings = ( state = {}, action ) => { * @return {string} Updated state. */ export function editorMode( state = 'edit', action ) { - // Let inserting block in navigation mode always trigger Edit mode. - if ( action.type === 'INSERT_BLOCKS' && state === 'navigation' ) { - return 'edit'; - } - if ( action.type === 'SET_EDITOR_MODE' ) { return action.mode; } diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 30fdb76bdbe78..a966d874e77c8 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2957,7 +2957,16 @@ export const getBlockEditingMode = createRegistrySelector( } const rootClientId = getBlockRootClientId( state, clientId ); const templateLock = getTemplateLock( state, rootClientId ); - if ( templateLock === 'contentOnly' ) { + const sectionRootClientId = getSectionRootClientId( state ); + const sectionsClientIds = getBlockOrder( + state, + sectionRootClientId + ); + if ( + templateLock === 'contentOnly' || + ( editorMode === 'navigation' && + ! sectionsClientIds.includes( clientId ) ) + ) { const name = getBlockName( state, clientId ); const isContent = select( blocksStore ).__experimentalHasContentRoleAttribute( diff --git a/test/e2e/specs/widgets/customizing-widgets.spec.js b/test/e2e/specs/widgets/customizing-widgets.spec.js index 53b4da7be2d61..11185327e3eb7 100644 --- a/test/e2e/specs/widgets/customizing-widgets.spec.js +++ b/test/e2e/specs/widgets/customizing-widgets.spec.js @@ -471,7 +471,7 @@ test.describe( 'Widgets Customizer', () => { await page.keyboard.press( 'Escape' ); await expect( page.locator( - 'css=.block-editor-block-list__layout.is-navigate-mode' + 'css=.block-editor-block-list__block-selection-button' ) ).toBeVisible(); await expect( paragraphBlock ).toBeVisible(); From fd0007aa22281eccbd50da0008ffd70eca37b1a1 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 10 Sep 2024 16:10:08 +0200 Subject: [PATCH 02/22] Remove some navigation mode leftovers --- .../src/components/block-actions/index.js | 2 - .../components/block-tools/insertion-point.js | 5 +-- .../components/use-block-commands/index.js | 3 +- .../components/writing-flow/use-tab-nav.js | 40 ++----------------- packages/block-editor/src/store/selectors.js | 8 ++-- .../src/blocks/legacy-widget/edit/index.js | 10 +---- 6 files changed, 10 insertions(+), 58 deletions(-) diff --git a/packages/block-editor/src/components/block-actions/index.js b/packages/block-editor/src/components/block-actions/index.js index 5e12165c67942..6b38a05924eb9 100644 --- a/packages/block-editor/src/components/block-actions/index.js +++ b/packages/block-editor/src/components/block-actions/index.js @@ -78,7 +78,6 @@ export default function BlockActions( { insertBeforeBlock, flashBlock, setBlockMovingClientId, - setNavigationMode, selectBlock, } = useDispatch( blockEditorStore ); @@ -104,7 +103,6 @@ export default function BlockActions( { insertAfterBlock( clientIds[ clientIds.length - 1 ] ); }, onMoveTo() { - setNavigationMode( true ); selectBlock( clientIds[ 0 ] ); setBlockMovingClientId( clientIds[ 0 ] ); }, diff --git a/packages/block-editor/src/components/block-tools/insertion-point.js b/packages/block-editor/src/components/block-tools/insertion-point.js index 469f7e53908cb..891a32eaa5dc9 100644 --- a/packages/block-editor/src/components/block-tools/insertion-point.js +++ b/packages/block-editor/src/components/block-tools/insertion-point.js @@ -37,7 +37,6 @@ function InbetweenInsertionPointPopover( { rootClientId, isInserterShown, isDistractionFree, - isNavigationMode, isZoomOutMode, } = useSelect( ( select ) => { const { @@ -48,7 +47,6 @@ function InbetweenInsertionPointPopover( { getPreviousBlockClientId, getNextBlockClientId, getSettings, - isNavigationMode: _isNavigationMode, __unstableGetEditorMode, } = select( blockEditorStore ); const insertionPoint = getBlockInsertionPoint(); @@ -78,7 +76,6 @@ function InbetweenInsertionPointPopover( { getBlockListSettings( insertionPoint.rootClientId ) ?.orientation || 'vertical', rootClientId: insertionPoint.rootClientId, - isNavigationMode: _isNavigationMode(), isDistractionFree: settings.isDistractionFree, isInserterShown: insertionPoint?.__unstableWithInserter, isZoomOutMode: __unstableGetEditorMode() === 'zoom-out', @@ -144,7 +141,7 @@ function InbetweenInsertionPointPopover( { }, }; - if ( isDistractionFree && ! isNavigationMode ) { + if ( isDistractionFree ) { return null; } diff --git a/packages/block-editor/src/components/use-block-commands/index.js b/packages/block-editor/src/components/use-block-commands/index.js index 8a09999ecdff3..9bac0d54793bc 100644 --- a/packages/block-editor/src/components/use-block-commands/index.js +++ b/packages/block-editor/src/components/use-block-commands/index.js @@ -140,7 +140,7 @@ const useActionsCommands = () => { const { getBlockRootClientId, canMoveBlocks, getBlockCount } = useSelect( blockEditorStore ); - const { setBlockMovingClientId, setNavigationMode, selectBlock } = + const { setBlockMovingClientId, selectBlock } = useDispatch( blockEditorStore ); if ( ! clientIds || clientIds.length < 1 ) { @@ -159,7 +159,6 @@ const useActionsCommands = () => { name: 'move-to', label: __( 'Move to' ), callback: () => { - setNavigationMode( true ); selectBlock( clientIds[ 0 ] ); setBlockMovingClientId( clientIds[ 0 ] ); }, diff --git a/packages/block-editor/src/components/writing-flow/use-tab-nav.js b/packages/block-editor/src/components/writing-flow/use-tab-nav.js index b321d7c8d2995..3788c7021fd66 100644 --- a/packages/block-editor/src/components/writing-flow/use-tab-nav.js +++ b/packages/block-editor/src/components/writing-flow/use-tab-nav.js @@ -2,7 +2,7 @@ * WordPress dependencies */ import { focus, isFormElement } from '@wordpress/dom'; -import { TAB, ESCAPE } from '@wordpress/keycodes'; +import { TAB } from '@wordpress/keycodes'; import { useSelect, useDispatch } from '@wordpress/data'; import { useRefEffect, useMergeRefs } from '@wordpress/compose'; import { useRef } from '@wordpress/element'; @@ -21,19 +21,9 @@ export default function useTabNav() { const { hasMultiSelection, getSelectedBlockClientId, getBlockCount } = useSelect( blockEditorStore ); - const { setNavigationMode, setLastFocus } = unlock( - useDispatch( blockEditorStore ) - ); - const isNavigationMode = useSelect( - ( select ) => select( blockEditorStore ).isNavigationMode(), - [] - ); - + const { setLastFocus } = unlock( useDispatch( blockEditorStore ) ); const { getLastFocus } = unlock( useSelect( blockEditorStore ) ); - // Don't allow tabbing to this element in Navigation mode. - const focusCaptureTabIndex = ! isNavigationMode ? '0' : undefined; - // Reference that holds the a flag for enabling or disabling // capturing on the focus capture elements. const noCaptureRef = useRef(); @@ -56,8 +46,6 @@ export default function useTabNav() { .focus(); } } else { - setNavigationMode( true ); - const canvasElement = container.current.ownerDocument === event.target.ownerDocument ? container.current @@ -82,7 +70,7 @@ export default function useTabNav() { const before = (
); @@ -90,7 +78,7 @@ export default function useTabNav() { const after = (
); @@ -101,12 +89,6 @@ export default function useTabNav() { return; } - if ( event.keyCode === ESCAPE && ! hasMultiSelection() ) { - event.preventDefault(); - setNavigationMode( true ); - return; - } - // In Edit mode, Tab should focus the first tabbable element after // the content, which is normally the sidebar (with block controls) // and Shift+Tab should focus the first tabbable element before the @@ -119,20 +101,6 @@ export default function useTabNav() { const isShift = event.shiftKey; const direction = isShift ? 'findPrevious' : 'findNext'; - - if ( ! hasMultiSelection() && ! getSelectedBlockClientId() ) { - // Preserve the behaviour of entering navigation mode when - // tabbing into the content without a block selection. - // `onFocusCapture` already did this previously, but we need to - // do it again here because after clearing block selection, - // focus land on the writing flow container and pressing Tab - // will no longer send focus through the focus capture element. - if ( event.target === node ) { - setNavigationMode( true ); - } - return; - } - const nextTabbable = focus.tabbable[ direction ]( event.target ); // We want to constrain the tabbing to the block and its child blocks. diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index a966d874e77c8..3e4261521a341 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2862,11 +2862,9 @@ export function __unstableHasActiveBlockOverlayActive( state, clientId ) { '__experimentalDisableBlockOverlay', false ); - const shouldEnableIfUnselected = - editorMode === 'navigation' || - ( blockSupportDisable - ? false - : areInnerBlocksControlled( state, clientId ) ); + const shouldEnableIfUnselected = blockSupportDisable + ? false + : areInnerBlocksControlled( state, clientId ); return ( shouldEnableIfUnselected && diff --git a/packages/widgets/src/blocks/legacy-widget/edit/index.js b/packages/widgets/src/blocks/legacy-widget/edit/index.js index f371786c106d6..c5ca43211e58e 100644 --- a/packages/widgets/src/blocks/legacy-widget/edit/index.js +++ b/packages/widgets/src/blocks/legacy-widget/edit/index.js @@ -11,13 +11,11 @@ import { BlockControls, InspectorControls, BlockIcon, - store as blockEditorStore, } from '@wordpress/block-editor'; import { Flex, FlexBlock, Spinner, Placeholder } from '@wordpress/components'; import { brush as brushIcon } from '@wordpress/icons'; import { __ } from '@wordpress/i18n'; import { useState, useCallback } from '@wordpress/element'; -import { useSelect } from '@wordpress/data'; import { useEntityRecord } from '@wordpress/core-data'; /** @@ -102,11 +100,6 @@ function NotEmpty( { const { record: widgetType, hasResolved: hasResolvedWidgetType } = useEntityRecord( 'root', 'widgetType', widgetTypeId ); - const isNavigationMode = useSelect( - ( select ) => select( blockEditorStore ).isNavigationMode(), - [] - ); - const setInstance = useCallback( ( nextInstance ) => { setAttributes( { instance: nextInstance } ); }, [] ); @@ -130,8 +123,7 @@ function NotEmpty( { ); } - const mode = - idBase && ( isNavigationMode || ! isSelected ) ? 'preview' : 'edit'; + const mode = idBase && ! isSelected ? 'preview' : 'edit'; return ( <> From 61508557b94cc10ce1079461e52ce5a6263c26e1 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 10 Sep 2024 16:13:32 +0200 Subject: [PATCH 03/22] Remove memoization --- .../src/store/private-selectors.js | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 98490c815b599..9e8137c5fb65a 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -495,24 +495,23 @@ export const getContentLockingParent = createSelector( ] ); -export const isContentLockingParent = createSelector( - ( state, clientId ) => { - const sectionRootClientId = getSectionRootClientId( state ); - const sectionClientIds = getBlockOrder( state, sectionRootClientId ); - return ( - getBlockName( state, clientId ) === 'core/block' || - getTemplateLock( state, clientId ) === 'contentOnly' || - ( isNavigationMode( state ) && - sectionClientIds.includes( clientId ) ) - ); - }, - ( state ) => [ - state.blocks.parents, - state.blockListSettings, - state.editorMode, - getSectionRootClientId( state ), - ] -); +/** + * Retrieves the client ID is a content locking parent + * + * @param {Object} state Global application state. + * @param {Object} clientId Client Id of the block. + * + * @return {boolean} Whether the block is a content locking parent. + */ +export function isContentLockingParent( state, clientId ) { + const sectionRootClientId = getSectionRootClientId( state ); + const sectionClientIds = getBlockOrder( state, sectionRootClientId ); + return ( + getBlockName( state, clientId ) === 'core/block' || + getTemplateLock( state, clientId ) === 'contentOnly' || + ( isNavigationMode( state ) && sectionClientIds.includes( clientId ) ) + ); +} /** * Retrieves the client ID of the block that is content locked but is From ea2e6d999e90580e1718dd251d6edcbda34f5548 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 11 Sep 2024 10:13:08 +0200 Subject: [PATCH 04/22] Remove block moving mode --- .../data/data-core-block-editor.md | 18 +- .../src/components/block-actions/index.js | 12 +- .../src/components/block-list/block.js | 14 -- .../src/components/block-list/content.scss | 28 ---- .../block-list/use-block-props/index.js | 4 - .../block-settings-menu-controls/index.js | 15 -- .../block-settings-dropdown.js | 8 - .../block-tools/zoom-out-toolbar.js | 14 +- .../components/list-view/block-contents.js | 29 +--- .../src/components/list-view/style.scss | 14 -- .../components/use-block-commands/index.js | 57 ------- packages/block-editor/src/store/actions.js | 27 +-- packages/block-editor/src/store/reducer.js | 21 --- packages/block-editor/src/store/selectors.js | 15 +- .../editor/various/block-moving-mode.spec.js | 155 ------------------ 15 files changed, 34 insertions(+), 397 deletions(-) delete mode 100644 test/e2e/specs/editor/various/block-moving-mode.spec.js diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index c6552ef431cef..4b3ca78f74d29 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -857,15 +857,9 @@ _Returns_ ### hasBlockMovingClientId -Returns whether block moving mode is enabled. - -_Parameters_ - -- _state_ `Object`: Editor state. - -_Returns_ +> **Deprecated** -- `string`: Client Id of moving block. +Returns whether block moving mode is enabled. ### hasDraggedInnerBlock @@ -1661,11 +1655,13 @@ _Returns_ ### setBlockMovingClientId -Action that enables or disables the block moving mode. +> **Deprecated** -_Parameters_ +Set the block moving client ID. -- _hasBlockMovingClientId_ `string|null`: Enable/Disable block moving mode. +_Returns_ + +- `Object`: Action object. ### setBlockVisibility diff --git a/packages/block-editor/src/components/block-actions/index.js b/packages/block-editor/src/components/block-actions/index.js index 6b38a05924eb9..f06c8addedad5 100644 --- a/packages/block-editor/src/components/block-actions/index.js +++ b/packages/block-editor/src/components/block-actions/index.js @@ -29,7 +29,6 @@ export default function BlockActions( { getBlockRootClientId, getBlocksByClientId, getDirectInsertBlock, - canMoveBlocks, canRemoveBlocks, } = select( blockEditorStore ); @@ -44,7 +43,6 @@ export default function BlockActions( { : null; return { - canMove: canMoveBlocks( clientIds ), canRemove: canRemoveBlocks( clientIds ), canInsertBlock: canInsertDefaultBlock || !! directInsertBlock, canCopyStyles: blocks.every( ( block ) => { @@ -67,8 +65,7 @@ export default function BlockActions( { ); const { getBlocksByClientId, getBlocks } = useSelect( blockEditorStore ); - const { canMove, canRemove, canInsertBlock, canCopyStyles, canDuplicate } = - selected; + const { canRemove, canInsertBlock, canCopyStyles, canDuplicate } = selected; const { removeBlocks, @@ -77,8 +74,6 @@ export default function BlockActions( { insertAfterBlock, insertBeforeBlock, flashBlock, - setBlockMovingClientId, - selectBlock, } = useDispatch( blockEditorStore ); const notifyCopy = useNotifyCopy(); @@ -88,7 +83,6 @@ export default function BlockActions( { canCopyStyles, canDuplicate, canInsertBlock, - canMove, canRemove, onDuplicate() { return duplicateBlocks( clientIds, updateSelection ); @@ -102,10 +96,6 @@ export default function BlockActions( { onInsertAfter() { insertAfterBlock( clientIds[ clientIds.length - 1 ] ); }, - onMoveTo() { - selectBlock( clientIds[ 0 ] ); - setBlockMovingClientId( clientIds[ 0 ] ); - }, onGroup() { if ( ! clientIds.length ) { return; diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 6f1ba557eed82..3c0c340abbce1 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -571,8 +571,6 @@ function BlockListBlockProvider( props ) { __unstableSelectionHasUnmergeableBlock, isBlockBeingDragged, isDragging, - hasBlockMovingClientId, - canInsertBlockType, __unstableHasActiveBlockOverlayActive, __unstableGetEditorMode, getSelectedBlocksInitialCaretPosition, @@ -632,7 +630,6 @@ function BlockListBlockProvider( props ) { clientId, checkDeep ); - const movingClientId = hasBlockMovingClientId(); const blockEditingMode = getBlockEditingMode( clientId ); const multiple = hasBlockSupport( blockName, 'multiple', true ); @@ -692,13 +689,6 @@ function BlockListBlockProvider( props ) { ! __unstableSelectionHasUnmergeableBlock(), isDragging: isBlockBeingDragged( clientId ), hasChildSelected: isAncestorOfSelectedBlock, - isBlockMovingMode: !! movingClientId, - canInsertMovingBlock: - movingClientId && - canInsertBlockType( - getBlockName( movingClientId ), - rootClientId - ), isEditingDisabled: blockEditingMode === 'disabled', hasEditableOutline: blockEditingMode !== 'disabled' && @@ -743,8 +733,6 @@ function BlockListBlockProvider( props ) { isReusable, isDragging, hasChildSelected, - isBlockMovingMode, - canInsertMovingBlock, templateLock, isEditingDisabled, hasEditableOutline, @@ -790,8 +778,6 @@ function BlockListBlockProvider( props ) { isReusable, isDragging, hasChildSelected, - isBlockMovingMode, - canInsertMovingBlock, templateLock, isEditingDisabled, hasEditableOutline, diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index 72fd10b163c69..5eae127bd354b 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -91,34 +91,6 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b } } - // Moving blocks using keyboard (Ellipsis > Move). - & .is-block-moving-mode.block-editor-block-list__block.is-selected { - - &::after { - content: ""; - position: absolute; - z-index: 0; - pointer-events: none; - transition: - border-color 0.1s linear, - border-style 0.1s linear, - box-shadow 0.1s linear; - right: 0; - left: 0; - top: -$default-block-margin * 0.5; - border-radius: $radius-small; - border-top: 4px solid $gray-400; - bottom: auto; - box-shadow: none; - } - } - - & .is-block-moving-mode.can-insert-moving-block.block-editor-block-list__block.is-selected { - &::after { - border-color: var(--wp-admin-theme-color); - } - } - // Ensure an accurate partial text selection. // To do this, we disable text selection on the main container, then re-enable it only on the // elements that actually get selected. diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index a1b8af90c3d35..0bac8c4580dfb 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -97,8 +97,6 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { isReusable, isDragging, hasChildSelected, - isBlockMovingMode, - canInsertMovingBlock, isEditingDisabled, hasEditableOutline, isTemporarilyEditingAsBlocks, @@ -180,8 +178,6 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { 'is-reusable': isReusable, 'is-dragging': isDragging, 'has-child-selected': hasChildSelected, - 'is-block-moving-mode': isBlockMovingMode, - 'can-insert-moving-block': canInsertMovingBlock, 'is-editing-disabled': isEditingDisabled, 'has-editable-outline': hasEditableOutline, 'has-negative-margin': hasNegativeMargin, diff --git a/packages/block-editor/src/components/block-settings-menu-controls/index.js b/packages/block-editor/src/components/block-settings-menu-controls/index.js index 39063db4f52e0..4ebce4172e9b3 100644 --- a/packages/block-editor/src/components/block-settings-menu-controls/index.js +++ b/packages/block-editor/src/components/block-settings-menu-controls/index.js @@ -4,12 +4,9 @@ import { createSlotFill, MenuGroup, - MenuItem, __experimentalStyleProvider as StyleProvider, } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; -import { pipe } from '@wordpress/compose'; -import { __ } from '@wordpress/i18n'; /** * Internal dependencies @@ -96,18 +93,6 @@ const BlockSettingsMenuControlsSlot = ( { fillProps, clientIds = null } ) => { /> ) } { fills } - { fillProps?.canMove && - ! fillProps?.onlyBlock && - ! isContentOnly && ( - - { __( 'Move to' ) } - - ) } { selectedClientIds.length === 1 && ( { const { - getBlockCount, getBlockName, getBlockRootClientId, getPreviousBlockClientId, @@ -86,7 +84,6 @@ export function BlockSettingsDropdown( { return { firstParentClientId: _firstParentClientId, - onlyBlock: 1 === getBlockCount( _firstParentClientId ), parentBlockType: _firstParentClientId && ( getActiveBlockVariation( @@ -195,7 +192,6 @@ export function BlockSettingsDropdown( { canCopyStyles, canDuplicate, canInsertBlock, - canMove, canRemove, onDuplicate, onInsertAfter, @@ -203,7 +199,6 @@ export function BlockSettingsDropdown( { onRemove, onCopy, onPasteStyles, - onMoveTo, } ) => ( { const { getBlock, - hasBlockMovingClientId, getNextBlockClientId, getPreviousBlockClientId, canRemoveBlock, @@ -62,7 +56,6 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { } return { - blockMovingMode: hasBlockMovingClientId(), isBlockTemplatePart, isNextBlockTemplatePart, isPrevBlockTemplatePart, @@ -75,7 +68,6 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { ); const { - blockMovingMode, isBlockTemplatePart, isNextBlockTemplatePart, isPrevBlockTemplatePart, @@ -87,15 +79,11 @@ export default function ZoomOutToolbar( { clientId, __unstableContentRef } ) { const { removeBlock, __unstableSetEditorMode } = useDispatch( blockEditorStore ); - const classNames = clsx( 'zoom-out-toolbar', { - 'is-block-moving-mode': !! blockMovingMode, - } ); - const showBlockDraggable = canMove && ! isBlockTemplatePart; return ( { const { clientId } = block; - - const { blockMovingClientId, selectedBlockInBlockEditor } = useSelect( - ( select ) => { - const { hasBlockMovingClientId, getSelectedBlockClientId } = - select( blockEditorStore ); - return { - blockMovingClientId: hasBlockMovingClientId(), - selectedBlockInBlockEditor: getSelectedBlockClientId(), - }; - }, - [] - ); - const { AdditionalBlockContent, insertedBlock, setInsertedBlock } = useListViewContext(); - const isBlockMoveTarget = - blockMovingClientId && selectedBlockInBlockEditor === clientId; - - const className = clsx( 'block-editor-list-view-block-contents', { - 'is-dropping-before': isBlockMoveTarget, - } ); - // Only include all selected blocks if the currently clicked on block // is one of the selected blocks. This ensures that if a user attempts // to drag a block that isn't part of the selection, they're still able @@ -82,7 +55,7 @@ const ListViewBlockContents = forwardRef( { ( { draggable, onDragStart, onDragEnd } ) => ( { return { isLoading: false, commands }; }; -const useActionsCommands = () => { - const { clientIds } = useSelect( ( select ) => { - const { getSelectedBlockClientIds } = select( blockEditorStore ); - const selectedBlockClientIds = getSelectedBlockClientIds(); - - return { - clientIds: selectedBlockClientIds, - }; - }, [] ); - - const { getBlockRootClientId, canMoveBlocks, getBlockCount } = - useSelect( blockEditorStore ); - - const { setBlockMovingClientId, selectBlock } = - useDispatch( blockEditorStore ); - - if ( ! clientIds || clientIds.length < 1 ) { - return { isLoading: false, commands: [] }; - } - - const rootClientId = getBlockRootClientId( clientIds[ 0 ] ); - - const canMove = - canMoveBlocks( clientIds ) && getBlockCount( rootClientId ) !== 1; - - const commands = []; - - if ( canMove ) { - commands.push( { - name: 'move-to', - label: __( 'Move to' ), - callback: () => { - selectBlock( clientIds[ 0 ] ); - setBlockMovingClientId( clientIds[ 0 ] ); - }, - icon: move, - } ); - } - - return { - isLoading: false, - commands: commands.map( ( command ) => ( { - ...command, - name: 'core/block-editor/action-' + command.name, - callback: ( { close } ) => { - command.callback(); - close(); - }, - } ) ), - }; -}; - const useQuickActionsCommands = () => { const { clientIds, isUngroupable, isGroupable } = useSelect( ( select ) => { const { @@ -343,10 +290,6 @@ export const useBlockCommands = () => { name: 'core/block-editor/blockTransforms', hook: useTransformCommands, } ); - useCommandLoader( { - name: 'core/block-editor/blockActions', - hook: useActionsCommands, - } ); useCommandLoader( { name: 'core/block-editor/blockQuickActions', hook: useQuickActionsCommands, diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js index e91f997ca6783..ee11838395ec5 100644 --- a/packages/block-editor/src/store/actions.js +++ b/packages/block-editor/src/store/actions.js @@ -1728,23 +1728,24 @@ export const __unstableSetEditorMode = }; /** - * Action that enables or disables the block moving mode. + * Set the block moving client ID. * - * @param {string|null} hasBlockMovingClientId Enable/Disable block moving mode. + * @deprecated + * + * @return {Object} Action object. */ -export const setBlockMovingClientId = - ( hasBlockMovingClientId = null ) => - ( { dispatch } ) => { - dispatch( { type: 'SET_BLOCK_MOVING_MODE', hasBlockMovingClientId } ); - - if ( hasBlockMovingClientId ) { - speak( - __( - 'Use the Tab key and Arrow keys to choose new block location. Use Left and Right Arrow keys to move between nesting levels. Once location is selected press Enter or Space to move the block.' - ) - ); +export function setBlockMovingClientId() { + deprecated( + 'wp.data.dispatch( "core/block-editor" ).setBlockMovingClientId', + { + since: '6.7', + hint: 'Block moving mode feature has been removed', } + ); + return { + type: 'DO_NOTHING', }; +} /** * Action that duplicates a list of blocks. diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js index d820f3f4a68ae..3a99d18ef17ee 100644 --- a/packages/block-editor/src/store/reducer.js +++ b/packages/block-editor/src/store/reducer.js @@ -1802,26 +1802,6 @@ export function editorMode( state = 'edit', action ) { return state; } -/** - * Reducer returning whether the block moving mode is enabled or not. - * - * @param {string|null} state Current state. - * @param {Object} action Dispatched action. - * - * @return {string|null} Updated state. - */ -export function hasBlockMovingClientId( state = null, action ) { - if ( action.type === 'SET_BLOCK_MOVING_MODE' ) { - return action.hasBlockMovingClientId; - } - - if ( action.type === 'SET_EDITOR_MODE' ) { - return null; - } - - return state; -} - /** * Reducer return an updated state representing the most recent block attribute * update. The state is structured as an object where the keys represent the @@ -2099,7 +2079,6 @@ const combinedReducers = combineReducers( { lastBlockAttributesChange, lastFocus, editorMode, - hasBlockMovingClientId, expandedBlock, highlightedBlock, lastBlockInserted, diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 3e4261521a341..87ea0492962fc 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2674,12 +2674,17 @@ export function __unstableGetEditorMode( state ) { /** * Returns whether block moving mode is enabled. * - * @param {Object} state Editor state. - * - * @return {string} Client Id of moving block. + * @deprecated */ -export function hasBlockMovingClientId( state ) { - return state.hasBlockMovingClientId; +export function hasBlockMovingClientId() { + deprecated( + 'wp.data.select( "core/block-editor" ).hasBlockMovingClientId', + { + since: '6.7', + hint: 'Block moving mode feature has been removed', + } + ); + return false; } /** diff --git a/test/e2e/specs/editor/various/block-moving-mode.spec.js b/test/e2e/specs/editor/various/block-moving-mode.spec.js deleted file mode 100644 index 5b8ef6bdcd051..0000000000000 --- a/test/e2e/specs/editor/various/block-moving-mode.spec.js +++ /dev/null @@ -1,155 +0,0 @@ -/** - * WordPress dependencies - */ -const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); - -test.describe( 'Block moving mode', () => { - test.beforeEach( async ( { admin } ) => { - await admin.createNewPost(); - } ); - - test.afterEach( async ( { requestUtils } ) => { - await requestUtils.deleteAllPosts(); - } ); - - test( 'can move block', async ( { editor, page } ) => { - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { content: 'First Paragraph' }, - } ); - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { content: 'Second Paragraph' }, - } ); - - // Move the second block in front of the first block. - await editor.showBlockToolbar(); - await page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Options' } ) - .click(); - await page.getByRole( 'menuitem', { name: 'Move to' } ).click(); - await page.keyboard.press( 'ArrowUp' ); - await page.keyboard.press( 'Enter' ); - - await expect.poll( editor.getBlocks ).toMatchObject( [ - { - name: 'core/paragraph', - attributes: { content: 'Second Paragraph' }, - }, - { - name: 'core/paragraph', - attributes: { content: 'First Paragraph' }, - }, - ] ); - } ); - - test( 'can move block in the nested block', async ( { editor, page } ) => { - // Create two group blocks with some blocks. - await editor.insertBlock( { name: 'core/group' } ); - await editor.canvas - .locator( - 'role=button[name="Group: Gather blocks in a container."i]' - ) - .click(); - await page.keyboard.press( 'ArrowDown' ); - await page.keyboard.press( 'Enter' ); - await page.getByRole( 'option', { name: 'Paragraph' } ).click(); - await page.keyboard.type( 'First Paragraph' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( 'Second Paragraph' ); - - await editor.insertBlock( { name: 'core/group' } ); - await editor.canvas - .locator( - 'role=button[name="Group: Gather blocks in a container."i]' - ) - .click(); - await page.keyboard.press( 'ArrowDown' ); - await page.keyboard.press( 'Enter' ); - await page.getByRole( 'option', { name: 'Paragraph' } ).click(); - await page.keyboard.type( 'Third Paragraph' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( 'Fourth Paragraph' ); - - // Move a paragraph block in the first group block into the second group block. - const paragraphBlock = editor.canvas.locator( - 'text="First Paragraph"' - ); - await paragraphBlock.focus(); - await editor.showBlockToolbar(); - await page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Options' } ) - .click(); - await page.getByRole( 'menuitem', { name: 'Move to' } ).click(); - await page.keyboard.press( 'ArrowLeft' ); // Select the first group block. - await page.keyboard.press( 'ArrowDown' ); // Select the second group block. - await page.keyboard.press( 'ArrowRight' ); // Enter the second group block. - await page.keyboard.press( 'ArrowDown' ); // Move down in the second group block. - await page.keyboard.press( 'Enter' ); - - await expect.poll( editor.getBlocks ).toMatchObject( [ - { - name: 'core/group', - innerBlocks: [ - { - name: 'core/paragraph', - attributes: { content: 'Second Paragraph' }, - }, - ], - }, - { - name: 'core/group', - innerBlocks: [ - { - name: 'core/paragraph', - attributes: { content: 'Third Paragraph' }, - }, - { - name: 'core/paragraph', - attributes: { content: 'First Paragraph' }, - }, - { - name: 'core/paragraph', - attributes: { content: 'Fourth Paragraph' }, - }, - ], - }, - ] ); - } ); - - test( 'can not move inside its own block', async ( { editor, page } ) => { - // Create a paragraph block and a group block. - await editor.insertBlock( { - name: 'core/paragraph', - attributes: { content: 'First Paragraph' }, - } ); - await editor.insertBlock( { name: 'core/group' } ); - await editor.canvas - .locator( - 'role=button[name="Group: Gather blocks in a container."i]' - ) - .click(); - await page.keyboard.press( 'ArrowDown' ); - await page.keyboard.press( 'Enter' ); - await page.getByRole( 'option', { name: 'Paragraph' } ).click(); - await page.keyboard.type( 'Second Paragraph' ); - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( 'Third Paragraph' ); - - // Trying to move the group block into its own. - const groupBlock = editor.canvas.locator( - 'role=document[name="Block: Group"i]' - ); - await groupBlock.focus(); - await editor.showBlockToolbar(); - await page - .getByRole( 'toolbar', { name: 'Block tools' } ) - .getByRole( 'button', { name: 'Options' } ) - .click(); - await page.getByRole( 'menuitem', { name: 'Move to' } ).click(); - await page.keyboard.press( 'ArrowRight' ); - await expect( groupBlock ).toHaveClass( /is-selected/ ); - } ); -} ); From e7d306a35cbaf18da9b8b205c9570f86da4833d6 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 11 Sep 2024 10:32:13 +0200 Subject: [PATCH 05/22] Fix unit tests --- .../src/store/test/private-selectors.js | 34 +++++++++++++ .../block-editor/src/store/test/selectors.js | 48 +++++++++++++++++-- 2 files changed, 77 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/store/test/private-selectors.js b/packages/block-editor/src/store/test/private-selectors.js index 45432b750bb9e..5f427e79cf699 100644 --- a/packages/block-editor/src/store/test/private-selectors.js +++ b/packages/block-editor/src/store/test/private-selectors.js @@ -394,6 +394,10 @@ describe( 'private selectors', () => { parents: new Map( [ [ '6cf70164-9097-4460-bcbf-200560546988', '' ], ] ), + order: new Map( [ + [ '6cf70164-9097-4460-bcbf-200560546988', [] ], + [ '', [ '6cf70164-9097-4460-bcbf-200560546988' ] ], + ] ), }, blockEditingModes: new Map(), }; @@ -424,6 +428,21 @@ describe( 'private selectors', () => { 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', ], ] ), + + order: new Map( [ + [ + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', + [ + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', + ], + ], + [ + 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', + [ '4c2b7140-fffd-44b4-b2a7-820c670a6514' ], + ], + [ '', [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337' ] ], + ] ), }, blockEditingModes: new Map( [ [ '', 'disabled' ], @@ -461,6 +480,21 @@ describe( 'private selectors', () => { 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', ], ] ), + order: new Map( [ + [ + 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337', + [ '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f' ], + ], + [ + '9b9c5c3f-2e46-4f02-9e14-9fe9515b958f', + [ 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c' ], + ], + [ + 'e178812d-ce5e-48c7-a945-8ae4ffcbbb7c', + [ '4c2b7140-fffd-44b4-b2a7-820c670a6514' ], + ], + [ '', [ 'ef45d5fd-5234-4fd5-ac4f-c3736c7f9337' ] ], + ] ), }, blockEditingModes: new Map( [ [ '', 'disabled' ], diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index 85006621c4701..0fc61f0c75f5c 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -2748,6 +2748,7 @@ describe( 'selectors', () => { byClientId: new Map(), attributes: new Map(), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: {}, @@ -2772,6 +2773,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: {}, @@ -2796,6 +2798,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { block1: {}, @@ -2822,6 +2825,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { block1: {}, @@ -2848,6 +2852,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { block1: { @@ -2876,6 +2881,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { block1: { @@ -2904,6 +2910,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: {}, @@ -2932,6 +2939,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { block1: { @@ -2960,6 +2968,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: {}, @@ -2976,6 +2985,7 @@ describe( 'selectors', () => { byClientId: new Map(), attributes: new Map(), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: {}, @@ -3006,6 +3016,10 @@ describe( 'selectors', () => { block2: 'block1', } ) ), + order: new Map( [ + [ '', [ 'block1' ] ], + [ 'block1', [ 'block2' ] ], + ] ), }, blockListSettings: { block1: {}, @@ -3046,6 +3060,11 @@ describe( 'selectors', () => { block3: 'block2', } ) ), + order: new Map( [ + [ '', [ 'block1' ] ], + [ 'block1', [ 'block2' ] ], + [ 'block2', [ 'block3' ] ], + ] ), }, blockListSettings: { block1: {}, @@ -3086,6 +3105,11 @@ describe( 'selectors', () => { block3: 'block2', } ) ), + order: new Map( [ + [ '', [ 'block1' ] ], + [ 'block1', [ 'block2' ] ], + [ 'block2', [ 'block3' ] ], + ] ), }, blockListSettings: { block1: {}, @@ -3126,6 +3150,11 @@ describe( 'selectors', () => { block3: 'block2', } ) ), + order: new Map( [ + [ '', [ 'block1' ] ], + [ 'block1', [ 'block2' ] ], + [ 'block2', [ 'block3' ] ], + ] ), }, blockListSettings: { block1: {}, @@ -3159,11 +3188,14 @@ describe( 'selectors', () => { block2: {}, } ) ), - parents: new Map( - Object.entries( { - block2: 'block1', - } ) - ), + order: new Map( [ + [ '', [ 'block1' ] ], + [ 'block1', [ 'block2' ] ], + ] ), + parents: new Map( [ + [ 'block2', 'block1' ], + [ 'block1', '' ], + ] ), }, blockListSettings: { block1: {}, @@ -3203,6 +3235,10 @@ describe( 'selectors', () => { block2: 'block1', } ) ), + order: new Map( [ + [ '', [ 'block1' ] ], + [ 'block1', [ 'block2' ] ], + ] ), }, blockListSettings: { block1: {}, @@ -3240,6 +3276,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { 1: { @@ -3273,6 +3310,7 @@ describe( 'selectors', () => { } ) ), parents: new Map(), + order: new Map(), }, blockListSettings: { 1: { From 8a954afedfaf20382d789f176b7bbfc836213b65 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 11 Sep 2024 11:37:46 +0200 Subject: [PATCH 06/22] Fix e2e tests --- .../various/keyboard-navigable-blocks.spec.js | 126 ++---------------- .../various/shortcut-focus-toolbar.spec.js | 26 ---- .../specs/editor/various/writing-flow.spec.js | 78 +---------- test/e2e/specs/site-editor/navigation.spec.js | 13 -- .../specs/widgets/customizing-widgets.spec.js | 10 -- 5 files changed, 15 insertions(+), 238 deletions(-) diff --git a/test/e2e/specs/editor/various/keyboard-navigable-blocks.spec.js b/test/e2e/specs/editor/various/keyboard-navigable-blocks.spec.js index 6a7125d04f7a6..e1ca121040b97 100644 --- a/test/e2e/specs/editor/various/keyboard-navigable-blocks.spec.js +++ b/test/e2e/specs/editor/various/keyboard-navigable-blocks.spec.js @@ -17,108 +17,26 @@ test.describe( 'Order of block keyboard navigation', () => { await editor.openDocumentSettingsSidebar(); } ); - test( 'permits tabbing through paragraph blocks in the expected order', async ( { + test( 'permits tabbing through the block toolbar of the paragraph block', async ( { editor, KeyboardNavigableBlocks, page, + pageUtils, } ) => { - const paragraphBlocks = [ 'Paragraph 0', 'Paragraph 1', 'Paragraph 2' ]; - - // Create 3 paragraphs blocks with some content. - for ( const paragraphBlock of paragraphBlocks ) { + // Insert three paragraph blocks. + for ( let i = 0; i < 3; i++ ) { await editor.insertBlock( { name: 'core/paragraph' } ); - await page.keyboard.type( paragraphBlock ); + await page.keyboard.type( `Paragraph ${ i + 1 }` ); } - - // Select the middle block. + // Select the middle paragraph block. await page.keyboard.press( 'ArrowUp' ); await editor.showBlockToolbar(); - await KeyboardNavigableBlocks.navigateToContentEditorTop(); - await KeyboardNavigableBlocks.tabThroughParagraphBlock( 'Paragraph 1' ); - - // Repeat the same steps to ensure that there is no change introduced in how the focus is handled. - // This prevents the previous regression explained in: https://github.com/WordPress/gutenberg/issues/11773. - await KeyboardNavigableBlocks.navigateToContentEditorTop(); - await KeyboardNavigableBlocks.tabThroughParagraphBlock( 'Paragraph 1' ); - } ); - - test( 'allows tabbing in navigation mode if no block is selected', async ( { - editor, - KeyboardNavigableBlocks, - page, - } ) => { - const paragraphBlocks = [ '0', '1' ]; - - // Create 2 paragraphs blocks with some content. - for ( const paragraphBlock of paragraphBlocks ) { - await editor.insertBlock( { name: 'core/paragraph' } ); - await page.keyboard.type( paragraphBlock ); - } - - // Clear the selected block. - const paragraph = editor.canvas - .locator( '[data-type="core/paragraph"]' ) - .getByText( '1' ); - const box = await paragraph.boundingBox(); - await page.mouse.click( box.x - 1, box.y ); - - await page.keyboard.press( 'Tab' ); - await KeyboardNavigableBlocks.expectLabelToHaveFocus( 'Add title' ); - - await page.keyboard.press( 'Tab' ); - await KeyboardNavigableBlocks.expectLabelToHaveFocus( - 'Paragraph Block. Row 1. 0' - ); - - await page.keyboard.press( 'Tab' ); - await KeyboardNavigableBlocks.expectLabelToHaveFocus( - 'Paragraph Block. Row 2. 1' - ); - - await page.keyboard.press( 'Tab' ); - await KeyboardNavigableBlocks.expectLabelToHaveFocus( 'Post' ); - } ); - - test( 'allows tabbing in navigation mode if no block is selected (reverse)', async ( { - editor, - KeyboardNavigableBlocks, - page, - pageUtils, - } ) => { - const paragraphBlocks = [ '0', '1' ]; - - // Create 2 paragraphs blocks with some content. - for ( const paragraphBlock of paragraphBlocks ) { - await editor.insertBlock( { name: 'core/paragraph' } ); - await page.keyboard.type( paragraphBlock ); - } - - // Clear the selected block. - const paragraph = editor.canvas - .locator( '[data-type="core/paragraph"]' ) - .getByText( '1' ); - const box = await paragraph.boundingBox(); - await page.mouse.click( box.x - 1, box.y ); - - // Put focus behind the block list. - await page.evaluate( () => { - document - .querySelector( '.interface-interface-skeleton__sidebar' ) - .focus(); - } ); - - await pageUtils.pressKeys( 'shift+Tab' ); - await KeyboardNavigableBlocks.expectLabelToHaveFocus( - 'Paragraph Block. Row 2. 1' - ); - await pageUtils.pressKeys( 'shift+Tab' ); + await KeyboardNavigableBlocks.navigateThroughBlockToolbar(); + await page.keyboard.press( 'Tab' ); await KeyboardNavigableBlocks.expectLabelToHaveFocus( - 'Paragraph Block. Row 1. 0' + 'Block: Paragraph' ); - - await pageUtils.pressKeys( 'shift+Tab' ); - await KeyboardNavigableBlocks.expectLabelToHaveFocus( 'Add title' ); } ); test( 'should navigate correctly with multi selection', async ( { @@ -208,31 +126,7 @@ class KeyboardNavigableBlocks { expect( ariaLabel ).toBe( label ); } - async navigateToContentEditorTop() { - // Use 'Ctrl+`' to return to the top of the editor. - await this.pageUtils.pressKeys( 'ctrl+`', { times: 5 } ); - } - - async tabThroughParagraphBlock( paragraphText ) { - await this.tabThroughBlockToolbar(); - - await this.page.keyboard.press( 'Tab' ); - await this.expectLabelToHaveFocus( 'Block: Paragraph' ); - - const activeElement = this.editor.canvas.locator( ':focus' ); - - await expect( activeElement ).toHaveText( paragraphText ); - - await this.page.keyboard.press( 'Tab' ); - await this.expectLabelToHaveFocus( 'Block' ); - - // Need to shift+tab here to end back in the block. If not, we'll be in the next region and it will only require 4 region jumps instead of 5. - await this.pageUtils.pressKeys( 'shift+Tab' ); - await this.expectLabelToHaveFocus( 'Block: Paragraph' ); - } - - async tabThroughBlockToolbar() { - await this.page.keyboard.press( 'Tab' ); + async navigateThroughBlockToolbar() { await this.expectLabelToHaveFocus( 'Paragraph' ); await this.page.keyboard.press( 'ArrowRight' ); diff --git a/test/e2e/specs/editor/various/shortcut-focus-toolbar.spec.js b/test/e2e/specs/editor/various/shortcut-focus-toolbar.spec.js index a8e49f7a6b84d..cfaf4e0be9188 100644 --- a/test/e2e/specs/editor/various/shortcut-focus-toolbar.spec.js +++ b/test/e2e/specs/editor/various/shortcut-focus-toolbar.spec.js @@ -50,32 +50,6 @@ test.describe( 'Focus toolbar shortcut (alt + F10)', () => { await expect( toolbarUtils.documentToolbarTooltip ).toBeHidden(); } ); - test( 'Focuses correct toolbar in default view options in select mode', async ( { - editor, - page, - toolbarUtils, - } ) => { - // Test: Focus the document toolbar from title - await toolbarUtils.useSelectMode(); - await toolbarUtils.moveToToolbarShortcut(); - await expect( toolbarUtils.documentToolbarButton ).toBeFocused(); - - // Test: Focus the top level toolbar from empty block - await editor.insertBlock( { name: 'core/paragraph' } ); - await toolbarUtils.useSelectMode(); - await toolbarUtils.moveToToolbarShortcut(); - await expect( toolbarUtils.documentToolbarButton ).toBeFocused(); - - // Test: Focus the top level toolbar from paragraph block - await editor.insertBlock( { name: 'core/paragraph' } ); - await page.keyboard.type( - 'Focus top level toolbar from paragraph block in select mode.' - ); - await toolbarUtils.useSelectMode(); - await toolbarUtils.moveToToolbarShortcut(); - await expect( toolbarUtils.documentToolbarButton ).toBeFocused(); - } ); - test.describe( 'In Top Toolbar option:', () => { test.beforeEach( async ( { editor } ) => { // Ensure the fixed toolbar option is on diff --git a/test/e2e/specs/editor/various/writing-flow.spec.js b/test/e2e/specs/editor/various/writing-flow.spec.js index bd1552ad4cb66..4077d6dcc5820 100644 --- a/test/e2e/specs/editor/various/writing-flow.spec.js +++ b/test/e2e/specs/editor/various/writing-flow.spec.js @@ -106,48 +106,6 @@ test.describe( 'Writing Flow (@firefox, @webkit)', () => { ] ); } ); - test( 'Should navigate between inner and root blocks in navigation mode', async ( { - page, - writingFlowUtils, - } ) => { - await writingFlowUtils.addDemoContent(); - - // Switch to navigation mode. - await page.keyboard.press( 'Escape' ); - // Arrow up to Columns block. - await page.keyboard.press( 'ArrowUp' ); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/columns' ); - // Arrow right into Column block. - await page.keyboard.press( 'ArrowRight' ); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/column' ); - // Arrow down to reach second Column block. - await page.keyboard.press( 'ArrowDown' ); - // Arrow right again into Paragraph block. - await page.keyboard.press( 'ArrowRight' ); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/paragraph' ); - // Arrow left back to Column block. - await page.keyboard.press( 'ArrowLeft' ); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/column' ); - // Arrow left back to Columns block. - await page.keyboard.press( 'ArrowLeft' ); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/columns' ); - // Arrow up to first paragraph. - await page.keyboard.press( 'ArrowUp' ); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/paragraph' ); - } ); - test( 'should navigate around inline boundaries', async ( { editor, page, @@ -958,32 +916,6 @@ test.describe( 'Writing Flow (@firefox, @webkit)', () => { ` ); } ); - test( 'escape should set select mode and then focus the canvas', async ( { - page, - writingFlowUtils, - } ) => { - await page.keyboard.press( 'Enter' ); - await page.keyboard.type( 'Random Paragraph' ); - - // First escape enters navigation mode. - await page.keyboard.press( 'Escape' ); - const navigationButton = page.getByLabel( - 'Paragraph Block. Row 1. Random Paragraph' - ); - await expect( navigationButton ).toBeVisible(); - await expect - .poll( writingFlowUtils.getActiveBlockName ) - .toBe( 'core/paragraph' ); - - // Second escape should send focus to the canvas - await page.keyboard.press( 'Escape' ); - // The navigation button should be hidden. - await expect( navigationButton ).toBeHidden(); - await expect( - page.getByRole( 'region', { name: 'Editor content' } ) - ).toBeFocused(); - } ); - // Checks for regressions of https://github.com/WordPress/gutenberg/issues/40091. test( 'does not deselect the block when selecting text outside the editor canvas', async ( { editor, @@ -1222,11 +1154,11 @@ class WritingFlowUtils { 'role=listbox[name="Blocks"i] >> role=option[name="Paragraph"i]' ); await this.page.keyboard.type( '2nd col' ); // If this text is too long, it may wrap to a new line and cause test failure. That's why we're using "2nd" instead of "Second" here. - - await this.page.keyboard.press( 'Escape' ); // Enter navigation mode. - await this.page.keyboard.press( 'ArrowLeft' ); // Move to the column block. - await this.page.keyboard.press( 'ArrowLeft' ); // Move to the columns block. - await this.page.keyboard.press( 'Enter' ); // Enter edit mode with the columns block selected. + await this.editor.showBlockToolbar(); + await this.page.keyboard.press( 'Shift+Tab' ); // Move to toolbar to select parent + await this.page.keyboard.press( 'Enter' ); // Selects the column block. + await this.page.keyboard.press( 'Shift+Tab' ); // Move to toolbar to select parent + await this.page.keyboard.press( 'Enter' ); // Selects the columns block. await this.page.keyboard.press( 'Enter' ); // Creates a paragraph after the columns block. await this.page.keyboard.type( 'Second paragraph' ); } diff --git a/test/e2e/specs/site-editor/navigation.spec.js b/test/e2e/specs/site-editor/navigation.spec.js index 4db860b703892..1b92ef2e850e6 100644 --- a/test/e2e/specs/site-editor/navigation.spec.js +++ b/test/e2e/specs/site-editor/navigation.spec.js @@ -83,19 +83,6 @@ test.describe( 'Site editor navigation', () => { // The button role should have been removed from the iframe. await expect( editorCanvasButton ).toBeHidden(); - // Test to make sure a Tab keypress works as expected. - // As of this writing, we are in select mode and a tab - // keypress will reveal the header template select mode - // button. This test is not documenting that we _want_ - // that action, but checking that we are within the site - // editor and keypresses work as intened. - await pageUtils.pressKeys( 'Tab' ); - await expect( - page.getByRole( 'button', { - name: 'Template Part Block. Row 1. header', - } ) - ).toBeFocused(); - // Test: We can go back to the main navigation from the editor frame // Move to the document toolbar await pageUtils.pressKeys( 'alt+F10' ); diff --git a/test/e2e/specs/widgets/customizing-widgets.spec.js b/test/e2e/specs/widgets/customizing-widgets.spec.js index 11185327e3eb7..38e9d3ee2c58a 100644 --- a/test/e2e/specs/widgets/customizing-widgets.spec.js +++ b/test/e2e/specs/widgets/customizing-widgets.spec.js @@ -465,16 +465,6 @@ test.describe( 'Widgets Customizer', () => { await expect( paragraphBlock ).toBeVisible(); await paragraphBlock.focus(); - - // Expect pressing the Escape key to enter navigation mode, - // but not close the editor. - await page.keyboard.press( 'Escape' ); - await expect( - page.locator( - 'css=.block-editor-block-list__block-selection-button' - ) - ).toBeVisible(); - await expect( paragraphBlock ).toBeVisible(); } ); test( 'should move (inner) blocks to another sidebar', async ( { From 596aff7af45bddeea9ac1ee5e3b22160d5b7d608 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 11 Sep 2024 16:35:46 +0200 Subject: [PATCH 07/22] Change wording in the tool selector --- .../src/components/tool-selector/index.js | 20 +++++++++++++------ .../src/components/tool-selector/style.scss | 5 +++++ .../src/menu-items-choice/style.scss | 2 ++ 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/tool-selector/index.js b/packages/block-editor/src/components/tool-selector/index.js index 4ec777a911cc7..bf55c78caf489 100644 --- a/packages/block-editor/src/components/tool-selector/index.js +++ b/packages/block-editor/src/components/tool-selector/index.js @@ -45,7 +45,7 @@ function ToolSelector( props, ref ) { __next40pxDefaultSize={ false } { ...props } ref={ ref } - icon={ mode === 'navigation' ? selectIcon : editIcon } + icon={ mode === 'navigation' ? editIcon : selectIcon } aria-expanded={ isOpen } aria-haspopup="true" onClick={ onToggle } @@ -56,7 +56,11 @@ function ToolSelector( props, ref ) { popoverProps={ { placement: 'bottom-start' } } renderContent={ () => ( <> - + - - { __( 'Edit' ) } + { selectIcon } + { __( 'Design' ) } ), + info: __( + 'Full control over layout and styling.' + ), }, { value: 'navigation', label: ( <> - { selectIcon } - { __( 'Select' ) } + + { __( 'Edit' ) } ), + info: __( 'Focus on content.' ), }, ] } /> diff --git a/packages/block-editor/src/components/tool-selector/style.scss b/packages/block-editor/src/components/tool-selector/style.scss index 03774fe0f6b9d..07ca91d346d90 100644 --- a/packages/block-editor/src/components/tool-selector/style.scss +++ b/packages/block-editor/src/components/tool-selector/style.scss @@ -8,3 +8,8 @@ color: $gray-700; min-width: 280px; } + +.block-editor-tool-selector__menu .components-menu-item__info { + margin-left: $grid-unit-30 + $grid-unit-15; // icon size + margin + text-align: left; +} diff --git a/packages/components/src/menu-items-choice/style.scss b/packages/components/src/menu-items-choice/style.scss index 5de8363be0d6e..383eb4066ba86 100644 --- a/packages/components/src/menu-items-choice/style.scss +++ b/packages/components/src/menu-items-choice/style.scss @@ -1,5 +1,7 @@ .components-menu-items-choice, .components-menu-items-choice.components-button { + height: auto; + svg { margin-right: $grid-unit-15; } From a80d1f3807472dce72bd5a4795635e8d4d3bafce Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 17 Sep 2024 09:27:15 +0100 Subject: [PATCH 08/22] Allow selection of sections Also helps give List View some structure --- 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 87ea0492962fc..9ed10e333bd1b 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2967,9 +2967,14 @@ export const getBlockEditingMode = createRegistrySelector( ); if ( templateLock === 'contentOnly' || - ( editorMode === 'navigation' && - ! sectionsClientIds.includes( clientId ) ) + editorMode === 'navigation' ) { + // Sections should always be contentOnly in navigation mode. + // This will also cause them to display in List View providing + // a structure. + if ( sectionsClientIds.includes( clientId ) ) { + return 'contentOnly'; + } const name = getBlockName( state, clientId ); const isContent = select( blocksStore ).__experimentalHasContentRoleAttribute( From ac9f4160706c5d2daf0214a925174b2a32371a46 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 17 Sep 2024 12:03:05 +0100 Subject: [PATCH 09/22] Avoid unnecessary subscriptions --- .../src/components/block-inspector/index.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index 4494941077429..5b6cf0db4a5a5 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -229,18 +229,22 @@ const BlockInspectorSingleBlock = ( { const borderPanelLabel = useBorderPanelLabel( { blockName } ); const contentClientIds = useSelect( ( select ) => { + // Avoid unnecessary subscription. + if ( ! isContentLockingParent ) { + return; + } + const { getClientIdsOfDescendants, getBlockName, getBlockEditingMode, } = select( blockEditorStore ); - return isContentLockingParent - ? getClientIdsOfDescendants( clientId ).filter( - ( current ) => - getBlockName( current ) !== 'core/list-item' && - getBlockEditingMode( current ) === 'contentOnly' - ) - : undefined; + + return getClientIdsOfDescendants( clientId ).filter( + ( current ) => + getBlockName( current ) !== 'core/list-item' && + getBlockEditingMode( current ) === 'contentOnly' + ); }, [ isContentLockingParent, clientId ] ); From f3d104df4c064e8fb3e3f3b5dc1cc31a39fe362d Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 17 Sep 2024 17:37:37 +0100 Subject: [PATCH 10/22] Untangle section blocks and content only parents --- .../src/components/block-inspector/index.js | 27 +++++++--------- .../src/store/private-selectors.js | 31 +++++++++++++++++-- .../content-only-settings-menu.js | 2 +- 3 files changed, 42 insertions(+), 18 deletions(-) diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index 5b6cf0db4a5a5..475d4f6a4b8c2 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -46,18 +46,18 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { selectedBlockName, selectedBlockClientId, blockType, - isContentLockingParent, + isSectionBlock, } = useSelect( ( select ) => { const { getSelectedBlockClientId, getSelectedBlockCount, getBlockName, - getContentLockingParent, - isContentLockingParent: _isContentLockingParent, + getParentSectionBlock, + isSectionBlock: _isSectionBlock, } = unlock( select( blockEditorStore ) ); const _selectedBlockClientId = getSelectedBlockClientId(); const renderedBlockClientId = - getContentLockingParent( _selectedBlockClientId ) || + getParentSectionBlock( _selectedBlockClientId ) || getSelectedBlockClientId(); const _selectedBlockName = renderedBlockClientId && getBlockName( renderedBlockClientId ); @@ -69,9 +69,7 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { selectedBlockClientId: renderedBlockClientId, selectedBlockName: _selectedBlockName, blockType: _blockType, - isContentLockingParent: _isContentLockingParent( - renderedBlockClientId - ), + isSectionBlock: _isSectionBlock( renderedBlockClientId ), }; }, [] ); @@ -91,7 +89,7 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { blockName: selectedBlockName, } ); - if ( count > 1 && ! isContentLockingParent ) { + if ( count > 1 && ! isSectionBlock ) { return (
@@ -167,7 +165,7 @@ const BlockInspector = ( { showNoBlockSelectedMessage = true } ) => { ); @@ -212,10 +210,10 @@ const AnimatedContainer = ( { const BlockInspectorSingleBlock = ( { clientId, blockName, - isContentLockingParent, + isSectionBlock, } ) => { const availableTabs = useInspectorControlsTabs( blockName ); - const showTabs = ! isContentLockingParent && availableTabs?.length > 1; + const showTabs = ! isSectionBlock && availableTabs?.length > 1; const hasBlockStyles = useSelect( ( select ) => { @@ -230,7 +228,7 @@ const BlockInspectorSingleBlock = ( { const contentClientIds = useSelect( ( select ) => { // Avoid unnecessary subscription. - if ( ! isContentLockingParent ) { + if ( ! isSectionBlock ) { return; } @@ -239,14 +237,13 @@ const BlockInspectorSingleBlock = ( { getBlockName, getBlockEditingMode, } = select( blockEditorStore ); - return getClientIdsOfDescendants( clientId ).filter( ( current ) => getBlockName( current ) !== 'core/list-item' && getBlockEditingMode( current ) === 'contentOnly' ); }, - [ isContentLockingParent, clientId ] + [ isSectionBlock, clientId ] ); return ( @@ -279,7 +276,7 @@ const BlockInspectorSingleBlock = ( { ) } - { ! isContentLockingParent && ( + { ! isSectionBlock && ( <> diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 9e8137c5fb65a..6c3dd752bf79b 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -481,7 +481,34 @@ export const getContentLockingParent = createSelector( let current = clientId; let result; while ( ( current = state.blocks.parents.get( current ) ) ) { - if ( isContentLockingParent( state, current ) ) { + if ( getTemplateLock( state, current ) === 'contentOnly' ) { + result = current; + } + } + return result; + }, + ( state ) => [ + state.blocks.parents, + state.blockListSettings, + state.editorMode, + getSectionRootClientId( state ), + ] +); + +/** + * Retrieves the client ID of the parent section block. + * + * @param {Object} state Global application state. + * @param {Object} clientId Client Id of the block. + * + * @return {?string} Client ID of the ancestor block that is content locking the block. + */ +export const getParentSectionBlock = createSelector( + ( state, clientId ) => { + let current = clientId; + let result; + while ( ( current = state.blocks.parents.get( current ) ) ) { + if ( isSectionBlock( state, current ) ) { result = current; } } @@ -503,7 +530,7 @@ export const getContentLockingParent = createSelector( * * @return {boolean} Whether the block is a content locking parent. */ -export function isContentLockingParent( state, clientId ) { +export function isSectionBlock( state, clientId ) { const sectionRootClientId = getSectionRootClientId( state ); const sectionClientIds = getBlockOrder( state, sectionRootClientId ); return ( diff --git a/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js b/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js index fcf7adfa77635..8aeeab79f8aa5 100644 --- a/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js +++ b/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js @@ -153,7 +153,7 @@ function TemplateLockContentOnlyMenuItems( { clientId, onClose } ) { onClose(); } } > - { _x( 'Unlock', 'Unlock content locked blocks' ) } + { _x( 'Unlock test', 'Unlock content locked blocks' ) } Date: Wed, 18 Sep 2024 09:52:02 +0100 Subject: [PATCH 11/22] Support block highlighting --- packages/block-editor/src/components/block-list/block.js | 7 ++++--- .../block-editor/src/components/block-list/content.scss | 2 +- .../src/components/block-list/use-block-props/index.js | 4 ++-- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index 3c0c340abbce1..90c39649319dc 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -549,6 +549,7 @@ function BlockListBlockProvider( props ) { getBlockMode, isSelectionEnabled, getTemplateLock, + isSectionBlock: _isSectionBlock, getBlockWithoutAttributes, getBlockAttributes, canRemoveBlock, @@ -650,7 +651,7 @@ function BlockListBlockProvider( props ) { mode: getBlockMode( clientId ), isSelectionEnabled: isSelectionEnabled(), isLocked: !! getTemplateLock( rootClientId ), - templateLock: getTemplateLock( clientId ), + isSectionBlock: _isSectionBlock( clientId ), canRemove, canMove, isSelected: _isSelected, @@ -733,7 +734,7 @@ function BlockListBlockProvider( props ) { isReusable, isDragging, hasChildSelected, - templateLock, + isSectionBlock, isEditingDisabled, hasEditableOutline, className, @@ -778,7 +779,7 @@ function BlockListBlockProvider( props ) { isReusable, isDragging, hasChildSelected, - templateLock, + isSectionBlock, isEditingDisabled, hasEditableOutline, isTemporarilyEditingAsBlocks, diff --git a/packages/block-editor/src/components/block-list/content.scss b/packages/block-editor/src/components/block-list/content.scss index 5eae127bd354b..3e3865e689bea 100644 --- a/packages/block-editor/src/components/block-list/content.scss +++ b/packages/block-editor/src/components/block-list/content.scss @@ -257,7 +257,7 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b } } -.is-root-container:not([inert]) .block-editor-block-list__block.is-reusable.is-selected .block-editor-block-list__block.has-editable-outline::after { +.is-root-container:not([inert]) .block-editor-block-list__block.is-selected .block-editor-block-list__block.has-editable-outline::after { animation-name: block-editor-is-editable__animation; animation-duration: 0.8s; animation-timing-function: ease-out; diff --git a/packages/block-editor/src/components/block-list/use-block-props/index.js b/packages/block-editor/src/components/block-list/use-block-props/index.js index 0bac8c4580dfb..1cf1d4908b076 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/index.js +++ b/packages/block-editor/src/components/block-list/use-block-props/index.js @@ -101,7 +101,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { hasEditableOutline, isTemporarilyEditingAsBlocks, defaultClassName, - templateLock, + isSectionBlock, } = useContext( PrivateBlockContext ); // translators: %s: Type of block (i.e. Text, Image etc) @@ -120,7 +120,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) { useDisabled( { isDisabled: ! hasOverlay } ), useFlashEditableBlocks( { clientId, - isEnabled: name === 'core/block' || templateLock === 'contentOnly', + isEnabled: isSectionBlock, } ), useScrollIntoView( { isSelected } ), ] ); From 0ae55fe8e41570e86ca8b95c9b3a544bf76a1985 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 18 Sep 2024 10:40:05 +0100 Subject: [PATCH 12/22] Fix canInsertBlockType dependents --- packages/block-editor/src/store/utils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/store/utils.js b/packages/block-editor/src/store/utils.js index b630912a5163d..af991608238e2 100644 --- a/packages/block-editor/src/store/utils.js +++ b/packages/block-editor/src/store/utils.js @@ -117,5 +117,6 @@ export function getInsertBlockTypeDependants( state, rootClientId ) { state.settings.allowedBlockTypes, state.settings.templateLock, state.blockEditingModes, + state.editorMode, ]; } From 51c2c81aa16e6b5e8801d7ea804e3f7dad980ea7 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 18 Sep 2024 11:01:41 +0100 Subject: [PATCH 13/22] Hide appender in section blocks --- .../src/components/block-list/index.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index 0e7d35d28c719..ed080d1208c69 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -182,7 +182,8 @@ function Items( { getTemplateLock, getBlockEditingMode, __unstableGetEditorMode, - } = select( blockEditorStore ); + isSectionBlock, + } = unlock( select( blockEditorStore ) ); const _order = getBlockOrder( rootClientId ); @@ -201,15 +202,16 @@ function Items( { visibleBlocks: __unstableGetVisibleBlocks(), isZoomOut: __unstableGetEditorMode() === 'zoom-out', shouldRenderAppender: + ! isSectionBlock( rootClientId ) && + ! getBlockEditingMode( rootClientId ) !== 'disabled' && + ! getTemplateLock( rootClientId ) && hasAppender && __unstableGetEditorMode() !== 'zoom-out' && - ( hasCustomAppender - ? ! getTemplateLock( rootClientId ) && - getBlockEditingMode( rootClientId ) !== 'disabled' - : rootClientId === selectedBlockClientId || - ( ! rootClientId && - ! selectedBlockClientId && - ! _order.length ) ), + ( hasCustomAppender || + rootClientId === selectedBlockClientId || + ( ! rootClientId && + ! selectedBlockClientId && + ! _order.length ) ), }; }, [ rootClientId, hasAppender, hasCustomAppender ] From 330efd3811a542a25049a18e1875cfa12867820c Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 18 Sep 2024 11:35:35 +0100 Subject: [PATCH 14/22] Disallow inserting blocks within sections --- packages/block-editor/src/store/selectors.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 9ed10e333bd1b..d6afb313400a8 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -38,6 +38,7 @@ import { getTemporarilyEditingAsBlocks, getTemporarilyEditingFocusModeToRevert, getSectionRootClientId, + isSectionBlock, } from './private-selectors'; /** @@ -1582,6 +1583,11 @@ const canInsertBlockTypeUnmemoized = ( return false; } + const _isSectionBlock = !! isSectionBlock( state, rootClientId ); + if ( _isSectionBlock ) { + return false; + } + if ( getBlockEditingMode( state, rootClientId ?? '' ) === 'disabled' ) { return false; } From 3eaf070560fa29bab409e9f5abdf6af18c0d1d12 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 18 Sep 2024 11:42:19 +0100 Subject: [PATCH 15/22] Update components changelog --- packages/components/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/CHANGELOG.md b/packages/components/CHANGELOG.md index 4dd18914a7acb..5161b5b524549 100644 --- a/packages/components/CHANGELOG.md +++ b/packages/components/CHANGELOG.md @@ -7,6 +7,7 @@ - `Tabs`: restore vertical indicator ([#65385](https://github.com/WordPress/gutenberg/pull/65385)). - `Tabs`: indicator positioning under RTL direction ([#64926](https://github.com/WordPress/gutenberg/pull/64926)). - `Popover`: Update `toolbar` variant radius to match block toolbar ([#65263](https://github.com/WordPress/gutenberg/pull/65263)). +- `MenuItemsChoice`: Allow menu items height to adapt to its content ([#65204](https://github.com/WordPress/gutenberg/pull/65204)). - `BoxControl`: Unify input filed width whether linked or not ([#65348](https://github.com/WordPress/gutenberg/pull/65348)). ### Deprecations From 7ed6c441638b5959dd8745a794e0d69283c1b9fb Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 18 Sep 2024 12:13:20 +0100 Subject: [PATCH 16/22] Fix and add unit tests --- .../block-editor/src/store/test/selectors.js | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js index 0fc61f0c75f5c..04899a9ee243f 100644 --- a/packages/block-editor/src/store/test/selectors.js +++ b/packages/block-editor/src/store/test/selectors.js @@ -2694,6 +2694,7 @@ describe( 'selectors', () => { byClientId: new Map(), attributes: new Map(), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: { @@ -2711,6 +2712,7 @@ describe( 'selectors', () => { blocks: { byClientId: new Map(), attributes: new Map(), + order: new Map(), }, blockListSettings: {}, settings: { @@ -2728,6 +2730,7 @@ describe( 'selectors', () => { byClientId: new Map(), attributes: new Map(), parents: new Map(), + order: new Map(), }, blockListSettings: {}, settings: {}, @@ -3002,7 +3005,7 @@ describe( 'selectors', () => { byClientId: new Map( Object.entries( { block1: { name: 'core/test-block-ancestor' }, - block2: { name: 'core/block' }, + block2: { name: 'core/block1' }, } ) ), attributes: new Map( @@ -3037,6 +3040,37 @@ describe( 'selectors', () => { ).toBe( true ); } ); + it( 'should prevent blocks from being inserted within sections', () => { + const state = { + blocks: { + byClientId: new Map( + Object.entries( { + block1: { name: 'core/block' }, // reusable blocks are always sections. + } ) + ), + attributes: new Map( + Object.entries( { + block1: {}, + } ) + ), + parents: new Map( + Object.entries( { + block1: '', + } ) + ), + order: new Map( [ [ '', [ 'block1' ] ] ] ), + }, + blockListSettings: { + block1: {}, + }, + settings: {}, + blockEditingModes: new Map(), + }; + expect( + canInsertBlockType( state, 'core/test-block-a', 'block1' ) + ).toBe( false ); + } ); + it( 'should allow blocks to be inserted if both parent and ancestor restrictions are met', () => { const state = { blocks: { From cf9cedf384e6daa0f1140657b6c364f77bf096ce Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 18 Sep 2024 13:34:21 +0100 Subject: [PATCH 17/22] Allow inserting blocks within the sections root container in navigation mode --- packages/block-editor/src/store/selectors.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index d6afb313400a8..1c3bf28ab082d 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -2964,13 +2964,19 @@ export const getBlockEditingMode = createRegistrySelector( if ( ! clientId ) { return 'default'; } - const rootClientId = getBlockRootClientId( state, clientId ); - const templateLock = getTemplateLock( state, rootClientId ); const sectionRootClientId = getSectionRootClientId( state ); + if ( + editorMode === 'navigation' && + clientId === sectionRootClientId + ) { + return 'default'; + } const sectionsClientIds = getBlockOrder( state, sectionRootClientId ); + const rootClientId = getBlockRootClientId( state, clientId ); + const templateLock = getTemplateLock( state, rootClientId ); if ( templateLock === 'contentOnly' || editorMode === 'navigation' From be0afbc1ca2d8974a526cde33a49a2ea96a89ed8 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 18 Sep 2024 16:49:02 +0100 Subject: [PATCH 18/22] Fix block settings menu --- .../content-only-settings-menu.js | 21 ++++---- .../disable-non-page-content-blocks.js | 54 +++++++------------ .../provider/use-post-content-blocks.js | 42 +++++++++++++++ 3 files changed, 74 insertions(+), 43 deletions(-) create mode 100644 packages/editor/src/components/provider/use-post-content-blocks.js diff --git a/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js b/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js index 8aeeab79f8aa5..4386c8af89d6e 100644 --- a/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js +++ b/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js @@ -17,21 +17,17 @@ import { __, _x } from '@wordpress/i18n'; */ import { store as editorStore } from '../../store'; import { unlock } from '../../lock-unlock'; +import usePostContentBlocks from '../provider/use-post-content-blocks'; function ContentOnlySettingsMenuItems( { clientId, onClose } ) { + const postContentBlocks = usePostContentBlocks(); const { entity, onNavigateToEntityRecord, canEditTemplates } = useSelect( ( select ) => { const { - getBlockEditingMode, getBlockParentsByBlockName, getSettings, getBlockAttributes, } = select( blockEditorStore ); - const contentOnly = - getBlockEditingMode( clientId ) === 'contentOnly'; - if ( ! contentOnly ) { - return {}; - } const patternParent = getBlockParentsByBlockName( clientId, 'core/block', @@ -48,10 +44,14 @@ function ContentOnlySettingsMenuItems( { clientId, onClose } ) { } else { const { getCurrentTemplateId } = select( editorStore ); const templateId = getCurrentTemplateId(); - const { getContentLockingParent } = unlock( + const { getBlockParents } = unlock( select( blockEditorStore ) ); - if ( ! getContentLockingParent( clientId ) && templateId ) { + if ( + ! getBlockParents( clientId ).some( ( parent ) => + postContentBlocks.includes( parent ) + ) + ) { record = select( coreStore ).getEntityRecord( 'postType', 'wp_template', @@ -59,6 +59,9 @@ function ContentOnlySettingsMenuItems( { clientId, onClose } ) { ); } } + if ( ! record ) { + return {}; + } const _canEditTemplates = select( coreStore ).canUser( 'create', { kind: 'postType', name: 'wp_template', @@ -70,7 +73,7 @@ function ContentOnlySettingsMenuItems( { clientId, onClose } ) { getSettings().onNavigateToEntityRecord, }; }, - [ clientId ] + [ clientId, postContentBlocks ] ); if ( ! entity ) { diff --git a/packages/editor/src/components/provider/disable-non-page-content-blocks.js b/packages/editor/src/components/provider/disable-non-page-content-blocks.js index 9abb0e14079d5..ae4fd1075fc26 100644 --- a/packages/editor/src/components/provider/disable-non-page-content-blocks.js +++ b/packages/editor/src/components/provider/disable-non-page-content-blocks.js @@ -3,52 +3,32 @@ */ import { useSelect, useRegistry } from '@wordpress/data'; import { store as blockEditorStore } from '@wordpress/block-editor'; -import { useEffect, useMemo } from '@wordpress/element'; -import { applyFilters } from '@wordpress/hooks'; +import { useEffect } from '@wordpress/element'; /** * Internal dependencies */ -import { store as editorStore } from '../../store'; -import { unlock } from '../../lock-unlock'; - -const POST_CONTENT_BLOCK_TYPES = [ - 'core/post-title', - 'core/post-featured-image', - 'core/post-content', -]; +import usePostContentBlocks from './use-post-content-blocks'; /** * Component that when rendered, makes it so that the site editor allows only * page content to be edited. */ export default function DisableNonPageContentBlocks() { - const contentOnlyBlockTypes = useMemo( - () => [ - ...applyFilters( - 'editor.postContentBlockTypes', - POST_CONTENT_BLOCK_TYPES - ), - 'core/template-part', - ], - [] - ); - - // Note that there are two separate subscriptions because the result for each - // returns a new array. - const contentOnlyIds = useSelect( + const contentOnlyIds = usePostContentBlocks(); + const templateParts = useSelect( ( select ) => { + const { getBlocksByName } = select( blockEditorStore ); + return getBlocksByName( 'core/template-part' ); + }, [] ); + const disabledIds = useSelect( ( select ) => { - const { getPostBlocksByName } = unlock( select( editorStore ) ); - return getPostBlocksByName( contentOnlyBlockTypes ); + const { getBlockOrder } = select( blockEditorStore ); + return templateParts.flatMap( ( clientId ) => + getBlockOrder( clientId ) + ); }, - [ contentOnlyBlockTypes ] + [ templateParts ] ); - const disabledIds = useSelect( ( select ) => { - const { getBlocksByName, getBlockOrder } = select( blockEditorStore ); - return getBlocksByName( 'core/template-part' ).flatMap( ( clientId ) => - getBlockOrder( clientId ) - ); - }, [] ); const registry = useRegistry(); @@ -61,6 +41,9 @@ export default function DisableNonPageContentBlocks() { for ( const clientId of contentOnlyIds ) { setBlockEditingMode( clientId, 'contentOnly' ); } + for ( const clientId of templateParts ) { + setBlockEditingMode( clientId, 'contentOnly' ); + } for ( const clientId of disabledIds ) { setBlockEditingMode( clientId, 'disabled' ); } @@ -72,12 +55,15 @@ export default function DisableNonPageContentBlocks() { for ( const clientId of contentOnlyIds ) { unsetBlockEditingMode( clientId ); } + for ( const clientId of templateParts ) { + unsetBlockEditingMode( clientId ); + } for ( const clientId of disabledIds ) { unsetBlockEditingMode( clientId ); } } ); }; - }, [ contentOnlyIds, disabledIds, registry ] ); + }, [ templateParts, contentOnlyIds, disabledIds, registry ] ); return null; } diff --git a/packages/editor/src/components/provider/use-post-content-blocks.js b/packages/editor/src/components/provider/use-post-content-blocks.js new file mode 100644 index 0000000000000..bdd277157e47e --- /dev/null +++ b/packages/editor/src/components/provider/use-post-content-blocks.js @@ -0,0 +1,42 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; +import { useMemo } from '@wordpress/element'; +import { applyFilters } from '@wordpress/hooks'; + +/** + * Internal dependencies + */ +import { store as editorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; + +const POST_CONTENT_BLOCK_TYPES = [ + 'core/post-title', + 'core/post-featured-image', + 'core/post-content', +]; + +export default function usePostContentBlocks() { + const contentOnlyBlockTypes = useMemo( + () => [ + ...applyFilters( + 'editor.postContentBlockTypes', + POST_CONTENT_BLOCK_TYPES + ), + ], + [] + ); + + // Note that there are two separate subscriptions because the result for each + // returns a new array. + const contentOnlyIds = useSelect( + ( select ) => { + const { getPostBlocksByName } = unlock( select( editorStore ) ); + return getPostBlocksByName( contentOnlyBlockTypes ); + }, + [ contentOnlyBlockTypes ] + ); + + return contentOnlyIds; +} From 96642a61417ba9be46262929e99ea218869844bf Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Wed, 18 Sep 2024 16:59:25 +0100 Subject: [PATCH 19/22] Remove debug code --- .../block-settings-menu/content-only-settings-menu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js b/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js index 4386c8af89d6e..c772a062b9e3b 100644 --- a/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js +++ b/packages/editor/src/components/block-settings-menu/content-only-settings-menu.js @@ -156,7 +156,7 @@ function TemplateLockContentOnlyMenuItems( { clientId, onClose } ) { onClose(); } } > - { _x( 'Unlock test', 'Unlock content locked blocks' ) } + { _x( 'Unlock', 'Unlock content locked blocks' ) } Date: Wed, 18 Sep 2024 17:23:48 +0100 Subject: [PATCH 20/22] Blocks within sections shouldn't be removable --- packages/block-editor/src/store/selectors.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js index 1c3bf28ab082d..ca66340a89e30 100644 --- a/packages/block-editor/src/store/selectors.js +++ b/packages/block-editor/src/store/selectors.js @@ -39,6 +39,7 @@ import { getTemporarilyEditingFocusModeToRevert, getSectionRootClientId, isSectionBlock, + getParentSectionBlock, } from './private-selectors'; /** @@ -1739,6 +1740,11 @@ export function canRemoveBlock( state, clientId ) { return false; } + const isBlockWithinSection = !! getParentSectionBlock( state, clientId ); + if ( isBlockWithinSection ) { + return false; + } + return getBlockEditingMode( state, rootClientId ) !== 'disabled'; } From 20843361b4f3b8b7466a236d4d1b172b418dcbfe Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 19 Sep 2024 15:32:07 +0100 Subject: [PATCH 21/22] Small fixes per review --- packages/block-editor/src/components/block-list/index.js | 2 +- packages/block-editor/src/store/private-selectors.js | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index ed080d1208c69..e2e019d4a9bf6 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -203,7 +203,7 @@ function Items( { isZoomOut: __unstableGetEditorMode() === 'zoom-out', shouldRenderAppender: ! isSectionBlock( rootClientId ) && - ! getBlockEditingMode( rootClientId ) !== 'disabled' && + getBlockEditingMode( rootClientId ) !== 'disabled' && ! getTemplateLock( rootClientId ) && hasAppender && __unstableGetEditorMode() !== 'zoom-out' && diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 6c3dd752bf79b..9cf7d96e0bae6 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -490,8 +490,7 @@ export const getContentLockingParent = createSelector( ( state ) => [ state.blocks.parents, state.blockListSettings, - state.editorMode, - getSectionRootClientId( state ), + state.settings.templateLock, ] ); @@ -516,8 +515,11 @@ export const getParentSectionBlock = createSelector( }, ( state ) => [ state.blocks.parents, + state.blocks.order, state.blockListSettings, state.editorMode, + state.settings.templateLock, + state.blocks.byClientId, getSectionRootClientId( state ), ] ); From a783818c3205e9ad45b8f508e3f3bccb754bc256 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Thu, 19 Sep 2024 15:59:54 +0100 Subject: [PATCH 22/22] Add condition to break the loop --- packages/block-editor/src/store/private-selectors.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/store/private-selectors.js b/packages/block-editor/src/store/private-selectors.js index 9cf7d96e0bae6..0e77e8e2ed433 100644 --- a/packages/block-editor/src/store/private-selectors.js +++ b/packages/block-editor/src/store/private-selectors.js @@ -480,7 +480,10 @@ export const getContentLockingParent = createSelector( ( state, clientId ) => { let current = clientId; let result; - while ( ( current = state.blocks.parents.get( current ) ) ) { + while ( + ! result && + ( current = state.blocks.parents.get( current ) ) + ) { if ( getTemplateLock( state, current ) === 'contentOnly' ) { result = current; } @@ -506,7 +509,10 @@ export const getParentSectionBlock = createSelector( ( state, clientId ) => { let current = clientId; let result; - while ( ( current = state.blocks.parents.get( current ) ) ) { + while ( + ! result && + ( current = state.blocks.parents.get( current ) ) + ) { if ( isSectionBlock( state, current ) ) { result = current; }