diff --git a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js
index ce059d7720a9ff..5f844b2a03668a 100644
--- a/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js
+++ b/packages/block-editor/src/components/block-settings-menu/block-settings-dropdown.js
@@ -18,7 +18,7 @@ import {
import { __, sprintf } from '@wordpress/i18n';
import {
store as keyboardShortcutsStore,
- __unstableUseShortcutEventMatch,
+ useShortcut,
} from '@wordpress/keyboard-shortcuts';
import { pipe, useCopyToClipboard } from '@wordpress/compose';
@@ -47,12 +47,51 @@ function CopyMenuItem( { blocks, onCopy, label } ) {
}
export function BlockSettingsDropdown( {
+ clientIds,
+ __experimentalSelectBlock,
+ ...props
+} ) {
+ return (
+
+ { ( blocksActionsProps ) => (
+
+ ) }
+
+ );
+}
+
+function BlockSettingsDropdownMenu( {
clientIds,
__experimentalSelectBlock,
children,
__unstableDisplayLocation,
+
+ // The following props are injected by BlockActions
+ canCopyStyles,
+ canDuplicate,
+ canInsertDefaultBlock,
+ canMove,
+ canRemove,
+ onDuplicate,
+ onInsertAfter,
+ onInsertBefore,
+ onRemove,
+ onCopy,
+ onPasteStyles,
+ onMoveTo,
+ blocks,
+
...props
} ) {
+ const scope = useRef();
const blockClientIds = Array.isArray( clientIds )
? clientIds
: [ clientIds ];
@@ -117,7 +156,6 @@ export function BlockSettingsDropdown( {
),
};
}, [] );
- const isMatch = __unstableUseShortcutEventMatch();
const { selectBlock } = useDispatch( blockEditorStore );
const hasSelectedBlocks = selectedBlockClientIds.length > 0;
@@ -158,6 +196,50 @@ export function BlockSettingsDropdown( {
getSelectedBlockClientIds,
] );
+ useShortcut(
+ 'core/block-editor/remove',
+ ( event ) => {
+ if ( event.defaultPrevented || ! canRemove ) return;
+
+ event.preventDefault();
+ updateSelectionAfterRemove( onRemove() );
+ },
+ { scope }
+ );
+
+ useShortcut(
+ 'core/block-editor/duplicate',
+ ( event ) => {
+ if ( event.defaultPrevented || ! canDuplicate ) return;
+
+ event.preventDefault();
+ updateSelectionAfterDuplicate( onDuplicate() );
+ },
+ { scope }
+ );
+
+ useShortcut(
+ 'core/block-editor/insert-after',
+ ( event ) => {
+ if ( event.defaultPrevented || ! canInsertDefaultBlock ) return;
+
+ event.preventDefault();
+ onInsertAfter();
+ },
+ { scope }
+ );
+
+ useShortcut(
+ 'core/block-editor/insert-after',
+ ( event ) => {
+ if ( event.defaultPrevented || ! canInsertDefaultBlock ) return;
+
+ event.preventDefault();
+ onInsertBefore();
+ },
+ { scope }
+ );
+
const removeBlockLabel =
count === 1 ? __( 'Delete' ) : __( 'Delete blocks' );
@@ -175,203 +257,120 @@ export function BlockSettingsDropdown( {
selectedBlockClientIds?.includes( firstParentClientId );
return (
-
- { ( {
- canCopyStyles,
- canDuplicate,
- canInsertDefaultBlock,
- canMove,
- canRemove,
- onDuplicate,
- onInsertAfter,
- onInsertBefore,
- onRemove,
- onCopy,
- onPasteStyles,
- onMoveTo,
- blocks,
- } ) => (
-
- { ( { onClose } ) => (
- <>
-
- <__unstableBlockSettingsMenuFirstItem.Slot
- fillProps={ { onClose } }
- />
- { ! parentBlockIsSelected &&
- !! firstParentClientId && (
-
- }
- onClick={ () =>
- selectBlock(
- firstParentClientId
- )
- }
- >
- { sprintf(
- /* translators: %s: Name of the block's parent. */
- __(
- 'Select parent block (%s)'
- ),
- parentBlockType.title
- ) }
-
- ) }
- { count === 1 && (
-
- ) }
-
- { canDuplicate && (
-
- ) }
- { canInsertDefaultBlock && (
- <>
-
-
- >
+ { ( { onClose } ) => (
+ <>
+
+ <__unstableBlockSettingsMenuFirstItem.Slot
+ fillProps={ { onClose } }
+ />
+ { ! parentBlockIsSelected && !! firstParentClientId && (
+
+ }
+ onClick={ () =>
+ selectBlock( firstParentClientId )
+ }
+ >
+ { sprintf(
+ /* translators: %s: Name of the block's parent. */
+ __( 'Select parent block (%s)' ),
+ parentBlockType.title
) }
-
- { canCopyStyles && (
-
-
-
-
- ) }
-
+ ) }
+ { count === 1 && (
+
+ ) }
+
+ { canDuplicate && (
+
+ ) }
+ { canInsertDefaultBlock && (
+ <>
+
+
+ >
+ ) }
+
+ { canCopyStyles && (
+
+
- { typeof children === 'function'
- ? children( { onClose } )
- : Children.map( ( child ) =>
- cloneElement( child, { onClose } )
- ) }
- { canRemove && (
-
-
-
- ) }
- >
+
+
+ ) }
+
+ { typeof children === 'function'
+ ? children( { onClose } )
+ : Children.map( ( child ) =>
+ cloneElement( child, { onClose } )
+ ) }
+ { canRemove && (
+
+
+
) }
-
+ >
) }
-
+
);
}
diff --git a/packages/block-editor/src/components/block-tools/index.js b/packages/block-editor/src/components/block-tools/index.js
index 8e3b240838fd04..8b3105ac85f6a0 100644
--- a/packages/block-editor/src/components/block-tools/index.js
+++ b/packages/block-editor/src/components/block-tools/index.js
@@ -4,7 +4,7 @@
import { useSelect, useDispatch } from '@wordpress/data';
import { useViewportMatch } from '@wordpress/compose';
import { Popover } from '@wordpress/components';
-import { __unstableUseShortcutEventMatch as useShortcutEventMatch } from '@wordpress/keyboard-shortcuts';
+import { useShortcut } from '@wordpress/keyboard-shortcuts';
import { useRef } from '@wordpress/element';
/**
@@ -45,12 +45,12 @@ export default function BlockTools( {
__unstableContentRef,
...props
} ) {
+ const scope = useRef( null );
const isLargeViewport = useViewportMatch( 'medium' );
const { hasFixedToolbar, isZoomOutMode, isTyping } = useSelect(
selector,
[]
);
- const isMatch = useShortcutEventMatch();
const { getSelectedBlockClientIds, getBlockRootClientId } =
useSelect( blockEditorStore );
const {
@@ -64,74 +64,89 @@ export default function BlockTools( {
moveBlocksDown,
} = useDispatch( blockEditorStore );
- function onKeyDown( event ) {
- if ( event.defaultPrevented ) return;
-
- if ( isMatch( 'core/block-editor/move-up', event ) ) {
+ useShortcut(
+ 'core/block-editor/move-up',
+ ( event ) => {
+ if ( event.defaultPrevented ) return;
const clientIds = getSelectedBlockClientIds();
if ( clientIds.length ) {
event.preventDefault();
const rootClientId = getBlockRootClientId( clientIds[ 0 ] );
moveBlocksUp( clientIds, rootClientId );
}
- } else if ( isMatch( 'core/block-editor/move-down', event ) ) {
- const clientIds = getSelectedBlockClientIds();
- if ( clientIds.length ) {
- event.preventDefault();
- const rootClientId = getBlockRootClientId( clientIds[ 0 ] );
- moveBlocksDown( clientIds, rootClientId );
- }
- } else if ( isMatch( 'core/block-editor/duplicate', event ) ) {
- const clientIds = getSelectedBlockClientIds();
- if ( clientIds.length ) {
- event.preventDefault();
- duplicateBlocks( clientIds );
- }
- } else if ( isMatch( 'core/block-editor/remove', event ) ) {
- const clientIds = getSelectedBlockClientIds();
- if ( clientIds.length ) {
- event.preventDefault();
- removeBlocks( clientIds );
- }
- } else if ( isMatch( 'core/block-editor/insert-after', event ) ) {
- const clientIds = getSelectedBlockClientIds();
- if ( clientIds.length ) {
- event.preventDefault();
- insertAfterBlock( clientIds[ clientIds.length - 1 ] );
- }
- } else if ( isMatch( 'core/block-editor/insert-before', event ) ) {
- const clientIds = getSelectedBlockClientIds();
- if ( clientIds.length ) {
- event.preventDefault();
- insertBeforeBlock( clientIds[ 0 ] );
- }
- } else if ( isMatch( 'core/block-editor/unselect', event ) ) {
- const clientIds = getSelectedBlockClientIds();
- if ( clientIds.length ) {
- event.preventDefault();
+ },
+ { scope }
+ );
+
+ useShortcut( 'core/block-editor/move-down', ( event ) => {
+ if ( event.defaultPrevented ) return;
+ const clientIds = getSelectedBlockClientIds();
+ if ( clientIds.length ) {
+ event.preventDefault();
+ const rootClientId = getBlockRootClientId( clientIds[ 0 ] );
+ moveBlocksDown( clientIds, rootClientId );
+ }
+ } );
+
+ useShortcut( 'core/block-editor/duplicate', ( event ) => {
+ if ( event.defaultPrevented ) return;
+ const clientIds = getSelectedBlockClientIds();
+ if ( clientIds.length ) {
+ event.preventDefault();
+ duplicateBlocks( clientIds );
+ }
+ } );
+
+ useShortcut( 'core/block-editor/remove', ( event ) => {
+ const clientIds = getSelectedBlockClientIds();
+ if ( clientIds.length ) {
+ event.preventDefault();
+ removeBlocks( clientIds );
+ }
+ } );
+
+ useShortcut( 'core/block-editor/insert-after', ( event ) => {
+ const clientIds = getSelectedBlockClientIds();
+ if ( clientIds.length ) {
+ event.preventDefault();
+ insertAfterBlock( clientIds[ clientIds.length - 1 ] );
+ }
+ } );
+
+ useShortcut( 'core/block-editor/insert-before', ( event ) => {
+ const clientIds = getSelectedBlockClientIds();
+ if ( clientIds.length ) {
+ event.preventDefault();
+ insertBeforeBlock( clientIds[ 0 ] );
+ }
+ } );
+
+ useShortcut( 'core/block-editor/unselect', ( event ) => {
+ const clientIds = getSelectedBlockClientIds();
+ if ( clientIds.length ) {
+ event.preventDefault();
- // If there is more than one block selected, select the first
- // block so that focus is directed back to the beginning of the selection.
- // In effect, to the user this feels like deselecting the multi-selection.
- if ( clientIds.length > 1 ) {
- selectBlock( clientIds[ 0 ] );
- } else {
- clearSelectedBlock();
- }
- event.target.ownerDocument.defaultView
- .getSelection()
- .removeAllRanges();
- __unstableContentRef?.current.focus();
+ // If there is more than one block selected, select the first
+ // block so that focus is directed back to the beginning of the selection.
+ // In effect, to the user this feels like deselecting the multi-selection.
+ if ( clientIds.length > 1 ) {
+ selectBlock( clientIds[ 0 ] );
+ } else {
+ clearSelectedBlock();
}
+ event.target.ownerDocument.defaultView
+ .getSelection()
+ .removeAllRanges();
+ __unstableContentRef?.current.focus();
}
- }
+ } );
const blockToolbarRef = usePopoverScroll( __unstableContentRef );
const blockToolbarAfterRef = usePopoverScroll( __unstableContentRef );
return (
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
-
+
{ ! isTyping && (
0 &&
- getSelectedBlockClientIds().length === 0;
+ // Update the selection if the original selection has been removed.
+ const shouldUpdateSelection =
+ selectedBlockClientIds.length > 0 &&
+ getSelectedBlockClientIds().length === 0;
- // If there's no previous block nor parent block, focus the first block.
- if ( ! blockToFocus ) {
- blockToFocus = getBlockOrder()[ 0 ];
- }
+ // If there's no previous block nor parent block, focus the first block.
+ if ( ! blockToFocus ) {
+ blockToFocus = getBlockOrder()[ 0 ];
+ }
+
+ updateFocusAndSelection( blockToFocus, shouldUpdateSelection );
+ }
- updateFocusAndSelection( blockToFocus, shouldUpdateSelection );
- } else if ( isMatch( 'core/block-editor/duplicate', event ) ) {
+ useShortcut( 'core/block-editor/remove', onRemoveBlock, { scope } );
+ useShortcut(
+ 'core/block-editor/duplicate',
+ async ( event ) => {
if ( event.defaultPrevented ) {
return;
}
@@ -183,9 +179,22 @@ function ListViewBlockSelectButton(
updateFocusAndSelection( updatedBlocks[ 0 ], false );
}
}
+ },
+ { scope }
+ );
+
+ async function onKeyDownHandler( event ) {
+ if ( event.keyCode === ENTER || event.keyCode === SPACE ) {
+ onClick( event );
+ } else if ( event.keyCode === BACKSPACE || event.keyCode === DELETE ) {
+ onRemoveBlock();
}
}
+ const scopeRef = useRefEffect( ( node ) => {
+ scope.current = node;
+ }, [] );
+
return (
<>