Add new `Product Rating Stars` block (https://github.com/woocommerce/woocommerce-blocks/pull/10005)
* Add new `Product Rating Stars` block * Make block experimental * Fix dep
This commit is contained in:
parent
fd86fd2e57
commit
b1bc51e3f0
|
@ -45,6 +45,15 @@ registerBlockComponent( {
|
|||
),
|
||||
} );
|
||||
|
||||
registerBlockComponent( {
|
||||
blockName: 'woocommerce/product-rating-stars',
|
||||
component: lazy( () =>
|
||||
import(
|
||||
/* webpackChunkName: "product-rating-stars" */ './product-elements/rating-stars/block'
|
||||
)
|
||||
),
|
||||
} );
|
||||
|
||||
registerBlockComponent( {
|
||||
blockName: 'woocommerce/product-button',
|
||||
component: lazy( () =>
|
||||
|
|
|
@ -5,6 +5,7 @@ import './product-elements/title';
|
|||
import './product-elements/price';
|
||||
import './product-elements/image';
|
||||
import './product-elements/rating';
|
||||
import './product-elements/rating-stars';
|
||||
import './product-elements/button';
|
||||
import './product-elements/summary';
|
||||
import './product-elements/sale-badge';
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"name": "woocommerce/product-rating-stars",
|
||||
"version": "1.0.0",
|
||||
"icon": "info",
|
||||
"title": "Product Rating Stars",
|
||||
"description": "Display the average rating of a product with stars",
|
||||
"attributes": {
|
||||
"productId": {
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
"isDescendentOfQueryLoop": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"textAlign": {
|
||||
"type": "string",
|
||||
"default": ""
|
||||
},
|
||||
"isDescendentOfSingleProductBlock": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"isDescendentOfSingleProductTemplate": {
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"usesContext": [ "query", "queryId", "postId" ],
|
||||
"category": "woocommerce",
|
||||
"keywords": [ "WooCommerce" ],
|
||||
"supports": {
|
||||
"align": true
|
||||
},
|
||||
"textdomain": "woo-gutenberg-products-block",
|
||||
"apiVersion": 2,
|
||||
"$schema": "https://schemas.wp.org/trunk/block.json"
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __, _n, sprintf } from '@wordpress/i18n';
|
||||
import classnames from 'classnames';
|
||||
import {
|
||||
useInnerBlockLayoutContext,
|
||||
useProductDataContext,
|
||||
} from '@woocommerce/shared-context';
|
||||
import { useStyleProps } from '@woocommerce/base-hooks';
|
||||
import { withProductDataContext } from '@woocommerce/shared-hocs';
|
||||
import { isNumber, ProductResponseItem } from '@woocommerce/types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
|
||||
type RatingProps = {
|
||||
reviews: number;
|
||||
rating: number;
|
||||
parentClassName?: string;
|
||||
};
|
||||
|
||||
const getAverageRating = (
|
||||
product: Omit< ProductResponseItem, 'average_rating' > & {
|
||||
average_rating: string;
|
||||
}
|
||||
) => {
|
||||
const rating = parseFloat( product.average_rating );
|
||||
|
||||
return Number.isFinite( rating ) && rating > 0 ? rating : 0;
|
||||
};
|
||||
|
||||
const getRatingCount = ( product: ProductResponseItem ) => {
|
||||
const count = isNumber( product.review_count )
|
||||
? product.review_count
|
||||
: parseInt( product.review_count, 10 );
|
||||
|
||||
return Number.isFinite( count ) && count > 0 ? count : 0;
|
||||
};
|
||||
|
||||
const getStarStyle = ( rating: number ) => ( {
|
||||
width: ( rating / 5 ) * 100 + '%',
|
||||
} );
|
||||
|
||||
const NoRating = ( { parentClassName }: { parentClassName: string } ) => {
|
||||
const starStyle = getStarStyle( 0 );
|
||||
|
||||
return (
|
||||
<div
|
||||
className={ classnames(
|
||||
'wc-block-components-product-rating__norating-container',
|
||||
`${ parentClassName }-product-rating__norating-container`
|
||||
) }
|
||||
>
|
||||
<div
|
||||
className={ 'wc-block-components-product-rating__norating' }
|
||||
role="img"
|
||||
>
|
||||
<span style={ starStyle } />
|
||||
</div>
|
||||
<span>{ __( 'No Reviews', 'woo-gutenberg-products-block' ) }</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const Rating = ( props: RatingProps ): JSX.Element => {
|
||||
const { rating, reviews, parentClassName } = props;
|
||||
|
||||
const starStyle = getStarStyle( rating );
|
||||
|
||||
const ratingText = sprintf(
|
||||
/* translators: %f is referring to the average rating value */
|
||||
__( 'Rated %f out of 5', 'woo-gutenberg-products-block' ),
|
||||
rating
|
||||
);
|
||||
|
||||
const ratingHTML = {
|
||||
__html: sprintf(
|
||||
/* translators: %1$s is referring to the average rating value, %2$s is referring to the number of ratings */
|
||||
_n(
|
||||
'Rated %1$s out of 5 based on %2$s customer rating',
|
||||
'Rated %1$s out of 5 based on %2$s customer ratings',
|
||||
reviews,
|
||||
'woo-gutenberg-products-block'
|
||||
),
|
||||
sprintf( '<strong class="rating">%f</strong>', rating ),
|
||||
sprintf( '<span class="rating">%d</span>', reviews )
|
||||
),
|
||||
};
|
||||
return (
|
||||
<div
|
||||
className={ classnames(
|
||||
'wc-block-components-product-rating__stars',
|
||||
`${ parentClassName }__product-rating__stars`
|
||||
) }
|
||||
role="img"
|
||||
aria-label={ ratingText }
|
||||
>
|
||||
<span style={ starStyle } dangerouslySetInnerHTML={ ratingHTML } />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface ProductRatingStarsProps {
|
||||
className?: string;
|
||||
textAlign?: string;
|
||||
isDescendentOfSingleProductBlock: boolean;
|
||||
isDescendentOfQueryLoop: boolean;
|
||||
postId: number;
|
||||
productId: number;
|
||||
shouldDisplayMockedReviewsWhenProductHasNoReviews: boolean;
|
||||
}
|
||||
|
||||
export const Block = ( props: ProductRatingStarsProps ): JSX.Element | null => {
|
||||
const { textAlign, shouldDisplayMockedReviewsWhenProductHasNoReviews } =
|
||||
props;
|
||||
const styleProps = useStyleProps( props );
|
||||
const { parentClassName } = useInnerBlockLayoutContext();
|
||||
const { product } = useProductDataContext();
|
||||
const rating = getAverageRating( product );
|
||||
const reviews = getRatingCount( product );
|
||||
|
||||
const className = classnames(
|
||||
styleProps.className,
|
||||
'wc-block-components-product-rating',
|
||||
{
|
||||
[ `${ parentClassName }__product-rating` ]: parentClassName,
|
||||
[ `has-text-align-${ textAlign }` ]: textAlign,
|
||||
}
|
||||
);
|
||||
const mockedRatings = shouldDisplayMockedReviewsWhenProductHasNoReviews ? (
|
||||
<NoRating parentClassName={ parentClassName } />
|
||||
) : null;
|
||||
|
||||
const content = reviews ? (
|
||||
<Rating
|
||||
rating={ rating }
|
||||
reviews={ reviews }
|
||||
parentClassName={ parentClassName }
|
||||
/>
|
||||
) : (
|
||||
mockedRatings
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={ className } style={ styleProps.style }>
|
||||
<div className="wc-block-components-product-rating-stars__container">
|
||||
{ content }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default withProductDataContext( Block );
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Icon, starFilled } from '@wordpress/icons';
|
||||
|
||||
export const BLOCK_TITLE: string = __(
|
||||
'Product Rating Stars',
|
||||
'woo-gutenberg-products-block'
|
||||
);
|
||||
export const BLOCK_ICON: JSX.Element = (
|
||||
<Icon
|
||||
icon={ starFilled }
|
||||
className="wc-block-editor-components-block-icon"
|
||||
/>
|
||||
);
|
||||
export const BLOCK_DESCRIPTION: string = __(
|
||||
'Display the average rating of a product with stars',
|
||||
'woo-gutenberg-products-block'
|
||||
);
|
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import {
|
||||
AlignmentToolbar,
|
||||
BlockControls,
|
||||
useBlockProps,
|
||||
} from '@wordpress/block-editor';
|
||||
import type { BlockEditProps } from '@wordpress/blocks';
|
||||
import { useEffect } from '@wordpress/element';
|
||||
import { ProductQueryContext as Context } from '@woocommerce/blocks/product-query/types';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import Block from './block';
|
||||
import { BlockAttributes } from './types';
|
||||
import { useIsDescendentOfSingleProductBlock } from '../shared/use-is-descendent-of-single-product-block';
|
||||
import { useIsDescendentOfSingleProductTemplate } from '../shared/use-is-descendent-of-single-product-template';
|
||||
|
||||
const Edit = (
|
||||
props: BlockEditProps< BlockAttributes > & { context: Context }
|
||||
): JSX.Element => {
|
||||
const { attributes, setAttributes, context } = props;
|
||||
const blockProps = useBlockProps( {
|
||||
className: 'wp-block-woocommerce-product-rating',
|
||||
} );
|
||||
const blockAttrs = {
|
||||
...attributes,
|
||||
...context,
|
||||
shouldDisplayMockedReviewsWhenProductHasNoReviews: true,
|
||||
};
|
||||
const isDescendentOfQueryLoop = Number.isFinite( context.queryId );
|
||||
const { isDescendentOfSingleProductBlock } =
|
||||
useIsDescendentOfSingleProductBlock( {
|
||||
blockClientId: blockProps?.id,
|
||||
} );
|
||||
let { isDescendentOfSingleProductTemplate } =
|
||||
useIsDescendentOfSingleProductTemplate();
|
||||
|
||||
if ( isDescendentOfQueryLoop || isDescendentOfSingleProductBlock ) {
|
||||
isDescendentOfSingleProductTemplate = false;
|
||||
}
|
||||
|
||||
useEffect( () => {
|
||||
setAttributes( {
|
||||
isDescendentOfQueryLoop,
|
||||
isDescendentOfSingleProductBlock,
|
||||
isDescendentOfSingleProductTemplate,
|
||||
} );
|
||||
}, [
|
||||
setAttributes,
|
||||
isDescendentOfQueryLoop,
|
||||
isDescendentOfSingleProductBlock,
|
||||
isDescendentOfSingleProductTemplate,
|
||||
] );
|
||||
|
||||
return (
|
||||
<>
|
||||
<BlockControls>
|
||||
<AlignmentToolbar
|
||||
value={ attributes.textAlign }
|
||||
onChange={ ( newAlign ) => {
|
||||
setAttributes( { textAlign: newAlign || '' } );
|
||||
} }
|
||||
/>
|
||||
</BlockControls>
|
||||
<div { ...blockProps }>
|
||||
<Block { ...blockAttrs } />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default Edit;
|
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { BlockConfiguration } from '@wordpress/blocks';
|
||||
import { registerBlockSingleProductTemplate } from '@woocommerce/atomic-utils';
|
||||
import { isExperimentalBuild } from '@woocommerce/block-settings';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import metadata from './block.json';
|
||||
import edit from './edit';
|
||||
import sharedConfig from '../shared/config';
|
||||
import { supports } from './support';
|
||||
import { BLOCK_ICON } from './constants';
|
||||
|
||||
const blockConfig: BlockConfiguration = {
|
||||
...sharedConfig,
|
||||
ancestor: [
|
||||
'woocommerce/all-products',
|
||||
'woocommerce/single-product',
|
||||
'core/post-template',
|
||||
'woocommerce/product-template',
|
||||
],
|
||||
icon: { src: BLOCK_ICON },
|
||||
supports,
|
||||
edit,
|
||||
};
|
||||
|
||||
if ( isExperimentalBuild() ) {
|
||||
registerBlockSingleProductTemplate( {
|
||||
blockName: 'woocommerce/product-rating-stars',
|
||||
blockMetadata: metadata,
|
||||
blockSettings: blockConfig,
|
||||
} );
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
.wc-block-components-product-rating {
|
||||
display: block;
|
||||
line-height: 1;
|
||||
|
||||
&__stars {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: 5.3em;
|
||||
height: 1.618em;
|
||||
line-height: 1.618;
|
||||
font-size: 1em;
|
||||
/* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */
|
||||
font-family: star;
|
||||
font-weight: 400;
|
||||
|
||||
&::before {
|
||||
content: "\53\53\53\53\53";
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
opacity: 0.5;
|
||||
color: inherit;
|
||||
white-space: nowrap;
|
||||
}
|
||||
span {
|
||||
overflow: hidden;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
color: inherit;
|
||||
padding-top: 1.5em;
|
||||
}
|
||||
span::before {
|
||||
content: "\53\53\53\53\53";
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
color: inherit;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
&__link {
|
||||
display: inline-block;
|
||||
height: 1.618em;
|
||||
width: 100%;
|
||||
text-align: inherit;
|
||||
@include font-size(small);
|
||||
}
|
||||
|
||||
.wc-block-all-products & {
|
||||
margin-top: 0;
|
||||
margin-bottom: $gap-small;
|
||||
}
|
||||
|
||||
&__norating-container {
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: $gap-smaller;
|
||||
}
|
||||
|
||||
&__norating {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
width: 1.5em;
|
||||
height: 1.618em;
|
||||
line-height: 1.618;
|
||||
font-size: 1em;
|
||||
/* stylelint-disable-next-line font-family-no-missing-generic-family-keyword */
|
||||
font-family: star;
|
||||
font-weight: 400;
|
||||
-webkit-text-stroke: 2px var(--wp--preset--color--black, #000);
|
||||
&::before {
|
||||
content: "\53";
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
color: transparent;
|
||||
white-space: nowrap;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wp-block-woocommerce-single-product {
|
||||
.wc-block-components-product-rating__stars {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-all-products,
|
||||
.wp-block-query {
|
||||
.is-loading {
|
||||
.wc-block-components-product-rating {
|
||||
@include placeholder();
|
||||
width: 7em;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/* eslint-disable @wordpress/no-unsafe-wp-apis */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { isFeaturePluginBuild } from '@woocommerce/block-settings';
|
||||
import { __experimentalGetSpacingClassesAndStyles } from '@wordpress/block-editor';
|
||||
|
||||
export const supports = {
|
||||
...( isFeaturePluginBuild() && {
|
||||
color: {
|
||||
text: true,
|
||||
background: false,
|
||||
link: false,
|
||||
__experimentalSkipSerialization: true,
|
||||
},
|
||||
spacing: {
|
||||
margin: true,
|
||||
padding: true,
|
||||
},
|
||||
typography: {
|
||||
fontSize: true,
|
||||
__experimentalSkipSerialization: true,
|
||||
},
|
||||
__experimentalSelector: '.wc-block-components-product-rating',
|
||||
} ),
|
||||
...( ! isFeaturePluginBuild() &&
|
||||
typeof __experimentalGetSpacingClassesAndStyles === 'function' && {
|
||||
spacing: {
|
||||
margin: true,
|
||||
},
|
||||
} ),
|
||||
};
|
|
@ -0,0 +1,7 @@
|
|||
export interface BlockAttributes {
|
||||
productId: number;
|
||||
isDescendentOfQueryLoop: boolean;
|
||||
isDescendentOfSingleProductBlock: boolean;
|
||||
isDescendentOfSingleProductTemplate: boolean;
|
||||
textAlign: string;
|
||||
}
|
|
@ -58,6 +58,9 @@ const blocks = {
|
|||
'product-top-rated': {},
|
||||
'products-by-attribute': {},
|
||||
'rating-filter': {},
|
||||
'product-rating-stars': {
|
||||
isExperimental: true,
|
||||
},
|
||||
'reviews-by-category': {
|
||||
customDir: 'reviews/reviews-by-category',
|
||||
},
|
||||
|
|
|
@ -0,0 +1,163 @@
|
|||
<?php
|
||||
namespace Automattic\WooCommerce\Blocks\BlockTypes;
|
||||
|
||||
use Automattic\WooCommerce\Blocks\Utils\StyleAttributesUtils;
|
||||
/**
|
||||
* ProductRating class.
|
||||
*/
|
||||
class ProductRatingStars extends AbstractBlock {
|
||||
|
||||
/**
|
||||
* Block name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $block_name = 'product-rating-stars';
|
||||
|
||||
/**
|
||||
* API version name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $api_version = '2';
|
||||
|
||||
/**
|
||||
* Get block supports. Shared with the frontend.
|
||||
* IMPORTANT: If you change anything here, make sure to update the JS file too.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_block_type_supports() {
|
||||
return array(
|
||||
'color' =>
|
||||
array(
|
||||
'text' => true,
|
||||
'background' => false,
|
||||
'link' => false,
|
||||
'__experimentalSkipSerialization' => true,
|
||||
),
|
||||
'typography' =>
|
||||
array(
|
||||
'fontSize' => true,
|
||||
'__experimentalSkipSerialization' => true,
|
||||
),
|
||||
'spacing' =>
|
||||
array(
|
||||
'margin' => true,
|
||||
'padding' => true,
|
||||
'__experimentalSkipSerialization' => true,
|
||||
),
|
||||
'__experimentalSelector' => '.wc-block-components-product-rating',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite parent method to prevent script registration.
|
||||
*
|
||||
* It is necessary to register and enqueues assets during the render
|
||||
* phase because we want to load assets only if the block has the content.
|
||||
*/
|
||||
protected function register_block_type_assets() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the context.
|
||||
*/
|
||||
protected function get_block_type_uses_context() {
|
||||
return [ 'query', 'queryId', 'postId' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Include and render the block.
|
||||
*
|
||||
* @param array $attributes Block attributes. Default empty array.
|
||||
* @param string $content Block content. Default empty string.
|
||||
* @param WP_Block $block Block instance.
|
||||
* @return string Rendered block type output.
|
||||
*/
|
||||
protected function render( $attributes, $content, $block ) {
|
||||
if ( ! empty( $content ) ) {
|
||||
parent::register_block_type_assets();
|
||||
$this->register_chunk_translations( [ $this->block_name ] );
|
||||
return $content;
|
||||
}
|
||||
|
||||
$post_id = $block->context['postId'];
|
||||
$product = wc_get_product( $post_id );
|
||||
|
||||
if ( $product ) {
|
||||
$product_reviews_count = $product->get_review_count();
|
||||
$product_rating = $product->get_average_rating();
|
||||
|
||||
$styles_and_classes = StyleAttributesUtils::get_classes_and_styles_by_attributes( $attributes );
|
||||
$text_align_styles_and_classes = StyleAttributesUtils::get_text_align_class_and_style( $attributes );
|
||||
|
||||
/**
|
||||
* Filter the output from wc_get_rating_html.
|
||||
*
|
||||
* @param string $html Star rating markup. Default empty string.
|
||||
* @param float $rating Rating being shown.
|
||||
* @param int $count Total number of ratings.
|
||||
* @return string
|
||||
*/
|
||||
$filter_rating_html = function( $html, $rating, $count ) use ( $product_rating, $product_reviews_count ) {
|
||||
$product_permalink = get_permalink();
|
||||
$reviews_count = $count;
|
||||
$average_rating = $rating;
|
||||
|
||||
if ( $product_rating ) {
|
||||
$average_rating = $product_rating;
|
||||
}
|
||||
|
||||
if ( $product_reviews_count ) {
|
||||
$reviews_count = $product_reviews_count;
|
||||
}
|
||||
|
||||
if ( 0 < $average_rating || false === $product_permalink ) {
|
||||
/* translators: %s: rating */
|
||||
$label = sprintf( __( 'Rated %s out of 5', 'woo-gutenberg-products-block' ), $average_rating );
|
||||
$html = sprintf(
|
||||
'<div class="wc-block-components-product-rating-stars__container">
|
||||
<div class="wc-block-components-product-rating__stars wc-block-grid__product-rating__stars" role="img" aria-label="%1$s">
|
||||
%2$s
|
||||
</div>
|
||||
</div>
|
||||
',
|
||||
esc_attr( $label ),
|
||||
wc_get_star_rating_html( $average_rating, $reviews_count )
|
||||
);
|
||||
} else {
|
||||
$html = '';
|
||||
}
|
||||
|
||||
return $html;
|
||||
};
|
||||
|
||||
add_filter(
|
||||
'woocommerce_product_get_rating_html',
|
||||
$filter_rating_html,
|
||||
10,
|
||||
3
|
||||
);
|
||||
|
||||
$rating_html = wc_get_rating_html( $product->get_average_rating() );
|
||||
|
||||
remove_filter(
|
||||
'woocommerce_product_get_rating_html',
|
||||
$filter_rating_html,
|
||||
10
|
||||
);
|
||||
|
||||
return sprintf(
|
||||
'<div class="wc-block-components-product-rating wc-block-grid__product-rating %1$s %2$s" style="%3$s">
|
||||
%4$s
|
||||
</div>',
|
||||
esc_attr( $text_align_styles_and_classes['class'] ?? '' ),
|
||||
esc_attr( $styles_and_classes['classes'] ),
|
||||
esc_attr( $styles_and_classes['styles'] ?? '' ),
|
||||
$rating_html
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -226,6 +226,7 @@ final class BlockTypesController {
|
|||
|
||||
if ( Package::feature()->is_experimental_build() ) {
|
||||
$block_types[] = 'ProductCollection';
|
||||
$block_types[] = 'ProductRatingStars';
|
||||
$block_types[] = 'ProductTemplate';
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue