Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block API: Allow "array of attributes to be compared" for isActive property in block variations #30913

Merged
merged 19 commits into from
Apr 22, 2021

Conversation

david-szabo97
Copy link
Member

@david-szabo97 david-szabo97 commented Apr 16, 2021

Fixes #30739

Description

Extends the variations API by adding one more possible way to define how active variations are recognized.

The only way currently in trunk is to use an isActive function. In this PR we introduce array of strings for isActive property.

Most of our variations use the following pattern:

variations.forEach( ( variation ) => {
if ( variation.isActive ) return;
variation.isActive = ( blockAttributes, variationAttributes ) =>
blockAttributes.providerNameSlug ===
variationAttributes.providerNameSlug;
} );

As you can see, we are just creating a function for each variation and check for a specific attribute whether it matches or not. Basically, this is what we do for (almost) all of our variations so far.

To reduce boilerplate code, we can now use an array of strings to do the same check behind the scenes:

variations.forEach( ( variation ) => {
	if ( variation.isActive ) return;
	variation.isActive = [ 'providerNameSlug' ];
} );

Every element in the array represents an attribute to be compared. If each attribute matches then it is considered active. For example:

isActive: [ 'theme', 'level' ]

translates to

( blockAttributes, variationAttributes ) =>
		blockAttributes.theme === variationAttributes.theme &&
		blockAttributes.level === variationAttributes.level ;

How has this been tested?

  1. Tests should pass

  2. Smoke test, make sure all blocks using variations are still working as before

Replace

variation.isActive = ( blockAttributes, variationAttributes ) =>

with

	variation.isActive = [ 'service' ];

Make sure Social Link block still works the same way as before.

Types of changes

New feature (non-breaking change which adds functionality)

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • I've tested my changes with keyboard and screen readers.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR (please manually search all *.native.js files for terms that need renaming or removal).

@david-szabo97 david-szabo97 self-assigned this Apr 16, 2021
@github-actions
Copy link

github-actions bot commented Apr 16, 2021

Size Change: +4.04 kB (0%)

Total Size: 1.47 MB

