diff --git a/packages/block-editor/src/components/block-settings-menu-controls/index.js b/packages/block-editor/src/components/block-settings-menu-controls/index.js index 310d295b3dca52..e6d37bb0ca2392 100644 --- a/packages/block-editor/src/components/block-settings-menu-controls/index.js +++ b/packages/block-editor/src/components/block-settings-menu-controls/index.js @@ -1,12 +1,16 @@ /** * External dependencies */ -import { isEmpty, map } from 'lodash'; +import { map } from 'lodash'; /** * WordPress dependencies */ -import { createSlotFill, MenuGroup } from '@wordpress/components'; +import { + createSlotFill, + MenuGroup, + __experimentalUseSlot as useSlot, +} from '@wordpress/components'; import { useSelect } from '@wordpress/data'; const { Fill: BlockSettingsMenuControls, Slot } = createSlotFill( @@ -25,13 +29,20 @@ const BlockSettingsMenuControlsSlot = ( { fillProps } ) => { ), }; }, [] ); + const slot = useSlot( 'BlockSettingsMenuControls' ); + const hasFills = Boolean( slot.fills && slot.fills.length ); + + if ( ! hasFills ) { + return null; + } return ( - - { ( fills ) => - ! isEmpty( fills ) && { fills } - } - + + + ); }; diff --git a/packages/block-editor/src/components/block-settings-menu/index.js b/packages/block-editor/src/components/block-settings-menu/index.js index e4c2c64682a32f..0329fa23b8788d 100644 --- a/packages/block-editor/src/components/block-settings-menu/index.js +++ b/packages/block-editor/src/components/block-settings-menu/index.js @@ -78,6 +78,7 @@ export function BlockSettingsMenu( { clientIds } ) { <> <__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 ( +
); 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 ) && (