@wordpress/block-library 8.28.8 → 8.28.10

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/block-library",
3
- "version": "8.28.8",
3
+ "version": "8.28.10",
4
4
  "description": "Block library for the WordPress editor.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -35,11 +35,11 @@
35
35
  "@wordpress/api-fetch": "^6.48.1",
36
36
  "@wordpress/autop": "^3.51.1",
37
37
  "@wordpress/blob": "^3.51.1",
38
- "@wordpress/block-editor": "^12.19.6",
38
+ "@wordpress/block-editor": "^12.19.8",
39
39
  "@wordpress/blocks": "^12.28.6",
40
- "@wordpress/components": "^26.0.5",
40
+ "@wordpress/components": "^26.0.6",
41
41
  "@wordpress/compose": "^6.28.1",
42
- "@wordpress/core-data": "^6.28.6",
42
+ "@wordpress/core-data": "^6.28.8",
43
43
  "@wordpress/data": "^9.21.1",
44
44
  "@wordpress/date": "^4.51.1",
45
45
  "@wordpress/deprecated": "^3.51.1",
@@ -54,12 +54,12 @@
54
54
  "@wordpress/interactivity-router": "^1.1.5",
55
55
  "@wordpress/keycodes": "^3.51.1",
56
56
  "@wordpress/notices": "^4.19.1",
57
- "@wordpress/patterns": "^1.12.6",
57
+ "@wordpress/patterns": "^1.12.8",
58
58
  "@wordpress/primitives": "^3.49.1",
59
59
  "@wordpress/private-apis": "^0.33.1",
60
- "@wordpress/reusable-blocks": "^4.28.6",
60
+ "@wordpress/reusable-blocks": "^4.28.8",
61
61
  "@wordpress/rich-text": "^6.28.4",
62
- "@wordpress/server-side-render": "^4.28.6",
62
+ "@wordpress/server-side-render": "^4.28.7",
63
63
  "@wordpress/url": "^3.52.1",
64
64
  "@wordpress/viewport": "^5.28.1",
65
65
  "@wordpress/wordcount": "^3.51.1",
@@ -80,5 +80,5 @@
80
80
  "publishConfig": {
81
81
  "access": "public"
82
82
  },
83
- "gitHead": "f8226c028ffa05f4e863c3346e46058ad09431e8"
83
+ "gitHead": "be077ee679b7b319a1d9eed46a74ffcbc5ad0b93"
84
84
  }
@@ -49,7 +49,7 @@ function render_block_core_avatar( $attributes, $content, $block ) {
49
49
  $label = '';
50
50
  if ( '_blank' === $attributes['linkTarget'] ) {
51
51
  // translators: %s is the Author name.
52
- $label = 'aria-label="' . sprintf( esc_attr__( '(%s author archive, opens in a new tab)' ), $author_name ) . '"';
52
+ $label = 'aria-label="' . esc_attr( sprintf( __( '(%s author archive, opens in a new tab)' ), $author_name ) ) . '"';
53
53
  }
54
54
  // translators: %1$s: Author archive link. %2$s: Link target. %3$s Aria label. %4$s Avatar image.
55
55
  $avatar_block = sprintf( '<a href="%1$s" target="%2$s" %3$s class="wp-block-avatar__link">%4$s</a>', esc_url( get_author_posts_url( $author_id ) ), esc_attr( $attributes['linkTarget'] ), $label, $avatar_block );
@@ -76,7 +76,7 @@ function render_block_core_avatar( $attributes, $content, $block ) {
76
76
  $label = '';
77
77
  if ( '_blank' === $attributes['linkTarget'] ) {
78
78
  // translators: %s is the Comment Author name.
79
- $label = 'aria-label="' . sprintf( esc_attr__( '(%s website link, opens in a new tab)' ), $comment->comment_author ) . '"';
79
+ $label = 'aria-label="' . esc_attr( sprintf( __( '(%s website link, opens in a new tab)' ), $comment->comment_author ) ) . '"';
80
80
  }
81
81
  // translators: %1$s: Comment Author website link. %2$s: Link target. %3$s Aria label. %4$s Avatar image.
82
82
  $avatar_block = sprintf( '<a href="%1$s" target="%2$s" %3$s class="wp-block-avatar__link">%4$s</a>', esc_url( $comment->comment_author_url ), esc_attr( $attributes['linkTarget'] ), $label, $avatar_block );
package/src/block/edit.js CHANGED
@@ -229,7 +229,36 @@ function setBlockEditMode( setEditMode, blocks, mode ) {
229
229
  } );
230
230
  }
231
231
 
