Skip to content

Commit

Permalink
Wipe traces of getBlockTypeActiveVariation
Browse files Browse the repository at this point in the history
  • Loading branch information
ockham committed Jun 10, 2024
1 parent c3ca16c commit 6bbb713
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 104 deletions.
18 changes: 0 additions & 18 deletions packages/blocks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,24 +190,6 @@ _Returns_

- `?Object`: Block type.

### getBlockTypeActiveVariation

Returns the active block variation for a given block based on its attributes. Variations are determined by their `isActive` property. Which is either an array of block attribute keys or a function.

In case of an array of block attribute keys, the `attributes` are compared to the variation's attributes using strict equality check.

In case of function type, the function should accept a block's attributes and the variation's attributes and determines if a variation is active. A function that accepts a block's attributes and the variation's attributes and determines if a variation is active.

_Parameters_

- _variations_ `Array`: Data state.
- _blockType_ `Object`: Name of block (example: “core/columns”).
- _attributes_ `Object`: Block attributes used to determine active variation.

_Returns_

- `(WPBlockVariation|undefined)`: Active block variation.

### getBlockTypes

Returns all registered blocks.
Expand Down
57 changes: 54 additions & 3 deletions packages/blocks/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ import removeAccents from 'remove-accents';
* WordPress dependencies
*/
import { createSelector } from '@wordpress/data';
import { RichTextData } from '@wordpress/rich-text';

/**
* Internal dependencies
*/
import { getValueFromObjectPath, getBlockTypeActiveVariation } from './utils';
import { getValueFromObjectPath, matchesAttributes } from './utils';

/** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */
/** @typedef {import('../api/registration').WPBlockVariationScope} WPBlockVariationScope */
Expand Down Expand Up @@ -173,6 +174,7 @@ export function getBlockStyles( state, name ) {
export const getBlockVariations = createSelector(
( state, blockName, scope ) => {
const variations = state.blockVariations[ blockName ];

if ( ! variations || ! scope ) {
return variations;
}
Expand Down Expand Up @@ -241,8 +243,57 @@ export function getActiveBlockVariation( state, blockName, attributes, scope ) {
}

const blockType = getBlockType( state, blockName );

return getBlockTypeActiveVariation( variations, blockType, attributes );
const attributeKeys = Object.keys( blockType?.attributes || {} );
let match;
let maxMatchedAttributes = 0;

for ( const variation of variations ) {
if ( Array.isArray( variation.isActive ) ) {
const definedAttributes = variation.isActive.filter(
( 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 );
}
);
const definedAttributesLength = definedAttributes.length;
if ( definedAttributesLength === 0 ) {
continue;
}
const isMatch = definedAttributes.every( ( attribute ) => {
const variationAttributeValue = getValueFromObjectPath(
variation.attributes,
attribute
);
if ( variationAttributeValue === undefined ) {
return false;
}
let blockAttributeValue = getValueFromObjectPath(
attributes,
attribute
);
if ( blockAttributeValue instanceof RichTextData ) {
blockAttributeValue = blockAttributeValue.toHTMLString();
}
return matchesAttributes(
blockAttributeValue,
variationAttributeValue
);
} );
if ( isMatch && definedAttributesLength > maxMatchedAttributes ) {
match = variation;
maxMatchedAttributes = definedAttributesLength;
}
} else if ( variation.isActive?.( attributes, variation.attributes ) ) {
// If isActive is a function, we cannot know how many attributes it matches.
// This means that we cannot compare the specificity of our matches,
// and simply return the best match we have found.
return match || variation;
}
}
return match;
}

/**
Expand Down
83 changes: 0 additions & 83 deletions packages/blocks/src/store/utils.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
/**
* WordPress dependencies
*/
import { RichTextData } from '@wordpress/rich-text';

/**
* Helper util to return a value from a certain path of the object.
* Path is specified as either:
Expand Down Expand Up @@ -53,81 +48,3 @@ export function matchesAttributes( blockAttributes, variationAttributes ) {

return blockAttributes === variationAttributes;
}

/** @typedef {import('../api/registration').WPBlockVariation} WPBlockVariation */

/**
* Returns the active block variation for a given block based on its attributes.
* Variations are determined by their `isActive` property.
* Which is either an array of block attribute keys or a function.
*
* In case of an array of block attribute keys, the `attributes` are compared
* to the variation's attributes using strict equality check.
*
* In case of function type, the function should accept a block's attributes
* and the variation's attributes and determines if a variation is active.
* A function that accepts a block's attributes and the variation's attributes and determines if a variation is active.
*
* @param {Array} variations Data state.
* @param {Object} blockType Name of block (example: “core/columns”).
* @param {Object} attributes Block attributes used to determine active variation.
*
* @return {(WPBlockVariation|undefined)} Active block variation.
*/
export function getBlockTypeActiveVariation(
variations,
blockType,
attributes
) {
const attributeKeys = Object.keys( blockType?.attributes || {} );
let match;
let maxMatchedAttributes = 0;

for ( const variation of variations ) {
if ( Array.isArray( variation.isActive ) ) {
const definedAttributes = variation.isActive.filter(
( 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 );
}
);
const definedAttributesLength = definedAttributes.length;
if ( definedAttributesLength === 0 ) {
continue;
}
const isMatch = definedAttributes.every( ( attribute ) => {
const variationAttributeValue = getValueFromObjectPath(
variation.attributes,
attribute
);
if ( variationAttributeValue === undefined ) {
return false;
}
let blockAttributeValue = getValueFromObjectPath(
attributes,
attribute
);
if ( blockAttributeValue instanceof RichTextData ) {
blockAttributeValue = blockAttributeValue.toHTMLString();
}
return matchesAttributes(
blockAttributeValue,
variationAttributeValue
);
} );
if ( isMatch && definedAttributesLength > maxMatchedAttributes ) {
match = variation;
maxMatchedAttributes = definedAttributesLength;
}
} else if ( variation.isActive?.( attributes, variation.attributes ) ) {
// If isActive is a function, we cannot know how many attributes it matches.
// This means that we cannot compare the specificity of our matches,
// and simply return the best match we have found.
return match || variation;
}
}
return match;
}

0 comments on commit 6bbb713

Please sign in to comment.