Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove experimental flag from navigation and file blocks to use the Interactivity API (as private) #51266

Merged
223 changes: 3 additions & 220 deletions lib/experimental/interactivity-api/blocks.php
Original file line number Diff line number Diff line change
@@ -1,237 +1,20 @@
<?php
/**
* Extend WordPress core navigation block to use the Interactivity API.
* Interactivity API directives are added using the Tag Processor while it is experimental.
* Extend WordPress core blocks to use the Interactivity API.
*
* @package gutenberg
*/

/**
* Adds Interactivity API directives to the File block markup using the Tag Processor.
*
* @param string $block_content Markup of the File block.
* @param array $block The full block, including name and attributes.
* @param WP_Block $instance The block instance.
*
* @return string File block markup with the directives injected when applicable.
*/
function gutenberg_block_core_file_add_directives_to_content( $block_content, $block, $instance ) {
if ( empty( $instance->attributes['displayPreview'] ) ) {
return $block_content;
}
$processor = new WP_HTML_Tag_Processor( $block_content );
$processor->next_tag();
$processor->set_attribute( 'data-wp-interactive', '' );
$processor->next_tag( 'object' );
$processor->set_attribute( 'data-wp-bind--hidden', '!selectors.core.file.hasPdfPreview' );
$processor->set_attribute( 'hidden', true );
return $processor->get_updated_html();
}
add_filter( 'render_block_core/file', 'gutenberg_block_core_file_add_directives_to_content', 10, 3 );

/**
* Add Interactivity API directives to the navigation block markup using the Tag Processor
* The final HTML of the navigation block will look similar to this:
*
* <nav
* data-wp-interactive
* data-wp-context='{ "core": { "navigation": { "isMenuOpen": { "click": false, "hover": false }, "overlay": true, "roleAttribute": "" } } }'
* >
* <button
* class="wp-block-navigation__responsive-container-open"
* data-wp-on--click="actions.core.navigation.openMenuOnClick"
* data-wp-on--keydown="actions.core.navigation.handleMenuKeydown"
* >
* <div
* class="wp-block-navigation__responsive-container"
* data-wp-class--has-modal-open="selectors.core.navigation.isMenuOpen"
* data-wp-class--is-menu-open="selectors.core.navigation.isMenuOpen"
* data-wp-bind--aria-hidden="!selectors.core.navigation.isMenuOpen"
* data-wp-effect="effects.core.navigation.initMenu"
* data-wp-on--keydown="actions.core.navigation.handleMenuKeydown"
* data-wp-on--focusout="actions.core.navigation.handleMenuFocusout"
* tabindex="-1"
* >
* <div class="wp-block-navigation__responsive-close">
* <div
* class="wp-block-navigation__responsive-dialog"
* data-wp-bind--aria-modal="selectors.core.navigation.isMenuOpen"
* data-wp-bind--role="selectors.core.navigation.roleAttribute"
* data-wp-effect="effects.core.navigation.focusFirstElement"
* >
* <button
* class="wp-block-navigation__responsive-container-close"
* data-wp-on--click="actions.core.navigation.closeMenuOnclick"
* >
* <svg>
* <button>
* MENU ITEMS
* </div>
* </div>
* </div>
* </nav>
*
* @param string $block_content Markup of the navigation block.
* @param array $block Block object.
*
* @return string Navigation block markup with the proper directives
*/
function gutenberg_block_core_navigation_add_directives_to_markup( $block_content, $block ) {
$w = new WP_HTML_Tag_Processor( $block_content );
// Add directives to the `<nav>` element.
if ( $w->next_tag( 'nav' ) ) {
$w->set_attribute( 'data-wp-interactive', '' );
$w->set_attribute( 'data-wp-context', '{ "core": { "navigation": { "isMenuOpen": { "click": false, "hover": false }, "overlay": true, "roleAttribute": "" } } }' );
};

// Add directives to the open menu button.
if ( $w->next_tag(
array(
'tag_name' => 'BUTTON',
'class_name' => 'wp-block-navigation__responsive-container-open',
)
) ) {
$w->set_attribute( 'data-wp-on--click', 'actions.core.navigation.openMenuOnClick' );
$w->set_attribute( 'data-wp-on--keydown', 'actions.core.navigation.handleMenuKeydown' );
$w->remove_attribute( 'data-micromodal-trigger' );
} else {
// If the open modal button not found, we handle submenus immediately.
$w = new WP_HTML_Tag_Processor( $w->get_updated_html() );

gutenberg_block_core_navigation_add_directives_to_submenu( $w, $block['attrs'] );

return $w->get_updated_html();
}

// Add directives to the menu container.
if ( $w->next_tag(
array(
'tag_name' => 'DIV',
'class_name' => 'wp-block-navigation__responsive-container',
)
) ) {
$w->set_attribute( 'data-wp-class--has-modal-open', 'selectors.core.navigation.isMenuOpen' );
$w->set_attribute( 'data-wp-class--is-menu-open', 'selectors.core.navigation.isMenuOpen' );
$w->set_attribute( 'data-wp-effect', 'effects.core.navigation.initMenu' );
$w->set_attribute( 'data-wp-on--keydown', 'actions.core.navigation.handleMenuKeydown' );
$w->set_attribute( 'data-wp-on--focusout', 'actions.core.navigation.handleMenuFocusout' );
$w->set_attribute( 'tabindex', '-1' );
};

// Remove micromodal attribute.
if ( $w->next_tag(
array(
'tag_name' => 'DIV',
'class_name' => 'wp-block-navigation__responsive-close',
)
) ) {
$w->remove_attribute( 'data-micromodal-close' );
};

// Add directives to the dialog container.
if ( $w->next_tag(
array(
'tag_name' => 'DIV',
'class_name' => 'wp-block-navigation__responsive-dialog',
)
) ) {
$w->set_attribute( 'data-wp-bind--aria-modal', 'selectors.core.navigation.isMenuOpen' );
$w->set_attribute( 'data-wp-bind--role', 'selectors.core.navigation.roleAttribute' );
$w->set_attribute( 'data-wp-effect', 'effects.core.navigation.focusFirstElement' );
};

// Add directives to the close button.
if ( $w->next_tag(
array(
'tag_name' => 'BUTTON',
'class_name' => 'wp-block-navigation__responsive-container-close',
)
) ) {
$w->set_attribute( 'data-wp-on--click', 'actions.core.navigation.closeMenuOnClick' );
$w->remove_attribute( 'data-micromodal-close' );
};

// Submenus.
gutenberg_block_core_navigation_add_directives_to_submenu( $w, $block['attrs'] );

return $w->get_updated_html();
};

