Editor: Update the WordPress packages to Gutenberg 17.7RC1.

This brings the latest and greatest from Gutenberg.
The full changelog is available here 
https://github.com/WordPress/gutenberg/releases/tag/v17.7.0-rc.1

Props youknowriad, get_dave.
See #60315.
Built from https://develop.svn.wordpress.org/trunk@57578


git-svn-id: http://core.svn.wordpress.org/trunk@57079 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
youknowriad 2024-02-09 18:22:22 +00:00
parent 336be7695c
commit f7c63b630c
227 changed files with 13322 additions and 10228 deletions

View File

@ -833,10 +833,6 @@ $_old_files = array(
'wp-includes/blocks/heading/editor.min.css', 'wp-includes/blocks/heading/editor.min.css',
'wp-includes/blocks/heading/editor-rtl.css', 'wp-includes/blocks/heading/editor-rtl.css',
'wp-includes/blocks/heading/editor-rtl.min.css', 'wp-includes/blocks/heading/editor-rtl.min.css',
'wp-includes/blocks/post-content/editor.css',
'wp-includes/blocks/post-content/editor.min.css',
'wp-includes/blocks/post-content/editor-rtl.css',
'wp-includes/blocks/post-content/editor-rtl.min.css',
'wp-includes/blocks/query-title/editor.css', 'wp-includes/blocks/query-title/editor.css',
'wp-includes/blocks/query-title/editor.min.css', 'wp-includes/blocks/query-title/editor.min.css',
'wp-includes/blocks/query-title/editor-rtl.css', 'wp-includes/blocks/query-title/editor-rtl.css',

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -47,6 +47,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-archives-editor" "editorStyle": "wp-block-archives-editor"

View File

@ -54,6 +54,9 @@
"margin": false, "margin": false,
"padding": false "padding": false
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-audio-editor", "editorStyle": "wp-block-audio-editor",

View File

@ -50,6 +50,9 @@
"text": false, "text": false,
"background": false, "background": false,
"__experimentalDuotone": "img" "__experimentalDuotone": "img"
},
"interactivity": {
"clientNavigation": true
} }
}, },
"selectors": { "selectors": {

View File

@ -46,7 +46,20 @@ function render_block_core_block( $attributes ) {
$content = $wp_embed->run_shortcode( $reusable_block->post_content ); $content = $wp_embed->run_shortcode( $reusable_block->post_content );
$content = $wp_embed->autoembed( $content ); $content = $wp_embed->autoembed( $content );
$has_pattern_overrides = isset( $attributes['overrides'] ); // Back compat, the content attribute was previously named overrides and
// had a slightly different format. For blocks that have not been migrated,
// also convert the format here so that the provided `pattern/overrides`
// context is correct.
if ( isset( $attributes['overrides'] ) && ! isset( $attributes['content'] ) ) {
$migrated_content = array();
foreach ( $attributes['overrides'] as $id => $values ) {
$migrated_content[ $id ] = array(
'values' => $values,
);
}
$attributes['content'] = $migrated_content;
}
$has_pattern_overrides = isset( $attributes['content'] );
/** /**
* We set the `pattern/overrides` context through the `render_block_context` * We set the `pattern/overrides` context through the `render_block_context`
@ -55,7 +68,7 @@ function render_block_core_block( $attributes ) {
*/ */
if ( $has_pattern_overrides ) { if ( $has_pattern_overrides ) {
$filter_block_context = static function ( $context ) use ( $attributes ) { $filter_block_context = static function ( $context ) use ( $attributes ) {
$context['pattern/overrides'] = $attributes['overrides']; $context['pattern/overrides'] = $attributes['content'];
return $context; return $context;
}; };
add_filter( 'render_block_context', $filter_block_context, 1 ); add_filter( 'render_block_context', $filter_block_context, 1 );

View File

@ -4,14 +4,14 @@
"name": "core/block", "name": "core/block",
"title": "Pattern", "title": "Pattern",
"category": "reusable", "category": "reusable",
"description": "Create and save content to reuse across your site. Update the pattern, and the changes apply everywhere its used.", "description": "Reuse this design across your site.",
"keywords": [ "reusable" ], "keywords": [ "reusable" ],
"textdomain": "default", "textdomain": "default",
"attributes": { "attributes": {
"ref": { "ref": {
"type": "number" "type": "number"
}, },
"overrides": { "content": {
"type": "object" "type": "object"
} }
}, },
@ -19,6 +19,9 @@
"customClassName": false, "customClassName": false,
"html": false, "html": false,
"inserter": false, "inserter": false,
"renaming": false "renaming": false,
"interactivity": {
"clientNavigation": true
}
} }
} }

View File

@ -48,6 +48,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-archives-editor' 'editorStyle' => 'wp-block-archives-editor'
@ -113,6 +116,9 @@
'margin' => false, 'margin' => false,
'padding' => false 'padding' => false
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-audio-editor', 'editorStyle' => 'wp-block-audio-editor',
@ -174,6 +180,9 @@
'text' => false, 'text' => false,
'background' => false, 'background' => false,
'__experimentalDuotone' => 'img' '__experimentalDuotone' => 'img'
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'selectors' => array( 'selectors' => array(
@ -188,7 +197,7 @@
'name' => 'core/block', 'name' => 'core/block',
'title' => 'Pattern', 'title' => 'Pattern',
'category' => 'reusable', 'category' => 'reusable',
'description' => 'Create and save content to reuse across your site. Update the pattern, and the changes apply everywhere its used.', 'description' => 'Reuse this design across your site.',
'keywords' => array( 'keywords' => array(
'reusable' 'reusable'
), ),
@ -197,7 +206,7 @@
'ref' => array( 'ref' => array(
'type' => 'number' 'type' => 'number'
), ),
'overrides' => array( 'content' => array(
'type' => 'object' 'type' => 'object'
) )
), ),
@ -205,7 +214,10 @@
'customClassName' => false, 'customClassName' => false,
'html' => false, 'html' => false,
'inserter' => false, 'inserter' => false,
'renaming' => false 'renaming' => false,
'interactivity' => array(
'clientNavigation' => true
)
) )
), ),
'button' => array( 'button' => array(
@ -317,7 +329,9 @@
) )
), ),
'reusable' => false, 'reusable' => false,
'shadow' => true, 'shadow' => array(
'__experimentalSkipSerialization' => true
),
'spacing' => array( 'spacing' => array(
'__experimentalSkipSerialization' => true, '__experimentalSkipSerialization' => true,
'padding' => array( 'padding' => array(
@ -341,7 +355,10 @@
'width' => true 'width' => true
) )
), ),
'__experimentalSelector' => '.wp-block-button .wp-block-button__link' '__experimentalSelector' => '.wp-block-button .wp-block-button__link',
'interactivity' => array(
'clientNavigation' => true
)
), ),
'styles' => array( 'styles' => array(
array( array(
@ -363,6 +380,9 @@
'name' => 'core/buttons', 'name' => 'core/buttons',
'title' => 'Buttons', 'title' => 'Buttons',
'category' => 'design', 'category' => 'design',
'allowedBlocks' => array(
'core/button'
),
'description' => 'Prompt visitors to take action with a group of button-style links.', 'description' => 'Prompt visitors to take action with a group of button-style links.',
'keywords' => array( 'keywords' => array(
'link' 'link'
@ -405,6 +425,9 @@
'default' => array( 'default' => array(
'type' => 'flex' 'type' => 'flex'
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-buttons-editor', 'editorStyle' => 'wp-block-buttons-editor',
@ -455,6 +478,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'style' => 'wp-block-calendar' 'style' => 'wp-block-calendar'
@ -512,6 +538,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-categories-editor', 'editorStyle' => 'wp-block-categories-editor',
@ -580,6 +609,9 @@
'background' => true, 'background' => true,
'text' => true 'text' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'style' => 'wp-block-code' 'style' => 'wp-block-code'
@ -633,6 +665,7 @@
'text' => true 'text' => true
) )
), ),
'shadow' => true,
'spacing' => array( 'spacing' => array(
'blockGap' => true, 'blockGap' => true,
'padding' => true, 'padding' => true,
@ -664,7 +697,10 @@
'fontSize' => true 'fontSize' => true
) )
), ),
'layout' => true 'layout' => true,
'interactivity' => array(
'clientNavigation' => true
)
) )
), ),
'columns' => array( 'columns' => array(
@ -673,6 +709,9 @@
'name' => 'core/columns', 'name' => 'core/columns',
'title' => 'Columns', 'title' => 'Columns',
'category' => 'design', 'category' => 'design',
'allowedBlocks' => array(
'core/column'
),
'description' => 'Display content in multiple columns, with blocks added to each column.', 'description' => 'Display content in multiple columns, with blocks added to each column.',
'textdomain' => 'default', 'textdomain' => 'default',
'attributes' => array( 'attributes' => array(
@ -764,7 +803,11 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
) ),
'interactivity' => array(
'clientNavigation' => true
),
'shadow' => true
), ),
'editorStyle' => 'wp-block-columns-editor', 'editorStyle' => 'wp-block-columns-editor',
'style' => 'wp-block-columns' 'style' => 'wp-block-columns'
@ -823,6 +866,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -929,6 +975,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -982,6 +1031,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -1068,6 +1120,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'style' => 'wp-block-comment-template' 'style' => 'wp-block-comment-template'
@ -1139,6 +1194,11 @@
'parent' => array( 'parent' => array(
'core/comments' 'core/comments'
), ),
'allowedBlocks' => array(
'core/comments-pagination-previous',
'core/comments-pagination-numbers',
'core/comments-pagination-next'
),
'description' => 'Displays a paginated navigation to next/previous set of comments, when applicable.', 'description' => 'Displays a paginated navigation to next/previous set of comments, when applicable.',
'textdomain' => 'default', 'textdomain' => 'default',
'attributes' => array( 'attributes' => array(
@ -1182,6 +1242,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-comments-pagination-editor', 'editorStyle' => 'wp-block-comments-pagination-editor',
@ -1229,6 +1292,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -1268,6 +1334,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -1313,6 +1382,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -1384,6 +1456,9 @@
'__experimentalFontStyle' => true, '__experimentalFontStyle' => true,
'__experimentalFontWeight' => true '__experimentalFontWeight' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -1537,6 +1612,9 @@
), ),
'layout' => array( 'layout' => array(
'allowJustification' => false 'allowJustification' => false
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-cover-editor', 'editorStyle' => 'wp-block-cover-editor',
@ -1610,6 +1688,9 @@
), ),
'layout' => array( 'layout' => array(
'allowEditing' => false 'allowEditing' => false
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-details-editor', 'editorStyle' => 'wp-block-details-editor',
@ -1661,6 +1742,9 @@
'align' => true, 'align' => true,
'spacing' => array( 'spacing' => array(
'margin' => true 'margin' => true
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-embed-editor', 'editorStyle' => 'wp-block-embed-editor',
@ -1809,6 +1893,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'style' => 'wp-block-footnotes' 'style' => 'wp-block-footnotes'
@ -1840,6 +1927,9 @@
'name' => 'core/gallery', 'name' => 'core/gallery',
'title' => 'Gallery', 'title' => 'Gallery',
'category' => 'media', 'category' => 'media',
'allowedBlocks' => array(
'core/image'
),
'description' => 'Display multiple images in a rich gallery.', 'description' => 'Display multiple images in a rich gallery.',
'keywords' => array( 'keywords' => array(
'images', 'images',
@ -1992,6 +2082,9 @@
'default' => array( 'default' => array(
'type' => 'flex' 'type' => 'flex'
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-gallery-editor', 'editorStyle' => 'wp-block-gallery-editor',
@ -2105,6 +2198,9 @@
), ),
'layout' => array( 'layout' => array(
'allowSizingOnChildren' => true 'allowSizingOnChildren' => true
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-group-editor', 'editorStyle' => 'wp-block-group-editor',
@ -2181,7 +2277,10 @@
) )
), ),
'__unstablePasteTextInline' => true, '__unstablePasteTextInline' => true,
'__experimentalSlashInserter' => true '__experimentalSlashInserter' => true,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'editorStyle' => 'wp-block-heading-editor', 'editorStyle' => 'wp-block-heading-editor',
'style' => 'wp-block-heading' 'style' => 'wp-block-heading'
@ -2226,6 +2325,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-home-link-editor', 'editorStyle' => 'wp-block-home-link-editor',
@ -2251,7 +2353,10 @@
'supports' => array( 'supports' => array(
'customClassName' => false, 'customClassName' => false,
'className' => false, 'className' => false,
'html' => false 'html' => false,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'editorStyle' => 'wp-block-html-editor' 'editorStyle' => 'wp-block-html-editor'
), ),
@ -2384,10 +2489,14 @@
'radius' => true, 'radius' => true,
'width' => true 'width' => true
) )
),
'shadow' => array(
'__experimentalSkipSerialization' => true
) )
), ),
'selectors' => array( 'selectors' => array(
'border' => '.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder', 'border' => '.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder',
'shadow' => '.wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder',
'filter' => array( 'filter' => array(
'duotone' => '.wp-block-image img, .wp-block-image .components-placeholder' 'duotone' => '.wp-block-image img, .wp-block-image .components-placeholder'
) )
@ -2456,6 +2565,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-latest-comments-editor', 'editorStyle' => 'wp-block-latest-comments-editor',
@ -2579,6 +2691,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-latest-posts-editor', 'editorStyle' => 'wp-block-latest-posts-editor',
@ -2619,6 +2734,9 @@
'name' => 'core/list', 'name' => 'core/list',
'title' => 'List', 'title' => 'List',
'category' => 'text', 'category' => 'text',
'allowedBlocks' => array(
'core/list-item'
),
'description' => 'Create a bulleted or numbered list.', 'description' => 'Create a bulleted or numbered list.',
'keywords' => array( 'keywords' => array(
'bullet list', 'bullet list',
@ -2692,7 +2810,10 @@
'__unstablePasteTextInline' => true, '__unstablePasteTextInline' => true,
'__experimentalSelector' => 'ol,ul', '__experimentalSelector' => 'ol,ul',
'__experimentalOnMerge' => true, '__experimentalOnMerge' => true,
'__experimentalSlashInserter' => true '__experimentalSlashInserter' => true,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'editorStyle' => 'wp-block-list-editor', 'editorStyle' => 'wp-block-list-editor',
'style' => 'wp-block-list' 'style' => 'wp-block-list'
@ -2706,6 +2827,9 @@
'parent' => array( 'parent' => array(
'core/list' 'core/list'
), ),
'allowedBlocks' => array(
'core/list'
),
'description' => 'Create a list item.', 'description' => 'Create a list item.',
'textdomain' => 'default', 'textdomain' => 'default',
'attributes' => array( 'attributes' => array(
@ -2742,6 +2866,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -2790,6 +2917,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -2924,6 +3054,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-media-text-editor', 'editorStyle' => 'wp-block-media-text-editor',
@ -2954,7 +3087,10 @@
'customClassName' => false, 'customClassName' => false,
'inserter' => false, 'inserter' => false,
'html' => false, 'html' => false,
'reusable' => false 'reusable' => false,
'interactivity' => array(
'clientNavigation' => true
)
) )
), ),
'more' => array( 'more' => array(
@ -2981,7 +3117,10 @@
'customClassName' => false, 'customClassName' => false,
'className' => false, 'className' => false,
'html' => false, 'html' => false,
'multiple' => false 'multiple' => false,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'editorStyle' => 'wp-block-more-editor' 'editorStyle' => 'wp-block-more-editor'
), ),
@ -2991,6 +3130,19 @@
'name' => 'core/navigation', 'name' => 'core/navigation',
'title' => 'Navigation', 'title' => 'Navigation',
'category' => 'theme', 'category' => 'theme',
'allowedBlocks' => array(
'core/navigation-link',
'core/search',
'core/social-links',
'core/page-list',
'core/spacer',
'core/home-link',
'core/site-title',
'core/site-logo',
'core/navigation-submenu',
'core/loginout',
'core/buttons'
),
'description' => 'A collection of blocks that allow visitors to get around your site.', 'description' => 'A collection of blocks that allow visitors to get around your site.',
'keywords' => array( 'keywords' => array(
'menu', 'menu',
@ -3158,6 +3310,11 @@
'parent' => array( 'parent' => array(
'core/navigation' 'core/navigation'
), ),
'allowedBlocks' => array(
'core/navigation-link',
'core/navigation-submenu',
'core/page-list'
),
'description' => 'Add a page, link, or another item to your navigation.', 'description' => 'Add a page, link, or another item to your navigation.',
'textdomain' => 'default', 'textdomain' => 'default',
'attributes' => array( 'attributes' => array(
@ -3225,7 +3382,10 @@
'fontSize' => true 'fontSize' => true
) )
), ),
'renaming' => false 'renaming' => false,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'editorStyle' => 'wp-block-navigation-link-editor', 'editorStyle' => 'wp-block-navigation-link-editor',
'style' => 'wp-block-navigation-link' 'style' => 'wp-block-navigation-link'
@ -3292,7 +3452,10 @@
), ),
'supports' => array( 'supports' => array(
'reusable' => false, 'reusable' => false,
'html' => false 'html' => false,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'editorStyle' => 'wp-block-navigation-submenu-editor', 'editorStyle' => 'wp-block-navigation-submenu-editor',
'style' => 'wp-block-navigation-submenu' 'style' => 'wp-block-navigation-submenu'
@ -3315,7 +3478,10 @@
'supports' => array( 'supports' => array(
'customClassName' => false, 'customClassName' => false,
'className' => false, 'className' => false,
'html' => false 'html' => false,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'editorStyle' => 'wp-block-nextpage-editor' 'editorStyle' => 'wp-block-nextpage-editor'
), ),
@ -3325,6 +3491,9 @@
'name' => 'core/page-list', 'name' => 'core/page-list',
'title' => 'Page List', 'title' => 'Page List',
'category' => 'widgets', 'category' => 'widgets',
'allowedBlocks' => array(
'core/page-list-item'
),
'description' => 'Display a list of all pages.', 'description' => 'Display a list of all pages.',
'keywords' => array( 'keywords' => array(
'menu', 'menu',
@ -3371,6 +3540,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-page-list-editor', 'editorStyle' => 'wp-block-page-list-editor',
@ -3429,7 +3601,10 @@
'html' => false, 'html' => false,
'lock' => false, 'lock' => false,
'inserter' => false, 'inserter' => false,
'__experimentalToolbar' => false '__experimentalToolbar' => false,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'editorStyle' => 'wp-block-page-list-editor', 'editorStyle' => 'wp-block-page-list-editor',
'style' => 'wp-block-page-list' 'style' => 'wp-block-page-list'
@ -3508,7 +3683,10 @@
) )
), ),
'__experimentalSelector' => 'p', '__experimentalSelector' => 'p',
'__unstablePasteTextInline' => true '__unstablePasteTextInline' => true,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'editorStyle' => 'wp-block-paragraph-editor', 'editorStyle' => 'wp-block-paragraph-editor',
'style' => 'wp-block-paragraph' 'style' => 'wp-block-paragraph'
@ -3523,7 +3701,10 @@
'supports' => array( 'supports' => array(
'html' => false, 'html' => false,
'inserter' => false, 'inserter' => false,
'renaming' => false 'renaming' => false,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'textdomain' => 'default', 'textdomain' => 'default',
'attributes' => array( 'attributes' => array(
@ -3599,6 +3780,9 @@
'background' => true, 'background' => true,
'text' => true 'text' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'style' => 'wp-block-post-author' 'style' => 'wp-block-post-author'
@ -3645,6 +3829,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -3700,6 +3887,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -3860,6 +4050,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -3919,6 +4112,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-post-excerpt-editor', 'editorStyle' => 'wp-block-post-excerpt-editor',
@ -4017,6 +4213,9 @@
'spacing' => array( 'spacing' => array(
'margin' => true, 'margin' => true,
'padding' => true 'padding' => true
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-post-featured-image-editor', 'editorStyle' => 'wp-block-post-featured-image-editor',
@ -4053,9 +4252,6 @@
'type' => 'string', 'type' => 'string',
'default' => 'none' 'default' => 'none'
), ),
'inSameTerm' => array(
'type' => 'boolean'
),
'taxonomy' => array( 'taxonomy' => array(
'type' => 'string', 'type' => 'string',
'default' => '' 'default' => ''
@ -4083,6 +4279,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'style' => 'wp-block-post-navigation-link' 'style' => 'wp-block-post-navigation-link'
@ -4142,6 +4341,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'blockGap' => true 'blockGap' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'style' => 'wp-block-post-template', 'style' => 'wp-block-post-template',
@ -4206,6 +4408,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'style' => 'wp-block-post-terms' 'style' => 'wp-block-post-terms'
@ -4276,6 +4481,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'style' => 'wp-block-post-title' 'style' => 'wp-block-post-title'
@ -4322,6 +4530,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'style' => 'wp-block-preformatted' 'style' => 'wp-block-preformatted'
@ -4402,6 +4613,9 @@
'fontSize' => '1.5em', 'fontSize' => '1.5em',
'lineHeight' => '1.6' 'lineHeight' => '1.6'
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-pullquote-editor', 'editorStyle' => 'wp-block-pullquote-editor',
@ -4465,10 +4679,10 @@
'full' 'full'
), ),
'html' => false, 'html' => false,
'layout' => true 'layout' => true,
'interactivity' => true
), ),
'editorStyle' => 'wp-block-query-editor', 'editorStyle' => 'wp-block-query-editor'
'style' => 'wp-block-query'
), ),
'query-no-results' => array( 'query-no-results' => array(
'$schema' => 'https://schemas.wp.org/trunk/block.json', '$schema' => 'https://schemas.wp.org/trunk/block.json',
@ -4505,6 +4719,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -4514,9 +4731,14 @@
'name' => 'core/query-pagination', 'name' => 'core/query-pagination',
'title' => 'Pagination', 'title' => 'Pagination',
'category' => 'theme', 'category' => 'theme',
'parent' => array( 'ancestor' => array(
'core/query' 'core/query'
), ),
'allowedBlocks' => array(
'core/query-pagination-previous',
'core/query-pagination-numbers',
'core/query-pagination-next'
),
'description' => 'Displays a paginated navigation to next/previous set of posts, when applicable.', 'description' => 'Displays a paginated navigation to next/previous set of posts, when applicable.',
'textdomain' => 'default', 'textdomain' => 'default',
'attributes' => array( 'attributes' => array(
@ -4569,6 +4791,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-query-pagination-editor', 'editorStyle' => 'wp-block-query-pagination-editor',
@ -4619,6 +4844,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -4666,6 +4894,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-query-pagination-numbers-editor' 'editorStyle' => 'wp-block-query-pagination-numbers-editor'
@ -4715,6 +4946,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -4775,6 +5009,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'style' => 'wp-block-query-title' 'style' => 'wp-block-query-title'
@ -4842,6 +5079,9 @@
), ),
'spacing' => array( 'spacing' => array(
'blockGap' => true 'blockGap' => true
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'styles' => array( 'styles' => array(
@ -4915,6 +5155,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'width' => true 'width' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'style' => 'wp-block-read-more' 'style' => 'wp-block-read-more'
@ -4967,7 +5210,10 @@
), ),
'supports' => array( 'supports' => array(
'align' => true, 'align' => true,
'html' => false 'html' => false,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'editorStyle' => 'wp-block-rss-editor', 'editorStyle' => 'wp-block-rss-editor',
'style' => 'wp-block-rss' 'style' => 'wp-block-rss'
@ -5113,6 +5359,9 @@
'top', 'top',
'bottom' 'bottom'
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'styles' => array( 'styles' => array(
@ -5201,6 +5450,9 @@
'margin' => false, 'margin' => false,
'padding' => false 'padding' => false
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'styles' => array( 'styles' => array(
@ -5269,6 +5521,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-site-tagline-editor' 'editorStyle' => 'wp-block-site-tagline-editor'
@ -5336,6 +5591,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-site-title-editor', 'editorStyle' => 'wp-block-site-title-editor',
@ -5376,7 +5634,10 @@
), ),
'supports' => array( 'supports' => array(
'reusable' => false, 'reusable' => false,
'html' => false 'html' => false,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'editorStyle' => 'wp-block-social-link-editor' 'editorStyle' => 'wp-block-social-link-editor'
), ),
@ -5386,6 +5647,9 @@
'name' => 'core/social-links', 'name' => 'core/social-links',
'title' => 'Social Icons', 'title' => 'Social Icons',
'category' => 'widgets', 'category' => 'widgets',
'allowedBlocks' => array(
'core/social-link'
),
'description' => 'Display icons linking to your social media profiles or sites.', 'description' => 'Display icons linking to your social media profiles or sites.',
'keywords' => array( 'keywords' => array(
'links' 'links'
@ -5474,6 +5738,9 @@
'margin' => true, 'margin' => true,
'padding' => false 'padding' => false
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'styles' => array( 'styles' => array(
@ -5524,6 +5791,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'margin' => true 'margin' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-spacer-editor', 'editorStyle' => 'wp-block-spacer-editor',
@ -5738,7 +6008,10 @@
'width' => true 'width' => true
) )
), ),
'__experimentalSelector' => '.wp-block-table > table' '__experimentalSelector' => '.wp-block-table > table',
'interactivity' => array(
'clientNavigation' => true
)
), ),
'styles' => array( 'styles' => array(
array( array(
@ -5811,6 +6084,9 @@
'__experimentalFontStyle' => true, '__experimentalFontStyle' => true,
'__experimentalTextTransform' => true, '__experimentalTextTransform' => true,
'__experimentalLetterSpacing' => true '__experimentalLetterSpacing' => true
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-tag-cloud-editor' 'editorStyle' => 'wp-block-tag-cloud-editor'
@ -5841,7 +6117,10 @@
'align' => true, 'align' => true,
'html' => false, 'html' => false,
'reusable' => false, 'reusable' => false,
'renaming' => false 'renaming' => false,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'editorStyle' => 'wp-block-template-part-editor' 'editorStyle' => 'wp-block-template-part-editor'
), ),
@ -5887,6 +6166,9 @@
'__experimentalDefaultControls' => array( '__experimentalDefaultControls' => array(
'fontSize' => true 'fontSize' => true
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
) )
), ),
@ -5928,7 +6210,10 @@
) )
), ),
'supports' => array( 'supports' => array(
'inserter' => false 'inserter' => false,
'interactivity' => array(
'clientNavigation' => true
)
), ),
'editorStyle' => 'wp-block-text-columns-editor', 'editorStyle' => 'wp-block-text-columns-editor',
'style' => 'wp-block-text-columns' 'style' => 'wp-block-text-columns'
@ -5993,6 +6278,9 @@
'width' => true, 'width' => true,
'color' => true, 'color' => true,
'style' => true 'style' => true
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'style' => 'wp-block-verse', 'style' => 'wp-block-verse',
@ -6092,6 +6380,9 @@
'margin' => false, 'margin' => false,
'padding' => false 'padding' => false
) )
),
'interactivity' => array(
'clientNavigation' => true
) )
), ),
'editorStyle' => 'wp-block-video-editor', 'editorStyle' => 'wp-block-video-editor',

