diff --git a/backport-changelog/6.8/7069.md b/backport-changelog/6.8/7069.md
deleted file mode 100644
index 3e734637ddbb2f..00000000000000
--- a/backport-changelog/6.8/7069.md
+++ /dev/null
@@ -1,6 +0,0 @@
-https://github.com/WordPress/wordpress-develop/pull/7069
-
-* https://github.com/WordPress/gutenberg/pull/63401
-* https://github.com/WordPress/gutenberg/pull/66918
-* https://github.com/WordPress/gutenberg/pull/67018
-* https://github.com/WordPress/gutenberg/pull/67552
diff --git a/backport-changelog/6.8/8031.md b/backport-changelog/6.8/8031.md
new file mode 100644
index 00000000000000..864dd7562cdf36
--- /dev/null
+++ b/backport-changelog/6.8/8031.md
@@ -0,0 +1,4 @@
+https://github.com/WordPress/wordpress-develop/pull/8031
+
+* https://github.com/WordPress/gutenberg/pull/66675
+* https://github.com/WordPress/gutenberg/pull/68243
diff --git a/docs/explanations/architecture/styles.md b/docs/explanations/architecture/styles.md
index 5f5e73d1372f7b..68f09f04d21d32 100644
--- a/docs/explanations/architecture/styles.md
+++ b/docs/explanations/architecture/styles.md
@@ -37,10 +37,8 @@ The user may change the state of this block by applying different styles: a text
After some user modifications to the block, the initial markup may become something like this:
```html
-
+
```
This is what we refer to as "user-provided block styles", also know as "local styles" or "serialized styles". Essentially, each tool (font size, color, etc) ends up adding some classes and/or inline styles to the block markup. The CSS styling for these classes is part of the block, global, or theme stylesheets.
@@ -125,7 +123,7 @@ The block supports API only serializes the font size value to the wrapper, resul
This is an active area of work you can follow [in the tracking issue](https://github.com/WordPress/gutenberg/issues/38167). The linked proposal is exploring a different way to serialize the user changes: instead of each block support serializing its own data (for example, classes such as `has-small-font-size`, `has-green-color`) the idea is the block would get a single class instead (for example, `wp-style-UUID`) and the CSS styling for that class will be generated in the server by WordPress.
-While work continues in that proposal, there's an escape hatch, an experimental option block authors can use. Any block support can skip the serialization to HTML markup by using `skipSerialization`. For example:
+While work continues in that proposal, there's an escape hatch, an experimental option block authors can use. Any block support can skip the serialization to HTML markup by using `__experimentalSkipSerialization`. For example:
```json
{
@@ -134,7 +132,7 @@ While work continues in that proposal, there's an escape hatch, an experimental
"supports": {
"typography": {
"fontSize": true,
- "skipSerialization": true
+ "__experimentalSkipSerialization": true
}
}
}
@@ -142,7 +140,7 @@ While work continues in that proposal, there's an escape hatch, an experimental
This means that the typography block support will do all of the things (create a UI control, bind the block attribute to the control, etc) except serializing the user values into the HTML markup. The classes and inline styles will not be automatically applied to the wrapper and it is the block author's responsibility to implement this in the `edit`, `save`, and `render_callback` functions. See [this issue](https://github.com/WordPress/gutenberg/issues/28913) for examples of how it was done for some blocks provided by WordPress.
-Note that, if `skipSerialization` is enabled for a group (typography, color, spacing) it affects _all_ block supports within this group. In the example above _all_ the properties within the `typography` group will be affected (e.g. `fontSize`, `lineHeight`, `fontFamily` .etc).
+Note that, if `__experimentalSkipSerialization` is enabled for a group (typography, color, spacing) it affects _all_ block supports within this group. In the example above _all_ the properties within the `typography` group will be affected (e.g. `fontSize`, `lineHeight`, `fontFamily` .etc).
To enable for a _single_ property only, you may use an array to declare which properties are to be skipped. In the example below, only `fontSize` will skip serialization, leaving other items within the `typography` group (e.g. `lineHeight`, `fontFamily` .etc) unaffected.
@@ -154,7 +152,7 @@ To enable for a _single_ property only, you may use an array to declare which pr
"typography": {
"fontSize": true,
"lineHeight": true,
- "skipSerialization": [ "fontSize" ]
+ "__experimentalSkipSerialization": [ "fontSize" ]
}
}
}
@@ -475,7 +473,7 @@ If blocks do this, they need to be registered in the server using the `block.jso
Every chunk of styles can only use a single selector.
-This is particularly relevant if the block is using `skipSerialization` to serialize the different style properties to different nodes other than the wrapper. See "Current limitations of blocks supports" for more.
+This is particularly relevant if the block is using `__experimentalSkipSerialization` to serialize the different style properties to different nodes other than the wrapper. See "Current limitations of blocks supports" for more.
#### 3. **Only a single property per block**
diff --git a/docs/getting-started/fundamentals/javascript-in-the-block-editor.md b/docs/getting-started/fundamentals/javascript-in-the-block-editor.md
index 7accc5d4c2129d..4cd7c0b36fe86a 100644
--- a/docs/getting-started/fundamentals/javascript-in-the-block-editor.md
+++ b/docs/getting-started/fundamentals/javascript-in-the-block-editor.md
@@ -26,7 +26,7 @@ The diagram below provides an overview of the build process when using the `wp-s
- **Production Mode (`npm run build`):** In this mode, `wp-scripts` compiles your JavaScript, minifying the output to reduce file size and improve loading times in the browser. This is ideal for deploying your code to a live site.
-- **Development Mode (`npm run start`):** This mode is tailored for active development. It skips minification for easier debugging, generates source maps for better error tracking, and watches your source files for changes. When a change is detected, it automatically rebuilds the affected files, allowing you to see updates in real-time.
+- **Development Mode (`npm start`):** This mode is tailored for active development. It skips minification for easier debugging, generates source maps for better error tracking, and watches your source files for changes. When a change is detected, it automatically rebuilds the affected files, allowing you to see updates in real-time.
The `wp-scripts` package also facilitates the use of JavaScript modules, allowing code distribution across multiple files and resulting in a streamlined bundle after the build process. The [block-development-example](https://github.com/WordPress/block-development-examples/tree/trunk/plugins/data-basics-59c8f8) GitHub repository provides some good examples.
diff --git a/docs/reference-guides/block-api/block-edit-save.md b/docs/reference-guides/block-api/block-edit-save.md
index 86721c77e463c6..a50a17b75cb54d 100644
--- a/docs/reference-guides/block-api/block-edit-save.md
+++ b/docs/reference-guides/block-api/block-edit-save.md
@@ -183,9 +183,34 @@ save: ( { attributes } ) => {
```
-
When saving your block, you want to save the attributes in the same format specified by the attribute source definition. If no attribute source is specified, the attribute will be saved to the block's comment delimiter. See the [Block Attributes documentation](/docs/reference-guides/block-api/block-attributes.md) for more details.
+### innerBlocks
+
+There is a second property in the props passed to the `save` function, `innerBlocks`. This property is typically used for internal operations, and there are very few scenarios where you would need to use it.
+
+`innerBlocks`, when initialized, is an array containing object representations of nested blocks. In those rare cases where you might use this property,
+it can help you adjust how a block is rendered. For example, you could render a block differently based on the number of nested blocks or if a specific block type is present..
+
+
+```jsx
+save: ( { attributes, innerBlocks } ) => {
+ const { className, ...rest } = useBlockProps.save();
+
+ // innerBlocks could also be an object - react element during initialization
+ const numberOfInnerBlocks = innerBlocks?.length;
+ if ( numberOfInnerBlocks > 1 ) {
+ className = className + ( className ? ' ' : '' ) + 'more-than-one';
+ };
+ const blockProps = { ...rest, className };
+
+ return
{ attributes.content }
;
+};
+```
+
+
+Here, an additional class is added to the block if number of inner blocks is greater than one, allowing for different styling of the block.
+
## Examples
Here are a couple examples of using attributes, edit, and save all together.
diff --git a/lib/block-supports/border.php b/lib/block-supports/border.php
index f890ed84566b7f..bd4c772675a5ed 100644
--- a/lib/block-supports/border.php
+++ b/lib/block-supports/border.php
@@ -17,7 +17,7 @@ function gutenberg_register_border_support( $block_type ) {
$block_type->attributes = array();
}
- if ( block_has_support( $block_type, array( 'border' ) ) && ! array_key_exists( 'style', $block_type->attributes ) ) {
+ if ( block_has_support( $block_type, array( '__experimentalBorder' ) ) && ! array_key_exists( 'style', $block_type->attributes ) ) {
$block_type->attributes['style'] = array(
'type' => 'object',
);
@@ -52,7 +52,7 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) {
if (
gutenberg_has_border_feature_support( $block_type, 'radius' ) &&
isset( $block_attributes['style']['border']['radius'] ) &&
- ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'radius' )
+ ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'radius' )
) {
$border_radius = $block_attributes['style']['border']['radius'];
@@ -67,7 +67,7 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) {
if (
gutenberg_has_border_feature_support( $block_type, 'style' ) &&
isset( $block_attributes['style']['border']['style'] ) &&
- ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'style' )
+ ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' )
) {
$border_block_styles['style'] = $block_attributes['style']['border']['style'];
}
@@ -76,7 +76,7 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) {
if (
$has_border_width_support &&
isset( $block_attributes['style']['border']['width'] ) &&
- ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'width' )
+ ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' )
) {
$border_width = $block_attributes['style']['border']['width'];
@@ -91,7 +91,7 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) {
// Border color.
if (
$has_border_color_support &&
- ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'color' )
+ ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' )
) {
$preset_border_color = array_key_exists( 'borderColor', $block_attributes ) ? "var:preset|color|{$block_attributes['borderColor']}" : null;
$custom_border_color = $block_attributes['style']['border']['color'] ?? null;
@@ -103,9 +103,9 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) {
foreach ( array( 'top', 'right', 'bottom', 'left' ) as $side ) {
$border = $block_attributes['style']['border'][ $side ] ?? null;
$border_side_values = array(
- 'width' => isset( $border['width'] ) && ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'width' ) ? $border['width'] : null,
- 'color' => isset( $border['color'] ) && ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'color' ) ? $border['color'] : null,
- 'style' => isset( $border['style'] ) && ! wp_should_skip_block_supports_serialization( $block_type, 'border', 'style' ) ? $border['style'] : null,
+ 'width' => isset( $border['width'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'width' ) ? $border['width'] : null,
+ 'color' => isset( $border['color'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'color' ) ? $border['color'] : null,
+ 'style' => isset( $border['style'] ) && ! wp_should_skip_block_supports_serialization( $block_type, '__experimentalBorder', 'style' ) ? $border['style'] : null,
);
$border_block_styles[ $side ] = $border_side_values;
}
@@ -129,9 +129,9 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) {
/**
* Checks whether the current block type supports the border feature requested.
*
- * If the `border` support flag is a boolean `true` all border
+ * If the `__experimentalBorder` support flag is a boolean `true` all border
* support features are available. Otherwise, the specific feature's support
- * flag nested under `border` must be enabled for the feature
+ * flag nested under `experimentalBorder` must be enabled for the feature
* to be opted into.
*
* @param WP_Block_Type $block_type Block type to check for support.
@@ -141,17 +141,17 @@ function gutenberg_apply_border_support( $block_type, $block_attributes ) {
* @return boolean Whether or not the feature is supported.
*/
function gutenberg_has_border_feature_support( $block_type, $feature, $default_value = false ) {
- // Check if all border support features have been opted into via `"border": true`.
+ // Check if all border support features have been opted into via `"__experimentalBorder": true`.
if ( $block_type instanceof WP_Block_Type ) {
- $block_type_supports_border = $block_type->supports['border'] ?? $default_value;
+ $block_type_supports_border = $block_type->supports['__experimentalBorder'] ?? $default_value;
if ( true === $block_type_supports_border ) {
return true;
}
}
// Check if the specific feature has been opted into individually
- // via nested flag under `border`.
- return block_has_support( $block_type, array( 'border', $feature ), $default_value );
+ // via nested flag under `__experimentalBorder`.
+ return block_has_support( $block_type, array( '__experimentalBorder', $feature ), $default_value );
}
// Register the block support.
diff --git a/lib/block-supports/elements.php b/lib/block-supports/elements.php
index 35a41270a19800..f3243bc7178951 100644
--- a/lib/block-supports/elements.php
+++ b/lib/block-supports/elements.php
@@ -255,12 +255,12 @@ function gutenberg_render_elements_class_name( $block_content, $block ) {
}
// Remove deprecated WordPress core filters.
-remove_filter( 'render_block', 'wp_render_elements_support', 10, 2 );
-remove_filter( 'pre_render_block', 'wp_render_elements_support_styles', 10, 2 );
+remove_filter( 'render_block', 'wp_render_elements_support', 10 );
+remove_filter( 'pre_render_block', 'wp_render_elements_support_styles', 10 );
// Remove WordPress core filters to avoid rendering duplicate elements stylesheet & attaching classes twice.
-remove_filter( 'render_block', 'wp_render_elements_class_name', 10, 2 );
-remove_filter( 'render_block_data', 'wp_render_elements_support_styles', 10, 1 );
+remove_filter( 'render_block', 'wp_render_elements_class_name', 10 );
+remove_filter( 'render_block_data', 'wp_render_elements_support_styles', 10 );
add_filter( 'render_block', 'gutenberg_render_elements_class_name', 10, 2 );
add_filter( 'render_block_data', 'gutenberg_render_elements_support_styles', 10, 1 );
diff --git a/lib/block-supports/layout.php b/lib/block-supports/layout.php
index ddbd1917c30547..7d63074ccb09bb 100644
--- a/lib/block-supports/layout.php
+++ b/lib/block-supports/layout.php
@@ -1055,8 +1055,8 @@ static function ( $matches ) {
}
if ( function_exists( 'wp_restore_group_inner_container' ) ) {
- remove_filter( 'render_block', 'wp_restore_group_inner_container', 10, 2 );
- remove_filter( 'render_block_core/group', 'wp_restore_group_inner_container', 10, 2 );
+ remove_filter( 'render_block', 'wp_restore_group_inner_container', 10 );
+ remove_filter( 'render_block_core/group', 'wp_restore_group_inner_container', 10 );
}
add_filter( 'render_block_core/group', 'gutenberg_restore_group_inner_container', 10, 2 );
@@ -1118,6 +1118,6 @@ function gutenberg_restore_image_outer_container( $block_content, $block ) {
}
if ( function_exists( 'wp_restore_image_outer_container' ) ) {
- remove_filter( 'render_block_core/image', 'wp_restore_image_outer_container', 10, 2 );
+ remove_filter( 'render_block_core/image', 'wp_restore_image_outer_container', 10 );
}
add_filter( 'render_block_core/image', 'gutenberg_restore_image_outer_container', 10, 2 );
diff --git a/lib/block-supports/settings.php b/lib/block-supports/settings.php
index b175fe778ce1b0..0246b5c039c86a 100644
--- a/lib/block-supports/settings.php
+++ b/lib/block-supports/settings.php
@@ -128,7 +128,7 @@ function _gutenberg_add_block_level_preset_styles( $pre_render, $block ) {
return null;
}
// Remove WordPress core filter to avoid rendering duplicate settings style blocks.
-remove_filter( 'render_block', '_wp_add_block_level_presets_class', 10, 2 );
-remove_filter( 'pre_render_block', '_wp_add_block_level_preset_styles', 10, 2 );
+remove_filter( 'render_block', '_wp_add_block_level_presets_class', 10 );
+remove_filter( 'pre_render_block', '_wp_add_block_level_preset_styles', 10 );
add_filter( 'render_block', '_gutenberg_add_block_level_presets_class', 10, 2 );
add_filter( 'pre_render_block', '_gutenberg_add_block_level_preset_styles', 10, 2 );
diff --git a/lib/block-supports/typography.php b/lib/block-supports/typography.php
index 21086b94f15c1a..a4719b7bdd4099 100644
--- a/lib/block-supports/typography.php
+++ b/lib/block-supports/typography.php
@@ -20,16 +20,16 @@ function gutenberg_register_typography_support( $block_type ) {
return;
}
- $has_font_family_support = $typography_supports['fontFamily'] ?? false;
+ $has_font_family_support = $typography_supports['__experimentalFontFamily'] ?? false;
$has_font_size_support = $typography_supports['fontSize'] ?? false;
- $has_font_style_support = $typography_supports['fontStyle'] ?? false;
- $has_font_weight_support = $typography_supports['fontWeight'] ?? false;
- $has_letter_spacing_support = $typography_supports['letterSpacing'] ?? false;
+ $has_font_style_support = $typography_supports['__experimentalFontStyle'] ?? false;
+ $has_font_weight_support = $typography_supports['__experimentalFontWeight'] ?? false;
+ $has_letter_spacing_support = $typography_supports['__experimentalLetterSpacing'] ?? false;
$has_line_height_support = $typography_supports['lineHeight'] ?? false;
$has_text_align_support = $typography_supports['textAlign'] ?? false;
$has_text_columns_support = $typography_supports['textColumns'] ?? false;
- $has_text_decoration_support = $typography_supports['textDecoration'] ?? false;
- $has_text_transform_support = $typography_supports['textTransform'] ?? false;
+ $has_text_decoration_support = $typography_supports['__experimentalTextDecoration'] ?? false;
+ $has_text_transform_support = $typography_supports['__experimentalTextTransform'] ?? false;
$has_writing_mode_support = $typography_supports['__experimentalWritingMode'] ?? false;
$has_typography_support = $has_font_family_support
@@ -91,16 +91,16 @@ function gutenberg_apply_typography_support( $block_type, $block_attributes ) {
return array();
}
- $has_font_family_support = $typography_supports['fontFamily'] ?? false;
+ $has_font_family_support = $typography_supports['__experimentalFontFamily'] ?? false;
$has_font_size_support = $typography_supports['fontSize'] ?? false;
- $has_font_style_support = $typography_supports['fontStyle'] ?? false;
- $has_font_weight_support = $typography_supports['fontWeight'] ?? false;
- $has_letter_spacing_support = $typography_supports['letterSpacing'] ?? false;
+ $has_font_style_support = $typography_supports['__experimentalFontStyle'] ?? false;
+ $has_font_weight_support = $typography_supports['__experimentalFontWeight'] ?? false;
+ $has_letter_spacing_support = $typography_supports['__experimentalLetterSpacing'] ?? false;
$has_line_height_support = $typography_supports['lineHeight'] ?? false;
$has_text_align_support = $typography_supports['textAlign'] ?? false;
$has_text_columns_support = $typography_supports['textColumns'] ?? false;
- $has_text_decoration_support = $typography_supports['textDecoration'] ?? false;
- $has_text_transform_support = $typography_supports['textTransform'] ?? false;
+ $has_text_decoration_support = $typography_supports['__experimentalTextDecoration'] ?? false;
+ $has_text_transform_support = $typography_supports['__experimentalTextTransform'] ?? false;
$has_writing_mode_support = $typography_supports['__experimentalWritingMode'] ?? false;
// Whether to skip individual block support features.
diff --git a/lib/class-wp-duotone-gutenberg.php b/lib/class-wp-duotone-gutenberg.php
index 5f3b1bb5cd6b11..cc49c320da6506 100644
--- a/lib/class-wp-duotone-gutenberg.php
+++ b/lib/class-wp-duotone-gutenberg.php
@@ -640,7 +640,7 @@ private static function get_global_styles_presets( $sources ) {
*
* @param string $block_name The block name.
*
- * @return string The CSS selector or null if there is no support.
+ * @return ?string The CSS selector or null if there is no support.
*/
private static function get_selector( $block_name ) {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block_name );
@@ -669,6 +669,8 @@ private static function get_selector( $block_name ) {
// Regular filter.duotone support uses filter.duotone selectors with fallbacks.
return wp_get_block_css_selector( $block_type, array( 'filter', 'duotone' ), true );
}
+
+ return null;
}
/**
diff --git a/lib/class-wp-theme-json-gutenberg.php b/lib/class-wp-theme-json-gutenberg.php
index 778dcdbec78d96..3af123d96bcc5a 100644
--- a/lib/class-wp-theme-json-gutenberg.php
+++ b/lib/class-wp-theme-json-gutenberg.php
@@ -615,10 +615,10 @@ class WP_Theme_JSON_Gutenberg {
* @var string[]
*/
const BLOCK_SUPPORT_FEATURE_LEVEL_SELECTORS = array(
- 'border' => 'border',
- 'color' => 'color',
- 'spacing' => 'spacing',
- 'typography' => 'typography',
+ '__experimentalBorder' => 'border',
+ 'color' => 'color',
+ 'spacing' => 'spacing',
+ 'typography' => 'typography',
);
/**
@@ -3413,6 +3413,8 @@ protected static function should_override_preset( $theme_json, $path, $override
return true;
}
+
+ return false;
}
/**
diff --git a/lib/compat/wordpress-6.8/blocks.php b/lib/compat/wordpress-6.8/blocks.php
index dc8747c04aec2f..6cfa98691020ef 100644
--- a/lib/compat/wordpress-6.8/blocks.php
+++ b/lib/compat/wordpress-6.8/blocks.php
@@ -5,151 +5,6 @@
* @package gutenberg
*/
-/**
- * Filters the block type arguments during registration to stabilize
- * experimental block supports.
- *
- * This is a temporary compatibility shim as the approach in core is for this
- * to be handled within the WP_Block_Type class rather than requiring a filter.
- *
- * @param array $args Array of arguments for registering a block type.
- * @return array Array of arguments for registering a block type.
- */
-function gutenberg_stabilize_experimental_block_supports( $args ) {
- if ( empty( $args['supports'] ) ) {
- return $args;
- }
-
- $experimental_supports_map = array( '__experimentalBorder' => 'border' );
- $common_experimental_properties = array(
- '__experimentalDefaultControls' => 'defaultControls',
- '__experimentalSkipSerialization' => 'skipSerialization',
- );
- $experimental_support_properties = array(
- 'typography' => array(
- '__experimentalFontFamily' => 'fontFamily',
- '__experimentalFontStyle' => 'fontStyle',
- '__experimentalFontWeight' => 'fontWeight',
- '__experimentalLetterSpacing' => 'letterSpacing',
- '__experimentalTextDecoration' => 'textDecoration',
- '__experimentalTextTransform' => 'textTransform',
- ),
- );
- $done = array();
-
- $updated_supports = array();
- foreach ( $args['supports'] as $support => $config ) {
- /*
- * If this support config has already been stabilized, skip it.
- * A stable support key occurring after an experimental key, gets
- * stabilized then so that the two configs can be merged effectively.
- */
- if ( isset( $done[ $support ] ) ) {
- continue;
- }
-
- $stable_support_key = $experimental_supports_map[ $support ] ?? $support;
-
- /*
- * Use the support's config as is when it's not in need of stabilization.
- *
- * A support does not need stabilization if:
- * - The support key doesn't need stabilization AND
- * - Either:
- * - The config isn't an array, so can't have experimental properties OR
- * - The config is an array but has no experimental properties to stabilize.
- */
- if ( $support === $stable_support_key &&
- ( ! is_array( $config ) ||
- ( ! isset( $experimental_support_properties[ $stable_support_key ] ) &&
- empty( array_intersect_key( $common_experimental_properties, $config ) )
- )
- )
- ) {
- $updated_supports[ $support ] = $config;
- continue;
- }
-
- $stabilize_config = function ( $unstable_config, $stable_support_key ) use ( $experimental_support_properties, $common_experimental_properties ) {
- if ( ! is_array( $unstable_config ) ) {
- return $unstable_config;
- }
-
- $stable_config = array();
- foreach ( $unstable_config as $key => $value ) {
- // Get stable key from support-specific map, common properties map, or keep original.
- $stable_key = $experimental_support_properties[ $stable_support_key ][ $key ] ??
- $common_experimental_properties[ $key ] ??
- $key;
-
- $stable_config[ $stable_key ] = $value;
-
- /*
- * The `__experimentalSkipSerialization` key needs to be kept until
- * WP 6.8 becomes the minimum supported version. This is due to the
- * core `wp_should_skip_block_supports_serialization` function only
- * checking for `__experimentalSkipSerialization` in earlier versions.
- */
- if ( '__experimentalSkipSerialization' === $key || 'skipSerialization' === $key ) {
- $stable_config['__experimentalSkipSerialization'] = $value;
- }
- }
- return $stable_config;
- };
-
- // Stabilize the config value.
- $stable_config = is_array( $config ) ? $stabilize_config( $config, $stable_support_key ) : $config;
-
- /*
- * If a plugin overrides the support config with the `register_block_type_args`
- * filter, both experimental and stable configs may be present. In that case,
- * use the order keys are defined in to determine the final value.
- * - If config is an array, merge the arrays in their order of definition.
- * - If config is not an array, use the value defined last.
- *
- * The reason for preferring the last defined key is that after filters
- * are applied, the last inserted key is likely the most up-to-date value.
- * We cannot determine with certainty which value was "last modified" so
- * the insertion order is the best guess. The extreme edge case of multiple
- * filters tweaking the same support property will become less over time as
- * extenders migrate existing blocks and plugins to stable keys.
- */
- if ( $support !== $stable_support_key && isset( $args['supports'][ $stable_support_key ] ) ) {
- $key_positions = array_flip( array_keys( $args['supports'] ) );
- $experimental_first =
- ( $key_positions[ $support ] ?? PHP_INT_MAX ) <
- ( $key_positions[ $stable_support_key ] ?? PHP_INT_MAX );
-
- /*
- * To merge the alternative support config effectively, it also needs to be
- * stabilized before merging to keep stabilized and experimental flags in
- * sync.
- */
- $args['supports'][ $stable_support_key ] = $stabilize_config( $args['supports'][ $stable_support_key ], $stable_support_key );
- // Prevents reprocessing this support as it was stabilized above.
- $done[ $stable_support_key ] = true;
-
- if ( is_array( $stable_config ) && is_array( $args['supports'][ $stable_support_key ] ) ) {
- $stable_config = $experimental_first
- ? array_merge( $stable_config, $args['supports'][ $stable_support_key ] )
- : array_merge( $args['supports'][ $stable_support_key ], $stable_config );
- } else {
- $stable_config = $experimental_first
- ? $args['supports'][ $stable_support_key ]
- : $stable_config;
- }
- }
-
- $updated_supports[ $stable_support_key ] = $stable_config;
- }
-
- $args['supports'] = $updated_supports;
-
- return $args;
-}
-
-add_filter( 'register_block_type_args', 'gutenberg_stabilize_experimental_block_supports', PHP_INT_MAX, 1 );
-
function gutenberg_apply_block_hooks_to_post_content( $content ) {
// The `the_content` filter does not provide the post that the content is coming from.
// However, we can infer it by calling `get_post()`, which will return the current post
diff --git a/lib/experimental/font-face/bc-layer/webfonts-deprecations.php b/lib/experimental/font-face/bc-layer/webfonts-deprecations.php
index 2534d8db165273..fb5e6b315dbdaf 100644
--- a/lib/experimental/font-face/bc-layer/webfonts-deprecations.php
+++ b/lib/experimental/font-face/bc-layer/webfonts-deprecations.php
@@ -28,7 +28,7 @@ function wp_webfonts() {
global $wp_webfonts;
if ( ! ( $wp_webfonts instanceof WP_Webfonts ) ) {
- $wp_webfonts = new WP_Webfonts( wp_fonts() );
+ $wp_webfonts = new WP_Webfonts();
}
return $wp_webfonts;
diff --git a/lib/experimental/posts/load.php b/lib/experimental/posts/load.php
index 699534f1886f52..b6dd9d55a8d7d8 100644
--- a/lib/experimental/posts/load.php
+++ b/lib/experimental/posts/load.php
@@ -51,7 +51,7 @@ function gutenberg_posts_dashboard() {
do_action( 'enqueue_block_editor_assets' );
wp_register_style(
'wp-gutenberg-posts-dashboard',
- gutenberg_url( 'build/edit-site/posts.css', __FILE__ ),
+ gutenberg_url( 'build/edit-site/posts.css' ),
array( 'wp-components', 'wp-commands', 'wp-edit-site' )
);
wp_enqueue_style( 'wp-gutenberg-posts-dashboard' );
diff --git a/lib/theme-i18n.json b/lib/theme-i18n.json
index e4d14502132cbe..1b7a8d0d31190b 100644
--- a/lib/theme-i18n.json
+++ b/lib/theme-i18n.json
@@ -45,6 +45,13 @@
}
]
},
+ "shadow": {
+ "presets": [
+ {
+ "name": "Shadow name"
+ }
+ ]
+ },
"blocks": {
"*": {
"typography": {
@@ -69,6 +76,18 @@
{
"name": "Gradient name"
}
+ ],
+ "duotone": [
+ {
+ "name": "Duotone name"
+ }
+ ]
+ },
+ "dimensions": {
+ "aspectRatios": [
+ {
+ "name": "Aspect ratio name"
+ }
]
},
"spacing": {
diff --git a/package-lock.json b/package-lock.json
index bd901baca24a96..eb2059e151f539 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -22,6 +22,7 @@
"@babel/runtime-corejs3": "7.25.7",
"@babel/traverse": "7.25.7",
"@emotion/babel-plugin": "11.11.0",
+ "@emotion/is-prop-valid": "1.2.2",
"@emotion/jest": "11.7.1",
"@emotion/native": "11.0.0",
"@geometricpanda/storybook-addon-badges": "2.0.5",
@@ -4467,6 +4468,19 @@
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz",
"integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ=="
},
+ "node_modules/@emotion/is-prop-valid": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
+ "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
+ "dependencies": {
+ "@emotion/memoize": "^0.8.1"
+ }
+ },
+ "node_modules/@emotion/is-prop-valid/node_modules/@emotion/memoize": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
+ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
+ },
"node_modules/@emotion/jest": {
"version": "11.7.1",
"resolved": "https://registry.npmjs.org/@emotion/jest/-/jest-11.7.1.tgz",
@@ -4618,19 +4632,6 @@
}
}
},
- "node_modules/@emotion/styled/node_modules/@emotion/is-prop-valid": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
- "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
- "dependencies": {
- "@emotion/memoize": "^0.8.1"
- }
- },
- "node_modules/@emotion/styled/node_modules/@emotion/memoize": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
- "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
- },
"node_modules/@emotion/unitless": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
@@ -17513,43 +17514,6 @@
"integrity": "sha512-LEeSAWeh2Gfa2FtlQE1shxQ8zi5F9GHarrGKz08TMdODD5T4eH6BMsvtnhbWZ+XQn+Gb6om/917ucvRu7l7ukw==",
"dev": true
},
- "node_modules/autoprefixer": {
- "version": "10.4.14",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz",
- "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==",
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/autoprefixer"
- }
- ],
- "dependencies": {
- "browserslist": "^4.21.5",
- "caniuse-lite": "^1.0.30001464",
- "fraction.js": "^4.2.0",
- "normalize-range": "^0.1.2",
- "picocolors": "^1.0.0",
- "postcss-value-parser": "^4.2.0"
- },
- "bin": {
- "autoprefixer": "bin/autoprefixer"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- },
- "peerDependencies": {
- "postcss": "^8.1.0"
- }
- },
- "node_modules/autoprefixer/node_modules/postcss-value-parser": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
- },
"node_modules/autosize": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/autosize/-/autosize-4.0.2.tgz",
@@ -25665,6 +25629,7 @@
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
"integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==",
+ "dev": true,
"engines": {
"node": "*"
},
@@ -51967,7 +51932,7 @@
"license": "GPL-2.0-or-later",
"dependencies": {
"@wordpress/base-styles": "*",
- "autoprefixer": "^10.2.5"
+ "autoprefixer": "^10.4.20"
},
"engines": {
"node": ">=18.12.0",
@@ -51977,6 +51942,59 @@
"postcss": "^8.0.0"
}
},
+ "packages/postcss-plugins-preset/node_modules/autoprefixer": {
+ "version": "10.4.20",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
+ "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "browserslist": "^4.23.3",
+ "caniuse-lite": "^1.0.30001646",
+ "fraction.js": "^4.3.7",
+ "normalize-range": "^0.1.2",
+ "picocolors": "^1.0.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "packages/postcss-plugins-preset/node_modules/fraction.js": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
+ "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://github.com/sponsors/rawify"
+ }
+ },
+ "packages/postcss-plugins-preset/node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
+ },
"packages/postcss-themes": {
"name": "@wordpress/postcss-themes",
"version": "6.14.0",
diff --git a/package.json b/package.json
index 792546d28582fe..de73148bd62450 100644
--- a/package.json
+++ b/package.json
@@ -31,6 +31,7 @@
"@babel/runtime-corejs3": "7.25.7",
"@babel/traverse": "7.25.7",
"@emotion/babel-plugin": "11.11.0",
+ "@emotion/is-prop-valid": "1.2.2",
"@emotion/jest": "11.7.1",
"@emotion/native": "11.0.0",
"@geometricpanda/storybook-addon-badges": "2.0.5",
diff --git a/packages/block-editor/src/components/colors-gradients/dropdown.js b/packages/block-editor/src/components/colors-gradients/dropdown.js
index 71b27c06e7ccfc..e667927bee7601 100644
--- a/packages/block-editor/src/components/colors-gradients/dropdown.js
+++ b/packages/block-editor/src/components/colors-gradients/dropdown.js
@@ -15,6 +15,13 @@ import {
__experimentalHStack as HStack,
__experimentalToolsPanelItem as ToolsPanelItem,
} from '@wordpress/components';
+import { useRef } from '@wordpress/element';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import { reset as resetIcon } from '@wordpress/icons';
/**
* Internal dependencies
@@ -76,7 +83,15 @@ const LabeledColorIndicator = ( { colorValue, label } ) => (
const renderToggle =
( settings ) =>
( { onToggle, isOpen } ) => {
- const { colorValue, label } = settings;
+ const {
+ clearable,
+ colorValue,
+ gradientValue,
+ onColorChange,
+ onGradientChange,
+ label,
+ } = settings;
+ const colorButtonRef = useRef( undefined );
const toggleProps = {
onClick: onToggle,
@@ -85,15 +100,45 @@ const renderToggle =
{ 'is-open': isOpen }
),
'aria-expanded': isOpen,
+ ref: colorButtonRef,
+ };
+
+ const clearValue = () => {
+ if ( colorValue ) {
+ onColorChange();
+ } else if ( gradientValue ) {
+ onGradientChange();
+ }
};
+ const value = colorValue ?? gradientValue;
+
return (
-
+ <>
+
+ { clearable && value && (
+