/**
* Add Interactivity API directives to the navigation-submenu and page-list blocks markup using the Tag Processor
* The final HTML of the navigation-submenu and the page-list blocks will look similar to this:
*
* <li
* class="has-child"
* data-wp-context='{ "core": { "navigation": { "isMenuOpen": { "click": false, "hover": false, "overlay": false } } }'
* data-wp-effect="effects.core.navigation.initMenu"
* data-wp-on--keydown="actions.core.navigation.handleMenuKeydown"
* data-wp-on--focusout="actions.core.navigation.handleMenuFocusout"
* data-wp-on--mouseenter="actions.core.navigation.openMenuOnHover"
* data-wp-on--mouseleave="actions.core.navigation.closeMenuOnHover"
* >
* <button
* class="wp-block-navigation-submenu__toggle"
* data-wp-on--click="actions.core.navigation.toggleMenuOnClick"
* data-wp-bind--aria-expanded="selectors.core.navigation.isMenuOpen"
* >
* </button>
* <span>Title</span>
* <ul class="wp-block-navigation__submenu-container">
* SUBMENU ITEMS
* </ul>
* </li>
*
* @param string $w Markup of the navigation block.
* @param array $block_attributes Block attributes.
*
* @return void
*/
function gutenberg_block_core_navigation_add_directives_to_submenu( $w, $block_attributes ) {
while ( $w->next_tag(
array(
'tag_name' => 'LI',
'class_name' => 'has-child',
)
) ) {
// Add directives to the parent `<li>`.
$w->set_attribute( 'data-wp-context', '{ "core": { "navigation": { "isMenuOpen": { "click": false, "hover": false }, "overlay": false } } }' );
$w->set_attribute( 'data-wp-effect', 'effects.core.navigation.initMenu' );
$w->set_attribute( 'data-wp-on--focusout', 'actions.core.navigation.handleMenuFocusout' );
$w->set_attribute( 'data-wp-on--keydown', 'actions.core.navigation.handleMenuKeydown' );
if ( ! isset( $block_attributes['openSubmenusOnClick'] ) || false === $block_attributes['openSubmenusOnClick'] ) {
$w->set_attribute( 'data-wp-on--mouseenter', 'actions.core.navigation.openMenuOnHover' );
$w->set_attribute( 'data-wp-on--mouseleave', 'actions.core.navigation.closeMenuOnHover' );
}

// Add directives to the toggle submenu button.
if ( $w->next_tag(
array(
'tag_name' => 'BUTTON',
'class_name' => 'wp-block-navigation-submenu__toggle',
)
) ) {
$w->set_attribute( 'data-wp-on--click', 'actions.core.navigation.toggleMenuOnClick' );
$w->set_attribute( 'data-wp-bind--aria-expanded', 'selectors.core.navigation.isMenuOpen' );
};

// Iterate through subitems if exist.
gutenberg_block_core_navigation_add_directives_to_submenu( $w, $block_attributes );
}
};

add_filter( 'render_block_core/navigation', 'gutenberg_block_core_navigation_add_directives_to_markup', 10, 2 );

