@wordpress/block-library 8.19.6 → 8.19.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/image/view.js CHANGED
@@ -103,12 +103,10 @@ store(
103
103
  context.core.image.lastFocusedElement =
104
104
  window.document.activeElement;
105
105
  context.core.image.scrollDelta = 0;
106
+ context.core.image.pointerType = event.pointerType;
106
107
 
107
108
  context.core.image.lightboxEnabled = true;
108
- setStyles(
109
- context,
110
- event.target.previousElementSibling
111
- );
109
+ setStyles( context, context.core.image.imageRef );
112
110
 
113
111
  context.core.image.scrollTopReset =
114
112
  window.pageYOffset ||
@@ -137,7 +135,7 @@ store(
137
135
  false
138
136
  );
139
137
  },
140
- hideLightbox: async ( { context } ) => {
138
+ hideLightbox: async ( { context, event } ) => {
141
139
  context.core.image.hideAnimationEnabled = true;
142
140
  if ( context.core.image.lightboxEnabled ) {
143
141
  // We want to wait until the close animation is completed
@@ -154,9 +152,16 @@ store(
154
152
  }, 450 );
155
153
 
156
154
  context.core.image.lightboxEnabled = false;
157
- context.core.image.lastFocusedElement.focus( {
158
- preventScroll: true,
159
- } );
155
+
156
+ // We want to avoid drawing attention to the button
157
+ // after the lightbox closes for mouse and touch users.
158
+ // Note that the `event.pointerType` property returns
159
+ // as an empty string if a keyboard fired the event.
160
+ if ( event.pointerType === '' ) {
161
+ context.core.image.lastFocusedElement.focus( {
162
+ preventScroll: true,
163
+ } );
164
+ }
160
165
  }
161
166
  },
162
167
  handleKeydown: ( { context, actions, event } ) => {
@@ -191,11 +196,12 @@ store(
191
196
  }
192
197
  }
193
198
  },
