Skip to content

Commit

Permalink
Merge pull request #3008 from WordPress/add/between-inserter-2
Browse files Browse the repository at this point in the history
Block List: Display inserter button between blocks
  • Loading branch information
aduth authored Oct 16, 2017
2 parents 385b1b9 + 7784c0f commit 588ccd3
Show file tree
Hide file tree
Showing 16 changed files with 496 additions and 104 deletions.
16 changes: 16 additions & 0 deletions components/dropdown/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ class Dropdown extends Component {
};
}

componentWillUnmount() {
const { isOpen } = this.state;
const { onToggle } = this.props;
if ( isOpen && onToggle ) {
onToggle( false );
}
}

componentWillUpdate( nextProps, nextState ) {
const { isOpen } = nextState;
const { onToggle } = nextProps;
if ( this.state.isOpen !== isOpen && onToggle ) {
onToggle( isOpen );
}
}

bindContainer( ref ) {
this.container = ref;
}
Expand Down
1 change: 1 addition & 0 deletions components/icon-button/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
overflow: hidden;

.dashicon {
display: block;
flex: 0 0 auto;
}

Expand Down
26 changes: 26 additions & 0 deletions editor/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,32 @@ export function hideInsertionPoint() {
};
}

/**
* Returns an action object used in signalling that block insertion should
* occur at the specified block index position.
*
* @param {Number} position Position at which to insert
* @return {Object} Action object
*/
export function setBlockInsertionPoint( position ) {
return {
type: 'SET_BLOCK_INSERTION_POINT',
position,
};
}

/**
* Returns an action object used in signalling that the block insertion point
* should be reset.
*
* @return {Object} Action object
*/
export function clearBlockInsertionPoint() {
return {
type: 'CLEAR_BLOCK_INSERTION_POINT',
};
}