/**
* Replaces view script for the File, Navigation, and Image blocks with version using Interactivity API.
* Replaces view script for the Image block with version using Interactivity API.
*
* @param array $metadata Block metadata as read in via block.json.
*
* @return array Filtered block type metadata.
*/
function gutenberg_block_update_interactive_view_script( $metadata ) {
if (
in_array( $metadata['name'], array( 'core/file', 'core/navigation', 'core/image' ), true ) &&
in_array( $metadata['name'], array( 'core/image' ), true ) &&
str_contains( $metadata['file'], 'build/block-library/blocks' )
) {
$metadata['viewScript'] = array( 'file:./interactivity.min.js' );
Expand Down
2 changes: 1 addition & 1 deletion lib/experiments-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ function gutenberg_initialize_experiments_settings() {
'gutenberg-experiments',
'gutenberg_experiments_section',
array(
'label' => __( 'Use the Interactivity API in File, Navigation and Image core blocks. It also enables the <a href="https://github.com/WordPress/gutenberg/issues/50029">Behaviors UI</a> in the Image block.', 'gutenberg' ),
'label' => __( 'Use the Interactivity API in Image core block. It also enables the <a href="https://github.com/WordPress/gutenberg/issues/50029">Behaviors UI</a> in the Image block.', 'gutenberg' ),
SantosGuillamot marked this conversation as resolved.
Show resolved Hide resolved
'id' => 'gutenberg-interactivity-api-core-blocks',
)
);
Expand Down
3 changes: 2 additions & 1 deletion lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,12 @@ function gutenberg_is_experiment_enabled( $name ) {
require __DIR__ . '/experimental/kses.php';
require __DIR__ . '/experimental/l10n.php';
require __DIR__ . '/experimental/navigation-fallback.php';
require __DIR__ . '/experimental/interactivity-api/script-loader.php';
if ( gutenberg_is_experiment_enabled( 'gutenberg-interactivity-api-core-blocks' ) ) {
require __DIR__ . '/experimental/interactivity-api/script-loader.php';
require __DIR__ . '/experimental/interactivity-api/blocks.php';
}


// Fonts API.
if ( ! class_exists( 'WP_Fonts' ) ) {
// Fonts API files.
Expand Down
2 changes: 1 addition & 1 deletion packages/block-library/src/file/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
}
}
},
"viewScript": "file:./view.min.js",
"viewScript": "file:./interactivity.min.js",
"editorStyle": "wp-block-file-editor",
"style": "wp-block-file"
}
35 changes: 29 additions & 6 deletions packages/block-library/src/file/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,27 @@
/**
* When the `core/file` block is rendering, check if we need to enqueue the `'wp-block-file-view` script.
*
* @param array $attributes The block attributes.
* @param string $content The block content.
* @param array $attributes The block attributes.
* @param string $content The block content.
* @param WP_Block $block The parsed block.
*
* @return string Returns the block content.
*/
function render_block_core_file( $attributes, $content ) {
$should_load_view_script = ! empty( $attributes['displayPreview'] ) && ! wp_script_is( 'wp-block-file-view' );
if ( $should_load_view_script ) {
wp_enqueue_script( 'wp-block-file-view' );
function render_block_core_file( $attributes, $content, $block ) {
$should_load_view_script = ! empty( $attributes['displayPreview'] );
$view_js_file = 'wp-block-file-view';
// If the script already exists, there is no point in removing it from viewScript.
if ( ! wp_script_is( $view_js_file ) ) {
$script_handles = $block->block_type->view_script_handles;

// If the script is not needed, and it is still in the `view_script_handles`, remove it.
if ( ! $should_load_view_script && in_array( $view_js_file, $script_handles, true ) ) {
$block->block_type->view_script_handles = array_diff( $script_handles, array( $view_js_file ) );
}
// If the script is needed, but it was previously removed, add it again.
if ( $should_load_view_script && ! in_array( $view_js_file, $script_handles, true ) ) {
$block->block_type->view_script_handles = array_merge( $script_handles, array( $view_js_file ) );
}
}

// Update object's aria-label attribute if present in block HTML.
Expand All @@ -41,6 +53,17 @@ static function ( $matches ) {
$content
);

// If it uses the Interactivity API, add the directives.
if ( $should_load_view_script ) {
$processor = new WP_HTML_Tag_Processor( $content );
$processor->next_tag();
$processor->set_attribute( 'data-wp-interactive', '' );
$processor->next_tag( 'object' );
$processor->set_attribute( 'data-wp-bind--hidden', '!selectors.core.file.hasPdfPreview' );
$processor->set_attribute( 'hidden', true );
return $processor->get_updated_html();
}

return $content;
}

Expand Down
9 changes: 0 additions & 9 deletions packages/block-library/src/file/view.js

This file was deleted.

2 changes: 1 addition & 1 deletion packages/block-library/src/navigation/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
}
}
},
"viewScript": [ "file:./view.min.js", "file:./view-modal.min.js" ],
"viewScript": "file:./interactivity.min.js",
"editorStyle": "wp-block-navigation-editor",
"style": "wp-block-navigation"
}
Loading