diff --git a/editor/inserter/index.js b/editor/inserter/index.js index 71002eb908ef6a..2c773d0c113050 100644 --- a/editor/inserter/index.js +++ b/editor/inserter/index.js @@ -13,7 +13,7 @@ import { IconButton } from 'components'; * Internal dependencies */ import InserterMenu from './menu'; -import { getSelectedBlock } from '../selectors'; +import { getBlockSelectionEnd, getSelectedBlock } from '../selectors'; import { insertBlock, clearInsertionPoint } from '../actions'; class Inserter extends wp.element.Component { @@ -41,10 +41,17 @@ class Inserter extends wp.element.Component { insertBlock( slug ) { if ( slug ) { - const { selectedBlock, onInsertBlock } = this.props; + const { selectedBlock, lastMultiSelectedBlock, onInsertBlock } = this.props; + let insertionPoint = null; + if ( lastMultiSelectedBlock ) { + insertionPoint = lastMultiSelectedBlock; + } else if ( selectedBlock ) { + insertionPoint = selectedBlock.uid; + } + onInsertBlock( slug, - selectedBlock ? selectedBlock.uid : null + insertionPoint ); } @@ -90,6 +97,7 @@ export default connect( ( state ) => { return { selectedBlock: getSelectedBlock( state ), + lastMultiSelectedBlock: getBlockSelectionEnd( state ), }; }, ( dispatch ) => ( { diff --git a/editor/inserter/menu.js b/editor/inserter/menu.js index d34ccd16b6d292..d02f0f9af12689 100644 --- a/editor/inserter/menu.js +++ b/editor/inserter/menu.js @@ -15,7 +15,7 @@ import { TAB, ESCAPE, LEFT, UP, RIGHT, DOWN } from 'utils/keycodes'; * Internal dependencies */ import './style.scss'; -import { getSelectedBlock } from '../selectors'; +import { getBlockSelectionEnd, getSelectedBlock } from '../selectors'; import { setInsertionPoint, clearInsertionPoint } from '../actions'; class InserterMenu extends wp.element.Component { @@ -68,10 +68,15 @@ class InserterMenu extends wp.element.Component { } hoverBlock() { + const { lastMultiSelectedBlock, selectedBlock } = this.props; + let insertionPoint = null; + if ( lastMultiSelectedBlock ) { + insertionPoint = lastMultiSelectedBlock; + } else if ( selectedBlock ) { + insertionPoint = selectedBlock.uid; + } return () => { - this.props.setInsertionPoint( - this.props.selectedBlock ? this.props.selectedBlock.uid : null - ); + this.props.setInsertionPoint( insertionPoint ); }; } @@ -306,6 +311,7 @@ export default connect( ( state ) => { return { selectedBlock: getSelectedBlock( state ), + lastMultiSelectedBlock: getBlockSelectionEnd( state ), }; }, { setInsertionPoint, clearInsertionPoint } diff --git a/editor/modes/visual-editor/block-list.js b/editor/modes/visual-editor/block-list.js index 37b99b5b872349..1e2f39da3d86dc 100644 --- a/editor/modes/visual-editor/block-list.js +++ b/editor/modes/visual-editor/block-list.js @@ -2,7 +2,6 @@ * External dependencies */ import { connect } from 'react-redux'; -import clickOutside from 'react-click-outside'; /** * Internal dependencies @@ -56,10 +55,6 @@ class VisualEditorBlockList extends wp.element.Component { this.setState( { selectionAtStart: null } ); } - handleClickOutside() { - this.props.clearSelectedBlock(); - } - render() { const { blocks, insertionPoint } = this.props; const insertionPointIndex = blocks.indexOf( insertionPoint ); @@ -106,9 +101,8 @@ export default connect( selectionEnd: getBlockSelectionEnd( state ), } ), ( dispatch ) => ( { - clearSelectedBlock: () => dispatch( { type: 'CLEAR_SELECTED_BLOCK' } ), onMultiSelect( { start, end } ) { dispatch( { type: 'MULTI_SELECT', start, end } ); }, } ) -)( clickOutside( VisualEditorBlockList ) ); +)( VisualEditorBlockList ); diff --git a/editor/modes/visual-editor/block.js b/editor/modes/visual-editor/block.js index 2101454a2f9e63..228855950c784e 100644 --- a/editor/modes/visual-editor/block.js +++ b/editor/modes/visual-editor/block.js @@ -52,7 +52,6 @@ class VisualEditorBlock extends wp.element.Component { this.maybeStartTyping = this.maybeStartTyping.bind( this ); this.removeOrDeselect = this.removeOrDeselect.bind( this ); this.mergeBlocks = this.mergeBlocks.bind( this ); - this.selectAndStopPropagation = this.selectAndStopPropagation.bind( this ); this.previousOffset = null; } @@ -151,13 +150,6 @@ class VisualEditorBlock extends wp.element.Component { } } - selectAndStopPropagation( event ) { - this.props.onSelect(); - // Visual editor infers click as intent to clear the selected block, so - // prevent bubbling when occurring on block where selection is intended - event.stopPropagation(); - } - componentDidUpdate( prevProps ) { if ( this.previousOffset ) { window.scrollTo( @@ -280,7 +272,7 @@ class VisualEditorBlock extends wp.element.Component {
- - - -
- ); +class VisualEditor extends Component { + constructor() { + super( ...arguments ); + this.bindContainer = this.bindContainer.bind( this ); + this.onClick = this.onClick.bind( this ); + } + + bindContainer( ref ) { + this.container = ref; + } + + onClick( event ) { + if ( event.target === this.container ) { + this.props.clearSelectedBlock(); + } + } + + render() { + // Disable reason: Clicking the canvas should clear the selection + /* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */ + return ( +
+ + + +
+ ); + /* eslint-enable jsx-a11y/no-static-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */ + } } + +export default connect( + undefined, + ( dispatch ) => ( { + clearSelectedBlock() { + dispatch( { type: 'CLEAR_SELECTED_BLOCK' } ); + }, + } ) +)( VisualEditor ); diff --git a/editor/modes/visual-editor/style.scss b/editor/modes/visual-editor/style.scss index 866e7b2db9cc60..ff1a0a3da33d34 100644 --- a/editor/modes/visual-editor/style.scss +++ b/editor/modes/visual-editor/style.scss @@ -125,15 +125,16 @@ margin: $item-spacing $item-spacing $item-spacing calc( 50% - #{ $visual-editor-max-width / 2 } ); // account for full-width trick } -.editor-visual-editor > .editor-visual-editor__insertion-point { +.editor-visual-editor .editor-visual-editor__insertion-point { position: relative; + margin-right: #{ ( $block-padding + $block-mover-margin) * 2 }; &:before { position: absolute; top: 6px; - right: #{ $block-padding + $block-mover-margin }; - left: 0; height: 3px; + left: 0; + right: 0; background: $blue-medium-500; content: ''; } diff --git a/editor/state.js b/editor/state.js index f99a19e829f2aa..da8f9b125570c5 100644 --- a/editor/state.js +++ b/editor/state.js @@ -279,6 +279,7 @@ export function multiSelectedBlocks( state = { start: null, end: null }, action switch ( action.type ) { case 'CLEAR_SELECTED_BLOCK': case 'TOGGLE_BLOCK_SELECTED': + case 'INSERT_BLOCK': return { start: null, end: null, diff --git a/editor/test/state.js b/editor/test/state.js index 7c38718836abdd..5a9635c82b19cf 100644 --- a/editor/test/state.js +++ b/editor/test/state.js @@ -786,6 +786,16 @@ describe( 'state', () => { } ); expect( state2 ).to.eql( { start: null, end: null } ); + + const state3 = multiSelectedBlocks( original, { + type: 'INSERT_BLOCK', + block: { + uid: 'ribs', + name: 'core/freeform', + }, + } ); + + expect( state3 ).to.eql( { start: null, end: null } ); } ); } );