diff --git a/package-lock.json b/package-lock.json index 98f12be61be58..68ee222ddb1be 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53316,6 +53316,7 @@ "@wordpress/icons": "file:../icons", "@wordpress/interactivity": "file:../interactivity", "@wordpress/interactivity-router": "file:../interactivity-router", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", "@wordpress/keycodes": "file:../keycodes", "@wordpress/notices": "file:../notices", "@wordpress/patterns": "file:../patterns", @@ -68634,6 +68635,7 @@ "@wordpress/icons": "file:../icons", "@wordpress/interactivity": "file:../interactivity", "@wordpress/interactivity-router": "file:../interactivity-router", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", "@wordpress/keycodes": "file:../keycodes", "@wordpress/notices": "file:../notices", "@wordpress/patterns": "file:../patterns", diff --git a/packages/block-library/package.json b/packages/block-library/package.json index 68b1695d38837..c4cded1866a73 100644 --- a/packages/block-library/package.json +++ b/packages/block-library/package.json @@ -52,6 +52,7 @@ "@wordpress/icons": "file:../icons", "@wordpress/interactivity": "file:../interactivity", "@wordpress/interactivity-router": "file:../interactivity-router", + "@wordpress/keyboard-shortcuts": "file:../keyboard-shortcuts", "@wordpress/keycodes": "file:../keycodes", "@wordpress/notices": "file:../notices", "@wordpress/patterns": "file:../patterns", diff --git a/packages/block-library/src/block-keyboard-shortcuts/index.js b/packages/block-library/src/block-keyboard-shortcuts/index.js new file mode 100644 index 0000000000000..7f9429e376d79 --- /dev/null +++ b/packages/block-library/src/block-keyboard-shortcuts/index.js @@ -0,0 +1,96 @@ +/** + * WordPress dependencies + */ +import { useEffect } from '@wordpress/element'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { + useShortcut, + store as keyboardShortcutsStore, +} from '@wordpress/keyboard-shortcuts'; +import { __ } from '@wordpress/i18n'; +import { createBlock } from '@wordpress/blocks'; +import { store as blockEditorStore } from '@wordpress/block-editor'; + +function BlockKeyboardShortcuts() { + const { registerShortcut } = useDispatch( keyboardShortcutsStore ); + const { replaceBlocks } = useDispatch( blockEditorStore ); + const { getBlockName, getSelectedBlockClientId, getBlockAttributes } = + useSelect( blockEditorStore ); + + const handleTransformHeadingAndParagraph = ( event, level ) => { + event.preventDefault(); + const destinationBlockName = + level === 0 ? 'core/paragraph' : 'core/heading'; + const currentClientId = getSelectedBlockClientId(); + if ( currentClientId === null ) { + return; + } + const blockName = getBlockName( currentClientId ); + if ( blockName !== 'core/paragraph' && blockName !== 'core/heading' ) { + return; + } + const attributes = getBlockAttributes( currentClientId ); + const textAlign = + blockName === 'core/paragraph' ? 'align' : 'textAlign'; + const destinationTextAlign = + destinationBlockName === 'core/paragraph' ? 'align' : 'textAlign'; + + replaceBlocks( + currentClientId, + createBlock( destinationBlockName, { + level, + content: attributes.content, + ...{ [ destinationTextAlign ]: attributes[ textAlign ] }, + } ) + ); + }; + + useEffect( () => { + registerShortcut( { + name: 'core/block-editor/transform-heading-to-paragraph', + category: 'block-library', + description: __( 'Transform heading to paragraph.' ), + keyCombination: { + modifier: 'access', + character: '0', + }, + aliases: [ + { + modifier: 'access', + character: '7', + }, + ], + } ); + + [ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => { + registerShortcut( { + name: `core/block-editor/transform-paragraph-to-heading-${ level }`, + category: 'block-library', + description: __( 'Transform paragraph to heading.' ), + keyCombination: { + modifier: 'access', + character: `${ level }`, + }, + } ); + } ); + }, [] ); + + useShortcut( + 'core/block-editor/transform-heading-to-paragraph', + ( event ) => handleTransformHeadingAndParagraph( event, 0 ) + ); + + [ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => { + //the loop is based off on a constant therefore + //the hook will execute the same way every time + //eslint-disable-next-line react-hooks/rules-of-hooks + useShortcut( + `core/block-editor/transform-paragraph-to-heading-${ level }`, + ( event ) => handleTransformHeadingAndParagraph( event, level ) + ); + } ); + + return null; +} + +export default BlockKeyboardShortcuts; diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index e2e0fd9e414ef..9cb2f44d05eb9 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -330,3 +330,5 @@ export const __experimentalRegisterExperimentalCoreBlocks = process.env .forEach( ( { init } ) => init() ); } : undefined; + +export { privateApis } from './private-apis'; diff --git a/packages/block-library/src/private-apis.js b/packages/block-library/src/private-apis.js new file mode 100644 index 0000000000000..3cee106895d6d --- /dev/null +++ b/packages/block-library/src/private-apis.js @@ -0,0 +1,13 @@ +/** + * Internal dependencies + */ +import { default as BlockKeyboardShortcuts } from './block-keyboard-shortcuts'; +import { lock } from './lock-unlock'; + +/** + * @private + */ +export const privateApis = {}; +lock( privateApis, { + BlockKeyboardShortcuts, +} ); diff --git a/packages/customize-widgets/src/components/keyboard-shortcut-help-modal/config.js b/packages/customize-widgets/src/components/keyboard-shortcut-help-modal/config.js index 4edf46204c75a..0380028aa100c 100644 --- a/packages/customize-widgets/src/components/keyboard-shortcut-help-modal/config.js +++ b/packages/customize-widgets/src/components/keyboard-shortcut-help-modal/config.js @@ -37,7 +37,16 @@ export const textFormattingShortcuts = [ description: __( 'Make the selected text inline code.' ), }, { - keyCombination: { modifier: 'access', character: '0' }, + keyCombination: { + modifier: 'access', + character: '0', + }, + aliases: [ + { + modifier: 'access', + character: '7', + }, + ], description: __( 'Convert the current heading to a paragraph.' ), }, { diff --git a/packages/customize-widgets/src/components/keyboard-shortcuts/index.js b/packages/customize-widgets/src/components/keyboard-shortcuts/index.js index b7cdc1d42de86..5c5f3ea2bca83 100644 --- a/packages/customize-widgets/src/components/keyboard-shortcuts/index.js +++ b/packages/customize-widgets/src/components/keyboard-shortcuts/index.js @@ -7,44 +7,10 @@ import { store as keyboardShortcutsStore, } from '@wordpress/keyboard-shortcuts'; import { isAppleOS } from '@wordpress/keycodes'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; -import { store as blockEditorStore } from '@wordpress/block-editor'; -import { createBlock } from '@wordpress/blocks'; function KeyboardShortcuts( { undo, redo, save } ) { - const { replaceBlocks } = useDispatch( blockEditorStore ); - const { getBlockName, getSelectedBlockClientId, getBlockAttributes } = - useSelect( blockEditorStore ); - - const handleTextLevelShortcut = ( event, level ) => { - event.preventDefault(); - const destinationBlockName = - level === 0 ? 'core/paragraph' : 'core/heading'; - const currentClientId = getSelectedBlockClientId(); - if ( currentClientId === null ) { - return; - } - const blockName = getBlockName( currentClientId ); - if ( blockName !== 'core/paragraph' && blockName !== 'core/heading' ) { - return; - } - const attributes = getBlockAttributes( currentClientId ); - const textAlign = - blockName === 'core/paragraph' ? 'align' : 'textAlign'; - const destinationTextAlign = - destinationBlockName === 'core/paragraph' ? 'align' : 'textAlign'; - - replaceBlocks( - currentClientId, - createBlock( destinationBlockName, { - level, - content: attributes.content, - ...{ [ destinationTextAlign ]: attributes[ textAlign ] }, - } ) - ); - }; - useShortcut( 'core/customize-widgets/undo', ( event ) => { undo(); event.preventDefault(); @@ -60,21 +26,6 @@ function KeyboardShortcuts( { undo, redo, save } ) { save(); } ); - useShortcut( - 'core/customize-widgets/transform-heading-to-paragraph', - ( event ) => handleTextLevelShortcut( event, 0 ) - ); - - [ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => { - //the loop is based off on a constant therefore - //the hook will execute the same way every time - //eslint-disable-next-line react-hooks/rules-of-hooks - useShortcut( - `core/customize-widgets/transform-paragraph-to-heading-${ level }`, - ( event ) => handleTextLevelShortcut( event, level ) - ); - } ); - return null; } @@ -126,28 +77,6 @@ function KeyboardShortcutsRegister() { }, } ); - registerShortcut( { - name: 'core/customize-widgets/transform-heading-to-paragraph', - category: 'block-library', - description: __( 'Transform heading to paragraph.' ), - keyCombination: { - modifier: 'access', - character: `0`, - }, - } ); - - [ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => { - registerShortcut( { - name: `core/customize-widgets/transform-paragraph-to-heading-${ level }`, - category: 'block-library', - description: __( 'Transform paragraph to heading.' ), - keyCombination: { - modifier: 'access', - character: `${ level }`, - }, - } ); - } ); - return () => { unregisterShortcut( 'core/customize-widgets/undo' ); unregisterShortcut( 'core/customize-widgets/redo' ); diff --git a/packages/customize-widgets/src/components/sidebar-block-editor/index.js b/packages/customize-widgets/src/components/sidebar-block-editor/index.js index 80deb12dfcf74..a42ec50097bcb 100644 --- a/packages/customize-widgets/src/components/sidebar-block-editor/index.js +++ b/packages/customize-widgets/src/components/sidebar-block-editor/index.js @@ -14,6 +14,7 @@ import { } from '@wordpress/block-editor'; import { uploadMedia } from '@wordpress/media-utils'; import { store as preferencesStore } from '@wordpress/preferences'; +import { privateApis as blockLibraryPrivateApis } from '@wordpress/block-library'; /** * Internal dependencies @@ -31,6 +32,8 @@ const { ExperimentalBlockCanvas: BlockCanvas } = unlock( blockEditorPrivateApis ); +const { BlockKeyboardShortcuts } = unlock( blockLibraryPrivateApis ); + export default function SidebarBlockEditor( { blockEditorSettings, sidebar, @@ -99,6 +102,7 @@ export default function SidebarBlockEditor( { return ( <> + { - event.preventDefault(); - const destinationBlockName = - level === 0 ? 'core/paragraph' : 'core/heading'; - const currentClientId = getSelectedBlockClientId(); - if ( currentClientId === null ) { - return; - } - const blockName = getBlockName( currentClientId ); - if ( blockName !== 'core/paragraph' && blockName !== 'core/heading' ) { - return; - } - const attributes = getBlockAttributes( currentClientId ); - const textAlign = - blockName === 'core/paragraph' ? 'align' : 'textAlign'; - const destinationTextAlign = - destinationBlockName === 'core/paragraph' ? 'align' : 'textAlign'; - - replaceBlocks( - currentClientId, - createBlock( destinationBlockName, { - level, - content: attributes.content, - ...{ [ destinationTextAlign ]: attributes[ textAlign ] }, - } ) - ); - }; useEffect( () => { registerShortcut( { @@ -97,48 +64,12 @@ function KeyboardShortcuts() { }, ], } ); - - registerShortcut( { - name: 'core/edit-post/transform-heading-to-paragraph', - category: 'block-library', - description: __( 'Transform heading to paragraph.' ), - keyCombination: { - modifier: 'access', - character: `0`, - }, - } ); - - [ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => { - registerShortcut( { - name: `core/edit-post/transform-paragraph-to-heading-${ level }`, - category: 'block-library', - description: __( 'Transform paragraph to heading.' ), - keyCombination: { - modifier: 'access', - character: `${ level }`, - }, - } ); - } ); }, [] ); useShortcut( 'core/edit-post/toggle-fullscreen', () => { toggleFeature( 'fullscreenMode' ); } ); - useShortcut( 'core/edit-post/transform-heading-to-paragraph', ( event ) => - handleTextLevelShortcut( event, 0 ) - ); - - [ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => { - //the loop is based off on a constant therefore - //the hook will execute the same way every time - //eslint-disable-next-line react-hooks/rules-of-hooks - useShortcut( - `core/edit-post/transform-paragraph-to-heading-${ level }`, - ( event ) => handleTextLevelShortcut( event, level ) - ); - } ); - return null; } diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js index 09a08da149ee0..6169e38122a0b 100644 --- a/packages/edit-post/src/components/layout/index.js +++ b/packages/edit-post/src/components/layout/index.js @@ -34,6 +34,7 @@ import { store as noticesStore } from '@wordpress/notices'; import { store as preferencesStore } from '@wordpress/preferences'; import { privateApis as commandsPrivateApis } from '@wordpress/commands'; import { privateApis as coreCommandsPrivateApis } from '@wordpress/core-commands'; +import { privateApis as blockLibraryPrivateApis } from '@wordpress/block-library'; /** * Internal dependencies @@ -64,6 +65,7 @@ const { InterfaceSkeleton, interfaceStore, } = unlock( editorPrivateApis ); +const { BlockKeyboardShortcuts } = unlock( blockLibraryPrivateApis ); const interfaceLabels = { /* translators: accessibility text for the editor top bar landmark region. */ @@ -286,6 +288,7 @@ function Layout( { initialPost } ) { + - + ) } diff --git a/packages/edit-site/src/components/keyboard-shortcuts/edit-mode.js b/packages/edit-site/src/components/keyboard-shortcuts/edit-mode.js deleted file mode 100644 index 597cde29e9f27..0000000000000 --- a/packages/edit-site/src/components/keyboard-shortcuts/edit-mode.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * WordPress dependencies - */ -import { useShortcut } from '@wordpress/keyboard-shortcuts'; -import { useDispatch, useSelect } from '@wordpress/data'; -import { store as blockEditorStore } from '@wordpress/block-editor'; -import { createBlock } from '@wordpress/blocks'; - -function KeyboardShortcutsEditMode() { - const { replaceBlocks } = useDispatch( blockEditorStore ); - const { getBlockName, getSelectedBlockClientId, getBlockAttributes } = - useSelect( blockEditorStore ); - - const handleTextLevelShortcut = ( event, level ) => { - event.preventDefault(); - const destinationBlockName = - level === 0 ? 'core/paragraph' : 'core/heading'; - const currentClientId = getSelectedBlockClientId(); - if ( currentClientId === null ) { - return; - } - const blockName = getBlockName( currentClientId ); - if ( blockName !== 'core/paragraph' && blockName !== 'core/heading' ) { - return; - } - const attributes = getBlockAttributes( currentClientId ); - const textAlign = - blockName === 'core/paragraph' ? 'align' : 'textAlign'; - const destinationTextAlign = - destinationBlockName === 'core/paragraph' ? 'align' : 'textAlign'; - - replaceBlocks( - currentClientId, - createBlock( destinationBlockName, { - level, - content: attributes.content, - ...{ [ destinationTextAlign ]: attributes[ textAlign ] }, - } ) - ); - }; - - useShortcut( 'core/edit-site/transform-heading-to-paragraph', ( event ) => - handleTextLevelShortcut( event, 0 ) - ); - - [ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => { - //the loop is based off on a constant therefore - //the hook will execute the same way every time - //eslint-disable-next-line react-hooks/rules-of-hooks - useShortcut( - `core/edit-site/transform-paragraph-to-heading-${ level }`, - ( event ) => handleTextLevelShortcut( event, level ) - ); - } ); - - return null; -} - -export default KeyboardShortcutsEditMode; diff --git a/packages/edit-site/src/components/keyboard-shortcuts/register.js b/packages/edit-site/src/components/keyboard-shortcuts/register.js index 6b4d9789a6f38..acbff4ab00846 100644 --- a/packages/edit-site/src/components/keyboard-shortcuts/register.js +++ b/packages/edit-site/src/components/keyboard-shortcuts/register.js @@ -55,28 +55,6 @@ function KeyboardShortcutsRegister() { }, ], } ); - - registerShortcut( { - name: 'core/edit-site/transform-heading-to-paragraph', - category: 'block-library', - description: __( 'Transform heading to paragraph.' ), - keyCombination: { - modifier: 'access', - character: `0`, - }, - } ); - - [ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => { - registerShortcut( { - name: `core/edit-site/transform-paragraph-to-heading-${ level }`, - category: 'block-library', - description: __( 'Transform paragraph to heading.' ), - keyCombination: { - modifier: 'access', - character: `${ level }`, - }, - } ); - } ); }, [ registerShortcut ] ); return null; diff --git a/packages/edit-widgets/src/components/keyboard-shortcut-help-modal/config.js b/packages/edit-widgets/src/components/keyboard-shortcut-help-modal/config.js index 4edf46204c75a..0380028aa100c 100644 --- a/packages/edit-widgets/src/components/keyboard-shortcut-help-modal/config.js +++ b/packages/edit-widgets/src/components/keyboard-shortcut-help-modal/config.js @@ -37,7 +37,16 @@ export const textFormattingShortcuts = [ description: __( 'Make the selected text inline code.' ), }, { - keyCombination: { modifier: 'access', character: '0' }, + keyCombination: { + modifier: 'access', + character: '0', + }, + aliases: [ + { + modifier: 'access', + character: '7', + }, + ], description: __( 'Convert the current heading to a paragraph.' ), }, { diff --git a/packages/edit-widgets/src/components/keyboard-shortcuts/index.js b/packages/edit-widgets/src/components/keyboard-shortcuts/index.js index dff0ac57f78c1..65ecceeb4aa8c 100644 --- a/packages/edit-widgets/src/components/keyboard-shortcuts/index.js +++ b/packages/edit-widgets/src/components/keyboard-shortcuts/index.js @@ -7,11 +7,9 @@ import { store as keyboardShortcutsStore, } from '@wordpress/keyboard-shortcuts'; import { isAppleOS } from '@wordpress/keycodes'; -import { useDispatch, useSelect } from '@wordpress/data'; +import { useDispatch } from '@wordpress/data'; import { __ } from '@wordpress/i18n'; import { store as coreStore } from '@wordpress/core-data'; -import { store as blockEditorStore } from '@wordpress/block-editor'; -import { createBlock } from '@wordpress/blocks'; /** * Internal dependencies @@ -22,38 +20,6 @@ function KeyboardShortcuts() { const { redo, undo } = useDispatch( coreStore ); const { saveEditedWidgetAreas } = useDispatch( editWidgetsStore ); - const { replaceBlocks } = useDispatch( blockEditorStore ); - const { getBlockName, getSelectedBlockClientId, getBlockAttributes } = - useSelect( blockEditorStore ); - - const handleTextLevelShortcut = ( event, level ) => { - event.preventDefault(); - const destinationBlockName = - level === 0 ? 'core/paragraph' : 'core/heading'; - const currentClientId = getSelectedBlockClientId(); - if ( currentClientId === null ) { - return; - } - const blockName = getBlockName( currentClientId ); - if ( blockName !== 'core/paragraph' && blockName !== 'core/heading' ) { - return; - } - const attributes = getBlockAttributes( currentClientId ); - const textAlign = - blockName === 'core/paragraph' ? 'align' : 'textAlign'; - const destinationTextAlign = - destinationBlockName === 'core/paragraph' ? 'align' : 'textAlign'; - - replaceBlocks( - currentClientId, - createBlock( destinationBlockName, { - level, - content: attributes.content, - ...{ [ destinationTextAlign ]: attributes[ textAlign ] }, - } ) - ); - }; - useShortcut( 'core/edit-widgets/undo', ( event ) => { undo(); event.preventDefault(); @@ -69,21 +35,6 @@ function KeyboardShortcuts() { saveEditedWidgetAreas(); } ); - useShortcut( - 'core/edit-widgets/transform-heading-to-paragraph', - ( event ) => handleTextLevelShortcut( event, 0 ) - ); - - [ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => { - //the loop is based off on a constant therefore - //the hook will execute the same way every time - //eslint-disable-next-line react-hooks/rules-of-hooks - useShortcut( - `core/edit-widgets/transform-paragraph-to-heading-${ level }`, - ( event ) => handleTextLevelShortcut( event, level ) - ); - } ); - return null; } @@ -178,28 +129,6 @@ function KeyboardShortcutsRegister() { }, ], } ); - - registerShortcut( { - name: 'core/edit-widgets/transform-heading-to-paragraph', - category: 'block-library', - description: __( 'Transform heading to paragraph.' ), - keyCombination: { - modifier: 'access', - character: `0`, - }, - } ); - - [ 1, 2, 3, 4, 5, 6 ].forEach( ( level ) => { - registerShortcut( { - name: `core/edit-widgets/transform-paragraph-to-heading-${ level }`, - category: 'block-library', - description: __( 'Transform paragraph to heading.' ), - keyCombination: { - modifier: 'access', - character: `${ level }`, - }, - } ); - } ); }, [ registerShortcut ] ); return null; diff --git a/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js b/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js index 4abc420434cc4..55704bfc7680f 100644 --- a/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js +++ b/packages/edit-widgets/src/components/widget-areas-block-editor-provider/index.js @@ -14,6 +14,7 @@ import { useMemo } from '@wordpress/element'; import { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor'; import { privateApis as editPatternsPrivateApis } from '@wordpress/patterns'; import { store as preferencesStore } from '@wordpress/preferences'; +import { privateApis as blockLibraryPrivateApis } from '@wordpress/block-library'; /** * Internal dependencies @@ -27,6 +28,8 @@ import { unlock } from '../../lock-unlock'; const { ExperimentalBlockEditorProvider } = unlock( blockEditorPrivateApis ); const { PatternsMenuItems } = unlock( editPatternsPrivateApis ); +const { BlockKeyboardShortcuts } = unlock( blockLibraryPrivateApis ); + export default function WidgetAreasBlockEditorProvider( { blockEditorSettings, children, @@ -111,6 +114,7 @@ export default function WidgetAreasBlockEditorProvider( { return ( +