Skip to content

Commit

Permalink
Fix focus loss after converting to a synced pattern (#55473)
Browse files Browse the repository at this point in the history
* Fix focus lost after converting to a synced pattern

* Fix for jsx
  • Loading branch information
kevin940726 authored Nov 17, 2023
1 parent 178ca84 commit c9cad59
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 24 deletions.
37 changes: 18 additions & 19 deletions packages/block-library/src/block/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,33 +114,28 @@ export default function ReusableBlockEdit( {
: InnerBlocks.ButtonBlockAppender,
} );

let children = null;
if ( hasAlreadyRendered ) {
return (
<div { ...blockProps }>
<Warning>
{ __( 'Block cannot be rendered inside itself.' ) }
</Warning>
</div>
children = (
<Warning>
{ __( 'Block cannot be rendered inside itself.' ) }
</Warning>
);
}

if ( isMissing ) {
return (
<div { ...blockProps }>
<Warning>
{ __( 'Block has been deleted or is unavailable.' ) }
</Warning>
</div>
children = (
<Warning>
{ __( 'Block has been deleted or is unavailable.' ) }
</Warning>
);
}

if ( ! hasResolved ) {
return (
<div { ...blockProps }>
<Placeholder>
<Spinner />
</Placeholder>
</div>
children = (
<Placeholder>
<Spinner />
</Placeholder>
);
}

Expand All @@ -157,7 +152,11 @@ export default function ReusableBlockEdit( {
/>
</PanelBody>
</InspectorControls>
<div { ...innerBlocksProps } />
{ children === null ? (
<div { ...innerBlocksProps } />
) : (
<div { ...blockProps }>{ children }</div>
) }
</RecursionProvider>
);
}
3 changes: 2 additions & 1 deletion packages/patterns/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import PatternsManageButton from './patterns-manage-button';
export default function PatternsMenuItems( { rootClientId } ) {
return (
<BlockSettingsMenuControls>
{ ( { selectedClientIds } ) => (
{ ( { selectedClientIds, onClose } ) => (
<>
<PatternConvertButton
clientIds={ selectedClientIds }
rootClientId={ rootClientId }
closeBlockSettingsMenu={ onClose }
/>
{ selectedClientIds.length === 1 && (
<PatternsManageButton
Expand Down
14 changes: 10 additions & 4 deletions packages/patterns/src/components/pattern-convert-button.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,17 @@ import { PATTERN_SYNC_TYPES } from '../constants';
/**
* Menu control to convert block(s) to a pattern block.
*
* @param {Object} props Component props.
* @param {string[]} props.clientIds Client ids of selected blocks.
* @param {string} props.rootClientId ID of the currently selected top-level block.
* @param {Object} props Component props.
* @param {string[]} props.clientIds Client ids of selected blocks.
* @param {string} props.rootClientId ID of the currently selected top-level block.
* @param {()=>void} props.closeBlockSettingsMenu Callback to close the block settings menu dropdown.
* @return {import('react').ComponentType} The menu control or null.
*/
export default function PatternConvertButton( { clientIds, rootClientId } ) {
export default function PatternConvertButton( {
clientIds,
rootClientId,
closeBlockSettingsMenu,
} ) {
const { createSuccessNotice } = useDispatch( noticesStore );
const { replaceBlocks } = useDispatch( blockEditorStore );
// Ignore reason: false positive of the lint rule.
Expand Down Expand Up @@ -104,6 +109,7 @@ export default function PatternConvertButton( { clientIds, rootClientId } ) {

replaceBlocks( clientIds, newBlock );
setEditingPattern( newBlock.clientId, true );
closeBlockSettingsMenu();
}

createSuccessNotice(
Expand Down
87 changes: 87 additions & 0 deletions test/e2e/specs/editor/various/patterns.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,90 @@ test.describe( 'Unsynced pattern', () => {
.toEqual( [ ...before, ...before ] );
} );
} );

test.describe( 'Synced pattern', () => {
test.beforeAll( async ( { requestUtils } ) => {
await requestUtils.deleteAllBlocks();
await requestUtils.deleteAllPatternCategories();
} );

test.beforeEach( async ( { admin } ) => {
await admin.createNewPost();
} );

test.afterEach( async ( { requestUtils } ) => {
await requestUtils.deleteAllBlocks();
await requestUtils.deleteAllPatternCategories();
} );

test( 'create a new synced pattern via the block options menu', async ( {
editor,
page,
} ) => {
await editor.insertBlock( {
name: 'core/paragraph',
attributes: { content: 'A useful paragraph to reuse' },
} );

// Create a synced pattern from the paragraph block.
await editor.showBlockToolbar();
await page
.getByRole( 'toolbar', { name: 'Block tools' } )
.getByRole( 'button', { name: 'Options' } )
.click();
await page.getByRole( 'menuitem', { name: 'Create pattern' } ).click();

const createPatternDialog = page.getByRole( 'dialog', {
name: 'Create pattern',
} );
await createPatternDialog
.getByRole( 'textbox', { name: 'Name' } )
.fill( 'My synced pattern' );
const newCategory = 'Contact details';
await createPatternDialog
.getByRole( 'combobox', { name: 'Categories' } )
.fill( newCategory );
await createPatternDialog
.getByRole( 'checkbox', { name: 'Synced' } )
.setChecked( true );

await createPatternDialog
.getByRole( 'button', { name: 'Create' } )
.click();

await expect
.poll(
editor.getBlocks,
'The block content should be wrapped by a pattern block wrapper'
)
.toEqual( [
{
name: 'core/block',
attributes: { ref: expect.any( Number ) },
innerBlocks: [],
},
] );
const after = await editor.getBlocks();

const patternBlock = editor.canvas.getByRole( 'document', {
name: 'Block: Pattern',
} );
await expect( patternBlock ).toBeFocused();

// Check that the new pattern is available in the inserter.
await page.getByLabel( 'Toggle block inserter' ).click();
await page
.getByRole( 'tab', {
name: 'Patterns',
} )
.click();
await page
.getByRole( 'button', {
name: newCategory,
} )
.click();
await page.getByRole( 'option', { name: 'My synced pattern' } ).click();

await expect.poll( editor.getBlocks ).toEqual( [ ...after, ...after ] );
} );
} );

0 comments on commit c9cad59

Please sign in to comment.