diff --git a/packages/editor/src/components/default-block-appender/test/__snapshots__/index.js.snap b/packages/editor/src/components/default-block-appender/test/__snapshots__/index.js.snap
index 46c017374b5149..71484219b7d98e 100644
--- a/packages/editor/src/components/default-block-appender/test/__snapshots__/index.js.snap
+++ b/packages/editor/src/components/default-block-appender/test/__snapshots__/index.js.snap
@@ -23,7 +23,7 @@ exports[`DefaultBlockAppender should append a default block when input focused 1
value="Write your story"
/>
-
@@ -45,7 +45,7 @@ exports[`DefaultBlockAppender should match snapshot 1`] = `
value="Write your story"
/>
-
@@ -67,7 +67,7 @@ exports[`DefaultBlockAppender should optionally show without prompt 1`] = `
value=""
/>
-
diff --git a/packages/editor/src/components/inserter/index.js b/packages/editor/src/components/inserter/index.js
index d10f70e315af2c..1879683b3c072a 100644
--- a/packages/editor/src/components/inserter/index.js
+++ b/packages/editor/src/components/inserter/index.js
@@ -3,10 +3,9 @@
*/
import { __ } from '@wordpress/i18n';
import { Dropdown, IconButton } from '@wordpress/components';
-import { createBlock, isUnmodifiedDefaultBlock } from '@wordpress/blocks';
import { Component } from '@wordpress/element';
-import { withSelect, withDispatch } from '@wordpress/data';
-import { compose } from '@wordpress/compose';
+import { withSelect } from '@wordpress/data';
+import { compose, ifCondition } from '@wordpress/compose';
/**
* Internal dependencies
@@ -30,6 +29,8 @@ class Inserter extends Component {
super( ...arguments );
this.onToggle = this.onToggle.bind( this );
+ this.renderToggle = this.renderToggle.bind( this );
+ this.renderContent = this.renderContent.bind( this );
}
onToggle( isOpen ) {
@@ -41,20 +42,46 @@ class Inserter extends Component {
}
}
- render() {
+ /**
+ * Render callback to display Dropdown toggle element.
+ *
+ * @param {Function} options.onToggle Callback to invoke when toggle is
+ * pressed.
+ * @param {boolean} options.isOpen Whether dropdown is currently open.
+ *
+ * @return {WPElement} Dropdown toggle element.
+ */
+ renderToggle( { onToggle, isOpen } ) {
const {
- items,
- position,
- title,
- onInsertBlock,
- rootClientId,
disabled,
renderToggle = defaultRenderToggle,
} = this.props;
- if ( items.length === 0 ) {
- return null;
- }
+ return renderToggle( { onToggle, isOpen, disabled } );
+ }
+
+ /**
+ * Render callback to display Dropdown content element.
+ *
+ * @param {Function} options.onClose Callback to invoke when dropdown is
+ * closed.
+ *
+ * @return {WPElement} Dropdown content element.
+ */
+ renderContent( { onClose } ) {
+ const { rootClientId, index } = this.props;
+
+ return (
+
+ );
+ }
+
+ render() {
+ const { position, title } = this.props;
return (
renderToggle( { onToggle, isOpen, disabled } ) }
- renderContent={ ( { onClose } ) => {
- const onSelect = ( item ) => {
- onInsertBlock( item );
-
- onClose();
- };
-
- return (
-
- );
- } }
+ renderToggle={ this.renderToggle }
+ renderContent={ this.renderContent }
/>
);
}
@@ -90,7 +103,6 @@ export default compose( [
const {
getEditedPostAttribute,
getBlockInsertionPoint,
- getSelectedBlock,
getInserterItems,
} = select( 'core/editor' );
@@ -106,21 +118,10 @@ export default compose( [
return {
title: getEditedPostAttribute( 'title' ),
- selectedBlock: getSelectedBlock(),
- items: getInserterItems( rootClientId ),
- index,
+ hasItems: getInserterItems( rootClientId ).length > 0,
rootClientId,
+ index,
};
} ),
- withDispatch( ( dispatch, ownProps ) => ( {
- onInsertBlock: ( item ) => {
- const { selectedBlock, index, rootClientId } = ownProps;
- const { name, initialAttributes } = item;
- const insertedBlock = createBlock( name, initialAttributes );
- if ( selectedBlock && isUnmodifiedDefaultBlock( selectedBlock ) ) {
- return dispatch( 'core/editor' ).replaceBlocks( selectedBlock.clientId, insertedBlock );
- }
- return dispatch( 'core/editor' ).insertBlock( insertedBlock, index, rootClientId );
- },
- } ) ),
+ ifCondition( ( { hasItems } ) => hasItems ),
] )( Inserter );
diff --git a/packages/editor/src/components/inserter/menu.js b/packages/editor/src/components/inserter/menu.js
index 4bb2362377c390..9780661f6442f9 100644
--- a/packages/editor/src/components/inserter/menu.js
+++ b/packages/editor/src/components/inserter/menu.js
@@ -23,7 +23,12 @@ import scrollIntoView from 'dom-scroll-into-view';
import { __, _n, _x, sprintf } from '@wordpress/i18n';
import { Component, findDOMNode, createRef } from '@wordpress/element';
import { withSpokenMessages, PanelBody } from '@wordpress/components';
-import { getCategories, isReusableBlock } from '@wordpress/blocks';
+import {
+ getCategories,
+ isReusableBlock,
+ createBlock,
+ isUnmodifiedDefaultBlock,
+} from '@wordpress/blocks';
import { withDispatch, withSelect } from '@wordpress/data';
import { withInstanceId, compose, withSafeTimeout } from '@wordpress/compose';
import { LEFT, RIGHT, UP, DOWN, BACKSPACE, ENTER } from '@wordpress/keycodes';
@@ -340,21 +345,55 @@ export class InserterMenu extends Component {
export default compose(
withSelect( ( select, { rootClientId } ) => {
const {
- getChildBlockNames,
- } = select( 'core/blocks' );
- const {
+ getEditedPostAttribute,
+ getSelectedBlock,
+ getInserterItems,
getBlockName,
} = select( 'core/editor' );
+ const {
+ getChildBlockNames,
+ } = select( 'core/blocks' );
+
const rootBlockName = getBlockName( rootClientId );
+
return {
+ selectedBlock: getSelectedBlock(),
rootChildBlocks: getChildBlockNames( rootBlockName ),
+ title: getEditedPostAttribute( 'title' ),
+ items: getInserterItems( rootClientId ),
+ rootClientId,
+ };
+ } ),
+ withDispatch( ( dispatch, ownProps ) => {
+ const {
+ __experimentalFetchReusableBlocks: fetchReusableBlocks,
+ showInsertionPoint,
+ hideInsertionPoint,
+ } = dispatch( 'core/editor' );
+
+ return {
+ fetchReusableBlocks,
+ showInsertionPoint,
+ hideInsertionPoint,
+ onSelect( item ) {
+ const {
+ replaceBlocks,
+ insertBlock,
+ } = dispatch( 'core/editor' );
+ const { selectedBlock, index, rootClientId } = ownProps;
+ const { name, initialAttributes } = item;
+
+ const insertedBlock = createBlock( name, initialAttributes );
+ if ( selectedBlock && isUnmodifiedDefaultBlock( selectedBlock ) ) {
+ replaceBlocks( selectedBlock.clientId, insertedBlock );
+ } else {
+ insertBlock( insertedBlock, index, rootClientId );
+ }
+
+ ownProps.onSelect();
+ },
};
} ),
- withDispatch( ( dispatch ) => ( {
- fetchReusableBlocks: dispatch( 'core/editor' ).__experimentalFetchReusableBlocks,
- showInsertionPoint: dispatch( 'core/editor' ).showInsertionPoint,
- hideInsertionPoint: dispatch( 'core/editor' ).hideInsertionPoint,
- } ) ),
withSpokenMessages,
withInstanceId,
withSafeTimeout