194
- handleLoad: ( { state, context, effects, ref } ) => {
199
+ // This is fired just by lazily loaded
200
+ // images on the page, not all images.
201
+ handleLoad: ( { context, effects, ref } ) => {
195
202
  context.core.image.imageLoaded = true;
196
203
  context.core.image.imageCurrentSrc = ref.currentSrc;
197
204
  effects.core.image.setButtonStyles( {
198
- state,
199
205
  context,
200
206
  ref,
201
207
  } );
@@ -258,17 +264,14 @@ store(
258
264
  effects: {
259
265
  core: {
260
266
  image: {
261
- setCurrentSrc: ( { context, ref } ) => {
267
+ initOriginImage: ( { context, ref } ) => {
268
+ context.core.image.imageRef = ref;
262
269
  if ( ref.complete ) {
263
270
  context.core.image.imageLoaded = true;
264
271
  context.core.image.imageCurrentSrc = ref.currentSrc;
265
272
  }
266
273
  },
267
274
  initLightbox: async ( { context, ref } ) => {
268
- context.core.image.figureRef =
269
- ref.querySelector( 'figure' );
270
- context.core.image.imageRef =
271
- ref.querySelector( 'img' );
272
275
  if ( context.core.image.lightboxEnabled ) {
273
276
  const focusableElements =
274
277
  ref.querySelectorAll( focusableSelectors );
@@ -279,10 +282,17 @@ store(
279
282
  focusableElements.length - 1
280
283
  ];
281
284
 
282
- ref.querySelector( '.close-button' ).focus();
285
+ // We want to avoid drawing unnecessary attention to the close
286
+ // button for mouse and touch users. Note that even if opening
287
+ // the lightbox via keyboard, the event fired is of type
288
+ // `pointerEvent`, so we need to rely on the `event.pointerType`
289
+ // property, which returns an empty string for keyboard events.
290
+ if ( context.core.image.pointerType === '' ) {
291
+ ref.querySelector( '.close-button' ).focus();
292
+ }
283
293
  }
284
294
  },
285
- setButtonStyles: ( { state, context, ref } ) => {
295
+ setButtonStyles: ( { context, ref } ) => {
286
296
  const {
287
297
  naturalWidth,
288
298
  naturalHeight,
@@ -291,54 +301,71 @@ store(
291
301
  } = ref;
292
302
 
293
303
  // If the image isn't loaded yet, we can't
294
- // calculate how big the button should be.
304
+ // calculate where the button should be.
295
305
  if ( naturalWidth === 0 || naturalHeight === 0 ) {
296
306
  return;
297
307
  }
298
308
 
299
- // Subscribe to the window dimensions so we can
300
- // recalculate the styles if the window is resized.
301
- if (
302
- ( state.core.image.windowWidth ||
303
- state.core.image.windowHeight ) &&
304
- context.core.image.scaleAttr === 'contain'
305
- ) {
306
- // In the case of an image with object-fit: contain, the
307
- // size of the img element can be larger than the image itself,
308
- // so we need to calculate the size of the button to match.
309
+ const figure = ref.parentElement;
310
+ const figureWidth = ref.parentElement.clientWidth;
311
+
312
+ // We need special handling for the height because
313
+ // a caption will cause the figure to be taller than
314
+ // the image, which means we need to account for that
315
+ // when calculating the placement of the button in the
316
+ // top right corner of the image.
317
+ let figureHeight = ref.parentElement.clientHeight;
318
+ const caption = figure.querySelector( 'figcaption' );
319
+ if ( caption ) {
320
+ const captionComputedStyle =
321
+ window.getComputedStyle( caption );
322
+ figureHeight =
323
+ figureHeight -
324
+ caption.offsetHeight -
325
+ parseFloat( captionComputedStyle.marginTop ) -
326
+ parseFloat( captionComputedStyle.marginBottom );
327
+ }
309
328
 
329
+ const buttonOffsetTop = figureHeight - offsetHeight;
330
+ const buttonOffsetRight = figureWidth - offsetWidth;
331
+
332
+ // In the case of an image with object-fit: contain, the
333
+ // size of the <img> element can be larger than the image itself,
334
+ // so we need to calculate where to place the button.
335
+ if ( context.core.image.scaleAttr === 'contain' ) {
310
336
  // Natural ratio of the image.
311
337
  const naturalRatio = naturalWidth / naturalHeight;
312
338
  // Offset ratio of the image.
313
339
  const offsetRatio = offsetWidth / offsetHeight;
314
340
 
315
- if ( naturalRatio > offsetRatio ) {
341
+ if ( naturalRatio >= offsetRatio ) {
316
342
  // If it reaches the width first, keep
317
- // the width and recalculate the height.
318
- context.core.image.imageButtonWidth =
319
- offsetWidth;
320
- const buttonHeight = offsetWidth / naturalRatio;
321
- context.core.image.imageButtonHeight =
322
- buttonHeight;
343
+ // the width and compute the height.
344
+ const referenceHeight =
345
+ offsetWidth / naturalRatio;
323
346
  context.core.image.imageButtonTop =
324
- ( offsetHeight - buttonHeight ) / 2;
347
+ ( offsetHeight - referenceHeight ) / 2 +
348
+ buttonOffsetTop +
349
+ 10;
350
+ context.core.image.imageButtonRight =
351
+ buttonOffsetRight + 10;
325
352
  } else {
326
353
  // If it reaches the height first, keep
327
- // the height and recalculate the width.
328
- context.core.image.imageButtonHeight =
329
- offsetHeight;
330
- const buttonWidth = offsetHeight * naturalRatio;
331
- context.core.image.imageButtonWidth =
332
- buttonWidth;
333
- context.core.image.imageButtonLeft =
334
- ( offsetWidth - buttonWidth ) / 2;
354
+ // the height and compute the width.
355
+ const referenceWidth =
356
+ offsetHeight * naturalRatio;
357
+ context.core.image.imageButtonTop =
358
+ buttonOffsetTop + 10;
359
+ context.core.image.imageButtonRight =
360
+ ( offsetWidth - referenceWidth ) / 2 +
361
+ buttonOffsetRight +
362
+ 10;
335
363
  }
336
364
  } else {
337
- // In all other cases, we can trust that the size of
338
- // the image is the right size for the button as well.
339
-
340
- context.core.image.imageButtonWidth = offsetWidth;
341
- context.core.image.imageButtonHeight = offsetHeight;
365
+ context.core.image.imageButtonTop =
366
+ buttonOffsetTop + 10;
367
+ context.core.image.imageButtonRight =
368
+ buttonOffsetRight + 10;
342
369
  }
343
370
  },
344
371
  setStylesOnResize: ( { state, context, ref } ) => {
@@ -38,6 +38,7 @@ function render_block_core_post_navigation_link( $attributes, $content ) {
38
38
  $link = 'next' === $navigation_type ? _x( 'Next', 'label for next post link' ) : _x( 'Previous', 'label for previous post link' );
39
39
  $label = '';
40
40
 
41
+ // Only use hardcoded values here, otherwise we need to add escaping where these values are used.
41
42
  $arrow_map = array(
42
43
  'none' => '',
43
44
  'arrow' => array(
@@ -88,7 +89,7 @@ function render_block_core_post_navigation_link( $attributes, $content ) {
88
89
  }
89
90
 
90
91
  // Display arrows.
91
- if ( isset( $attributes['arrow'] ) && ! empty( $attributes['arrow'] ) && 'none' !== $attributes['arrow'] ) {
92
+ if ( isset( $attributes['arrow'] ) && 'none' !== $attributes['arrow'] && isset( $arrow_map[ $attributes['arrow'] ] ) ) {
92
93
  $arrow = $arrow_map[ $attributes['arrow'] ][ $navigation_type ];
93
94
 
94
95
  if ( 'next' === $navigation_type ) {