diff --git a/packages/blocks/src/api/index.js b/packages/blocks/src/api/index.js
index 8d1fae98aa56d7..127b329df4fe9b 100644
--- a/packages/blocks/src/api/index.js
+++ b/packages/blocks/src/api/index.js
@@ -39,6 +39,7 @@ export {
isReusableBlock,
getChildBlockNames,
hasChildBlocks,
+ hasChildBlocksWithInserterSupport,
unstable__bootstrapServerSideBlockDefinitions, // eslint-disable-line camelcase
registerBlockStyle,
} from './registration';
diff --git a/packages/blocks/src/api/registration.js b/packages/blocks/src/api/registration.js
index af23347818a98b..267ab2443b90de 100644
--- a/packages/blocks/src/api/registration.js
+++ b/packages/blocks/src/api/registration.js
@@ -235,17 +235,11 @@ export function getBlockTypes() {
* @param {string} feature Feature to retrieve
* @param {*} defaultSupports Default value to return if not
* explicitly defined
- * @return {?*} Block support value
+ *
+ * @return {?*} Block support value
*/
export function getBlockSupport( nameOrType, feature, defaultSupports ) {
- const blockType = 'string' === typeof nameOrType ?
- getBlockType( nameOrType ) :
- nameOrType;
-
- return get( blockType, [
- 'supports',
- feature,
- ], defaultSupports );
+ return select( 'core/blocks' ).getBlockSupport( nameOrType, feature, defaultSupports );
}
/**
@@ -259,7 +253,7 @@ export function getBlockSupport( nameOrType, feature, defaultSupports ) {
* @return {boolean} Whether block supports feature.
*/
export function hasBlockSupport( nameOrType, feature, defaultSupports ) {
- return !! getBlockSupport( nameOrType, feature, defaultSupports );
+ return select( 'core/blocks' ).hasBlockSupport( nameOrType, feature, defaultSupports );
}
/**
@@ -297,6 +291,18 @@ export const hasChildBlocks = ( blockName ) => {
return select( 'core/blocks' ).hasChildBlocks( blockName );
};
+/**
+ * Returns a boolean indicating if a block has at least one child block with inserter support.
+ *
+ * @param {string} blockName Block type name.
+ *
+ * @return {boolean} True if a block contains at least one child blocks with inserter support
+ * and false otherwise.
+ */
+export const hasChildBlocksWithInserterSupport = ( blockName ) => {
+ return select( 'core/blocks' ).hasChildBlocksWithInserterSupport( blockName );
+};
+
/**
* Registers a new block style variation for the given block.
*
diff --git a/packages/blocks/src/store/selectors.js b/packages/blocks/src/store/selectors.js
index bf6541ae3a1950..92950ffe43a11a 100644
--- a/packages/blocks/src/store/selectors.js
+++ b/packages/blocks/src/store/selectors.js
@@ -2,7 +2,7 @@
* External dependencies
*/
import createSelector from 'rememo';
-import { filter, includes, map } from 'lodash';
+import { filter, get, includes, map, some } from 'lodash';
/**
* Returns all the available block types.
@@ -85,6 +85,43 @@ export const getChildBlockNames = createSelector(
]
);
+/**
+ * Returns the block support value for a feature, if defined.
+ *
+ * @param {Object} state Data state.
+ * @param {(string|Object)} nameOrType Block name or type object
+ * @param {string} feature Feature to retrieve
+ * @param {*} defaultSupports Default value to return if not
+ * explicitly defined
+ *
+ * @return {?*} Block support value
+ */
+export const getBlockSupport = ( state, nameOrType, feature, defaultSupports ) => {
+ const blockType = 'string' === typeof nameOrType ?
+ getBlockType( state, nameOrType ) :
+ nameOrType;
+
+ return get( blockType, [
+ 'supports',
+ feature,
+ ], defaultSupports );
+};
+
+/**
+ * Returns true if the block defines support for a feature, or false otherwise.
+ *
+ * @param {Object} state Data state.
+ * @param {(string|Object)} nameOrType Block name or type object.
+ * @param {string} feature Feature to test.
+ * @param {boolean} defaultSupports Whether feature is supported by
+ * default if not explicitly defined.
+ *
+ * @return {boolean} Whether block supports feature.
+ */
+export function hasBlockSupport( state, nameOrType, feature, defaultSupports ) {
+ return !! getBlockSupport( state, nameOrType, feature, defaultSupports );
+}
+
/**
* Returns a boolean indicating if a block has child blocks or not.
*
@@ -96,3 +133,18 @@ export const getChildBlockNames = createSelector(
export const hasChildBlocks = ( state, blockName ) => {
return getChildBlockNames( state, blockName ).length > 0;
};
+
+/**
+ * Returns a boolean indicating if a block has at least one child block with inserter support.
+ *
+ * @param {Object} state Data state.
+ * @param {string} blockName Block type name.
+ *
+ * @return {boolean} True if a block contains at least one child blocks with inserter support
+ * and false otherwise.
+ */
+export const hasChildBlocksWithInserterSupport = ( state, blockName ) => {
+ return some( getChildBlockNames( state, blockName ), ( childBlockName ) => {
+ return hasBlockSupport( state, childBlockName, 'inserter', true );
+ } );
+};
diff --git a/packages/editor/src/components/block-switcher/index.js b/packages/editor/src/components/block-switcher/index.js
index 734415632805d0..9c8efa4eb05d3f 100644
--- a/packages/editor/src/components/block-switcher/index.js
+++ b/packages/editor/src/components/block-switcher/index.js
@@ -8,7 +8,7 @@ import { castArray, filter, first, get, mapKeys, orderBy } from 'lodash';
*/
import { __, _n, sprintf } from '@wordpress/i18n';
import { Dropdown, IconButton, Toolbar, PanelBody, AccessibleSVG } from '@wordpress/components';
-import { getBlockType, getPossibleBlockTransformations, switchToBlockType, hasChildBlocks } from '@wordpress/blocks';
+import { getBlockType, getPossibleBlockTransformations, switchToBlockType, hasChildBlocksWithInserterSupport } from '@wordpress/blocks';
import { Component, Fragment } from '@wordpress/element';
import { DOWN } from '@wordpress/keycodes';
import { withSelect, withDispatch } from '@wordpress/data';
@@ -128,7 +128,7 @@ export class BlockSwitcher extends Component {
id: destinationBlockType.name,
icon: destinationBlockType.icon,
title: destinationBlockType.title,
- hasChildBlocks: hasChildBlocks( destinationBlockType.name ),
+ hasChildBlocksWithInserterSupport: hasChildBlocksWithInserterSupport( destinationBlockType.name ),
} ) ) }
onSelect={ ( item ) => {
onTransform( blocks, item.id );
diff --git a/packages/editor/src/components/block-types-list/index.js b/packages/editor/src/components/block-types-list/index.js
index 381587ae0f068e..d27d0d96ea61ac 100644
--- a/packages/editor/src/components/block-types-list/index.js
+++ b/packages/editor/src/components/block-types-list/index.js
@@ -42,7 +42,7 @@ class BlockTypesList extends Component {
'editor-block-types-list__item',
getBlockMenuDefaultClassName( item.id ),
{
- 'editor-block-types-list__item-has-children': item.hasChildBlocks,
+ 'editor-block-types-list__item-has-children': item.hasChildBlocksWithInserterSupport,
}
)
}
@@ -62,7 +62,7 @@ class BlockTypesList extends Component {
style={ itemIconStyle }
>
- { item.hasChildBlocks &&
+ { item.hasChildBlocksWithInserterSupport &&
{
isDisabled: false,
utility: 0,
frecency: 0,
- hasChildBlocks: false,
+ hasChildBlocksWithInserterSupport: false,
} );
const reusableBlockItem = items.find( ( item ) => item.id === 'core/block/1' );
expect( reusableBlockItem ).toEqual( {