Skip to content

Commit

Permalink
Query block setup with block patterns integration (#28891)
Browse files Browse the repository at this point in the history
* first stab

* first iterations from design

Keyboard navigation, style changes, refactor LayoutStep, create `usePostTypes` util hook

* remove duplicate imports from rebase

* design iteration part 2 + keyboard navigation

* Matching block patterns API v1

* change API

* move and change block patterns

* Polish

* __experimentalGetScopedBlockPatterns doc and tests

* jsdoc usePostTypes

* show start empty at the end

* Improve thumbnails.

* fix empty variation

* Polish the labels.

Co-authored-by: jasmussen <[email protected]>
  • Loading branch information
ntsekouras and jasmussen authored Feb 25, 2021
1 parent f8f2c13 commit 68caf86
Show file tree
Hide file tree
Showing 12 changed files with 669 additions and 52 deletions.
64 changes: 64 additions & 0 deletions lib/block-patterns.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
/**
* Block patterns registration.
*
* @package gutenberg
*/

// Initial Query block patterns.
register_block_pattern(
'query/large-posts',
array(
'title' => __( 'Large', 'gutenberg' ),
'scope' => array(
'inserter' => false,
'block' => array( 'core/query' ),
),
'content' => '<!-- wp:post-title {"isLink":true} /-->
<!-- wp:post-featured-image {"isLink":true,"align":"wide"} /-->
<!-- wp:post-excerpt /-->
<!-- wp:separator -->
<hr class="wp-block-separator"/>
<!-- /wp:separator -->
<!-- wp:post-date /-->',
)
);

register_block_pattern(
'query/medium-posts',
array(
'title' => __( 'Medium', 'gutenberg' ),
'scope' => array(
'inserter' => false,
'block' => array( 'core/query' ),
),
'content' => '<!-- wp:columns {"align":"wide"} -->
<div class="wp-block-columns alignwide"><!-- wp:column {"width":"66.66%"} -->
<div class="wp-block-column" style="flex-basis:66.66%"><!-- wp:post-featured-image {"isLink":true} /--></div>
<!-- /wp:column -->
<!-- wp:column {"width":"33.33%"} -->
<div class="wp-block-column" style="flex-basis:33.33%"><!-- wp:post-title {"isLink":true} /-->
<!-- wp:post-excerpt /--></div>
<!-- /wp:column --></div>
<!-- /wp:columns -->',
)
);

register_block_pattern(
'query/small-posts',
array(
'title' => __( 'Small', 'gutenberg' ),
'scope' => array(
'inserter' => false,
'block' => array( 'core/query' ),
),
'content' => '<!-- wp:columns {"verticalAlignment":"center"} -->
<div class="wp-block-columns are-vertically-aligned-center"><!-- wp:column {"verticalAlignment":"center","width":"25%"} -->
<div class="wp-block-column is-vertically-aligned-center" style="flex-basis:25%"><!-- wp:post-featured-image {"isLink":true} /--></div>
<!-- /wp:column -->
<!-- wp:column {"verticalAlignment":"center","width":"75%"} -->
<div class="wp-block-column is-vertically-aligned-center" style="flex-basis:75%"><!-- wp:post-title {"isLink":true} /--></div>
<!-- /wp:column --></div>
<!-- /wp:columns -->',
)
);
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/full-site-editing/edit-site-export.php';

require __DIR__ . '/blocks.php';
require __DIR__ . '/block-patterns.php';
require __DIR__ . '/client-assets.php';
require __DIR__ . '/demo.php';
require __DIR__ . '/widgets.php';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,13 @@ const usePatternsState = ( onInsert, rootClientId ) => {
const { __experimentalGetAllowedPatterns, getSettings } = select(
blockEditorStore
);
const inserterPatterns = __experimentalGetAllowedPatterns(
rootClientId
).filter(
( pattern ) => ! pattern.scope || pattern.scope.inserter
);
return {
patterns: __experimentalGetAllowedPatterns( rootClientId ),
patterns: inserterPatterns,
patternCategories: getSettings()
.__experimentalBlockPatternCategories,
};
Expand Down
26 changes: 26 additions & 0 deletions packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -1801,6 +1801,32 @@ export const __experimentalGetAllowedPatterns = createSelector(
]
);

/**
* Returns the list of patterns based on specific `scope` and
* a block's name.
* `inserter` scope should be handled differently, probably in
* combination with `__experimentalGetAllowedPatterns`.
* For now `__experimentalGetScopedBlockPatterns` handles properly
* all other scopes.
* Since both APIs are experimental we should revisit this.
*
* @param {Object} state Editor state.
* @param {string} scope Block pattern scope.
* @param {string} blockName Block's name.
*
* @return {Array} The list of matched block patterns based on provided scope and block name.
*/
export const __experimentalGetScopedBlockPatterns = createSelector(
( state, scope, blockName ) => {
if ( ! scope && ! blockName ) return EMPTY_ARRAY;
const patterns = state.settings.__experimentalBlockPatterns;
return patterns.filter( ( pattern ) =>
pattern.scope?.[ scope ]?.includes?.( blockName )
);
},
( state ) => [ state.settings.__experimentalBlockPatterns ]
);

/**
* Returns the Block List settings of a block, if any exist.
*
Expand Down
48 changes: 48 additions & 0 deletions packages/block-editor/src/store/test/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const {
__experimentalGetActiveBlockIdByBlockNames: getActiveBlockIdByBlockNames,
__experimentalGetParsedReusableBlock,
__experimentalGetAllowedPatterns,
__experimentalGetScopedBlockPatterns,
} = selectors;

describe( 'selectors', () => {
Expand Down Expand Up @@ -3402,6 +3403,53 @@ describe( 'selectors', () => {
).toHaveLength( 0 );
} );
} );
describe( '__experimentalGetScopedBlockPatterns', () => {
const state = {
blocks: {},
settings: {
__experimentalBlockPatterns: [
{
title: 'pattern a',
scope: { block: [ 'test/block-a' ] },
},
{
title: 'pattern b',
scope: { block: [ 'test/block-b' ] },
},
],
},
};
it( 'should return empty array if no scope and block name is provided', () => {
expect( __experimentalGetScopedBlockPatterns( state ) ).toEqual(
[]
);
expect(
__experimentalGetScopedBlockPatterns( state, 'block' )
).toEqual( [] );
} );
it( 'shoud return empty array if no match is found', () => {
const patterns = __experimentalGetScopedBlockPatterns(
state,
'block',
'test/block-not-exists'
);
expect( patterns ).toEqual( [] );
} );
it( 'should return proper results when there are matched block patterns', () => {
const patterns = __experimentalGetScopedBlockPatterns(
state,
'block',
'test/block-a'
);
expect( patterns ).toHaveLength( 1 );
expect( patterns[ 0 ] ).toEqual(
expect.objectContaining( {
title: 'pattern a',
scope: { block: [ 'test/block-a' ] },
} )
);
} );
} );
} );

describe( '__experimentalGetParsedReusableBlock', () => {
Expand Down
49 changes: 49 additions & 0 deletions packages/block-library/src/query/edit/block-setup/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { useBlockProps } from '@wordpress/block-editor';
import { store as blocksStore } from '@wordpress/blocks';
import { Placeholder } from '@wordpress/components';

/**
* Internal dependencies
*/
import LayoutSetupStep from './layout-step';

const BlockSetup = ( {
blockName,
useLayoutSetup,
onVariationSelect = () => {},
onBlockPatternSelect = () => {},
children,
} ) => {
const { blockType } = useSelect(
( select ) => {
const { getBlockType } = select( blocksStore );
return { blockType: getBlockType( blockName ) };
},
[ blockName ]
);
const blockProps = useBlockProps();
return (
<div { ...blockProps }>
<Placeholder
icon={ blockType?.icon?.src }
label={ blockType?.title }
isColumnLayout
>
{ useLayoutSetup && (
<LayoutSetupStep
blockType={ blockType }
onVariationSelect={ onVariationSelect }
onBlockPatternSelect={ onBlockPatternSelect }
/>
) }
{ children }
</Placeholder>
</div>
);
};

export default BlockSetup;
Loading

0 comments on commit 68caf86

Please sign in to comment.