diff --git a/packages/block-editor/src/components/block-controls/fill.js b/packages/block-editor/src/components/block-controls/fill.js index 2392c3d07ee3ae..10b94728306863 100644 --- a/packages/block-editor/src/components/block-controls/fill.js +++ b/packages/block-editor/src/components/block-controls/fill.js @@ -15,18 +15,18 @@ import { /** * Internal dependencies */ -import useDisplayBlockControls from '../use-display-block-controls'; -import groups from './groups'; +import useBlockControlsFill from './hook'; export default function BlockControlsFill( { group = 'default', controls, children, + __experimentalExposeToChildren = false, } ) { - if ( ! useDisplayBlockControls() ) { + const Fill = useBlockControlsFill( group, __experimentalExposeToChildren ); + if ( ! Fill ) { return null; } - const Fill = groups[ group ].Fill; return ( diff --git a/packages/block-editor/src/components/block-controls/groups.js b/packages/block-editor/src/components/block-controls/groups.js index 42a94a4ab7a81b..9b9dfec8d8d450 100644 --- a/packages/block-editor/src/components/block-controls/groups.js +++ b/packages/block-editor/src/components/block-controls/groups.js @@ -7,12 +7,14 @@ const BlockControlsDefault = createSlotFill( 'BlockControls' ); const BlockControlsBlock = createSlotFill( 'BlockControlsBlock' ); const BlockControlsInline = createSlotFill( 'BlockFormatControls' ); const BlockControlsOther = createSlotFill( 'BlockControlsOther' ); +const BlockControlsParent = createSlotFill( 'BlockControlsParent' ); const groups = { default: BlockControlsDefault, block: BlockControlsBlock, inline: BlockControlsInline, other: BlockControlsOther, + parent: BlockControlsParent, }; export default groups; diff --git a/packages/block-editor/src/components/block-controls/hook.js b/packages/block-editor/src/components/block-controls/hook.js new file mode 100644 index 00000000000000..d907a9aad5c364 --- /dev/null +++ b/packages/block-editor/src/components/block-controls/hook.js @@ -0,0 +1,44 @@ +/** + * WordPress dependencies + */ +import { store as blocksStore } from '@wordpress/blocks'; +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import groups from './groups'; +import { store as blockEditorStore } from '../../store'; +import { useBlockEditContext } from '../block-edit/context'; +import useDisplayBlockControls from '../use-display-block-controls'; + +export default function useBlockControlsFill( group, exposeToChildren ) { + const isDisplayed = useDisplayBlockControls(); + const { clientId } = useBlockEditContext(); + const isParentDisplayed = useSelect( + ( select ) => { + const { getBlockName, hasSelectedInnerBlock } = select( + blockEditorStore + ); + const { hasBlockSupport } = select( blocksStore ); + return ( + exposeToChildren && + hasBlockSupport( + getBlockName( clientId ), + '__experimentalExposeControlsToChildren', + false + ) && + hasSelectedInnerBlock( clientId ) + ); + }, + [ exposeToChildren, clientId ] + ); + + if ( isDisplayed ) { + return groups[ group ]?.Fill; + } + if ( isParentDisplayed ) { + return groups.parent.Fill; + } + return null; +} diff --git a/packages/block-editor/src/components/block-toolbar/index.js b/packages/block-editor/src/components/block-toolbar/index.js index 599c936eeeb73a..def5b425760d10 100644 --- a/packages/block-editor/src/components/block-toolbar/index.js +++ b/packages/block-editor/src/components/block-toolbar/index.js @@ -123,6 +123,10 @@ export default function BlockToolbar( { hideDragHandle } ) { { shouldShowVisualToolbar && ( <> + { export function useInnerBlocksProps( props = {}, options = {} ) { const { clientId } = useBlockEditContext(); const isSmallScreen = useViewportMatch( 'medium', '<' ); - const hasOverlay = useSelect( + const { __experimentalCaptureToolbars, hasOverlay } = useSelect( ( select ) => { if ( ! clientId ) { - return; + return {}; } const { @@ -149,13 +153,22 @@ export function useInnerBlocksProps( props = {}, options = {} ) { hasSelectedInnerBlock, isNavigationMode, } = select( blockEditorStore ); + const blockName = getBlockName( clientId ); const enableClickThrough = isNavigationMode() || isSmallScreen; - return ( - getBlockName( clientId ) !== 'core/template' && - ! isBlockSelected( clientId ) && - ! hasSelectedInnerBlock( clientId, true ) && - enableClickThrough - ); + return { + __experimentalCaptureToolbars: select( + blocksStore + ).hasBlockSupport( + blockName, + '__experimentalExposeControlsToChildren', + false + ), + hasOverlay: + blockName !== 'core/template' && + ! isBlockSelected( clientId ) && + ! hasSelectedInnerBlock( clientId, true ) && + enableClickThrough, + }; }, [ clientId, isSmallScreen ] ); @@ -167,11 +180,14 @@ export function useInnerBlocksProps( props = {}, options = {} ) { } ), ] ); + const innerBlocksProps = { + __experimentalCaptureToolbars, + ...options, + }; const InnerBlocks = - options.value && options.onChange + innerBlocksProps.value && innerBlocksProps.onChange ? ControlledInnerBlocks : UncontrolledInnerBlocks; - return { ...props, ref, @@ -183,7 +199,7 @@ export function useInnerBlocksProps( props = {}, options = {} ) { } ), children: clientId ? ( - + ) : ( ), 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 index a3f4e7c4362f6c..605556f295b968 100644 --- a/packages/block-editor/src/components/use-display-block-controls/index.js +++ b/packages/block-editor/src/components/use-display-block-controls/index.js @@ -11,11 +11,10 @@ import { store as blockEditorStore } from '../../store'; export default function useDisplayBlockControls() { const { isSelected, clientId, name } = useBlockEditContext(); - const isFirstAndSameTypeMultiSelected = useSelect( + return useSelect( ( select ) => { - // Don't bother checking, see OR statement below. if ( isSelected ) { - return; + return true; } const { @@ -24,16 +23,14 @@ export default function useDisplayBlockControls() { getMultiSelectedBlockClientIds, } = select( blockEditorStore ); - if ( ! isFirstMultiSelectedBlock( clientId ) ) { - return false; + if ( isFirstMultiSelectedBlock( clientId ) ) { + return getMultiSelectedBlockClientIds().every( + ( id ) => getBlockName( id ) === name + ); } - return getMultiSelectedBlockClientIds().every( - ( id ) => getBlockName( id ) === name - ); + return false; }, [ clientId, isSelected, name ] ); - - return isSelected || isFirstAndSameTypeMultiSelected; } diff --git a/packages/block-editor/src/hooks/align.js b/packages/block-editor/src/hooks/align.js index 7cfd5f8b13fdef..b1e68b68bfe260 100644 --- a/packages/block-editor/src/hooks/align.js +++ b/packages/block-editor/src/hooks/align.js @@ -140,18 +140,20 @@ export const withToolbarControls = createHigherOrderComponent( props.setAttributes( { align: nextAlign } ); }; - return [ - validAlignments.length > 0 && props.isSelected && ( - - - - ), - , - ]; + return ( + <> + { validAlignments.length > 0 && ( + + + + ) } + + + ); }, 'withToolbarControls' ); diff --git a/packages/block-editor/src/hooks/duotone.js b/packages/block-editor/src/hooks/duotone.js index bf62161e1d1825..0bde4cdbe2c60e 100644 --- a/packages/block-editor/src/hooks/duotone.js +++ b/packages/block-editor/src/hooks/duotone.js @@ -140,7 +140,7 @@ function DuotonePanel( { attributes, setAttributes } ) { } return ( - + - + - +