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 Variations: Support dot notation in isActive string array #62088

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/reference-guides/block-api/block-variations.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,12 @@ The `string[]` version is used to declare which attributes should be compared as
isActive: [ 'providerNameSlug' ]
```

Nested object paths are also supported. For example, consider a block variation that has a `query` object as an attribute. It is possible to determine if the variation is active solely based on that object's `postType` property (while ignoring all its other properties):

```js
isActive: [ 'query.postType' ]
```

### Caveats to using `isActive`

The `isActive` property can return false positives if multiple variations exist for a specific block and the `isActive` checks are not specific enough. To demonstrate this, consider the following example:
Expand Down
4 changes: 1 addition & 3 deletions packages/block-library/src/query/variations.js
Copy link
Contributor Author

Choose a reason for hiding this comment

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

❤️

Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,7 @@ const variations = [
},
},
scope: [ 'inserter' ],
isActive: ( { namespace, query } ) => {
return namespace === 'core/posts-list' && query.postType === 'post';
},
isActive: [ 'namespace', 'query.postType' ],
},
{
name: 'title-date',
Expand Down
26 changes: 20 additions & 6 deletions packages/blocks/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,16 +243,30 @@ export function getActiveBlockVariation( state, blockName, attributes, scope ) {
const blockType = getBlockType( state, blockName );
const attributeKeys = Object.keys( blockType?.attributes || {} );
const definedAttributes = variation.isActive.filter(
( attribute ) => attributeKeys.includes( attribute )
( attribute ) => {
// We support nested attribute paths, e.g. `layout.type`.
// In this case, we need to check if the part before the
// first dot is a known attribute.
const topLevelAttribute = attribute.split( '.' )[ 0 ];
return attributeKeys.includes( topLevelAttribute );
}
);
if ( definedAttributes.length === 0 ) {
return false;
}
return definedAttributes.every(
( attribute ) =>
attributes[ attribute ] ===
variation.attributes[ attribute ]
);
return definedAttributes.every( ( attribute ) => {
const attributeValue = getValueFromObjectPath(
attributes,
attribute
);
if ( attributeValue === undefined ) {
ntsekouras marked this conversation as resolved.
Show resolved Hide resolved
return false;
}
return (
attributeValue ===
getValueFromObjectPath( variation.attributes, attribute )
);
} );
}

return variation.isActive?.( attributes, variation.attributes );
Expand Down
41 changes: 41 additions & 0 deletions packages/blocks/src/store/test/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,47 @@ describe( 'selectors', () => {
expect( result ).toEqual( variation );
} );
} );
it( 'should support nested attribute paths in the isActive array', () => {
const variations = [
{
name: 'variation-1',
attributes: {
firstTestAttribute: {
nestedProperty: 1,
otherNestedProperty: 5555,
},
},
isActive: [ 'firstTestAttribute.nestedProperty' ],
},
{
name: 'variation-2',
attributes: {
firstTestAttribute: {
nestedProperty: 2,
otherNestedProperty: 5555,
},
},
isActive: [ 'firstTestAttribute.nestedProperty' ],
},
];
const state =
createBlockVariationsStateWithTestBlockType( variations );

expect(
getActiveBlockVariation( state, blockName, {
firstTestAttribute: {
nestedProperty: 1,
},
} )
).toEqual( variations[ 0 ] );
expect(
getActiveBlockVariation( state, blockName, {
firstTestAttribute: {
nestedProperty: 2,
},
} )
).toEqual( variations[ 1 ] );
} );
it( 'should return the active variation based on the given isActive array (multiple values)', () => {
const variations = [
{
Expand Down
Loading