Skip to content

Commit

Permalink
Block Action: Implement cut functionality in block actions and settin…
Browse files Browse the repository at this point in the history
…gs menu. (#68554)

Co-authored-by: yogeshbhutkar <[email protected]>
Co-authored-by: t-hamano <[email protected]>
Co-authored-by: carolinan <[email protected]>
Co-authored-by: afercia <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: fabiankaegy <[email protected]>
  • Loading branch information
7 people authored Feb 28, 2025
1 parent 5e7c286 commit 0d5c310
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { useDispatch, useSelect } from '@wordpress/data';
import { moreVertical } from '@wordpress/icons';
import { Children, cloneElement } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { displayShortcut } from '@wordpress/keycodes';
import { store as keyboardShortcutsStore } from '@wordpress/keyboard-shortcuts';
import { pipe, useCopyToClipboard } from '@wordpress/compose';

Expand Down Expand Up @@ -39,16 +38,27 @@ function CopyMenuItem( {
label,
shortcut,
eventType = 'copy',
__experimentalUpdateSelection: updateSelection = false,
} ) {
const { getBlocksByClientId } = useSelect( blockEditorStore );
const { removeBlocks } = useDispatch( blockEditorStore );
const notifyCopy = useNotifyCopy();
const ref = useCopyToClipboard(
() => serialize( getBlocksByClientId( clientIds ) ),
() => {
if ( onCopy && eventType === 'copy' ) {
onCopy();
switch ( eventType ) {
case 'copy':
case 'copyStyles':
onCopy();
notifyCopy( eventType, clientIds );
break;
case 'cut':
notifyCopy( eventType, clientIds );
removeBlocks( clientIds, updateSelection );
break;
default:
break;
}
notifyCopy( eventType, clientIds );
}
);
const copyMenuItemLabel = label ? label : __( 'Copy' );
Expand Down Expand Up @@ -127,6 +137,8 @@ export function BlockSettingsDropdown( {
const shortcuts = useSelect( ( select ) => {
const { getShortcutRepresentation } = select( keyboardShortcutsStore );
return {
copy: getShortcutRepresentation( 'core/block-editor/copy' ),
cut: getShortcutRepresentation( 'core/block-editor/cut' ),
duplicate: getShortcutRepresentation(
'core/block-editor/duplicate'
),
Expand Down Expand Up @@ -266,9 +278,16 @@ export function BlockSettingsDropdown( {
<CopyMenuItem
clientIds={ clientIds }
onCopy={ onCopy }
shortcut={ displayShortcut.primary(
'c'
) }
shortcut={ shortcuts.copy }
/>
<CopyMenuItem
clientIds={ clientIds }
label={ __( 'Cut' ) }
eventType="cut"
shortcut={ shortcuts.cut }
__experimentalUpdateSelection={
! __experimentalSelectBlock
}
/>
{ canDuplicate && (
<MenuItem
Expand Down
30 changes: 30 additions & 0 deletions packages/block-editor/src/components/keyboard-shortcuts/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,36 @@ function KeyboardShortcutsRegister() {
// Registering the shortcuts.
const { registerShortcut } = useDispatch( keyboardShortcutsStore );
useEffect( () => {
registerShortcut( {
name: 'core/block-editor/copy',
category: 'block',
description: __( 'Copy the selected block(s).' ),
keyCombination: {
modifier: 'primary',
character: 'c',
},
} );

registerShortcut( {
name: 'core/block-editor/cut',
category: 'block',
description: __( 'Cut the selected block(s).' ),
keyCombination: {
modifier: 'primary',
character: 'x',
},
} );

registerShortcut( {
name: 'core/block-editor/paste',
category: 'block',
description: __( 'Paste the selected block(s).' ),
keyCombination: {
modifier: 'primary',
character: 'v',
},
} );

registerShortcut( {
name: 'core/block-editor/duplicate',
category: 'block',
Expand Down
4 changes: 2 additions & 2 deletions test/e2e/specs/editor/various/write-design-mode.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ test.describe( 'Write/Design mode', () => {
.getByRole( 'menu', { name: 'Options' } )
.getByRole( 'menuitem' );

// we expect 3 items in the options menu
await expect( optionsMenu ).toHaveCount( 3 );
// we expect 4 items in the options menu
await expect( optionsMenu ).toHaveCount( 4 );

// We should be able to select the paragraph block and write in it.
await paragraph.click();
Expand Down
6 changes: 3 additions & 3 deletions test/e2e/specs/site-editor/zoom-out.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ test.describe( 'Zoom Out', () => {
await expect( fourthSectionStart ).not.toBeInViewport();
} );

test( 'Zoom out selected section has three items in options menu', async ( {
test( 'Zoom out selected section has four items in options menu', async ( {
page,
} ) => {
// open the inserter
Expand Down Expand Up @@ -263,8 +263,8 @@ test.describe( 'Zoom Out', () => {
.getByRole( 'menu', { name: 'Options' } )
.getByRole( 'menuitem' );

// we expect 3 items in the options menu
await expect( optionsMenu ).toHaveCount( 3 );
// we expect 4 items in the options menu
await expect( optionsMenu ).toHaveCount( 4 );
} );

test( 'Zoom Out cannot be activated when the section root is missing', async ( {
Expand Down

0 comments on commit 0d5c310

Please sign in to comment.