Filename Size Change
build/annotations/index.js 3.78 kB +3 B (0%)
build/api-fetch/index.js 3.41 kB -1 B (0%)
build/autop/index.js 2.83 kB +16 B (+1%)
build/block-directory/index.js 8.62 kB +2 B (0%)
build/block-editor/index.js 130 kB +1 kB (+1%)
build/block-editor/style-rtl.css 12.6 kB +56 B (0%)
build/block-editor/style.css 12.6 kB +54 B (0%)
build/block-library/blocks/file/editor-rtl.css 301 B +126 B (+72%) 🆘
build/block-library/blocks/file/editor.css 300 B +126 B (+72%) 🆘
build/block-library/blocks/file/style-rtl.css 255 B +7 B (+3%)
build/block-library/blocks/file/style.css 255 B +7 B (+3%)
build/block-library/editor-rtl.css 9.83 kB +35 B (0%)
build/block-library/editor.css 9.82 kB +36 B (0%)
build/block-library/index.js 154 kB +861 B (+1%)
build/block-library/style-rtl.css 9.44 kB +6 B (0%)
build/block-library/style.css 9.44 kB +6 B (0%)
build/block-serialization-default-parser/index.js 1.87 kB +4 B (0%)
build/blocks/index.js 48.7 kB +174 B (0%)
build/components/index.js 285 kB -633 B (0%)
build/components/style-rtl.css 16.2 kB -11 B (0%)
build/components/style.css 16.2 kB -11 B (0%)
build/compose/index.js 11.6 kB +327 B (+3%)
build/core-data/index.js 17.2 kB +44 B (0%)
build/customize-widgets/index.js 8.25 kB +1.14 kB (+16%) ⚠️
build/data-controls/index.js 836 B +1 B (0%)
build/data/index.js 8.87 kB -4 B (0%)
build/date/index.js 31.9 kB -1 B (0%)
build/dom/index.js 5.12 kB +22 B (0%)
build/edit-navigation/index.js 17 kB +13 B (0%)
build/edit-navigation/style-rtl.css 2.86 kB +4 B (0%)
build/edit-navigation/style.css 2.86 kB +4 B (0%)
build/edit-post/index.js 339 kB +245 B (0%)
build/edit-post/style-rtl.css 6.96 kB -30 B (0%)
build/edit-post/style.css 6.95 kB -31 B (0%)
build/edit-site/index.js 28.7 kB +452 B (+2%)
build/edit-widgets/index.js 16.7 kB -101 B (-1%)
build/editor/index.js 42.6 kB +31 B (0%)
build/editor/style-rtl.css 3.9 kB -20 B (-1%)
build/editor/style.css 3.9 kB -21 B (-1%)
build/element/index.js 4.62 kB +8 B (0%)
build/format-library/index.js 6.77 kB +20 B (0%)
build/keyboard-shortcuts/index.js 2.53 kB +8 B (0%)
build/keycodes/index.js 1.95 kB -1 B (0%)
build/list-reusable-blocks/index.js 3.19 kB -1 B (0%)
build/media-utils/index.js 5.39 kB +14 B (0%)
build/nux/index.js 3.42 kB +11 B (0%)
build/plugins/index.js 2.95 kB -2 B (0%)
build/primitives/index.js 1.42 kB -1 B (0%)
build/react-i18n/index.js 1.45 kB -2 B (0%)
build/reusable-blocks/index.js 3.8 kB +18 B (0%)
build/rich-text/index.js 13.5 kB +37 B (0%)
build/url/index.js 3.01 kB -2 B (0%)
build/viewport/index.js 1.85 kB -4 B (0%)
build/warning/index.js 1.14 kB +1 B (0%)
build/wordcount/index.js 1.22 kB -1 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.14 kB 0 B
build/blob/index.js 664 B 0 B
build/block-directory/style-rtl.css 1 kB 0 B
build/block-directory/style.css 1.01 kB 0 B
build/block-library/blocks/archives/editor-rtl.css 61 B 0 B
build/block-library/blocks/archives/editor.css 60 B 0 B
build/block-library/blocks/audio/editor-rtl.css 58 B 0 B
build/block-library/blocks/audio/editor.css 58 B 0 B
build/block-library/blocks/audio/style-rtl.css 112 B 0 B
build/block-library/blocks/audio/style.css 112 B 0 B
build/block-library/blocks/block/editor-rtl.css 161 B 0 B
build/block-library/blocks/block/editor.css 161 B 0 B
build/block-library/blocks/button/editor-rtl.css 475 B 0 B
build/block-library/blocks/button/editor.css 474 B 0 B
build/block-library/blocks/button/style-rtl.css 503 B 0 B
build/block-library/blocks/button/style.css 503 B 0 B
build/block-library/blocks/buttons/editor-rtl.css 315 B 0 B
build/block-library/blocks/buttons/editor.css 315 B 0 B
build/block-library/blocks/buttons/style-rtl.css 368 B 0 B
build/block-library/blocks/buttons/style.css 368 B 0 B
build/block-library/blocks/calendar/style-rtl.css 208 B 0 B
build/block-library/blocks/calendar/style.css 208 B 0 B
build/block-library/blocks/categories/editor-rtl.css 84 B 0 B
build/block-library/blocks/categories/editor.css 83 B 0 B
build/block-library/blocks/categories/style-rtl.css 79 B 0 B
build/block-library/blocks/categories/style.css 79 B 0 B
build/block-library/blocks/code/style-rtl.css 90 B 0 B
build/block-library/blocks/code/style.css 90 B 0 B
build/block-library/blocks/columns/editor-rtl.css 190 B 0 B
build/block-library/blocks/columns/editor.css 190 B 0 B
build/block-library/blocks/columns/style-rtl.css 436 B 0 B
build/block-library/blocks/columns/style.css 435 B 0 B
build/block-library/blocks/cover/editor-rtl.css 605 B 0 B
build/block-library/blocks/cover/editor.css 605 B 0 B
build/block-library/blocks/cover/style-rtl.css 1.23 kB 0 B
build/block-library/blocks/cover/style.css 1.23 kB 0 B
build/block-library/blocks/embed/editor-rtl.css 486 B 0 B
build/block-library/blocks/embed/editor.css 486 B 0 B
build/block-library/blocks/embed/style-rtl.css 401 B 0 B
build/block-library/blocks/embed/style.css 400 B 0 B
build/block-library/blocks/file/frontend.js 765 B 0 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB 0 B
build/block-library/blocks/freeform/editor.css 2.44 kB 0 B
build/block-library/blocks/gallery/editor-rtl.css 704 B 0 B
build/block-library/blocks/gallery/editor.css 705 B 0 B
build/block-library/blocks/gallery/style-rtl.css 1.09 kB 0 B
build/block-library/blocks/gallery/style.css 1.09 kB 0 B
build/block-library/blocks/group/editor-rtl.css 160 B 0 B
build/block-library/blocks/group/editor.css 160 B 0 B
build/block-library/blocks/group/style-rtl.css 57 B 0 B
build/block-library/blocks/group/style.css 57 B 0 B
build/block-library/blocks/heading/editor-rtl.css 129 B 0 B
build/block-library/blocks/heading/editor.css 129 B 0 B
build/block-library/blocks/heading/style-rtl.css 76 B 0 B
build/block-library/blocks/heading/style.css 76 B 0 B
build/block-library/blocks/html/editor-rtl.css 281 B 0 B
build/block-library/blocks/html/editor.css 281 B 0 B
build/block-library/blocks/image/editor-rtl.css 717 B 0 B
build/block-library/blocks/image/editor.css 716 B 0 B
build/block-library/blocks/image/style-rtl.css 476 B 0 B
build/block-library/blocks/image/style.css 478 B 0 B
build/block-library/blocks/latest-comments/style-rtl.css 281 B 0 B
build/block-library/blocks/latest-comments/style.css 282 B 0 B
build/block-library/blocks/latest-posts/editor-rtl.css 137 B 0 B
build/block-library/blocks/latest-posts/editor.css 137 B 0 B
build/block-library/blocks/latest-posts/style-rtl.css 523 B 0 B
build/block-library/blocks/latest-posts/style.css 522 B 0 B
build/block-library/blocks/legacy-widget/editor-rtl.css 398 B 0 B
build/block-library/blocks/legacy-widget/editor.css 399 B 0 B
build/block-library/blocks/list/style-rtl.css 63 B 0 B
build/block-library/blocks/list/style.css 63 B 0 B
build/block-library/blocks/media-text/editor-rtl.css 191 B 0 B
build/block-library/blocks/media-text/editor.css 191 B 0 B
build/block-library/blocks/media-text/style-rtl.css 535 B 0 B
build/block-library/blocks/media-text/style.css 532 B 0 B
build/block-library/blocks/more/editor-rtl.css 434 B 0 B
build/block-library/blocks/more/editor.css 434 B 0 B
build/block-library/blocks/navigation-link/editor-rtl.css 597 B 0 B
build/block-library/blocks/navigation-link/editor.css 597 B 0 B
build/block-library/blocks/navigation-link/style-rtl.css 1.07 kB 0 B
build/block-library/blocks/navigation-link/style.css 1.07 kB 0 B
build/block-library/blocks/navigation/editor-rtl.css 1.24 kB 0 B
build/block-library/blocks/navigation/editor.css 1.24 kB 0 B
build/block-library/blocks/navigation/style-rtl.css 272 B 0 B
build/block-library/blocks/navigation/style.css 271 B 0 B
build/block-library/blocks/nextpage/editor-rtl.css 395 B 0 B
build/block-library/blocks/nextpage/editor.css 395 B 0 B
build/block-library/blocks/page-list/editor-rtl.css 239 B 0 B
build/block-library/blocks/page-list/editor.css 240 B 0 B
build/block-library/blocks/page-list/style-rtl.css 167 B 0 B
build/block-library/blocks/page-list/style.css 167 B 0 B
build/block-library/blocks/paragraph/editor-rtl.css 157 B 0 B
build/block-library/blocks/paragraph/editor.css 157 B 0 B
build/block-library/blocks/paragraph/style-rtl.css 247 B 0 B
build/block-library/blocks/paragraph/style.css 248 B 0 B
build/block-library/blocks/post-author/editor-rtl.css 209 B 0 B
build/block-library/blocks/post-author/editor.css 209 B 0 B
build/block-library/blocks/post-author/style-rtl.css 183 B 0 B
build/block-library/blocks/post-author/style.css 184 B 0 B
build/block-library/blocks/post-comments-form/style-rtl.css 250 B 0 B
build/block-library/blocks/post-comments-form/style.css 250 B 0 B
build/block-library/blocks/post-content/editor-rtl.css 139 B 0 B
build/block-library/blocks/post-content/editor.css 139 B 0 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B 0 B
build/block-library/blocks/post-excerpt/editor.css 73 B 0 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B 0 B
build/block-library/blocks/post-excerpt/style.css 69 B 0 B
build/block-library/blocks/post-featured-image/editor-rtl.css 338 B 0 B
build/block-library/blocks/post-featured-image/editor.css 338 B 0 B
build/block-library/blocks/post-featured-image/style-rtl.css 100 B 0 B
build/block-library/blocks/post-featured-image/style.css 100 B 0 B
build/block-library/blocks/post-title/style-rtl.css 60 B 0 B
build/block-library/blocks/post-title/style.css 60 B 0 B
build/block-library/blocks/preformatted/style-rtl.css 103 B 0 B
build/block-library/blocks/preformatted/style.css 103 B 0 B
build/block-library/blocks/pullquote/editor-rtl.css 183 B 0 B
build/block-library/blocks/pullquote/editor.css 183 B 0 B
build/block-library/blocks/pullquote/style-rtl.css 318 B 0 B
build/block-library/blocks/pullquote/style.css 318 B 0 B
build/block-library/blocks/query-loop/editor-rtl.css 83 B 0 B
build/block-library/blocks/query-loop/editor.css 82 B 0 B
build/block-library/blocks/query-loop/style-rtl.css 315 B 0 B
build/block-library/blocks/query-loop/style.css 317 B 0 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B 0 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B 0 B
build/block-library/blocks/query-pagination/editor-rtl.css 270 B 0 B
build/block-library/blocks/query-pagination/editor.css 262 B 0 B
build/block-library/blocks/query-pagination/style-rtl.css 168 B 0 B
build/block-library/blocks/query-pagination/style.css 168 B 0 B
build/block-library/blocks/query-title/editor-rtl.css 86 B 0 B
build/block-library/blocks/query-title/editor.css 86 B 0 B
build/block-library/blocks/query/editor-rtl.css 810 B 0 B
build/block-library/blocks/query/editor.css 809 B 0 B
build/block-library/blocks/quote/style-rtl.css 169 B 0 B
build/block-library/blocks/quote/style.css 169 B 0 B
build/block-library/blocks/rss/editor-rtl.css 201 B 0 B
build/block-library/blocks/rss/editor.css 202 B 0 B
build/block-library/blocks/rss/style-rtl.css 290 B 0 B
build/block-library/blocks/rss/style.css 290 B 0 B
build/block-library/blocks/search/editor-rtl.css 189 B 0 B
build/block-library/blocks/search/editor.css 189 B 0 B
build/block-library/blocks/search/style-rtl.css 359 B 0 B
build/block-library/blocks/search/style.css 362 B 0 B
build/block-library/blocks/separator/editor-rtl.css 99 B 0 B
build/block-library/blocks/separator/editor.css 99 B 0 B
build/block-library/blocks/separator/style-rtl.css 251 B 0 B
build/block-library/blocks/separator/style.css 251 B 0 B
build/block-library/blocks/shortcode/editor-rtl.css 512 B 0 B
build/block-library/blocks/shortcode/editor.css 512 B 0 B
build/block-library/blocks/site-logo/editor-rtl.css 440 B 0 B
build/block-library/blocks/site-logo/editor.css 441 B 0 B
build/block-library/blocks/site-logo/style-rtl.css 154 B 0 B
build/block-library/blocks/site-logo/style.css 154 B 0 B
build/block-library/blocks/social-link/editor-rtl.css 164 B 0 B
build/block-library/blocks/social-link/editor.css 165 B 0 B
build/block-library/blocks/social-links/editor-rtl.css 796 B 0 B
build/block-library/blocks/social-links/editor.css 795 B 0 B
build/block-library/blocks/social-links/style-rtl.css 1.32 kB 0 B
build/block-library/blocks/social-links/style.css 1.33 kB 0 B
build/block-library/blocks/spacer/editor-rtl.css 308 B 0 B
build/block-library/blocks/spacer/editor.css 308 B 0 B
build/block-library/blocks/spacer/style-rtl.css 48 B 0 B
build/block-library/blocks/spacer/style.css 48 B 0 B
build/block-library/blocks/table/editor-rtl.css 478 B 0 B
build/block-library/blocks/table/editor.css 478 B 0 B
build/block-library/blocks/table/style-rtl.css 402 B 0 B
build/block-library/blocks/table/style.css 402 B 0 B
build/block-library/blocks/tag-cloud/editor-rtl.css 118 B 0 B
build/block-library/blocks/tag-cloud/editor.css 118 B 0 B
build/block-library/blocks/tag-cloud/style-rtl.css 94 B 0 B
build/block-library/blocks/tag-cloud/style.css 94 B 0 B
build/block-library/blocks/template-part/editor-rtl.css 552 B 0 B
build/block-library/blocks/template-part/editor.css 551 B 0 B
build/block-library/blocks/term-description/editor-rtl.css 90 B 0 B
build/block-library/blocks/term-description/editor.css 90 B 0 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B 0 B
build/block-library/blocks/text-columns/editor.css 95 B 0 B
build/block-library/blocks/text-columns/style-rtl.css 166 B 0 B
build/block-library/blocks/text-columns/style.css 166 B 0 B
build/block-library/blocks/verse/style-rtl.css 87 B 0 B
build/block-library/blocks/verse/style.css 87 B 0 B
build/block-library/blocks/video/editor-rtl.css 568 B 0 B
build/block-library/blocks/video/editor.css 569 B 0 B
build/block-library/blocks/video/style-rtl.css 173 B 0 B
build/block-library/blocks/video/style.css 173 B 0 B
build/block-library/common-rtl.css 1.31 kB 0 B
build/block-library/common.css 1.31 kB 0 B
build/block-library/reset-rtl.css 502 B 0 B
build/block-library/reset.css 503 B 0 B
build/block-library/theme-rtl.css 692 B 0 B
build/block-library/theme.css 693 B 0 B
build/block-serialization-spec-parser/index.js 3.06 kB 0 B
build/customize-widgets/style-rtl.css 630 B 0 B
build/customize-widgets/style.css 631 B 0 B
build/deprecated/index.js 787 B 0 B
build/dom-ready/index.js 577 B 0 B
build/edit-post/classic-rtl.css 454 B 0 B
build/edit-post/classic.css 454 B 0 B
build/edit-site/style-rtl.css 4.9 kB 0 B
build/edit-site/style.css 4.89 kB 0 B
build/edit-widgets/style-rtl.css 2.97 kB 0 B
build/edit-widgets/style.css 2.98 kB 0 B
build/escape-html/index.js 735 B 0 B
build/format-library/style-rtl.css 637 B 0 B
build/format-library/style.css 639 B 0 B
build/hooks/index.js 2.28 kB 0 B
build/html-entities/index.js 622 B 0 B
build/i18n/index.js 4.04 kB 0 B
build/is-shallow-equal/index.js 699 B 0 B
build/list-reusable-blocks/style-rtl.css 629 B 0 B
build/list-reusable-blocks/style.css 628 B 0 B
build/notices/index.js 1.85 kB 0 B
build/nux/style-rtl.css 731 B 0 B
build/nux/style.css 727 B 0 B
build/priority-queue/index.js 791 B 0 B
build/redux-routine/index.js 2.83 kB 0 B
build/reusable-blocks/style-rtl.css 225 B 0 B
build/reusable-blocks/style.css 225 B 0 B
build/server-side-render/index.js 2.6 kB 0 B
build/shortcode/index.js 1.7 kB 0 B
build/token-list/index.js 1.27 kB 0 B

