Skip to content

Commit

Permalink
add lightbox support to gallery block
Browse files Browse the repository at this point in the history
  • Loading branch information
madhusudhand committed Jul 11, 2024
1 parent a24fa62 commit 5af6a6b
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 10 deletions.
58 changes: 57 additions & 1 deletion packages/block-library/src/gallery/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function block_core_gallery_data_id_backcompatibility( $parsed_block ) {
* @param string $content Content of the block being rendered.
* @return string The content of the block being rendered.
*/
function block_core_gallery_render( $attributes, $content ) {
function block_core_gallery_render( $attributes, $content, $block ) {
// Adds a style tag for the --wp--style--unstable-gallery-gap var.
// The Gallery block needs to recalculate Image block width based on
// the current gap setting in order to maintain the number of flex columns
Expand Down Expand Up @@ -121,6 +121,35 @@ function block_core_gallery_render( $attributes, $content ) {
)
);

$lightbox_settings = block_core_image_get_lightbox_settings( $block->parsed_block );

if (
isset( $lightbox_settings ) &&
// 'none' === $link_destination &&
isset( $lightbox_settings['enabled'] ) &&
true === $lightbox_settings['enabled']
) {
$processed_content->set_attribute( 'data-wp-interactive', 'core/gallery' );
$processed_content->set_attribute( 'data-wp-context', '{"lightbox": true, "images": []}' );
$processed_content->set_attribute( 'data-wp-init', 'callbacks.init' );
$processed_content->set_attribute( 'data-wp-on-async--load', 'callbacks.init' );

$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/gallery.min.js' );
}

wp_register_script_module(
'@wordpress/block-library/gallery',
isset( $module_url ) ? $module_url : includes_url( "blocks/gallery/view{$suffix}.js" ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);

wp_enqueue_script_module( '@wordpress/block-library/gallery' );

}

// The WP_HTML_Tag_Processor class calls get_updated_html() internally
// when the instance is treated as a string, but here we explicitly
// convert it to a string.
Expand Down Expand Up @@ -166,6 +195,33 @@ static function () use ( $image_blocks, &$i ) {

return $content;
}

// NOTE: this setting isn't required for the gallery block.
// since lightbox implementation is done in the image block, it can totally be removed.
function block_core_gallery_get_lightbox_settings( $block ) {

Check failure on line 201 in packages/block-library/src/gallery/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Missing @SInCE tag for the "block_core_gallery_get_lightbox_settings()" function.
// Gets the lightbox setting from the block attributes.
if ( isset( $block['attrs']['lightbox'] ) ) {
$lightbox_settings = $block['attrs']['lightbox'];
}

if ( ! isset( $lightbox_settings ) ) {
// TODO: change it to gallery block name.
$lightbox_settings = wp_get_global_settings( array( 'lightbox' ), array( 'block_name' => 'core/image' ) );

// If not present in global settings, check the top-level global settings.
//
// NOTE: If no block-level settings are found, the previous call to
// `wp_get_global_settings` will return the whole `theme.json` structure in
// which case we can check if the "lightbox" key is present at the top-level
// of the global settings and use its value.
if ( isset( $lightbox_settings['lightbox'] ) ) {
$lightbox_settings = wp_get_global_settings( array( 'lightbox' ) );
}
}

return $lightbox_settings ?? null;
}

/**
* Registers the `core/gallery` block on server.
*
Expand Down
20 changes: 20 additions & 0 deletions packages/block-library/src/gallery/view.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* WordPress dependencies
*/
import { store, getContext, getElement } from '@wordpress/interactivity';

store(
'core/gallery',
{
callbacks: {
init() {
const { ref } = getElement();
const ctx = getContext();
ctx.galleryRef = ref;
},
},
},
{
lock: false,
}
);
11 changes: 10 additions & 1 deletion packages/block-library/src/image/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ function block_core_image_render_lightbox( $block_content, $block ) {
JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
)
);
$p->set_attribute( 'data-wp-init', 'callbacks.initImage' );

// Image.
$p->next_tag( 'img' );
Expand Down Expand Up @@ -265,6 +266,8 @@ class="lightbox-trigger"
*/
function block_core_image_print_lightbox_overlay() {
$close_button_label = esc_attr__( 'Close' );
$prev_button_label = esc_attr__( 'Previous' );

Check warning on line 269 in packages/block-library/src/image/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Equals sign not aligned with surrounding assignments; expected 2 spaces but found 1 space
$next_button_label = esc_attr__( 'Next' );

Check warning on line 270 in packages/block-library/src/image/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Equals sign not aligned with surrounding assignments; expected 2 spaces but found 1 space

// If the current theme does NOT have a `theme.json`, or the colors are not
// defined, it needs to set the background color & close button color to some
Expand All @@ -285,7 +288,7 @@ function block_core_image_print_lightbox_overlay() {
<div
class="wp-lightbox-overlay zoom"
data-wp-interactive="core/image"
data-wp-context='{}'
data-wp-context='{ "carousel": "true" }'
data-wp-bind--role="state.roleAttribute"
data-wp-bind--aria-label="state.currentImage.ariaLabel"
data-wp-bind--aria-modal="state.ariaModal"
Expand All @@ -304,6 +307,12 @@ class="wp-lightbox-overlay zoom"
<button type="button" aria-label="$close_button_label" style="fill: $close_button_color" class="close-button">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" focusable="false"><path d="M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"></path></svg>
</button>
<button type="button" aria-label="$prev_button_label" style="fill: $close_button_color" class="prev-button" data-wp-bind--hidden="!state.isGallery" data-wp-on--click="actions.showPreviousImage">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" focusable="false"><path d="M14.6 7l-1.2-1L8 12l5.4 6 1.2-1-4.6-5z"></path></svg>
</button>
<button type="button" aria-label="$next_button_label" style="fill: $close_button_color" class="next-button" data-wp-bind--hidden="!state.isGallery" data-wp-on--click="actions.showNextImage">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" focusable="false"><path d="M10.6 6L9.4 7l4.6 5-4.6 5 1.2 1 5.4-6z"></path></svg>
</button>
<div class="lightbox-image-container">
<figure data-wp-bind--class="state.currentImage.figureClassNames" data-wp-bind--style="state.currentImage.figureStyles">
<img data-wp-bind--alt="state.currentImage.alt" data-wp-bind--class="state.currentImage.imgClassNames" data-wp-bind--style="state.imgStyles" data-wp-bind--src="state.currentImage.currentSrc">
Expand Down
34 changes: 34 additions & 0 deletions packages/block-library/src/image/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,40 @@
}
}

.prev-button,
.next-button {
position: absolute;
top: 50%;
transform: translateY(-50%);
padding: 0;
cursor: pointer;
z-index: 5000000;
min-width: 40px; // equivalent to $button-size-next-default-40px
min-height: 40px; // equivalent to $button-size-next-default-40px;
display: flex;
align-items: center;
justify-content: center;

&[hidden] {
display: none;
}

&:hover,
&:focus,
&:not(:hover):not(:active):not(.has-background) {
background: none;
border: none;
}
}

.prev-button {
left: calc(env(safe-area-inset-left) + 16px); // equivalent to $grid-unit-20
}

.next-button {
right: calc(env(safe-area-inset-right) + 16px); // equivalent to $grid-unit-20
}

.lightbox-image-container {
position: absolute;
overflow: hidden;
Expand Down
78 changes: 70 additions & 8 deletions packages/block-library/src/image/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ const { state, actions, callbacks } = store(
state: {
metadata: {},
currentImage: {},
images: [],
isGallery: false,
get overlayOpened() {
return state.currentImage.currentSrc;
},
Expand Down Expand Up @@ -59,18 +61,20 @@ const { state, actions, callbacks } = store(
return;
}

state.overlayEnabled = true;

// Stores the positions of the scroll to fix it until the overlay is
// closed.
state.scrollTopReset = document.documentElement.scrollTop;
state.scrollLeftReset = document.documentElement.scrollLeft;

// Sets the information of the expanded image in the state.
state.currentImage = state.metadata[ ctx.imageId ];
const { lightbox, images } = getContext( 'core/gallery' ) || {};
state.isGallery = !! lightbox || false;
state.images = state.isGallery ? images || [] : [ ctx.imageId ];

// Computes the styles of the overlay for the animation.
callbacks.setOverlayStyles();
// Sets the current image index to the one that was clicked.
callbacks.setCurrentImageIndex( ctx.imageId );

// Sets the information of the expanded image in the state.
callbacks.setCurrentImage();
},
hideLightbox() {
if ( state.overlayEnabled ) {
Expand All @@ -97,18 +101,50 @@ const { state, actions, callbacks } = store(
state.overlayEnabled = false;
}
},
showPreviousImage( e ) {
if ( ! state.isGallery ) {
return;
}

e.stopPropagation();
if ( state.currentImageIndex - 1 < 0 ) {
return;
}
state.currentImageIndex = state.currentImageIndex - 1;
callbacks.setCurrentImage();
},
showNextImage( e ) {
if ( ! state.isGallery ) {
return;
}

e.stopPropagation();
if ( state.currentImageIndex + 1 >= state.images.length ) {
return;
}
state.currentImageIndex = state.currentImageIndex + 1;
callbacks.setCurrentImage();
},
handleKeydown( event ) {
if ( state.overlayEnabled ) {
// Focuses the close button when the user presses the tab key.
if ( event.key === 'Tab' ) {
event.preventDefault();
const { ref } = getElement();
ref.querySelector( 'button' ).focus();

// TODO: now that there are next and prev buttons, rotate the focus
}
// Closes the lightbox when the user presses the escape key.
if ( event.key === 'Escape' ) {
actions.hideLightbox();
}

if ( event.key === 'ArrowLeft' ) {
actions.showPreviousImage( event );
} else if ( event.key === 'ArrowRight' ) {
actions.showNextImage( event );
}
}
},
handleTouchMove( event ) {
Expand Down Expand Up @@ -156,6 +192,30 @@ const { state, actions, callbacks } = store(
},
},
callbacks: {
initImage() {
const { lightbox, images } = getContext( 'core/gallery' ) || {};
if ( ! lightbox ) {
return;
}

const ctx = getContext();
images.push( ctx.imageId );
},
setCurrentImageIndex( imageId ) {
const currentIndex = state.images.findIndex(
( id ) => id === imageId
);
state.currentImageIndex = currentIndex;
},
setCurrentImage() {
const imageId = state.images[ state.currentImageIndex ];
state.currentImage = state.metadata[ imageId ];

state.overlayEnabled = true;

// Computes the styles of the overlay for the animation.
callbacks.setOverlayStyles();
},
setOverlayStyles() {
if ( ! state.currentImage.imageRef ) {
return;
Expand Down Expand Up @@ -198,12 +258,14 @@ const { state, actions, callbacks } = store(
// size), the image's dimensions in the lightbox are the same
// as those of the image in the content.
let imgMaxWidth = parseFloat(
state.currentImage.targetWidth !== 'none'
state.currentImage.targetWidth &&
state.currentImage.targetWidth !== 'none'
? state.currentImage.targetWidth
: naturalWidth
);
let imgMaxHeight = parseFloat(
state.currentImage.targetHeight !== 'none'
state.currentImage.targetHeight &&
state.currentImage.targetHeight !== 'none'
? state.currentImage.targetHeight
: naturalHeight
);
Expand Down
1 change: 1 addition & 0 deletions tools/webpack/interactivity.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ module.exports = {
navigation: './packages/block-library/src/navigation/view.js',
query: './packages/block-library/src/query/view.js',
image: './packages/block-library/src/image/view.js',
gallery: './packages/block-library/src/gallery/view.js',
file: './packages/block-library/src/file/view.js',
search: './packages/block-library/src/search/view.js',
},
Expand Down

0 comments on commit 5af6a6b

Please sign in to comment.