View File

@ -98,7 +98,9 @@
} }
}, },
"reusable": false, "reusable": false,
"shadow": true, "shadow": {
"__experimentalSkipSerialization": true
},
"spacing": { "spacing": {
"__experimentalSkipSerialization": true, "__experimentalSkipSerialization": true,
"padding": [ "horizontal", "vertical" ], "padding": [ "horizontal", "vertical" ],
@ -119,7 +121,10 @@
"width": true "width": true
} }
}, },
"__experimentalSelector": ".wp-block-button .wp-block-button__link" "__experimentalSelector": ".wp-block-button .wp-block-button__link",
"interactivity": {
"clientNavigation": true
}
}, },
"styles": [ "styles": [
{ "name": "fill", "label": "Fill", "isDefault": true }, { "name": "fill", "label": "Fill", "isDefault": true },

View File

@ -4,6 +4,7 @@
"name": "core/buttons", "name": "core/buttons",
"title": "Buttons", "title": "Buttons",
"category": "design", "category": "design",
"allowedBlocks": [ "core/button" ],
"description": "Prompt visitors to take action with a group of button-style links.", "description": "Prompt visitors to take action with a group of button-style links.",
"keywords": [ "link" ], "keywords": [ "link" ],
"textdomain": "default", "textdomain": "default",
@ -38,6 +39,9 @@
"default": { "default": {
"type": "flex" "type": "flex"
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-buttons-editor", "editorStyle": "wp-block-buttons-editor",

View File

@ -37,6 +37,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"style": "wp-block-calendar" "style": "wp-block-calendar"

View File

@ -51,6 +51,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-categories-editor", "editorStyle": "wp-block-categories-editor",

View File

@ -56,6 +56,9 @@
"background": true, "background": true,
"text": true "text": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"style": "wp-block-code" "style": "wp-block-code"

View File

@ -37,6 +37,7 @@
"text": true "text": true
} }
}, },
"shadow": true,
"spacing": { "spacing": {
"blockGap": true, "blockGap": true,
"padding": true, "padding": true,
@ -68,6 +69,9 @@
"fontSize": true "fontSize": true
} }
}, },
"layout": true "layout": true,
"interactivity": {
"clientNavigation": true
}
} }
} }

View File

@ -4,6 +4,7 @@
"name": "core/columns", "name": "core/columns",
"title": "Columns", "title": "Columns",
"category": "design", "category": "design",
"allowedBlocks": [ "core/column" ],
"description": "Display content in multiple columns, with blocks added to each column.", "description": "Display content in multiple columns, with blocks added to each column.",
"textdomain": "default", "textdomain": "default",
"attributes": { "attributes": {
@ -78,7 +79,11 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
} },
"interactivity": {
"clientNavigation": true
},
"shadow": true
}, },
"editorStyle": "wp-block-columns-editor", "editorStyle": "wp-block-columns-editor",
"style": "wp-block-columns" "style": "wp-block-columns"

View File

@ -48,6 +48,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -44,6 +44,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -44,6 +44,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -28,6 +28,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"style": "wp-block-comment-template" "style": "wp-block-comment-template"

View File

