diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md index e0e9695a0036a..f38cc49a87c0a 100644 --- a/docs/reference-guides/data/data-core-block-editor.md +++ b/docs/reference-guides/data/data-core-block-editor.md @@ -1492,7 +1492,7 @@ Action that enables or disables the navigation mode. _Parameters_ -- _isNavigationMode_ `string`: Enable/Disable navigation mode. +- _isNavigationMode_ `boolean`: Enable/Disable navigation mode. ### setTemplateValidity diff --git a/packages/block-editor/src/components/block-list-appender/index.js b/packages/block-editor/src/components/block-list-appender/index.js index d6cc56d5e2cc9..ec5687b6fec9d 100644 --- a/packages/block-editor/src/components/block-list-appender/index.js +++ b/packages/block-editor/src/components/block-list-appender/index.js @@ -6,7 +6,7 @@ import classnames from 'classnames'; /** * WordPress dependencies */ -import { withSelect } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; import { getDefaultBlockName } from '@wordpress/blocks'; /** @@ -18,14 +18,38 @@ import { store as blockEditorStore } from '../../store'; function BlockListAppender( { rootClientId, - canInsertDefaultBlock, - isLocked, renderAppender: CustomAppender, className, - selectedBlockClientId, tagName: TagName = 'div', } ) { - if ( isLocked || CustomAppender === false ) { + const { + hideInserter, + canInsertDefaultBlock, + selectedBlockClientId, + } = useSelect( + ( select ) => { + const { + canInsertBlockType, + getTemplateLock, + getSelectedBlockClientId, + __unstableGetEditorMode, + } = select( blockEditorStore ); + + return { + hideInserter: + !! getTemplateLock( rootClientId ) || + __unstableGetEditorMode() !== 'edit', + canInsertDefaultBlock: canInsertBlockType( + getDefaultBlockName(), + rootClientId + ), + selectedBlockClientId: getSelectedBlockClientId(), + }; + }, + [ rootClientId ] + ); + + if ( hideInserter || CustomAppender === false ) { return null; } @@ -92,19 +116,4 @@ function BlockListAppender( { ); } -export default withSelect( ( select, { rootClientId } ) => { - const { - canInsertBlockType, - getTemplateLock, - getSelectedBlockClientId, - } = select( blockEditorStore ); - - return { - isLocked: !! getTemplateLock( rootClientId ), - canInsertDefaultBlock: canInsertBlockType( - getDefaultBlockName(), - rootClientId - ), - selectedBlockClientId: getSelectedBlockClientId(), - }; -} )( BlockListAppender ); +export default BlockListAppender; diff --git a/packages/block-editor/src/components/block-list/index.js b/packages/block-editor/src/components/block-list/index.js index b97bb03c5c142..db91eb7c13d3e 100644 --- a/packages/block-editor/src/components/block-list/index.js +++ b/packages/block-editor/src/components/block-list/index.js @@ -34,16 +34,16 @@ export const IntersectionObserver = createContext(); function Root( { className, ...settings } ) { const [ element, setElement ] = useState(); const isLargeViewport = useViewportMatch( 'medium' ); - const { isOutlineMode, isFocusMode, isNavigationMode } = useSelect( + const { isOutlineMode, isFocusMode, editorMode } = useSelect( ( select ) => { - const { getSettings, isNavigationMode: _isNavigationMode } = select( + const { getSettings, __unstableGetEditorMode } = select( blockEditorStore ); const { outlineMode, focusMode } = getSettings(); return { isOutlineMode: outlineMode, isFocusMode: focusMode, - isNavigationMode: _isNavigationMode(), + editorMode: __unstableGetEditorMode(), }; }, [] @@ -75,7 +75,8 @@ function Root( { className, ...settings } ) { className: classnames( 'is-root-container', className, { 'is-outline-mode': isOutlineMode, 'is-focus-mode': isFocusMode && isLargeViewport, - 'is-navigate-mode': isNavigationMode, + 'is-navigate-mode': editorMode === 'navigation', + 'is-exploded-mode': editorMode === 'exploded', } ), }, settings diff --git a/packages/block-editor/src/components/block-list/style.scss b/packages/block-editor/src/components/block-list/style.scss index da02c6fd4b801..b6c37cb2cf2b0 100644 --- a/packages/block-editor/src/components/block-list/style.scss +++ b/packages/block-editor/src/components/block-list/style.scss @@ -408,3 +408,38 @@ margin-bottom: auto; } } + +/** Exploded mode styles **/ +.is-root-container.is-exploded-mode > .wp-block { + transform-origin: center center; + position: relative; + overflow: hidden; + + &::after { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: z-index(".block-editor-block-content-overlay__overlay"); + pointer-events: unset !important; + } + + &:hover:not(.is-selected)::after { + background: rgba(var(--wp-admin-theme-color--rgb), 0.1); + box-shadow: 0 0 0 0 var(--wp-admin-theme-color) inset; + } + + &.overlay-active * { + pointer-events: none; + } + + &.is-selected { + box-shadow: $border-width 0 0 0 var(--wp-admin-theme-color) inset; + } +} + +.is-root-container.is-exploded-mode > .block-list-appender { + display: none; +} 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 17ea149b61da7..a08a2a5386c81 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 @@ -74,6 +74,8 @@ export function useBlockProps( isPartOfSelection, adjustScrolling, enableAnimation, + isExplodedMode, + isRootBlock, } = useSelect( ( select ) => { const { @@ -86,6 +88,8 @@ export function useBlockProps( isBlockMultiSelected, isAncestorMultiSelected, isFirstMultiSelectedBlock, + __unstableGetEditorMode, + getBlockRootClientId, } = select( blockEditorStore ); const isSelected = isBlockSelected( clientId ); const isPartOfMultiSelection = @@ -106,6 +110,8 @@ export function useBlockProps( enableAnimation: ! isTyping() && getGlobalBlockCount() <= BLOCK_ANIMATION_THRESHOLD, + isExplodedMode: __unstableGetEditorMode() === 'exploded', + isRootBlock: ! getBlockRootClientId( clientId ), }; }, [ clientId ] @@ -128,6 +134,7 @@ export function useBlockProps( adjustScrolling, enableAnimation, triggerAnimationOnChange: index, + scale: isExplodedMode && isRootBlock ? 0.8 : 1, } ), useDisabled( { isDisabled: ! __unstableIsDisabled } ), ] ); diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js b/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js index 8b95f19f3c9ff..d9b6b3831f1a4 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-focus-first-element.js @@ -36,7 +36,7 @@ function useInitialPosition( clientId ) { ( select ) => { const { getSelectedBlocksInitialCaretPosition, - isNavigationMode, + __unstableGetEditorMode, isBlockSelected, } = select( blockEditorStore ); @@ -44,7 +44,7 @@ function useInitialPosition( clientId ) { return; } - if ( isNavigationMode() ) { + if ( __unstableGetEditorMode() !== 'edit' ) { return; } diff --git a/packages/block-editor/src/components/block-list/use-block-props/use-is-hovered.js b/packages/block-editor/src/components/block-list/use-block-props/use-is-hovered.js index 26fc68c21ce2f..608026214b778 100644 --- a/packages/block-editor/src/components/block-list/use-block-props/use-is-hovered.js +++ b/packages/block-editor/src/components/block-list/use-block-props/use-is-hovered.js @@ -26,8 +26,14 @@ function listener( event ) { */ export function useIsHovered() { const isEnabled = useSelect( ( select ) => { - const { isNavigationMode, getSettings } = select( blockEditorStore ); - return isNavigationMode() || getSettings().outlineMode; + const { __unstableGetEditorMode, getSettings } = select( + blockEditorStore + ); + return ( + __unstableGetEditorMode() === 'navigation' || + ( getSettings().outlineMode && + __unstableGetEditorMode() === 'exploded' ) + ); }, [] ); return useRefEffect( diff --git a/packages/block-editor/src/components/block-popover/inbetween.js b/packages/block-editor/src/components/block-popover/inbetween.js index a671d7f312c0e..28c178cf5b3c3 100644 --- a/packages/block-editor/src/components/block-popover/inbetween.js +++ b/packages/block-editor/src/components/block-popover/inbetween.js @@ -7,7 +7,13 @@ import classnames from 'classnames'; * WordPress dependencies */ import { useSelect } from '@wordpress/data'; -import { useCallback, useMemo, createContext } from '@wordpress/element'; +import { + useCallback, + useMemo, + createContext, + useState, + useEffect, +} from '@wordpress/element'; import { Popover } from '@wordpress/components'; import { isRTL } from '@wordpress/i18n'; @@ -28,6 +34,13 @@ function BlockPopoverInbetween( { __unstableContentRef, ...props } ) { + // This is a temporary hack to get the inbetween inserter to recompute properly. + const [ positionRecompute, forceRecompute ] = useState( {} ); + useEffect( () => { + const intervalHandle = setInterval( forceRecompute, 500 ); + return () => clearInterval( intervalHandle ); + }, [] ); + const { orientation, rootClientId, isVisible } = useSelect( ( select ) => { const { @@ -66,9 +79,7 @@ function BlockPopoverInbetween( { if ( isVertical ) { return { - width: previousElement - ? previousElement.offsetWidth - : nextElement.offsetWidth, + width: previousRect ? previousRect.width : nextRect.width, height: nextRect && previousRect ? nextRect.top - previousRect.bottom @@ -85,11 +96,15 @@ function BlockPopoverInbetween( { return { width, - height: previousElement - ? previousElement.offsetHeight - : nextElement.offsetHeight, + height: previousRect ? previousRect.height : nextRect.height, }; - }, [ previousElement, nextElement, isVertical ] ); + }, [ + previousElement, + nextElement, + isVertical, + positionRecompute, + isVisible, + ] ); const getAnchorRect = useCallback( () => { if ( ( ! previousElement && ! nextElement ) || ! isVisible ) { @@ -110,8 +125,8 @@ function BlockPopoverInbetween( { return { top: previousRect ? previousRect.bottom : nextRect.top, left: previousRect ? previousRect.right : nextRect.right, - right: previousRect ? previousRect.left : nextRect.left, - bottom: nextRect ? nextRect.top : previousRect.bottom, + right: previousRect ? previousRect.right : nextRect.right, + bottom: previousRect ? previousRect.bottom : nextRect.top, height: 0, width: 0, ownerDocument, @@ -121,8 +136,8 @@ function BlockPopoverInbetween( { return { top: previousRect ? previousRect.bottom : nextRect.top, left: previousRect ? previousRect.left : nextRect.left, - right: previousRect ? previousRect.right : nextRect.right, - bottom: nextRect ? nextRect.top : previousRect.bottom, + right: previousRect ? previousRect.left : nextRect.left, + bottom: previousRect ? previousRect.bottom : nextRect.top, height: 0, width: 0, ownerDocument, @@ -133,8 +148,8 @@ function BlockPopoverInbetween( { return { top: previousRect ? previousRect.top : nextRect.top, left: previousRect ? previousRect.left : nextRect.right, - right: nextRect ? nextRect.right : previousRect.left, - bottom: previousRect ? previousRect.bottom : nextRect.bottom, + right: previousRect ? previousRect.left : nextRect.right, + bottom: previousRect ? previousRect.top : nextRect.top, height: 0, width: 0, ownerDocument, @@ -144,13 +159,13 @@ function BlockPopoverInbetween( { return { top: previousRect ? previousRect.top : nextRect.top, left: previousRect ? previousRect.right : nextRect.left, - right: nextRect ? nextRect.left : previousRect.right, - bottom: previousRect ? previousRect.bottom : nextRect.bottom, + right: previousRect ? previousRect.right : nextRect.left, + bottom: previousRect ? previousRect.left : nextRect.right, height: 0, width: 0, ownerDocument, }; - }, [ previousElement, nextElement ] ); + }, [ previousElement, nextElement, positionRecompute, isVisible ] ); const popoverScrollRef = usePopoverScroll( __unstableContentRef ); @@ -183,8 +198,14 @@ function BlockPopoverInbetween( { props.className ) } __unstableForcePosition + placement="bottom-start" > -
{ children }
+
+ { children } +
); /* eslint-enable jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */ diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index ce28d8943b010..83f1478371596 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -62,6 +62,7 @@ export default function BlockPopover( { // Observe movement for block animations (especially horizontal). __unstableObserveElement={ selectedElement } __unstableForcePosition + __unstableShift { ...props } className={ classnames( 'block-editor-block-popover', diff --git a/packages/block-editor/src/components/block-popover/style.scss b/packages/block-editor/src/components/block-popover/style.scss index df2218950999e..c93d6d865059d 100644 --- a/packages/block-editor/src/components/block-popover/style.scss +++ b/packages/block-editor/src/components/block-popover/style.scss @@ -6,6 +6,9 @@ // like the popover is impacted by the block gap margin. margin: 0 !important; + // Allow clicking through the toolbar holder. + pointer-events: none; + .components-popover__content { margin: 0 !important; min-width: auto; @@ -16,13 +19,15 @@ box-shadow: none; overflow-y: visible; - // Allow clicking through the toolbar holder. - pointer-events: none; - - // Position the block toolbar. - > * { + > div > * { pointer-events: all; } } } +.block-editor-block-popover__inbetween-container { + pointer-events: none !important; + > div > * { + pointer-events: all; + } +} 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 index 07ba78151e9de..c139a5eae6f33 100644 --- a/packages/block-editor/src/components/block-tools/block-selection-button.js +++ b/packages/block-editor/src/components/block-tools/block-selection-button.js @@ -39,6 +39,7 @@ import { store as blockEditorStore } from '../../store'; import BlockDraggable from '../block-draggable'; import useBlockDisplayInformation from '../use-block-display-information'; import { __unstableUseBlockElement as useBlockElement } from '../block-list/use-block-props/use-block-refs'; +import BlockMover from '../block-mover'; /** * Block selection button component, displaying the label of the block. If the block @@ -59,6 +60,7 @@ function BlockSelectionButton( { clientId, rootClientId } ) { getBlockIndex, hasBlockMovingClientId, getBlockListSettings, + __unstableGetEditorMode, } = select( blockEditorStore ); const index = getBlockIndex( clientId ); const { name, attributes } = getBlock( clientId ); @@ -69,11 +71,19 @@ function BlockSelectionButton( { clientId, rootClientId } ) { attributes, blockMovingMode, orientation: getBlockListSettings( rootClientId )?.orientation, + editorMode: __unstableGetEditorMode(), }; }, [ clientId, rootClientId ] ); - const { index, name, attributes, blockMovingMode, orientation } = selected; + const { + index, + name, + attributes, + blockMovingMode, + orientation, + editorMode, + } = selected; const { setNavigationMode, removeBlock } = useDispatch( blockEditorStore ); const ref = useRef(); @@ -226,6 +236,7 @@ function BlockSelectionButton( { clientId, rootClientId } ) { 'block-editor-block-list__block-selection-button', { 'is-block-moving-mode': !! blockMovingMode, + 'is-exploded-mode': editorMode === 'exploded', } ); @@ -241,20 +252,25 @@ function BlockSelectionButton( { clientId, rootClientId } ) { - - { ( draggableProps ) => ( -