export function editPost( edits ) {
return {
type: 'EDIT_POST',
Expand Down
1 change: 1 addition & 0 deletions editor/assets/stylesheets/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ $block-padding: 14px;
$block-mover-margin: 18px;
$block-mover-padding-hidden: 10px;
$block-mover-padding-visible: 32px;
$block-spacing: 4px;

/* Media Queries */

Expand Down
16 changes: 9 additions & 7 deletions editor/assets/stylesheets/_z-index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,22 @@ $z-layers: (
'.editor-block-switcher__arrow': 1,
'.editor-visual-editor__block:before': -1,
'.editor-visual-editor__block .wp-block-more:before': -1,
'.editor-visual-editor__block {core/image aligned left or right}': 10,
'.editor-block-toolbar': 1,
'.editor-visual-editor__block {core/image aligned left or right}': 20,
'.editor-block-toolbar': 10,
'.editor-visual-editor__block-warning': 1,
'.editor-visual-editor__sibling-inserter': 1,
'.components-form-toggle__input': 1,
'.editor-format-list__menu': 1,
'.editor-inserter__tabs': 1,
'.editor-inserter__tab.is-active': 1,
'.components-panel__header': 1,
'.blocks-format-toolbar__link-modal': 1,
'.editor-block-mover': 10,
'.blocks-gallery-image__inline-menu': 10,
'.editor-block-settings-menu__popover': 10, // Bellow the header
'.editor-header': 20,
'.editor-text-editor__formatting': 20,
'.editor-block-switcher__menu': 2,
'.editor-block-mover': 20,
'.blocks-gallery-image__inline-menu': 20,
'.editor-block-settings-menu__popover': 20, // Below the header
'.editor-header': 30,
'.editor-text-editor__formatting': 30,

// Show drop zone above most standard content, but below any overlays
'.components-drop-zone': 100,
Expand Down
111 changes: 81 additions & 30 deletions editor/inserter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,52 +2,99 @@
* External dependencies
*/
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { Dropdown, IconButton } from '@wordpress/components';
import { createBlock } from '@wordpress/blocks';
import { Component } from '@wordpress/element';

/**
* Internal dependencies
*/
import InserterMenu from './menu';
import { getBlockInsertionPoint, getEditorMode } from '../selectors';
import { insertBlock, hideInsertionPoint } from '../actions';
import {
insertBlock,
setBlockInsertionPoint,
clearBlockInsertionPoint,
hideInsertionPoint,
} from '../actions';

function Inserter( { position, children, onInsertBlock, insertionPoint } ) {
return (
<Dropdown
className="editor-inserter"
position={ position }
renderToggle={ ( { onToggle, isOpen } ) => (
<IconButton
icon="insert"
label={ __( 'Insert block' ) }
onClick={ onToggle }
className="editor-inserter__toggle"
aria-haspopup="true"
aria-expanded={ isOpen }
>
{ children }
</IconButton>
) }
renderContent={ ( { onClose } ) => {
const onInsert = ( name ) => {
onInsertBlock(
name,
insertionPoint
);
class Inserter extends Component {
constructor() {
super( ...arguments );

onClose();
};
this.onToggle = this.onToggle.bind( this );
}

return <InserterMenu onSelect={ onInsert } />;
} }
/>
);
onToggle( isOpen ) {
const {
insertIndex,
setInsertionPoint,
clearInsertionPoint,
onToggle,
} = this.props;

// When inserting at specific index, assign as insertion point when
// the inserter is opened, clearing on close.
if ( insertIndex !== undefined ) {
if ( isOpen ) {
setInsertionPoint( insertIndex );
} else {
clearInsertionPoint();
}
}

// Surface toggle callback to parent component
if ( onToggle ) {
onToggle( isOpen );
}
}

render() {
const {
position,
children,
onInsertBlock,
insertionPoint,
} = this.props;

return (
<Dropdown
className="editor-inserter"
position={ position }
onToggle={ this.onToggle }
renderToggle={ ( { onToggle, isOpen } ) => (
<IconButton
icon="insert"
label={ __( 'Insert block' ) }
onClick={ onToggle }
className="editor-inserter__toggle"
aria-haspopup="true"
aria-expanded={ isOpen }
>
{ children }
</IconButton>
) }
renderContent={ ( { onClose } ) => {
const onInsert = ( name ) => {
onInsertBlock(
name,
insertionPoint
);

onClose();
};

return <InserterMenu onSelect={ onInsert } />;
} }
/>
);
}
}

export default connect(
Expand All @@ -65,5 +112,9 @@ export default connect(
position
) );
},
...bindActionCreators( {
setInsertionPoint: setBlockInsertionPoint,
clearInsertionPoint: clearBlockInsertionPoint,
}, dispatch ),
} )
)( Inserter );
22 changes: 12 additions & 10 deletions editor/inserter/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ export class InserterMenu extends Component {
}

componentDidMount() {
document.addEventListener( 'keydown', this.onKeyDown );
document.addEventListener( 'keydown', this.onKeyDown, true );
}

componentWillUnmount() {
document.removeEventListener( 'keydown', this.onKeyDown );
document.removeEventListener( 'keydown', this.onKeyDown, true );
}

componentDidUpdate( prevProps, prevState ) {
Expand Down Expand Up @@ -239,28 +239,32 @@ export class InserterMenu extends Component {
return;
}
this.focusPrevious( this );

break;

case UP:
keydown.preventDefault();
this.focusPrevious( this );

break;

case RIGHT:
if ( this.state.currentFocus === 'search' ) {
return;
}
this.focusNext( this );

break;

case DOWN:
keydown.preventDefault();
this.focusNext( this );

break;
default :
break;

default:
return;
}

// Since unhandled key will return in the default case, we can assume
// having reached this point implies that the key is handled.
keydown.stopImmediatePropagation();
}