compressed-size-action

@david-szabo97 david-szabo97 changed the title Add/block variation isactive array Blocks variations API: Allow array of attributes to be compared for isActive property Apr 19, 2021
@david-szabo97 david-szabo97 changed the title Blocks variations API: Allow array of attributes to be compared for isActive property Blocks variations API: Allow "array of attributes to be compared" for isActive property Apr 19, 2021
@david-szabo97 david-szabo97 added [Feature] Block Variations Block variations, including introducing new variations and variations as a feature [Package] Blocks /packages/blocks [Package] Block editor /packages/block-editor labels Apr 19, 2021
@david-szabo97 david-szabo97 marked this pull request as ready for review April 19, 2021 08:03
@gziolo gziolo requested a review from gwwar April 19, 2021 08:21
Copy link
Contributor

@ntsekouras ntsekouras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this @david-szabo97! 💯

In general this looks good. I haven't checked the tests you wrote for now, but I will after addressing the main thing about attributes validation.

docs/reference-guides/block-api/block-variations.md Outdated Show resolved Hide resolved
packages/blocks/src/store/selectors.js Outdated Show resolved Hide resolved
packages/blocks/src/store/selectors.js Show resolved Hide resolved
packages/blocks/src/store/selectors.js Outdated Show resolved Hide resolved
packages/blocks/src/store/selectors.js Show resolved Hide resolved
Copy link
Contributor

