diff --git a/plugins/woocommerce-blocks/assets/js/blocks/product-gallery/block.json b/plugins/woocommerce-blocks/assets/js/blocks/product-gallery/block.json index 33ee6f94473..9ae830b7d9e 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/product-gallery/block.json +++ b/plugins/woocommerce-blocks/assets/js/blocks/product-gallery/block.json @@ -9,7 +9,8 @@ "keywords": [ "WooCommerce" ], "supports": { "align": true, - "multiple": false + "multiple": false, + "interactivity": true }, "textdomain": "woo-gutenberg-products-block", "providesContext": { @@ -47,5 +48,6 @@ "type": "boolean", "default": false } - } + }, + "viewScript": "wc-product-gallery-interactivity-frontend" } diff --git a/plugins/woocommerce-blocks/assets/js/blocks/product-gallery/frontend.tsx b/plugins/woocommerce-blocks/assets/js/blocks/product-gallery/frontend.tsx new file mode 100644 index 00000000000..c502d97f04e --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/blocks/product-gallery/frontend.tsx @@ -0,0 +1,39 @@ +/** + * External dependencies + */ +import { store as interactivityApiStore } from '@woocommerce/interactivity'; + +interface State { + [ key: string ]: unknown; +} + +interface Context { + productGallery: { numberOfThumbnails: number }; +} + +interface Selectors { + productGallery: { + getNumberOfPages: ( store: unknown ) => number; + }; +} + +interface Store { + state: State; + context: Context; + selectors: Selectors; + ref: HTMLElement; +} + +type SelectorsStore = Pick< Store, 'context' | 'selectors' >; + +interactivityApiStore( { + selectors: { + productGallery: { + getNumberOfPages: ( store: SelectorsStore ) => { + const { context } = store; + + return context.productGallery.numberOfThumbnails; + }, + }, + }, +} as Store ); diff --git a/plugins/woocommerce-blocks/src/BlockTypes/ProductGallery.php b/plugins/woocommerce-blocks/src/BlockTypes/ProductGallery.php index d8def9530b1..d89f7823e0d 100644 --- a/plugins/woocommerce-blocks/src/BlockTypes/ProductGallery.php +++ b/plugins/woocommerce-blocks/src/BlockTypes/ProductGallery.php @@ -21,6 +21,38 @@ class ProductGallery extends AbstractBlock { return null; } + /** + * 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 ) { + $classname = $attributes['className'] ?? ''; + $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => trim( sprintf( 'woocommerce %1$s', $classname ) ) ) ); + $html = sprintf( + '
+ %2$s +
', + $wrapper_attributes, + $content + ); + $p = new \WP_HTML_Tag_Processor( $content ); + + if ( $p->next_tag() ) { + $p->set_attribute( 'data-wc-interactive', true ); + $p->set_attribute( + 'data-wc-context', + wp_json_encode( array( 'productGallery' => array( 'numberOfThumbnails' => 0 ) ) ) + ); + $html = $p->get_updated_html(); + } + + return $html; + } + /** * It isn't necessary register block assets because it is a server side block. */ @@ -29,4 +61,19 @@ class ProductGallery extends AbstractBlock { return null; } + + /** + * Get the Interactivity API's view script handle for this block type. + * + * @param string $key Data to get, or default to everything. + */ + protected function get_block_type_script( $key = null ) { + $script = [ + 'handle' => 'wc-' . $this->block_name . '-interactivity-frontend', + 'path' => $this->asset_api->get_block_asset_build_path( $this->block_name . '-interactivity-frontend' ), + 'dependencies' => [ 'wc-interactivity' ], + ]; + + return $key ? $script[ $key ] : $script; + } }