@@ -215,6 +215,15 @@ class WP_Theme_JSON {
215215 'classes ' => array (),
216216 'properties ' => array ( 'border-radius ' ),
217217 ),
218+ array (
219+ 'path ' => array ( 'dimensions ' , 'dimensionSizes ' ),
220+ 'prevent_override ' => false ,
221+ 'use_default_names ' => false ,
222+ 'value_key ' => 'size ' ,
223+ 'css_vars ' => '--wp--preset--dimension--$slug ' ,
224+ 'classes ' => array (),
225+ 'properties ' => array ( 'width ' , 'height ' , 'min-height ' ),
226+ ),
218227 );
219228
220229 /**
@@ -238,6 +247,7 @@ class WP_Theme_JSON {
238247 * @since 6.6.0 Added `background-[image|position|repeat|size]` properties.
239248 * @since 6.7.0 Added `background-attachment` property.
240249 * @since 7.0.0 Added `dimensions.width` and `dimensions.height`.
250+ * Added `text-indent` property.
241251 * @var array
242252 */
243253 const PROPERTIES_METADATA = array (
@@ -300,6 +310,7 @@ class WP_Theme_JSON {
300310 '--wp--style--root--padding-left ' => array ( 'spacing ' , 'padding ' , 'left ' ),
301311 'text-decoration ' => array ( 'typography ' , 'textDecoration ' ),
302312 'text-transform ' => array ( 'typography ' , 'textTransform ' ),
313+ 'text-indent ' => array ( 'typography ' , 'textIndent ' ),
303314 'filter ' => array ( 'filter ' , 'duotone ' ),
304315 'box-shadow ' => array ( 'shadow ' ),
305316 'height ' => array ( 'dimensions ' , 'height ' ),
@@ -400,6 +411,7 @@ class WP_Theme_JSON {
400411 * @since 6.9.0 Added support for `border.radiusSizes`.
401412 * @since 7.0.0 Added type markers to the schema for boolean values.
402413 * Added support for `dimensions.width` and `dimensions.height`.
414+ * Added support for `typography.textIndent`.
403415 * @var array
404416 */
405417 const VALID_SETTINGS = array (
@@ -438,6 +450,7 @@ class WP_Theme_JSON {
438450 'aspectRatio ' => null ,
439451 'aspectRatios ' => null ,
440452 'defaultAspectRatios ' => null ,
453+ 'dimensionSizes ' => null ,
441454 'height ' => null ,
442455 'minHeight ' => null ,
443456 'width ' => null ,
@@ -484,6 +497,7 @@ class WP_Theme_JSON {
484497 'textAlign ' => null ,
485498 'textColumns ' => null ,
486499 'textDecoration ' => null ,
500+ 'textIndent ' => null ,
487501 'textTransform ' => null ,
488502 'writingMode ' => null ,
489503 ),
@@ -591,6 +605,7 @@ class WP_Theme_JSON {
591605 'textAlign ' => null ,
592606 'textColumns ' => null ,
593607 'textDecoration ' => null ,
608+ 'textIndent ' => null ,
594609 'textTransform ' => null ,
595610 'writingMode ' => null ,
596611 ),
@@ -2739,6 +2754,48 @@ private static function update_separator_declarations( $declarations ) {
27392754 return $ declarations ;
27402755 }
27412756
2757+ /**
2758+ * Updates the text indent selector for paragraph blocks based on the textIndent setting.
2759+ *
2760+ * The textIndent setting can be 'subsequent' (default), 'all', or false.
2761+ * When set to 'all', the selector should be '.wp-block-paragraph' instead of
2762+ * '.wp-block-paragraph + .wp-block-paragraph' to apply indent to all paragraphs.
2763+ *
2764+ * @since 7.0.0
2765+ *
2766+ * @param array $feature_declarations The feature declarations keyed by selector.
2767+ * @param array $settings The theme.json settings.
2768+ * @param string $block_name The block name being processed.
2769+ * @return array The updated feature declarations.
2770+ */
2771+ private static function update_paragraph_text_indent_selector ( $ feature_declarations , $ settings , $ block_name ) {
2772+ if ( 'core/paragraph ' !== $ block_name ) {
2773+ return $ feature_declarations ;
2774+ }
2775+
2776+ // Check block-level settings first, then fall back to global settings.
2777+ $ block_settings = $ settings ['blocks ' ]['core/paragraph ' ] ?? null ;
2778+ $ text_indent_setting = $ block_settings ['typography ' ]['textIndent ' ]
2779+ ?? $ settings ['typography ' ]['textIndent ' ]
2780+ ?? 'subsequent ' ;
2781+
2782+ if ( 'all ' !== $ text_indent_setting ) {
2783+ return $ feature_declarations ;
2784+ }
2785+
2786+ // Look for the text indent selector and replace it.
2787+ $ old_selector = '.wp-block-paragraph + .wp-block-paragraph ' ;
2788+ $ new_selector = '.wp-block-paragraph ' ;
2789+
2790+ if ( isset ( $ feature_declarations [ $ old_selector ] ) ) {
2791+ $ declarations = $ feature_declarations [ $ old_selector ];
2792+ unset( $ feature_declarations [ $ old_selector ] );
2793+ $ feature_declarations [ $ new_selector ] = $ declarations ;
2794+ }
2795+
2796+ return $ feature_declarations ;
2797+ }
2798+
27422799 /**
27432800 * An internal method to get the block nodes from a theme.json file.
27442801 *
@@ -2900,6 +2957,10 @@ public function get_styles_for_block( $block_metadata ) {
29002957 $ feature_declarations = static ::get_feature_declarations_for_node ( $ block_metadata , $ node );
29012958 $ is_root_selector = static ::ROOT_BLOCK_SELECTOR === $ selector ;
29022959
2960+ // Update text indent selector for paragraph blocks based on the textIndent setting.
2961+ $ block_name = $ block_metadata ['name ' ] ?? null ;
2962+ $ feature_declarations = static ::update_paragraph_text_indent_selector ( $ feature_declarations , $ settings , $ block_name );
2963+
29032964 // If there are style variations, generate the declarations for them, including any feature selectors the block may have.
29042965 $ style_variation_declarations = array ();
29052966 $ style_variation_custom_css = array ();
@@ -2912,6 +2973,9 @@ public function get_styles_for_block( $block_metadata ) {
29122973 // Generate any feature/subfeature style declarations for the current style variation.
29132974 $ variation_declarations = static ::get_feature_declarations_for_node ( $ block_metadata , $ style_variation_node );
29142975
2976+ // Update text indent selector for paragraph blocks based on the textIndent setting.
2977+ $ variation_declarations = static ::update_paragraph_text_indent_selector ( $ variation_declarations , $ settings , $ block_name );
2978+
29152979 // Combine selectors with style variation's selector and add to overall style variation declarations.
29162980 foreach ( $ variation_declarations as $ current_selector => $ new_declarations ) {
29172981 /*
0 commit comments