diff --git a/src/components/modules/blockEvents.ts b/src/components/modules/blockEvents.ts index 40e0973e2..3f00f3557 100644 --- a/src/components/modules/blockEvents.ts +++ b/src/components/modules/blockEvents.ts @@ -93,7 +93,10 @@ export default class BlockEvents extends Module { * - close Toolbar * - clear block highlighting */ - if (_.isPrintableKey(event.keyCode)) { + + const isPrintableKey = _.isPrintableKey(event.keyCode); + + if (isPrintableKey) { this.Editor.Toolbar.close(); /** @@ -101,7 +104,7 @@ export default class BlockEvents extends Module { * * @type {boolean} */ - const isShortcut = event.ctrlKey || event.metaKey || event.altKey || event.shiftKey; + const isShortcut = event.ctrlKey || event.metaKey || event.altKey || (event.shiftKey && !isPrintableKey); if (!isShortcut) { this.Editor.BlockSelection.clearSelection(event); @@ -660,15 +663,16 @@ export default class BlockEvents extends Module { const toolboxItemSelected = (event.keyCode === _.keyCodes.ENTER && this.Editor.Toolbar.toolbox.opened), blockSettingsItemSelected = (event.keyCode === _.keyCodes.ENTER && this.Editor.BlockSettings.opened), inlineToolbarItemSelected = (event.keyCode === _.keyCodes.ENTER && this.Editor.InlineToolbar.opened), - flippingToolbarItems = event.keyCode === _.keyCodes.TAB; + flippingToolbarItems = event.keyCode === _.keyCodes.TAB, + shiftKeyEventEmitted = event.shiftKey && !_.isPrintableKey(event.keyCode); /** * Do not close Toolbar in cases: - * 1. ShiftKey pressed (or combination with shiftKey) + * 1. ShiftKey event emitted * 2. When Toolbar is opened and Tab leafs its Tools * 3. When Toolbar's component is opened and some its item selected */ - return !(event.shiftKey || + return !(shiftKeyEventEmitted || flippingToolbarItems || toolboxItemSelected || blockSettingsItemSelected || diff --git a/src/components/modules/blockSelection.ts b/src/components/modules/blockSelection.ts index a6edcb8c8..a65445d17 100644 --- a/src/components/modules/blockSelection.ts +++ b/src/components/modules/blockSelection.ts @@ -252,7 +252,9 @@ export default class BlockSelection extends Module { * * @see https://developer.mozilla.org/ru/docs/Web/API/KeyboardEvent/key */ - Caret.insertContentAtCaretPosition(eventKey.length > 1 ? '' : eventKey); + if (eventKey.length > 1) { + Caret.insertContentAtCaretPosition(''); + } // eslint-disable-next-line @typescript-eslint/no-magic-numbers }, 20)(); } diff --git a/test/cypress/tests/modules/Ui.cy.ts b/test/cypress/tests/modules/Ui.cy.ts index eaf2246a8..0c911decf 100644 --- a/test/cypress/tests/modules/Ui.cy.ts +++ b/test/cypress/tests/modules/Ui.cy.ts @@ -93,6 +93,84 @@ describe('Ui module', function () { }); }); }); + + describe('Replace', function() { + it('should replace selected blocks with a single keystroke', function() { + cy.createEditor({ + data: { + blocks: [ + { + id: 'block1', + type: 'paragraph', + data: { + text: 'The first block', + }, + }, + { + id: 'block2', + type: 'paragraph', + data: { + text: 'The second block', + }, + }, + ], + }, + }).as('editorInstance'); + + /** + * Select two blocks by shift+down + */ + cy.get('[data-cy=editorjs]') + .find('.ce-paragraph') + .first() + .click() + .type('{shift+downArrow}') + .type('f'); + + cy.get('[data-cy=editorjs]') + .find('.ce-paragraph') + .first() + .should('have.text', 'f'); + }); + + it('should replace selected blocks with a single shift + keystroke', function() { + cy.createEditor({ + data: { + blocks: [ + { + id: 'block1', + type: 'paragraph', + data: { + text: 'The first block', + }, + }, + { + id: 'block2', + type: 'paragraph', + data: { + text: 'The second block', + }, + }, + ], + }, + }).as('editorInstance'); + + /** + * Select two blocks by shift+down + */ + cy.get('[data-cy=editorjs]') + .find('.ce-paragraph') + .first() + .click() + .type('{shift+downArrow}') + .type('{shift+F}'); + + cy.get('[data-cy=editorjs]') + .find('.ce-paragraph') + .first() + .should('have.text', 'F'); + }); + }); }); describe('mousedown', function () {