Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix query block duplicate group block rename controls for WP 6.4 #55604

Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const emptyString = ( testString ) => testString?.trim()?.length === 0;
getdave marked this conversation as resolved.
Show resolved Hide resolved
3 changes: 3 additions & 0 deletions packages/block-editor/src/components/block-rename/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as BlockRenameControl } from './rename-control';
export { default as BlockRenameModal } from './modal';
export { default as useBlockRename } from './use-block-rename';
114 changes: 114 additions & 0 deletions packages/block-editor/src/components/block-rename/modal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* WordPress dependencies
*/
import {
__experimentalHStack as HStack,
__experimentalVStack as VStack,
Button,
TextControl,
Modal,
} from '@wordpress/components';
import { useInstanceId } from '@wordpress/compose';
import { __, sprintf } from '@wordpress/i18n';
import { useState } from '@wordpress/element';
import { speak } from '@wordpress/a11y';
/**
* Internal dependencies
*/
import { emptyString } from './empty-string';

export default function BlockRenameModal( {
blockName,
originalBlockName,
onClose,
onSave,
} ) {
const [ editedBlockName, setEditedBlockName ] = useState( blockName );

const nameHasChanged = editedBlockName !== blockName;
const nameIsOriginal = editedBlockName === originalBlockName;
const nameIsEmpty = emptyString( editedBlockName );

const isNameValid = nameHasChanged || nameIsOriginal;

const autoSelectInputText = ( event ) => event.target.select();

const dialogDescription = useInstanceId(
BlockRenameModal,
`block-editor-rename-modal__description`
);

const handleSubmit = () => {
const message =
nameIsOriginal || nameIsEmpty
? sprintf(
/* translators: %s: new name/label for the block */
__( 'Block name reset to: "%s".' ),
editedBlockName
)
: sprintf(
/* translators: %s: new name/label for the block */
__( 'Block name changed to: "%s".' ),
editedBlockName
);

// Must be assertive to immediately announce change.
speak( message, 'assertive' );
onSave( editedBlockName );

// Immediate close avoids ability to hit save multiple times.
onClose();
};

return (
<Modal
title={ __( 'Rename' ) }
onRequestClose={ onClose }
overlayClassName="block-editor-block-rename-modal"
aria={ {
describedby: dialogDescription,
} }
focusOnMount="firstContentElement"
>
<p id={ dialogDescription }>
{ __( 'Enter a custom name for this block.' ) }
</p>
<form
onSubmit={ ( e ) => {
e.preventDefault();

if ( ! isNameValid ) {
return;
}

handleSubmit();
} }
>
<VStack spacing="3">
<TextControl
__nextHasNoMarginBottom
value={ editedBlockName }
label={ __( 'Block name' ) }
hideLabelFromVision={ true }
placeholder={ originalBlockName }
onChange={ setEditedBlockName }
onFocus={ autoSelectInputText }
/>
<HStack justify="right">
<Button variant="tertiary" onClick={ onClose }>
{ __( 'Cancel' ) }
</Button>

<Button
aria-disabled={ ! isNameValid }
variant="primary"
type="submit"
>
{ __( 'Save' ) }
</Button>
</HStack>
</VStack>
</form>
</Modal>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* WordPress dependencies
*/
import { MenuItem } from '@wordpress/components';
import { useSelect, useDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { useState } from '@wordpress/element';
/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../../store';
import { useBlockDisplayInformation } from '..';
import { emptyString } from './empty-string';
import BlockRenameModal from './modal';

export default function BlockRenameControl( { clientId } ) {
const [ renamingBlock, setRenamingBlock ] = useState( false );

const { metadata } = useSelect(
( select ) => {
const { getBlockAttributes } = select( blockEditorStore );

const _metadata = getBlockAttributes( clientId )?.metadata;
return {
metadata: _metadata,
};
},
[ clientId ]
);

const { updateBlockAttributes } = useDispatch( blockEditorStore );

const customName = metadata?.name;

function onChange( newName ) {
updateBlockAttributes( [ clientId ], {
metadata: {
...( metadata && metadata ),
name: newName,
},
} );
}

const blockInformation = useBlockDisplayInformation( clientId );

return (
<>
<MenuItem
onClick={ () => {
setRenamingBlock( true );
} }
aria-expanded={ renamingBlock }
aria-haspopup="dialog"
>
{ __( 'Rename' ) }
</MenuItem>
{ renamingBlock && (
<BlockRenameModal
blockName={ customName || '' }
originalBlockName={ blockInformation?.title }
onClose={ () => setRenamingBlock( false ) }
onSave={ ( newName ) => {
// If the new value is the block's original name (e.g. `Group`)
// or it is an empty string then assume the intent is to reset
// the value. Therefore reset the metadata.
if (
newName === blockInformation?.title ||
emptyString( newName )
) {
newName = undefined;
}

onChange( newName );
} }
/>
) }
</>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.block-editor-block-rename-modal {
z-index: z-index(".block-editor-block-rename-modal");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* WordPress dependencies
*/
import { getBlockSupport } from '@wordpress/blocks';

export default function useBlockRename( name ) {
const metaDataSupport = getBlockSupport(
name,
'__experimentalMetadata',
false
);

const supportsBlockNaming = !! (
true === metaDataSupport || metaDataSupport?.name
);

return {
canRename: supportsBlockNaming,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import { BlockLockMenuItem, useBlockLock } from '../block-lock';
import { store as blockEditorStore } from '../../store';
import BlockModeToggle from '../block-settings-menu/block-mode-toggle';

import { BlockRenameControl, useBlockRename } from '../block-rename';

const { Fill, Slot } = createSlotFill( 'BlockSettingsMenuControls' );

const BlockSettingsMenuControlsSlot = ( {
Expand All @@ -44,7 +46,13 @@ const BlockSettingsMenuControlsSlot = ( {
);

const { canLock } = useBlockLock( selectedClientIds[ 0 ] );
const { canRename } = useBlockRename( selectedBlocks[ 0 ] );
const showLockButton = selectedClientIds.length === 1 && canLock;
const showRenameButton =
selectedClientIds.length === 1 &&
// Todo confirm whether following conditional is needed anymore.
// clientId === selectedClientIds[ 0 ] &&
canRename;
mikachan marked this conversation as resolved.
Show resolved Hide resolved

// Check if current selection of blocks is Groupable or Ungroupable
// and pass this props down to ConvertToGroupButton.
Expand Down Expand Up @@ -84,6 +92,11 @@ const BlockSettingsMenuControlsSlot = ( {
clientId={ selectedClientIds[ 0 ] }
/>
) }
{ showRenameButton && (
<BlockRenameControl
clientId={ selectedClientIds[ 0 ] }
/>
) }
{ fills }
{ fillProps?.canMove && ! fillProps?.onlyBlock && (
<MenuItem
Expand Down
Loading
Loading