Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
Product Gallery > Next/Previous Buttons block: Add support to Interac…
Browse files Browse the repository at this point in the history
…tivity API (#10938)

* Add interactivity API to the Pager block

* Replace Large Image when clicking on page

* Fix php cs errors

* Fix php cs errors

* Fix php cs errors

* fix php cs errors

* Add support to Interactivity API

* Fix phpcs errors

* Fix phpcs errors

* Remove unnecessary code and fix block classes

* Rename interactivity actions

* Remove unnecessary type conversion

* Fix error when clicking on page in Pager block

* Fix php cs errors

* Fix ProductGalleryUtils import

* fix php cs error

* Fix styles for next/previous buttons

* Fix styles for the next/previous buttons

* Fix php cs errors

* Fix next/previous icons when buttons are outside image

* Fix php cs errors

* Fix php cs errors

* Fix buttons not visible in Editor

* Delete src/SpeciticTemplateController.php

Delete unnecessary file that is causing php cs error
  • Loading branch information
thealexandrelara authored Oct 5, 2023
1 parent ca0d427 commit 5c8340d
Show file tree
Hide file tree
Showing 8 changed files with 192 additions and 98 deletions.
29 changes: 29 additions & 0 deletions assets/js/blocks/product-gallery/frontend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ interface Context {
woocommerce: {
selectedImage: string;
imageId: string;
visibleImagesIds: string[];
isDialogOpen: boolean;
};
}
Expand All @@ -19,6 +20,7 @@ interface Selectors {
woocommerce: {
isSelected: ( store: unknown ) => boolean;
pagerDotFillOpacity: ( store: SelectorsStore ) => number;
selectedImageIndex: ( store: SelectorsStore ) => number;
isDialogOpen: ( store: unknown ) => boolean;
};
}
Expand Down Expand Up @@ -80,6 +82,33 @@ interactivityApiStore( {
handleSelectImage: ( { context }: Store ) => {
context.woocommerce.selectedImage = context.woocommerce.imageId;
},
handleNextImageButtonClick: ( store: Store ) => {
const { context } = store;
const selectedImageIdIndex =
context.woocommerce.visibleImagesIds.indexOf(
context.woocommerce.selectedImage
);
const nextImageIndex = Math.min(
selectedImageIdIndex + 1,
context.woocommerce.visibleImagesIds.length - 1
);

context.woocommerce.selectedImage =
context.woocommerce.visibleImagesIds[ nextImageIndex ];
},
handlePreviousImageButtonClick: ( store: Store ) => {
const { context } = store;
const selectedImageIdIndex =
context.woocommerce.visibleImagesIds.indexOf(
context.woocommerce.selectedImage
);
const previousImageIndex = Math.max(
selectedImageIdIndex - 1,
0
);
context.woocommerce.selectedImage =
context.woocommerce.visibleImagesIds[ previousImageIndex ];
},
},
},
} );
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
width: 100%;
position: absolute;
height: 50px;
}

.wc-block-editor-product-gallery-large-image-next-previous--outside-image .wc-block-product-gallery-large-image-next-previous {
margin-right: 0;
margin-left: 0;
svg {
z-index: 1;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,3 @@
max-width: calc(100% - 60px);
}
}

.wc-block-product-gallery-large-image__inner-blocks {
.wc-block-editor-product-gallery-large-image-next-previous--outside-image & > * {
margin-left: 30px;
margin-right: 30px;
}
}
7 changes: 5 additions & 2 deletions assets/js/blocks/product-gallery/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,13 @@ $outside-image-max-width: calc(100% - (2 * $outside-image-offset));
width: 100%;
height: 100%;

svg {
button {
cursor: pointer;
z-index: 3;
pointer-events: all;
padding: 0;
border: none;
background: none;
}

.is-vertically-aligned-top {
Expand Down Expand Up @@ -215,4 +219,3 @@ $outside-image-max-width: calc(100% - (2 * $outside-image-offset));

}
}

16 changes: 9 additions & 7 deletions src/BlockTypes/ProductGallery.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?php
namespace Automattic\WooCommerce\Blocks\BlockTypes;

use Automattic\WooCommerce\Blocks\Utils\ProductGalleryUtils;
use Automattic\WooCommerce\Blocks\Utils\BlockTemplateUtils;
use Automattic\WooCommerce\Blocks\Utils\ProductGalleryUtils;