@gwwar gwwar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks pretty close @david-szabo97! I think this should be good to go once PR checks are ✅ and folks' feedback is addressed.

const blockType = getBlockType( state, blockName );
const attributeKeys = Object.keys( blockType.attributes || {} );
return variation.isActive
.filter( ( attribute ) => attributeKeys.includes( attribute ) )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: Would it be worth validating this earlier during block registration? It might be nice for folks to know that something isn't quite right when developing blocks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually that's what I had in mind too in my first comment. This way we will avoid calling this check so many times.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! First iteration is here: 637b62b

.every(
( attribute ) =>
attributes[ attribute ] ===
variation.attributes[ attribute ]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we'll still want to return false if either of these values is undefined. Blocks and variations may have optional attributes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't come up with a case for this 🤔 It seems to be working as expected:

  1. If both of them are undefined, then that's correct and should match.
  2. If variation.attributes[ attribute ] = undefined and attributes[ attribute ] != undefined then it won't match
  3. If variation.attributes[ attribute ] != undefined and attributes[ attribute ] = undefined then it won't match

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gwwar can you expand on the use case you have in mind with an example?

Copy link
Contributor

@gwwar gwwar Apr 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I missed 👀 that we were already iterating over variations instead of all possible block attributes, so only the left side may be undefined, eg attributes[ attribute ]. Code here is fine 👍

btw I personally find that code reuse in tests isn't that useful. What's nicer for me is being able to read a single test case without needing to skip to different definitions. (Fixtures/snapshots can also help when things go crazy). Curious if folks had thoughts on that.

Here's a free test case, where I verified this:

it( 'should handle optional attributes', () => {
				const testLinkName = 'test/link-block';
				const state = {
					blockTypes: {
						[ testLinkName ]: {
							name: testLinkName,
							attributes: {
								url: { type: 'string' },
								type: { type: 'string' },
								id: { type: 'number' },
							},
						},
					},
					blockVariations: {
						[ testLinkName ]: [
							{
								attributes: { url: 'https://wordpress.org' },
								isActive: [ 'url' ],
							},
							{
								attributes: { type: 'foo' },
								isActive: [ 'type' ],
							},
							{
								attributes: {
									type: 'bar',
									url: 'https://example.com',
								},
								isActive: [ 'type', 'url' ],
							},
						],
					},
				};

				expect(
					getActiveBlockVariation( state, testLinkName, {
						type: 'foo',
					} )
				).toEqual( {
					attributes: { type: 'foo' },
					isActive: [ 'type' ],
				} );

				expect(
					getActiveBlockVariation( state, testLinkName, {
						url: 'https://wordpress.org',
					} )
				).toEqual( {
					attributes: { url: 'https://wordpress.org' },
					isActive: [ 'url' ],
				} );

				expect(
					getActiveBlockVariation( state, testLinkName, {
						type: 'bar',
						url: 'https://example.com',
					} )
				).toEqual( {
					attributes: {
						type: 'bar',
						url: 'https://example.com',
					},
					isActive: [ 'type', 'url' ],
				} );

				expect(
					getActiveBlockVariation( state, testLinkName, {
						id: 1234,
					} )
				).toEqual( undefined );
			} );

Copy link
Member Author

@david-szabo97 david-szabo97 Apr 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I had that in mind too. 😄 That's why the last tests are totally separate. Definitely needs some cleaning. A little bit of reuse doesn't hurt though 😄

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A little bit of reuse doesn't hurt though

Certainly, I wanted to leave a note since I was having a bit of trouble reading what the state shape was without inspecting tests.

Copy link
Contributor

@gwwar gwwar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks solid to me @david-szabo97 ✨ Thanks for taking this one on!

I found another area where we should update before landing, which is the type definition in

* @property {Function} [isActive] A function that accepts a block's attributes
* and the variation's attributes and determines
* if a variation is active. This function doesn't
* try to find a match dynamically based on all
* block's attributes, as in many cases some
* attributes are irrelevant. An example would
* be for `embed` block where we only care about
* `providerNameSlug` attribute's value.

🤔 Optional/followup: I wonder if there's a way to get this typedef to help generate the block-variations.md. We do have support for autogenerating other examples with <!-- START TOKEN(Autogenerated API docs) --> and npm run docs:build

@gziolo @ntsekouras were there any other blocking changes needed here?

@gziolo
Copy link
Member

gziolo commented Apr 21, 2021

@gwwar, I will do a cross-check shortly. There is one follow-up that I can think of, it's changing API schema for block types in WordPress core to account for isActive as an array. In addition to that, we should be able to know to define isActive for Navigation Link block variations on the server 🎉

Copy link
Contributor

@ntsekouras ntsekouras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @david-szabo97 ! A last change that is needed and let's land.

packages/blocks/src/store/selectors.js Outdated Show resolved Hide resolved
dispatch( blocksStore ).addBlockTypes( settings );

return settings;
}