@ -35,6 +35,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -30,6 +30,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -35,6 +35,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -5,6 +5,11 @@
"title": "Comments Pagination", "title": "Comments Pagination",
"category": "theme", "category": "theme",
"parent": [ "core/comments" ], "parent": [ "core/comments" ],
"allowedBlocks": [
"core/comments-pagination-previous",
"core/comments-pagination-numbers",
"core/comments-pagination-next"
],
"description": "Displays a paginated navigation to next/previous set of comments, when applicable.", "description": "Displays a paginated navigation to next/previous set of comments, when applicable.",
"textdomain": "default", "textdomain": "default",
"attributes": { "attributes": {
@ -48,6 +53,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-comments-pagination-editor", "editorStyle": "wp-block-comments-pagination-editor",

View File

@ -61,6 +61,9 @@
"__experimentalFontStyle": true, "__experimentalFontStyle": true,
"__experimentalFontWeight": true "__experimentalFontWeight": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -132,6 +132,9 @@
}, },
"layout": { "layout": {
"allowJustification": false "allowJustification": false
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-cover-editor", "editorStyle": "wp-block-cover-editor",

View File

@ -58,6 +58,9 @@
}, },
"layout": { "layout": {
"allowEditing": false "allowEditing": false
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-details-editor", "editorStyle": "wp-block-details-editor",

View File

@ -44,6 +44,9 @@
"align": true, "align": true,
"spacing": { "spacing": {
"margin": true "margin": true
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-embed-editor", "editorStyle": "wp-block-embed-editor",

View File

@ -10,9 +10,13 @@
.wp-block-embed .components-placeholder__error{ .wp-block-embed .components-placeholder__error{
word-break:break-word; word-break:break-word;
} }
.wp-block-embed .components-placeholder__learn-more{
.wp-block-embed__learn-more{
margin-top:1em; margin-top:1em;
} }
.wp-block-post-content .wp-block-embed__learn-more a{
color:var(--wp-admin-theme-color);
}
.block-library-embed__interactive-overlay{ .block-library-embed__interactive-overlay{
bottom:0; bottom:0;

View File

@ -1 +1 @@
.wp-block-embed{clear:both;margin-left:0;margin-right:0}.wp-block-embed.is-loading{display:flex;justify-content:center}.wp-block-embed .components-placeholder__error{word-break:break-word}.wp-block-embed .components-placeholder__learn-more{margin-top:1em}.block-library-embed__interactive-overlay{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0}.wp-block[data-align=left]>.wp-block-embed,.wp-block[data-align=right]>.wp-block-embed{max-width:360px;width:100%}.wp-block[data-align=left]>.wp-block-embed .wp-block-embed__wrapper,.wp-block[data-align=right]>.wp-block-embed .wp-block-embed__wrapper{min-width:280px} .wp-block-embed{clear:both;margin-left:0;margin-right:0}.wp-block-embed.is-loading{display:flex;justify-content:center}.wp-block-embed .components-placeholder__error{word-break:break-word}.wp-block-embed__learn-more{margin-top:1em}.wp-block-post-content .wp-block-embed__learn-more a{color:var(--wp-admin-theme-color)}.block-library-embed__interactive-overlay{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0}.wp-block[data-align=left]>.wp-block-embed,.wp-block[data-align=right]>.wp-block-embed{max-width:360px;width:100%}.wp-block[data-align=left]>.wp-block-embed .wp-block-embed__wrapper,.wp-block[data-align=right]>.wp-block-embed .wp-block-embed__wrapper{min-width:280px}

View File

@ -10,9 +10,13 @@
.wp-block-embed .components-placeholder__error{ .wp-block-embed .components-placeholder__error{
word-break:break-word; word-break:break-word;
} }
.wp-block-embed .components-placeholder__learn-more{
.wp-block-embed__learn-more{
margin-top:1em; margin-top:1em;
} }
.wp-block-post-content .wp-block-embed__learn-more a{
color:var(--wp-admin-theme-color);
}
.block-library-embed__interactive-overlay{ .block-library-embed__interactive-overlay{
bottom:0; bottom:0;

View File

@ -1 +1 @@
.wp-block-embed{clear:both;margin-left:0;margin-right:0}.wp-block-embed.is-loading{display:flex;justify-content:center}.wp-block-embed .components-placeholder__error{word-break:break-word}.wp-block-embed .components-placeholder__learn-more{margin-top:1em}.block-library-embed__interactive-overlay{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0}.wp-block[data-align=left]>.wp-block-embed,.wp-block[data-align=right]>.wp-block-embed{max-width:360px;width:100%}.wp-block[data-align=left]>.wp-block-embed .wp-block-embed__wrapper,.wp-block[data-align=right]>.wp-block-embed .wp-block-embed__wrapper{min-width:280px} .wp-block-embed{clear:both;margin-left:0;margin-right:0}.wp-block-embed.is-loading{display:flex;justify-content:center}.wp-block-embed .components-placeholder__error{word-break:break-word}.wp-block-embed__learn-more{margin-top:1em}.wp-block-post-content .wp-block-embed__learn-more a{color:var(--wp-admin-theme-color)}.block-library-embed__interactive-overlay{bottom:0;left:0;opacity:0;position:absolute;right:0;top:0}.wp-block[data-align=left]>.wp-block-embed,.wp-block[data-align=right]>.wp-block-embed{max-width:360px;width:100%}.wp-block[data-align=left]>.wp-block-embed .wp-block-embed__wrapper,.wp-block[data-align=right]>.wp-block-embed .wp-block-embed__wrapper{min-width:280px}

View File

@ -38,6 +38,17 @@ function render_block_core_file( $attributes, $content ) {
// If it's interactive, enqueue the script module and add the directives. // If it's interactive, enqueue the script module and add the directives.
if ( ! empty( $attributes['displayPreview'] ) ) { if ( ! empty( $attributes['displayPreview'] ) ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/file.min.js' );
}
wp_register_script_module(
'@wordpress/block-library/file',
isset( $module_url ) ? $module_url : includes_url( "blocks/file/view{$suffix}.js" ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
wp_enqueue_script_module( '@wordpress/block-library/file' ); wp_enqueue_script_module( '@wordpress/block-library/file' );
$processor = new WP_HTML_Tag_Processor( $content ); $processor = new WP_HTML_Tag_Processor( $content );
@ -62,12 +73,5 @@ function register_block_core_file() {
'render_callback' => 'render_block_core_file', 'render_callback' => 'render_block_core_file',
) )
); );
wp_register_script_module(
'@wordpress/block-library/file',
defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ? gutenberg_url( '/build/interactivity/file.min.js' ) : includes_url( 'blocks/file/view.min.js' ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
} }
add_action( 'init', 'register_block_core_file' ); add_action( 'init', 'register_block_core_file' );

View File

@ -89,5 +89,7 @@ const createActiveXObject = type => {
return browserSupportsPdfs(); return browserSupportsPdfs();
} }
} }
}, {
lock: true
}); });

View File

@ -1 +1 @@
import*as e from"@wordpress/interactivity";var t={d:(e,o)=>{for(var r in o)t.o(o,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:o[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const o=(e=>{var o={};return t.d(o,e),o})({store:()=>e.store}),r=e=>{let t;try{t=new window.ActiveXObject(e)}catch(e){t=void 0}return t};(0,o.store)("core/file",{state:{get hasPdfPreview(){return!(window.navigator.userAgent.indexOf("Mobi")>-1||window.navigator.userAgent.indexOf("Android")>-1||window.navigator.userAgent.indexOf("Macintosh")>-1&&window.navigator.maxTouchPoints&&window.navigator.maxTouchPoints>2||(window.ActiveXObject||"ActiveXObject"in window)&&!r("AcroPDF.PDF")&&!r("PDF.PdfCtrl"))}}}); import*as e from"@wordpress/interactivity";var t={d:(e,o)=>{for(var r in o)t.o(o,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:o[r]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const o=(e=>{var o={};return t.d(o,e),o})({store:()=>e.store}),r=e=>{let t;try{t=new window.ActiveXObject(e)}catch(e){t=void 0}return t};(0,o.store)("core/file",{state:{get hasPdfPreview(){return!(window.navigator.userAgent.indexOf("Mobi")>-1||window.navigator.userAgent.indexOf("Android")>-1||window.navigator.userAgent.indexOf("Macintosh")>-1&&window.navigator.maxTouchPoints&&window.navigator.maxTouchPoints>2||(window.ActiveXObject||"ActiveXObject"in window)&&!r("AcroPDF.PDF")&&!r("PDF.PdfCtrl"))}}},{lock:!0});

View File

@ -55,6 +55,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"style": "wp-block-footnotes" "style": "wp-block-footnotes"

View File

@ -33,32 +33,18 @@ function block_core_gallery_data_id_backcompatibility( $parsed_block ) {
add_filter( 'render_block_data', 'block_core_gallery_data_id_backcompatibility' ); add_filter( 'render_block_data', 'block_core_gallery_data_id_backcompatibility' );
/** /**
* Filter to randomize the order of image blocks. * Renders the `core/gallery` block on the server.
*
* @param array $parsed_block The block being rendered.
* @return array The block object with randomized order of image blocks.
*/
function block_core_gallery_random_order( $parsed_block ) {
if ( 'core/gallery' === $parsed_block['blockName'] && ! empty( $parsed_block['attrs']['randomOrder'] ) ) {
shuffle( $parsed_block['innerBlocks'] );
}
return $parsed_block;
}
add_filter( 'render_block_data', 'block_core_gallery_random_order' );
/**
* 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
* so a css var is added to allow this.
* *
* @param array $attributes Attributes of the block being rendered. * @param array $attributes Attributes of the block being rendered.
* @param string $content Content of the block being rendered. * @param string $content Content of the block being rendered.
* @return string The 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 ) {
// 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
// so a css var is added to allow this.
$gap = $attributes['style']['spacing']['blockGap'] ?? null; $gap = $attributes['style']['spacing']['blockGap'] ?? null;
// Skip if gap value contains unsupported characters. // Skip if gap value contains unsupported characters.
// Regex for CSS value borrowed from `safecss_filter_attr`, and used here // Regex for CSS value borrowed from `safecss_filter_attr`, and used here
@ -130,7 +116,51 @@ function block_core_gallery_render( $attributes, $content ) {
'context' => 'block-supports', 'context' => 'block-supports',
) )
); );
return (string) $processed_content;
// 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.
$updated_content = $processed_content->get_updated_html();
/*
* Randomize the order of image blocks. Ideally we should shuffle
* the `$parsed_block['innerBlocks']` via the `render_block_data` hook.
* However, this hook doesn't apply inner block updates when blocks are
* nested.
* @todo: In the future, if this hook supports updating innerBlocks in
* nested blocks, it should be refactored.
*
* @see: https://github.com/WordPress/gutenberg/pull/58733
*/
if ( empty( $attributes['randomOrder'] ) ) {
return $updated_content;
}
// This pattern matches figure elements with the `wp-block-image` class to
// avoid the gallery's wrapping `figure` element and extract images only.
$pattern = '/<figure[^>]*\bwp-block-image\b[^>]*>.*?<\/figure>/';
// Find all Image blocks.
preg_match_all( $pattern, $updated_content, $matches );
if ( ! $matches ) {
return $updated_content;
}
$image_blocks = $matches[0];
// Randomize the order of Image blocks.
shuffle( $image_blocks );
$i = 0;
$content = preg_replace_callback(
$pattern,
static function () use ( $image_blocks, &$i ) {
$new_image_block = $image_blocks[ $i ];
++$i;
return $new_image_block;
},
$updated_content
);
return $content;
} }
/** /**
* Registers the `core/gallery` block on server. * Registers the `core/gallery` block on server.

View File

@ -4,6 +4,7 @@
"name": "core/gallery", "name": "core/gallery",
"title": "Gallery", "title": "Gallery",
"category": "media", "category": "media",
"allowedBlocks": [ "core/image" ],
"description": "Display multiple images in a rich gallery.", "description": "Display multiple images in a rich gallery.",
"keywords": [ "images", "photos" ], "keywords": [ "images", "photos" ],
"textdomain": "default", "textdomain": "default",
@ -136,6 +137,9 @@
"default": { "default": {
"type": "flex" "type": "flex"
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-gallery-editor", "editorStyle": "wp-block-gallery-editor",

View File

@ -87,6 +87,9 @@
}, },
"layout": { "layout": {
"allowSizingOnChildren": true "allowSizingOnChildren": true
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-group-editor", "editorStyle": "wp-block-group-editor",

View File

@ -61,7 +61,10 @@
} }
}, },
"__unstablePasteTextInline": true, "__unstablePasteTextInline": true,
"__experimentalSlashInserter": true "__experimentalSlashInserter": true,
"interactivity": {
"clientNavigation": true
}
}, },
"editorStyle": "wp-block-heading-editor", "editorStyle": "wp-block-heading-editor",
"style": "wp-block-heading" "style": "wp-block-heading"

View File

@ -129,7 +129,10 @@ function block_core_home_link_build_li_wrapper_attributes( $context ) {
*/ */
function render_block_core_home_link( $attributes, $content, $block ) { function render_block_core_home_link( $attributes, $content, $block ) {
if ( empty( $attributes['label'] ) ) { if ( empty( $attributes['label'] ) ) {
return ''; // Using a fallback for the label attribute allows rendering the block even if no attributes have been set,
// e.g. when using the block as a hooked block.
// Note that the fallback value needs to be kept in sync with the one set in `edit.js` (upon first loading the block in the editor).
$attributes['label'] = __( 'Home' );
} }
$aria_current = ''; $aria_current = '';

View File

@ -36,6 +36,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-home-link-editor", "editorStyle": "wp-block-home-link-editor",

View File

@ -16,7 +16,10 @@
"supports": { "supports": {
"customClassName": false, "customClassName": false,
"className": false, "className": false,
"html": false "html": false,
"interactivity": {
"clientNavigation": true
}
}, },
"editorStyle": "wp-block-html-editor" "editorStyle": "wp-block-html-editor"
} }

View File

@ -20,26 +20,26 @@ function render_block_core_image( $attributes, $content, $block ) {
return ''; return '';
} }
$processor = new WP_HTML_Tag_Processor( $content ); $p = new WP_HTML_Tag_Processor( $content );
if ( ! $processor->next_tag( 'img' ) || null === $processor->get_attribute( 'src' ) ) { if ( ! $p->next_tag( 'img' ) || null === $p->get_attribute( 'src' ) ) {
return ''; return '';
} }
if ( isset( $attributes['data-id'] ) ) { if ( isset( $attributes['data-id'] ) ) {
// Add the data-id="$id" attribute to the img element // Adds the data-id="$id" attribute to the img element to provide backwards
// to provide backwards compatibility for the Gallery Block, // compatibility for the Gallery Block, which now wraps Image Blocks within
// which now wraps Image Blocks within innerBlocks. // innerBlocks. The data-id attribute is added in a core/gallery
// The data-id attribute is added in a core/gallery `render_block_data` hook. // `render_block_data` hook.
$processor->set_attribute( 'data-id', $attributes['data-id'] ); $p->set_attribute( 'data-id', $attributes['data-id'] );
} }
$link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none'; $link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none';
$lightbox_settings = block_core_image_get_lightbox_settings( $block->parsed_block ); $lightbox_settings = block_core_image_get_lightbox_settings( $block->parsed_block );
/* /*
* If the lightbox is enabled and the image is not linked, add the filter * If the lightbox is enabled and the image is not linked, adds the filter and
* and the JavaScript view file. * the JavaScript view file.
*/ */
if ( if (
isset( $lightbox_settings ) && isset( $lightbox_settings ) &&
@ -47,15 +47,27 @@ function render_block_core_image( $attributes, $content, $block ) {
isset( $lightbox_settings['enabled'] ) && isset( $lightbox_settings['enabled'] ) &&
true === $lightbox_settings['enabled'] true === $lightbox_settings['enabled']
) { ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/image.min.js' );
}
wp_register_script_module(
'@wordpress/block-library/image',
isset( $module_url ) ? $module_url : includes_url( "blocks/image/view{$suffix}.js" ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
wp_enqueue_script_module( '@wordpress/block-library/image' ); wp_enqueue_script_module( '@wordpress/block-library/image' );
/* /*
* This render needs to happen in a filter with priority 15 to ensure that * This render needs to happen in a filter with priority 15 to ensure that
* it runs after the duotone filter and that duotone styles are applied to * it runs after the duotone filter and that duotone styles are applied to
* the image in the lightbox. Lightbox has to work with any plugins that * the image in the lightbox. Lightbox has to work with any plugins that
* might use filters as well. Removing this can be considered in the * might use filters as well. Removing this can be considered in the future
* future if the way the blocks are rendered changes, or if a * if the way the blocks are rendered changes, or if a new kind of filter is
* new kind of filter is introduced. * introduced.
*/ */
add_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15, 2 ); add_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15, 2 );
} else { } else {
@ -65,7 +77,7 @@ function render_block_core_image( $attributes, $content, $block ) {
remove_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15 ); remove_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15 );
} }
return $processor->get_updated_html(); return $p->get_updated_html();
} }
/** /**
@ -78,7 +90,7 @@ function render_block_core_image( $attributes, $content, $block ) {
* @return array Filtered block data. * @return array Filtered block data.
*/ */
function block_core_image_get_lightbox_settings( $block ) { function block_core_image_get_lightbox_settings( $block ) {
// Get the lightbox setting from the block attributes. // Gets the lightbox setting from the block attributes.
if ( isset( $block['attrs']['lightbox'] ) ) { if ( isset( $block['attrs']['lightbox'] ) ) {
$lightbox_settings = $block['attrs']['lightbox']; $lightbox_settings = $block['attrs']['lightbox'];
} }
@ -89,9 +101,9 @@ function block_core_image_get_lightbox_settings( $block ) {
// If not present in global settings, check the top-level global settings. // If not present in global settings, check the top-level global settings.
// //
// NOTE: If no block-level settings are found, the previous call to // NOTE: If no block-level settings are found, the previous call to
// `wp_get_global_settings` will return the whole `theme.json` // `wp_get_global_settings` will return the whole `theme.json` structure in
// structure in which case we can check if the "lightbox" key is present at // which case we can check if the "lightbox" key is present at the top-level
// the top-level of the global settings and use its value. // of the global settings and use its value.
if ( isset( $lightbox_settings['lightbox'] ) ) { if ( isset( $lightbox_settings['lightbox'] ) ) {
$lightbox_settings = wp_get_global_settings( array( 'lightbox' ) ); $lightbox_settings = wp_get_global_settings( array( 'lightbox' ) );
} }
@ -110,103 +122,76 @@ function block_core_image_get_lightbox_settings( $block ) {
*/ */
function block_core_image_render_lightbox( $block_content, $block ) { function block_core_image_render_lightbox( $block_content, $block ) {
/* /*
* If it's not possible that an IMG element exists then return the given * If there's no IMG tag in the block then return the given block content
* block content as-is. It may be that there's no actual image in the block * as-is. There's nothing that this code can knowingly modify to add the
* or it could be that another plugin already modified this HTML. * lightbox behavior.
*/ */
if ( false === stripos( $block_content, '<img' ) ) { $p = new WP_HTML_Tag_Processor( $block_content );
if ( $p->next_tag( 'figure' ) ) {
$p->set_bookmark( 'figure' );
}
if ( ! $p->next_tag( 'img' ) ) {
return $block_content; return $block_content;
} }
$processor = new WP_HTML_Tag_Processor( $block_content ); $alt = $p->get_attribute( 'alt' );
$img_uploaded_src = $p->get_attribute( 'src' );
$img_class_names = $p->get_attribute( 'class' );
$img_styles = $p->get_attribute( 'style' );
$img_width = 'none';
$img_height = 'none';
$aria_label = __( 'Enlarge image' );
$aria_label = __( 'Enlarge image' ); if ( $alt ) {
/*
* If there's definitely no IMG element in the block then return the given
* block content as-is. There's nothing that this code can knowingly modify
* to add the lightbox behavior.
*/
if ( ! $processor->next_tag( 'img' ) ) {
return $block_content;
}
$alt_attribute = $processor->get_attribute( 'alt' );
// An empty alt attribute `alt=""` is valid for decorative images.
if ( is_string( $alt_attribute ) ) {
$alt_attribute = trim( $alt_attribute );
}
// It only makes sense to append the alt text to the button aria-label when the alt text is non-empty.
if ( $alt_attribute ) {
/* translators: %s: Image alt text. */ /* translators: %s: Image alt text. */
$aria_label = sprintf( __( 'Enlarge image: %s' ), $alt_attribute ); $aria_label = sprintf( __( 'Enlarge image: %s' ), $alt );
} }
// Currently, we are only enabling the zoom animation.
$lightbox_animation = 'zoom';
// Note: We want to store the `src` in the context so we
// can set it dynamically when the lightbox is opened.
if ( isset( $block['attrs']['id'] ) ) { if ( isset( $block['attrs']['id'] ) ) {
$img_uploaded_src = wp_get_attachment_url( $block['attrs']['id'] ); $img_uploaded_src = wp_get_attachment_url( $block['attrs']['id'] );
$img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] ); $img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] );
$img_width = $img_metadata['width'] ?? 'none'; $img_width = $img_metadata['width'] ?? 'none';
$img_height = $img_metadata['height'] ?? 'none'; $img_height = $img_metadata['height'] ?? 'none';
} else {
$img_uploaded_src = $processor->get_attribute( 'src' );
$img_width = 'none';
$img_height = 'none';
} }
if ( isset( $block['attrs']['scale'] ) ) { // Figure.
$scale_attr = $block['attrs']['scale']; $p->seek( 'figure' );
} else { $figure_class_names = $p->get_attribute( 'class' );
$scale_attr = false; $figure_styles = $p->get_attribute( 'style' );
} $p->add_class( 'wp-lightbox-container' );
$p->set_attribute( 'data-wp-interactive', '{"namespace":"core/image"}' );
$w = new WP_HTML_Tag_Processor( $block_content ); $p->set_attribute(
$w->next_tag( 'figure' );
$w->add_class( 'wp-lightbox-container' );
$w->set_attribute( 'data-wp-interactive', '{"namespace":"core/image"}' );
$w->set_attribute(
'data-wp-context', 'data-wp-context',
sprintf( wp_json_encode(
'{ "imageLoaded": false, array(
"initialized": false, 'uploadedSrc' => $img_uploaded_src,
"lightboxEnabled": false, 'figureClassNames' => $figure_class_names,
"hideAnimationEnabled": false, 'figureStyles' => $figure_styles,
"preloadInitialized": false, 'imgClassNames' => $img_class_names,
"lightboxAnimation": "%s", 'imgStyles' => $img_styles,
"imageUploadedSrc": "%s", 'targetWidth' => $img_width,
"imageCurrentSrc": "", 'targetHeight' => $img_height,
"targetWidth": "%s", 'scaleAttr' => $block['attrs']['scale'] ?? false,
"targetHeight": "%s", 'ariaLabel' => $aria_label,
"scaleAttr": "%s", 'alt' => $alt,
"dialogLabel": "%s" ),
}', JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
$lightbox_animation,
$img_uploaded_src,
$img_width,
$img_height,
$scale_attr,
__( 'Enlarged image' )
) )
); );
$w->next_tag( 'img' );
$w->set_attribute( 'data-wp-init', 'callbacks.initOriginImage' );
$w->set_attribute( 'data-wp-on--load', 'actions.handleLoad' );
$w->set_attribute( 'data-wp-watch', 'callbacks.setButtonStyles' );
// We need to set an event callback on the `img` specifically
// because the `figure` element can also contain a caption, and
// we don't want to trigger the lightbox when the caption is clicked.
$w->set_attribute( 'data-wp-on--click', 'actions.showLightbox' );
$w->set_attribute( 'data-wp-watch--setStylesOnResize', 'callbacks.setStylesOnResize' );
$body_content = $w->get_updated_html();
// Add a button alongside image in the body content. // Image.
$p->next_tag( 'img' );
$p->set_attribute( 'data-wp-init', 'callbacks.setButtonStyles' );
$p->set_attribute( 'data-wp-on--load', 'callbacks.setButtonStyles' );
$p->set_attribute( 'data-wp-on-window--resize', 'callbacks.setButtonStyles' );
// Sets an event callback on the `img` because the `figure` element can also
// contain a caption, and we don't want to trigger the lightbox when the
// caption is clicked.
$p->set_attribute( 'data-wp-on--click', 'actions.showLightbox' );
$body_content = $p->get_updated_html();
// Adds a button alongside image in the body content.
$img = null; $img = null;
preg_match( '/<img[^>]+>/', $body_content, $img ); preg_match( '/<img[^>]+>/', $body_content, $img );
@ -229,46 +214,17 @@ function block_core_image_render_lightbox( $block_content, $block ) {
$body_content = preg_replace( '/<img[^>]+>/', $button, $body_content ); $body_content = preg_replace( '/<img[^>]+>/', $button, $body_content );
// We need both a responsive image and an enlarged image to animate add_action( 'wp_footer', 'block_core_image_print_lightbox_overlay' );
// the zoom seamlessly on slow internet connections; the responsive
// image is a copy of the one in the body, which animates immediately
// as the lightbox is opened, while the enlarged one is a full-sized
// version that will likely still be loading as the animation begins.
$m = new WP_HTML_Tag_Processor( $block_content );
$m->next_tag( 'figure' );
$m->add_class( 'responsive-image' );
$m->next_tag( 'img' );
// We want to set the 'src' attribute to an empty string in the responsive image
// because otherwise, as of this writing, the wp_filter_content_tags() function in
// WordPress will automatically add a 'srcset' attribute to the image, which will at
// times cause the incorrectly sized image to be loaded in the lightbox on Firefox.
// Because of this, we bind the 'src' attribute explicitly the current src to reliably
// use the exact same image as in the content when the lightbox is first opened while
// we wait for the larger image to load.
$m->set_attribute( 'src', '' );
$m->set_attribute( 'data-wp-bind--src', 'context.imageCurrentSrc' );
$m->set_attribute( 'data-wp-style--object-fit', 'state.lightboxObjectFit' );
$initial_image_content = $m->get_updated_html();
$q = new WP_HTML_Tag_Processor( $block_content ); return $body_content;
$q->next_tag( 'figure' ); }
$q->add_class( 'enlarged-image' );
$q->next_tag( 'img' );
// We set the 'src' attribute to an empty string to prevent the browser from loading the image function block_core_image_print_lightbox_overlay() {
// on initial page load, then bind the attribute to a selector that returns the full-sized image src when $close_button_label = esc_attr__( 'Close' );
// the lightbox is opened. We could use 'loading=lazy' in combination with the 'hidden' attribute to
// accomplish the same behavior, but that approach breaks progressive loading of the image in Safari
// and Chrome (see https://github.com/WordPress/gutenberg/pull/52765#issuecomment-1674008151). Until that
// is resolved, manually setting the 'src' seems to be the best solution to load the large image on demand.
$q->set_attribute( 'src', '' );
$q->set_attribute( 'data-wp-bind--src', 'state.enlargedImgSrc' );
$q->set_attribute( 'data-wp-style--object-fit', 'state.lightboxObjectFit' );
$enlarged_image_content = $q->get_updated_html();
// If the current theme does NOT have a `theme.json`, or the colors are not defined, // If the current theme does NOT have a `theme.json`, or the colors are not
// we need to set the background color & close button color to some default values // defined, it needs to set the background color & close button color to some
// because we can't get them from the Global Styles. // default values because it can't get them from the Global Styles.
$background_color = '#fff'; $background_color = '#fff';
$close_button_color = '#000'; $close_button_color = '#000';
if ( wp_theme_has_theme_json() ) { if ( wp_theme_has_theme_json() ) {
@ -281,35 +237,43 @@ function block_core_image_render_lightbox( $block_content, $block ) {
} }
} }
$close_button_icon = '<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>'; echo <<<HTML
$close_button_label = esc_attr__( 'Close' ); <div
class="wp-lightbox-overlay zoom"
$lightbox_html = <<<HTML data-wp-interactive='{"namespace":"core/image"}'
<div data-wp-body="" class="wp-lightbox-overlay $lightbox_animation" data-wp-context='{}'
data-wp-bind--role="state.roleAttribute" data-wp-bind--role="state.roleAttribute"
data-wp-bind--aria-label="state.dialogLabel" data-wp-bind--aria-label="state.currentImage.ariaLabel"
data-wp-class--initialized="context.initialized" data-wp-bind--aria-modal="state.ariaModal"
data-wp-class--active="context.lightboxEnabled" data-wp-class--active="state.overlayEnabled"
data-wp-class--hideAnimationEnabled="context.hideAnimationEnabled" data-wp-class--show-closing-animation="state.showClosingAnimation"
data-wp-bind--aria-modal="state.ariaModal" data-wp-watch="callbacks.setOverlayFocus"
data-wp-watch="callbacks.initLightbox" data-wp-on--keydown="actions.handleKeydown"
data-wp-on--keydown="actions.handleKeydown" data-wp-on--touchstart="actions.handleTouchStart"
data-wp-on--touchstart="actions.handleTouchStart" data-wp-on--touchmove="actions.handleTouchMove"
data-wp-on--touchmove="actions.handleTouchMove" data-wp-on--touchend="actions.handleTouchEnd"
data-wp-on--touchend="actions.handleTouchEnd" data-wp-on--click="actions.hideLightbox"
data-wp-on--click="actions.hideLightbox" data-wp-on-window--resize="callbacks.setOverlayStyles"
tabindex="-1" data-wp-on-window--scroll="actions.handleScroll"
> tabindex="-1"
<button type="button" aria-label="$close_button_label" style="fill: $close_button_color" class="close-button" data-wp-on--click="actions.hideLightbox"> >
$close_button_icon <button type="button" aria-label="$close_button_label" style="fill: $close_button_color" class="close-button">
</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>
<div class="lightbox-image-container">$initial_image_content</div> </button>
<div class="lightbox-image-container">$enlarged_image_content</div> <div class="lightbox-image-container">
<div class="scrim" style="background-color: $background_color" aria-hidden="true"></div> <figure data-wp-bind--class="state.currentImage.figureClassNames" data-wp-bind--style="state.currentImage.figureStyles">
</div> <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">
</figure>
</div>
<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.enlargedSrc">
</figure>
</div>
<div class="scrim" style="background-color: $background_color" aria-hidden="true"></div>
<style data-wp-text="state.overlayStyles"></style>
</div>
HTML; HTML;
return str_replace( '</figure>', $lightbox_html . '</figure>', $body_content );
} }
/** /**
@ -322,12 +286,5 @@ function register_block_core_image() {
'render_callback' => 'render_block_core_image', 'render_callback' => 'render_block_core_image',
) )
); );
wp_register_script_module(
'@wordpress/block-library/image',
defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ? gutenberg_url( '/build/interactivity/image.min.js' ) : includes_url( 'blocks/image/view.min.js' ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
} }
add_action( 'init', 'register_block_core_image' ); add_action( 'init', 'register_block_core_image' );

View File

@ -117,10 +117,14 @@
"radius": true, "radius": true,
"width": true "width": true
} }
},
"shadow": {
"__experimentalSkipSerialization": true
} }
}, },
"selectors": { "selectors": {
"border": ".wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder", "border": ".wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder",
"shadow": ".wp-block-image img, .wp-block-image .wp-block-image__crop-area, .wp-block-image .components-placeholder",
"filter": { "filter": {
"duotone": ".wp-block-image img, .wp-block-image .components-placeholder" "duotone": ".wp-block-image img, .wp-block-image .components-placeholder"
} }

View File

@ -221,10 +221,10 @@
.wp-lightbox-overlay.active img{ .wp-lightbox-overlay.active img{
animation:turn-on-visibility .35s both; animation:turn-on-visibility .35s both;
} }
.wp-lightbox-overlay.hideanimationenabled:not(.active){ .wp-lightbox-overlay.show-closing-animation:not(.active){
animation:turn-off-visibility .35s both; animation:turn-off-visibility .35s both;
} }
.wp-lightbox-overlay.hideanimationenabled:not(.active) img{ .wp-lightbox-overlay.show-closing-animation:not(.active) img{
animation:turn-off-visibility .25s both; animation:turn-off-visibility .25s both;
} }
@media (prefers-reduced-motion:no-preference){ @media (prefers-reduced-motion:no-preference){
@ -242,16 +242,16 @@
.wp-lightbox-overlay.zoom.active .scrim{ .wp-lightbox-overlay.zoom.active .scrim{
animation:turn-on-visibility .4s forwards; animation:turn-on-visibility .4s forwards;
} }
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active){ .wp-lightbox-overlay.zoom.show-closing-animation:not(.active){
animation:none; animation:none;
} }
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active) .lightbox-image-container{ .wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .lightbox-image-container{
animation:lightbox-zoom-out .4s; animation:lightbox-zoom-out .4s;
} }
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active) .lightbox-image-container img{ .wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .lightbox-image-container img{
animation:none; animation:none;
} }
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active) .scrim{ .wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .scrim{
animation:turn-off-visibility .4s forwards; animation:turn-off-visibility .4s forwards;
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -221,10 +221,10 @@
.wp-lightbox-overlay.active img{ .wp-lightbox-overlay.active img{
animation:turn-on-visibility .35s both; animation:turn-on-visibility .35s both;
} }
.wp-lightbox-overlay.hideanimationenabled:not(.active){ .wp-lightbox-overlay.show-closing-animation:not(.active){
animation:turn-off-visibility .35s both; animation:turn-off-visibility .35s both;
} }
.wp-lightbox-overlay.hideanimationenabled:not(.active) img{ .wp-lightbox-overlay.show-closing-animation:not(.active) img{
animation:turn-off-visibility .25s both; animation:turn-off-visibility .25s both;
} }
@media (prefers-reduced-motion:no-preference){ @media (prefers-reduced-motion:no-preference){
@ -242,16 +242,16 @@
.wp-lightbox-overlay.zoom.active .scrim{ .wp-lightbox-overlay.zoom.active .scrim{
animation:turn-on-visibility .4s forwards; animation:turn-on-visibility .4s forwards;
} }
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active){ .wp-lightbox-overlay.zoom.show-closing-animation:not(.active){
animation:none; animation:none;
} }
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active) .lightbox-image-container{ .wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .lightbox-image-container{
animation:lightbox-zoom-out .4s; animation:lightbox-zoom-out .4s;
} }
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active) .lightbox-image-container img{ .wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .lightbox-image-container img{
animation:none; animation:none;
} }
.wp-lightbox-overlay.zoom.hideanimationenabled:not(.active) .scrim{ .wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .scrim{
animation:turn-off-visibility .4s forwards; animation:turn-off-visibility .4s forwards;
} }
} }

File diff suppressed because one or more lines are too long

View File

@ -32,242 +32,315 @@ const interactivity_namespaceObject = x({ ["getContext"]: () => __WEBPACK_EXTERN
* WordPress dependencies * WordPress dependencies
*/ */
const focusableSelectors = ['a[href]', 'area[href]', 'input:not([disabled]):not([type="hidden"]):not([aria-hidden])', 'select:not([disabled]):not([aria-hidden])', 'textarea:not([disabled]):not([aria-hidden])', 'button:not([disabled]):not([aria-hidden])', 'iframe', 'object', 'embed', '[contenteditable]', '[tabindex]:not([tabindex^="-"])'];
/** /**
* Stores a context-bound scroll handler. * Tracks whether user is touching screen; used to differentiate behavior for
* * touch and mouse input.
* This callback could be defined inline inside of the store
* object but it's created externally to avoid confusion about
* how its logic is called. This logic is not referenced directly
* by the directives in the markup because the scroll event we
* need to listen to is triggered on the window; so by defining it
* outside of the store, we signal that the behavior here is different.
* If we find a compelling reason to move it to the store, feel free.
*
* @type {Function}
*/
let scrollCallback;
/**
* Tracks whether user is touching screen; used to
* differentiate behavior for touch and mouse input.
* *
* @type {boolean} * @type {boolean}
*/ */
let isTouching = false; let isTouching = false;
/** /**
* Tracks the last time the screen was touched; used to * Tracks the last time the screen was touched; used to differentiate behavior
* differentiate behavior for touch and mouse input. * for touch and mouse input.
* *
* @type {number} * @type {number}
*/ */
let lastTouchTime = 0; let lastTouchTime = 0;
/** /**
* Lightbox page-scroll handler: prevents scrolling. * Stores the image reference of the currently opened lightbox.
* *
* This handler is added to prevent scrolling behaviors that * @type {HTMLElement}
* trigger content shift while the lightbox is open.
*
* It would be better to accomplish this through CSS alone, but
* using overflow: hidden is currently the only way to do so, and
* that causes the layout to shift and prevents the zoom animation
* from working in some cases because we're unable to account for
* the layout shift when doing the animation calculations. Instead,
* here we use JavaScript to prevent and reset the scrolling
* behavior. In the future, we may be able to use CSS or overflow: hidden
* instead to not rely on JavaScript, but this seems to be the best approach
* for now that provides the best visual experience.
*
* @param {Object} ctx Context object with the `core/image` namespace.
*/ */
function handleScroll(ctx) { let imageRef;
// We can't override the scroll behavior on mobile devices
// because doing so breaks the pinch to zoom functionality, and we /**
// want to allow users to zoom in further on the high-res image. * Stores the button reference of the currently opened lightbox.
if (!isTouching && Date.now() - lastTouchTime > 450) { *
// We are unable to use event.preventDefault() to prevent scrolling * @type {HTMLElement}
// because the scroll event can't be canceled, so we reset the position instead. */
window.scrollTo(ctx.scrollLeftReset, ctx.scrollTopReset); let buttonRef;
}
}
const { const {
state, state,
actions, actions,
callbacks callbacks
} = (0,interactivity_namespaceObject.store)('core/image', { } = (0,interactivity_namespaceObject.store)('core/image', {
state: { state: {
windowWidth: window.innerWidth, currentImage: {},
windowHeight: window.innerHeight, get overlayOpened() {
return state.currentImage.currentSrc;
},
get roleAttribute() { get roleAttribute() {
const ctx = (0,interactivity_namespaceObject.getContext)(); return state.overlayOpened ? 'dialog' : null;
return ctx.lightboxEnabled ? 'dialog' : null;
}, },
get ariaModal() { get ariaModal() {
const ctx = (0,interactivity_namespaceObject.getContext)(); return state.overlayOpened ? 'true' : null;
return ctx.lightboxEnabled ? 'true' : null;
}, },
get dialogLabel() { get enlargedSrc() {
const ctx = (0,interactivity_namespaceObject.getContext)(); return state.currentImage.uploadedSrc || 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
return ctx.lightboxEnabled ? ctx.dialogLabel : null;
}, },
get lightboxObjectFit() { get imgStyles() {
const ctx = (0,interactivity_namespaceObject.getContext)(); return state.overlayOpened && `${state.currentImage.imgStyles?.replace(/;$/, '')}; object-fit:cover;`;
if (ctx.initialized) {
return 'cover';
}
},
get enlargedImgSrc() {
const ctx = (0,interactivity_namespaceObject.getContext)();
return ctx.initialized ? ctx.imageUploadedSrc : 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
} }
}, },
actions: { actions: {
showLightbox(event) { showLightbox() {
const ctx = (0,interactivity_namespaceObject.getContext)(); const ctx = (0,interactivity_namespaceObject.getContext)();
// We can't initialize the lightbox until the reference
// image is loaded, otherwise the UX is broken. // Bails out if the image has not loaded yet.
if (!ctx.imageLoaded) { if (!ctx.imageRef?.complete) {
return; return;
} }
ctx.initialized = true;
ctx.lastFocusedElement = window.document.activeElement;
ctx.scrollDelta = 0;
ctx.pointerType = event.pointerType;
ctx.lightboxEnabled = true;
setStyles(ctx, ctx.imageRef);
ctx.scrollTopReset = window.pageYOffset || document.documentElement.scrollTop;
// In most cases, this value will be 0, but this is included // Stores the positons of the scroll to fix it until the overlay is
// in case a user has created a page with horizontal scrolling. // closed.
ctx.scrollLeftReset = window.pageXOffset || document.documentElement.scrollLeft; state.scrollTopReset = document.documentElement.scrollTop;
state.scrollLeftReset = document.documentElement.scrollLeft;
// We define and bind the scroll callback here so // Moves the information of the expaned image to the state.
// that we can pass the context and as an argument. ctx.currentSrc = ctx.imageRef.currentSrc;
// We may be able to change this in the future if we imageRef = ctx.imageRef;
// define the scroll callback in the store instead, but buttonRef = ctx.buttonRef;
// this approach seems to tbe clearest for now. state.currentImage = ctx;
scrollCallback = handleScroll.bind(null, ctx); state.overlayEnabled = true;
// We need to add a scroll event listener to the window // Computes the styles of the overlay for the animation.
// here because we are unable to otherwise access it via callbacks.setOverlayStyles();
// the Interactivity API directives. If we add a native way
// to access the window, we can remove this.
window.addEventListener('scroll', scrollCallback, false);
}, },
hideLightbox() { hideLightbox() {
const ctx = (0,interactivity_namespaceObject.getContext)(); if (state.overlayEnabled) {
ctx.hideAnimationEnabled = true; // Waits until the close animation has completed before allowing a
if (ctx.lightboxEnabled) { // user to scroll again. The duration of this animation is defined in
// We want to wait until the close animation is completed // the `styles.scss` file, but in any case we should wait a few
// before allowing a user to scroll again. The duration of this // milliseconds longer than the duration, otherwise a user may scroll
// animation is defined in the styles.scss and depends on if the // too soon and cause the animation to look sloppy.
// animation is 'zoom' or 'fade', but in any case we should wait
// a few milliseconds longer than the duration, otherwise a user
// may scroll too soon and cause the animation to look sloppy.
setTimeout(function () { setTimeout(function () {
window.removeEventListener('scroll', scrollCallback); // Delays before changing the focus. Otherwise the focus ring will
// If we don't delay before changing the focus, // appear on Firefox before the image has finished animating, which
// the focus ring will appear on Firefox before // looks broken.
// the image has finished animating, which looks broken. buttonRef.focus({
ctx.lightboxTriggerRef.focus({
preventScroll: true preventScroll: true
}); });
// Resets the current image to mark the overlay as closed.
state.currentImage = {};
imageRef = null;
buttonRef = null;
}, 450); }, 450);
ctx.lightboxEnabled = false;
// Starts the overlay closing animation. The showClosingAnimation
// class is used to avoid showing it on page load.
state.showClosingAnimation = true;
state.overlayEnabled = false;
} }
}, },
handleKeydown(event) { handleKeydown(event) {
const ctx = (0,interactivity_namespaceObject.getContext)(); if (state.overlayEnabled) {
if (ctx.lightboxEnabled) { // Focuses the close button when the user presses the tab key.
if (event.key === 'Tab' || event.keyCode === 9) { if (event.key === 'Tab') {
// If shift + tab it change the direction event.preventDefault();
if (event.shiftKey && window.document.activeElement === ctx.firstFocusableElement) { const {
event.preventDefault(); ref
ctx.lastFocusableElement.focus(); } = (0,interactivity_namespaceObject.getElement)();
} else if (!event.shiftKey && window.document.activeElement === ctx.lastFocusableElement) { ref.querySelector('button').focus();
event.preventDefault();
ctx.firstFocusableElement.focus();
}
} }
if (event.key === 'Escape' || event.keyCode === 27) { // Closes the lightbox when the user presses the escape key.
actions.hideLightbox(event); if (event.key === 'Escape') {
actions.hideLightbox();
} }
} }
}, },
// This is fired just by lazily loaded handleTouchMove(event) {
// images on the page, not all images. // On mobile devices, prevents triggering the scroll event because
handleLoad() { // otherwise the page jumps around when it resets the scroll position.
const ctx = (0,interactivity_namespaceObject.getContext)(); // This also means that closing the lightbox requires that a user
const { // perform a simple tap. This may be changed in the future if there is a
ref // better alternative to override or reset the scroll position during
} = (0,interactivity_namespaceObject.getElement)(); // swipe actions.
ctx.imageLoaded = true; if (state.overlayEnabled) {
ctx.imageCurrentSrc = ref.currentSrc; event.preventDefault();
callbacks.setButtonStyles(); }
}, },
handleTouchStart() { handleTouchStart() {
isTouching = true; isTouching = true;
}, },
handleTouchMove(event) {
const ctx = (0,interactivity_namespaceObject.getContext)();
// On mobile devices, we want to prevent triggering the
// scroll event because otherwise the page jumps around as
// we reset the scroll position. This also means that closing
// the lightbox requires that a user perform a simple tap. This
// may be changed in the future if we find a better alternative
// to override or reset the scroll position during swipe actions.
if (ctx.lightboxEnabled) {
event.preventDefault();
}
},
handleTouchEnd() { handleTouchEnd() {
// We need to wait a few milliseconds before resetting // Waits a few milliseconds before resetting to ensure that pinch to
// to ensure that pinch to zoom works consistently // zoom works consistently on mobile devices when the lightbox is open.
// on mobile devices when the lightbox is open.
lastTouchTime = Date.now(); lastTouchTime = Date.now();
isTouching = false; isTouching = false;
},
handleScroll() {
// Prevents scrolling behaviors that trigger content shift while the
// lightbox is open. It would be better to accomplish through CSS alone,
// but using overflow: hidden is currently the only way to do so and
// that causes a layout to shift and prevents the zoom animation from
// working in some cases because it's not possible to account for the
// layout shift when doing the animation calculations. Instead, it uses
// JavaScript to prevent and reset the scrolling behavior.
if (state.overlayOpened) {
// Avoids overriding the scroll behavior on mobile devices because
// doing so breaks the pinch to zoom functionality, and users should
// be able to zoom in further on the high-res image.
if (!isTouching && Date.now() - lastTouchTime > 450) {
// It doesn't rely on `event.preventDefault()` to prevent scrolling
// because the scroll event can't be canceled, so it resets the
// position instead.
window.scrollTo(state.scrollLeftReset, state.scrollTopReset);
}
}
} }
}, },
callbacks: { callbacks: {
initOriginImage() { setOverlayStyles() {
if (!imageRef) return;
let {
naturalWidth,
naturalHeight,
offsetWidth: originalWidth,
offsetHeight: originalHeight
} = imageRef;
let {
x: screenPosX,
y: screenPosY
} = imageRef.getBoundingClientRect();
// Natural ratio of the image clicked to open the lightbox.
const naturalRatio = naturalWidth / naturalHeight;
// Original ratio of the image clicked to open the lightbox.
let originalRatio = originalWidth / originalHeight;
// If it has object-fit: contain, recalculates the original sizes
// and the screen position without the blank spaces.
if (state.currentImage.scaleAttr === 'contain') {
if (naturalRatio > originalRatio) {
const heightWithoutSpace = originalWidth / naturalRatio;
// Recalculates screen position without the top space.
screenPosY += (originalHeight - heightWithoutSpace) / 2;
originalHeight = heightWithoutSpace;
} else {
const widthWithoutSpace = originalHeight * naturalRatio;
// Recalculates screen position without the left space.
screenPosX += (originalWidth - widthWithoutSpace) / 2;
originalWidth = widthWithoutSpace;
}
}
originalRatio = originalWidth / originalHeight;
// Typically, it uses the image's full-sized dimensions. If those
// dimensions have not been set (i.e. an external image with only one
// 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 : naturalWidth);
let imgMaxHeight = parseFloat(state.currentImage.targetHeight !== 'none' ? state.currentImage.targetHeight : naturalHeight);
// Ratio of the biggest image stored in the database.
let imgRatio = imgMaxWidth / imgMaxHeight;
let containerMaxWidth = imgMaxWidth;
let containerMaxHeight = imgMaxHeight;
let containerWidth = imgMaxWidth;
let containerHeight = imgMaxHeight;
// Checks if the target image has a different ratio than the original
// one (thumbnail). Recalculates the width and height.
if (naturalRatio.toFixed(2) !== imgRatio.toFixed(2)) {
if (naturalRatio > imgRatio) {
// If the width is reached before the height, it keeps the maxWidth
// and recalculates the height unless the difference between the
// maxHeight and the reducedHeight is higher than the maxWidth,
// where it keeps the reducedHeight and recalculate the width.
const reducedHeight = imgMaxWidth / naturalRatio;
if (imgMaxHeight - reducedHeight > imgMaxWidth) {
imgMaxHeight = reducedHeight;
imgMaxWidth = reducedHeight * naturalRatio;
} else {
imgMaxHeight = imgMaxWidth / naturalRatio;
}
} else {
// If the height is reached before the width, it keeps the maxHeight
// and recalculate the width unlesss the difference between the
// maxWidth and the reducedWidth is higher than the maxHeight, where
// it keeps the reducedWidth and recalculate the height.
const reducedWidth = imgMaxHeight * naturalRatio;
if (imgMaxWidth - reducedWidth > imgMaxHeight) {
imgMaxWidth = reducedWidth;
imgMaxHeight = reducedWidth / naturalRatio;
} else {
imgMaxWidth = imgMaxHeight * naturalRatio;
}
}
containerWidth = imgMaxWidth;
containerHeight = imgMaxHeight;
imgRatio = imgMaxWidth / imgMaxHeight;
// Calculates the max size of the container.
if (originalRatio > imgRatio) {
containerMaxWidth = imgMaxWidth;
containerMaxHeight = containerMaxWidth / originalRatio;
} else {
containerMaxHeight = imgMaxHeight;
containerMaxWidth = containerMaxHeight * originalRatio;
}
}
// If the image has been pixelated on purpose, it keeps that size.
if (originalWidth > containerWidth || originalHeight > containerHeight) {
containerWidth = originalWidth;
containerHeight = originalHeight;
}
// Calculates the final lightbox image size and the scale factor.
// MaxWidth is either the window container (accounting for padding) or
// the image resolution.
let horizontalPadding = 0;
if (window.innerWidth > 480) {
horizontalPadding = 80;
} else if (window.innerWidth > 1920) {
horizontalPadding = 160;
}
const verticalPadding = 80;
const targetMaxWidth = Math.min(window.innerWidth - horizontalPadding, containerWidth);
const targetMaxHeight = Math.min(window.innerHeight - verticalPadding, containerHeight);
const targetContainerRatio = targetMaxWidth / targetMaxHeight;
if (originalRatio > targetContainerRatio) {
// If targetMaxWidth is reached before targetMaxHeight.
containerWidth = targetMaxWidth;
containerHeight = containerWidth / originalRatio;
} else {
// If targetMaxHeight is reached before targetMaxWidth.
containerHeight = targetMaxHeight;
containerWidth = containerHeight * originalRatio;
}
const containerScale = originalWidth / containerWidth;
const lightboxImgWidth = imgMaxWidth * (containerWidth / containerMaxWidth);
const lightboxImgHeight = imgMaxHeight * (containerHeight / containerMaxHeight);
// As of this writing, using the calculations above will render the
// lightbox with a small, erroneous whitespace on the left side of the
// image in iOS Safari, perhaps due to an inconsistency in how browsers
// handle absolute positioning and CSS transformation. In any case,
// adding 1 pixel to the container width and height solves the problem,
// though this can be removed if the issue is fixed in the future.
state.overlayStyles = `
:root {
--wp--lightbox-initial-top-position: ${screenPosY}px;
--wp--lightbox-initial-left-position: ${screenPosX}px;
--wp--lightbox-container-width: ${containerWidth + 1}px;
--wp--lightbox-container-height: ${containerHeight + 1}px;
--wp--lightbox-image-width: ${lightboxImgWidth}px;
--wp--lightbox-image-height: ${lightboxImgHeight}px;
--wp--lightbox-scale: ${containerScale};
--wp--lightbox-scrollbar-width: ${window.innerWidth - document.documentElement.clientWidth}px;
}
`;
},
setButtonStyles() {
const ctx = (0,interactivity_namespaceObject.getContext)(); const ctx = (0,interactivity_namespaceObject.getContext)();
const { const {
ref ref
} = (0,interactivity_namespaceObject.getElement)(); } = (0,interactivity_namespaceObject.getElement)();
ctx.imageRef = ref; ctx.imageRef = ref;
if (ref.complete) {
ctx.imageLoaded = true;
ctx.imageCurrentSrc = ref.currentSrc;
}
},
initTriggerButton() {
const ctx = (0,interactivity_namespaceObject.getContext)();
const {
ref
} = (0,interactivity_namespaceObject.getElement)();
ctx.lightboxTriggerRef = ref;
},
initLightbox() {
const ctx = (0,interactivity_namespaceObject.getContext)();
const {
ref
} = (0,interactivity_namespaceObject.getElement)();
if (ctx.lightboxEnabled) {
const focusableElements = ref.querySelectorAll(focusableSelectors);
ctx.firstFocusableElement = focusableElements[0];
ctx.lastFocusableElement = focusableElements[focusableElements.length - 1];
// Move focus to the dialog when opening it.
ref.focus();
}
},
setButtonStyles() {
const {
ref
} = (0,interactivity_namespaceObject.getElement)();
const { const {
naturalWidth, naturalWidth,
naturalHeight, naturalHeight,
@ -275,18 +348,17 @@ const {
offsetHeight offsetHeight
} = ref; } = ref;
// If the image isn't loaded yet, we can't // If the image isn't loaded yet, it can't calculate where the button
// calculate where the button should be. // should be.
if (naturalWidth === 0 || naturalHeight === 0) { if (naturalWidth === 0 || naturalHeight === 0) {
return; return;
} }
const figure = ref.parentElement; const figure = ref.parentElement;
const figureWidth = ref.parentElement.clientWidth; const figureWidth = ref.parentElement.clientWidth;
// We need special handling for the height because // It needs special handling for the height because a caption will cause
// a caption will cause the figure to be taller than // the figure to be taller than the image, which means it needs to
// the image, which means we need to account for that // account for that when calculating the placement of the button in the
// when calculating the placement of the button in the
// top right corner of the image. // top right corner of the image.
let figureHeight = ref.parentElement.clientHeight; let figureHeight = ref.parentElement.clientHeight;
const caption = figure.querySelector('figcaption'); const caption = figure.querySelector('figcaption');
@ -298,25 +370,24 @@ const {
} }
const buttonOffsetTop = figureHeight - offsetHeight; const buttonOffsetTop = figureHeight - offsetHeight;
const buttonOffsetRight = figureWidth - offsetWidth; const buttonOffsetRight = figureWidth - offsetWidth;
const ctx = (0,interactivity_namespaceObject.getContext)();
// In the case of an image with object-fit: contain, the // In the case of an image with object-fit: contain, the size of the
// size of the <img> element can be larger than the image itself, // <img> element can be larger than the image itself, so it needs to
// so we need to calculate where to place the button. // calculate where to place the button.
if (ctx.scaleAttr === 'contain') { if (ctx.scaleAttr === 'contain') {
// Natural ratio of the image. // Natural ratio of the image.
const naturalRatio = naturalWidth / naturalHeight; const naturalRatio = naturalWidth / naturalHeight;
// Offset ratio of the image. // Offset ratio of the image.
const offsetRatio = offsetWidth / offsetHeight; const offsetRatio = offsetWidth / offsetHeight;
if (naturalRatio >= offsetRatio) { if (naturalRatio >= offsetRatio) {
// If it reaches the width first, keep // If it reaches the width first, it keeps the width and compute the
// the width and compute the height. // height.
const referenceHeight = offsetWidth / naturalRatio; const referenceHeight = offsetWidth / naturalRatio;
ctx.imageButtonTop = (offsetHeight - referenceHeight) / 2 + buttonOffsetTop + 16; ctx.imageButtonTop = (offsetHeight - referenceHeight) / 2 + buttonOffsetTop + 16;
ctx.imageButtonRight = buttonOffsetRight + 16; ctx.imageButtonRight = buttonOffsetRight + 16;
} else { } else {
// If it reaches the height first, keep // If it reaches the height first, it keeps the height and compute
// the height and compute the width. // the width.
const referenceWidth = offsetHeight * naturalRatio; const referenceWidth = offsetHeight * naturalRatio;
ctx.imageButtonTop = buttonOffsetTop + 16; ctx.imageButtonTop = buttonOffsetTop + 16;
ctx.imageButtonRight = (offsetWidth - referenceWidth) / 2 + buttonOffsetRight + 16; ctx.imageButtonRight = (offsetWidth - referenceWidth) / 2 + buttonOffsetRight + 16;
@ -326,197 +397,24 @@ const {
ctx.imageButtonRight = buttonOffsetRight + 16; ctx.imageButtonRight = buttonOffsetRight + 16;
} }
}, },
setStylesOnResize() { setOverlayFocus() {
if (state.overlayEnabled) {
// Moves the focus to the dialog when it opens.
const {
ref
} = (0,interactivity_namespaceObject.getElement)();
ref.focus();
}
},
initTriggerButton() {
const ctx = (0,interactivity_namespaceObject.getContext)(); const ctx = (0,interactivity_namespaceObject.getContext)();
const { const {
ref ref
} = (0,interactivity_namespaceObject.getElement)(); } = (0,interactivity_namespaceObject.getElement)();
if (ctx.lightboxEnabled && (state.windowWidth || state.windowHeight)) { ctx.buttonRef = ref;
setStyles(ctx, ref);
}
} }
} }
}, {
lock: true
}); });
window.addEventListener('resize', debounce(() => {
state.windowWidth = window.innerWidth;
state.windowHeight = window.innerHeight;
}));
/**
* Computes styles for the lightbox and adds them to the document.
*
* @function
* @param {Object} ctx - Context for the `core/image` namespace.
* @param {Object} ref - The element reference.
*/
function setStyles(ctx, ref) {
// The reference img element lies adjacent
// to the event target button in the DOM.
let {
naturalWidth,
naturalHeight,
offsetWidth: originalWidth,
offsetHeight: originalHeight
} = ref;
let {
x: screenPosX,
y: screenPosY
} = ref.getBoundingClientRect();
// Natural ratio of the image clicked to open the lightbox.
const naturalRatio = naturalWidth / naturalHeight;
// Original ratio of the image clicked to open the lightbox.
let originalRatio = originalWidth / originalHeight;
// If it has object-fit: contain, recalculate the original sizes
// and the screen position without the blank spaces.
if (ctx.scaleAttr === 'contain') {
if (naturalRatio > originalRatio) {
const heightWithoutSpace = originalWidth / naturalRatio;
// Recalculate screen position without the top space.
screenPosY += (originalHeight - heightWithoutSpace) / 2;
originalHeight = heightWithoutSpace;
} else {
const widthWithoutSpace = originalHeight * naturalRatio;
// Recalculate screen position without the left space.
screenPosX += (originalWidth - widthWithoutSpace) / 2;
originalWidth = widthWithoutSpace;
}
}
originalRatio = originalWidth / originalHeight;
// Typically, we use the image's full-sized dimensions. If those
// dimensions have not been set (i.e. an external image with only one size),
// the image's dimensions in the lightbox are the same
// as those of the image in the content.
let imgMaxWidth = parseFloat(ctx.targetWidth !== 'none' ? ctx.targetWidth : naturalWidth);
let imgMaxHeight = parseFloat(ctx.targetHeight !== 'none' ? ctx.targetHeight : naturalHeight);
// Ratio of the biggest image stored in the database.
let imgRatio = imgMaxWidth / imgMaxHeight;
let containerMaxWidth = imgMaxWidth;
let containerMaxHeight = imgMaxHeight;
let containerWidth = imgMaxWidth;
let containerHeight = imgMaxHeight;
// Check if the target image has a different ratio than the original one (thumbnail).
// Recalculate the width and height.
if (naturalRatio.toFixed(2) !== imgRatio.toFixed(2)) {
if (naturalRatio > imgRatio) {
// If the width is reached before the height, we keep the maxWidth
// and recalculate the height.
// Unless the difference between the maxHeight and the reducedHeight
// is higher than the maxWidth, where we keep the reducedHeight and
// recalculate the width.
const reducedHeight = imgMaxWidth / naturalRatio;
if (imgMaxHeight - reducedHeight > imgMaxWidth) {
imgMaxHeight = reducedHeight;
imgMaxWidth = reducedHeight * naturalRatio;
} else {
imgMaxHeight = imgMaxWidth / naturalRatio;
}
} else {
// If the height is reached before the width, we keep the maxHeight
// and recalculate the width.
// Unless the difference between the maxWidth and the reducedWidth
// is higher than the maxHeight, where we keep the reducedWidth and
// recalculate the height.
const reducedWidth = imgMaxHeight * naturalRatio;
if (imgMaxWidth - reducedWidth > imgMaxHeight) {
imgMaxWidth = reducedWidth;
imgMaxHeight = reducedWidth / naturalRatio;
} else {
imgMaxWidth = imgMaxHeight * naturalRatio;
}
}
containerWidth = imgMaxWidth;
containerHeight = imgMaxHeight;
imgRatio = imgMaxWidth / imgMaxHeight;
// Calculate the max size of the container.
if (originalRatio > imgRatio) {
containerMaxWidth = imgMaxWidth;
containerMaxHeight = containerMaxWidth / originalRatio;
} else {
containerMaxHeight = imgMaxHeight;
containerMaxWidth = containerMaxHeight * originalRatio;
}
}
// If the image has been pixelated on purpose, keep that size.
if (originalWidth > containerWidth || originalHeight > containerHeight) {
containerWidth = originalWidth;
containerHeight = originalHeight;
}
// Calculate the final lightbox image size and the
// scale factor. MaxWidth is either the window container
// (accounting for padding) or the image resolution.
let horizontalPadding = 0;
if (window.innerWidth > 480) {
horizontalPadding = 80;
} else if (window.innerWidth > 1920) {
horizontalPadding = 160;
}
const verticalPadding = 80;
const targetMaxWidth = Math.min(window.innerWidth - horizontalPadding, containerWidth);
const targetMaxHeight = Math.min(window.innerHeight - verticalPadding, containerHeight);
const targetContainerRatio = targetMaxWidth / targetMaxHeight;
if (originalRatio > targetContainerRatio) {
// If targetMaxWidth is reached before targetMaxHeight
containerWidth = targetMaxWidth;
containerHeight = containerWidth / originalRatio;
} else {
// If targetMaxHeight is reached before targetMaxWidth
containerHeight = targetMaxHeight;
containerWidth = containerHeight * originalRatio;
}
const containerScale = originalWidth / containerWidth;
const lightboxImgWidth = imgMaxWidth * (containerWidth / containerMaxWidth);
const lightboxImgHeight = imgMaxHeight * (containerHeight / containerMaxHeight);
// Add the CSS variables needed.
let styleTag = document.getElementById('wp-lightbox-styles');
if (!styleTag) {
styleTag = document.createElement('style');
styleTag.id = 'wp-lightbox-styles';
document.head.appendChild(styleTag);
}
// As of this writing, using the calculations above will render the lightbox
// with a small, erroneous whitespace on the left side of the image in iOS Safari,
// perhaps due to an inconsistency in how browsers handle absolute positioning and CSS
// transformation. In any case, adding 1 pixel to the container width and height solves
// the problem, though this can be removed if the issue is fixed in the future.
styleTag.innerHTML = `
:root {
--wp--lightbox-initial-top-position: ${screenPosY}px;
--wp--lightbox-initial-left-position: ${screenPosX}px;
--wp--lightbox-container-width: ${containerWidth + 1}px;
--wp--lightbox-container-height: ${containerHeight + 1}px;
--wp--lightbox-image-width: ${lightboxImgWidth}px;
--wp--lightbox-image-height: ${lightboxImgHeight}px;
--wp--lightbox-scale: ${containerScale};
--wp--lightbox-scrollbar-width: ${window.innerWidth - document.documentElement.clientWidth}px;
}
`;
}
/**
* Debounces a function call.
*
* @function
* @param {Function} func - A function to be called
* @param {number} wait - The time to wait before calling the function
*/
function debounce(func, wait = 50) {
let timeout;
return () => {
const later = () => {
timeout = null;
func();
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}

File diff suppressed because one or more lines are too long

View File

@ -46,6 +46,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-latest-comments-editor", "editorStyle": "wp-block-latest-comments-editor",

View File

@ -110,6 +110,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-latest-posts-editor", "editorStyle": "wp-block-latest-posts-editor",

View File

@ -5,6 +5,7 @@
"title": "List item", "title": "List item",
"category": "text", "category": "text",
"parent": [ "core/list" ], "parent": [ "core/list" ],
"allowedBlocks": [ "core/list" ],
"description": "Create a list item.", "description": "Create a list item.",
"textdomain": "default", "textdomain": "default",
"attributes": { "attributes": {
@ -41,6 +42,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -4,6 +4,7 @@
"name": "core/list", "name": "core/list",
"title": "List", "title": "List",
"category": "text", "category": "text",
"allowedBlocks": [ "core/list-item" ],
"description": "Create a bulleted or numbered list.", "description": "Create a bulleted or numbered list.",
"keywords": [ "bullet list", "ordered list", "numbered list" ], "keywords": [ "bullet list", "ordered list", "numbered list" ],
"textdomain": "default", "textdomain": "default",
@ -70,7 +71,10 @@
"__unstablePasteTextInline": true, "__unstablePasteTextInline": true,
"__experimentalSelector": "ol,ul", "__experimentalSelector": "ol,ul",
"__experimentalOnMerge": true, "__experimentalOnMerge": true,
"__experimentalSlashInserter": true "__experimentalSlashInserter": true,
"interactivity": {
"clientNavigation": true
}
}, },
"editorStyle": "wp-block-list-editor", "editorStyle": "wp-block-list-editor",
"style": "wp-block-list" "style": "wp-block-list"

View File

@ -39,6 +39,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -123,6 +123,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-media-text-editor", "editorStyle": "wp-block-media-text-editor",

View File

@ -23,6 +23,9 @@
"customClassName": false, "customClassName": false,
"inserter": false, "inserter": false,
"html": false, "html": false,
"reusable": false "reusable": false,
"interactivity": {
"clientNavigation": true
}
} }
} }

