From 1acd27e54045130bc9b3dcc0ed79a781db251056 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Wed, 7 Jun 2023 14:12:18 +0200 Subject: [PATCH] Block Controls SlotFill: refactor to allow passing multiple contexts, including internal components context (#51264) * SlotFill: pass array of contexts in fillProps, use it to pass components context (cherry picked from commit d7d169783b89b0838f2add86852b9cb378fdc890) * Use lock/unlock instead of exporting experimental API * Pass props object instead of just value prop * Mobile BlockControlsSlot: remove ToolbarContext teleport, the context is present anyway * Put forwardedContext into a fillProps field --------- Co-authored-by: Jarda Snajdr --- .../src/components/block-controls/fill.js | 30 +++++++------- .../src/components/block-controls/slot.js | 39 ++++++++++--------- .../components/block-controls/slot.native.js | 11 ++---- packages/components/src/private-apis.ts | 2 + 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/packages/block-editor/src/components/block-controls/fill.js b/packages/block-editor/src/components/block-controls/fill.js index 0c7464449c72d..3090cfe5e0c8c 100644 --- a/packages/block-editor/src/components/block-controls/fill.js +++ b/packages/block-editor/src/components/block-controls/fill.js @@ -3,7 +3,6 @@ */ import { __experimentalStyleProvider as StyleProvider, - __experimentalToolbarContext as ToolbarContext, ToolbarGroup, } from '@wordpress/components'; @@ -26,24 +25,25 @@ export default function BlockControlsFill( { return null; } + const innerMarkup = ( + <> + { group === 'default' && } + { children } + + ); + return ( { ( fillProps ) => { - // Children passed to BlockControlsFill will not have access to any - // React Context whose Provider is part of the BlockControlsSlot tree. - // So we re-create the Provider in this subtree. - const value = - fillProps && Object.keys( fillProps ).length > 0 - ? fillProps - : null; - return ( - - { group === 'default' && ( - - ) } - { children } - + // `fillProps.forwardedContext` is an array of context provider entries, provided by slot, + // that should wrap the fill markup. + const { forwardedContext = [] } = fillProps; + return forwardedContext.reduce( + ( inner, [ Provider, props ] ) => ( + { inner } + ), + innerMarkup ); } } diff --git a/packages/block-editor/src/components/block-controls/slot.js b/packages/block-editor/src/components/block-controls/slot.js index 65a3151552c9c..ad800b49ab40d 100644 --- a/packages/block-editor/src/components/block-controls/slot.js +++ b/packages/block-editor/src/components/block-controls/slot.js @@ -1,8 +1,9 @@ /** * WordPress dependencies */ -import { useContext } from '@wordpress/element'; +import { useContext, useMemo } from '@wordpress/element'; import { + privateApis, __experimentalToolbarContext as ToolbarContext, ToolbarGroup, __experimentalUseSlotFills as useSlotFills, @@ -13,9 +14,23 @@ import warning from '@wordpress/warning'; * Internal dependencies */ import groups from './groups'; +import { unlock } from '../../lock-unlock'; + +const { ComponentsContext } = unlock( privateApis ); export default function BlockControlsSlot( { group = 'default', ...props } ) { - const accessibleToolbarState = useContext( ToolbarContext ); + const toolbarState = useContext( ToolbarContext ); + const contextState = useContext( ComponentsContext ); + const fillProps = useMemo( + () => ( { + forwardedContext: [ + [ ToolbarContext.Provider, { value: toolbarState } ], + [ ComponentsContext.Provider, { value: contextState } ], + ], + } ), + [ toolbarState, contextState ] + ); + const Slot = groups[ group ]?.Slot; const fills = useSlotFills( Slot?.__unstableName ); if ( ! Slot ) { @@ -27,23 +42,11 @@ export default function BlockControlsSlot( { group = 'default', ...props } ) { return null; } + const slot = ; + if ( group === 'default' ) { - return ( - - ); + return slot; } - return ( - - - - ); + return { slot }; } diff --git a/packages/block-editor/src/components/block-controls/slot.native.js b/packages/block-editor/src/components/block-controls/slot.native.js index 5919972aef202..8b4e0ef25ce0d 100644 --- a/packages/block-editor/src/components/block-controls/slot.native.js +++ b/packages/block-editor/src/components/block-controls/slot.native.js @@ -1,11 +1,7 @@ /** * WordPress dependencies */ -import { useContext } from '@wordpress/element'; -import { - __experimentalToolbarContext as ToolbarContext, - ToolbarGroup, -} from '@wordpress/components'; +import { ToolbarGroup } from '@wordpress/components'; import warning from '@wordpress/warning'; /** @@ -14,7 +10,6 @@ import warning from '@wordpress/warning'; import groups from './groups'; export default function BlockControlsSlot( { group = 'default', ...props } ) { - const accessibleToolbarState = useContext( ToolbarContext ); const Slot = groups[ group ]?.Slot; if ( ! Slot ) { warning( `Unknown BlockControls group "${ group }" provided.` ); @@ -22,11 +17,11 @@ export default function BlockControlsSlot( { group = 'default', ...props } ) { } if ( group === 'default' ) { - return ; + return ; } return ( - + { ( fills ) => { if ( ! fills.length ) { return null; diff --git a/packages/components/src/private-apis.ts b/packages/components/src/private-apis.ts index 3d94ac4a44ea2..641ba5c26d40b 100644 --- a/packages/components/src/private-apis.ts +++ b/packages/components/src/private-apis.ts @@ -21,6 +21,7 @@ import { DropdownSubMenu as DropdownSubMenuV2, DropdownSubMenuTrigger as DropdownSubMenuTriggerV2, } from './dropdown-menu-v2'; +import { ComponentsContext } from './ui/context/context-system-provider'; export const { lock, unlock } = __dangerousOptInToUnstableAPIsOnlyForCoreModules( @@ -33,6 +34,7 @@ lock( privateApis, { CustomSelectControl, __experimentalPopoverLegacyPositionToPlacement, createPrivateSlotFill, + ComponentsContext, DropdownMenuV2, DropdownMenuCheckboxItemV2, DropdownMenuGroupV2,