diff --git a/packages/block-editor/src/components/block-inspector/index.js b/packages/block-editor/src/components/block-inspector/index.js index a91c072d94cc76..2a8f7ffeb40dbc 100644 --- a/packages/block-editor/src/components/block-inspector/index.js +++ b/packages/block-editor/src/components/block-inspector/index.js @@ -12,7 +12,7 @@ import { PanelBody, __experimentalUseSlot as useSlot, } from '@wordpress/components'; -import { withSelect } from '@wordpress/data'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies @@ -29,14 +29,40 @@ import useBlockDisplayInformation from '../use-block-display-information'; import { store as blockEditorStore } from '../../store'; const BlockInspector = ( { - blockType, - count, - hasBlockStyles, - selectedBlockClientId, - selectedBlockName, showNoBlockSelectedMessage = true, bubblesVirtually = true, } ) => { + const { + count, + hasBlockStyles, + selectedBlockName, + selectedBlockClientId, + blockType, + } = useSelect( ( select ) => { + const { + getSelectedBlockClientId, + getSelectedBlockCount, + getBlockName, + } = select( blockEditorStore ); + const { getBlockStyles } = select( blocksStore ); + + const _selectedBlockClientId = getSelectedBlockClientId(); + const _selectedBlockName = + _selectedBlockClientId && getBlockName( _selectedBlockClientId ); + const _blockType = + _selectedBlockName && getBlockType( _selectedBlockName ); + const blockStyles = + _selectedBlockName && getBlockStyles( _selectedBlockName ); + + return { + count: getSelectedBlockCount(), + selectedBlockClientId: _selectedBlockClientId, + selectedBlockName: _selectedBlockName, + blockType: _blockType, + hasBlockStyles: blockStyles && blockStyles.length > 0, + }; + }, [] ); + if ( count > 1 ) { return (
@@ -133,25 +159,4 @@ const AdvancedControls = ( { slotName, bubblesVirtually } ) => { ); }; -export default withSelect( ( select ) => { - const { - getSelectedBlockClientId, - getSelectedBlockCount, - getBlockName, - } = select( blockEditorStore ); - const { getBlockStyles } = select( blocksStore ); - const selectedBlockClientId = getSelectedBlockClientId(); - const selectedBlockName = - selectedBlockClientId && getBlockName( selectedBlockClientId ); - const blockType = - selectedBlockClientId && getBlockType( selectedBlockName ); - const blockStyles = - selectedBlockClientId && getBlockStyles( selectedBlockName ); - return { - count: getSelectedBlockCount(), - hasBlockStyles: blockStyles && blockStyles.length > 0, - selectedBlockName, - selectedBlockClientId, - blockType, - }; -} )( BlockInspector ); +export default BlockInspector; diff --git a/packages/block-editor/src/components/block-styles/index.js b/packages/block-editor/src/components/block-styles/index.js index 2bcf224506e315..dd438e0bfbad66 100644 --- a/packages/block-editor/src/components/block-styles/index.js +++ b/packages/block-editor/src/components/block-styles/index.js @@ -25,17 +25,25 @@ import { getActiveStyle, replaceActiveStyle } from './utils'; import BlockPreview from '../block-preview'; import { store as blockEditorStore } from '../../store'; -const useGenericPreviewBlock = ( block, type ) => - useMemo( - () => - type.example - ? getBlockFromExample( block.name, { - attributes: type.example.attributes, - innerBlocks: type.example.innerBlocks, - } ) - : cloneBlock( block ), - [ type.example ? block.name : block, type ] - ); +const EMPTY_OBJECT = {}; + +function useGenericPreviewBlock( block, type ) { + return useMemo( () => { + const example = type?.example; + const blockName = type?.name; + + if ( example && blockName ) { + return getBlockFromExample( blockName, { + attributes: example.attributes, + innerBlocks: example.innerBlocks, + } ); + } + + if ( block ) { + return cloneBlock( block ); + } + }, [ type?.example ? block?.name : block, type ] ); +} function BlockStyles( { clientId, @@ -45,9 +53,14 @@ function BlockStyles( { } ) { const selector = ( select ) => { const { getBlock } = select( blockEditorStore ); - const { getBlockStyles } = select( blocksStore ); const block = getBlock( clientId ); + + if ( ! block ) { + return EMPTY_OBJECT; + } + const blockType = getBlockType( block.name ); + const { getBlockStyles } = select( blocksStore ); return { block, type: blockType, diff --git a/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js b/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js index d99aed303ba494..e1087a10fe3297 100644 --- a/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js +++ b/packages/e2e-tests/specs/editor/various/reusable-blocks.test.js @@ -322,4 +322,36 @@ describe( 'Reusable blocks', () => { // Check that there's only a paragraph. expect( await getEditedPostContent() ).toMatchSnapshot(); } ); + + // Test for regressions of https://github.com/WordPress/gutenberg/issues/27243. + it( 'should allow a block with styles to be converted to a reusable block', async () => { + // Insert a quote and reload the page. + insertBlock( 'Quote' ); + await saveDraft(); + await page.reload(); + + // The quote block should have a visible preview in the sidebar for this test to be valid. + const quoteBlock = await page.waitForSelector( + '.block-editor-block-list__block[aria-label="Block: Quote"]' + ); + await quoteBlock.click(); + await openDocumentSettingsSidebar(); + await page.waitForXPath( + '//*[@role="region"][@aria-label="Editor settings"]//button[.="Styles"]' + ); + + // Convert to reusable. + await clickBlockToolbarButton( 'Options' ); + await clickMenuItem( 'Add to Reusable blocks' ); + const nameInput = await page.waitForSelector( + reusableBlockNameInputSelector + ); + await nameInput.click(); + await page.keyboard.type( 'Block with styles' ); + await page.keyboard.press( 'Enter' ); + const reusableBlock = await page.waitForSelector( + '.block-editor-block-list__block[aria-label="Block: Reusable block"]' + ); + expect( reusableBlock ).toBeTruthy(); + } ); } );