@wordpress/block-library 8.19.7 → 8.19.9
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/build/image/image.js +8 -2
- package/build/image/image.js.map +1 -1
- package/build/image/view.js +47 -34
- package/build/image/view.js.map +1 -1
- package/build/navigation/view.js +20 -5
- package/build/navigation/view.js.map +1 -1
- package/build-module/image/image.js +8 -2
- package/build-module/image/image.js.map +1 -1
- package/build-module/image/view.js +47 -34
- package/build-module/image/view.js.map +1 -1
- package/build-module/navigation/view.js +20 -5
- package/build-module/navigation/view.js.map +1 -1
- package/build-style/image/style-rtl.css +23 -4
- package/build-style/image/style.css +23 -4
- package/build-style/style-rtl.css +23 -4
- package/build-style/style.css +23 -4
- package/package.json +32 -32
- package/src/image/image.js +13 -2
- package/src/image/index.php +16 -7
- package/src/image/style.scss +27 -4
- package/src/image/view.js +69 -48
- package/src/navigation/index.php +7 -0
- package/src/navigation/view.js +18 -6
package/src/image/index.php
CHANGED
|
@@ -218,28 +218,36 @@ function block_core_image_render_lightbox( $block_content, $block ) {
|
|
|
218
218
|
)
|
|
219
219
|
);
|
|
220
220
|
$w->next_tag( 'img' );
|
|
221
|
-
$w->set_attribute( 'data-wp-init', 'effects.core.image.
|
|
221
|
+
$w->set_attribute( 'data-wp-init', 'effects.core.image.initOriginImage' );
|
|
222
222
|
$w->set_attribute( 'data-wp-on--load', 'actions.core.image.handleLoad' );
|
|
223
223
|
$w->set_attribute( 'data-wp-effect', 'effects.core.image.setButtonStyles' );
|
|
224
|
+
// We need to set an event callback on the `img` specifically
|
|
225
|
+
// because the `figure` element can also contain a caption, and
|
|
226
|
+
// we don't want to trigger the lightbox when the caption is clicked.
|
|
227
|
+
$w->set_attribute( 'data-wp-on--click', 'actions.core.image.showLightbox' );
|
|
224
228
|
$w->set_attribute( 'data-wp-effect--setStylesOnResize', 'effects.core.image.setStylesOnResize' );
|
|
225
229
|
$body_content = $w->get_updated_html();
|
|
226
230
|
|
|
227
|
-
//
|
|
231
|
+
// Add a button alongside image in the body content.
|
|
228
232
|
$img = null;
|
|
229
233
|
preg_match( '/<img[^>]+>/', $body_content, $img );
|
|
230
234
|
|
|
231
235
|
$button =
|
|
232
236
|
$img[0]
|
|
233
237
|
. '<button
|
|
238
|
+
class="lightbox-trigger"
|
|
234
239
|
type="button"
|
|
235
240
|
aria-haspopup="dialog"
|
|
236
241
|
aria-label="' . esc_attr( $aria_label ) . '"
|
|
237
242
|
data-wp-on--click="actions.core.image.showLightbox"
|
|
238
|
-
data-wp-style--
|
|
239
|
-
data-wp-style--height="context.core.image.imageButtonHeight"
|
|
240
|
-
data-wp-style--left="context.core.image.imageButtonLeft"
|
|
243
|
+
data-wp-style--right="context.core.image.imageButtonRight"
|
|
241
244
|
data-wp-style--top="context.core.image.imageButtonTop"
|
|
242
|
-
|
|
245
|
+
style="background: #000"
|
|
246
|
+
>
|
|
247
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" aria-hidden="true" focusable="false">
|
|
248
|
+
<Path stroke="#FFFFFF" d="M6 4a2 2 0 0 0-2 2v3h1.5V6a.5.5 0 0 1 .5-.5h3V4H6Zm3 14.5H6a.5.5 0 0 1-.5-.5v-3H4v3a2 2 0 0 0 2 2h3v-1.5Zm6 1.5v-1.5h3a.5.5 0 0 0 .5-.5v-3H20v3a2 2 0 0 1-2 2h-3Zm3-16a2 2 0 0 1 2 2v3h-1.5V6a.5.5 0 0 0-.5-.5h-3V4h3Z" />
|
|
249
|
+
</svg>
|
|
250
|
+
</button>';
|
|
243
251
|
|
|
244
252
|
$body_content = preg_replace( '/<img[^>]+>/', $button, $body_content );
|
|
245
253
|
|
|
@@ -312,12 +320,13 @@ function block_core_image_render_lightbox( $block_content, $block ) {
|
|
|
312
320
|
data-wp-on--touchmove="actions.core.image.handleTouchMove"
|
|
313
321
|
data-wp-on--touchend="actions.core.image.handleTouchEnd"
|
|
314
322
|
data-wp-on--click="actions.core.image.hideLightbox"
|
|
323
|
+
tabindex="-1"
|
|
315
324
|
>
|
|
316
325
|
<button type="button" aria-label="$close_button_label" style="fill: $close_button_color" class="close-button" data-wp-on--click="actions.core.image.hideLightbox">
|
|
317
326
|
$close_button_icon
|
|
318
327
|
</button>
|
|
319
328
|
<div class="lightbox-image-container">$initial_image_content</div>
|
|
320
|
-
|
|
329
|
+
<div class="lightbox-image-container">$enlarged_image_content</div>
|
|
321
330
|
<div class="scrim" style="background-color: $background_color" aria-hidden="true"></div>
|
|
322
331
|
</div>
|
|
323
332
|
HTML;
|
package/src/image/style.scss
CHANGED
|
@@ -157,14 +157,28 @@
|
|
|
157
157
|
display: flex;
|
|
158
158
|
flex-direction: column;
|
|
159
159
|
|
|
160
|
+
img {
|
|
161
|
+
cursor: zoom-in;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
img:hover + button {
|
|
165
|
+
opacity: 1;
|
|
166
|
+
}
|
|
167
|
+
|
|
160
168
|
button {
|
|
169
|
+
opacity: 0;
|
|
161
170
|
border: none;
|
|
162
|
-
background:
|
|
171
|
+
background: #000;
|
|
163
172
|
cursor: zoom-in;
|
|
164
|
-
width:
|
|
165
|
-
height:
|
|
173
|
+
width: 24px;
|
|
174
|
+
height: 24px;
|
|
166
175
|
position: absolute;
|
|
167
176
|
z-index: 100;
|
|
177
|
+
top: 10px;
|
|
178
|
+
right: 10px;
|
|
179
|
+
text-align: center;
|
|
180
|
+
padding: 0;
|
|
181
|
+
border-radius: 10%;
|
|
168
182
|
|
|
169
183
|
&:focus-visible {
|
|
170
184
|
outline: 5px auto #212121;
|
|
@@ -172,10 +186,19 @@
|
|
|
172
186
|
outline-offset: 5px;
|
|
173
187
|
}
|
|
174
188
|
|
|
189
|
+
&:hover {
|
|
190
|
+
cursor: pointer;
|
|
191
|
+
opacity: 1;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
&:focus {
|
|
195
|
+
opacity: 1;
|
|
196
|
+
}
|
|
197
|
+
|
|
175
198
|
&:hover,
|
|
176
199
|
&:focus,
|
|
177
200
|
&:not(:hover):not(:active):not(.has-background) {
|
|
178
|
-
background:
|
|
201
|
+
background: #000;
|
|
179
202
|
border: none;
|
|
180
203
|
}
|
|
181
204
|
}
|
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 ||
|
|
@@ -151,12 +149,15 @@ store(
|
|
|
151
149
|
'scroll',
|
|
152
150
|
scrollCallback
|
|
153
151
|
);
|
|
152
|
+
// If we don't delay before changing the focus,
|
|
153
|
+
// the focus ring will appear on Firefox before
|
|
154
|
+
// the image has finished animating, which looks broken.
|
|
155
|
+
context.core.image.lightboxTriggerRef.focus( {
|
|
156
|
+
preventScroll: true,
|
|
157
|
+
} );
|
|
154
158
|
}, 450 );
|
|
155
159
|
|
|
156
160
|
context.core.image.lightboxEnabled = false;
|
|
157
|
-
context.core.image.lastFocusedElement.focus( {
|
|
158
|
-
preventScroll: true,
|
|
159
|
-
} );
|
|
160
161
|
}
|
|
161
162
|
},
|
|
162
163
|
handleKeydown: ( { context, actions, event } ) => {
|
|
@@ -191,11 +192,12 @@ store(
|
|
|
191
192
|
}
|
|
192
193
|
}
|
|
193
194
|
},
|
|
194
|
-
|
|
195
|
+
// This is fired just by lazily loaded
|
|
196
|
+
// images on the page, not all images.
|
|
197
|
+
handleLoad: ( { context, effects, ref } ) => {
|
|
195
198
|
context.core.image.imageLoaded = true;
|
|
196
199
|
context.core.image.imageCurrentSrc = ref.currentSrc;
|
|
197
200
|
effects.core.image.setButtonStyles( {
|
|
198
|
-
state,
|
|
199
201
|
context,
|
|
200
202
|
ref,
|
|
201
203
|
} );
|
|
@@ -258,17 +260,18 @@ store(
|
|
|
258
260
|
effects: {
|
|
259
261
|
core: {
|
|
260
262
|
image: {
|
|
261
|
-
|
|
263
|
+
initOriginImage: ( { context, ref } ) => {
|
|
264
|
+
context.core.image.imageRef = ref;
|
|
265
|
+
context.core.image.lightboxTriggerRef =
|
|
266
|
+
ref.parentElement.querySelector(
|
|
267
|
+
'.lightbox-trigger'
|
|
268
|
+
);
|
|
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,11 @@ store(
|
|
|
279
282
|
focusableElements.length - 1
|
|
280
283
|
];
|
|
281
284
|
|
|
282
|
-
|
|
285
|
+
// Move focus to the dialog when opening it.
|
|
286
|
+
ref.focus();
|
|
283
287
|
}
|
|
284
288
|
},
|
|
285
|
-
setButtonStyles: ( {
|
|
289
|
+
setButtonStyles: ( { context, ref } ) => {
|
|
286
290
|
const {
|
|
287
291
|
naturalWidth,
|
|
288
292
|
naturalHeight,
|
|
@@ -291,54 +295,71 @@ store(
|
|
|
291
295
|
} = ref;
|
|
292
296
|
|
|
293
297
|
// If the image isn't loaded yet, we can't
|
|
294
|
-
// calculate
|
|
298
|
+
// calculate where the button should be.
|
|
295
299
|
if ( naturalWidth === 0 || naturalHeight === 0 ) {
|
|
296
300
|
return;
|
|
297
301
|
}
|
|
298
302
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
303
|
+
const figure = ref.parentElement;
|
|
304
|
+
const figureWidth = ref.parentElement.clientWidth;
|
|
305
|
+
|
|
306
|
+
// We need special handling for the height because
|
|
307
|
+
// a caption will cause the figure to be taller than
|
|
308
|
+
// the image, which means we need to account for that
|
|
309
|
+
// when calculating the placement of the button in the
|
|
310
|
+
// top right corner of the image.
|
|
311
|
+
let figureHeight = ref.parentElement.clientHeight;
|
|
312
|
+
const caption = figure.querySelector( 'figcaption' );
|
|
313
|
+
if ( caption ) {
|
|
314
|
+
const captionComputedStyle =
|
|
315
|
+
window.getComputedStyle( caption );
|
|
316
|
+
figureHeight =
|
|
317
|
+
figureHeight -
|
|
318
|
+
caption.offsetHeight -
|
|
319
|
+
parseFloat( captionComputedStyle.marginTop ) -
|
|
320
|
+
parseFloat( captionComputedStyle.marginBottom );
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
const buttonOffsetTop = figureHeight - offsetHeight;
|
|
324
|
+
const buttonOffsetRight = figureWidth - offsetWidth;
|
|
309
325
|
|
|
326
|
+
// In the case of an image with object-fit: contain, the
|
|
327
|
+
// size of the <img> element can be larger than the image itself,
|
|
328
|
+
// so we need to calculate where to place the button.
|
|
329
|
+
if ( context.core.image.scaleAttr === 'contain' ) {
|
|
310
330
|
// Natural ratio of the image.
|
|
311
331
|
const naturalRatio = naturalWidth / naturalHeight;
|
|
312
332
|
// Offset ratio of the image.
|
|
313
333
|
const offsetRatio = offsetWidth / offsetHeight;
|
|
314
334
|
|
|
315
|
-
if ( naturalRatio
|
|
335
|
+
if ( naturalRatio >= offsetRatio ) {
|
|
316
336
|
// If it reaches the width first, keep
|
|
317
|
-
// the width and
|
|
318
|
-
|
|
319
|
-
offsetWidth;
|
|
320
|
-
const buttonHeight = offsetWidth / naturalRatio;
|
|
321
|
-
context.core.image.imageButtonHeight =
|
|
322
|
-
buttonHeight;
|
|
337
|
+
// the width and compute the height.
|
|
338
|
+
const referenceHeight =
|
|
339
|
+
offsetWidth / naturalRatio;
|
|
323
340
|
context.core.image.imageButtonTop =
|
|
324
|
-
( offsetHeight -
|
|
341
|
+
( offsetHeight - referenceHeight ) / 2 +
|
|
342
|
+
buttonOffsetTop +
|
|
343
|
+
10;
|
|
344
|
+
context.core.image.imageButtonRight =
|
|
345
|
+
buttonOffsetRight + 10;
|
|
325
346
|
} else {
|
|
326
347
|
// If it reaches the height first, keep
|
|
327
|
-
// the height and
|
|
328
|
-
|
|
329
|
-
offsetHeight;
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
348
|
+
// the height and compute the width.
|
|
349
|
+
const referenceWidth =
|
|
350
|
+
offsetHeight * naturalRatio;
|
|
351
|
+
context.core.image.imageButtonTop =
|
|
352
|
+
buttonOffsetTop + 10;
|
|
353
|
+
context.core.image.imageButtonRight =
|
|
354
|
+
( offsetWidth - referenceWidth ) / 2 +
|
|
355
|
+
buttonOffsetRight +
|
|
356
|
+
10;
|
|
335
357
|
}
|
|
336
358
|
} else {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
context.core.image.imageButtonHeight = offsetHeight;
|
|
359
|
+
context.core.image.imageButtonTop =
|
|
360
|
+
buttonOffsetTop + 10;
|
|
361
|
+
context.core.image.imageButtonRight =
|
|
362
|
+
buttonOffsetRight + 10;
|
|
342
363
|
}
|
|
343
364
|
},
|
|
344
365
|
setStylesOnResize: ( { state, context, ref } ) => {
|
package/src/navigation/index.php
CHANGED
|
@@ -90,6 +90,13 @@ function block_core_navigation_add_directives_to_submenu( $w, $block_attributes
|
|
|
90
90
|
$w->set_attribute( 'data-wp-effect', 'effects.core.navigation.initMenu' );
|
|
91
91
|
$w->set_attribute( 'data-wp-on--focusout', 'actions.core.navigation.handleMenuFocusout' );
|
|
92
92
|
$w->set_attribute( 'data-wp-on--keydown', 'actions.core.navigation.handleMenuKeydown' );
|
|
93
|
+
|
|
94
|
+
// This is a fix for Safari. Without it, Safari doesn't change the active
|
|
95
|
+
// element when the user clicks on a button. It can be removed once we add
|
|
96
|
+
// an overlay to capture the clicks, instead of relying on the focusout
|
|
97
|
+
// event.
|
|
98
|
+
$w->set_attribute( 'tabindex', '-1' );
|
|
99
|
+
|
|
93
100
|
if ( ! isset( $block_attributes['openSubmenusOnClick'] ) || false === $block_attributes['openSubmenusOnClick'] ) {
|
|
94
101
|
$w->set_attribute( 'data-wp-on--mouseenter', 'actions.core.navigation.openMenuOnHover' );
|
|
95
102
|
$w->set_attribute( 'data-wp-on--mouseleave', 'actions.core.navigation.closeMenuOnHover' );
|
package/src/navigation/view.js
CHANGED
|
@@ -13,10 +13,14 @@ const focusableSelectors = [
|
|
|
13
13
|
'[tabindex]:not([tabindex^="-"])',
|
|
14
14
|
];
|
|
15
15
|
|
|
16
|
+
// This is a fix for Safari in iOS/iPadOS. Without it, Safari doesn't focus out
|
|
17
|
+
// when the user taps in the body. It can be removed once we add an overlay to
|
|
18
|
+
// capture the clicks, instead of relying on the focusout event.
|
|
19
|
+
document.addEventListener( 'click', () => {} );
|
|
20
|
+
|
|
16
21
|
const openMenu = ( store, menuOpenedOn ) => {
|
|
17
|
-
const { context,
|
|
22
|
+
const { context, selectors } = store;
|
|
18
23
|
selectors.core.navigation.menuOpenedBy( store )[ menuOpenedOn ] = true;
|
|
19
|
-
context.core.navigation.previousFocus = ref;
|
|
20
24
|
if ( context.core.navigation.type === 'overlay' ) {
|
|
21
25
|
// Add a `has-modal-open` class to the <html> root.
|
|
22
26
|
document.documentElement.classList.add( 'has-modal-open' );
|
|
@@ -33,7 +37,7 @@ const closeMenu = ( store, menuClosedOn ) => {
|
|
|
33
37
|
window.document.activeElement
|
|
34
38
|
)
|
|
35
39
|
) {
|
|
36
|
-
context.core.navigation.previousFocus
|
|
40
|
+
context.core.navigation.previousFocus?.focus();
|
|
37
41
|
}
|
|
38
42
|
context.core.navigation.modal = null;
|
|
39
43
|
context.core.navigation.previousFocus = null;
|
|
@@ -130,6 +134,8 @@ wpStore( {
|
|
|
130
134
|
closeMenu( store, 'hover' );
|
|
131
135
|
},
|
|
132
136
|
openMenuOnClick( store ) {
|
|
137
|
+
const { context, ref } = store;
|
|
138
|
+
context.core.navigation.previousFocus = ref;
|
|
133
139
|
openMenu( store, 'click' );
|
|
134
140
|
},
|
|
135
141
|
closeMenuOnClick( store ) {
|
|
@@ -140,13 +146,16 @@ wpStore( {
|
|
|
140
146
|
openMenu( store, 'focus' );
|
|
141
147
|
},
|
|
142
148
|
toggleMenuOnClick: ( store ) => {
|
|
143
|
-
const { selectors } = store;
|
|
149
|
+
const { selectors, context, ref } = store;
|
|
150
|
+
// Safari won't send focus to the clicked element, so we need to manually place it: https://bugs.webkit.org/show_bug.cgi?id=22261
|
|
151
|
+
if ( window.document.activeElement !== ref ) ref.focus();
|
|
144
152
|
const menuOpenedBy =
|
|
145
153
|
selectors.core.navigation.menuOpenedBy( store );
|
|
146
154
|
if ( menuOpenedBy.click || menuOpenedBy.focus ) {
|
|
147
155
|
closeMenu( store, 'click' );
|
|
148
156
|
closeMenu( store, 'focus' );
|
|
149
157
|
} else {
|
|
158
|
+
context.core.navigation.previousFocus = ref;
|
|
150
159
|
openMenu( store, 'click' );
|
|
151
160
|
}
|
|
152
161
|
},
|
|
@@ -194,11 +203,14 @@ wpStore( {
|
|
|
194
203
|
// event.relatedTarget === The element receiving focus (if any)
|
|
195
204
|
// When focusout is outsite the document,
|
|
196
205
|
// `window.document.activeElement` doesn't change.
|
|
206
|
+
|
|
207
|
+
// The event.relatedTarget is null when something outside the navigation menu is clicked. This is only necessary for Safari.
|
|
197
208
|
if (
|
|
198
|
-
|
|
209
|
+
event.relatedTarget === null ||
|
|
210
|
+
( ! context.core.navigation.modal?.contains(
|
|
199
211
|
event.relatedTarget
|
|
200
212
|
) &&
|
|
201
|
-
|
|
213
|
+
event.target !== window.document.activeElement )
|
|
202
214
|
) {
|
|
203
215
|
closeMenu( store, 'click' );
|
|
204
216
|
closeMenu( store, 'focus' );
|