changeMenuSelection( refName ) {
Expand Down Expand Up @@ -345,7 +349,6 @@ export class InserterMenu extends Component {
const isShowingEmbeds = ! isSearching && 'embeds' === this.state.tab;
const isShowingRecent = ! isSearching && 'recent' === this.state.tab;

/* eslint-disable jsx-a11y/no-autofocus */
return (
<div className="editor-inserter__menu">
<label htmlFor={ `editor-inserter__search-${ instanceId }` } className="screen-reader-text">
Expand Down Expand Up @@ -390,7 +393,6 @@ export class InserterMenu extends Component {
}
</div>
);
/* eslint-enable jsx-a11y/no-autofocus */
}
}

Expand Down
55 changes: 16 additions & 39 deletions editor/modes/visual-editor/block-list.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@ import { serialize, getDefaultBlockName, createBlock } from '@wordpress/blocks';
* Internal dependencies
*/
import VisualEditorBlock from './block';
import VisualEditorSiblingInserter from './sibling-inserter';
import BlockDropZone from './block-drop-zone';
import {
getBlockUids,
getBlockInsertionPoint,
isBlockInsertionPointVisible,
getMultiSelectedBlocksStartUid,
getMultiSelectedBlocksEndUid,
getMultiSelectedBlocks,
Expand All @@ -28,8 +27,6 @@ import {
} from '../../selectors';
import { insertBlock, startMultiSelect, stopMultiSelect, multiSelect, selectBlock } from '../../actions';

const INSERTION_POINT_PLACEHOLDER = '[[insertion-point]]';

class VisualEditorBlockList extends Component {
constructor( props ) {
super( props );
Expand Down Expand Up @@ -195,42 +192,24 @@ class VisualEditorBlockList extends Component {
}

render() {
const {
blocks,
showInsertionPoint,
insertionPoint,
} = this.props;

const blocksWithInsertionPoint = showInsertionPoint
? [
...blocks.slice( 0, insertionPoint ),
INSERTION_POINT_PLACEHOLDER,
...blocks.slice( insertionPoint ),
]
: blocks;
const { blocks } = this.props;

return (
<div>
{ !! blocks.length && blocksWithInsertionPoint.map( ( uid ) => {
if ( uid === INSERTION_POINT_PLACEHOLDER ) {
return (
<div
key={ INSERTION_POINT_PLACEHOLDER }
className="editor-visual-editor__insertion-point"
/>
);
}

return (
<VisualEditorBlock
key={ uid }
uid={ uid }
blockRef={ ( ref ) => this.setBlockRef( ref, uid ) }
onSelectionStart={ this.onSelectionStart }
onShiftSelection={ this.onShiftSelection }
/>
);
} ) }
{ !! blocks.length && <VisualEditorSiblingInserter insertIndex={ 0 } /> }
{ blocks.reduce( ( result, uid, index ) => result.concat(
<VisualEditorBlock
key={ 'block-' + uid }
uid={ uid }
blockRef={ ( ref ) => this.setBlockRef( ref, uid ) }
onSelectionStart={ this.onSelectionStart }
onShiftSelection={ this.onShiftSelection }
/>,
<VisualEditorSiblingInserter
key={ 'sibling-inserter-' + uid }
insertIndex={ index + 1 }
/>,
), [] ) }
{ ! blocks.length &&
<div className="editor-visual-editor__placeholder">
<BlockDropZone />
Expand All @@ -252,8 +231,6 @@ class VisualEditorBlockList extends Component {
export default connect(
( state ) => ( {
blocks: getBlockUids( state ),
insertionPoint: getBlockInsertionPoint( state ),
showInsertionPoint: isBlockInsertionPointVisible( state ),
selectionStart: getMultiSelectedBlocksStartUid( state ),
selectionEnd: getMultiSelectedBlocksEndUid( state ),
multiSelectedBlocks: getMultiSelectedBlocks( state ),
Expand Down
Loading

0 comments on commit 588ccd3

Please sign in to comment.