View File

@ -20,7 +20,10 @@
"customClassName": false, "customClassName": false,
"className": false, "className": false,
"html": false, "html": false,
"multiple": false "multiple": false,
"interactivity": {
"clientNavigation": true
}
}, },
"editorStyle": "wp-block-more-editor" "editorStyle": "wp-block-more-editor"
} }

View File

@ -132,6 +132,10 @@ function block_core_navigation_link_maybe_urldecode( $url ) {
$query_params = wp_parse_args( $query ); $query_params = wp_parse_args( $query );
foreach ( $query_params as $query_param ) { foreach ( $query_params as $query_param ) {
$can_query_param_be_encoded = is_string( $query_param ) && ! empty( $query_param );
if ( ! $can_query_param_be_encoded ) {
continue;
}
if ( rawurldecode( $query_param ) !== $query_param ) { if ( rawurldecode( $query_param ) !== $query_param ) {
$is_url_encoded = true; $is_url_encoded = true;
break; break;
@ -323,70 +327,40 @@ function build_variation_for_navigation_link( $entity, $kind ) {
} }
/** /**
* Register a variation for a post type / taxonomy for the navigation link block. * Filters the registered variations for a block type.
* Returns the dynamically built variations for all post-types and taxonomies.
* *
* @param array $variation Variation array from build_variation_for_navigation_link. * @since 6.5.0
* @return void *
* @param array $variations Array of registered variations for a block type.
* @param WP_Block_Type $block_type The full block type object.
*/ */
function block_core_navigation_link_register_variation( $variation ) { function block_core_navigation_link_filter_variations( $variations, $block_type ) {
// Directly set the variations on the registered block type if ( 'core/navigation-link' !== $block_type->name ) {
// because there's no server side registration for variations (see #47170). return $variations;
$navigation_block_type = WP_Block_Type_Registry::get_instance()->get_registered( 'core/navigation-link' );
// If the block is not registered yet, bail early.
// Variation will be registered in register_block_core_navigation_link then.
if ( ! $navigation_block_type ) {
return;
} }
$navigation_block_type->variations = array_merge( $generated_variations = block_core_navigation_link_build_variations();
$navigation_block_type->variations, return array_merge( $variations, $generated_variations );
array( $variation )
);
} }
/** /**
* Unregister a variation for a post type / taxonomy for the navigation link block.
*
* @param string $name Name of the post type / taxonomy (which was used as variation name).
* @return void
*/
function block_core_navigation_link_unregister_variation( $name ) {
// Directly get the variations from the registered block type
// because there's no server side (un)registration for variations (see #47170).
$navigation_block_type = WP_Block_Type_Registry::get_instance()->get_registered( 'core/navigation-link' );
// If the block is not registered (yet), there's no need to remove a variation.
if ( ! $navigation_block_type || empty( $navigation_block_type->variations ) ) {
return;
}
$variations = $navigation_block_type->variations;
// Search for the variation and remove it from the array.
foreach ( $variations as $i => $variation ) {
if ( $variation['name'] === $name ) {
unset( $variations[ $i ] );
break;
}
}
// Reindex array after removing one variation.
$navigation_block_type->variations = array_values( $variations );
}
/**
* Register the navigation link block.
* Returns an array of variations for the navigation link block. * Returns an array of variations for the navigation link block.
* *
* @since 6.5.0
*
* @return array * @return array
*/ */
function build_navigation_link_block_variations() { function block_core_navigation_link_build_variations() {
// This will only handle post types and taxonomies registered until this point (init on priority 9).
// See action hooks below for other post types and taxonomies.
// See https://github.com/WordPress/gutenberg/issues/53826 for details.
$post_types = get_post_types( array( 'show_in_nav_menus' => true ), 'objects' ); $post_types = get_post_types( array( 'show_in_nav_menus' => true ), 'objects' );
$taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'objects' ); $taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'objects' );
// Use two separate arrays as a way to order the variations in the UI. /*
// Known variations (like Post Link and Page Link) are added to the * Use two separate arrays as a way to order the variations in the UI.
// `built_ins` array. Variations for custom post types and taxonomies are * Known variations (like Post Link and Page Link) are added to the
// added to the `variations` array and will always appear after `built-ins. * `built_ins` array. Variations for custom post types and taxonomies are
* added to the `variations` array and will always appear after `built-ins.
*/
$built_ins = array(); $built_ins = array();
$variations = array(); $variations = array();
@ -415,76 +389,23 @@ function build_navigation_link_block_variations() {
} }
/** /**
* Register the navigation link block. * Registers the navigation link block.
* *
* @uses render_block_core_navigation() * @uses render_block_core_navigation_link()
* @uses build_navigation_link_block_variations()
* @throws WP_Error An WP_Error exception parsing the block definition. * @throws WP_Error An WP_Error exception parsing the block definition.
*/ */
function register_block_core_navigation_link() { function register_block_core_navigation_link() {
register_block_type_from_metadata( register_block_type_from_metadata(
__DIR__ . '/navigation-link', __DIR__ . '/navigation-link',
array( array(
'render_callback' => 'render_block_core_navigation_link', 'render_callback' => 'render_block_core_navigation_link',
'variation_callback' => 'build_navigation_link_block_variations',
) )
); );
} }
add_action( 'init', 'register_block_core_navigation_link' ); add_action( 'init', 'register_block_core_navigation_link' );
// Register actions for all post types and taxonomies, to add variations when they are registered.
// All post types/taxonomies registered before register_block_core_navigation_link, will be handled by that function.
add_action( 'registered_post_type', 'block_core_navigation_link_register_post_type_variation', 10, 2 );
add_action( 'registered_taxonomy', 'block_core_navigation_link_register_taxonomy_variation', 10, 3 );
// Handle unregistering of post types and taxonomies and remove the variations.
add_action( 'unregistered_post_type', 'block_core_navigation_link_unregister_post_type_variation' );
add_action( 'unregistered_taxonomy', 'block_core_navigation_link_unregister_taxonomy_variation' );
/** /**
* Register custom post type variations for navigation link on post type registration * Creates all variations for post types / taxonomies dynamically (= each time when variations are requested).
* Handles all post types registered after the block is registered in register_navigation_link_post_type_variations * Do not use variation_callback, to also account for unregistering post types/taxonomies later on.
*
* @param string $post_type The post type name passed from registered_post_type action hook.
* @param WP_Post_Type $post_type_object The post type object passed from registered_post_type.
* @return void
*/ */
function block_core_navigation_link_register_post_type_variation( $post_type, $post_type_object ) { add_action( 'get_block_type_variations', 'block_core_navigation_link_filter_variations', 10, 2 );
if ( $post_type_object->show_in_nav_menus ) {
$variation = build_variation_for_navigation_link( $post_type_object, 'post-type' );
block_core_navigation_link_register_variation( $variation );
}
}
/**
* Register a custom taxonomy variation for navigation link on taxonomy registration
* Handles all taxonomies registered after the block is registered in register_navigation_link_post_type_variations
*
* @param string $taxonomy Taxonomy slug.
* @param array|string $object_type Object type or array of object types.
* @param array $args Array of taxonomy registration arguments.
* @return void
*/
function block_core_navigation_link_register_taxonomy_variation( $taxonomy, $object_type, $args ) {
if ( isset( $args['show_in_nav_menus'] ) && $args['show_in_nav_menus'] ) {
$variation = build_variation_for_navigation_link( (object) $args, 'post-type' );
block_core_navigation_link_register_variation( $variation );
}
}
/**
* Unregisters a custom post type variation for navigation link on post type unregistration.
*
* @param string $post_type The post type name passed from unregistered_post_type action hook.
* @return void
*/
function block_core_navigation_link_unregister_post_type_variation( $post_type ) {
block_core_navigation_link_unregister_variation( $post_type );
}
/**
* Unregisters a custom taxonomy variation for navigation link on taxonomy unregistration.
*
* @param string $taxonomy The taxonomy name passed from unregistered_taxonomy action hook.
* @return void
*/
function block_core_navigation_link_unregister_taxonomy_variation( $taxonomy ) {
block_core_navigation_link_unregister_variation( $taxonomy );
}

View File

@ -5,6 +5,11 @@
"title": "Custom Link", "title": "Custom Link",
"category": "design", "category": "design",
"parent": [ "core/navigation" ], "parent": [ "core/navigation" ],
"allowedBlocks": [
"core/navigation-link",
"core/navigation-submenu",
"core/page-list"
],
"description": "Add a page, link, or another item to your navigation.", "description": "Add a page, link, or another item to your navigation.",
"textdomain": "default", "textdomain": "default",
"attributes": { "attributes": {
@ -72,7 +77,10 @@
"fontSize": true "fontSize": true
} }
}, },
"renaming": false "renaming": false,
"interactivity": {
"clientNavigation": true
}
}, },
"editorStyle": "wp-block-navigation-link-editor", "editorStyle": "wp-block-navigation-link-editor",
"style": "wp-block-navigation-link" "style": "wp-block-navigation-link"

View File

@ -3,4 +3,26 @@
} }
.wp-block-navigation .wp-block-navigation-item__description{ .wp-block-navigation .wp-block-navigation-item__description{
display:none; display:none;
}
.link-ui-tools{
border-top:1px solid #f0f0f0;
padding:8px;
}
.link-ui-block-inserter{
padding-top:8px;
}
.link-ui-block-inserter__back{
margin-right:8px;
text-transform:uppercase;
}
.components-popover-pointer-events-trap{
background-color:initial;
cursor:pointer;
inset:0;
position:fixed;
z-index:1000000;
} }

View File

@ -1 +1 @@
.wp-block-navigation .wp-block-navigation-item__label{overflow-wrap:break-word}.wp-block-navigation .wp-block-navigation-item__description{display:none} .wp-block-navigation .wp-block-navigation-item__label{overflow-wrap:break-word}.wp-block-navigation .wp-block-navigation-item__description{display:none}.link-ui-tools{border-top:1px solid #f0f0f0;padding:8px}.link-ui-block-inserter{padding-top:8px}.link-ui-block-inserter__back{margin-right:8px;text-transform:uppercase}.components-popover-pointer-events-trap{background-color:initial;cursor:pointer;inset:0;position:fixed;z-index:1000000}

View File

@ -3,4 +3,26 @@
} }
.wp-block-navigation .wp-block-navigation-item__description{ .wp-block-navigation .wp-block-navigation-item__description{
display:none; display:none;
}
.link-ui-tools{
border-top:1px solid #f0f0f0;
padding:8px;
}
.link-ui-block-inserter{
padding-top:8px;
}
.link-ui-block-inserter__back{
margin-left:8px;
text-transform:uppercase;
}
.components-popover-pointer-events-trap{
background-color:initial;
cursor:pointer;
inset:0;
position:fixed;
z-index:1000000;
} }

View File

@ -1 +1 @@
.wp-block-navigation .wp-block-navigation-item__label{overflow-wrap:break-word}.wp-block-navigation .wp-block-navigation-item__description{display:none} .wp-block-navigation .wp-block-navigation-item__label{overflow-wrap:break-word}.wp-block-navigation .wp-block-navigation-item__description{display:none}.link-ui-tools{border-top:1px solid #f0f0f0;padding:8px}.link-ui-block-inserter{padding-top:8px}.link-ui-block-inserter__back{margin-left:8px;text-transform:uppercase}.components-popover-pointer-events-trap{background-color:initial;cursor:pointer;inset:0;position:fixed;z-index:1000000}

View File

@ -58,7 +58,10 @@
], ],
"supports": { "supports": {
"reusable": false, "reusable": false,
"html": false "html": false,
"interactivity": {
"clientNavigation": true
}
}, },
"editorStyle": "wp-block-navigation-submenu-editor", "editorStyle": "wp-block-navigation-submenu-editor",
"style": "wp-block-navigation-submenu" "style": "wp-block-navigation-submenu"

View File

@ -9,18 +9,11 @@
* Helper functions used to render the navigation block. * Helper functions used to render the navigation block.
*/ */
class WP_Navigation_Block_Renderer { class WP_Navigation_Block_Renderer {
/** /**
* Used to determine which blocks are wrapped in an <li>. * Used to determine whether or not a navigation has submenus.
*
* @var array
*/ */
private static $nav_blocks_wrapped_in_list_item = array( private static $has_submenus = false;
'core/navigation-link',
'core/home-link',
'core/site-title',
'core/site-logo',
'core/navigation-submenu',
);
/** /**
* Used to determine which blocks need an <li> wrapper. * Used to determine which blocks need an <li> wrapper.
@ -58,22 +51,37 @@ class WP_Navigation_Block_Renderer {
* Returns whether or not a navigation has a submenu. * Returns whether or not a navigation has a submenu.
* *
* @param WP_Block_List $inner_blocks The list of inner blocks. * @param WP_Block_List $inner_blocks The list of inner blocks.
* @return bool Returns whether or not a navigation has a submenu. * @return bool Returns whether or not a navigation has a submenu and also sets the member variable.
*/ */
private static function has_submenus( $inner_blocks ) { private static function has_submenus( $inner_blocks ) {
if ( true === static::$has_submenus ) {
return static::$has_submenus;
}
foreach ( $inner_blocks as $inner_block ) { foreach ( $inner_blocks as $inner_block ) {
$inner_block_content = $inner_block->render(); // If this is a page list then work out if any of the pages have children.
$p = new WP_HTML_Tag_Processor( $inner_block_content ); if ( 'core/page-list' === $inner_block->name ) {
if ( $p->next_tag( $all_pages = get_pages(
array( array(
'name' => 'LI', 'sort_column' => 'menu_order,post_title',
'class_name' => 'has-child', 'order' => 'asc',
) )
) ) { );
return true; foreach ( (array) $all_pages as $page ) {
if ( $page->post_parent ) {
static::$has_submenus = true;
break;
}
}
}
// If this is a navigation submenu then we know we have submenus.
if ( 'core/navigation-submenu' === $inner_block->name ) {
static::$has_submenus = true;
break;
} }
} }
return false;
return static::$has_submenus;
} }
/** /**
@ -96,7 +104,23 @@ class WP_Navigation_Block_Renderer {
* @return bool Returns whether or not a block needs a list item wrapper. * @return bool Returns whether or not a block needs a list item wrapper.
*/ */
private static function does_block_need_a_list_item_wrapper( $block ) { private static function does_block_need_a_list_item_wrapper( $block ) {
return in_array( $block->name, static::$needs_list_item_wrapper, true );
/**
* Filter the list of blocks that need a list item wrapper.
*
* Affords the ability to customize which blocks need a list item wrapper when rendered
* within a core/navigation block.
* This is useful for blocks that are not list items but should be wrapped in a list
* item when used as a child of a navigation block.
*
* @since 6.5.0
*
* @param array $needs_list_item_wrapper The list of blocks that need a list item wrapper.
* @return array The list of blocks that need a list item wrapper.
*/
$needs_list_item_wrapper = apply_filters( 'block_core_navigation_listable_blocks', static::$needs_list_item_wrapper );
return in_array( $block->name, $needs_list_item_wrapper, true );
} }
/** /**
@ -140,7 +164,9 @@ class WP_Navigation_Block_Renderer {
$is_list_open = false; $is_list_open = false;
foreach ( $inner_blocks as $inner_block ) { foreach ( $inner_blocks as $inner_block ) {
$is_list_item = in_array( $inner_block->name, static::$nav_blocks_wrapped_in_list_item, true ); $inner_block_markup = static::get_markup_for_inner_block( $inner_block );
$p = new WP_HTML_Tag_Processor( $inner_block_markup );
$is_list_item = $p->next_tag( 'LI' );
if ( $is_list_item && ! $is_list_open ) { if ( $is_list_item && ! $is_list_open ) {
$is_list_open = true; $is_list_open = true;
@ -155,7 +181,7 @@ class WP_Navigation_Block_Renderer {
$inner_blocks_html .= '</ul>'; $inner_blocks_html .= '</ul>';
} }
$inner_blocks_html .= static::get_markup_for_inner_block( $inner_block ); $inner_blocks_html .= $inner_block_markup;
} }
if ( $is_list_open ) { if ( $is_list_open ) {
@ -567,6 +593,17 @@ class WP_Navigation_Block_Renderer {
*/ */
private static function handle_view_script_module_loading( $attributes, $block, $inner_blocks ) { private static function handle_view_script_module_loading( $attributes, $block, $inner_blocks ) {
if ( static::is_interactive( $attributes, $inner_blocks ) ) { if ( static::is_interactive( $attributes, $inner_blocks ) ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/navigation.min.js' );
}
wp_register_script_module(
'@wordpress/block-library/navigation',
isset( $module_url ) ? $module_url : includes_url( "blocks/navigation/view{$suffix}.js" ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
wp_enqueue_script_module( '@wordpress/block-library/navigation' ); wp_enqueue_script_module( '@wordpress/block-library/navigation' );
} }
} }
@ -968,7 +1005,9 @@ function block_core_navigation_block_contains_core_navigation( $inner_blocks ) {
function block_core_navigation_get_fallback_blocks() { function block_core_navigation_get_fallback_blocks() {
$page_list_fallback = array( $page_list_fallback = array(
array( array(
'blockName' => 'core/page-list', 'blockName' => 'core/page-list',
'innerContent' => array(),
'attrs' => array(),
), ),
); );
@ -976,12 +1015,7 @@ function block_core_navigation_get_fallback_blocks() {
// If `core/page-list` is not registered then return empty blocks. // If `core/page-list` is not registered then return empty blocks.
$fallback_blocks = $registry->is_registered( 'core/page-list' ) ? $page_list_fallback : array(); $fallback_blocks = $registry->is_registered( 'core/page-list' ) ? $page_list_fallback : array();
$navigation_post = WP_Navigation_Fallback::get_fallback();
if ( class_exists( 'WP_Navigation_Fallback' ) ) {
$navigation_post = WP_Navigation_Fallback::get_fallback();
} else {
$navigation_post = Gutenberg_Navigation_Fallback::get_fallback();
}
// Use the first non-empty Navigation as fallback if available. // Use the first non-empty Navigation as fallback if available.
if ( $navigation_post ) { if ( $navigation_post ) {
@ -1079,13 +1113,6 @@ function register_block_core_navigation() {
'render_callback' => 'render_block_core_navigation', 'render_callback' => 'render_block_core_navigation',
) )
); );
wp_register_script_module(
'@wordpress/block-library/navigation',
defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ? gutenberg_url( '/build/interactivity/navigation.min.js' ) : includes_url( 'blocks/navigation/view.min.js' ),
array( '@wordpress/interactivity' ),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
} }
add_action( 'init', 'register_block_core_navigation' ); add_action( 'init', 'register_block_core_navigation' );
@ -1418,9 +1445,14 @@ function block_core_navigation_update_ignore_hooked_blocks_meta( $post ) {
} }
} }
// Before adding our filter, we verify if it's already added in Core.
// However, during the build process, Gutenberg automatically prefixes our functions with "gutenberg_".
// Therefore, we concatenate the Core's function name to circumvent this prefix for our check.
$rest_insert_wp_navigation_core_callback = 'block_core_navigation_' . 'update_ignore_hooked_blocks_meta';
// Injection of hooked blocks into the Navigation block relies on some functions present in WP >= 6.5 // Injection of hooked blocks into the Navigation block relies on some functions present in WP >= 6.5
// that are not present in Gutenberg's WP 6.5 compatibility layer. // that are not present in Gutenberg's WP 6.5 compatibility layer.
if ( function_exists( 'get_hooked_block_markup' ) ) { if ( function_exists( 'get_hooked_block_markup' ) && ! has_filter( 'rest_insert_wp_navigation', $rest_insert_wp_navigation_core_callback ) ) {
add_action( 'rest_insert_wp_navigation', 'block_core_navigation_update_ignore_hooked_blocks_meta', 10, 3 ); add_action( 'rest_insert_wp_navigation', 'block_core_navigation_update_ignore_hooked_blocks_meta', 10, 3 );
} }
@ -1450,8 +1482,13 @@ function block_core_navigation_insert_hooked_blocks_into_rest_response( $respons
return $response; return $response;
} }
// Before adding our filter, we verify if it's already added in Core.
// However, during the build process, Gutenberg automatically prefixes our functions with "gutenberg_".
// Therefore, we concatenate the Core's function name to circumvent this prefix for our check.
$rest_prepare_wp_navigation_core_callback = 'block_core_navigation_' . 'insert_hooked_blocks_into_rest_response';
// Injection of hooked blocks into the Navigation block relies on some functions present in WP >= 6.5 // Injection of hooked blocks into the Navigation block relies on some functions present in WP >= 6.5
// that are not present in Gutenberg's WP 6.5 compatibility layer. // that are not present in Gutenberg's WP 6.5 compatibility layer.
if ( function_exists( 'get_hooked_block_markup' ) ) { if ( function_exists( 'get_hooked_block_markup' ) && ! has_filter( 'rest_prepare_wp_navigation', $rest_prepare_wp_navigation_core_callback ) ) {
add_filter( 'rest_prepare_wp_navigation', 'block_core_navigation_insert_hooked_blocks_into_rest_response', 10, 3 ); add_filter( 'rest_prepare_wp_navigation', 'block_core_navigation_insert_hooked_blocks_into_rest_response', 10, 3 );
} }

View File

@ -4,6 +4,19 @@
"name": "core/navigation", "name": "core/navigation",
"title": "Navigation", "title": "Navigation",
"category": "theme", "category": "theme",
"allowedBlocks": [
"core/navigation-link",
"core/search",
"core/social-links",
"core/page-list",
"core/spacer",
"core/home-link",
"core/site-title",
"core/site-logo",
"core/navigation-submenu",
"core/loginout",
"core/buttons"
],
"description": "A collection of blocks that allow visitors to get around your site.", "description": "A collection of blocks that allow visitors to get around your site.",
"keywords": [ "menu", "navigation", "links" ], "keywords": [ "menu", "navigation", "links" ],
"textdomain": "default", "textdomain": "default",

View File

@ -31,7 +31,6 @@ const interactivity_namespaceObject = x({ ["getContext"]: () => __WEBPACK_EXTERN
const DEFAULT_BLOCK = { const DEFAULT_BLOCK = {
name: 'core/navigation-link' name: 'core/navigation-link'
}; };
const ALLOWED_BLOCKS = (/* unused pure expression or super */ null && (['core/navigation-link', 'core/search', 'core/social-links', 'core/page-list', 'core/spacer', 'core/home-link', 'core/site-title', 'core/site-logo', 'core/navigation-submenu', 'core/loginout', 'core/buttons']));
const PRIORITIZED_INSERTER_BLOCKS = (/* unused pure expression or super */ null && (['core/navigation-link/page', 'core/navigation-link'])); const PRIORITIZED_INSERTER_BLOCKS = (/* unused pure expression or super */ null && (['core/navigation-link/page', 'core/navigation-link']));
// These parameters must be kept aligned with those in // These parameters must be kept aligned with those in
@ -245,5 +244,7 @@ const {
}; };
} }
} }
}, {
lock: true
}); });

View File

@ -1 +1 @@
import*as e from"@wordpress/interactivity";var t={d:(e,n)=>{for(var o in n)t.o(n,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:n[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const n=(e=>{var n={};return t.d(n,e),n})({getContext:()=>e.getContext,getElement:()=>e.getElement,store:()=>e.store}),o=["a[href]",'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',"select:not([disabled]):not([aria-hidden])","textarea:not([disabled]):not([aria-hidden])","button:not([disabled]):not([aria-hidden])","[contenteditable]",'[tabindex]:not([tabindex^="-"])'];document.addEventListener("click",(()=>{}));const{state:l,actions:c}=(0,n.store)("core/navigation",{state:{get roleAttribute(){return"overlay"===(0,n.getContext)().type&&l.isMenuOpen?"dialog":null},get ariaModal(){return"overlay"===(0,n.getContext)().type&&l.isMenuOpen?"true":null},get ariaLabel(){const e=(0,n.getContext)();return"overlay"===e.type&&l.isMenuOpen?e.ariaLabel:null},get isMenuOpen(){return Object.values(l.menuOpenedBy).filter(Boolean).length>0},get menuOpenedBy(){const e=(0,n.getContext)();return"overlay"===e.type?e.overlayOpenedBy:e.submenuOpenedBy}},actions:{openMenuOnHover(){const{type:e,overlayOpenedBy:t}=(0,n.getContext)();"submenu"===e&&0===Object.values(t||{}).filter(Boolean).length&&c.openMenu("hover")},closeMenuOnHover(){c.closeMenu("hover")},openMenuOnClick(){const e=(0,n.getContext)(),{ref:t}=(0,n.getElement)();e.previousFocus=t,c.openMenu("click")},closeMenuOnClick(){c.closeMenu("click"),c.closeMenu("focus")},openMenuOnFocus(){c.openMenu("focus")},toggleMenuOnClick(){const e=(0,n.getContext)(),{ref:t}=(0,n.getElement)();window.document.activeElement!==t&&t.focus();const{menuOpenedBy:o}=l;o.click||o.focus?(c.closeMenu("click"),c.closeMenu("focus")):(e.previousFocus=t,c.openMenu("click"))},handleMenuKeydown(e){const{type:t,firstFocusableElement:o,lastFocusableElement:s}=(0,n.getContext)();if(l.menuOpenedBy.click){if("Escape"===e?.key)return c.closeMenu("click"),void c.closeMenu("focus");"overlay"===t&&"Tab"===e.key&&(e.shiftKey&&window.document.activeElement===o?(e.preventDefault(),s.focus()):e.shiftKey||window.document.activeElement!==s||(e.preventDefault(),o.focus()))}},handleMenuFocusout(e){const{modal:t}=(0,n.getContext)();(null===e.relatedTarget||!t?.contains(e.relatedTarget)&&e.target!==window.document.activeElement)&&(c.closeMenu("click"),c.closeMenu("focus"))},openMenu(e="click"){const{type:t}=(0,n.getContext)();l.menuOpenedBy[e]=!0,"overlay"===t&&document.documentElement.classList.add("has-modal-open")},closeMenu(e="click"){const t=(0,n.getContext)();l.menuOpenedBy[e]=!1,l.isMenuOpen||(t.modal?.contains(window.document.activeElement)&&t.previousFocus?.focus(),t.modal=null,t.previousFocus=null,"overlay"===t.type&&document.documentElement.classList.remove("has-modal-open"))}},callbacks:{initMenu(){const e=(0,n.getContext)(),{ref:t}=(0,n.getElement)();if(l.isMenuOpen){const n=t.querySelectorAll(o);e.modal=t,e.firstFocusableElement=n[0],e.lastFocusableElement=n[n.length-1]}},focusFirstElement(){const{ref:e}=(0,n.getElement)();if(l.isMenuOpen){const t=e.querySelectorAll(o);t?.[0]?.focus()}},initNav(){const e=(0,n.getContext)(),t=window.matchMedia("(max-width: 600px)");function o(t){e.isCollapsed=t.matches}return e.isCollapsed=t.matches,t.addEventListener("change",o),()=>{t.removeEventListener("change",o)}}}}); import*as e from"@wordpress/interactivity";var t={d:(e,n)=>{for(var o in n)t.o(n,o)&&!t.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:n[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};const n=(e=>{var n={};return t.d(n,e),n})({getContext:()=>e.getContext,getElement:()=>e.getElement,store:()=>e.store}),o=["a[href]",'input:not([disabled]):not([type="hidden"]):not([aria-hidden])',"select:not([disabled]):not([aria-hidden])","textarea:not([disabled]):not([aria-hidden])","button:not([disabled]):not([aria-hidden])","[contenteditable]",'[tabindex]:not([tabindex^="-"])'];document.addEventListener("click",(()=>{}));const{state:l,actions:c}=(0,n.store)("core/navigation",{state:{get roleAttribute(){return"overlay"===(0,n.getContext)().type&&l.isMenuOpen?"dialog":null},get ariaModal(){return"overlay"===(0,n.getContext)().type&&l.isMenuOpen?"true":null},get ariaLabel(){const e=(0,n.getContext)();return"overlay"===e.type&&l.isMenuOpen?e.ariaLabel:null},get isMenuOpen(){return Object.values(l.menuOpenedBy).filter(Boolean).length>0},get menuOpenedBy(){const e=(0,n.getContext)();return"overlay"===e.type?e.overlayOpenedBy:e.submenuOpenedBy}},actions:{openMenuOnHover(){const{type:e,overlayOpenedBy:t}=(0,n.getContext)();"submenu"===e&&0===Object.values(t||{}).filter(Boolean).length&&c.openMenu("hover")},closeMenuOnHover(){c.closeMenu("hover")},openMenuOnClick(){const e=(0,n.getContext)(),{ref:t}=(0,n.getElement)();e.previousFocus=t,c.openMenu("click")},closeMenuOnClick(){c.closeMenu("click"),c.closeMenu("focus")},openMenuOnFocus(){c.openMenu("focus")},toggleMenuOnClick(){const e=(0,n.getContext)(),{ref:t}=(0,n.getElement)();window.document.activeElement!==t&&t.focus();const{menuOpenedBy:o}=l;o.click||o.focus?(c.closeMenu("click"),c.closeMenu("focus")):(e.previousFocus=t,c.openMenu("click"))},handleMenuKeydown(e){const{type:t,firstFocusableElement:o,lastFocusableElement:s}=(0,n.getContext)();if(l.menuOpenedBy.click){if("Escape"===e?.key)return c.closeMenu("click"),void c.closeMenu("focus");"overlay"===t&&"Tab"===e.key&&(e.shiftKey&&window.document.activeElement===o?(e.preventDefault(),s.focus()):e.shiftKey||window.document.activeElement!==s||(e.preventDefault(),o.focus()))}},handleMenuFocusout(e){const{modal:t}=(0,n.getContext)();(null===e.relatedTarget||!t?.contains(e.relatedTarget)&&e.target!==window.document.activeElement)&&(c.closeMenu("click"),c.closeMenu("focus"))},openMenu(e="click"){const{type:t}=(0,n.getContext)();l.menuOpenedBy[e]=!0,"overlay"===t&&document.documentElement.classList.add("has-modal-open")},closeMenu(e="click"){const t=(0,n.getContext)();l.menuOpenedBy[e]=!1,l.isMenuOpen||(t.modal?.contains(window.document.activeElement)&&t.previousFocus?.focus(),t.modal=null,t.previousFocus=null,"overlay"===t.type&&document.documentElement.classList.remove("has-modal-open"))}},callbacks:{initMenu(){const e=(0,n.getContext)(),{ref:t}=(0,n.getElement)();if(l.isMenuOpen){const n=t.querySelectorAll(o);e.modal=t,e.firstFocusableElement=n[0],e.lastFocusableElement=n[n.length-1]}},focusFirstElement(){const{ref:e}=(0,n.getElement)();if(l.isMenuOpen){const t=e.querySelectorAll(o);t?.[0]?.focus()}},initNav(){const e=(0,n.getContext)(),t=window.matchMedia("(max-width: 600px)");function o(t){e.isCollapsed=t.matches}return e.isCollapsed=t.matches,t.addEventListener("change",o),()=>{t.removeEventListener("change",o)}}}},{lock:!0});

View File

@ -11,7 +11,10 @@
"supports": { "supports": {
"customClassName": false, "customClassName": false,
"className": false, "className": false,
"html": false "html": false,
"interactivity": {
"clientNavigation": true
}
}, },
"editorStyle": "wp-block-nextpage-editor" "editorStyle": "wp-block-nextpage-editor"
} }

View File

@ -45,7 +45,10 @@
"html": false, "html": false,
"lock": false, "lock": false,
"inserter": false, "inserter": false,
"__experimentalToolbar": false "__experimentalToolbar": false,
"interactivity": {
"clientNavigation": true
}
}, },
"editorStyle": "wp-block-page-list-editor", "editorStyle": "wp-block-page-list-editor",
"style": "wp-block-page-list" "style": "wp-block-page-list"

View File

@ -4,6 +4,7 @@
"name": "core/page-list", "name": "core/page-list",
"title": "Page List", "title": "Page List",
"category": "widgets", "category": "widgets",
"allowedBlocks": [ "core/page-list-item" ],
"description": "Display a list of all pages.", "description": "Display a list of all pages.",
"keywords": [ "menu", "navigation" ], "keywords": [ "menu", "navigation" ],
"textdomain": "default", "textdomain": "default",
@ -47,6 +48,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-page-list-editor", "editorStyle": "wp-block-page-list-editor",

View File

@ -64,7 +64,10 @@
} }
}, },
"__experimentalSelector": "p", "__experimentalSelector": "p",
"__unstablePasteTextInline": true "__unstablePasteTextInline": true,
"interactivity": {
"clientNavigation": true
}
}, },
"editorStyle": "wp-block-paragraph-editor", "editorStyle": "wp-block-paragraph-editor",
"style": "wp-block-paragraph" "style": "wp-block-paragraph"

View File

@ -8,7 +8,10 @@
"supports": { "supports": {
"html": false, "html": false,
"inserter": false, "inserter": false,
"renaming": false "renaming": false,
"interactivity": {
"clientNavigation": true
}
}, },
"textdomain": "default", "textdomain": "default",
"attributes": { "attributes": {

View File

@ -37,6 +37,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -47,6 +47,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -61,6 +61,9 @@
"background": true, "background": true,
"text": true "text": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"style": "wp-block-post-author" "style": "wp-block-post-author"

View File

@ -0,0 +1,4 @@
.wp-block-post-content.wp-block-post-content{
-webkit-user-select:none;
user-select:none;
}

View File

@ -0,0 +1 @@
.wp-block-post-content.wp-block-post-content{-webkit-user-select:none;user-select:none}

View File

@ -0,0 +1,4 @@
.wp-block-post-content.wp-block-post-content{
-webkit-user-select:none;
user-select:none;
}

View File

@ -0,0 +1 @@
.wp-block-post-content.wp-block-post-content{-webkit-user-select:none;user-select:none}

View File

@ -50,6 +50,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -50,6 +50,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-post-excerpt-editor", "editorStyle": "wp-block-post-excerpt-editor",

View File

@ -81,6 +81,9 @@
"spacing": { "spacing": {
"margin": true, "margin": true,
"padding": true "padding": true
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-post-featured-image-editor", "editorStyle": "wp-block-post-featured-image-editor",

View File

@ -99,9 +99,6 @@ function render_block_core_post_navigation_link( $attributes, $content ) {
} }
} }
$in_same_term = isset( $attributes['inSameTerm'] ) ? $attributes['inSameTerm'] : false;
$taxonomy = isset( $attributes['taxonomy'] ) && $in_same_term ? $attributes['taxonomy'] : '';
/* /*
* The dynamic portion of the function name, `$navigation_type`, * The dynamic portion of the function name, `$navigation_type`,
* Refers to the type of adjacency, 'next' or 'previous'. * Refers to the type of adjacency, 'next' or 'previous'.
@ -111,8 +108,8 @@ function render_block_core_post_navigation_link( $attributes, $content ) {
*/ */
$get_link_function = "get_{$navigation_type}_post_link"; $get_link_function = "get_{$navigation_type}_post_link";
if ( $in_same_term ) { if ( ! empty( $attributes['taxonomy'] ) ) {
$content = $get_link_function( $format, $link, $in_same_term, '', $taxonomy ); $content = $get_link_function( $format, $link, true, '', $attributes['taxonomy'] );
} else { } else {
$content = $get_link_function( $format, $link ); $content = $get_link_function( $format, $link );
} }

View File

@ -29,9 +29,6 @@
"type": "string", "type": "string",
"default": "none" "default": "none"
}, },
"inSameTerm": {
"type": "boolean"
},
"taxonomy": { "taxonomy": {
"type": "string", "type": "string",
"default": "" "default": ""
@ -57,6 +54,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"style": "wp-block-post-navigation-link" "style": "wp-block-post-navigation-link"

View File

@ -48,6 +48,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"blockGap": true "blockGap": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"style": "wp-block-post-template", "style": "wp-block-post-template",

View File

@ -63,7 +63,7 @@ function render_block_core_post_terms( $attributes, $content, $block ) {
* *
* @return array The available variations for the block. * @return array The available variations for the block.
*/ */
function build_post_term_block_variations() { function block_core_post_terms_build_variations() {
$taxonomies = get_taxonomies( $taxonomies = get_taxonomies(
array( array(
'publicly_queryable' => true, 'publicly_queryable' => true,
@ -116,7 +116,7 @@ function register_block_core_post_terms() {
__DIR__ . '/post-terms', __DIR__ . '/post-terms',
array( array(
'render_callback' => 'render_block_core_post_terms', 'render_callback' => 'render_block_core_post_terms',
'variation_callback' => 'build_post_term_block_variations', 'variation_callback' => 'block_core_post_terms_build_variations',
) )
); );
} }

View File

@ -54,6 +54,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"style": "wp-block-post-terms" "style": "wp-block-post-terms"

View File

@ -57,6 +57,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"style": "wp-block-post-title" "style": "wp-block-post-title"

View File

@ -40,6 +40,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"style": "wp-block-preformatted" "style": "wp-block-preformatted"

View File

@ -69,6 +69,9 @@
"fontSize": "1.5em", "fontSize": "1.5em",
"lineHeight": "1.6" "lineHeight": "1.6"
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-pullquote-editor", "editorStyle": "wp-block-pullquote-editor",

View File

@ -28,6 +28,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -41,6 +41,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -36,6 +36,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-query-pagination-numbers-editor" "editorStyle": "wp-block-query-pagination-numbers-editor"

View File

@ -41,6 +41,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
} }
} }

View File

@ -4,7 +4,12 @@
"name": "core/query-pagination", "name": "core/query-pagination",
"title": "Pagination", "title": "Pagination",
"category": "theme", "category": "theme",
"parent": [ "core/query" ], "ancestor": [ "core/query" ],
"allowedBlocks": [
"core/query-pagination-previous",
"core/query-pagination-numbers",
"core/query-pagination-next"
],
"description": "Displays a paginated navigation to next/previous set of posts, when applicable.", "description": "Displays a paginated navigation to next/previous set of posts, when applicable.",
"textdomain": "default", "textdomain": "default",
"attributes": { "attributes": {
@ -54,6 +59,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"editorStyle": "wp-block-query-pagination-editor", "editorStyle": "wp-block-query-pagination-editor",

View File

@ -52,6 +52,9 @@
"__experimentalDefaultControls": { "__experimentalDefaultControls": {
"fontSize": true "fontSize": true
} }
},
"interactivity": {
"clientNavigation": true
} }
}, },
"style": "wp-block-query-title" "style": "wp-block-query-title"

View File

@ -17,11 +17,33 @@
* @return string Returns the modified output of the query block. * @return string Returns the modified output of the query block.
*/ */
function render_block_core_query( $attributes, $content, $block ) { function render_block_core_query( $attributes, $content, $block ) {
$is_interactive = isset( $attributes['enhancedPagination'] ) && true === $attributes['enhancedPagination'] && isset( $attributes['queryId'] ); $is_interactive = isset( $attributes['enhancedPagination'] )
&& true === $attributes['enhancedPagination']
&& isset( $attributes['queryId'] );
// Enqueue the script module and add the necessary directives if the block is // Enqueue the script module and add the necessary directives if the block is
// interactive. // interactive.
if ( $is_interactive ) { if ( $is_interactive ) {
$suffix = wp_scripts_get_suffix();
if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
$module_url = gutenberg_url( '/build/interactivity/query.min.js' );
}
wp_register_script_module(
'@wordpress/block-library/query',
isset( $module_url ) ? $module_url : includes_url( "blocks/query/view{$suffix}.js" ),
array(
array(
'id' => '@wordpress/interactivity',
'import' => 'static',
),
array(
'id' => '@wordpress/interactivity-router',
'import' => 'dynamic',
),
),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
wp_enqueue_script_module( '@wordpress/block-library/query' ); wp_enqueue_script_module( '@wordpress/block-library/query' );
$p = new WP_HTML_Tag_Processor( $content ); $p = new WP_HTML_Tag_Processor( $content );
@ -30,43 +52,8 @@ function render_block_core_query( $attributes, $content, $block ) {
$p->set_attribute( 'data-wp-interactive', '{"namespace":"core/query"}' ); $p->set_attribute( 'data-wp-interactive', '{"namespace":"core/query"}' );
$p->set_attribute( 'data-wp-router-region', 'query-' . $attributes['queryId'] ); $p->set_attribute( 'data-wp-router-region', 'query-' . $attributes['queryId'] );
$p->set_attribute( 'data-wp-init', 'callbacks.setQueryRef' ); $p->set_attribute( 'data-wp-init', 'callbacks.setQueryRef' );
// Use context to send translated strings. $p->set_attribute( 'data-wp-context', '{}' );
$p->set_attribute(
'data-wp-context',
wp_json_encode(
array(
'loadingText' => __( 'Loading page, please wait.' ),
'loadedText' => __( 'Page Loaded.' ),
),
JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP
)
);
$content = $p->get_updated_html(); $content = $p->get_updated_html();
// Mark the block as interactive.
$block->block_type->supports['interactivity'] = true;
// Add a div to announce messages using `aria-live`.
$html_tag = 'div';
if ( ! empty( $attributes['tagName'] ) ) {
$html_tag = esc_attr( $attributes['tagName'] );
}
$last_tag_position = strripos( $content, '</' . $html_tag . '>' );
$content = substr_replace(
$content,
'<div
class="screen-reader-text"
aria-live="polite"
data-wp-text="context.message"
></div>
<div
class="wp-block-query__enhanced-pagination-animation"
data-wp-class--start-animation="state.startAnimation"
data-wp-class--finish-animation="state.finishAnimation"
></div>',
$last_tag_position,
0
);
} }
} }
@ -98,22 +85,6 @@ function register_block_core_query() {
'render_callback' => 'render_block_core_query', 'render_callback' => 'render_block_core_query',
) )
); );
wp_register_script_module(
'@wordpress/block-library/query',
defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ? gutenberg_url( '/build/interactivity/query.min.js' ) : includes_url( 'blocks/query/view.min.js' ),
array(
array(
'id' => '@wordpress/interactivity',
'import' => 'static',
),
array(
'id' => '@wordpress/interactivity-router',
'import' => 'dynamic',
),
),
defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
);
} }
add_action( 'init', 'register_block_core_query' ); add_action( 'init', 'register_block_core_query' );
@ -133,10 +104,18 @@ function block_core_query_disable_enhanced_pagination( $parsed_block ) {
static $dirty_enhanced_queries = array(); static $dirty_enhanced_queries = array();
static $render_query_callback = null; static $render_query_callback = null;
$is_interactive = isset( $parsed_block['attrs']['enhancedPagination'] ) && true === $parsed_block['attrs']['enhancedPagination'] && isset( $parsed_block['attrs']['queryId'] ); $block_name = $parsed_block['blockName'];
$block_name = $parsed_block['blockName']; $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_name );
$has_enhanced_pagination = isset( $parsed_block['attrs']['enhancedPagination'] ) && true === $parsed_block['attrs']['enhancedPagination'] && isset( $parsed_block['attrs']['queryId'] );
/*
* Client side navigation can be true in two states:
* - supports.interactivity = true;
* - supports.interactivity.clientNavigation = true;
*/
$supports_client_navigation = ( isset( $block_type->supports['interactivity']['clientNavigation'] ) && true === $block_type->supports['interactivity']['clientNavigation'] )
|| ( isset( $block_type->supports['interactivity'] ) && true === $block_type->supports['interactivity'] );
if ( 'core/query' === $block_name && $is_interactive ) { if ( 'core/query' === $block_name && $has_enhanced_pagination ) {
$enhanced_query_stack[] = $parsed_block['attrs']['queryId']; $enhanced_query_stack[] = $parsed_block['attrs']['queryId'];
if ( ! isset( $render_query_callback ) ) { if ( ! isset( $render_query_callback ) ) {
@ -151,18 +130,15 @@ function block_core_query_disable_enhanced_pagination( $parsed_block ) {
* @return string Returns the modified output of the query block. * @return string Returns the modified output of the query block.
*/ */
$render_query_callback = static function ( $content, $block ) use ( &$enhanced_query_stack, &$dirty_enhanced_queries, &$render_query_callback ) { $render_query_callback = static function ( $content, $block ) use ( &$enhanced_query_stack, &$dirty_enhanced_queries, &$render_query_callback ) {
$is_interactive = isset( $block['attrs']['enhancedPagination'] ) && true === $block['attrs']['enhancedPagination'] && isset( $block['attrs']['queryId'] ); $has_enhanced_pagination = isset( $block['attrs']['enhancedPagination'] ) && true === $block['attrs']['enhancedPagination'] && isset( $block['attrs']['queryId'] );
if ( ! $is_interactive ) { if ( ! $has_enhanced_pagination ) {
return $content; return $content;
} }
if ( isset( $dirty_enhanced_queries[ $block['attrs']['queryId'] ] ) ) { if ( isset( $dirty_enhanced_queries[ $block['attrs']['queryId'] ] ) ) {
$p = new WP_HTML_Tag_Processor( $content ); // Disable navigation in the router store config.
if ( $p->next_tag() ) { wp_interactivity_config( 'core/router', array( 'clientNavigationDisabled' => true ) );
$p->set_attribute( 'data-wp-navigation-disabled', 'true' );
}
$content = $p->get_updated_html();
$dirty_enhanced_queries[ $block['attrs']['queryId'] ] = null; $dirty_enhanced_queries[ $block['attrs']['queryId'] ] = null;
} }
@ -181,7 +157,7 @@ function block_core_query_disable_enhanced_pagination( $parsed_block ) {
} elseif ( } elseif (
! empty( $enhanced_query_stack ) && ! empty( $enhanced_query_stack ) &&
isset( $block_name ) && isset( $block_name ) &&
( ! str_starts_with( $block_name, 'core/' ) || 'core/post-content' === $block_name ) ( ! $supports_client_navigation )
) { ) {
foreach ( $enhanced_query_stack as $query_id ) { foreach ( $enhanced_query_stack as $query_id ) {
$dirty_enhanced_queries[ $query_id ] = true; $dirty_enhanced_queries[ $query_id ] = true;

Some files were not shown because too many files have changed in this diff Show More