232
- export default function ReusableBlockEdit( {
232
+ function RecursionWarning() {
233
+ const blockProps = useBlockProps();
234
+ return (
235
+ <div { ...blockProps }>
236
+ <Warning>
237
+ { __( 'Block cannot be rendered inside itself.' ) }
238
+ </Warning>
239
+ </div>
240
+ );
241
+ }
242
+
243
+ // Wrap the main Edit function for the pattern block with a recursion wrapper
244
+ // that allows short-circuiting rendering as early as possible, before any
245
+ // of the other effects in the block edit have run.
246
+ export default function ReusableBlockEditRecursionWrapper( props ) {
247
+ const { ref } = props.attributes;
248
+ const hasAlreadyRendered = useHasRecursion( ref );
249
+
250
+ if ( hasAlreadyRendered ) {
251
+ return <RecursionWarning />;
252
+ }
253
+
254
+ return (
255
+ <RecursionProvider uniqueId={ ref }>
256
+ <ReusableBlockEdit { ...props } />
257
+ </RecursionProvider>
258
+ );
259
+ }
260
+
261
+ function ReusableBlockEdit( {
233
262
  name,
234
263
  attributes: { ref, content },
235
264
  __unstableParentLayout: parentLayout,
@@ -237,7 +266,6 @@ export default function ReusableBlockEdit( {
237
266
  setAttributes,
238
267
  } ) {
239
268
  const registry = useRegistry();
240
- const hasAlreadyRendered = useHasRecursion( ref );
241
269
  const { record, editedRecord, hasResolved } = useEntityRecord(
242
270
  'postType',
243
271
  'wp_block',
@@ -434,14 +462,6 @@ export default function ReusableBlockEdit( {
434
462
 
435
463
  let children = null;
436
464
 
437
- if ( hasAlreadyRendered ) {
438
- children = (
439
- <Warning>
440
- { __( 'Block cannot be rendered inside itself.' ) }
441
- </Warning>
442
- );
443
- }
444
-
445
465
  if ( isMissing ) {
446
466
  children = (
447
467
  <Warning>
@@ -459,7 +479,7 @@ export default function ReusableBlockEdit( {
459
479
  }
460
480
 
461
481
  return (
462
- <RecursionProvider uniqueId={ ref }>
482
+ <>
463
483
  { userCanEdit && onNavigateToEntityRecord && (
464
484
  <BlockControls>
465
485
  <ToolbarGroup>
@@ -489,6 +509,6 @@ export default function ReusableBlockEdit( {
489
509
  ) : (
490
510
  <div { ...blockProps }>{ children }</div>
491
511
  ) }
492
- </RecursionProvider>
512
+ </>
493
513
  );
494
514
  }
@@ -274,6 +274,22 @@ export default function Image( {
274
274
  }
275
275
  }
276
276
 
277
+ function resetLightbox() {
278
+ // When deleting a link from an image while lightbox settings
279
+ // are enabled by default, we should disable the lightbox,
280
+ // otherwise the resulting UX looks like a mistake.
281
+ // See https://github.com/WordPress/gutenberg/pull/59890/files#r1532286123.
282
+ if ( lightboxSetting?.enabled && lightboxSetting?.allowEditing ) {
283
+ setAttributes( {
284
+ lightbox: { enabled: false },
285
+ } );
286
+ } else {
287
+ setAttributes( {
288
+ lightbox: undefined,
289
+ } );
290
+ }
291
+ }
292
+
277
293
  function onSetTitle( value ) {
278
294
  // This is the HTML title attribute, separate from the media object
279
295
  // title.
@@ -348,7 +364,10 @@ export default function Image( {
348
364
  const [ lightboxSetting ] = useSettings( 'lightbox' );
349
365
 
350
366
  const showLightboxSetting =
351
- !! lightbox || lightboxSetting?.allowEditing === true;
367
+ // If a block-level override is set, we should give users the option to
368
+ // remove that override, even if the lightbox UI is disabled in the settings.
369
+ ( !! lightbox && lightbox?.enabled !== lightboxSetting?.enabled ) ||
370
+ lightboxSetting?.allowEditing;
352
371
 
353
372
  const lightboxChecked =
354
373
  !! lightbox?.enabled || ( ! lightbox && !! lightboxSetting?.enabled );
@@ -498,6 +517,7 @@ export default function Image( {
498
517
  showLightboxSetting={ showLightboxSetting }
499
518
  lightboxEnabled={ lightboxChecked }
500
519
  onSetLightbox={ onSetLightbox }
520
+ resetLightbox={ resetLightbox }
501
521
  />
502
522
  ) }
503
523
  { allowCrop && (
@@ -1472,6 +1472,14 @@ function block_core_navigation_update_ignore_hooked_blocks_meta( $post ) {
1472
1472
  return $post;
1473
1473
  }
1474
1474
 
1475
+ /**
1476
+ * Skip meta generation when consumers intentionally update specific Navigation fields
1477
+ * and omit the content update.
1478
+ */
1479
+ if ( ! isset( $post->post_content ) ) {
1480
+ return $post;
1481
+ }
1482
+
1475
1483
  /*
1476
1484
  * We run the Block Hooks mechanism to inject the `metadata.ignoredHookedBlocks` attribute into
1477
1485
  * all anchor blocks. For the root level, we create a mock Navigation and extract them from there.
@@ -62,11 +62,20 @@ const { state, actions } = store(
62
62
  // Only open on hover if the overlay is closed.
63
63
  Object.values( overlayOpenedBy || {} ).filter( Boolean )
64
64
  .length === 0
65
- )
65
+ ) {
66
66
  actions.openMenu( 'hover' );
67
+ }
67
68
  },
68
69
  closeMenuOnHover() {
69
- actions.closeMenu( 'hover' );
70
+ const { type, overlayOpenedBy } = getContext();
71
+ if (
72
+ type === 'submenu' &&
73
+ // Only close on hover if the overlay is closed.
74
+ Object.values( overlayOpenedBy || {} ).filter( Boolean )
75
+ .length === 0
76
+ ) {
77
+ actions.closeMenu( 'hover' );
78
+ }
70
79
  },
71
80
  openMenuOnClick() {
72
81
  const ctx = getContext();
@@ -128,7 +137,7 @@ const { state, actions } = store(
128
137
  }
129
138
  },
130
139
  handleMenuFocusout( event ) {
131
- const { modal } = getContext();
140
+ const { modal, type } = getContext();
132
141
  // If focus is outside modal, and in the document, close menu
133
142
  // event.target === The element losing focus
134
143
  // event.relatedTarget === The element receiving focus (if any)
@@ -139,7 +148,8 @@ const { state, actions } = store(
139
148
  if (
140
149
  event.relatedTarget === null ||
141
150
  ( ! modal?.contains( event.relatedTarget ) &&
142
- event.target !== window.document.activeElement )
151
+ event.target !== window.document.activeElement &&
152
+ type === 'submenu' )
143
153
  ) {
144
154
  actions.closeMenu( 'click' );
145
155
  actions.closeMenu( 'focus' );
@@ -43,7 +43,7 @@ export default function EnhancedPaginationModal( {
43
43
  if ( hasBlocksFromPlugins ) {
44
44
  notice =
45
45
  __(
46
- 'Currently, avoiding full page reloads is not possible when blocks from plugins are present inside the Query block.'
46
+ 'Currently, avoiding full page reloads is not possible when non-interactive or non-clientNavigation compatible blocks from plugins are present inside the Query block.'
47
47
  ) +
48
48
  ' ' +
49
49
  notice;
@@ -6,7 +6,11 @@ import { useMemo } from '@wordpress/element';
6
6
  import { store as coreStore } from '@wordpress/core-data';
7
7
  import { store as blockEditorStore } from '@wordpress/block-editor';
8
8
  import { decodeEntities } from '@wordpress/html-entities';
9
- import { cloneBlock, store as blocksStore } from '@wordpress/blocks';
9
+ import {
10
+ cloneBlock,
11
+ getBlockSupport,
12
+ store as blocksStore,
13
+ } from '@wordpress/blocks';
10
14
 
11
15
  /** @typedef {import('@wordpress/blocks').WPBlockVariation} WPBlockVariation */
12
16
 
@@ -373,7 +377,24 @@ export const useUnsupportedBlocks = ( clientId ) => {
373
377
  getClientIdsOfDescendants( clientId ).forEach(
374
378
  ( descendantClientId ) => {
375
379
  const blockName = getBlockName( descendantClientId );
376
- if ( ! blockName.startsWith( 'core/' ) ) {
380
+ /*
381
+ * Client side navigation can be true in two states:
382
+ * - supports.interactivity = true;
383
+ * - supports.interactivity.clientNavigation = true;
384
+ */
385
+ const blockSupportsInteractivity = Object.is(
386
+ getBlockSupport( blockName, 'interactivity' ),
387
+ true
388
+ );
389
+ const blockSupportsInteractivityClientNavigation =
390
+ getBlockSupport(
391
+ blockName,
392
+ 'interactivity.clientNavigation'
393
+ );
394
+ const blockInteractivity =
395
+ blockSupportsInteractivity ||
396
+ blockSupportsInteractivityClientNavigation;
397
+ if ( ! blockInteractivity ) {
377
398
  blocks.hasBlocksFromPlugins = true;
378
399
  } else if ( blockName === 'core/post-content' ) {
379
400
  blocks.hasPostContentBlock = true;