Skip to content

Commit

Permalink
Manual cherry pick for #65627 (#66119)
Browse files Browse the repository at this point in the history
* Make zoom out vertical toolbar consistent (#65627)

* enable vertical toolbar for non full width elements, anchor based on parent

* Update packages/block-editor/src/components/block-popover/index.js

Co-authored-by: Dave Smith <[email protected]>

* Update packages/block-editor/src/components/block-popover/index.js

Co-authored-by: Dave Smith <[email protected]>

* make zoom out check a dependency of the memoization, improve code readability

* comment typos

* subscribe to state instead of calculating zoom out view state when calculating the anchor

* get the section wrapper for anchoring instead of the parent

* use a selector instead of computing on the fly the parent section

* check if the block element exists yet before computing the anchor

* check if the block element exists yet before computing the anchor

* differentiate between section toolbar and block toolbar for correct positioning when both are visible

* address some nits

* make the select in anchor setting rerun when block selection changes

* fix bug with anchor rect when zoom out not engaged

* fix typo

* Use root container element in post editor as popover anchor

* improve comment

* improve comment to max improvement possible

Co-authored-by: Dave Smith <[email protected]>

* mega nit commit

Co-authored-by: Dave Smith <[email protected]>

* Fix bug with Posts with no full width blocks

* give up on section root, always seek canvas element to position vertical toolbar, also fix typo

* introduce the concept of canvas via a 1st variable

* Use `__unstableContentRef` for zoomed out toolbar positioning instead of dom classname

---------
Co-authored-by: draganescu <[email protected]>
Co-authored-by: getdave <[email protected]>
Co-authored-by: talldan <[email protected]>
Co-authored-by: ciampo <[email protected]>
Co-authored-by: jsnajdr <[email protected]>
Co-authored-by: MaggieCabrera <[email protected]>
Co-authored-by: richtabor <[email protected]>
Co-authored-by: stokesman <[email protected]>
Co-authored-by: andrewserong <[email protected]>

* bring over two private selectors from trunk the fix depends on

---------

Co-authored-by: Dave Smith <[email protected]>
Co-authored-by: getdave <[email protected]>
Co-authored-by: talldan <[email protected]>
Co-authored-by: ciampo <[email protected]>
Co-authored-by: jsnajdr <[email protected]>
Co-authored-by: MaggieCabrera <[email protected]>
Co-authored-by: richtabor <[email protected]>
Co-authored-by: stokesman <[email protected]>
Co-authored-by: andrewserong <[email protected]>
  • Loading branch information
10 people authored Oct 17, 2024
1 parent d0dae48 commit 7ebc19a
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 6 deletions.
66 changes: 64 additions & 2 deletions packages/block-editor/src/components/block-popover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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;

Expand Down Expand Up @@ -74,12 +77,38 @@ function BlockPopover(
};
}, [ selectedElement ] );

const { isZoomOut, parentSectionBlock, isSectionSelected } = useSelect(
( select ) => {
const {
isZoomOut: isZoomOutSelector,
getSectionRootClientId,
getParentSectionBlock,
getBlockOrder,
} = unlock( select( blockEditorStore ) );

return {
isZoomOut: isZoomOutSelector(),
parentSectionBlock:
getParentSectionBlock( clientId ) ?? clientId,
isSectionSelected: getBlockOrder(
getSectionRootClientId()
).includes( clientId ),
};
},
[ clientId ]
);

// This element is used to position the zoom out view vertical toolbar
// correctly, relative to the selected section.
const parentSectionElement = useBlockElement( parentSectionBlock );

const popoverAnchor = useMemo( () => {
if (
// popoverDimensionsRecomputeCounter is by definition always equal or greater
// than 0. This check is only there to satisfy the correctness of the
// exhaustive-deps rule for the `useMemo` hook.
popoverDimensionsRecomputeCounter < 0 ||
( isZoomOut && ! parentSectionElement ) ||
! selectedElement ||
( bottomClientId && ! lastSelectedElement )
) {
Expand All @@ -88,6 +117,35 @@ function BlockPopover(

return {
getBoundingClientRect() {
// 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 ) {
// 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(
__unstableContentRef.current
);
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 anchorWidth = canvasElementRect.width;
return new window.DOMRectReadOnly(
canvasElementRect.left,
parentSectionElementRect.top,
anchorWidth,
anchorHeight
);
}

return lastSelectedElement
? rectUnion(
getVisibleElementBounds( selectedElement ),
Expand All @@ -98,10 +156,14 @@ function BlockPopover(
contextElement: selectedElement,
};
}, [
popoverDimensionsRecomputeCounter,
isZoomOut,
parentSectionElement,
selectedElement,
bottomClientId,
lastSelectedElement,
selectedElement,
popoverDimensionsRecomputeCounter,
isSectionSelected,
__unstableContentRef,
] );

if ( ! selectedElement || ( bottomClientId && ! lastSelectedElement ) ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -25,7 +26,9 @@ export function useShowBlockTools() {
hasMultiSelection,
__unstableGetEditorMode,
isTyping,
} = select( blockEditorStore );
getBlockOrder,
getSectionRootClientId,
} = unlock( select( blockEditorStore ) );

const clientId =
getSelectedBlockClientId() || getFirstMultiSelectedBlockClientId();
Expand All @@ -48,11 +51,14 @@ export function useShowBlockTools() {
editorMode === 'navigation';

const isZoomOut = editorMode === 'zoom-out';
const isSectionSelected = getBlockOrder(
getSectionRootClientId()
).includes( clientId );
const _showZoomOutToolbar =
clientId &&
isZoomOut &&
block?.attributes?.align === 'full' &&
! _showEmptyBlockSideInserter &&
! maybeShowBreadcrumb;
isSectionSelected;
const _showBlockToolbarPopover =
! _showZoomOutToolbar &&
! getSettings().hasFixedToolbar &&
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -29,6 +29,7 @@ export default function ZoomOutPopover( { clientId, __unstableContentRef } ) {

return (
<BlockPopover
__unstableContentRef={ __unstableContentRef }
clientId={ capturingClientId || clientId }
bottomClientId={ lastClientId }
className={ clsx( 'zoom-out-toolbar-popover', {
Expand Down
38 changes: 38 additions & 0 deletions packages/block-editor/src/store/private-selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
getBlockName,
getTemplateLock,
getClientIdsWithDescendants,
isNavigationMode,
} from './selectors';
import {
checkAllowListRecursive,
Expand Down Expand Up @@ -580,3 +581,40 @@ export function getZoomLevel( state ) {
export function isZoomOut( state ) {
return getZoomLevel( state ) < 100;
}

/**
* Retrieves the client ID of the parent section block.
*
* @param {Object} state Global application state.
* @param {string} clientId Client Id of the block.
*
* @return {?string} Client ID of the ancestor block that is content locking the block.
*/
export const getParentSectionBlock = ( state, clientId ) => {
let current = clientId;
let result;
while ( ! result && ( current = state.blocks.parents.get( current ) ) ) {
if ( isSectionBlock( state, current ) ) {
result = current;
}
}
return result;
};

/**
* Retrieves the client ID is a content locking parent
*
* @param {Object} state Global application state.
* @param {string} clientId Client Id of the block.
*
* @return {boolean} Whether the block is a content locking parent.
*/
export function isSectionBlock( 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 ) )
);
}

0 comments on commit 7ebc19a

Please sign in to comment.