diff --git a/packages/block-editor/src/components/block-controls/hook.js b/packages/block-editor/src/components/block-controls/hook.js index e3f69c8bec3b2..4e9592471cb29 100644 --- a/packages/block-editor/src/components/block-controls/hook.js +++ b/packages/block-editor/src/components/block-controls/hook.js @@ -6,14 +6,18 @@ * Internal dependencies */ import groups from './groups'; -import useDisplayBlockControls from '../use-display-block-controls'; +import { + useBlockEditContext, + mayDisplayControlsKey, + mayDisplayParentControlsKey, +} from '../block-edit/context'; export default function useBlockControlsFill( group, shareWithChildBlocks ) { - const { isDisplayed, isParentDisplayed } = useDisplayBlockControls(); - if ( isDisplayed ) { + const context = useBlockEditContext(); + if ( context[ mayDisplayControlsKey ] ) { return groups[ group ]?.Fill; } - if ( isParentDisplayed && shareWithChildBlocks ) { + if ( context[ mayDisplayParentControlsKey ] && shareWithChildBlocks ) { return groups.parent.Fill; } return null; diff --git a/packages/block-editor/src/components/block-controls/test/index.js b/packages/block-editor/src/components/block-controls/test/index.js index cbfcb3c1873a7..bbd987cbeb20e 100644 --- a/packages/block-editor/src/components/block-controls/test/index.js +++ b/packages/block-editor/src/components/block-controls/test/index.js @@ -59,7 +59,7 @@ describe( 'BlockControls', () => { it( 'should render a dynamic toolbar of controls', () => { render( - +

Child

@@ -84,7 +84,7 @@ describe( 'BlockControls', () => { it( 'should render its children', () => { render( - +

Child

@@ -99,7 +99,7 @@ describe( 'BlockControls', () => { it( 'should a dynamic toolbar when passed as children', () => { render( - + diff --git a/packages/block-editor/src/components/block-edit/context.js b/packages/block-editor/src/components/block-edit/context.js index d8b9c82948410..6b0b1af9ea22d 100644 --- a/packages/block-editor/src/components/block-edit/context.js +++ b/packages/block-editor/src/components/block-edit/context.js @@ -3,6 +3,9 @@ */ import { createContext, useContext } from '@wordpress/element'; +export const mayDisplayControlsKey = Symbol( 'mayDisplayControls' ); +export const mayDisplayParentControlsKey = Symbol( 'mayDisplayParentControls' ); + export const DEFAULT_BLOCK_EDIT_CONTEXT = { name: '', isSelected: false, diff --git a/packages/block-editor/src/components/block-edit/index.js b/packages/block-editor/src/components/block-edit/index.js index 6faefbc626192..bbef47b27c579 100644 --- a/packages/block-editor/src/components/block-edit/index.js +++ b/packages/block-editor/src/components/block-edit/index.js @@ -8,7 +8,12 @@ import { hasBlockSupport } from '@wordpress/blocks'; * Internal dependencies */ import Edit from './edit'; -import { BlockEditContextProvider, useBlockEditContext } from './context'; +import { + BlockEditContextProvider, + useBlockEditContext, + mayDisplayControlsKey, + mayDisplayParentControlsKey, +} from './context'; /** * The `useBlockEditContext` hook provides information about the block this hook is being used in. @@ -20,7 +25,13 @@ import { BlockEditContextProvider, useBlockEditContext } from './context'; */ export { useBlockEditContext }; -export default function BlockEdit( props ) { +export default function BlockEdit( { + mayDisplayControls, + mayDisplayParentControls, + // The remaining props are passed through the BlockEdit filters and are thus + // public API! + ...props +} ) { const { name, isSelected, @@ -32,19 +43,34 @@ export default function BlockEdit( props ) { const layoutSupport = hasBlockSupport( name, 'layout', false ) || hasBlockSupport( name, '__experimentalLayout', false ); - const context = { - name, - isSelected, - clientId, - layout: layoutSupport ? layout : null, - __unstableLayoutClassNames, - }; return ( context, Object.values( context ) ) } + value={ useMemo( + () => ( { + name, + isSelected, + clientId, + layout: layoutSupport ? layout : null, + __unstableLayoutClassNames, + // We use symbols in favour of an __unstable prefix to avoid + // usage outside of the package (this context is exposed). + [ mayDisplayControlsKey ]: mayDisplayControls, + [ mayDisplayParentControlsKey ]: mayDisplayParentControls, + } ), + [ + name, + isSelected, + clientId, + layoutSupport, + layout, + __unstableLayoutClassNames, + mayDisplayControls, + mayDisplayParentControls, + ] + ) } > diff --git a/packages/block-editor/src/components/block-info-slot-fill/index.js b/packages/block-editor/src/components/block-info-slot-fill/index.js index 8e16757f3ebbc..8c9503313d754 100644 --- a/packages/block-editor/src/components/block-info-slot-fill/index.js +++ b/packages/block-editor/src/components/block-info-slot-fill/index.js @@ -7,14 +7,17 @@ import { privateApis as componentsPrivateApis } from '@wordpress/components'; * Internal dependencies */ import { unlock } from '../../lock-unlock'; -import useDisplayBlockControls from '../use-display-block-controls'; +import { + useBlockEditContext, + mayDisplayControlsKey, +} from '../block-edit/context'; const { createPrivateSlotFill } = unlock( componentsPrivateApis ); const { Fill, Slot } = createPrivateSlotFill( 'BlockInformation' ); const BlockInfo = ( props ) => { - const { isDisplayed } = useDisplayBlockControls(); - if ( ! isDisplayed ) { + const context = useBlockEditContext(); + if ( ! context[ mayDisplayControlsKey ] ) { return null; } return ; diff --git a/packages/block-editor/src/components/block-list/block.js b/packages/block-editor/src/components/block-list/block.js index ff5915981acdf..b1a97237ab630 100644 --- a/packages/block-editor/src/components/block-list/block.js +++ b/packages/block-editor/src/components/block-list/block.js @@ -15,6 +15,7 @@ import { switchToBlockType, getDefaultBlockName, isUnmodifiedBlock, + store as blocksStore, } from '@wordpress/blocks'; import { withFilters } from '@wordpress/components'; import { @@ -95,21 +96,40 @@ function BlockListBlock( { themeSupportsLayout, isTemporarilyEditingAsBlocks, blockEditingMode, + mayDisplayControls, + mayDisplayParentControls, } = useSelect( ( select ) => { const { getSettings, __unstableGetTemporarilyEditingAsBlocks, getBlockEditingMode, + getBlockName, + isFirstMultiSelectedBlock, + getMultiSelectedBlockClientIds, + hasSelectedInnerBlock, } = select( blockEditorStore ); + const { hasBlockSupport } = select( blocksStore ); return { themeSupportsLayout: getSettings().supportsLayout, isTemporarilyEditingAsBlocks: __unstableGetTemporarilyEditingAsBlocks() === clientId, blockEditingMode: getBlockEditingMode( clientId ), + mayDisplayControls: + isSelected || + ( isFirstMultiSelectedBlock( clientId ) && + getMultiSelectedBlockClientIds().every( + ( id ) => getBlockName( id ) === name + ) ), + mayDisplayParentControls: + hasBlockSupport( + getBlockName( clientId ), + '__experimentalExposeControlsToChildren', + false + ) && hasSelectedInnerBlock( clientId ), }; }, - [ clientId ] + [ clientId, isSelected, name ] ); const { removeBlock } = useDispatch( blockEditorStore ); const onRemove = useCallback( () => removeBlock( clientId ), [ clientId ] ); @@ -137,6 +157,8 @@ function BlockListBlock( { __unstableParentLayout={ Object.keys( parentLayout ).length ? parentLayout : undefined } + mayDisplayControls={ mayDisplayControls } + mayDisplayParentControls={ mayDisplayParentControls } /> ); diff --git a/packages/block-editor/src/components/block-list/block.native.js b/packages/block-editor/src/components/block-list/block.native.js index 03a84d530ba12..2daaf846443b5 100644 --- a/packages/block-editor/src/components/block-list/block.native.js +++ b/packages/block-editor/src/components/block-list/block.native.js @@ -148,6 +148,7 @@ function BlockListBlock( { isDescendentBlockSelected, isParentSelected, order, + mayDisplayControls, } = useSelect( ( select ) => { const { @@ -158,6 +159,9 @@ function BlockListBlock( { getSelectedBlockClientId, getSettings, hasSelectedInnerBlock, + getBlockName, + isFirstMultiSelectedBlock, + getMultiSelectedBlockClientIds, } = select( blockEditorStore ); const currentBlockType = getBlockType( name || 'core/missing' ); const currentBlockCategory = currentBlockType?.category; @@ -205,6 +209,12 @@ function BlockListBlock( { isDescendentBlockSelected: descendentBlockSelected, isParentSelected: parentSelected, order: blockOrder, + mayDisplayControls: + isSelected || + ( isFirstMultiSelectedBlock( clientId ) && + getMultiSelectedBlockClientIds().every( + ( id ) => getBlockName( id ) === name + ) ), }; }, [ clientId, isSelected, name, rootClientId ] @@ -346,6 +356,7 @@ function BlockListBlock( { : undefined } wrapperProps={ wrapperProps } + mayDisplayControls={ mayDisplayControls } /> diff --git a/packages/block-editor/src/components/inspector-controls/fill.js b/packages/block-editor/src/components/inspector-controls/fill.js index fdb0d44f0eccb..456b33af9137f 100644 --- a/packages/block-editor/src/components/inspector-controls/fill.js +++ b/packages/block-editor/src/components/inspector-controls/fill.js @@ -12,7 +12,10 @@ import { useEffect, useContext } from '@wordpress/element'; /** * Internal dependencies */ -import useDisplayBlockControls from '../use-display-block-controls'; +import { + useBlockEditContext, + mayDisplayControlsKey, +} from '../block-edit/context'; import groups from './groups'; export default function InspectorControlsFill( { @@ -33,13 +36,13 @@ export default function InspectorControlsFill( { group = __experimentalGroup; } - const { isDisplayed } = useDisplayBlockControls(); + const context = useBlockEditContext(); const Fill = groups[ group ]?.Fill; if ( ! Fill ) { warning( `Unknown InspectorControls group "${ group }" provided.` ); return null; } - if ( ! isDisplayed ) { + if ( ! context[ mayDisplayControlsKey ] ) { return null; } diff --git a/packages/block-editor/src/components/inspector-controls/fill.native.js b/packages/block-editor/src/components/inspector-controls/fill.native.js index f1ee5a14cd18e..98b6698721e1c 100644 --- a/packages/block-editor/src/components/inspector-controls/fill.native.js +++ b/packages/block-editor/src/components/inspector-controls/fill.native.js @@ -15,7 +15,10 @@ import deprecated from '@wordpress/deprecated'; * Internal dependencies */ import groups from './groups'; -import useDisplayBlockControls from '../use-display-block-controls'; +import { + useBlockEditContext, + mayDisplayControlsKey, +} from '../block-edit/context'; import { BlockSettingsButton } from '../block-settings'; export default function InspectorControlsFill( { @@ -35,14 +38,14 @@ export default function InspectorControlsFill( { ); group = __experimentalGroup; } - const { isDisplayed } = useDisplayBlockControls(); + const context = useBlockEditContext(); const Fill = groups[ group ]?.Fill; if ( ! Fill ) { warning( `Unknown InspectorControls group "${ group }" provided.` ); return null; } - if ( ! isDisplayed ) { + if ( ! context[ mayDisplayControlsKey ] ) { return null; } diff --git a/packages/block-editor/src/components/use-display-block-controls/index.js b/packages/block-editor/src/components/use-display-block-controls/index.js deleted file mode 100644 index ef27479593a73..0000000000000 --- a/packages/block-editor/src/components/use-display-block-controls/index.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect } from '@wordpress/data'; -import { store as blocksStore } from '@wordpress/blocks'; - -/** - * Internal dependencies - */ -import { useBlockEditContext } from '../block-edit/context'; -import { store as blockEditorStore } from '../../store'; - -export default function useDisplayBlockControls() { - const { isSelected, clientId, name } = useBlockEditContext(); - return useSelect( - ( select ) => { - const { - getBlockName, - isFirstMultiSelectedBlock, - getMultiSelectedBlockClientIds, - hasSelectedInnerBlock, - } = select( blockEditorStore ); - const { hasBlockSupport } = select( blocksStore ); - - return { - isDisplayed: - isSelected || - ( isFirstMultiSelectedBlock( clientId ) && - getMultiSelectedBlockClientIds().every( - ( id ) => getBlockName( id ) === name - ) ), - isParentDisplayed: - hasBlockSupport( - getBlockName( clientId ), - '__experimentalExposeControlsToChildren', - false - ) && hasSelectedInnerBlock( clientId ), - }; - }, - [ clientId, isSelected, name ] - ); -} diff --git a/packages/block-editor/src/components/use-display-block-controls/index.native.js b/packages/block-editor/src/components/use-display-block-controls/index.native.js deleted file mode 100644 index d865ed6d9d7b2..0000000000000 --- a/packages/block-editor/src/components/use-display-block-controls/index.native.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * WordPress dependencies - */ -import { useSelect } from '@wordpress/data'; -import { hasBlockSupport } from '@wordpress/blocks'; - -/** - * Internal dependencies - */ -import { useBlockEditContext } from '../block-edit/context'; -import { store as blockEditorStore } from '../../store'; - -export default function useDisplayBlockControls() { - const { isSelected, clientId, name } = useBlockEditContext(); - return useSelect( - ( select ) => { - const { getBlockName, getBlockRootClientId } = - select( blockEditorStore ); - - const parentId = getBlockRootClientId( clientId ); - const parentBlockName = getBlockName( parentId ); - - const hideControls = hasBlockSupport( - parentBlockName, - '__experimentalHideChildBlockControls', - false - ); - - return { isDisplayed: ! hideControls && isSelected }; - }, - [ clientId, isSelected, name ] - ); -} diff --git a/packages/block-editor/src/hooks/utils.js b/packages/block-editor/src/hooks/utils.js index 76260ed0d4a63..c6076b822545a 100644 --- a/packages/block-editor/src/hooks/utils.js +++ b/packages/block-editor/src/hooks/utils.js @@ -10,7 +10,11 @@ import { addFilter } from '@wordpress/hooks'; /** * Internal dependencies */ -import useDisplayBlockControls from '../components/use-display-block-controls'; +import { + useBlockEditContext, + mayDisplayControlsKey, + mayDisplayParentControlsKey, +} from '../components/block-edit/context'; import { useSettings } from '../components'; import { useSettingsForBlockElement } from '../components/global-styles/hooks'; import { getValueFromObjectPath, setImmutably } from '../utils/object'; @@ -379,8 +383,7 @@ export function createBlockEditFilter( features ) { } ); const withBlockEditHooks = createHigherOrderComponent( ( OriginalBlockEdit ) => ( props ) => { - const { isDisplayed, isParentDisplayed } = - useDisplayBlockControls(); + const context = useBlockEditContext(); // CAUTION: code added before this line will be executed for all // blocks, not just those that support the feature! Code added // above this line should be carefully evaluated for its impact on @@ -394,8 +397,9 @@ export function createBlockEditFilter( features ) { shareWithChildBlocks, } = feature; const shouldDisplayControls = - isDisplayed || - ( isParentDisplayed && shareWithChildBlocks ); + context[ mayDisplayControlsKey ] || + ( context[ mayDisplayParentControlsKey ] && + shareWithChildBlocks ); if ( ! shouldDisplayControls || diff --git a/packages/block-library/src/cover/test/edit.native.js b/packages/block-library/src/cover/test/edit.native.js index 3ca2755ee1aeb..6925cfe3f6221 100644 --- a/packages/block-library/src/cover/test/edit.native.js +++ b/packages/block-library/src/cover/test/edit.native.js @@ -80,7 +80,13 @@ const MEDIA_OPTIONS = [ // Simplified tree to render Cover edit within slot. const CoverEdit = ( props ) => ( - + ); diff --git a/packages/format-library/src/text-color/test/index.native.js b/packages/format-library/src/text-color/test/index.native.js index 9a148dec4358b..2ff9b5edfac21 100644 --- a/packages/format-library/src/text-color/test/index.native.js +++ b/packages/format-library/src/text-color/test/index.native.js @@ -205,7 +205,7 @@ describe( 'Text color', () => { const { getByLabelText } = render( - +