@@ -248,7 +248,7 @@ class WP_Theme_JSON {
248248 * @since 6.7.0 Added `background-attachment` property.
249249 * @since 7.0.0 Added `dimensions.width` and `dimensions.height`.
250250 * Added `text-indent` property.
251- * @since 7.1.0 Added `text-shadow` property .
251+ * @since 7.1.0 Added `min-width` and ` text-shadow`.
252252 * @var array
253253 */
254254 const PROPERTIES_METADATA = array (
@@ -295,6 +295,7 @@ class WP_Theme_JSON {
295295 'margin-bottom ' => array ( 'spacing ' , 'margin ' , 'bottom ' ),
296296 'margin-left ' => array ( 'spacing ' , 'margin ' , 'left ' ),
297297 'min-height ' => array ( 'dimensions ' , 'minHeight ' ),
298+ 'min-width ' => array ( 'dimensions ' , 'minWidth ' ),
298299 'outline-color ' => array ( 'outline ' , 'color ' ),
299300 'outline-offset ' => array ( 'outline ' , 'offset ' ),
300301 'outline-style ' => array ( 'outline ' , 'style ' ),
@@ -417,7 +418,7 @@ class WP_Theme_JSON {
417418 * Added support for `dimensions.width` and `dimensions.height`.
418419 * Added support for `typography.textIndent`.
419420 * @since 7.1.0 Added `viewport` property.
420- * Added support for `background.gradient` and `blockVisibility.allowEditing`.
421+ * Added support for `background.gradient`, `dimensions.minWidth` and `blockVisibility.allowEditing`.
421422 * @var array
422423 */
423424 const VALID_SETTINGS = array (
@@ -460,6 +461,7 @@ class WP_Theme_JSON {
460461 'dimensionSizes ' => null ,
461462 'height ' => null ,
462463 'minHeight ' => null ,
464+ 'minWidth ' => null ,
463465 'width ' => null ,
464466 ),
465467 'layout ' => array (
@@ -563,8 +565,8 @@ class WP_Theme_JSON {
563565 * @since 6.5.0 Added support for `dimensions.aspectRatio`.
564566 * @since 6.6.0 Added `background` sub properties to top-level only.
565567 * @since 7.0.0 Added support for `dimensions.width` and `dimensions.height`.
566- * @since 7.1.0 Added `background.gradient`.
567- * @since 7.1.0 Added support for `typography.textShadow`.
568+ * @since 7.1.0 Added support for `background.gradient`,`dimensions.minWidth`,
569+ * and `typography.textShadow`.
568570 * @var array
569571 */
570572 const VALID_STYLES = array (
@@ -595,6 +597,7 @@ class WP_Theme_JSON {
595597 'aspectRatio ' => null ,
596598 'height ' => null ,
597599 'minHeight ' => null ,
600+ 'minWidth ' => null ,
598601 'width ' => null ,
599602 ),
600603 'filter ' => array (
@@ -1035,6 +1038,7 @@ public static function get_element_class_name( $element ) {
10351038 * @since 6.5.0 Added `background.backgroundSize` and `dimensions.aspectRatio`.
10361039 * @since 7.0.0 Added `dimensions.width` and `dimensions.height`.
10371040 * @since 7.1.0 Added `background.gradient`.
1041+ * Added `dimensions.minWidth`.
10381042 * @var array
10391043 */
10401044 const APPEARANCE_TOOLS_OPT_INS = array (
@@ -1052,6 +1056,7 @@ public static function get_element_class_name( $element ) {
10521056 array ( 'dimensions ' , 'aspectRatio ' ),
10531057 array ( 'dimensions ' , 'height ' ),
10541058 array ( 'dimensions ' , 'minHeight ' ),
1059+ array ( 'dimensions ' , 'minWidth ' ),
10551060 array ( 'dimensions ' , 'width ' ),
10561061 array ( 'position ' , 'sticky ' ),
10571062 array ( 'spacing ' , 'blockGap ' ),
@@ -2480,21 +2485,89 @@ protected function get_css_variables( $nodes, $origins ) {
24802485 continue ;
24812486 }
24822487
2483- $ selector = $ metadata ['selector ' ];
2488+ $ selector = $ metadata ['selector ' ];
2489+ $ feature_selectors = $ metadata ['selectors ' ] ?? array ();
2490+ $ node = _wp_array_get ( $ this ->theme_json , $ metadata ['path ' ], array () );
2491+
2492+ /*
2493+ * Group preset declarations by selector. Blocks that define
2494+ * feature-level selectors need their preset CSS variables
2495+ * output under that feature selector instead of the block's
2496+ * root selector.
2497+ */
2498+ $ vars_by_selector = array ();
2499+ $ vars_by_selector [ $ selector ] = array ();
2500+
2501+ foreach ( static ::PRESETS_METADATA as $ preset_metadata ) {
2502+ if ( empty ( $ preset_metadata ['css_vars ' ] ) ) {
2503+ continue ;
2504+ }
2505+
2506+ $ values_by_slug = static ::get_settings_values_by_slug ( $ node , $ preset_metadata , $ origins );
2507+ if ( empty ( $ values_by_slug ) ) {
2508+ continue ;
2509+ }
2510+
2511+ $ target = static ::get_feature_selector ( $ feature_selectors , $ preset_metadata ['path ' ][0 ], $ selector );
2512+
2513+ if ( ! isset ( $ vars_by_selector [ $ target ] ) ) {
2514+ $ vars_by_selector [ $ target ] = array ();
2515+ }
2516+
2517+ foreach ( $ values_by_slug as $ slug => $ value ) {
2518+ $ vars_by_selector [ $ target ][] = array (
2519+ 'name ' => static ::replace_slug_in_string ( $ preset_metadata ['css_vars ' ], $ slug ),
2520+ 'value ' => $ value ,
2521+ );
2522+ }
2523+ }
24842524
2485- $ node = _wp_array_get ( $ this ->theme_json , $ metadata ['path ' ], array () );
2486- $ declarations = static ::compute_preset_vars ( $ node , $ origins );
2487- $ theme_vars_declarations = static ::compute_theme_vars ( $ node );
2488- foreach ( $ theme_vars_declarations as $ theme_vars_declaration ) {
2489- $ declarations [] = $ theme_vars_declaration ;
2525+ // Theme vars always use the block's default selector.
2526+ foreach ( static ::compute_theme_vars ( $ node ) as $ theme_var ) {
2527+ $ vars_by_selector [ $ selector ][] = $ theme_var ;
24902528 }
24912529
2492- $ stylesheet .= static ::to_ruleset ( $ selector , $ declarations );
2530+ foreach ( $ vars_by_selector as $ rule_selector => $ declarations ) {
2531+ $ stylesheet .= static ::to_ruleset ( $ rule_selector , $ declarations );
2532+ }
24932533 }
24942534
24952535 return $ stylesheet ;
24962536 }
24972537
2538+ /**
2539+ * Returns the appropriate selector for a block support feature's
2540+ * preset CSS variables.
2541+ *
2542+ * If the block defines a feature-level selector (as a string or an
2543+ * object with a `root` key), that selector is returned. Otherwise,
2544+ * the block's default selector is used.
2545+ *
2546+ * @since 7.1.0
2547+ *
2548+ * @param array<string, string|array<string, string>> $feature_selectors The block's feature selectors map.
2549+ * @param string $feature_key The feature to look up (e.g. 'dimensions').
2550+ * @param string $default_selector Fallback selector.
2551+ * @return string The resolved selector.
2552+ */
2553+ private static function get_feature_selector ( array $ feature_selectors , string $ feature_key , string $ default_selector ): string {
2554+ if ( ! isset ( $ feature_selectors [ $ feature_key ] ) ) {
2555+ return $ default_selector ;
2556+ }
2557+
2558+ $ feature = $ feature_selectors [ $ feature_key ];
2559+
2560+ if ( is_string ( $ feature ) ) {
2561+ return $ feature ;
2562+ }
2563+
2564+ if ( isset ( $ feature ['root ' ] ) && is_string ( $ feature ['root ' ] ) ) {
2565+ return $ feature ['root ' ];
2566+ }
2567+
2568+ return $ default_selector ;
2569+ }
2570+
24982571 /**
24992572 * Given a selector and a declaration list,
25002573 * creates the corresponding ruleset.
@@ -3145,8 +3218,9 @@ protected static function get_setting_nodes( $theme_json, $selectors = array() )
31453218 }
31463219
31473220 $ nodes [] = array (
3148- 'path ' => array ( 'settings ' , 'blocks ' , $ name ),
3149- 'selector ' => $ selector ,
3221+ 'path ' => array ( 'settings ' , 'blocks ' , $ name ),
3222+ 'selector ' => $ selector ,
3223+ 'selectors ' => $ selectors [ $ name ]['selectors ' ] ?? array (),
31503224 );
31513225 }
31523226
0 commit comments