function validateVariations( settings ) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really sure where to put this. 😄 I'm also wondering why don't we dispatch( blocksStore ).addBlockVariation( settings.variations ) instead of handling variations here:

...get( blockType, [ 'variations' ], [] ),

For this reason we need to do the variations validation in two functions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we extract it to another PR? It isn't a blocker really and it requires some more thinking because you can register block variations also through the store directly. I don't remember exactly but most likely they are stored in two places in the store. It's similar to how block styles can be registered, so plugin authors could register styles or variations before the block gets registered so plugins wouldn't have to declare dependencies on each other.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I didn't know it meant to be that way - registering variation even without an existing block type. This comes with its own challenges 😄

I revert the commit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I double-checked, it's stored in one reducer but you can add variations with ADD_BLOCK_TYPES or ADD_BLOCK_VARIATIONS 😄

Copy link
Contributor

@ntsekouras ntsekouras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's 🚢 💯

@david-szabo97 david-szabo97 merged commit 971c0f6 into trunk Apr 22, 2021
@david-szabo97 david-szabo97 deleted the add/block-variation-isactive-array branch April 22, 2021 09:29
@github-actions github-actions bot added this to the Gutenberg 10.6 milestone Apr 22, 2021
@gziolo gziolo added the [Type] New API New API to be used by plugin developers or package users. label Apr 22, 2021
@gziolo gziolo changed the title Blocks variations API: Allow "array of attributes to be compared" for isActive property Blocks Variations: Allow "array of attributes to be compared" for isActive property Apr 22, 2021
@gziolo gziolo changed the title Blocks Variations: Allow "array of attributes to be compared" for isActive property Blocks API: Allow "array of attributes to be compared" for isActive property in block variations Apr 22, 2021
@gziolo gziolo added [Feature] Block API API that allows to express the block paradigm. and removed [Package] Blocks /packages/blocks labels Apr 22, 2021
@gziolo gziolo changed the title Blocks API: Allow "array of attributes to be compared" for isActive property in block variations Block API: Allow "array of attributes to be compared" for isActive property in block variations Apr 22, 2021
lipemat added a commit to lipemat/types-js-boilerplate that referenced this pull request May 19, 2021
Instead of a callback, you may pass an array of attributes which are
checked against the block to see if this variation is active.

WordPress/gutenberg#30913
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block API API that allows to express the block paradigm. [Feature] Block Variations Block variations, including introducing new variations and variations as a feature [Package] Block editor /packages/block-editor [Type] New API New API to be used by plugin developers or package users.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Blocks: Make it more flexible to match the currently applied block variation
4 participants