diff --git a/packages/block-editor/src/components/inserter/test/fixtures/index.js b/packages/block-editor/src/components/inserter/test/fixtures/index.js index 5d87650bbb077..c46620ec156dc 100644 --- a/packages/block-editor/src/components/inserter/test/fixtures/index.js +++ b/packages/block-editor/src/components/inserter/test/fixtures/index.js @@ -40,6 +40,21 @@ export const withSingleVariationItem = { ], }; +export const withDefaultVariationItem = { + id: 'core/block-with-default-variation', + name: 'core/block-with-default-variation', + description: 'core description', + initialAttributes: {}, + category: 'text', + variations: [ + { + name: 'special', + title: 'Special', + isDefault: true, + }, + ], +}; + export const withVariationsItem = { id: 'core/block-with-variations', name: 'core/block-with-variations', diff --git a/packages/block-editor/src/components/inserter/test/utils.js b/packages/block-editor/src/components/inserter/test/utils.js index e86bf4afbb105..d09376f55f6b5 100644 --- a/packages/block-editor/src/components/inserter/test/utils.js +++ b/packages/block-editor/src/components/inserter/test/utils.js @@ -7,11 +7,33 @@ import { someOtherItem, withVariationsItem, withSingleVariationItem, + withDefaultVariationItem, } from './fixtures'; import { includeVariationsInInserterItems } from '../utils'; describe( 'inserter utils', () => { describe( 'includeVariationsInInserterItems', () => { + it( 'should let a block type be replaced with the default variation', () => { + // The base block type is replaced with the default variation + expect( + includeVariationsInInserterItems( [ withDefaultVariationItem ] ) + ).toEqual( [ + expect.objectContaining( { + id: 'core/block-with-default-variation-special', + } ), + ] ); + // The base block type is supplemented by non-default variations + expect( + includeVariationsInInserterItems( [ withSingleVariationItem ] ) + ).toEqual( [ + expect.objectContaining( { + id: 'core/embed', + } ), + expect.objectContaining( { + id: 'core/embed-youtube', + } ), + ] ); + } ); it( 'should return items if limit is equal to items length', () => { const items = [ moreItem, paragraphItem, someOtherItem ]; const res = includeVariationsInInserterItems( items, 3 ); @@ -27,6 +49,28 @@ describe( 'inserter utils', () => { const res = includeVariationsInInserterItems( items, 2 ); expect( res ).toEqual( [ moreItem, paragraphItem ] ); } ); + it( 'should fill the items with variations, if limit is set and items are fewer than limit and variations exist', () => { + const items = [ moreItem, paragraphItem, withVariationsItem ]; + const res = includeVariationsInInserterItems( items, 5 ); + expect( res.length ).toEqual( 5 ); + expect( res ).toEqual( [ + ...items, + expect.objectContaining( { + id: 'core/block-with-variations-variation-one', + title: 'Variation One', + } ), + expect.objectContaining( { + id: 'core/block-with-variations-variation-two', + title: 'Variation Two', + } ), + ] ); + } ); + it( 'should return the items, if limit is set and items are fewer than limit and variations do NOT exist', () => { + const items = [ moreItem, paragraphItem, someOtherItem ]; + const res = includeVariationsInInserterItems( items, 4 ); + expect( res.length ).toEqual( 3 ); + expect( res ).toEqual( items ); + } ); it( 'should return proper result if no limit provided and block variations do NOT exist', () => { const items = [ moreItem, paragraphItem, someOtherItem ]; const res = includeVariationsInInserterItems( items ); diff --git a/packages/block-editor/src/components/inserter/utils.js b/packages/block-editor/src/components/inserter/utils.js index a30d8a712718b..08f3ca03ae8f2 100644 --- a/packages/block-editor/src/components/inserter/utils.js +++ b/packages/block-editor/src/components/inserter/utils.js @@ -29,28 +29,30 @@ const getItemFromVariation = ( item ) => ( variation ) => ( { * @return {Array} Normalized inserter items. */ export function includeVariationsInInserterItems( items, limit = Infinity ) { - if ( items.length >= limit ) { - // No need to iterate for variations - return items.slice( 0, limit ); - } - // Show all available blocks with variations - return items.reduce( ( result, item ) => { - const { variations = [] } = item; - const hasDefaultVariation = variations.some( - ( { isDefault } ) => isDefault - ); + // Exclude any block type item that is to be replaced by a default + // variation. + const filteredItems = items.filter( + ( { variations = [] } ) => + ! variations.some( ( { isDefault } ) => isDefault ) + ); - // If there is no default inserter variation provided, - // then default block type is displayed. - if ( ! hasDefaultVariation ) { - result.push( item ); - } + // Fill `variationsToAdd` until there are as many items in total as + // `limit`. + const variationsToAdd = []; + if ( filteredItems.length < limit ) { + // Show all available blocks with variations + for ( const item of items ) { + if ( filteredItems.length + variationsToAdd.length >= limit ) { + break; + } - if ( variations.length ) { - const variationMapper = getItemFromVariation( item ); - result.push( ...variations.map( variationMapper ) ); + const { variations = [] } = item; + if ( variations.length ) { + const variationMapper = getItemFromVariation( item ); + variationsToAdd.push( ...variations.map( variationMapper ) ); + } } + } - return result; - }, [] ); + return [ ...filteredItems, ...variationsToAdd ].slice( 0, limit ); }