Skip to content

Commit

Permalink
Block Controls SlotFill: refactor to allow passing multiple contexts,…
Browse files Browse the repository at this point in the history
… 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 <jsnajdr@gmail.com>
  • Loading branch information
ciampo and jsnajdr authored Jun 7, 2023
1 parent a191930 commit 1acd27e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 41 deletions.
30 changes: 15 additions & 15 deletions packages/block-editor/src/components/block-controls/fill.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*/
import {
__experimentalStyleProvider as StyleProvider,
__experimentalToolbarContext as ToolbarContext,
ToolbarGroup,
} from '@wordpress/components';

Expand All @@ -26,24 +25,25 @@ export default function BlockControlsFill( {
return null;
}

const innerMarkup = (
<>
{ group === 'default' && <ToolbarGroup controls={ controls } /> }
{ children }
</>
);

return (
<StyleProvider document={ document }>
<Fill>
{ ( 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 (
<ToolbarContext.Provider value={ value }>
{ group === 'default' && (
<ToolbarGroup controls={ controls } />
) }
{ children }
</ToolbarContext.Provider>
// `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 ] ) => (
<Provider { ...props }>{ inner }</Provider>
),
innerMarkup
);
} }
</Fill>
Expand Down
39 changes: 21 additions & 18 deletions packages/block-editor/src/components/block-controls/slot.js
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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 ) {
Expand All @@ -27,23 +42,11 @@ export default function BlockControlsSlot( { group = 'default', ...props } ) {
return null;
}

const slot = <Slot { ...props } bubblesVirtually fillProps={ fillProps } />;

if ( group === 'default' ) {
return (
<Slot
{ ...props }
bubblesVirtually
fillProps={ accessibleToolbarState }
/>
);
return slot;
}

return (
<ToolbarGroup>
<Slot
{ ...props }
bubblesVirtually
fillProps={ accessibleToolbarState }
/>
</ToolbarGroup>
);
return <ToolbarGroup>{ slot }</ToolbarGroup>;
}
Original file line number Diff line number Diff line change
@@ -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';

/**
Expand All @@ -14,19 +10,18 @@ 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.` );
return null;
}

if ( group === 'default' ) {
return <Slot { ...props } fillProps={ accessibleToolbarState } />;
return <Slot { ...props } />;
}

return (
<Slot { ...props } fillProps={ accessibleToolbarState }>
<Slot { ...props }>
{ ( fills ) => {
if ( ! fills.length ) {
return null;
Expand Down
2 changes: 2 additions & 0 deletions packages/components/src/private-apis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -33,6 +34,7 @@ lock( privateApis, {
CustomSelectControl,
__experimentalPopoverLegacyPositionToPlacement,
createPrivateSlotFill,
ComponentsContext,
DropdownMenuV2,
DropdownMenuCheckboxItemV2,
DropdownMenuGroupV2,
Expand Down

0 comments on commit 1acd27e

Please sign in to comment.