/**
* ProductGallery class.
Expand Down Expand Up @@ -121,10 +121,11 @@ protected function render( $attributes, $content, $block ) {
$classname_single_image = 'is-single-product-gallery-image';
}

$classname = $attributes['className'] ?? '';
$dialog = ( true === $attributes['fullScreenOnClick'] && isset( $attributes['mode'] ) && 'full' !== $attributes['mode'] ) ? $this->render_dialog() : '';
$post_id = $block->context['postId'] ?? '';
$product = wc_get_product( $post_id );
$number_of_thumbnails = $block->attributes['thumbnailsNumberOfThumbnails'] ?? 0;
$classname = $attributes['className'] ?? '';
$dialog = ( true === $attributes['fullScreenOnClick'] && isset( $attributes['mode'] ) && 'full' !== $attributes['mode'] ) ? $this->render_dialog() : '';
$post_id = $block->context['postId'] ?? '';
$product = wc_get_product( $post_id );

$html = $this->inject_dialog( $content, $dialog );
$p = new \WP_HTML_Tag_Processor( $html );
Expand All @@ -136,8 +137,9 @@ protected function render( $attributes, $content, $block ) {
wp_json_encode(
array(
'woocommerce' => array(
'selectedImage' => $product->get_image_id(),
'isDialogOpen' => false,
'selectedImage' => $product->get_image_id(),
'visibleImagesIds' => ProductGalleryUtils::get_product_gallery_image_ids( $product, $number_of_thumbnails, true ),
'isDialogOpen' => false,
),
)
)
Expand Down
200 changes: 128 additions & 72 deletions src/BlockTypes/ProductGalleryLargeImageNextPrevious.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,83 +40,23 @@ protected function get_block_type_uses_context() {
}

/**
* Return icons and class based on the nextPreviousButtonsPosition option
* Return class suffix
*
* @param array $context Block context.
* @return string
*/
private function get_icons( $context ) {
private function get_class_suffix( $context ) {
switch ( $context['nextPreviousButtonsPosition'] ) {
case 'insideTheImage':
return array(
'class' => 'inside-image',
'prev_button' => '<svg class="wc-block-product-gallery-large-image-next-previous-left--inside-image" xmlns="http://www.w3.org/2000/svg" width="49" height="48" viewBox="0 0 49 48" fill="none">
<g filter="url(#filter0_b_397_11356)">
<rect x="0.5" width="48" height="48" rx="5" fill="black" fill-opacity="0.5"/>
<path d="M28.1 12L30.5 14L21.3 24L30.5 34L28.1 36L17.3 24L28.1 12Z" fill="white"/>
</g>
<defs>
<filter id="filter0_b_397_11356" x="-9.5" y="-10" width="68" height="68" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feGaussianBlur in="BackgroundImageFix" stdDeviation="5"/>
<feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_397_11356"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_backgroundBlur_397_11356" result="shape"/>
</filter>
</defs>
</svg>',
'next_button' => '<svg class="wc-block-product-gallery-large-image-next-previous-right--inside-image" xmlns="http://www.w3.org/2000/svg" width="49" height="48" viewBox="0 0 49 48" fill="none">
<g filter="url(#filter0_b_397_11354)">
<rect x="0.5" width="48" height="48" rx="5" fill="black" fill-opacity="0.5"/>
<path d="M21.7001 12L19.3 14L28.5 24L19.3 34L21.7001 36L32.5 24L21.7001 12Z" fill="white"/>
</g>
<defs>
<filter id="filter0_b_397_11354" x="-9.5" y="-10" width="68" height="68" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feGaussianBlur in="BackgroundImageFix" stdDeviation="5"/>
<feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_397_11354"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_backgroundBlur_397_11354" result="shape"/>
</filter>
</defs>
</svg>',
);
return 'inside-image';
case 'outsideTheImage':
return array(
'class' => 'outside-image',
'prev_button' => '<svg
width="22"
height="38"
viewBox="0 0 22 38"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class=wc-block-product-gallery-large-image-next-previous-left--outside-image
>
<path
d="M17.7 0L21.5 3.16667L6.93334 19L21.5 34.8333L17.7 38L0.600002 19L17.7 0Z"
fill="black"
/>
</svg>',
'next_button' => '<svg
width="22"
height="38"
viewBox="0 0 22 38"
fill="none"
xmlns="http://www.w3.org/2000/svg"
class="wc-block-product-gallery-large-image-next-previous-right--outside-image"
>
<path
d="M4.56666 0L0.766663 3.16667L15.3333 19L0.766663 34.8333L4.56666 38L21.6667 19L4.56666 0Z"
fill="black"
/>
</svg>',
);

return 'outside-image';
case 'off':
return array(
'class' => 'off',
);
return 'off';
default:
return array( 'class' => 'off' );
} }
return 'off';
}
}

