Product Gallery: Polish Gallery in full view mode (https://github.com/woocommerce/woocommerce-blocks/pull/10947)
* Product Gallery: add support for On Sale Badge Block * add align support * Add E2E tests * set margin via Block Styles * disable experimental flag * add next previous block * restore support file * fix TS error * fix layout * change product * change product * Product Gallert Block: Add zoom on hover * set to true by default * remove block is already registered error * remove unecessary await * Improve zoom logic Co-authored-by: Alexandre Lara <allexandrelara@gmail.com> * Product Gallery Full view mode: Add the logic to render the dedicated template * use template-part instead template * add E2E tests * update selectors * add feature flag product gallery template part * fix E2E tests * remove not necessary file * polish the dialog * fix: dialog show always the selected product * fix: not open the dialog when the user click on icon * rename handleClick to handleCloseButtonClick * improve style * fix overlay css * fix registration * improve logic * improve default template --------- Co-authored-by: Alexandre Lara <allexandrelara@gmail.com>
This commit is contained in:
parent
60e5943c53
commit
29fe7cdce0
|
@ -20,7 +20,8 @@
|
|||
"productGalleryClientId": "productGalleryClientId",
|
||||
"nextPreviousButtonsPosition": "nextPreviousButtonsPosition",
|
||||
"pagerDisplayMode": "pagerDisplayMode",
|
||||
"hoverZoom": "hoverZoom"
|
||||
"hoverZoom": "hoverZoom",
|
||||
"fullScreenOnClick": "fullScreenOnClick"
|
||||
},
|
||||
"usesContext": [ "postId" ],
|
||||
"attributes": {
|
||||
|
|
|
@ -88,19 +88,14 @@ const TEMPLATE: InnerBlockTemplate[] = [
|
|||
],
|
||||
];
|
||||
|
||||
const setMode = (
|
||||
currentTemplateId: string,
|
||||
templateType: string,
|
||||
setAttributes: ( attrs: Partial< ProductGalleryAttributes > ) => void
|
||||
) => {
|
||||
const getMode = ( currentTemplateId: string, templateType: string ) => {
|
||||
if (
|
||||
templateType === 'wp_template_part' &&
|
||||
currentTemplateId.includes( 'product-gallery' )
|
||||
) {
|
||||
setAttributes( {
|
||||
mode: 'full',
|
||||
} );
|
||||
return 'full';
|
||||
}
|
||||
return 'standard';
|
||||
};
|
||||
|
||||
export const Edit = ( {
|
||||
|
@ -123,17 +118,22 @@ export const Edit = ( {
|
|||
);
|
||||
|
||||
useEffect( () => {
|
||||
setMode( currentTemplateId, templateType, setAttributes );
|
||||
}, [ currentTemplateId, setAttributes, templateType ] );
|
||||
const mode = getMode( currentTemplateId, templateType );
|
||||
|
||||
useEffect( () => {
|
||||
setAttributes( {
|
||||
...attributes,
|
||||
mode,
|
||||
productGalleryClientId: clientId,
|
||||
} );
|
||||
// Move the Thumbnails block to the correct above or below the Large Image based on the thumbnailsPosition attribute.
|
||||
moveInnerBlocksToPosition( attributes, clientId );
|
||||
}, [ setAttributes, attributes, clientId ] );
|
||||
}, [
|
||||
setAttributes,
|
||||
attributes,
|
||||
clientId,
|
||||
currentTemplateId,
|
||||
templateType,
|
||||
] );
|
||||
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
|
|
|
@ -60,7 +60,7 @@ interactivityApiStore( {
|
|||
: 0.2;
|
||||
},
|
||||
isDialogOpen: ( { context }: Store ) => {
|
||||
return context?.woocommerce.isDialogOpen;
|
||||
return context.woocommerce.isDialogOpen;
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -72,6 +72,11 @@ interactivityApiStore( {
|
|||
context.woocommerce.imageId;
|
||||
},
|
||||
},
|
||||
dialog: {
|
||||
handleCloseButtonClick: ( { context }: Store ) => {
|
||||
context.woocommerce.isDialogOpen = false;
|
||||
},
|
||||
},
|
||||
handleSelectImage: ( { context }: Store ) => {
|
||||
context.woocommerce.selectedImage = context.woocommerce.imageId;
|
||||
},
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { registerBlockSingleProductTemplate } from '@woocommerce/atomic-utils';
|
||||
import { isExperimentalBuild } from '@woocommerce/block-settings';
|
||||
import { registerBlockType } from '@wordpress/blocks';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -18,16 +18,10 @@ import './inner-blocks/product-gallery-pager';
|
|||
import './inner-blocks/product-gallery-thumbnails';
|
||||
|
||||
if ( isExperimentalBuild() ) {
|
||||
registerBlockSingleProductTemplate( {
|
||||
blockName: metadata.name,
|
||||
// @ts-expect-error: `metadata` currently does not have a type definition in WordPress core
|
||||
blockMetadata: metadata,
|
||||
blockSettings: {
|
||||
icon,
|
||||
// @ts-expect-error `edit` can be extended to include other attributes
|
||||
edit: Edit,
|
||||
save: Save,
|
||||
},
|
||||
isAvailableOnPostEditor: true,
|
||||
// @ts-expect-error: `metadata` currently does not have a type definition in WordPress core.
|
||||
registerBlockType( metadata, {
|
||||
icon,
|
||||
edit: Edit,
|
||||
save: Save,
|
||||
} );
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"description": "Display the Large Image of a product.",
|
||||
"category": "woocommerce",
|
||||
"keywords": [ "WooCommerce" ],
|
||||
"usesContext": [ "nextPreviousButtonsPosition", "postId", "hoverZoom"],
|
||||
"usesContext": [ "nextPreviousButtonsPosition", "postId", "hoverZoom", "fullScreenOnClick"],
|
||||
"supports": {
|
||||
"interactivity": true
|
||||
},
|
||||
|
|
|
@ -65,8 +65,16 @@ interactivityStore(
|
|||
context.woocommerce.styles.transform = `scale(1.0)`;
|
||||
context.woocommerce.styles[ 'transform-origin' ] = '';
|
||||
},
|
||||
handleClick: ( { context }: { context: Context } ) => {
|
||||
context.woocommerce.isDialogOpen = true;
|
||||
handleClick: ( {
|
||||
context,
|
||||
event,
|
||||
}: {
|
||||
context: Context;
|
||||
event: Event;
|
||||
} ) => {
|
||||
if ( ( event.target as HTMLElement ).tagName === 'IMG' ) {
|
||||
context.woocommerce.isDialogOpen = true;
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -11,13 +11,39 @@ $outside-image-max-width: calc(100% - (2 * $outside-image-offset));
|
|||
|
||||
// Product Gallery
|
||||
#{$gallery} {
|
||||
.wc-block-product-gallery-dialog__overlay {
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: #808080;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
dialog {
|
||||
position: fixed;
|
||||
width: 90vw;
|
||||
width: calc(100vw - 100px);
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
height: 90vh;
|
||||
top: 0;
|
||||
margin: $gap-largest;
|
||||
margin-top: $gap-largest;
|
||||
margin-bottom: $gap-largest;
|
||||
z-index: 9999;
|
||||
|
||||
.wc-block-product-galler-dialog__header-right {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
.wc-block-product-gallery-dialog__close {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -37,9 +63,16 @@ $outside-image-max-width: calc(100% - (2 * $outside-image-offset));
|
|||
|
||||
img {
|
||||
display: block;
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
z-index: 1;
|
||||
transition: all 0.1s linear;
|
||||
|
||||
// Keep the order in this way. The hoverZoom class should override the full-screen-on-click class when both are applied.
|
||||
&.wc-block-woocommerce-product-gallery-large-image__image--full-screen-on-click {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.wc-block-woocommerce-product-gallery-large-image__image--hoverZoom {
|
||||
cursor: zoom-in;
|
||||
}
|
||||
|
@ -53,8 +86,6 @@ $outside-image-max-width: calc(100% - (2 * $outside-image-offset));
|
|||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
|
@ -76,6 +107,11 @@ $outside-image-max-width: calc(100% - (2 * $outside-image-offset));
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
svg {
|
||||
z-index: 3;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.is-vertically-aligned-top {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ export interface ProductGalleryBlockAttributes {
|
|||
cropImages?: boolean;
|
||||
hoverZoom?: boolean;
|
||||
fullScreenOnClick?: boolean;
|
||||
mode: 'standard' | 'full';
|
||||
mode?: 'standard' | 'full';
|
||||
}
|
||||
|
||||
export interface ProductGalleryThumbnailsBlockAttributes {
|
||||
|
|
|
@ -65,7 +65,39 @@ class ProductGallery extends AbstractBlock {
|
|||
''
|
||||
);
|
||||
|
||||
$gallery_dialog = '<dialog data-wc-bind--open="selectors.woocommerce.isDialogOpen">' . $html . '</dialog>';
|
||||
$html_processor = new \WP_HTML_Tag_Processor( $html );
|
||||
|
||||
$html_processor->next_tag(
|
||||
array(
|
||||
'class_name' => 'wp-block-woocommerce-product-gallery',
|
||||
)
|
||||
);
|
||||
|
||||
$html_processor->remove_attribute( 'data-wc-context' );
|
||||
|
||||
$gallery_dialog = strtr(
|
||||
'
|
||||
<div class="wc-block-product-gallery-dialog__overlay" hidden data-wc-bind--hidden="!selectors.woocommerce.isDialogOpen">
|
||||
<dialog data-wc-bind--open="selectors.woocommerce.isDialogOpen">
|
||||
<div class="wc-block-product-gallery-dialog__header">
|
||||
<div class="wc-block-product-galler-dialog__header-right">
|
||||
<button class="wc-block-product-gallery-dialog__close" data-wc-on--click="actions.woocommerce.dialog.handleCloseButtonClick">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect width="24" height="24" rx="2"/>
|
||||
<path d="M13 11.8L19.1 5.5L18.1 4.5L12 10.7L5.9 4.5L4.9 5.5L11 11.8L4.5 18.5L5.5 19.5L12 12.9L18.5 19.5L19.5 18.5L13 11.8Z" fill="black"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="wc-block-product-gallery-dialog__body">
|
||||
{{html}}
|
||||
</div>
|
||||
</dialog>
|
||||
</div>',
|
||||
array(
|
||||
'{{html}}' => $html_processor->get_updated_html(),
|
||||
)
|
||||
);
|
||||
return $gallery_dialog;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class ProductGalleryLargeImage extends AbstractBlock {
|
|||
* @return string[]
|
||||
*/
|
||||
protected function get_block_type_uses_context() {
|
||||
return [ 'postId', 'hoverZoom' ];
|
||||
return [ 'postId', 'hoverZoom', 'fullScreenOnClick' ];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -41,7 +41,7 @@ class ProductGalleryLargeImage extends AbstractBlock {
|
|||
* @param WP_Block $block The block object.
|
||||
*/
|
||||
protected function enqueue_assets( array $attributes, $content, $block ) {
|
||||
if ( $block->context['hoverZoom'] ) {
|
||||
if ( $block->context['hoverZoom'] || $block->context['fullScreenOnClick'] ) {
|
||||
parent::enqueue_assets( $attributes, $content, $block );
|
||||
}
|
||||
}
|
||||
|
@ -124,6 +124,10 @@ class ProductGalleryLargeImage extends AbstractBlock {
|
|||
|
||||
);
|
||||
|
||||
if ( $context['fullScreenOnClick'] ) {
|
||||
$attributes['class'] .= ' wc-block-woocommerce-product-gallery-large-image__image--full-screen-on-click';
|
||||
}
|
||||
|
||||
if ( $context['hoverZoom'] ) {
|
||||
$attributes['class'] .= ' wc-block-woocommerce-product-gallery-large-image__image--hoverZoom';
|
||||
$attributes['data-wc-bind--style'] = 'selectors.woocommerce.styles';
|
||||
|
@ -147,17 +151,30 @@ class ProductGalleryLargeImage extends AbstractBlock {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get directives for the hover zoom.
|
||||
* Get directives for the block.
|
||||
*
|
||||
* @param array $block_context The block context.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_directives( $block_context ) {
|
||||
return array_merge(
|
||||
$this->get_zoom_directives( $block_context ),
|
||||
$this->get_open_dialog_directives( $block_context )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get directives for zoom.
|
||||
*
|
||||
* @param array $block_context The block context.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_zoom_directives( $block_context ) {
|
||||
if ( ! $block_context['hoverZoom'] ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$context = array(
|
||||
'woocommerce' => array(
|
||||
'styles' => array(
|
||||
|
@ -170,8 +187,24 @@ class ProductGalleryLargeImage extends AbstractBlock {
|
|||
return array(
|
||||
'data-wc-on--mousemove' => 'actions.woocommerce.handleMouseMove',
|
||||
'data-wc-on--mouseleave' => 'actions.woocommerce.handleMouseLeave',
|
||||
'data-wc-on--click' => 'actions.woocommerce.handleClick',
|
||||
'data-wc-context' => wp_json_encode( $context, JSON_NUMERIC_CHECK ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get directives for opening the dialog.
|
||||
*
|
||||
* @param array $block_context The block context.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function get_open_dialog_directives( $block_context ) {
|
||||
if ( ! $block_context['fullScreenOnClick'] ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
return array(
|
||||
'data-wc-on--click' => 'actions.woocommerce.handleClick',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,27 @@
|
|||
<!-- wp:woocommerce/product-gallery {"mode":"full"} -->
|
||||
<div class="wp-block-woocommerce-product-gallery"><!-- wp:group {"layout":{"type":"flex","flexWrap":"nowrap"}} -->
|
||||
<div class="wp-block-group"><!-- wp:woocommerce/product-gallery-thumbnails {"lock":{"move":true,"remove":true}} /-->
|
||||
<!-- wp:group {"layout":{"type":"constrained"}} -->
|
||||
<div class="wp-block-group">
|
||||
<!-- wp:woocommerce/product-gallery {"mode":"full"} -->
|
||||
<div
|
||||
class="wp-block-woocommerce-product-gallery wc-block-product-gallery wc-block-product-gallery--has-next-previous-buttons-inside-image">
|
||||
<!-- wp:group {"layout":{"type":"flex","flexWrap":"nowrap"}} -->
|
||||
<div class="wp-block-group">
|
||||
<!-- wp:woocommerce/product-gallery-thumbnails {"lock":{"move":true,"remove":true}} /-->
|
||||
|
||||
<!-- wp:woocommerce/product-gallery-large-image {"lock":{"move":true,"remove":true}} -->
|
||||
<div
|
||||
class="wp-block-woocommerce-product-gallery-large-image wc-block-product-gallery-large-image__inner-blocks">
|
||||
<!-- wp:woocommerce/product-sale-badge {"isDescendentOfSingleProductTemplate":true,"align":"right","style":{"spacing":{"margin":{"top":"4px","right":"4px","bottom":"4px","left":"4px"}}}} /-->
|
||||
<!-- wp:woocommerce/product-gallery-large-image {"lock":{"move":true,"remove":true}} -->
|
||||
<div
|
||||
class="wp-block-woocommerce-product-gallery-large-image wc-block-product-gallery-large-image__inner-blocks">
|
||||
<!-- wp:woocommerce/product-sale-badge {"isDescendentOfSingleProductTemplate":true,"align":"right","style":{"spacing":{"margin":{"top":"4px","right":"4px","bottom":"4px","left":"4px"}}}} /-->
|
||||
|
||||
<!-- wp:woocommerce/product-gallery-large-image-next-previous {"layout":{"type":"flex","verticalAlignment":"bottom"}} -->
|
||||
<div class="wp-block-woocommerce-product-gallery-large-image-next-previous"></div>
|
||||
<!-- /wp:woocommerce/product-gallery-large-image-next-previous -->
|
||||
<!-- wp:woocommerce/product-gallery-large-image-next-previous {"layout":{"type":"flex","verticalAlignment":"bottom"}} -->
|
||||
<div class="wp-block-woocommerce-product-gallery-large-image-next-previous"></div>
|
||||
<!-- /wp:woocommerce/product-gallery-large-image-next-previous -->
|
||||
</div>
|
||||
<!-- /wp:woocommerce/product-gallery-large-image -->
|
||||
</div>
|
||||
<!-- /wp:woocommerce/product-gallery-large-image -->
|
||||
</div>
|
||||
<!-- /wp:group -->
|
||||
<!-- /wp:group -->
|
||||
|
||||
<!-- wp:woocommerce/product-gallery-pager {"lock":{"move":true,"remove":true}} /-->
|
||||
<!-- wp:woocommerce/product-gallery-pager {"lock":{"move":true,"remove":true}} /-->
|
||||
</div>
|
||||
<!-- /wp:woocommerce/product-gallery -->
|
||||
</div>
|
||||
<!-- /wp:woocommerce/product-gallery -->
|
||||
<!-- /wp:group -->
|
Loading…
Reference in New Issue