diff --git a/packages/block-editor/src/components/inserter/index.js b/packages/block-editor/src/components/inserter/index.js
index 4b842b4b7b3c5..37ac654d14c98 100644
--- a/packages/block-editor/src/components/inserter/index.js
+++ b/packages/block-editor/src/components/inserter/index.js
@@ -1,11 +1,21 @@
+/**
+ * External dependencies
+ */
+import classnames from 'classnames';
+import {
+ get,
+} from 'lodash';
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
-import { Dropdown, IconButton } from '@wordpress/components';
+import { Dropdown, IconButton, Button, Icon } from '@wordpress/components';
import { Component } from '@wordpress/element';
-import { withSelect } from '@wordpress/data';
+import { withDispatch, withSelect } from '@wordpress/data';
import { compose, ifCondition } from '@wordpress/compose';
+import {
+ createBlock,
+} from '@wordpress/blocks';
/**
* Internal dependencies
@@ -83,7 +93,23 @@ class Inserter extends Component {
}
render() {
- const { position } = this.props;
+ const { position, hasOneAllowedItem, createIfOne } = this.props;
+ let toggle = null;
+ if ( hasOneAllowedItem ) {
+ toggle = () => {
+ return (
+
+ );
+ };
+ } else {
+ toggle = this.renderToggle;
+ }
return (
);
@@ -102,10 +128,62 @@ class Inserter extends Component {
export default compose( [
withSelect( ( select, { rootClientId } ) => {
- const { hasInserterItems } = select( 'core/block-editor' );
+ const { hasInserterItems, hasOneAllowedItem } = select( 'core/block-editor' );
return {
hasItems: hasInserterItems( rootClientId ),
+ hasOneAllowedItem: hasOneAllowedItem( rootClientId ),
+ };
+ } ),
+ withDispatch( ( dispatch, ownProps, { select } ) => {
+ // eslint-disable-next-line no-restricted-syntax
+ function getInsertionIndex() {
+ const {
+ getBlockIndex,
+ getBlockSelectionEnd,
+ getBlockOrder,
+ } = select( 'core/block-editor' );
+ const { clientId, destinationRootClientId, isAppender } = ownProps;
+
+ // If the clientId is defined, we insert at the position of the block.
+ if ( clientId ) {
+ return getBlockIndex( clientId, destinationRootClientId );
+ }
+
+ // If there a selected block, we insert after the selected block.
+ const end = getBlockSelectionEnd();
+ if ( ! isAppender && end ) {
+ return getBlockIndex( end, destinationRootClientId ) + 1;
+ }
+
+ // Otherwise, we insert at the end of the current rootClientId
+ return getBlockOrder( destinationRootClientId ).length;
+ }
+ const { rootClientId } = ownProps;
+
+ // eslint-disable-next-line no-restricted-syntax
+ function createIfOne( ) {
+ const {
+ insertBlock,
+ } = dispatch( 'core/block-editor' );
+ const {
+ getBlockListSettings,
+ } = select( 'core/block-editor' );
+ const parentBlockListSettings = getBlockListSettings( rootClientId );
+ const parentAllowedBlocks = get( parentBlockListSettings, [ 'allowedBlocks' ] );
+ if ( parentAllowedBlocks.length > 1 ) {
+ return false;
+ }
+ const insertedBlock = createBlock( parentAllowedBlocks[ 0 ] );
+ insertBlock(
+ insertedBlock,
+ getInsertionIndex(),
+ rootClientId
+ );
+ }
+
+ return {
+ createIfOne,
};
} ),
ifCondition( ( { hasItems } ) => hasItems ),
diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js
index 5e8771ff94935..24958dcd2b41d 100644
--- a/packages/block-editor/src/store/selectors.js
+++ b/packages/block-editor/src/store/selectors.js
@@ -1328,6 +1328,29 @@ export const hasInserterItems = createSelector(
],
);
+/**
+ * Determines whether there is only one item that may be inserted.
+ * @param {Object} state Editor state.
+ * @param {?string} rootClientId Optional root client ID of block list.
+ *
+ * @return {boolean} True if there is one item available, false if zero or more than one.
+ */
+export const hasOneAllowedItem = createSelector(
+ ( state, rootClientId = null ) => {
+ if ( rootClientId ) {
+ const parentBlockListSettings = getBlockListSettings( state, rootClientId );
+ return ( !! get( parentBlockListSettings, [ 'allowedBlocks' ] ) &&
+ get( parentBlockListSettings, [ 'allowedBlocks' ] ).length === 1 );
+ }
+
+ return false;
+ },
+ ( state, rootClientId ) => [
+ state,
+ rootClientId,
+ ],
+);
+
/**
* Returns the Block List settings of a block, if any exist.
*