diff --git a/plugins/woocommerce-blocks/assets/js/blocks/featured-product/block.json b/plugins/woocommerce-blocks/assets/js/blocks/featured-product/block.json
new file mode 100644
index 00000000000..0d60dc1d229
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/blocks/featured-product/block.json
@@ -0,0 +1,100 @@
+{
+ "name": "woocommerce/featured-product",
+ "version": "1.0.0",
+ "title": "Featured Product",
+ "description": "Visually highlight a product or variation and encourage prompt action.",
+ "category": "woocommerce",
+ "keywords": [ "WooCommerce" ],
+ "supports": {
+ "align": [
+ "wide",
+ "full"
+ ],
+ "html": false,
+ "color": {
+ "background": false,
+ "text": true,
+ "__experimentalDuotone": ".wc-block-featured-product__background-image"
+ },
+ "spacing": {
+ "padding": true,
+ "__experimentalDefaultControls": {
+ "padding": true
+ },
+ "__experimentalSkipSerialization": true
+ },
+ "__experimentalBorder": {
+ "color": true,
+ "radius": true,
+ "width": true,
+ "__experimentalSkipSerialization": true
+ },
+ "multiple": true
+ },
+ "attributes": {
+ "alt": {
+ "type": "string",
+ "default": ""
+ },
+ "contentAlign": {
+ "type": "string",
+ "default": "center"
+ },
+ "dimRatio": {
+ "type": "number",
+ "default": 50
+ },
+ "editMode": {
+ "type": "boolean",
+ "default": true
+ },
+ "focalPoint": {
+ "type": "object",
+ "default": false
+ },
+ "imageFit": {
+ "type": "string",
+ "default": "none"
+ },
+ "mediaId": {
+ "type": "number",
+ "default": 0
+ },
+ "mediaSrc": {
+ "type": "string",
+ "default": ""
+ },
+ "minHeight": {
+ "type": "number",
+ "default": 500
+ },
+ "linkText": {
+ "type": "string",
+ "default": "Shop now"
+ },
+ "overlayColor": {
+ "type": "string",
+ "default": "#000000"
+ },
+ "overlayGradient": {
+ "type": "string"
+ },
+ "productId": {
+ "type": "number"
+ },
+ "previewProduct": {
+ "type": "object",
+ "default": null
+ },
+ "showDesc": {
+ "type": "boolean",
+ "default": true
+ },
+ "showPrice": {
+ "type": "boolean",
+ "default": true
+ }
+ },
+ "textdomain": "woo-gutenberg-products-block",
+ "apiVersion": 2
+}
diff --git a/plugins/woocommerce-blocks/assets/js/blocks/featured-product/index.js b/plugins/woocommerce-blocks/assets/js/blocks/featured-product/index.js
deleted file mode 100644
index e5c39f62acc..00000000000
--- a/plugins/woocommerce-blocks/assets/js/blocks/featured-product/index.js
+++ /dev/null
@@ -1,213 +0,0 @@
-/**
- * External dependencies
- */
-import { __ } from '@wordpress/i18n';
-import { InnerBlocks } from '@wordpress/block-editor';
-import { registerBlockType } from '@wordpress/blocks';
-import { getSetting } from '@woocommerce/settings';
-import { isFeaturePluginBuild } from '@woocommerce/block-settings';
-import { Icon, starEmpty } from '@wordpress/icons';
-
-/**
- * Internal dependencies
- */
-import './style.scss';
-import { example } from './example';
-import { Edit } from './edit';
-
-/**
- * Register and run the "Featured Product" block.
- */
-registerBlockType( 'woocommerce/featured-product', {
- apiVersion: 2,
- title: __( 'Featured Product', 'woo-gutenberg-products-block' ),
- icon: {
- src: (
-
- ),
- },
- category: 'woocommerce',
- keywords: [ __( 'WooCommerce', 'woo-gutenberg-products-block' ) ],
- description: __(
- 'Visually highlight a product or variation and encourage prompt action.',
- 'woo-gutenberg-products-block'
- ),
- supports: {
- align: [ 'wide', 'full' ],
- html: false,
- color: {
- background: false,
- text: true,
- ...( isFeaturePluginBuild() && {
- __experimentalDuotone:
- '.wc-block-featured-product__background-image',
- } ),
- },
- spacing: {
- padding: true,
- ...( isFeaturePluginBuild() && {
- __experimentalDefaultControls: {
- padding: true,
- },
- __experimentalSkipSerialization: true,
- } ),
- },
- ...( isFeaturePluginBuild() && {
- __experimentalBorder: {
- color: true,
- radius: true,
- width: true,
- __experimentalSkipSerialization: true,
- },
- } ),
- },
- example,
- attributes: {
- alt: {
- type: 'string',
- default: '',
- },
- /**
- * Alignment of content inside block.
- */
- contentAlign: {
- type: 'string',
- default: 'center',
- },
-
- /**
- * Percentage opacity of overlay.
- */
- dimRatio: {
- type: 'number',
- default: 50,
- },
-
- /**
- * Toggle for edit mode in the block preview.
- */
- editMode: {
- type: 'boolean',
- default: true,
- },
-
- /**
- * Focus point for the background image
- */
- focalPoint: {
- type: 'object',
- },
-
- /**
- * Whether the image should fit the container or not be resized
- *
- * Note: when the image is resized to fit the container, the user loses
- * the ability to have full control over the focus.
- */
- imageFit: {
- type: 'string',
- default: 'none',
- },
-
- /**
- * ID for a custom image, overriding the product's featured image.
- */
- mediaId: {
- type: 'number',
- default: 0,
- },
-
- /**
- * URL for a custom image, overriding the product's featured image.
- */
- mediaSrc: {
- type: 'string',
- default: '',
- },
-
- /**
- * A minimum height for the block.
- *
- * Note: if padding is increased, this way the inner content will never
- * overflow, but instead will resize the container.
- *
- * It was decided to change this to make this block more in line with
- * the “Cover” block.
- */
- minHeight: {
- type: 'number',
- default: getSetting( 'default_height', 500 ),
- },
-
- /**
- * Text for the product link.
- */
- linkText: {
- type: 'string',
- default: __( 'Shop now', 'woo-gutenberg-products-block' ),
- },
-
- /**
- * Color for the overlay layer on top of the product image.
- */
- overlayColor: {
- type: 'string',
- default: '#000000',
- },
-
- /**
- * Gradient for the overlay layer on top of the product image.
- */
- overlayGradient: {
- type: 'string',
- },
-
- /**
- * The product ID to display.
- */
- productId: {
- type: 'number',
- },
-
- /**
- * Product preview.
- */
- previewProduct: {
- type: 'object',
- default: null,
- },
-
- /**
- * Show the product description.
- */
- showDesc: {
- type: 'boolean',
- default: true,
- },
-
- /**
- * Show the product price.
- */
- showPrice: {
- type: 'boolean',
- default: true,
- },
- },
-
- /**
- * Renders and manages the block.
- *
- * @param {Object} props Props to pass to block.
- */
- edit: Edit,
-
- /**
- * Block content is rendered in PHP, not via save function.
- */
- save() {
- return ;
- },
-} );
diff --git a/plugins/woocommerce-blocks/assets/js/blocks/featured-product/index.tsx b/plugins/woocommerce-blocks/assets/js/blocks/featured-product/index.tsx
new file mode 100644
index 00000000000..5a0500e5e89
--- /dev/null
+++ b/plugins/woocommerce-blocks/assets/js/blocks/featured-product/index.tsx
@@ -0,0 +1,89 @@
+/**
+ * External dependencies
+ */
+import { InnerBlocks } from '@wordpress/block-editor';
+import { registerBlockType } from '@wordpress/blocks';
+import { getSetting } from '@woocommerce/settings';
+import { isFeaturePluginBuild } from '@woocommerce/block-settings';
+import { Icon, starEmpty } from '@wordpress/icons';
+
+/**
+ * Internal dependencies
+ */
+import './style.scss';
+import { example } from './example';
+import { Edit } from './edit';
+import metadata from './block.json';
+
+/**
+ * Register and run the "Featured Product" block.
+ */
+registerBlockType( metadata, {
+ icon: {
+ src: (
+
+ ),
+ },
+ attributes: {
+ ...metadata.attributes,
+ /**
+ * A minimum height for the block.
+ *
+ * Note: if padding is increased, this way the inner content will never
+ * overflow, but instead will resize the container.
+ *
+ * It was decided to change this to make this block more in line with
+ * the “Cover” block.
+ */
+ minHeight: {
+ type: 'number',
+ default: getSetting( 'default_height', 500 ),
+ },
+ },
+ supports: {
+ ...metadata.supports,
+ color: {
+ background: false,
+ text: true,
+ ...( isFeaturePluginBuild() && {
+ __experimentalDuotone:
+ '.wc-block-featured-product__background-image',
+ } ),
+ },
+ spacing: {
+ padding: true,
+ ...( isFeaturePluginBuild() && {
+ __experimentalDefaultControls: {
+ padding: true,
+ },
+ __experimentalSkipSerialization: true,
+ } ),
+ },
+ ...( isFeaturePluginBuild() && {
+ __experimentalBorder: {
+ color: true,
+ radius: true,
+ width: true,
+ __experimentalSkipSerialization: true,
+ },
+ } ),
+ },
+ example,
+
+ /**
+ * Renders and manages the block.
+ *
+ * @param {Object} props Props to pass to block.
+ */
+ edit: Edit,
+
+ /**
+ * Block content is rendered in PHP, not via save function.
+ */
+ save: () => {
+ return ;
+ },
+} );
diff --git a/plugins/woocommerce-blocks/bin/webpack-configs.js b/plugins/woocommerce-blocks/bin/webpack-configs.js
index 48e1a9cc7c9..e068e2d1aba 100644
--- a/plugins/woocommerce-blocks/bin/webpack-configs.js
+++ b/plugins/woocommerce-blocks/bin/webpack-configs.js
@@ -263,6 +263,10 @@ const getMainConfig = ( options = {} ) => {
from: './assets/js/blocks/checkout/block.json',
to: './checkout/block.json',
},
+ {
+ from: './assets/js/blocks/featured-product/block.json',
+ to: './featured-product/block.json',
+ },
],
} ),
],
diff --git a/plugins/woocommerce-blocks/src/BlockTypes/FeaturedProduct.php b/plugins/woocommerce-blocks/src/BlockTypes/FeaturedProduct.php
index 9bd4ec47d55..f9e4f2bbfba 100644
--- a/plugins/woocommerce-blocks/src/BlockTypes/FeaturedProduct.php
+++ b/plugins/woocommerce-blocks/src/BlockTypes/FeaturedProduct.php
@@ -15,21 +15,12 @@ class FeaturedProduct extends AbstractDynamicBlock {
protected $block_name = 'featured-product';
/**
- * Default attribute values, should match what's set in JS `registerBlockType`.
+ * Default attribute values.
*
* @var array
*/
protected $defaults = array(
- 'align' => 'none',
- 'contentAlign' => 'center',
- 'dimRatio' => 50,
- 'focalPoint' => false,
- 'imageFit' => 'none',
- 'mediaId' => 0,
- 'mediaSrc' => '',
- 'minHeight' => 500,
- 'showDesc' => true,
- 'showPrice' => true,
+ 'align' => 'none',
);
/**
@@ -37,7 +28,16 @@ class FeaturedProduct extends AbstractDynamicBlock {
*
* @var array
*/
- protected $global_style_wrapper = array( 'text_color', 'font_size', 'border_color', 'border_radius', 'border_width', 'background_color', 'text_color', 'padding' );
+ protected $global_style_wrapper = array(
+ 'text_color',
+ 'font_size',
+ 'border_color',
+ 'border_radius',
+ 'border_width',
+ 'background_color',
+ 'text_color',
+ 'padding',
+ );
/**
* Get the supports array for this block type.
@@ -147,7 +147,7 @@ class FeaturedProduct extends AbstractDynamicBlock {
if ( ! empty( $image ) ) {
return sprintf(
'',
- wp_kses_post( $attributes['alt'] ?? $product->get_name() ),
+ wp_kses_post( $attributes['alt'] ?: $product->get_name() ),
esc_url( $image ),
$style
);