@wordpress/block-library 9.37.2-next.79a2f3cdd.0 → 9.37.2-next.ba3aee3a2.0
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/CHANGELOG.md +1 -1
- package/build/code/transforms.cjs +1 -1
- package/build/code/transforms.cjs.map +1 -1
- package/build/image/block.json +3 -0
- package/build/image/image.cjs +42 -4
- package/build/image/image.cjs.map +2 -2
- package/build/image/save.cjs +3 -0
- package/build/image/save.cjs.map +2 -2
- package/build/image/utils.cjs +5 -0
- package/build/image/utils.cjs.map +2 -2
- package/build/navigation/constants.cjs +3 -0
- package/build/navigation/constants.cjs.map +2 -2
- package/build/navigation/edit/overlay-template-part-selector.cjs +2 -1
- package/build/navigation/edit/overlay-template-part-selector.cjs.map +2 -2
- package/build/navigation/edit/use-create-overlay.cjs +2 -1
- package/build/navigation/edit/use-create-overlay.cjs.map +2 -2
- package/build/navigation/view.cjs +14 -2
- package/build/navigation/view.cjs.map +2 -2
- package/build/private-apis.cjs +3 -1
- package/build/private-apis.cjs.map +2 -2
- package/build/quote/transforms.cjs +30 -6
- package/build/quote/transforms.cjs.map +2 -2
- package/build/separator/transforms.cjs +5 -2
- package/build/separator/transforms.cjs.map +2 -2
- package/build/template-part/edit/index.cjs +9 -2
- package/build/template-part/edit/index.cjs.map +2 -2
- package/build-module/code/transforms.mjs +1 -1
- package/build-module/code/transforms.mjs.map +1 -1
- package/build-module/image/block.json +3 -0
- package/build-module/image/image.mjs +44 -5
- package/build-module/image/image.mjs.map +2 -2
- package/build-module/image/save.mjs +3 -0
- package/build-module/image/save.mjs.map +2 -2
- package/build-module/image/utils.mjs +4 -0
- package/build-module/image/utils.mjs.map +2 -2
- package/build-module/navigation/constants.mjs +2 -0
- package/build-module/navigation/constants.mjs.map +2 -2
- package/build-module/navigation/edit/overlay-template-part-selector.mjs +2 -1
- package/build-module/navigation/edit/overlay-template-part-selector.mjs.map +2 -2
- package/build-module/navigation/edit/use-create-overlay.mjs +2 -1
- package/build-module/navigation/edit/use-create-overlay.mjs.map +2 -2
- package/build-module/navigation/view.mjs +14 -2
- package/build-module/navigation/view.mjs.map +2 -2
- package/build-module/private-apis.mjs +3 -1
- package/build-module/private-apis.mjs.map +2 -2
- package/build-module/quote/transforms.mjs +30 -6
- package/build-module/quote/transforms.mjs.map +2 -2
- package/build-module/separator/transforms.mjs +6 -3
- package/build-module/separator/transforms.mjs.map +2 -2
- package/build-module/template-part/edit/index.mjs +9 -2
- package/build-module/template-part/edit/index.mjs.map +2 -2
- package/build-style/navigation/style-rtl.css +25 -6
- package/build-style/navigation/style.css +25 -6
- package/build-style/navigation-overlay-close/style-rtl.css +0 -1
- package/build-style/navigation-overlay-close/style.css +0 -1
- package/build-style/style-rtl.css +25 -7
- package/build-style/style.css +25 -7
- package/package.json +37 -37
- package/src/code/transforms.js +1 -1
- package/src/image/block.json +3 -0
- package/src/image/image.js +43 -2
- package/src/image/save.js +10 -0
- package/src/image/utils.js +4 -0
- package/src/navigation/constants.js +9 -0
- package/src/navigation/edit/overlay-template-part-selector.js +3 -1
- package/src/navigation/edit/test/overlay-template-part-selector.js +3 -3
- package/src/navigation/edit/test/use-create-overlay.js +5 -5
- package/src/navigation/edit/use-create-overlay.js +2 -1
- package/src/navigation/index.php +271 -13
- package/src/navigation/style.scss +46 -9
- package/src/navigation/view.js +24 -4
- package/src/navigation-overlay-close/style.scss +0 -1
- package/src/private-apis.js +2 -0
- package/src/quote/transforms.js +31 -5
- package/src/separator/transforms.js +6 -3
- package/src/template-part/edit/index.js +21 -4
package/src/navigation/index.php
CHANGED
|
@@ -41,6 +41,18 @@ class WP_Navigation_Block_Renderer {
|
|
|
41
41
|
*/
|
|
42
42
|
private static $seen_menu_names = array();
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Returns whether the navigation overlay experiment is enabled.
|
|
46
|
+
*
|
|
47
|
+
* @since 6.5.0
|
|
48
|
+
*
|
|
49
|
+
* @return bool Returns whether the navigation overlay experiment is enabled.
|
|
50
|
+
*/
|
|
51
|
+
private static function is_overlay_experiment_enabled() {
|
|
52
|
+
$gutenberg_experiments = get_option( 'gutenberg-experiments' );
|
|
53
|
+
return $gutenberg_experiments && array_key_exists( 'gutenberg-customizable-navigation-overlays', $gutenberg_experiments );
|
|
54
|
+
}
|
|
55
|
+
|
|
44
56
|
/**
|
|
45
57
|
* Returns whether or not this is responsive navigation.
|
|
46
58
|
*
|
|
@@ -158,6 +170,22 @@ class WP_Navigation_Block_Renderer {
|
|
|
158
170
|
return $inner_block_content;
|
|
159
171
|
}
|
|
160
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Returns the html for blocks from a template part (without navigation container wrapper).
|
|
175
|
+
*
|
|
176
|
+
* @since 6.5.0
|
|
177
|
+
*
|
|
178
|
+
* @param WP_Block_List $blocks The list of blocks to render.
|
|
179
|
+
* @return string Returns the html for the template part blocks.
|
|
180
|
+
*/
|
|
181
|
+
private static function get_template_part_blocks_html( $blocks ) {
|
|
182
|
+
$html = '';
|
|
183
|
+
foreach ( $blocks as $block ) {
|
|
184
|
+
$html .= $block->render();
|
|
185
|
+
}
|
|
186
|
+
return $html;
|
|
187
|
+
}
|
|
188
|
+
|
|
161
189
|
/**
|
|
162
190
|
* Returns the html for the inner blocks of the navigation block.
|
|
163
191
|
*
|
|
@@ -272,6 +300,127 @@ class WP_Navigation_Block_Renderer {
|
|
|
272
300
|
return new WP_Block_List( $fallback_blocks, $attributes );
|
|
273
301
|
}
|
|
274
302
|
|
|
303
|
+
/**
|
|
304
|
+
* Recursively disables overlay menu for navigation blocks within overlay blocks.
|
|
305
|
+
* Prevents nested overlays (inception).
|
|
306
|
+
*
|
|
307
|
+
* @since 6.5.0
|
|
308
|
+
*
|
|
309
|
+
* @param array $blocks Array of parsed block arrays.
|
|
310
|
+
* @return array Modified blocks with overlayMenu set to 'never' for navigation blocks.
|
|
311
|
+
*/
|
|
312
|
+
private static function disable_overlay_menu_for_nested_navigation_blocks( $blocks ) {
|
|
313
|
+
if ( empty( $blocks ) || ! is_array( $blocks ) ) {
|
|
314
|
+
return $blocks;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
foreach ( $blocks as &$block ) {
|
|
318
|
+
if ( ! isset( $block['blockName'] ) ) {
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// If this is a navigation block, disable its overlay menu.
|
|
323
|
+
if ( 'core/navigation' === $block['blockName'] ) {
|
|
324
|
+
if ( ! isset( $block['attrs'] ) ) {
|
|
325
|
+
$block['attrs'] = array();
|
|
326
|
+
}
|
|
327
|
+
$block['attrs']['overlayMenu'] = 'never';
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Recursively process inner blocks.
|
|
331
|
+
if ( ! empty( $block['innerBlocks'] ) && is_array( $block['innerBlocks'] ) ) {
|
|
332
|
+
$block['innerBlocks'] = static::disable_overlay_menu_for_nested_navigation_blocks( $block['innerBlocks'] );
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return $blocks;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Gets the inner blocks for the navigation block from an overlay template part.
|
|
341
|
+
*
|
|
342
|
+
* @since 6.5.0
|
|
343
|
+
*
|
|
344
|
+
* @param string $overlay_template_part_id The overlay template part ID in format "theme//slug".
|
|
345
|
+
* @param array $attributes The block attributes.
|
|
346
|
+
* @return WP_Block_List Returns the inner blocks for the overlay template part.
|
|
347
|
+
*/
|
|
348
|
+
private static function get_overlay_blocks_from_template_part( $overlay_template_part_id, $attributes ) {
|
|
349
|
+
if ( empty( $overlay_template_part_id ) || ! is_string( $overlay_template_part_id ) ) {
|
|
350
|
+
return new WP_Block_List( array(), $attributes );
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Parse the template part ID (format: "theme//slug").
|
|
354
|
+
$parts = explode( '//', $overlay_template_part_id, 2 );
|
|
355
|
+
if ( count( $parts ) !== 2 ) {
|
|
356
|
+
return new WP_Block_List( array(), $attributes );
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
$theme = $parts[0];
|
|
360
|
+
$slug = $parts[1];
|
|
361
|
+
|
|
362
|
+
// Only query for template parts from the active theme.
|
|
363
|
+
if ( get_stylesheet() !== $theme ) {
|
|
364
|
+
return new WP_Block_List( array(), $attributes );
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Query for the template part post.
|
|
368
|
+
$template_part_query = new WP_Query(
|
|
369
|
+
array(
|
|
370
|
+
'post_type' => 'wp_template_part',
|
|
371
|
+
'post_status' => 'publish',
|
|
372
|
+
'post_name__in' => array( $slug ),
|
|
373
|
+
'tax_query' => array(
|
|
374
|
+
array(
|
|
375
|
+
'taxonomy' => 'wp_theme',
|
|
376
|
+
'field' => 'name',
|
|
377
|
+
'terms' => $theme,
|
|
378
|
+
),
|
|
379
|
+
),
|
|
380
|
+
'posts_per_page' => 1,
|
|
381
|
+
'no_found_rows' => true,
|
|
382
|
+
'lazy_load_term_meta' => false, // Do not lazy load term meta, as template parts only have one term.
|
|
383
|
+
)
|
|
384
|
+
);
|
|
385
|
+
|
|
386
|
+
$template_part_post = $template_part_query->have_posts() ? $template_part_query->next_post() : null;
|
|
387
|
+
|
|
388
|
+
if ( ! $template_part_post ) {
|
|
389
|
+
// Try to get from theme file if not in database.
|
|
390
|
+
$block_template = get_block_file_template( $overlay_template_part_id, 'wp_template_part' );
|
|
391
|
+
if ( isset( $block_template->content ) ) {
|
|
392
|
+
$parsed_blocks = parse_blocks( $block_template->content );
|
|
393
|
+
$blocks = block_core_navigation_filter_out_empty_blocks( $parsed_blocks );
|
|
394
|
+
// Disable overlay menu for any navigation blocks within the overlay to prevent nested overlays.
|
|
395
|
+
$blocks = static::disable_overlay_menu_for_nested_navigation_blocks( $blocks );
|
|
396
|
+
return new WP_Block_List( $blocks, $attributes );
|
|
397
|
+
}
|
|
398
|
+
return new WP_Block_List( array(), $attributes );
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Get the template part content.
|
|
402
|
+
$block_template = _build_block_template_result_from_post( $template_part_post );
|
|
403
|
+
if ( ! isset( $block_template->content ) ) {
|
|
404
|
+
return new WP_Block_List( array(), $attributes );
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
$parsed_blocks = parse_blocks( $block_template->content );
|
|
408
|
+
|
|
409
|
+
// 'parse_blocks' includes a null block with '\n\n' as the content when
|
|
410
|
+
// it encounters whitespace. This code strips it.
|
|
411
|
+
$blocks = block_core_navigation_filter_out_empty_blocks( $parsed_blocks );
|
|
412
|
+
|
|
413
|
+
// Re-serialize, and run Block Hooks algorithm to inject hooked blocks.
|
|
414
|
+
$markup = serialize_blocks( $blocks );
|
|
415
|
+
$markup = apply_block_hooks_to_content_from_post_object( $markup, $template_part_post );
|
|
416
|
+
$blocks = parse_blocks( $markup );
|
|
417
|
+
|
|
418
|
+
// Disable overlay menu for any navigation blocks within the overlay to prevent nested overlays.
|
|
419
|
+
$blocks = static::disable_overlay_menu_for_nested_navigation_blocks( $blocks );
|
|
420
|
+
|
|
421
|
+
return new WP_Block_List( $blocks, $attributes );
|
|
422
|
+
}
|
|
423
|
+
|
|
275
424
|
/**
|
|
276
425
|
* Gets the inner blocks for the navigation block.
|
|
277
426
|
*
|
|
@@ -467,9 +616,44 @@ class WP_Navigation_Block_Renderer {
|
|
|
467
616
|
|
|
468
617
|
$is_hidden_by_default = isset( $attributes['overlayMenu'] ) && 'always' === $attributes['overlayMenu'];
|
|
469
618
|
|
|
619
|
+
// Set-up variables for the custom overlay experiment.
|
|
620
|
+
// Values are set to "off" so they don't affect the default behavior.
|
|
621
|
+
$is_overlay_experiment_enabled = static::is_overlay_experiment_enabled();
|
|
622
|
+
$has_custom_overlay = false;
|
|
623
|
+
$close_button_markup = '';
|
|
624
|
+
$has_custom_overlay_close_block = false;
|
|
625
|
+
$overlay_blocks_html = '';
|
|
626
|
+
$custom_overlay_markup = '';
|
|
627
|
+
|
|
628
|
+
if ( $is_overlay_experiment_enabled ) {
|
|
629
|
+
// Check if an overlay template part is selected and render it.
|
|
630
|
+
// This needs to happen before building classes so we know if overlay blocks actually exist.
|
|
631
|
+
if ( ! empty( $attributes['overlay'] ) ) {
|
|
632
|
+
// Get blocks from the overlay template part.
|
|
633
|
+
$overlay_blocks = static::get_overlay_blocks_from_template_part( $attributes['overlay'], $attributes );
|
|
634
|
+
// Check if overlay contains a navigation-overlay-close block.
|
|
635
|
+
$has_custom_overlay_close_block = block_core_navigation_block_tree_has_block_type(
|
|
636
|
+
$overlay_blocks,
|
|
637
|
+
'core/navigation-overlay-close',
|
|
638
|
+
array( 'core/navigation' ) // Skip navigation blocks, as they cannot contain an overlay close block
|
|
639
|
+
);
|
|
640
|
+
// Render template part blocks directly without navigation container wrapper.
|
|
641
|
+
$overlay_blocks_html = static::get_template_part_blocks_html( $overlay_blocks );
|
|
642
|
+
// Add Interactivity API directives to the overlay close block if present.
|
|
643
|
+
if ( $has_custom_overlay_close_block && $is_interactive ) {
|
|
644
|
+
$tags = new WP_HTML_Tag_Processor( $overlay_blocks_html );
|
|
645
|
+
$overlay_blocks_html = block_core_navigation_add_directives_to_overlay_close( $tags );
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
$has_custom_overlay = ! empty( $overlay_blocks_html );
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// Only add the disable-default-overlay class if experiment is enabled AND overlay blocks actually rendered.
|
|
470
653
|
$responsive_container_classes = array(
|
|
471
654
|
'wp-block-navigation__responsive-container',
|
|
472
655
|
$is_hidden_by_default ? 'hidden-by-default' : '',
|
|
656
|
+
$has_custom_overlay ? 'disable-default-overlay' : '',
|
|
473
657
|
implode( ' ', $colors['overlay_css_classes'] ),
|
|
474
658
|
);
|
|
475
659
|
$open_button_classes = array(
|
|
@@ -523,14 +707,33 @@ class WP_Navigation_Block_Renderer {
|
|
|
523
707
|
|
|
524
708
|
$overlay_inline_styles = esc_attr( safecss_filter_attr( $colors['overlay_inline_styles'] ) );
|
|
525
709
|
|
|
710
|
+
if ( $has_custom_overlay ) {
|
|
711
|
+
$custom_overlay_markup = sprintf(
|
|
712
|
+
'<div class="wp-block-navigation__overlay-container">%s</div>',
|
|
713
|
+
$overlay_blocks_html
|
|
714
|
+
);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
// Show default close button for all responsive navigation,
|
|
718
|
+
// unless custom overlay has its own close block.
|
|
719
|
+
if ( ! $has_custom_overlay_close_block ) {
|
|
720
|
+
$close_button_markup = sprintf(
|
|
721
|
+
'<button %1$s class="wp-block-navigation__responsive-container-close" %2$s>%3$s</button>',
|
|
722
|
+
$toggle_aria_label_close,
|
|
723
|
+
$close_button_directives,
|
|
724
|
+
$toggle_close_button_content
|
|
725
|
+
);
|
|
726
|
+
}
|
|
727
|
+
|
|
526
728
|
return sprintf(
|
|
527
729
|
'<button aria-haspopup="dialog" %3$s class="%6$s" %10$s>%8$s</button>
|
|
528
730
|
<div class="%5$s" %7$s id="%1$s" %11$s>
|
|
529
731
|
<div class="wp-block-navigation__responsive-close" tabindex="-1">
|
|
530
732
|
<div class="wp-block-navigation__responsive-dialog" %12$s>
|
|
531
|
-
|
|
733
|
+
%13$s
|
|
532
734
|
<div class="wp-block-navigation__responsive-container-content" %14$s id="%1$s-content">
|
|
533
735
|
%2$s
|
|
736
|
+
%15$s
|
|
534
737
|
</div>
|
|
535
738
|
</div>
|
|
536
739
|
</div>
|
|
@@ -547,8 +750,9 @@ class WP_Navigation_Block_Renderer {
|
|
|
547
750
|
$open_button_directives,
|
|
548
751
|
$responsive_container_directives,
|
|
549
752
|
$responsive_dialog_directives,
|
|
550
|
-
$
|
|
551
|
-
$responsive_container_content_directives
|
|
753
|
+
$close_button_markup,
|
|
754
|
+
$responsive_container_content_directives,
|
|
755
|
+
$has_custom_overlay ? $custom_overlay_markup : ''
|
|
552
756
|
);
|
|
553
757
|
}
|
|
554
758
|
|
|
@@ -699,7 +903,10 @@ class WP_Navigation_Block_Renderer {
|
|
|
699
903
|
|
|
700
904
|
$inner_blocks = static::get_inner_blocks( $attributes, $block );
|
|
701
905
|
// Prevent navigation blocks referencing themselves from rendering.
|
|
702
|
-
if (
|
|
906
|
+
if ( block_core_navigation_block_tree_has_block_type(
|
|
907
|
+
$inner_blocks,
|
|
908
|
+
'core/navigation'
|
|
909
|
+
) ) {
|
|
703
910
|
return '';
|
|
704
911
|
}
|
|
705
912
|
|
|
@@ -798,6 +1005,29 @@ if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
|
|
|
798
1005
|
}
|
|
799
1006
|
}
|
|
800
1007
|
|
|
1008
|
+
/**
|
|
1009
|
+
* Add Interactivity API directives to the navigation-overlay-close block
|
|
1010
|
+
* markup using the Tag Processor.
|
|
1011
|
+
*
|
|
1012
|
+
* @since 6.5.0
|
|
1013
|
+
*
|
|
1014
|
+
* @param WP_HTML_Tag_Processor $tags Markup of the navigation block.
|
|
1015
|
+
* @return string Overlay close markup with the directives injected.
|
|
1016
|
+
*/
|
|
1017
|
+
function block_core_navigation_add_directives_to_overlay_close( $tags ) {
|
|
1018
|
+
// Find the navigation-overlay-close button.
|
|
1019
|
+
if ( $tags->next_tag(
|
|
1020
|
+
array(
|
|
1021
|
+
'tag_name' => 'BUTTON',
|
|
1022
|
+
'class_name' => 'wp-block-navigation-overlay-close',
|
|
1023
|
+
)
|
|
1024
|
+
) ) {
|
|
1025
|
+
// Add the same close directive as the default close button.
|
|
1026
|
+
$tags->set_attribute( 'data-wp-on--click', 'actions.closeMenuOnClick' );
|
|
1027
|
+
}
|
|
1028
|
+
return $tags->get_updated_html();
|
|
1029
|
+
}
|
|
1030
|
+
|
|
801
1031
|
/**
|
|
802
1032
|
* Add Interactivity API directives to the navigation-submenu and page-list
|
|
803
1033
|
* blocks markup using the Tag Processor.
|
|
@@ -1020,26 +1250,54 @@ function block_core_navigation_filter_out_empty_blocks( $parsed_blocks ) {
|
|
|
1020
1250
|
}
|
|
1021
1251
|
|
|
1022
1252
|
/**
|
|
1023
|
-
*
|
|
1253
|
+
* Recursively checks if blocks contain a specific block type.
|
|
1024
1254
|
*
|
|
1025
|
-
* @since
|
|
1255
|
+
* @since 7.0.0
|
|
1026
1256
|
*
|
|
1027
|
-
* @param WP_Block_List $
|
|
1028
|
-
* @
|
|
1257
|
+
* @param WP_Block_List $blocks The list of blocks to check.
|
|
1258
|
+
* @param string $block_type The block type to search for (e.g., 'core/navigation').
|
|
1259
|
+
* @param array $skip_block_types Optional. Block types to skip when recursing. Default empty array.
|
|
1260
|
+
* @return bool Returns true if the specified block type is found.
|
|
1029
1261
|
*/
|
|
1030
|
-
function
|
|
1031
|
-
|
|
1032
|
-
|
|
1262
|
+
function block_core_navigation_block_tree_has_block_type( $blocks, $block_type, $skip_block_types = array() ) {
|
|
1263
|
+
if ( empty( $blocks ) ) {
|
|
1264
|
+
return false;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
foreach ( $blocks as $block ) {
|
|
1268
|
+
if ( $block_type === $block->name ) {
|
|
1033
1269
|
return true;
|
|
1034
1270
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1271
|
+
|
|
1272
|
+
// Recursively check inner blocks, skipping specified block types.
|
|
1273
|
+
if ( ! in_array( $block->name, $skip_block_types, true ) && ! empty( $block->inner_blocks ) ) {
|
|
1274
|
+
if ( block_core_navigation_block_tree_has_block_type( $block->inner_blocks, $block_type, $skip_block_types ) ) {
|
|
1275
|
+
return true;
|
|
1276
|
+
}
|
|
1037
1277
|
}
|
|
1038
1278
|
}
|
|
1039
1279
|
|
|
1040
1280
|
return false;
|
|
1041
1281
|
}
|
|
1042
1282
|
|
|
1283
|
+
/**
|
|
1284
|
+
* Returns true if the navigation block contains a nested navigation block.
|
|
1285
|
+
*
|
|
1286
|
+
* @since 6.2.0
|
|
1287
|
+
* @deprecated 7.0.0 Use block_core_navigation_block_tree_has_block_type() instead.
|
|
1288
|
+
*
|
|
1289
|
+
* @param WP_Block_List $inner_blocks Inner block instance to be normalized.
|
|
1290
|
+
* @return bool true if the navigation block contains a nested navigation block.
|
|
1291
|
+
*/
|
|
1292
|
+
function block_core_navigation_block_contains_core_navigation( $inner_blocks ) {
|
|
1293
|
+
_deprecated_function( __FUNCTION__, '7.0.0', 'block_core_navigation_block_tree_has_block_type()' );
|
|
1294
|
+
|
|
1295
|
+
return block_core_navigation_block_tree_has_block_type(
|
|
1296
|
+
$inner_blocks,
|
|
1297
|
+
'core/navigation'
|
|
1298
|
+
);
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1043
1301
|
/**
|
|
1044
1302
|
* Retrieves the appropriate fallback to be used on the front of the
|
|
1045
1303
|
* site when there is no menu assigned to the Nav block.
|
|
@@ -523,10 +523,13 @@ button.wp-block-navigation-item__content {
|
|
|
523
523
|
}
|
|
524
524
|
|
|
525
525
|
// Try to inherit any root paddings set, so the X can align to a top-right aligned menu.
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
526
|
+
// Don't apply default padding when custom overlay is present.
|
|
527
|
+
&:not(.disable-default-overlay) {
|
|
528
|
+
padding-top: clamp(1rem, var(--wp--style--root--padding-top), 20rem);
|
|
529
|
+
padding-right: clamp(1rem, var(--wp--style--root--padding-right), 20rem);
|
|
530
|
+
padding-bottom: clamp(1rem, var(--wp--style--root--padding-bottom), 20rem);
|
|
531
|
+
padding-left: clamp(1rem, var(--wp--style--root--padding-left), 20rem);
|
|
532
|
+
}
|
|
530
533
|
|
|
531
534
|
// Allow modal to scroll.
|
|
532
535
|
overflow: auto;
|
|
@@ -534,10 +537,13 @@ button.wp-block-navigation-item__content {
|
|
|
534
537
|
// Give it a z-index just higher than the adminbar.
|
|
535
538
|
z-index: 100000;
|
|
536
539
|
|
|
537
|
-
.
|
|
538
|
-
|
|
540
|
+
// Add padding above to accommodate close button.
|
|
541
|
+
// Don't apply default padding when custom overlay is present.
|
|
542
|
+
&:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content {
|
|
539
543
|
padding-top: calc(2rem + #{ $navigation-icon-size });
|
|
544
|
+
}
|
|
540
545
|
|
|
546
|
+
.wp-block-navigation__responsive-container-content {
|
|
541
547
|
// Don't crop the focus style.
|
|
542
548
|
overflow: visible;
|
|
543
549
|
|
|
@@ -623,6 +629,29 @@ button.wp-block-navigation-item__content {
|
|
|
623
629
|
}
|
|
624
630
|
}
|
|
625
631
|
|
|
632
|
+
// Custom overlay container visibility.
|
|
633
|
+
// When there's a custom overlay, by default hide overlay container.
|
|
634
|
+
&.disable-default-overlay {
|
|
635
|
+
.wp-block-navigation__overlay-container {
|
|
636
|
+
display: none;
|
|
637
|
+
width: 100%;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// When menu is open with custom overlay, hide default navigation and show overlay.
|
|
641
|
+
&.is-menu-open {
|
|
642
|
+
.wp-block-navigation__responsive-container-content {
|
|
643
|
+
// Hides the content of the non-overlay navigation.
|
|
644
|
+
> .wp-block-navigation__container {
|
|
645
|
+
display: none;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
.wp-block-navigation__overlay-container {
|
|
649
|
+
display: block;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
|
|
626
655
|
@include break-small() {
|
|
627
656
|
&:not(.hidden-by-default) {
|
|
628
657
|
&:not(.is-menu-open) {
|
|
@@ -648,13 +677,14 @@ button.wp-block-navigation-item__content {
|
|
|
648
677
|
}
|
|
649
678
|
|
|
650
679
|
// Default menu background and font color.
|
|
680
|
+
// Don't apply default colors when custom overlay is present.
|
|
651
681
|
.wp-block-navigation:not(.has-background)
|
|
652
|
-
.wp-block-navigation__responsive-container.is-menu-open {
|
|
682
|
+
.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
|
|
653
683
|
background-color: #fff;
|
|
654
684
|
}
|
|
655
685
|
|
|
656
686
|
.wp-block-navigation:not(.has-text-color)
|
|
657
|
-
.wp-block-navigation__responsive-container.is-menu-open {
|
|
687
|
+
.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
|
|
658
688
|
color: #000;
|
|
659
689
|
}
|
|
660
690
|
|
|
@@ -721,6 +751,12 @@ button.wp-block-navigation-item__content {
|
|
|
721
751
|
}
|
|
722
752
|
}
|
|
723
753
|
|
|
754
|
+
// When default close button is within a custom overlay, add spacing from edges.
|
|
755
|
+
.disable-default-overlay .wp-block-navigation__responsive-container-close {
|
|
756
|
+
top: clamp(1rem, var(--wp--style--root--padding-left), 20rem);
|
|
757
|
+
right: clamp(1rem, var(--wp--style--root--padding-left), 20rem);
|
|
758
|
+
}
|
|
759
|
+
|
|
724
760
|
// The menu adds wrapping containers.
|
|
725
761
|
.wp-block-navigation__responsive-close {
|
|
726
762
|
width: 100%;
|
|
@@ -753,7 +789,8 @@ button.wp-block-navigation-item__content {
|
|
|
753
789
|
|
|
754
790
|
// Adjust open dialog top margin when admin-bar is visible.
|
|
755
791
|
// Needs to be scoped to .is-menu-open, or it will shift the position of any other navigations that may be present.
|
|
756
|
-
|
|
792
|
+
// Don't apply margin when custom overlay is present.
|
|
793
|
+
.has-modal-open .admin-bar .is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-dialog {
|
|
757
794
|
margin-top: $admin-bar-height-big;
|
|
758
795
|
|
|
759
796
|
// Handle smaller admin-bar.
|
package/src/navigation/view.js
CHANGED
|
@@ -18,6 +18,28 @@ const focusableSelectors = [
|
|
|
18
18
|
'[tabindex]:not([tabindex^="-"])',
|
|
19
19
|
];
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Gets all visible focusable elements within a container.
|
|
23
|
+
* Filters out elements that are hidden.
|
|
24
|
+
*
|
|
25
|
+
* @param {HTMLElement} ref - The container element to search within
|
|
26
|
+
* @return {HTMLElement[]} Array of visible focusable elements
|
|
27
|
+
*/
|
|
28
|
+
function getFocusableElements( ref ) {
|
|
29
|
+
const focusableElements = ref.querySelectorAll( focusableSelectors );
|
|
30
|
+
return Array.from( focusableElements ).filter( ( element ) => {
|
|
31
|
+
// Use modern checkVisibility API if available (Chrome 105+, Firefox 106+, Safari 17.4+)
|
|
32
|
+
if ( typeof element.checkVisibility === 'function' ) {
|
|
33
|
+
return element.checkVisibility( {
|
|
34
|
+
checkOpacity: false,
|
|
35
|
+
checkVisibilityCSS: true,
|
|
36
|
+
} );
|
|
37
|
+
}
|
|
38
|
+
// Fallback for older browsers
|
|
39
|
+
return element.offsetParent !== null;
|
|
40
|
+
} );
|
|
41
|
+
}
|
|
42
|
+
|
|
21
43
|
// This is a fix for Safari in iOS/iPadOS. Without it, Safari doesn't focus out
|
|
22
44
|
// when the user taps in the body. It can be removed once we add an overlay to
|
|
23
45
|
// capture the clicks, instead of relying on the focusout event.
|
|
@@ -198,8 +220,7 @@ const { state, actions } = store(
|
|
|
198
220
|
const ctx = getContext();
|
|
199
221
|
const { ref } = getElement();
|
|
200
222
|
if ( state.isMenuOpen ) {
|
|
201
|
-
const focusableElements =
|
|
202
|
-
ref.querySelectorAll( focusableSelectors );
|
|
223
|
+
const focusableElements = getFocusableElements( ref );
|
|
203
224
|
ctx.modal = ref;
|
|
204
225
|
ctx.firstFocusableElement = focusableElements[ 0 ];
|
|
205
226
|
ctx.lastFocusableElement =
|
|
@@ -209,8 +230,7 @@ const { state, actions } = store(
|
|
|
209
230
|
focusFirstElement() {
|
|
210
231
|
const { ref } = getElement();
|
|
211
232
|
if ( state.isMenuOpen ) {
|
|
212
|
-
const focusableElements =
|
|
213
|
-
ref.querySelectorAll( focusableSelectors );
|
|
233
|
+
const focusableElements = getFocusableElements( ref );
|
|
214
234
|
focusableElements?.[ 0 ]?.focus();
|
|
215
235
|
}
|
|
216
236
|
},
|
package/src/private-apis.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Internal dependencies
|
|
3
3
|
*/
|
|
4
4
|
import { default as BlockKeyboardShortcuts } from './block-keyboard-shortcuts';
|
|
5
|
+
import { NAVIGATION_OVERLAY_TEMPLATE_PART_AREA } from './navigation/constants';
|
|
5
6
|
import { lock } from './lock-unlock';
|
|
6
7
|
|
|
7
8
|
/**
|
|
@@ -10,4 +11,5 @@ import { lock } from './lock-unlock';
|
|
|
10
11
|
export const privateApis = {};
|
|
11
12
|
lock( privateApis, {
|
|
12
13
|
BlockKeyboardShortcuts,
|
|
14
|
+
NAVIGATION_OVERLAY_TEMPLATE_PART_AREA,
|
|
13
15
|
} );
|
package/src/quote/transforms.js
CHANGED
|
@@ -141,15 +141,41 @@ const transforms = {
|
|
|
141
141
|
{
|
|
142
142
|
type: 'block',
|
|
143
143
|
blocks: [ 'core/paragraph' ],
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
isMatch: ( { citation }, block ) => {
|
|
145
|
+
const innerBlocks = block.innerBlocks;
|
|
146
|
+
if ( ! innerBlocks.length ) {
|
|
147
|
+
return ! RichText.isEmpty( citation );
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return innerBlocks.every( ( innerBlock ) => {
|
|
151
|
+
if ( innerBlock.name === 'core/paragraph' ) {
|
|
152
|
+
return true;
|
|
153
|
+
}
|
|
154
|
+
const converted = switchToBlockType(
|
|
155
|
+
innerBlock,
|
|
156
|
+
'core/paragraph'
|
|
157
|
+
);
|
|
158
|
+
return converted !== null;
|
|
159
|
+
} );
|
|
160
|
+
},
|
|
161
|
+
transform: ( { citation }, innerBlocks ) => {
|
|
162
|
+
const paragraphs = innerBlocks.flatMap( ( innerBlock ) => {
|
|
163
|
+
if ( innerBlock.name === 'core/paragraph' ) {
|
|
164
|
+
return innerBlock;
|
|
165
|
+
}
|
|
166
|
+
return (
|
|
167
|
+
switchToBlockType( innerBlock, 'core/paragraph' ) || []
|
|
168
|
+
);
|
|
169
|
+
} );
|
|
170
|
+
return RichText.isEmpty( citation )
|
|
171
|
+
? paragraphs
|
|
147
172
|
: [
|
|
148
|
-
...
|
|
173
|
+
...paragraphs,
|
|
149
174
|
createBlock( 'core/paragraph', {
|
|
150
175
|
content: citation,
|
|
151
176
|
} ),
|
|
152
|
-
]
|
|
177
|
+
];
|
|
178
|
+
},
|
|
153
179
|
},
|
|
154
180
|
{
|
|
155
181
|
type: 'block',
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* WordPress dependencies
|
|
3
3
|
*/
|
|
4
|
-
import { createBlock } from '@wordpress/blocks';
|
|
4
|
+
import { createBlock, getDefaultBlockName } from '@wordpress/blocks';
|
|
5
5
|
|
|
6
6
|
const transforms = {
|
|
7
7
|
from: [
|
|
8
8
|
{
|
|
9
|
-
type: '
|
|
9
|
+
type: 'input',
|
|
10
10
|
regExp: /^-{3,}$/,
|
|
11
|
-
transform: () =>
|
|
11
|
+
transform: () => [
|
|
12
|
+
createBlock( 'core/separator' ),
|
|
13
|
+
createBlock( getDefaultBlockName() ),
|
|
14
|
+
],
|
|
12
15
|
},
|
|
13
16
|
{
|
|
14
17
|
type: 'raw',
|
|
@@ -40,6 +40,23 @@ import {
|
|
|
40
40
|
useTemplatePartArea,
|
|
41
41
|
} from './utils/hooks';
|
|
42
42
|
|
|
43
|
+
const SUPPORTED_AREAS = [ 'header', 'footer' ];
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Returns the list of supported template part areas for pattern replacement.
|
|
47
|
+
* Includes 'overlay' only if the navigation overlays experiment is enabled.
|
|
48
|
+
*
|
|
49
|
+
* @return {string[]} Array of supported area names.
|
|
50
|
+
*/
|
|
51
|
+
function getSupportedAreas() {
|
|
52
|
+
const isOverlayExperimentEnabled =
|
|
53
|
+
typeof window !== 'undefined' &&
|
|
54
|
+
window.__experimentalNavigationOverlays === true;
|
|
55
|
+
return isOverlayExperimentEnabled
|
|
56
|
+
? [ ...SUPPORTED_AREAS, 'navigation-overlay' ]
|
|
57
|
+
: SUPPORTED_AREAS;
|
|
58
|
+
}
|
|
59
|
+
|
|
43
60
|
function ReplaceButton( {
|
|
44
61
|
isEntityAvailable,
|
|
45
62
|
area,
|
|
@@ -54,10 +71,9 @@ function ReplaceButton( {
|
|
|
54
71
|
templatePartId
|
|
55
72
|
);
|
|
56
73
|
const hasReplacements = !! templateParts.length;
|
|
74
|
+
const supportedAreas = getSupportedAreas();
|
|
57
75
|
const canReplace =
|
|
58
|
-
isEntityAvailable &&
|
|
59
|
-
hasReplacements &&
|
|
60
|
-
( area === 'header' || area === 'footer' );
|
|
76
|
+
isEntityAvailable && hasReplacements && supportedAreas.includes( area );
|
|
61
77
|
|
|
62
78
|
if ( ! canReplace ) {
|
|
63
79
|
return null;
|
|
@@ -80,10 +96,11 @@ function TemplatesList( { area, clientId, isEntityAvailable, onSelect } ) {
|
|
|
80
96
|
// This hook fetches patterns, so don't run it unconditionally in the main
|
|
81
97
|
// edit function!
|
|
82
98
|
const blockPatterns = useAlternativeBlockPatterns( area, clientId );
|
|
99
|
+
const supportedAreas = getSupportedAreas();
|
|
83
100
|
const canReplace =
|
|
84
101
|
isEntityAvailable &&
|
|
85
102
|
!! blockPatterns.length &&
|
|
86
|
-
( area
|
|
103
|
+
supportedAreas.includes( area );
|
|
87
104
|
|
|
88
105
|
if ( ! canReplace ) {
|
|
89
106
|
return null;
|