From 41f810aca5cc2fb3b391ae661c75fe69fa174793 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 30 Oct 2018 10:51:24 +0100 Subject: [PATCH 1/3] Fix multiselecting blocks using shift + arrow --- .../editor/src/components/block-list/block.js | 6 ++ .../src/components/block-toolbar/index.js | 70 +++++-------------- 2 files changed, 25 insertions(+), 51 deletions(-) diff --git a/packages/editor/src/components/block-list/block.js b/packages/editor/src/components/block-list/block.js index 30b3806aad5bd0..39ecdbbd13f0df 100644 --- a/packages/editor/src/components/block-list/block.js +++ b/packages/editor/src/components/block-list/block.js @@ -93,6 +93,12 @@ export class BlockListBlock extends Component { if ( this.props.isSelected && ! prevProps.isSelected ) { this.focusTabbable( true ); } + + // When triggering a multi-selection, + // move the focus to the wrapper of the first selected block. + if ( this.props.isFirstMultiSelected && ! prevProps.isFirstMultiSelected ) { + this.wrapperNode.focus(); + } } setBlockListRef( node ) { diff --git a/packages/editor/src/components/block-toolbar/index.js b/packages/editor/src/components/block-toolbar/index.js index de34bf2747ec25..511ed1d7da0536 100644 --- a/packages/editor/src/components/block-toolbar/index.js +++ b/packages/editor/src/components/block-toolbar/index.js @@ -2,8 +2,7 @@ * WordPress Dependencies */ import { withSelect } from '@wordpress/data'; -import { Component, createRef, Fragment } from '@wordpress/element'; -import { focus } from '@wordpress/dom'; +import { Fragment } from '@wordpress/element'; /** * Internal Dependencies @@ -14,63 +13,32 @@ import BlockControls from '../block-controls'; import BlockFormatControls from '../block-format-controls'; import BlockSettingsMenu from '../block-settings-menu'; -class BlockToolbar extends Component { - constructor() { - super( ...arguments ); - this.container = createRef(); +function BlockToolbar( { blockClientIds, isValid, mode } ) { + if ( blockClientIds.length === 0 ) { + return null; } - componentDidMount() { - if ( this.props.blockClientIds.length > 1 ) { - this.focusContainer(); - } - } - - componentDidUpdate( prevProps ) { - if ( - prevProps.blockClientIds.length <= 1 && - this.props.blockClientIds.length > 1 - ) { - this.focusContainer(); - } - } - - focusContainer() { - const tabbables = focus.tabbable.find( this.container.current ); - if ( tabbables.length ) { - tabbables[ 0 ].focus(); - } - } - - render() { - const { blockClientIds, isValid, mode } = this.props; - - if ( blockClientIds.length === 0 ) { - return null; - } - - if ( blockClientIds.length > 1 ) { - return ( -
- - -
- ); - } - + if ( blockClientIds.length > 1 ) { return (
- { mode === 'visual' && isValid && ( - - - - - - ) } +
); } + + return ( +
+ { mode === 'visual' && isValid && ( + + + + + + ) } + +
+ ); } export default withSelect( ( select ) => { From 59546d4b8325cbc8498a9c04f392673c9cdf0f60 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 30 Oct 2018 11:04:36 +0100 Subject: [PATCH 2/3] Test multiple shift + arrows selections --- test/e2e/specs/multi-block-selection.test.js | 42 +++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/test/e2e/specs/multi-block-selection.test.js b/test/e2e/specs/multi-block-selection.test.js index d341f099bf3b1e..866b9465834a85 100644 --- a/test/e2e/specs/multi-block-selection.test.js +++ b/test/e2e/specs/multi-block-selection.test.js @@ -10,7 +10,7 @@ import { } from '../support/utils'; describe( 'Multi-block selection', () => { - beforeAll( async () => { + beforeEach( async () => { await newPost(); } ); @@ -77,4 +77,44 @@ describe( 'Multi-block selection', () => { await pressWithModifier( META_KEY, 'a' ); await expectMultiSelected( blocks, true ); } ); + + it( 'Should select/unselect multiple blocks using Shift + Arrows', async () => { + const firstBlockSelector = '[data-type="core/paragraph"]'; + const secondBlockSelector = '[data-type="core/image"]'; + const thirdBlockSelector = '[data-type="core/quote"]'; + const multiSelectedCssClass = 'is-multi-selected'; + + // Creating test blocks + await clickBlockAppender(); + await page.keyboard.type( 'First Paragraph' ); + await insertBlock( 'Image' ); + await insertBlock( 'Quote' ); + await page.keyboard.type( 'Quote Block' ); + + const blocks = [ firstBlockSelector, secondBlockSelector, thirdBlockSelector ]; + const expectMultiSelected = async ( selectors, areMultiSelected ) => { + for ( const selector of selectors ) { + const className = await page.$eval( selector, ( element ) => element.className ); + if ( areMultiSelected ) { + expect( className ).toEqual( expect.stringContaining( multiSelectedCssClass ) ); + } else { + expect( className ).not.toEqual( expect.stringContaining( multiSelectedCssClass ) ); + } + } + }; + + // Default: No selection + await expectMultiSelected( blocks, false ); + + // Multiselect via Shift + click + await page.mouse.move( 200, 300 ); + await page.click( firstBlockSelector ); + await page.keyboard.down( 'Shift' ); + await page.keyboard.press( 'ArrowDown' ); // Two blocks selected + await page.keyboard.press( 'ArrowDown' ); // Three blocks selected + await page.keyboard.up( 'Shift' ); + + // Verify selection + await expectMultiSelected( blocks, true ); + } ); } ); From 2b9f20ab27fc26ebd71da1567b0e3f6d2b629f15 Mon Sep 17 00:00:00 2001 From: Riad Benguella Date: Tue, 30 Oct 2018 13:19:18 +0100 Subject: [PATCH 3/3] Fix end2end test failures --- packages/editor/src/components/block-list/block.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/editor/src/components/block-list/block.js b/packages/editor/src/components/block-list/block.js index 39ecdbbd13f0df..1213d1c424453e 100644 --- a/packages/editor/src/components/block-list/block.js +++ b/packages/editor/src/components/block-list/block.js @@ -320,7 +320,11 @@ export class BlockListBlock extends Component { deleteOrInsertAfterWrapper( event ) { const { keyCode, target } = event; - if ( target !== this.wrapperNode || this.props.isLocked ) { + if ( + ! this.props.isSelected || + target !== this.wrapperNode || + this.props.isLocked + ) { return; }