diff --git a/packages/block-library/src/navigation/placeholder.js b/packages/block-library/src/navigation/placeholder.js index 5dbc53f7e04bfb..2ba25b7479d2fe 100644 --- a/packages/block-library/src/navigation/placeholder.js +++ b/packages/block-library/src/navigation/placeholder.js @@ -16,7 +16,13 @@ import { Placeholder, } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; -import { forwardRef, useCallback, useMemo, useState } from '@wordpress/element'; +import { + forwardRef, + useCallback, + useMemo, + useState, + useEffect, +} from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { navigation as icon } from '@wordpress/icons'; @@ -137,51 +143,11 @@ function convertPagesToBlocks( pages ) { ); } -/** - * Returns a value that indicates whether the create button should be disabled. - * - * @param {Object} selectedCreateOption An object containing details of - * the selected create option. - * @param {boolean} hasResolvedPages Indicates whether pages have loaded. - * @param {boolean} hasResolvedMenuItems Indicates whether menu items have loaded. - * - * @return {boolean} A value that indicates whether the create button is disabled. - */ -function getIsCreateButtonDisabled( - selectedCreateOption, - hasResolvedPages, - hasResolvedMenuItems -) { - // If there is no key at all then disable. - if ( ! selectedCreateOption ) { - return true; - } - - const optionKey = selectedCreateOption?.key; - - // Always disable if the default "placeholder" option is selected. - if ( optionKey === CREATE_PLACEHOLDER_VALUE ) { - return true; - } - - // Always enable if Create Empty is selected. - if ( optionKey === CREATE_EMPTY_OPTION_VALUE ) { - return false; - } - - // Enable if Pages option selected and we have Pages available. - if ( optionKey === CREATE_FROM_PAGES_OPTION_VALUE && hasResolvedPages ) { - return false; - } - - // Enable if a menu is selected and menu items have loaded. - const selectedMenu = getSelectedMenu( selectedCreateOption ); - return selectedMenu === undefined || ! hasResolvedMenuItems; -} - function NavigationPlaceholder( { onCreate }, ref ) { const [ selectedCreateOption, setSelectedCreateOption ] = useState(); + const [ isCreatingFromMenu, setIsCreatingFromMenu ] = useState( false ); + const { pages, isResolvingPages, @@ -279,38 +245,65 @@ function NavigationPlaceholder( { onCreate }, ref ) { [ menus, hasMenus, hasPages ] ); + const createFromMenu = useCallback( () => { + // If an empty menu was selected, create an empty block. + if ( ! menuItems.length ) { + const blocks = [ createBlock( 'core/navigation-link' ) ]; + onCreate( blocks ); + return; + } + + const blocks = convertMenuItemsToBlocks( menuItems ); + const selectNavigationBlock = true; + onCreate( blocks, selectNavigationBlock ); + } ); + const onCreateButtonClick = useCallback( () => { if ( ! selectedCreateOption ) { return; } const { key } = selectedCreateOption; + switch ( key ) { + case CREATE_PLACEHOLDER_VALUE: + // Do nothing. + return; + + case CREATE_EMPTY_OPTION_VALUE: { + const blocks = [ createBlock( 'core/navigation-link' ) ]; + onCreate( blocks ); + return; + } - if ( key === CREATE_FROM_PAGES_OPTION_VALUE && hasPages ) { - const blocks = convertPagesToBlocks( pages ); - const selectNavigationBlock = true; - onCreate( blocks, selectNavigationBlock ); - return; - } + case CREATE_FROM_PAGES_OPTION_VALUE: { + const blocks = convertPagesToBlocks( pages ); + const selectNavigationBlock = true; + onCreate( blocks, selectNavigationBlock ); + return; + } - if ( key === CREATE_EMPTY_OPTION_VALUE || ! menuItems?.length ) { - const blocks = [ createBlock( 'core/navigation-link' ) ]; - onCreate( blocks ); - } + // The default case indicates that a menu was selected. + default: + // If we have menu items, create the block right away. + if ( hasResolvedMenuItems ) { + createFromMenu(); + return; + } - // Infer that the user selected a menu to create from. - // If either there's no selected menu or menu items are undefined - // this is undefined behavior, do nothing. - const selectedMenu = getSelectedMenu( selectedCreateOption ); - if ( selectedMenu === undefined || menuItems === undefined ) { - return; + // Otherwise, create the block when resolution finishes. + setIsCreatingFromMenu( true ); } - - const blocks = convertMenuItemsToBlocks( menuItems ); - const selectNavigationBlock = true; - onCreate( blocks, selectNavigationBlock ); } ); + useEffect( () => { + // If the user selected a menu but we had to wait for menu items to + // finish resolving, then create the block once resolution finishes. + if ( isCreatingFromMenu && hasResolvedMenuItems ) { + createFromMenu(); + setIsCreatingFromMenu( false ); + } + }, [ isCreatingFromMenu, hasResolvedMenuItems ] ); + return ( { return { @@ -360,12 +354,13 @@ function NavigationPlaceholder( { onCreate }, ref ) {