Skip to content

Commit

Permalink
Fix: Don't show stacked icon on parent blocks if all of its children …
Browse files Browse the repository at this point in the history
…are hidden from the inserter (#9337)

Until now even if all the children of a block were hidden from the inserter we showed the stacked icon in the parent.
Given that for this cases no child blocks will appear on the inserter of the parent we should not show the stacked icon.

We also move the logic of getBlockSupport to a selector so other selectors can use it. Some of the other simpler functions available in the block registration API are also promoted to selectors so we can add the new selector needed that uses them.
  • Loading branch information
jorgefilipecosta authored Sep 14, 2018
1 parent 51a0287 commit cd167ce
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 18 deletions.
1 change: 1 addition & 0 deletions packages/blocks/src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export {
isReusableBlock,
getChildBlockNames,
hasChildBlocks,
hasChildBlocksWithInserterSupport,
unstable__bootstrapServerSideBlockDefinitions, // eslint-disable-line camelcase
registerBlockStyle,
} from './registration';
Expand Down
26 changes: 16 additions & 10 deletions packages/blocks/src/api/registration.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}

/**
Expand All @@ -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 );
}

/**
Expand Down Expand Up @@ -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.
*
Expand Down
54 changes: 53 additions & 1 deletion packages/blocks/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
*
Expand All @@ -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 );
} );
};
4 changes: 2 additions & 2 deletions packages/editor/src/components/block-switcher/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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 );
Expand Down
4 changes: 2 additions & 2 deletions packages/editor/src/components/block-types-list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
)
}
Expand All @@ -62,7 +62,7 @@ class BlockTypesList extends Component {
style={ itemIconStyle }
>
<BlockIcon icon={ item.icon && item.icon.src } showColors />
{ item.hasChildBlocks &&
{ item.hasChildBlocksWithInserterSupport &&
<span
className="editor-block-types-list__item-icon-stack"
style={ itemIconStackStyle }
Expand Down
4 changes: 2 additions & 2 deletions packages/editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import createSelector from 'rememo';
/**
* WordPress dependencies
*/
import { serialize, getBlockType, getBlockTypes, hasBlockSupport, hasChildBlocks, getUnknownTypeHandlerName } from '@wordpress/blocks';
import { serialize, getBlockType, getBlockTypes, hasBlockSupport, hasChildBlocksWithInserterSupport, getUnknownTypeHandlerName } from '@wordpress/blocks';
import { moment } from '@wordpress/date';
import { removep } from '@wordpress/autop';

Expand Down Expand Up @@ -1571,7 +1571,7 @@ export const getInserterItems = createSelector(
isDisabled,
utility: calculateUtility( blockType.category, count, isContextual ),
frecency: calculateFrecency( time, count ),
hasChildBlocks: hasChildBlocks( blockType.name ),
hasChildBlocksWithInserterSupport: hasChildBlocksWithInserterSupport( blockType.name ),
};
};

Expand Down
2 changes: 1 addition & 1 deletion packages/editor/src/store/test/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -3084,7 +3084,7 @@ describe( 'selectors', () => {
isDisabled: false,
utility: 0,
frecency: 0,
hasChildBlocks: false,
hasChildBlocksWithInserterSupport: false,
} );
const reusableBlockItem = items.find( ( item ) => item.id === 'core/block/1' );
expect( reusableBlockItem ).toEqual( {
Expand Down

0 comments on commit cd167ce

Please sign in to comment.