From 598d612245faf07547fd8b0f66faf3c2c37f25f9 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Wed, 25 Sep 2024 02:15:15 +0300 Subject: [PATCH 01/23] enable vertical toolbar for non full width elements, anchor based on parent --- .../src/components/block-popover/index.js | 19 +++++++++++++++++++ .../block-tools/use-show-block-tools.js | 4 +--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 47022e336e4869..d088ee87b31ada 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -8,6 +8,7 @@ import clsx from 'clsx'; */ import { useMergeRefs } from '@wordpress/compose'; import { Popover } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; import { forwardRef, useMemo, @@ -21,6 +22,8 @@ import { import { useBlockElement } from '../block-list/use-block-props/use-block-refs'; import usePopoverScroll from './use-popover-scroll'; import { rectUnion, getVisibleElementBounds } from '../../utils/dom'; +import { store as blockEditorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; const MAX_POPOVER_RECOMPUTE_COUNTER = Number.MAX_SAFE_INTEGER; @@ -74,6 +77,8 @@ function BlockPopover( }; }, [ selectedElement ] ); + const { isZoomOut } = unlock( useSelect( blockEditorStore ) ); + const popoverAnchor = useMemo( () => { if ( // popoverDimensionsRecomputeCounter is by definition always equal or greater @@ -88,6 +93,20 @@ function BlockPopover( return { getBoundingClientRect() { + if ( isZoomOut() ) { + const selectedRect = + getVisibleElementBounds( selectedElement ); + const parentRect = getVisibleElementBounds( + selectedElement.parentElement + ); + return new window.DOMRectReadOnly( + parentRect.left, + selectedRect.top, + parentRect.right - parentRect.left, + selectedRect.bottom - selectedRect.top + ); + } + return lastSelectedElement ? rectUnion( getVisibleElementBounds( selectedElement ), 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 02a8f0583bcddf..b24644de51fcc6 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 @@ -43,9 +43,7 @@ export function useShowBlockTools() { isEmptyDefaultBlock; const isZoomOut = editorMode === 'zoom-out'; const _showZoomOutToolbar = - isZoomOut && - block?.attributes?.align === 'full' && - ! _showEmptyBlockSideInserter; + clientId && isZoomOut && ! _showEmptyBlockSideInserter; const _showBlockToolbarPopover = ! _showZoomOutToolbar && ! getSettings().hasFixedToolbar && From ced9cbd31f6a42fc7930abf2a5952968f7db3d5b Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Wed, 25 Sep 2024 15:17:34 +0300 Subject: [PATCH 02/23] Update packages/block-editor/src/components/block-popover/index.js Co-authored-by: Dave Smith --- packages/block-editor/src/components/block-popover/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index d088ee87b31ada..88f5f6a7aaa6f4 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -94,7 +94,7 @@ function BlockPopover( return { getBoundingClientRect() { if ( isZoomOut() ) { - const selectedRect = + const selectedBlockRect = getVisibleElementBounds( selectedElement ); const parentRect = getVisibleElementBounds( selectedElement.parentElement From 31f69eb0902b4ac24e71b0fc71894390752e9e3a Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Wed, 25 Sep 2024 15:27:59 +0300 Subject: [PATCH 03/23] Update packages/block-editor/src/components/block-popover/index.js Co-authored-by: Dave Smith --- packages/block-editor/src/components/block-popover/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 88f5f6a7aaa6f4..9a38a5b0ae35d5 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -96,7 +96,7 @@ function BlockPopover( if ( isZoomOut() ) { const selectedBlockRect = getVisibleElementBounds( selectedElement ); - const parentRect = getVisibleElementBounds( + const sectionRootElementRect = getVisibleElementBounds( selectedElement.parentElement ); return new window.DOMRectReadOnly( From 0d91f44212f2cb83a05b42f5f5fbf377f3ede26c Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Mon, 30 Sep 2024 07:49:43 +0300 Subject: [PATCH 04/23] make zoom out check a dependency of the memoization, improve code readability --- .../src/components/block-popover/index.js | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 9a38a5b0ae35d5..9b8e991583239f 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -77,7 +77,8 @@ function BlockPopover( }; }, [ selectedElement ] ); - const { isZoomOut } = unlock( useSelect( blockEditorStore ) ); + const { isZoomOut: isZoomOutFn } = unlock( useSelect( blockEditorStore ) ); + const isZoomOut = isZoomOutFn(); const popoverAnchor = useMemo( () => { if ( @@ -93,17 +94,26 @@ function BlockPopover( return { getBoundingClientRect() { - if ( isZoomOut() ) { + // The zoom out view has a verical block toolbar that should always + // be on the edge of the canvas. This condition chnages the anchor + // of the toolbar to the section instead of the block to cover for blocks + // that are not full width. + if ( isZoomOut ) { const selectedBlockRect = getVisibleElementBounds( selectedElement ); const sectionRootElementRect = getVisibleElementBounds( selectedElement.parentElement ); + const selectedBlockRectHeight = + selectedBlockRect.bottom - selectedBlockRect.top; + const sectionRootElementRectWidth = + sectionRootElementRect.right - + sectionRootElementRect.left; return new window.DOMRectReadOnly( - parentRect.left, - selectedRect.top, - parentRect.right - parentRect.left, - selectedRect.bottom - selectedRect.top + sectionRootElementRect.left, + selectedBlockRect.top, + sectionRootElementRectWidth, + selectedBlockRectHeight ); } @@ -121,6 +131,7 @@ function BlockPopover( lastSelectedElement, selectedElement, popoverDimensionsRecomputeCounter, + isZoomOut, ] ); if ( ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) { From 2bb5176ca3ab09980a9795034dfa13f8570e226e Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Tue, 1 Oct 2024 10:13:11 +0300 Subject: [PATCH 05/23] comment typos --- packages/block-editor/src/components/block-popover/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 9b8e991583239f..9d23c0b2ff3499 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -94,9 +94,9 @@ function BlockPopover( return { getBoundingClientRect() { - // The zoom out view has a verical block toolbar that should always - // be on the edge of the canvas. This condition chnages the anchor - // of the toolbar to the section instead of the block to cover for blocks + // The zoom out view has a vertical block toolbar that should always + // be on the edge of the canvas. This condition changes the anchor + // of the toolbar to the section instead of the block to handle blocks // that are not full width. if ( isZoomOut ) { const selectedBlockRect = From bb2b790fb9851b5dc9ea62056a4a442ab511a12f Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Tue, 1 Oct 2024 10:42:35 +0300 Subject: [PATCH 06/23] subscribe to state instead of calculating zoom out view state when calculating the anchor --- .../block-editor/src/components/block-popover/index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 9d23c0b2ff3499..45a2b3aa970043 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -77,8 +77,12 @@ function BlockPopover( }; }, [ selectedElement ] ); - const { isZoomOut: isZoomOutFn } = unlock( useSelect( blockEditorStore ) ); - const isZoomOut = isZoomOutFn(); + const { isZoomOut } = useSelect( + ( select ) => ( { + isZoomOut: unlock( select( blockEditorStore ) ).isZoomOut(), + } ), + [] + ); const popoverAnchor = useMemo( () => { if ( From 216f472f095b93ea7e4d15d9ee2328290009345e Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Wed, 2 Oct 2024 18:09:47 +0300 Subject: [PATCH 07/23] get the section wrapper for anchoring instead of the parent --- .../src/components/block-popover/index.js | 85 ++++++++++++++----- 1 file changed, 62 insertions(+), 23 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 45a2b3aa970043..c4ed7da3f1831b 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -77,12 +77,44 @@ function BlockPopover( }; }, [ selectedElement ] ); - const { isZoomOut } = useSelect( - ( select ) => ( { - isZoomOut: unlock( select( blockEditorStore ) ).isZoomOut(), - } ), - [] - ); + const { + selectedBlockParentClientIds, + isZoomOut, + sectionRootClientId, + sectionClientIds, + } = useSelect( ( select ) => { + const { + isZoomOut: isZoomOutSelector, + getBlockOrder, + getSectionRootClientId, + getBlockParents, + getSelectedBlock, + } = unlock( select( blockEditorStore ) ); + + const root = getSectionRootClientId(); + const sectionRootClientIds = getBlockOrder( root ); + return { + sectionRootClientId: root, + sectionClientIds: sectionRootClientIds, + isZoomOut: isZoomOutSelector(), + selectedBlockParentClientIds: getBlockParents( getSelectedBlock() ), + }; + }, [] ); + + // These elements are used to position the zoom out view vertical toolbar + // correctly, relative to the selected section. + const rootSectionElement = useBlockElement( sectionRootClientId ); + let parentSectionClientId; + if ( sectionClientIds.includes( clientId ) ) { + parentSectionClientId = clientId; + } else { + parentSectionClientId = + selectedBlockParentClientIds.find( ( parentClientId ) => + sectionClientIds.includes( parentClientId ) + ) ?? clientId; + } + + const parentSectionElement = useBlockElement( parentSectionClientId ); const popoverAnchor = useMemo( () => { if ( @@ -99,25 +131,32 @@ function BlockPopover( return { getBoundingClientRect() { // The zoom out view has a vertical block toolbar that should always - // be on the edge of the canvas. This condition changes the anchor - // of the toolbar to the section instead of the block to handle blocks - // that are not full width. + // be on the edge of the canvas, aligned to the top of the currently + // selected section. This condition changes the anchor of the toolbar + // to the section instead of the block to handle blocksn that are + // not full width and nested blocks to keep section height. if ( isZoomOut ) { - const selectedBlockRect = - getVisibleElementBounds( selectedElement ); - const sectionRootElementRect = getVisibleElementBounds( - selectedElement.parentElement - ); - const selectedBlockRectHeight = - selectedBlockRect.bottom - selectedBlockRect.top; - const sectionRootElementRectWidth = - sectionRootElementRect.right - - sectionRootElementRect.left; + // Compute the height based on the parent section of the + // selected block, because the selected block may be + // shorter than the section. + const rootSectionElementRect = + getVisibleElementBounds( rootSectionElement ); + const parentSectionElementRect = + getVisibleElementBounds( parentSectionElement ); + const anchorHeight = + parentSectionElementRect.bottom - + parentSectionElementRect.top; + + // Always use the width of the section root element to make sure + // the toolbar is always on the edge of the canvas. + const andchorWidth = + rootSectionElementRect.right - + rootSectionElementRect.left; return new window.DOMRectReadOnly( - sectionRootElementRect.left, - selectedBlockRect.top, - sectionRootElementRectWidth, - selectedBlockRectHeight + rootSectionElementRect.left, + parentSectionElementRect.top, + andchorWidth, + anchorHeight ); } From 64b48d6bc088fe0a308ece9fbd1b039e87a625aa Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Wed, 2 Oct 2024 18:44:35 +0300 Subject: [PATCH 08/23] use a selector instead of computing on the fly the parent section --- .../src/components/block-popover/index.js | 54 +++++++------------ 1 file changed, 20 insertions(+), 34 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index c4ed7da3f1831b..d48252ba34839c 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -77,44 +77,30 @@ function BlockPopover( }; }, [ selectedElement ] ); - const { - selectedBlockParentClientIds, - isZoomOut, - sectionRootClientId, - sectionClientIds, - } = useSelect( ( select ) => { - const { - isZoomOut: isZoomOutSelector, - getBlockOrder, - getSectionRootClientId, - getBlockParents, - getSelectedBlock, - } = unlock( select( blockEditorStore ) ); - - const root = getSectionRootClientId(); - const sectionRootClientIds = getBlockOrder( root ); - return { - sectionRootClientId: root, - sectionClientIds: sectionRootClientIds, - isZoomOut: isZoomOutSelector(), - selectedBlockParentClientIds: getBlockParents( getSelectedBlock() ), - }; - }, [] ); + const { isZoomOut, sectionRootClientId, getParentSectionBlock } = useSelect( + ( select ) => { + const { + isZoomOut: isZoomOutSelector, + getSectionRootClientId, + getParentSectionBlock: getParentSectionBlockFn, + } = unlock( select( blockEditorStore ) ); + + const root = getSectionRootClientId(); + return { + sectionRootClientId: root, + isZoomOut: isZoomOutSelector(), + getParentSectionBlock: getParentSectionBlockFn, + }; + }, + [] + ); // These elements are used to position the zoom out view vertical toolbar // correctly, relative to the selected section. const rootSectionElement = useBlockElement( sectionRootClientId ); - let parentSectionClientId; - if ( sectionClientIds.includes( clientId ) ) { - parentSectionClientId = clientId; - } else { - parentSectionClientId = - selectedBlockParentClientIds.find( ( parentClientId ) => - sectionClientIds.includes( parentClientId ) - ) ?? clientId; - } - - const parentSectionElement = useBlockElement( parentSectionClientId ); + const parentSectionElement = useBlockElement( + getParentSectionBlock( clientId ) ?? clientId + ); const popoverAnchor = useMemo( () => { if ( From 457db0340934ddd9d29ff2ff0c7529b2a2559e2b Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Wed, 2 Oct 2024 18:50:10 +0300 Subject: [PATCH 09/23] check if the block element exists yet before computing the anchor --- packages/block-editor/src/components/block-popover/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index d48252ba34839c..328a7d74e12a51 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -108,6 +108,7 @@ function BlockPopover( // than 0. This check is only there to satisfy the correctness of the // exhaustive-deps rule for the `useMemo` hook. popoverDimensionsRecomputeCounter < 0 || + ! rootSectionElement || ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) { From 6c3aa91c103b62fa5a42862f528e96812b4a2584 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Wed, 2 Oct 2024 18:52:15 +0300 Subject: [PATCH 10/23] check if the block element exists yet before computing the anchor --- packages/block-editor/src/components/block-popover/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 328a7d74e12a51..66f82162c36bcb 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -109,6 +109,7 @@ function BlockPopover( // exhaustive-deps rule for the `useMemo` hook. popoverDimensionsRecomputeCounter < 0 || ! rootSectionElement || + ! parentSectionElement || ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) { From 605e66075689a888f9b3fe5e7ecf34b59cc274ef Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Fri, 4 Oct 2024 10:59:44 +0300 Subject: [PATCH 11/23] differentiate between section toolbar and block toolbar for correct positioning when both are visible --- .../src/components/block-popover/index.js | 42 +++++++++++-------- .../block-tools/use-show-block-tools.js | 13 +++++- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 66f82162c36bcb..30ed77f0f1a9ab 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -77,23 +77,27 @@ function BlockPopover( }; }, [ selectedElement ] ); - const { isZoomOut, sectionRootClientId, getParentSectionBlock } = useSelect( - ( select ) => { - const { - isZoomOut: isZoomOutSelector, - getSectionRootClientId, - getParentSectionBlock: getParentSectionBlockFn, - } = unlock( select( blockEditorStore ) ); - - const root = getSectionRootClientId(); - return { - sectionRootClientId: root, - isZoomOut: isZoomOutSelector(), - getParentSectionBlock: getParentSectionBlockFn, - }; - }, - [] - ); + const { + isZoomOut, + sectionRootClientId, + getParentSectionBlock, + getBlockOrder, + } = useSelect( ( select ) => { + const { + isZoomOut: isZoomOutSelector, + getSectionRootClientId, + getParentSectionBlock: getParentSectionBlockFn, + getBlockOrder: getBlockOrderFn, + } = unlock( select( blockEditorStore ) ); + + const root = getSectionRootClientId(); + return { + sectionRootClientId: root, + isZoomOut: isZoomOutSelector(), + getParentSectionBlock: getParentSectionBlockFn, + getBlockOrder: getBlockOrderFn, + }; + }, [] ); // These elements are used to position the zoom out view vertical toolbar // correctly, relative to the selected section. @@ -101,6 +105,8 @@ function BlockPopover( const parentSectionElement = useBlockElement( getParentSectionBlock( clientId ) ?? clientId ); + const isSectionSelected = + getBlockOrder( sectionRootClientId ).includes( clientId ); const popoverAnchor = useMemo( () => { if ( @@ -123,7 +129,7 @@ function BlockPopover( // selected section. This condition changes the anchor of the toolbar // to the section instead of the block to handle blocksn that are // not full width and nested blocks to keep section height. - if ( isZoomOut ) { + if ( isZoomOut && isSectionSelected ) { // Compute the height based on the parent section of the // selected block, because the selected block may be // shorter than the section. 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 b24644de51fcc6..97737b4ec2f5b4 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 @@ -8,6 +8,7 @@ import { isUnmodifiedDefaultBlock } from '@wordpress/blocks'; * Internal dependencies */ import { store as blockEditorStore } from '../../store'; +import { unlock } from '../../lock-unlock'; /** * Source of truth for which block tools are showing in the block editor. @@ -24,7 +25,9 @@ export function useShowBlockTools() { getSettings, __unstableGetEditorMode, isTyping, - } = select( blockEditorStore ); + getBlockOrder, + getSectionRootClientId, + } = unlock( select( blockEditorStore ) ); const clientId = getSelectedBlockClientId() || getFirstMultiSelectedBlockClientId(); @@ -42,8 +45,14 @@ export function useShowBlockTools() { editorMode === 'edit' && isEmptyDefaultBlock; const isZoomOut = editorMode === 'zoom-out'; + const isSectionSelected = getBlockOrder( + getSectionRootClientId() + ).includes( clientId ); const _showZoomOutToolbar = - clientId && isZoomOut && ! _showEmptyBlockSideInserter; + clientId && + isZoomOut && + ! _showEmptyBlockSideInserter && + isSectionSelected; const _showBlockToolbarPopover = ! _showZoomOutToolbar && ! getSettings().hasFixedToolbar && From cc9ec1694630c7a9d22b19c9c960596d829a23cc Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Fri, 4 Oct 2024 12:40:54 +0300 Subject: [PATCH 12/23] address some nits --- .../src/components/block-popover/index.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 30ed77f0f1a9ab..18d96748f6036c 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -86,16 +86,15 @@ function BlockPopover( const { isZoomOut: isZoomOutSelector, getSectionRootClientId, - getParentSectionBlock: getParentSectionBlockFn, - getBlockOrder: getBlockOrderFn, + getParentSectionBlock: getParentSectionBlockSelector, + getBlockOrder: getBlockOrderSelector, } = unlock( select( blockEditorStore ) ); - const root = getSectionRootClientId(); return { - sectionRootClientId: root, + sectionRootClientId: getSectionRootClientId(), isZoomOut: isZoomOutSelector(), - getParentSectionBlock: getParentSectionBlockFn, - getBlockOrder: getBlockOrderFn, + getParentSectionBlock: getParentSectionBlockSelector, + getBlockOrder: getBlockOrderSelector, }; }, [] ); From 086fe1677216289ee942ce6efa518d218481464f Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Mon, 7 Oct 2024 09:49:58 +0300 Subject: [PATCH 13/23] make the select in anchor setting rerun when block selection changes --- .../src/components/block-popover/index.js | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 18d96748f6036c..1898d8ffb0f329 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -80,32 +80,34 @@ function BlockPopover( const { isZoomOut, sectionRootClientId, - getParentSectionBlock, - getBlockOrder, - } = useSelect( ( select ) => { - const { - isZoomOut: isZoomOutSelector, - getSectionRootClientId, - getParentSectionBlock: getParentSectionBlockSelector, - getBlockOrder: getBlockOrderSelector, - } = unlock( select( blockEditorStore ) ); - - return { - sectionRootClientId: getSectionRootClientId(), - isZoomOut: isZoomOutSelector(), - getParentSectionBlock: getParentSectionBlockSelector, - getBlockOrder: getBlockOrderSelector, - }; - }, [] ); + parentSectionBlock, + isSectionSelected, + } = useSelect( + ( select ) => { + const { + isZoomOut: isZoomOutSelector, + getSectionRootClientId, + getParentSectionBlock, + getBlockOrder, + } = unlock( select( blockEditorStore ) ); + + return { + sectionRootClientId: getSectionRootClientId(), + isZoomOut: isZoomOutSelector(), + parentSectionBlock: + getParentSectionBlock( clientId ) ?? clientId, + isSectionSelected: getBlockOrder( + getSectionRootClientId() + ).includes( clientId ), + }; + }, + [ clientId ] + ); // These elements are used to position the zoom out view vertical toolbar // correctly, relative to the selected section. const rootSectionElement = useBlockElement( sectionRootClientId ); - const parentSectionElement = useBlockElement( - getParentSectionBlock( clientId ) ?? clientId - ); - const isSectionSelected = - getBlockOrder( sectionRootClientId ).includes( clientId ); + const parentSectionElement = useBlockElement( parentSectionBlock ); const popoverAnchor = useMemo( () => { if ( From 1fb06f5162d5ccb9563357db4298b909b47f0a1a Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Mon, 7 Oct 2024 09:53:32 +0300 Subject: [PATCH 14/23] fix bug with anchor rect when zoom out not engaged --- packages/block-editor/src/components/block-popover/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 1898d8ffb0f329..061525e75b5dfb 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -115,8 +115,8 @@ function BlockPopover( // than 0. This check is only there to satisfy the correctness of the // exhaustive-deps rule for the `useMemo` hook. popoverDimensionsRecomputeCounter < 0 || - ! rootSectionElement || - ! parentSectionElement || + ( isZoomOut && ! rootSectionElement ) || + ( isZoomOut && ! parentSectionElement ) || ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) { From 7589c5d4d4bd89dac459a44889911feaab65aa98 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Mon, 7 Oct 2024 13:52:40 +0300 Subject: [PATCH 15/23] fix typo --- packages/block-editor/src/components/block-popover/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 061525e75b5dfb..93a867025dfd55 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -128,7 +128,7 @@ function BlockPopover( // The zoom out view has a vertical block toolbar that should always // be on the edge of the canvas, aligned to the top of the currently // selected section. This condition changes the anchor of the toolbar - // to the section instead of the block to handle blocksn that are + // to the section instead of the block to handle blocks that are // not full width and nested blocks to keep section height. if ( isZoomOut && isSectionSelected ) { // Compute the height based on the parent section of the From 22286ac09a254f57490b3728358483d38c373397 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 8 Oct 2024 12:04:03 +0100 Subject: [PATCH 16/23] Use root container element in post editor as popover anchor --- .../src/components/block-popover/index.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 93a867025dfd55..ba25da50f95908 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -115,7 +115,6 @@ function BlockPopover( // than 0. This check is only there to satisfy the correctness of the // exhaustive-deps rule for the `useMemo` hook. popoverDimensionsRecomputeCounter < 0 || - ( isZoomOut && ! rootSectionElement ) || ( isZoomOut && ! parentSectionElement ) || ! selectedElement || ( bottomClientId && ! lastSelectedElement ) @@ -125,17 +124,26 @@ function BlockPopover( return { getBoundingClientRect() { + let postRootElement; // The zoom out view has a vertical block toolbar that should always // be on the edge of the canvas, aligned to the top of the currently // selected section. This condition changes the anchor of the toolbar // to the section instead of the block to handle blocks that are // not full width and nested blocks to keep section height. if ( isZoomOut && isSectionSelected ) { + // if the rootSectionElement is undefined then we need to recurse up the DOM tree + // to find the element with wp-block-post-content classname + if ( ! rootSectionElement ) { + postRootElement = + selectedElement.closest( '.is-root-container' ); + } + // Compute the height based on the parent section of the // selected block, because the selected block may be // shorter than the section. - const rootSectionElementRect = - getVisibleElementBounds( rootSectionElement ); + const rootSectionElementRect = getVisibleElementBounds( + rootSectionElement || postRootElement + ); const parentSectionElementRect = getVisibleElementBounds( parentSectionElement ); const anchorHeight = From ee585e4d77035ed69396f24f17311a1d1c85cb3d Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Wed, 9 Oct 2024 10:29:16 +0300 Subject: [PATCH 17/23] improve comment --- packages/block-editor/src/components/block-popover/index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index ba25da50f95908..2e0a3b639793bf 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -132,7 +132,9 @@ function BlockPopover( // not full width and nested blocks to keep section height. if ( isZoomOut && isSectionSelected ) { // if the rootSectionElement is undefined then we need to recurse up the DOM tree - // to find the element with wp-block-post-content classname + // to find the element with ` is-root-container` classname + // FIXME: we should not rely on classnames to find the + // root section element if ( ! rootSectionElement ) { postRootElement = selectedElement.closest( '.is-root-container' ); From 97836d3e418f93d3ac3d1d8af93e6bb174010e05 Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Wed, 9 Oct 2024 14:00:00 +0300 Subject: [PATCH 18/23] improve comment to max improvement possible Co-authored-by: Dave Smith --- packages/block-editor/src/components/block-popover/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 2e0a3b639793bf..2bea0f02598f68 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -131,8 +131,9 @@ function BlockPopover( // to the section instead of the block to handle blocks that are // not full width and nested blocks to keep section height. if ( isZoomOut && isSectionSelected ) { - // if the rootSectionElement is undefined then we need to recurse up the DOM tree - // to find the element with ` is-root-container` classname + // If the rootSectionElement is undefined then recurse up the DOM tree + // to find the element with ` is-root-container` classname. + // This can then be used as the anchor point. // FIXME: we should not rely on classnames to find the // root section element if ( ! rootSectionElement ) { From dfa04be3786f9abebaab2d97062b761a57b9bfff Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Wed, 9 Oct 2024 17:39:27 +0300 Subject: [PATCH 19/23] mega nit commit Co-authored-by: Dave Smith --- packages/block-editor/src/components/block-popover/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 2bea0f02598f68..d51ad046e395f5 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -132,7 +132,7 @@ function BlockPopover( // not full width and nested blocks to keep section height. if ( isZoomOut && isSectionSelected ) { // If the rootSectionElement is undefined then recurse up the DOM tree - // to find the element with ` is-root-container` classname. + // to find the element with `is-root-container` classname. // This can then be used as the anchor point. // FIXME: we should not rely on classnames to find the // root section element From b95d7efab0a600c12a79db7cd98e9a961d546da9 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 10 Oct 2024 15:42:35 +0100 Subject: [PATCH 20/23] Fix bug with Posts with no full width blocks --- .../src/components/block-popover/index.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index d51ad046e395f5..e41bb239798263 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -132,13 +132,14 @@ function BlockPopover( // not full width and nested blocks to keep section height. if ( isZoomOut && isSectionSelected ) { // If the rootSectionElement is undefined then recurse up the DOM tree - // to find the element with `is-root-container` classname. + // to find the element with `block-editor-iframe__body` classname. // This can then be used as the anchor point. // FIXME: we should not rely on classnames to find the // root section element if ( ! rootSectionElement ) { - postRootElement = - selectedElement.closest( '.is-root-container' ); + postRootElement = selectedElement.closest( + '.block-editor-iframe__body' + ); } // Compute the height based on the parent section of the @@ -176,11 +177,14 @@ function BlockPopover( contextElement: selectedElement, }; }, [ - bottomClientId, - lastSelectedElement, - selectedElement, popoverDimensionsRecomputeCounter, isZoomOut, + parentSectionElement, + selectedElement, + bottomClientId, + lastSelectedElement, + isSectionSelected, + rootSectionElement, ] ); if ( ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) { From 9fadd3333919b34cdff5ec1749a74f0e8ab0fc4c Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Mon, 14 Oct 2024 17:46:17 +0300 Subject: [PATCH 21/23] give up on section root, always seek canvas element to position vertical toolbar, also fix typo --- .../src/components/block-popover/index.js | 40 +++++-------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index e41bb239798263..23236fcb64f3c0 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -77,12 +77,7 @@ function BlockPopover( }; }, [ selectedElement ] ); - const { - isZoomOut, - sectionRootClientId, - parentSectionBlock, - isSectionSelected, - } = useSelect( + const { isZoomOut, parentSectionBlock, isSectionSelected } = useSelect( ( select ) => { const { isZoomOut: isZoomOutSelector, @@ -92,7 +87,6 @@ function BlockPopover( } = unlock( select( blockEditorStore ) ); return { - sectionRootClientId: getSectionRootClientId(), isZoomOut: isZoomOutSelector(), parentSectionBlock: getParentSectionBlock( clientId ) ?? clientId, @@ -104,9 +98,8 @@ function BlockPopover( [ clientId ] ); - // These elements are used to position the zoom out view vertical toolbar + // This element is used to position the zoom out view vertical toolbar // correctly, relative to the selected section. - const rootSectionElement = useBlockElement( sectionRootClientId ); const parentSectionElement = useBlockElement( parentSectionBlock ); const popoverAnchor = useMemo( () => { @@ -124,30 +117,22 @@ function BlockPopover( return { getBoundingClientRect() { - let postRootElement; + // The popover should be positioned relative to the root element of the canvas. + // FIXME: This should not be accessed by classname. + const rootSectionElement = selectedElement.closest( + '.block-editor-iframe__body' + ); // The zoom out view has a vertical block toolbar that should always // be on the edge of the canvas, aligned to the top of the currently // selected section. This condition changes the anchor of the toolbar // to the section instead of the block to handle blocks that are // not full width and nested blocks to keep section height. if ( isZoomOut && isSectionSelected ) { - // If the rootSectionElement is undefined then recurse up the DOM tree - // to find the element with `block-editor-iframe__body` classname. - // This can then be used as the anchor point. - // FIXME: we should not rely on classnames to find the - // root section element - if ( ! rootSectionElement ) { - postRootElement = selectedElement.closest( - '.block-editor-iframe__body' - ); - } - // Compute the height based on the parent section of the // selected block, because the selected block may be // shorter than the section. - const rootSectionElementRect = getVisibleElementBounds( - rootSectionElement || postRootElement - ); + const rootSectionElementRect = + getVisibleElementBounds( rootSectionElement ); const parentSectionElementRect = getVisibleElementBounds( parentSectionElement ); const anchorHeight = @@ -156,13 +141,11 @@ function BlockPopover( // Always use the width of the section root element to make sure // the toolbar is always on the edge of the canvas. - const andchorWidth = - rootSectionElementRect.right - - rootSectionElementRect.left; + const anchorWidth = rootSectionElementRect.width; return new window.DOMRectReadOnly( rootSectionElementRect.left, parentSectionElementRect.top, - andchorWidth, + anchorWidth, anchorHeight ); } @@ -184,7 +167,6 @@ function BlockPopover( bottomClientId, lastSelectedElement, isSectionSelected, - rootSectionElement, ] ); if ( ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) { From 0afb084a3e4ecfd99633a92d28d58817d8f3086b Mon Sep 17 00:00:00 2001 From: Andrei Draganescu Date: Mon, 14 Oct 2024 17:51:24 +0300 Subject: [PATCH 22/23] introduce the concept of canvas via a 1st variable --- .../src/components/block-popover/index.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 23236fcb64f3c0..3740e396af52f8 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -117,9 +117,10 @@ function BlockPopover( return { getBoundingClientRect() { - // The popover should be positioned relative to the root element of the canvas. + // The popover should be positioned relative to the root element of the canvas. The canvas is the container of + // content in zoom out mode. // FIXME: This should not be accessed by classname. - const rootSectionElement = selectedElement.closest( + const canvasElement = selectedElement.closest( '.block-editor-iframe__body' ); // The zoom out view has a vertical block toolbar that should always @@ -131,8 +132,8 @@ function BlockPopover( // Compute the height based on the parent section of the // selected block, because the selected block may be // shorter than the section. - const rootSectionElementRect = - getVisibleElementBounds( rootSectionElement ); + const canvasElementRect = + getVisibleElementBounds( canvasElement ); const parentSectionElementRect = getVisibleElementBounds( parentSectionElement ); const anchorHeight = @@ -141,9 +142,9 @@ function BlockPopover( // Always use the width of the section root element to make sure // the toolbar is always on the edge of the canvas. - const anchorWidth = rootSectionElementRect.width; + const anchorWidth = canvasElementRect.width; return new window.DOMRectReadOnly( - rootSectionElementRect.left, + canvasElementRect.left, parentSectionElementRect.top, anchorWidth, anchorHeight From f5a632e15757710a2ec2343cfc28befcc885e2ff Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Mon, 14 Oct 2024 18:23:31 +0200 Subject: [PATCH 23/23] Use `__unstableContentRef` for zoomed out toolbar positioning instead of dom classname --- .../src/components/block-popover/index.js | 12 ++++-------- .../src/components/block-tools/zoom-out-popover.js | 3 ++- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/block-editor/src/components/block-popover/index.js b/packages/block-editor/src/components/block-popover/index.js index 3740e396af52f8..637ab1cb8a53e0 100644 --- a/packages/block-editor/src/components/block-popover/index.js +++ b/packages/block-editor/src/components/block-popover/index.js @@ -117,12 +117,6 @@ function BlockPopover( return { getBoundingClientRect() { - // The popover should be positioned relative to the root element of the canvas. The canvas is the container of - // content in zoom out mode. - // FIXME: This should not be accessed by classname. - const canvasElement = selectedElement.closest( - '.block-editor-iframe__body' - ); // The zoom out view has a vertical block toolbar that should always // be on the edge of the canvas, aligned to the top of the currently // selected section. This condition changes the anchor of the toolbar @@ -132,8 +126,9 @@ function BlockPopover( // Compute the height based on the parent section of the // selected block, because the selected block may be // shorter than the section. - const canvasElementRect = - getVisibleElementBounds( canvasElement ); + const canvasElementRect = getVisibleElementBounds( + __unstableContentRef.current + ); const parentSectionElementRect = getVisibleElementBounds( parentSectionElement ); const anchorHeight = @@ -168,6 +163,7 @@ function BlockPopover( bottomClientId, lastSelectedElement, isSectionSelected, + __unstableContentRef, ] ); if ( ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) { diff --git a/packages/block-editor/src/components/block-tools/zoom-out-popover.js b/packages/block-editor/src/components/block-tools/zoom-out-popover.js index a1f2990a5cc1ef..7a5c2243cf0540 100644 --- a/packages/block-editor/src/components/block-tools/zoom-out-popover.js +++ b/packages/block-editor/src/components/block-tools/zoom-out-popover.js @@ -5,7 +5,7 @@ import clsx from 'clsx'; /** * Internal dependencies */ -import BlockPopover from '../block-popover'; +import { PrivateBlockPopover as BlockPopover } from '../block-popover'; import useBlockToolbarPopoverProps from './use-block-toolbar-popover-props'; import useSelectedBlockToolProps from './use-selected-block-tool-props'; import ZoomOutToolbar from './zoom-out-toolbar'; @@ -29,6 +29,7 @@ export default function ZoomOutPopover( { clientId, __unstableContentRef } ) { return (