<__experimentalBlockSettingsMenuFirstItem.Slot
+ bubblesVirtually
fillProps={ { onClose } }
/>
{ count === 1 && (
diff --git a/packages/block-editor/src/components/inserter-menu-extension/index.js b/packages/block-editor/src/components/inserter-menu-extension/index.js
index c93b6fda2850b9..fa540ed82128fd 100644
--- a/packages/block-editor/src/components/inserter-menu-extension/index.js
+++ b/packages/block-editor/src/components/inserter-menu-extension/index.js
@@ -8,5 +8,7 @@ const { Fill: __experimentalInserterMenuExtension, Slot } = createSlotFill(
);
__experimentalInserterMenuExtension.Slot = Slot;
+__experimentalInserterMenuExtension.Slot.slotName =
+ '__experimentalInserterMenuExtension';
export default __experimentalInserterMenuExtension;
diff --git a/packages/block-editor/src/components/inserter/block-list.js b/packages/block-editor/src/components/inserter/block-list.js
index a1aafcd54061de..cbc75691706558 100644
--- a/packages/block-editor/src/components/inserter/block-list.js
+++ b/packages/block-editor/src/components/inserter/block-list.js
@@ -16,12 +16,15 @@ import {
* WordPress dependencies
*/
import { __, _x, _n, sprintf } from '@wordpress/i18n';
-import { withSpokenMessages } from '@wordpress/components';
+import {
+ withSpokenMessages,
+ __experimentalUseSlot as useSlot,
+} from '@wordpress/components';
import { addQueryArgs } from '@wordpress/url';
import { controlsRepeat } from '@wordpress/icons';
import { speak } from '@wordpress/a11y';
import { createBlock } from '@wordpress/blocks';
-import { useMemo, useEffect } from '@wordpress/element';
+import { useMemo, useEffect, useCallback } from '@wordpress/element';
import { useSelect } from '@wordpress/data';
import { compose } from '@wordpress/compose';
@@ -97,22 +100,25 @@ function InserterBlockList( {
}
}, [] );
- const onSelectItem = ( item ) => {
- const { name, title, initialAttributes, innerBlocks } = item;
- const insertedBlock = createBlock(
- name,
- initialAttributes,
- createBlocksFromInnerBlocksTemplate( innerBlocks )
- );
+ const onSelectItem = useCallback(
+ ( item ) => {
+ const { name, title, initialAttributes, innerBlocks } = item;
+ const insertedBlock = createBlock(
+ name,
+ initialAttributes,
+ createBlocksFromInnerBlocksTemplate( innerBlocks )
+ );
- onInsert( insertedBlock );
+ onInsert( insertedBlock );
- if ( ! selectBlockOnInsert ) {
- // translators: %s: the name of the block that has been added
- const message = sprintf( __( '%s block added' ), title );
- speak( message );
- }
- };
+ if ( ! selectBlockOnInsert ) {
+ // translators: %s: the name of the block that has been added
+ const message = sprintf( __( '%s block added' ), title );
+ speak( message );
+ }
+ },
+ [ onInsert, selectBlockOnInsert ]
+ );
const filteredItems = useMemo( () => {
return searchBlockItems( items, categories, collections, filterValue );
@@ -187,6 +193,10 @@ function InserterBlockList( {
const hasItems = ! isEmpty( filteredItems );
const hasChildItems = childItems.length > 0;
+ const slot = useSlot( __experimentalInserterMenuExtension.Slot.slotName );
+ const hasInserterExtensionFills = Boolean(
+ slot.fills && slot.fills.length
+ );
return (
@@ -272,28 +282,23 @@ function InserterBlockList( {
) }
- <__experimentalInserterMenuExtension.Slot
- fillProps={ {
- onSelect: onSelectItem,
- onHover,
- filterValue,
- hasItems,
- } }
- >
- { ( fills ) => {
- if ( fills.length ) {
- return (
-
- { fills }
-
- );
- }
- if ( ! hasItems ) {
- return ;
- }
- return null;
- } }
-
+ { hasInserterExtensionFills && ! hasItems && (
+
+ <__experimentalInserterMenuExtension.Slot
+ bubblesVirtually
+ fillProps={ {
+ onSelect: onSelectItem,
+ onHover,
+ filterValue,
+ hasItems,
+ } }
+ />
+
+ ) }
+
+ { ! hasInserterExtensionFills && ! hasItems && (
+
+ ) }
);
}
diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js
index 3d9864fc14a3e3..46219bbc271019 100644
--- a/packages/block-editor/src/components/inserter/menu.js
+++ b/packages/block-editor/src/components/inserter/menu.js
@@ -6,7 +6,7 @@ import { includes, pick } from 'lodash';
/**
* WordPress dependencies
*/
-import { useState } from '@wordpress/element';
+import { useState, useCallback } from '@wordpress/element';
import { LEFT, RIGHT, UP, DOWN, BACKSPACE, ENTER } from '@wordpress/keycodes';
import { TabPanel } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
@@ -91,7 +91,7 @@ function InserterMenu( {
// Since it's a function only called when the event handlers are called,
// it's fine to extract it.
// eslint-disable-next-line no-restricted-syntax
- function getInsertionIndex() {
+ const getInsertionIndex = useCallback( () => {
// If the clientId is defined, we insert at the position of the block.
if ( clientId ) {
return getBlockIndex( clientId, destinationRootClientId );
@@ -105,37 +105,48 @@ function InserterMenu( {
// Otherwise, we insert at the end of the current rootClientId
return getBlockOrder( destinationRootClientId ).length;
- }
+ }, [ isAppender, clientId, destinationRootClientId ] );
- const onInsertBlocks = ( blocks ) => {
- const selectedBlock = getSelectedBlock();
- if (
- ! isAppender &&
- selectedBlock &&
- isUnmodifiedDefaultBlock( selectedBlock )
- ) {
- replaceBlocks( selectedBlock.clientId, blocks );
- } else {
- insertBlocks(
- blocks,
- getInsertionIndex(),
- destinationRootClientId,
- __experimentalSelectBlockOnInsert
- );
- }
+ const onInsertBlocks = useCallback(
+ ( blocks ) => {
+ const selectedBlock = getSelectedBlock();
+ if (
+ ! isAppender &&
+ selectedBlock &&
+ isUnmodifiedDefaultBlock( selectedBlock )
+ ) {
+ replaceBlocks( selectedBlock.clientId, blocks );
+ } else {
+ insertBlocks(
+ blocks,
+ getInsertionIndex(),
+ destinationRootClientId,
+ __experimentalSelectBlockOnInsert
+ );
+ }
- onSelect();
- };
+ onSelect();
+ },
+ [
+ isAppender,
+ getInsertionIndex,
+ destinationRootClientId,
+ __experimentalSelectBlockOnInsert,
+ ]
+ );
- const onHover = ( item ) => {
- setHoveredItem( item );
- if ( item ) {
- const index = getInsertionIndex();
- showInsertionPoint( destinationRootClientId, index );
- } else {
- hideInsertionPoint();
- }
- };
+ const onHover = useCallback(
+ ( item ) => {
+ setHoveredItem( item );
+ if ( item ) {
+ const index = getInsertionIndex();
+ showInsertionPoint( destinationRootClientId, index );
+ } else {
+ hideInsertionPoint();
+ }
+ },
+ [ getInsertionIndex, destinationRootClientId ]
+ );
const blocksTab = (
<>
diff --git a/packages/block-editor/src/components/rich-text/format-toolbar/index.js b/packages/block-editor/src/components/rich-text/format-toolbar/index.js
index 3bbc0eadd680e3..6e180cfbf031c0 100644
--- a/packages/block-editor/src/components/rich-text/format-toolbar/index.js
+++ b/packages/block-editor/src/components/rich-text/format-toolbar/index.js
@@ -1,15 +1,16 @@
-/**
- * External dependencies
- */
-
-import { orderBy } from 'lodash';
-
/**
* WordPress dependencies
*/
-
import { __ } from '@wordpress/i18n';
-import { Toolbar, Slot, DropdownMenu } from '@wordpress/components';
+import {
+ Toolbar,
+ Slot,
+ Dropdown,
+ Button,
+ NavigableMenu,
+ __experimentalUseSlot as useSlot,
+} from '@wordpress/components';
+import { DOWN } from '@wordpress/keycodes';
import { chevronDown } from '@wordpress/icons';
const POPOVER_PROPS = {
@@ -18,6 +19,9 @@ const POPOVER_PROPS = {
};
const FormatToolbar = () => {
+ const slot = useSlot( 'RichText.ToolbarControls' );
+ const hasFills = Boolean( slot.fills && slot.fills.length );
+
return (
@@ -26,24 +30,48 @@ const FormatToolbar = () => {
)
) }
-
- { ( fills ) =>
- fills.length !== 0 && (
- props ),
- 'title'
- ) }
- popoverProps={ POPOVER_PROPS }
- />
- )
- }
-
+ { hasFills && (
+ {
+ const openOnArrowDown = ( event ) => {
+ if ( ! isOpen && event.keyCode === DOWN ) {
+ event.preventDefault();
+ event.stopPropagation();
+ onToggle();
+ }
+ };
+
+ return (
+
+ );
+ } }
+ renderContent={ ( { onClose } ) => (
+
+
+
+ ) }
+ />
+ ) }
);
diff --git a/packages/block-editor/src/components/rich-text/format-toolbar/index.native.js b/packages/block-editor/src/components/rich-text/format-toolbar/index.native.js
index e7be93d4b43100..771e23d37bdb64 100644
--- a/packages/block-editor/src/components/rich-text/format-toolbar/index.native.js
+++ b/packages/block-editor/src/components/rich-text/format-toolbar/index.native.js
@@ -11,6 +11,7 @@ const FormatToolbar = () => {
) ) }
diff --git a/packages/block-editor/src/components/rich-text/style.scss b/packages/block-editor/src/components/rich-text/style.scss
index cc5f2a1d379a3a..9f91a18f347f6d 100644
--- a/packages/block-editor/src/components/rich-text/style.scss
+++ b/packages/block-editor/src/components/rich-text/style.scss
@@ -64,3 +64,9 @@ figcaption.block-editor-rich-text__editable [data-rich-text-placeholder]::before
padding-right: $grid-unit-15;
}
}
+
+
+.block-editor-rich-text__advanced-toolbar-button {
+ display: flex;
+ width: 100%;
+}
diff --git a/packages/block-editor/src/components/rich-text/toolbar-button.js b/packages/block-editor/src/components/rich-text/toolbar-button.js
index e7ff63189fd92e..89cb9e7a6e6899 100644
--- a/packages/block-editor/src/components/rich-text/toolbar-button.js
+++ b/packages/block-editor/src/components/rich-text/toolbar-button.js
@@ -1,7 +1,12 @@
+/**
+ * External dependencies
+ */
+import { omit } from 'lodash';
+
/**
* WordPress dependencies
*/
-import { Fill, ToolbarButton } from '@wordpress/components';
+import { Fill, ToolbarButton, Button } from '@wordpress/components';
import { displayShortcut } from '@wordpress/keycodes';
export function RichTextToolbarButton( {
@@ -21,9 +26,31 @@ export function RichTextToolbarButton( {
shortcut = displayShortcut[ shortcutType ]( shortcutCharacter );
}
+ if ( name ) {
+ return (
+
+
+
+ );
+ }
+
return (
-
+ { ( { onClose } ) => (
+
+ ) }
);
}
diff --git a/packages/components/src/slot-fill/bubbles-virtually/slot.js b/packages/components/src/slot-fill/bubbles-virtually/slot.js
index 0483a5057e1f22..f90f8b8f8628ca 100644
--- a/packages/components/src/slot-fill/bubbles-virtually/slot.js
+++ b/packages/components/src/slot-fill/bubbles-virtually/slot.js
@@ -33,6 +33,7 @@ export default function Slot( {
// fillProps may be an update that interact with the layout, so
// we useLayoutEffect
+ // Make sure to memoize your fill Props to avoid infinite loops.
useLayoutEffect( () => {
if ( slot.fillProps && ! isShallowEqual( slot.fillProps, fillProps ) ) {
registry.updateSlot( name, ref, fillProps );
diff --git a/packages/components/src/slot-fill/index.js b/packages/components/src/slot-fill/index.js
index f24ff8134dd15b..9d0aed72c059ca 100644
--- a/packages/components/src/slot-fill/index.js
+++ b/packages/components/src/slot-fill/index.js
@@ -1,3 +1,8 @@
+/**
+ * WordPress dependencies
+ */
+import deprecated from '@wordpress/deprecated';
+
/**
* Internal dependencies
*/
@@ -12,6 +17,13 @@ export function Slot( { bubblesVirtually, ...props } ) {
if ( bubblesVirtually ) {
return ;
}
+
+ deprecated( 'Slots without event bubbling', {
+ hint:
+ "Set the bubblesVirtually prop to true for your slot and make sure it doesn't regress. On future versions, this prop will be enabled by default. Your slot name: " +
+ props.name,
+ } );
+
return ;
}
diff --git a/packages/edit-post/src/components/header/plugins-more-menu-group/index.js b/packages/edit-post/src/components/header/plugins-more-menu-group/index.js
index 50b7aa5efd69d7..89615883cda9ed 100644
--- a/packages/edit-post/src/components/header/plugins-more-menu-group/index.js
+++ b/packages/edit-post/src/components/header/plugins-more-menu-group/index.js
@@ -1,26 +1,32 @@
-/**
- * External dependencies
- */
-import { isEmpty } from 'lodash';
-
/**
* WordPress dependencies
*/
-import { createSlotFill, MenuGroup } from '@wordpress/components';
+import {
+ createSlotFill,
+ MenuGroup,
+ __experimentalUseSlot as useSlot,
+} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
const { Fill: PluginsMoreMenuGroup, Slot } = createSlotFill(
'PluginsMoreMenuGroup'
);
-PluginsMoreMenuGroup.Slot = ( { fillProps } ) => (
-
- { ( fills ) =>
- ! isEmpty( fills ) && (
- { fills }
- )
- }
-
-);
+function PluginsMoreMenuGroupSlot( { fillProps } ) {
+ const slot = useSlot( 'PluginsMoreMenuGroup' );
+ const hasFills = Boolean( slot.fills && slot.fills.length );
+
+ if ( ! hasFills ) {
+ return null;
+ }
+
+ return (
+
+
+
+ );
+}
+
+PluginsMoreMenuGroup.Slot = PluginsMoreMenuGroupSlot;
export default PluginsMoreMenuGroup;
diff --git a/packages/edit-post/src/components/header/tools-more-menu-group/index.js b/packages/edit-post/src/components/header/tools-more-menu-group/index.js
index d49db11a0b4afb..fc20661c825b84 100644
--- a/packages/edit-post/src/components/header/tools-more-menu-group/index.js
+++ b/packages/edit-post/src/components/header/tools-more-menu-group/index.js
@@ -1,26 +1,32 @@
-/**
- * External dependencies
- */
-import { isEmpty } from 'lodash';
-
/**
* WordPress dependencies
*/
-import { createSlotFill, MenuGroup } from '@wordpress/components';
+import {
+ createSlotFill,
+ MenuGroup,
+ __experimentalUseSlot as useSlot,
+} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
const { Fill: ToolsMoreMenuGroup, Slot } = createSlotFill(
'ToolsMoreMenuGroup'
);
-ToolsMoreMenuGroup.Slot = ( { fillProps } ) => (
-
- { ( fills ) =>
- ! isEmpty( fills ) && (
- { fills }
- )
- }
-
-);
+function ToolsMoreMenuGroupSlot( { fillProps } ) {
+ const slot = useSlot( 'ToolsMoreMenuGroup' );
+ const hasFills = Boolean( slot.fills && slot.fills.length );
+
+ if ( ! hasFills ) {
+ return null;
+ }
+
+ return (
+
+
+
+ );
+}
+
+ToolsMoreMenuGroup.Slot = ToolsMoreMenuGroupSlot;
export default ToolsMoreMenuGroup;
diff --git a/packages/edit-post/src/components/options-modal/index.js b/packages/edit-post/src/components/options-modal/index.js
index a4fa06cc512fca..7ce3e74b8739e6 100644
--- a/packages/edit-post/src/components/options-modal/index.js
+++ b/packages/edit-post/src/components/options-modal/index.js
@@ -49,7 +49,7 @@ export function OptionsModal( { isModalActive, isViewable, closeModal } ) {
/>
-
+
{ isViewable && (
{
My plugin post status info
-
+
).toJSON();
diff --git a/packages/edit-post/src/components/sidebar/post-status/index.js b/packages/edit-post/src/components/sidebar/post-status/index.js
index 11311e91849c2b..85da9c39d82c54 100644
--- a/packages/edit-post/src/components/sidebar/post-status/index.js
+++ b/packages/edit-post/src/components/sidebar/post-status/index.js
@@ -32,21 +32,15 @@ function PostStatus( { isOpened, onTogglePanel } ) {
opened={ isOpened }
onToggle={ onTogglePanel }
>
-
- { ( fills ) => (
- <>
-
-
-
-
-
-
-
- { fills }
-
- >
- ) }
-
+
+
+
+
+
+
+
+
+
);
}
diff --git a/packages/edit-post/src/components/sidebar/settings-sidebar/index.js b/packages/edit-post/src/components/sidebar/settings-sidebar/index.js
index befb270be4f668..81063ed3ee8a24 100644
--- a/packages/edit-post/src/components/sidebar/settings-sidebar/index.js
+++ b/packages/edit-post/src/components/sidebar/settings-sidebar/index.js
@@ -45,7 +45,7 @@ const SettingsSidebar = () => {
{ sidebarName === 'edit-post/document' && (
<>
-
+
diff --git a/packages/interface/src/components/complementary-area/index.js b/packages/interface/src/components/complementary-area/index.js
index 2a60be08d3b456..456a71b58eb40e 100644
--- a/packages/interface/src/components/complementary-area/index.js
+++ b/packages/interface/src/components/complementary-area/index.js
@@ -19,7 +19,13 @@ import ComplementaryAreaHeader from '../complementary-area-header';
import PinnedItems from '../pinned-items';
function ComplementaryAreaSlot( { scope, ...props } ) {
- return ;
+ return (
+
+ );
}
function ComplementaryAreaFill( { scope, children, className } ) {
diff --git a/packages/interface/src/components/pinned-items/index.js b/packages/interface/src/components/pinned-items/index.js
index 59fc70003095bb..7a56f0d075e095 100644
--- a/packages/interface/src/components/pinned-items/index.js
+++ b/packages/interface/src/components/pinned-items/index.js
@@ -15,7 +15,7 @@ function PinnedItems( { scope, ...props } ) {
function PinnedItemsSlot( { scope, className, ...props } ) {
return (
-
+
{ ( fills ) =>
! isEmpty( fills ) && (