diff --git a/docs/reference-guides/core-blocks.md b/docs/reference-guides/core-blocks.md index 6e66df88bbac8..3d5c9c344e9ce 100644 --- a/docs/reference-guides/core-blocks.md +++ b/docs/reference-guides/core-blocks.md @@ -339,7 +339,7 @@ Insert an image to make a visual statement. ([Source](https://github.com/WordPre - **Name:** core/image - **Category:** media -- **Supports:** anchor, behaviors (lightbox), color (~~background~~, ~~text~~), filter (duotone) +- **Supports:** anchor, color (~~background~~, ~~text~~), filter (duotone) - **Attributes:** align, alt, aspectRatio, caption, height, href, id, linkClass, linkDestination, linkTarget, rel, scale, sizeSlug, title, url, width ## Latest Comments diff --git a/docs/reference-guides/theme-json-reference/theme-json-living.md b/docs/reference-guides/theme-json-reference/theme-json-living.md index ba80addbd1f65..fe7dab112b2a4 100644 --- a/docs/reference-guides/theme-json-reference/theme-json-living.md +++ b/docs/reference-guides/theme-json-reference/theme-json-living.md @@ -183,16 +183,6 @@ Settings related to typography. Generate custom CSS custom properties of the form `--wp--custom--{key}--{nested-key}: {value};`. `camelCased` keys are transformed to `kebab-case` as to follow the CSS property naming schema. Keys at different depth levels are separated by `--`, so keys should not include `--` in the name. ---- - -### behaviors - -Settings related to behaviors. - -| Property | Type | Default | Props | -| --- | --- | --- |--- | -| lightbox | boolean | false | | - --- ## Styles diff --git a/lib/class-wp-rest-global-styles-controller-gutenberg.php b/lib/class-wp-rest-global-styles-controller-gutenberg.php index 499a410b16f8e..8125b2ebf1c28 100644 --- a/lib/class-wp-rest-global-styles-controller-gutenberg.php +++ b/lib/class-wp-rest-global-styles-controller-gutenberg.php @@ -302,7 +302,6 @@ public function update_item( $request ) { * * @since 5.9.0 * @since 6.2.0 Added validation of styles.css property. - * @since 6.4.0 Added validation of behaviors property. * * @param WP_REST_Request $request Request object. * @return stdClass|WP_Error Prepared item on success. WP_Error on when the custom CSS is not valid. @@ -322,7 +321,7 @@ protected function prepare_item_for_database( $request ) { } } - if ( isset( $request['styles'] ) || isset( $request['settings'] ) || isset( $request['behaviors'] ) ) { + if ( isset( $request['styles'] ) || isset( $request['settings'] ) ) { $config = array(); if ( isset( $request['styles'] ) ) { if ( isset( $request['styles']['css'] ) ) { @@ -340,11 +339,6 @@ protected function prepare_item_for_database( $request ) { } elseif ( isset( $existing_config['settings'] ) ) { $config['settings'] = $existing_config['settings']; } - if ( isset( $request['behaviors'] ) ) { - $config['behaviors'] = $request['behaviors']; - } elseif ( isset( $existing_config['behaviors'] ) ) { - $config['behaviors'] = $existing_config['behaviors']; - } $config['isGlobalStylesUserThemeJSON'] = true; $config['version'] = WP_Theme_JSON_Gutenberg::LATEST_SCHEMA; $changes->post_content = wp_json_encode( $config ); @@ -367,7 +361,6 @@ protected function prepare_item_for_database( $request ) { * * @since 5.9.0 * @since 6.2.0 Handling of style.css was added to WP_Theme_JSON. - * @since 6.4.0 Added `behavior` field. * * @param WP_Post $post Global Styles post object. * @param WP_REST_Request $request Request object. @@ -411,10 +404,6 @@ public function prepare_item_for_response( $post, $request ) { // phpcs:ignore V $data['styles'] = ! empty( $config['styles'] ) && $is_global_styles_user_theme_json ? $config['styles'] : new stdClass(); } - if ( rest_is_field_included( 'behaviors', $fields ) ) { - $data['behaviors'] = ! empty( $config['behaviors'] ) && $is_global_styles_user_theme_json ? $config['behaviors'] : new stdClass(); - } - $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; $data = $this->add_additional_fields_to_object( $data, $request ); $data = $this->filter_response_by_context( $data, $context ); @@ -521,7 +510,6 @@ public function get_collection_params() { * Retrieves the global styles type' schema, conforming to JSON Schema. * * @since 5.9.0 - * @since 6.4.0 Added `behaviors` property. * * @return array Item schema data. */ @@ -535,28 +523,23 @@ public function get_item_schema() { 'title' => $this->post_type, 'type' => 'object', 'properties' => array( - 'id' => array( + 'id' => array( 'description' => __( 'ID of global styles config.', 'gutenberg' ), 'type' => 'string', 'context' => array( 'embed', 'view', 'edit' ), 'readonly' => true, ), - 'styles' => array( + 'styles' => array( 'description' => __( 'Global styles.', 'gutenberg' ), 'type' => array( 'object' ), 'context' => array( 'view', 'edit' ), ), - 'settings' => array( + 'settings' => array( 'description' => __( 'Global settings.', 'gutenberg' ), 'type' => array( 'object' ), 'context' => array( 'view', 'edit' ), ), - 'behaviors' => array( - 'description' => __( 'Global behaviors.', 'default' ), - 'type' => array( 'object' ), - 'context' => array( 'view', 'edit' ), - ), - 'title' => array( + 'title' => array( 'description' => __( 'Title of the global styles variation.', 'gutenberg' ), 'type' => array( 'object', 'string' ), 'default' => '', @@ -614,7 +597,6 @@ public function get_theme_item_permissions_check( $request ) { // phpcs:ignore V * Returns the given theme global styles config. * * @since 5.9.0 - * @since 6.4.0 Added value for `behaviors` rest field. * * @param WP_REST_Request $request The request instance. * @return WP_REST_Response|WP_Error @@ -642,11 +624,6 @@ public function get_theme_item( $request ) { $data['styles'] = isset( $raw_data['styles'] ) ? $raw_data['styles'] : array(); } - if ( rest_is_field_included( 'behaviors', $fields ) ) { - $raw_data = $theme->get_raw_data(); - $data['behaviors'] = isset( $raw_data['behaviors'] ) ? $raw_data['behaviors'] : array(); - } - $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; $data = $this->add_additional_fields_to_object( $data, $request ); $data = $this->filter_response_by_context( $data, $context ); diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php index 7aa165ecc0635..330b336bbd0a2 100644 --- a/lib/class-wp-theme-json-gutenberg.php +++ b/lib/class-wp-theme-json-gutenberg.php @@ -331,7 +331,6 @@ class WP_Theme_JSON_Gutenberg { 'templateParts', 'title', 'version', - 'behaviors', ); /** @@ -419,7 +418,6 @@ class WP_Theme_JSON_Gutenberg { 'textTransform' => null, 'writingMode' => null, ), - 'behaviors' => null, ); /** diff --git a/lib/compat/wordpress-6.4/class-gutenberg-rest-global-styles-revisions-controller-6-4.php b/lib/compat/wordpress-6.4/class-gutenberg-rest-global-styles-revisions-controller-6-4.php index 75b3916a1697d..910f6973e53f8 100644 --- a/lib/compat/wordpress-6.4/class-gutenberg-rest-global-styles-revisions-controller-6-4.php +++ b/lib/compat/wordpress-6.4/class-gutenberg-rest-global-styles-revisions-controller-6-4.php @@ -19,7 +19,6 @@ class Gutenberg_REST_Global_Styles_Revisions_Controller_6_4 extends Gutenberg_RE * Prepares the revision for the REST response. * * @since 6.3.0 - * @since 6.4.0 Added `behaviors` field to the response. * * @param WP_Post $post Post revision object. * @param WP_REST_Request $request Request object. @@ -36,7 +35,7 @@ public function prepare_item_for_response( $post, $request ) { $fields = $this->get_fields_for_response( $request ); $data = array(); - if ( ! empty( $global_styles_config['styles'] ) || ! empty( $global_styles_config['settings'] ) || ! empty( $global_styles_config['behaviors'] ) ) { + if ( ! empty( $global_styles_config['styles'] ) || ! empty( $global_styles_config['settings'] ) ) { $global_styles_config = ( new WP_Theme_JSON_Gutenberg( $global_styles_config, 'custom' ) )->get_raw_data(); if ( rest_is_field_included( 'settings', $fields ) ) { $data['settings'] = ! empty( $global_styles_config['settings'] ) ? $global_styles_config['settings'] : new stdClass(); @@ -44,9 +43,6 @@ public function prepare_item_for_response( $post, $request ) { if ( rest_is_field_included( 'styles', $fields ) ) { $data['styles'] = ! empty( $global_styles_config['styles'] ) ? $global_styles_config['styles'] : new stdClass(); } - if ( rest_is_field_included( 'behaviors', $fields ) ) { - $data['behaviors'] = ! empty( $global_styles_config['behaviors'] ) ? $global_styles_config['behaviors'] : new stdClass(); - } } if ( rest_is_field_included( 'author', $fields ) ) { @@ -88,7 +84,6 @@ public function prepare_item_for_response( $post, $request ) { * Retrieves the revision's schema, conforming to JSON Schema. * * @since 6.3.0 - * @since 6.4.0 Added `behaviors` field to the schema properties. * * @return array Item schema data. */ @@ -159,11 +154,6 @@ public function get_item_schema() { 'type' => array( 'object' ), 'context' => array( 'view', 'edit' ), ), - 'behaviors' => array( - 'description' => __( 'Global behaviors.', 'gutenberg' ), - 'type' => array( 'object' ), - 'context' => array( 'view', 'edit' ), - ), ), ); diff --git a/lib/load.php b/lib/load.php index c0b69e2ab2ca0..c749294003012 100644 --- a/lib/load.php +++ b/lib/load.php @@ -231,5 +231,4 @@ function gutenberg_is_experiment_enabled( $name ) { require __DIR__ . '/block-supports/dimensions.php'; require __DIR__ . '/block-supports/duotone.php'; require __DIR__ . '/block-supports/shadow.php'; -require __DIR__ . '/block-supports/behaviors.php'; require __DIR__ . '/block-supports/background.php'; diff --git a/lib/theme.json b/lib/theme.json index 5c64526b1a253..91990215470b9 100644 --- a/lib/theme.json +++ b/lib/theme.json @@ -1,15 +1,5 @@ { "version": 2, - "behaviors": { - "blocks": { - "core/image": { - "lightbox": { - "enabled": false, - "animation": "" - } - } - } - }, "settings": { "appearanceTools": false, "useRootPaddingAwareAlignments": false, @@ -290,11 +280,6 @@ "style": true, "width": true } - }, - "core/image": { - "behaviors": { - "lightbox": true - } } } }, diff --git a/packages/block-editor/src/components/global-styles/behaviors-panel.js b/packages/block-editor/src/components/global-styles/behaviors-panel.js deleted file mode 100644 index fa8c2305ae037..0000000000000 --- a/packages/block-editor/src/components/global-styles/behaviors-panel.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * WordPress dependencies - */ -import { SelectControl } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; - -export default function ( { onChange, value, behaviors } ) { - const defaultBehaviors = { - default: { - value: 'default', - label: __( 'Default' ), - }, - noBehaviors: { - value: '', - label: __( 'No behaviors' ), - }, - }; - - const behaviorsOptions = Object.entries( behaviors ).map( - ( [ behaviorName ] ) => ( { - value: behaviorName, - // Capitalize the first letter of the behavior name. - label: `${ behaviorName.charAt( 0 ).toUpperCase() }${ behaviorName - .slice( 1 ) - .toLowerCase() }`, - } ) - ); - - const options = [ - ...Object.values( defaultBehaviors ), - ...behaviorsOptions, - ]; - - const animations = [ - { - value: 'zoom', - label: __( 'Zoom' ), - }, - { - value: 'fade', - label: __( 'Fade' ), - }, - ]; - return ( -
- - { value === 'lightbox' && ( - - ) } -
- ); -} diff --git a/packages/block-editor/src/components/global-styles/hooks.js b/packages/block-editor/src/components/global-styles/hooks.js index abd7ebc61b7c7..7d81e0d4d224d 100644 --- a/packages/block-editor/src/components/global-styles/hooks.js +++ b/packages/block-editor/src/components/global-styles/hooks.js @@ -8,7 +8,7 @@ import fastDeepEqual from 'fast-deep-equal/es6'; */ import { useContext, useCallback, useMemo } from '@wordpress/element'; import { useSelect } from '@wordpress/data'; -import { store as blocksStore, hasBlockSupport } from '@wordpress/blocks'; +import { store as blocksStore } from '@wordpress/blocks'; import { _x } from '@wordpress/i18n'; /** @@ -19,11 +19,10 @@ import { getValueFromObjectPath, setImmutably } from '../../utils/object'; import { GlobalStylesContext } from './context'; import { unlock } from '../../lock-unlock'; -const EMPTY_CONFIG = { settings: {}, styles: {}, behaviors: {} }; +const EMPTY_CONFIG = { settings: {}, styles: {} }; const VALID_SETTINGS = [ 'appearanceTools', - 'behaviors', 'useRootPaddingAwareAlignments', 'border.color', 'border.radius', @@ -461,112 +460,3 @@ export function useGradientsPerOrigin( settings ) { shouldDisplayDefaultGradients, ] ); } - -export function __experimentalUseGlobalBehaviors( blockName, source = 'all' ) { - const { - merged: mergedConfig, - base: baseConfig, - user: userConfig, - setUserConfig, - } = useContext( GlobalStylesContext ); - const finalPath = ! blockName - ? `behaviors` - : `behaviors.blocks.${ blockName }`; - - let rawResult, result; - switch ( source ) { - case 'all': - rawResult = getValueFromObjectPath( mergedConfig, finalPath ); - result = getValueFromVariable( mergedConfig, blockName, rawResult ); - break; - case 'user': - rawResult = getValueFromObjectPath( userConfig, finalPath ); - result = getValueFromVariable( mergedConfig, blockName, rawResult ); - break; - case 'base': - rawResult = getValueFromObjectPath( baseConfig, finalPath ); - result = getValueFromVariable( baseConfig, blockName, rawResult ); - break; - default: - throw 'Unsupported source'; - } - - const animation = result?.lightbox?.animation || 'zoom'; - - const setBehavior = ( newValue ) => { - let newBehavior; - // The user saves with Apply Globally option. - if ( typeof newValue === 'object' ) { - newBehavior = newValue; - } else { - switch ( newValue ) { - case 'lightbox': - newBehavior = { - lightbox: { - enabled: true, - animation, - }, - }; - break; - case 'fade': - newBehavior = { - lightbox: { - enabled: true, - animation: 'fade', - }, - }; - break; - case 'zoom': - newBehavior = { - lightbox: { - enabled: true, - animation: 'zoom', - }, - }; - break; - case '': - newBehavior = { - lightbox: { - enabled: false, - animation, - }, - }; - break; - default: - break; - } - } - setUserConfig( ( currentConfig ) => - setImmutably( currentConfig, finalPath.split( '.' ), newBehavior ) - ); - }; - let behavior = ''; - if ( result === undefined ) behavior = 'default'; - if ( result?.lightbox.enabled ) behavior = 'lightbox'; - - return { behavior, inheritedBehaviors: result, setBehavior }; -} - -export function __experimentalUseHasBehaviorsPanel( - settings, - name, - { blockSupportOnly = false } = {} -) { - if ( ! settings?.behaviors ) { - return false; - } - - // If every behavior is disabled on block supports, do not show the behaviors inspector control. - const hasSomeBlockSupport = Object.keys( settings?.behaviors ).some( - ( key ) => hasBlockSupport( name, `behaviors.${ key }` ) - ); - - if ( blockSupportOnly ) { - return hasSomeBlockSupport; - } - - // If every behavior is disabled, do not show the behaviors inspector control. - return Object.values( settings?.behaviors ).some( - ( value ) => value === true && hasSomeBlockSupport - ); -} diff --git a/packages/block-editor/src/components/global-styles/index.js b/packages/block-editor/src/components/global-styles/index.js index ee5c66ebe8a65..24bab543b9ada 100644 --- a/packages/block-editor/src/components/global-styles/index.js +++ b/packages/block-editor/src/components/global-styles/index.js @@ -1,6 +1,4 @@ export { - __experimentalUseGlobalBehaviors, - __experimentalUseHasBehaviorsPanel, useGlobalStylesReset, useGlobalSetting, useGlobalStyle, @@ -25,6 +23,5 @@ export { default as BorderPanel, useHasBorderPanel } from './border-panel'; export { default as ColorPanel, useHasColorPanel } from './color-panel'; export { default as EffectsPanel, useHasEffectsPanel } from './effects-panel'; export { default as FiltersPanel, useHasFiltersPanel } from './filters-panel'; -export { default as __experimentalBehaviorsPanel } from './behaviors-panel'; export { default as AdvancedPanel } from './advanced-panel'; export { areGlobalStyleConfigsEqual } from './utils'; diff --git a/packages/block-editor/src/components/global-styles/utils.js b/packages/block-editor/src/components/global-styles/utils.js index 8f9e1f1f39600..d4f2d959a3365 100644 --- a/packages/block-editor/src/components/global-styles/utils.js +++ b/packages/block-editor/src/components/global-styles/utils.js @@ -415,7 +415,6 @@ export function areGlobalStyleConfigsEqual( original, variation ) { } return ( fastDeepEqual( original?.styles, variation?.styles ) && - fastDeepEqual( original?.settings, variation?.settings ) && - fastDeepEqual( original?.behaviors, variation?.behaviors ) + fastDeepEqual( original?.settings, variation?.settings ) ); } diff --git a/packages/block-editor/src/hooks/behaviors.js b/packages/block-editor/src/hooks/behaviors.js deleted file mode 100644 index ab44edbfa8fd8..0000000000000 --- a/packages/block-editor/src/hooks/behaviors.js +++ /dev/null @@ -1,206 +0,0 @@ -/** - * WordPress dependencies - */ -import { addFilter } from '@wordpress/hooks'; -import { SelectControl } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; -import { hasBlockSupport } from '@wordpress/blocks'; -import { createHigherOrderComponent } from '@wordpress/compose'; -import { useSelect } from '@wordpress/data'; -import { useMemo } from '@wordpress/element'; - -/** - * Internal dependencies - */ -import { store as blockEditorStore } from '../store'; -import { InspectorControls } from '../components'; - -function BehaviorsControl( { - blockName, - blockBehaviors, - onChangeBehavior, - onChangeAnimation, - disabled = false, -} ) { - const { settings } = useSelect( - ( select ) => { - const { getSettings } = select( blockEditorStore ); - return { - settings: - getSettings()?.__experimentalFeatures?.blocks?.[ blockName ] - ?.behaviors || {}, - }; - }, - [ blockName ] - ); - - const defaultBehaviors = { - default: { - value: 'default', - label: __( 'Default' ), - }, - noBehaviors: { - value: '', - label: __( 'No behaviors' ), - }, - }; - const behaviorsOptions = Object.entries( settings ) - .filter( - ( [ behaviorName, behaviorValue ] ) => - hasBlockSupport( blockName, `behaviors.${ behaviorName }` ) && - behaviorValue - ) // Filter out behaviors that are disabled. - .map( ( [ behaviorName ] ) => ( { - value: behaviorName, - // Capitalize the first letter of the behavior name. - label: `${ behaviorName.charAt( 0 ).toUpperCase() }${ behaviorName - .slice( 1 ) - .toLowerCase() }`, - } ) ); - const options = [ - ...Object.values( defaultBehaviors ), - ...behaviorsOptions, - ]; - - const { behaviors, behaviorsValue } = useMemo( () => { - const mergedBehaviors = { - ...( blockBehaviors || {} ), - }; - - let value = ''; - if ( blockBehaviors === undefined ) { - value = 'default'; - } - if ( blockBehaviors?.lightbox.enabled ) { - value = 'lightbox'; - } - return { - behaviors: mergedBehaviors, - behaviorsValue: value, - }; - }, [ blockBehaviors ] ); - - // If every behavior is disabled, do not show the behaviors inspector control. - if ( behaviorsOptions.length === 0 ) { - return null; - } - - const helpText = disabled - ? __( 'The lightbox behavior is disabled for linked images.' ) - : ''; - - return ( - -
- - { behaviorsValue === 'lightbox' && ( - - ) } -
-
- ); -} - -/** - * Override the default edit UI to include a new block inspector control for - * assigning behaviors to blocks if behaviors are enabled in the theme.json. - * - * Currently, only the `core/image` block is supported. - * - * @param {WPComponent} BlockEdit Original component. - * - * @return {WPComponent} Wrapped component. - */ -export const withBehaviors = createHigherOrderComponent( ( BlockEdit ) => { - return ( props ) => { - const blockEdit = ; - // Only add behaviors to blocks with support. - if ( ! hasBlockSupport( props.name, 'behaviors' ) ) { - return blockEdit; - } - const blockHasLink = - typeof props.attributes?.linkDestination !== 'undefined' && - props.attributes?.linkDestination !== 'none'; - return ( - <> - { blockEdit } - { - if ( nextValue === 'default' ) { - props.setAttributes( { - behaviors: undefined, - } ); - } else { - // If the user selects something, it means that they want to - // change the default value (true) so we save it in the attributes. - props.setAttributes( { - behaviors: { - lightbox: { - enabled: nextValue === 'lightbox', - animation: - nextValue === 'lightbox' - ? 'zoom' - : '', - }, - }, - } ); - } - } } - onChangeAnimation={ ( nextValue ) => { - props.setAttributes( { - behaviors: { - lightbox: { - enabled: - props.attributes.behaviors.lightbox - .enabled, - animation: nextValue, - }, - }, - } ); - } } - disabled={ blockHasLink } - /> - - ); - }; -}, 'withBehaviors' ); - -addFilter( - 'editor.BlockEdit', - 'core/behaviors/with-inspector-control', - withBehaviors -); diff --git a/packages/block-editor/src/hooks/index.js b/packages/block-editor/src/hooks/index.js index 0f6d52cc2c00d..8ae5c1dbe3a7e 100644 --- a/packages/block-editor/src/hooks/index.js +++ b/packages/block-editor/src/hooks/index.js @@ -20,7 +20,6 @@ import './layout'; import './content-lock-ui'; import './metadata'; import './metadata-name'; -import './behaviors'; import './custom-fields'; import './block-hooks'; import './block-rename-ui'; diff --git a/packages/block-library/src/image/block.json b/packages/block-library/src/image/block.json index 005f322722d70..a360e59528126 100644 --- a/packages/block-library/src/image/block.json +++ b/packages/block-library/src/image/block.json @@ -90,9 +90,6 @@ }, "supports": { "anchor": true, - "behaviors": { - "lightbox": true - }, "color": { "text": false, "background": false diff --git a/packages/block-library/src/image/deprecated.js b/packages/block-library/src/image/deprecated.js index d159009b17373..83816e1e3f74e 100644 --- a/packages/block-library/src/image/deprecated.js +++ b/packages/block-library/src/image/deprecated.js @@ -632,9 +632,6 @@ const v6 = { }, supports: { anchor: true, - behaviors: { - lightbox: true, - }, color: { text: false, background: false, @@ -830,9 +827,6 @@ const v7 = { }, supports: { anchor: true, - behaviors: { - lightbox: true, - }, color: { text: false, background: false, diff --git a/packages/block-library/src/image/index.php b/packages/block-library/src/image/index.php index 0a9f8f60ca107..fceba38244033 100644 --- a/packages/block-library/src/image/index.php +++ b/packages/block-library/src/image/index.php @@ -33,17 +33,10 @@ function render_block_core_image( $attributes, $content, $block ) { $should_load_view_script = false; $link_destination = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none'; + // Get the lightbox setting from the block attributes. - if ( isset( $attributes['behaviors']['lightbox'] ) ) { - $lightbox_settings = $attributes['behaviors']['lightbox']; - // If the lightbox setting is not set in the block attributes, get it from the theme.json file. - } else { - $theme_data = WP_Theme_JSON_Resolver_Gutenberg::get_merged_data()->get_data(); - if ( isset( $theme_data['behaviors']['blocks'][ $block->name ]['lightbox'] ) ) { - $lightbox_settings = $theme_data['behaviors']['blocks'][ $block->name ]['lightbox']; - } else { - $lightbox_settings = null; - } + if ( isset( $attributes['lightbox'] ) ) { + $lightbox_settings = $attributes['lightbox']; } // If the lightbox is enabled, the image is not linked, and the Interactivity API is enabled, load the view script. @@ -76,6 +69,202 @@ function render_block_core_image( $attributes, $content, $block ) { return $processor->get_updated_html(); } + +/** + * Add the directives and layout needed for the lightbox behavior. + * + * @param string $block_content Rendered block content. + * @param array $block Block object. + * @return string Filtered block content. + */ +function block_core_image_render_lightbox( $block_content, $block ) { + $link_destination = isset( $block['attrs']['linkDestination'] ) ? $block['attrs']['linkDestination'] : 'none'; + + // Get the lightbox setting from the block attributes. + if ( isset( $block['attrs']['lightbox'] ) ) { + $lightbox_settings = $block['attrs']['lightbox']; + } + + if ( ! isset( $lightbox_settings ) || 'none' !== $link_destination ) { + return $block_content; + } + + if ( isset( $lightbox_settings['enabled'] ) && false === $lightbox_settings['enabled'] ) { + return $block_content; + } + + $processor = new WP_HTML_Tag_Processor( $block_content ); + + $aria_label = __( 'Enlarge image', 'gutenberg' ); + + $alt_attribute = $processor->get_attribute( 'alt' ); + + if ( null !== $alt_attribute ) { + $alt_attribute = trim( $alt_attribute ); + } + + if ( $alt_attribute ) { + /* translators: %s: Image alt text. */ + $aria_label = sprintf( __( 'Enlarge image: %s', 'gutenberg' ), $alt_attribute ); + } + $content = $processor->get_updated_html(); + + // Currently, the only supported animation is 'zoom'. + $lightbox_animation = 'zoom'; + + // We want to store the src in the context so we can set it dynamically when the lightbox is opened. + $z = new WP_HTML_Tag_Processor( $content ); + $z->next_tag( 'img' ); + + if ( isset( $block['attrs']['id'] ) ) { + $img_uploaded_src = wp_get_attachment_url( $block['attrs']['id'] ); + $img_metadata = wp_get_attachment_metadata( $block['attrs']['id'] ); + $img_width = $img_metadata['width']; + $img_height = $img_metadata['height']; + } else { + $img_uploaded_src = $z->get_attribute( 'src' ); + $img_width = 'none'; + $img_height = 'none'; + } + + if ( isset( $block['attrs']['scale'] ) ) { + $scale_attr = $block['attrs']['scale']; + } else { + $scale_attr = false; + } + + $w = new WP_HTML_Tag_Processor( $content ); + $w->next_tag( 'figure' ); + $w->add_class( 'wp-lightbox-container' ); + $w->set_attribute( 'data-wp-interactive', true ); + + $w->set_attribute( + 'data-wp-context', + sprintf( + '{ "core": + { "image": + { "imageLoaded": false, + "initialized": false, + "lightboxEnabled": false, + "hideAnimationEnabled": false, + "preloadInitialized": false, + "lightboxAnimation": "%s", + "imageUploadedSrc": "%s", + "imageCurrentSrc": "", + "targetWidth": "%s", + "targetHeight": "%s", + "scaleAttr": "%s" + } + } + }', + $lightbox_animation, + $img_uploaded_src, + $img_width, + $img_height, + $scale_attr + ) + ); + $w->next_tag( 'img' ); + $w->set_attribute( 'data-wp-init', 'effects.core.image.setCurrentSrc' ); + $w->set_attribute( 'data-wp-on--load', 'actions.core.image.handleLoad' ); + $w->set_attribute( 'data-wp-effect', 'effects.core.image.setButtonStyles' ); + $body_content = $w->get_updated_html(); + + // Wrap the image in the body content with a button. + $img = null; + preg_match( '/]+>/', $body_content, $img ); + $button = + '' + . $img[0]; + $body_content = preg_replace( '/]+>/', $button, $body_content ); + + // We need both a responsive image and an enlarged image to animate + // 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( $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.core.image.imageCurrentSrc' ); + $m->set_attribute( 'data-wp-style--object-fit', 'selectors.core.image.lightboxObjectFit' ); + $initial_image_content = $m->get_updated_html(); + + $q = new WP_HTML_Tag_Processor( $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 + // on initial page load, then bind the attribute to a selector that returns the full-sized image src when + // 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', 'selectors.core.image.enlargedImgSrc' ); + $q->set_attribute( 'data-wp-style--object-fit', 'selectors.core.image.lightboxObjectFit' ); + $enlarged_image_content = $q->get_updated_html(); + + $background_color = esc_attr( wp_get_global_styles( array( 'color', 'background' ) ) ); + + $close_button_icon = ''; + $close_button_color = esc_attr( wp_get_global_styles( array( 'color', 'text' ) ) ); + $dialog_label = $alt_attribute ? esc_attr( $alt_attribute ) : esc_attr__( 'Image', 'gutenberg' ); + $close_button_label = esc_attr__( 'Close', 'gutenberg' ); + + $lightbox_html = << + + + +
+ +HTML; + + return str_replace( '', $lightbox_html . '', $body_content ); +} + +// TODO: We should not be adding a separate filter but rather move the +// the lightbox rendering to the `render_block_core_image` function. + +// Use priority 15 to run this hook after other hooks/plugins. +// They could use the `render_block_{$this->name}` filter to modify the markup. +add_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15, 2 ); + /** * Registers the `core/image` block on server. */ diff --git a/packages/edit-site/src/components/global-styles/global-styles-provider.js b/packages/edit-site/src/components/global-styles/global-styles-provider.js index 250cca0ebfc6d..1e2d43e267a2d 100644 --- a/packages/edit-site/src/components/global-styles/global-styles-provider.js +++ b/packages/edit-site/src/components/global-styles/global-styles-provider.js @@ -31,7 +31,7 @@ export function mergeBaseAndUserConfigs( base, user ) { } function useGlobalStylesUserConfig() { - const { globalStylesId, isReady, settings, styles, behaviors } = useSelect( + const { globalStylesId, isReady, settings, styles } = useSelect( ( select ) => { const { getEditedEntityRecord, hasFinishedResolution } = select( coreStore ); @@ -65,7 +65,6 @@ function useGlobalStylesUserConfig() { isReady: hasResolved, settings: record?.settings, styles: record?.styles, - behaviors: record?.behaviors, }; }, [] @@ -77,9 +76,8 @@ function useGlobalStylesUserConfig() { return { settings: settings ?? {}, styles: styles ?? {}, - behaviors: behaviors ?? {}, }; - }, [ settings, styles, behaviors ] ); + }, [ settings, styles ] ); const setConfig = useCallback( ( callback, options = {} ) => { @@ -91,7 +89,6 @@ function useGlobalStylesUserConfig() { const currentConfig = { styles: record?.styles ?? {}, settings: record?.settings ?? {}, - behaviors: record?.behaviors ?? {}, }; const updatedConfig = callback( currentConfig ); editEntityRecord( @@ -101,8 +98,6 @@ function useGlobalStylesUserConfig() { { styles: cleanEmptyObject( updatedConfig.styles ) || {}, settings: cleanEmptyObject( updatedConfig.settings ) || {}, - behaviors: - cleanEmptyObject( updatedConfig.behaviors ) || {}, }, options ); diff --git a/packages/edit-site/src/components/global-styles/screen-block.js b/packages/edit-site/src/components/global-styles/screen-block.js index 87dae3c8f2f36..f683c559e59bc 100644 --- a/packages/edit-site/src/components/global-styles/screen-block.js +++ b/packages/edit-site/src/components/global-styles/screen-block.js @@ -61,15 +61,12 @@ const { useHasDimensionsPanel, useHasTypographyPanel, useHasBorderPanel, - __experimentalUseHasBehaviorsPanel: useHasBehaviorsPanel, useGlobalSetting, useSettingsForBlockElement, useHasColorPanel, useHasEffectsPanel, useHasFiltersPanel, useGlobalStyle, - __experimentalUseGlobalBehaviors: useGlobalBehaviors, - __experimentalBehaviorsPanel: StylesBehaviorsPanel, BorderPanel: StylesBorderPanel, ColorPanel: StylesColorPanel, TypographyPanel: StylesTypographyPanel, @@ -94,9 +91,6 @@ function ScreenBlock( { name, variation } ) { } ); const [ rawSettings, setSettings ] = useGlobalSetting( '', name ); const settings = useSettingsForBlockElement( rawSettings, name ); - const { inheritedBehaviors, setBehavior } = useGlobalBehaviors( name ); - const { behavior } = useGlobalBehaviors( name, 'user' ); - const blockType = getBlockType( name ); // Only allow `blockGap` support if serialization has not been skipped, to be sure global spacing can be applied. @@ -115,7 +109,6 @@ function ScreenBlock( { name, variation } ) { const blockVariations = useBlockVariations( name ); const hasTypographyPanel = useHasTypographyPanel( settings ); const hasColorPanel = useHasColorPanel( settings ); - const hasBehaviorsPanel = useHasBehaviorsPanel( rawSettings, name ); const hasBorderPanel = useHasBorderPanel( settings ); const hasDimensionsPanel = useHasDimensionsPanel( settings ); const hasEffectsPanel = useHasEffectsPanel( settings ); @@ -288,14 +281,6 @@ function ScreenBlock( { name, variation } ) { onChange={ setStyle } inheritedValue={ inheritedStyle } /> - { hasBehaviorsPanel && ( - - ) } ) } diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/index.js b/packages/edit-site/src/components/global-styles/screen-revisions/index.js index 7af3d40ec2c75..46a7a8c74ab69 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/index.js +++ b/packages/edit-site/src/components/global-styles/screen-revisions/index.js @@ -71,7 +71,6 @@ function ScreenRevisions() { setUserConfig( () => ( { styles: revision?.styles, settings: revision?.settings, - behaviors: revision?.behaviors, } ) ); setIsLoadingRevisionWithUnsavedChanges( false ); onCloseRevisions(); @@ -81,7 +80,6 @@ function ScreenRevisions() { setGlobalStylesRevision( { styles: revision?.styles || {}, settings: revision?.settings || {}, - behaviors: revision?.behaviors || {}, id: revision?.id, } ); setSelectedRevisionId( revision?.id ); diff --git a/packages/edit-site/src/components/global-styles/screen-revisions/use-global-styles-revisions.js b/packages/edit-site/src/components/global-styles/screen-revisions/use-global-styles-revisions.js index 02e4a63154ec6..6e3573061a421 100644 --- a/packages/edit-site/src/components/global-styles/screen-revisions/use-global-styles-revisions.js +++ b/packages/edit-site/src/components/global-styles/screen-revisions/use-global-styles-revisions.js @@ -89,7 +89,6 @@ export default function useGlobalStylesRevisions() { id: 'unsaved', styles: userConfig?.styles, settings: userConfig?.settings, - behaviors: userConfig?.behaviors, author: { name: currentUser?.name, avatar_urls: currentUser?.avatar_urls, diff --git a/packages/edit-site/src/components/global-styles/style-variations-container.js b/packages/edit-site/src/components/global-styles/style-variations-container.js index 69a66a707d252..6cc8b53b800d3 100644 --- a/packages/edit-site/src/components/global-styles/style-variations-container.js +++ b/packages/edit-site/src/components/global-styles/style-variations-container.js @@ -113,13 +113,11 @@ export default function StyleVariationsContainer() { title: __( 'Default' ), settings: {}, styles: {}, - behaviors: {}, }, ...( variations ?? [] ).map( ( variation ) => ( { ...variation, settings: variation.settings ?? {}, styles: variation.styles ?? {}, - behaviors: variation.behaviors ?? {}, } ) ), ]; }, [ variations ] ); diff --git a/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js b/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js index bd751ef4b312b..f90bf30ce0211 100644 --- a/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js +++ b/packages/edit-site/src/hooks/push-changes-to-global-styles/index.js @@ -26,12 +26,9 @@ import { store as noticesStore } from '@wordpress/notices'; import { useSupportedStyles } from '../../components/global-styles/hooks'; import { unlock } from '../../lock-unlock'; -const { - cleanEmptyObject, - GlobalStylesContext, - __experimentalUseGlobalBehaviors: useGlobalBehaviors, - __experimentalUseHasBehaviorsPanel: useHasBehaviorsPanel, -} = unlock( blockEditorPrivateApis ); +const { cleanEmptyObject, GlobalStylesContext } = unlock( + blockEditorPrivateApis +); // Block Gap is a special case and isn't defined within the blocks // style properties config. We'll add it here to allow it to be pushed @@ -286,10 +283,6 @@ function PushChangesToGlobalStylesControl( { attributes, setAttributes, } ) { - const hasBehaviorsPanel = useHasBehaviorsPanel( attributes, name, { - blockSupportOnly: true, - } ); - const { user: userConfig, setUserConfig } = useContext( GlobalStylesContext ); @@ -299,13 +292,8 @@ function PushChangesToGlobalStylesControl( { useDispatch( blockEditorStore ); const { createSuccessNotice } = useDispatch( noticesStore ); - const { inheritedBehaviors, setBehavior } = useGlobalBehaviors( name ); - - const userHasEditedBehaviors = - attributes.hasOwnProperty( 'behaviors' ) && hasBehaviorsPanel; - const pushChanges = useCallback( () => { - if ( changes.length === 0 && ! userHasEditedBehaviors ) { + if ( changes.length === 0 ) { return; } @@ -364,46 +352,15 @@ function PushChangesToGlobalStylesControl( { } ); } - - if ( userHasEditedBehaviors ) { - __unstableMarkNextChangeAsNotPersistent(); - setAttributes( { behaviors: undefined } ); - setBehavior( attributes.behaviors ); - createSuccessNotice( - sprintf( - // translators: %s: Title of the block e.g. 'Heading'. - __( '%s behaviors applied.' ), - getBlockType( name ).title - ), - { - type: 'snackbar', - actions: [ - { - label: __( 'Undo' ), - onClick() { - __unstableMarkNextChangeAsNotPersistent(); - setBehavior( inheritedBehaviors ); - setUserConfig( () => userConfig, { - undoIgnore: true, - } ); - }, - }, - ], - } - ); - } }, [ __unstableMarkNextChangeAsNotPersistent, attributes, changes, createSuccessNotice, - inheritedBehaviors, name, setAttributes, - setBehavior, setUserConfig, userConfig, - userHasEditedBehaviors, ] ); return ( @@ -412,7 +369,7 @@ function PushChangesToGlobalStylesControl( { help={ sprintf( // translators: %s: Title of the block e.g. 'Heading'. __( - 'Apply this block’s typography, spacing, dimensions, color styles, and behaviors to all %s blocks.' + 'Apply this block’s typography, spacing, dimensions, and color styles to all %s blocks.' ), getBlockType( name ).title ) } @@ -422,7 +379,7 @@ function PushChangesToGlobalStylesControl( {