/**
* Include and render the block.
Expand All @@ -141,11 +81,30 @@ protected function render( $attributes, $content, $block ) {
}

$context = $block->context;
$prev_button = isset( $this->get_icons( $context )['prev_button'] ) ? $this->get_icons( $context )['prev_button'] : '';
$next_button = isset( $this->get_icons( $context )['next_button'] ) ? $this->get_icons( $context )['next_button'] : '';
$prev_button = $this->get_button( 'previous', $context );
$p = new \WP_HTML_Tag_Processor( $prev_button );

$alignment_class = isset( $attributes['layout']['verticalAlignment'] ) ? 'is-vertically-aligned-' . esc_attr( $attributes['layout']['verticalAlignment'] ) : '';
$position_class = 'wc-block-product-gallery-large-image-next-previous--' . $this->get_icons( $context )['class'];
if ( $p->next_tag() ) {
$p->set_attribute(
'data-wc-on--click',
'actions.woocommerce.handlePreviousImageButtonClick'
);
$prev_button = $p->get_updated_html();
}

$next_button = $this->get_button( 'next', $context );
$p = new \WP_HTML_Tag_Processor( $next_button );

if ( $p->next_tag() ) {
$p->set_attribute(
'data-wc-on--click',
'actions.woocommerce.handleNextImageButtonClick'
);
$next_button = $p->get_updated_html();
}

$alignment_class = isset( $attributes['layout']['verticalAlignment'] ) ? 'is-vertically-aligned-' . $attributes['layout']['verticalAlignment'] : '';
$position_class = 'wc-block-product-gallery-large-image-next-previous--' . $this->get_class_suffix( $context );

return strtr(
'<div class="wc-block-product-gallery-large-image-next-previous wp-block-woocommerce-product-gallery-large-image-next-previous {alignment_class}">
Expand All @@ -162,4 +121,101 @@ protected function render( $attributes, $content, $block ) {
)
);
}

/**
* Generates the HTML for a next or previous button for the product gallery large image.
*
* @param string $button_type The type of button to generate. Either 'previous' or 'next'.
* @param string $context The block context.
* @return string The HTML for the generated button.
*/
protected function get_button( $button_type, $context ) {
if ( 'insideTheImage' === $context['nextPreviousButtonsPosition'] ) {
return $this->get_inside_button( $button_type, $context );
}

return $this->get_outside_button( $button_type, $context );
}

/**
* Returns an HTML button element with an SVG icon for the previous or next button when the buttons are inside the image.
*
* @param string $button_type The type of button to return. Either "previous" or "next".
* @param string $context The context in which the button is being used.
* @return string The HTML for the button element.
*/
protected function get_inside_button( $button_type, $context ) {
$previous_button_icon_path = 'M28.1 12L30.5 14L21.3 24L30.5 34L28.1 36L17.3 24L28.1 12Z';
$next_button_icon_path = 'M21.7001 12L19.3 14L28.5 24L19.3 34L21.7001 36L32.5 24L21.7001 12Z';
$icon_path = $previous_button_icon_path;
$button_side_class = 'left';

if ( 'next' === $button_type ) {
$icon_path = $next_button_icon_path;
$button_side_class = 'right';
}

return sprintf(
'<button class="wc-block-product-gallery-large-image-next-previous--button wc-block-product-gallery-large-image-next-previous-%1$s--%2$s">
<svg xmlns="http://www.w3.org/2000/svg" width="49" height="48" viewBox="0 0 49 48" fill="none">
<g filter="url(#filter0_b_397_11354)">
<rect x="0.5" width="48" height="48" rx="5" fill="black" fill-opacity="0.5"/>
<path d="%3$s" fill="white"/>
</g>
<defs>
<filter id="filter0_b_397_11354" x="-9.5" y="-10" width="68" height="68" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feGaussianBlur in="BackgroundImageFix" stdDeviation="5"/>
<feComposite in2="SourceAlpha" operator="in" result="effect1_backgroundBlur_397_11354"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_backgroundBlur_397_11354" result="shape"/>
</filter>
</defs>
</svg>
</button>',
$button_side_class,
$this->get_class_suffix( $context ),
$icon_path
);

}

/**
* Returns an HTML button element with an SVG icon for the previous or next button when the buttons are outside the image.
*
* @param string $button_type The type of button to return. Either "previous" or "next".
* @param string $context The context in which the button is being used.
* @return string The HTML for the button element.
*/
protected function get_outside_button( $button_type, $context ) {
$next_button_icon_path = 'M4.56666 0L0.766663 3.16667L15.3333 19L0.766663 34.8333L4.56666 38L21.6667 19L4.56666 0Z';
$previous_button_icon_path = 'M17.7 0L21.5 3.16667L6.93334 19L21.5 34.8333L17.7 38L0.600002 19L17.7 0Z';
$icon_path = $previous_button_icon_path;
$button_side_class = 'left';

if ( 'next' === $button_type ) {
$icon_path = $next_button_icon_path;
$button_side_class = 'right';
}

return sprintf(
'<button class="wc-block-product-gallery-large-image-next-previous--button wc-block-product-gallery-large-image-next-previous-%1$s--%2$s">
<svg
width="22"
height="38"
viewBox="0 0 22 38"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="%3$s"
fill="black"
/>
</svg>
</button>',
$button_side_class,
$this->get_class_suffix( $context ),
$icon_path
);

}
}
2 changes: 1 addition & 1 deletion src/BlockTypes/ProductGalleryPager.php
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ private function render_pager_pages( $product_gallery_images_ids, $number_of_thu
'data-wc-context',
wp_json_encode(
array(
'woocommerce' => array( 'imageId' => strval( $product_gallery_image_id ) ),
'woocommerce' => array( 'imageId' => $product_gallery_image_id ),
)
)
);
Expand Down
Loading

0 comments on commit 5c8340d

Please sign in to comment.