Make WordPress Core

Changeset 58170


Ignore:
Timestamp:
05/18/2024 08:30:57 PM (2 months ago)
Author:
isabel_brison
Message:

Editor: add column and row spans to grid children.

Adds support for setting spans using grid-column and grid-row properties on children of blocks with grid layout.

Props isabel_brison, andrewserong, peterwilsoncc, mukesh27.
Fixes #61111.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/block-supports/layout.php

    r57383 r58170  
    490490            $layout_styles[] = array(
    491491                'selector'     => $selector,
    492                 'declarations' => array( 'grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))' ),
     492                'declarations' => array(
     493                    'grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))',
     494                    'container-type'        => 'inline-size',
     495                ),
    493496            );
    494497        }
     
    556559    $block_type            = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
    557560    $block_supports_layout = block_has_support( $block_type, 'layout', false ) || block_has_support( $block_type, '__experimentalLayout', false );
    558     $layout_from_parent    = isset( $block['attrs']['style']['layout']['selfStretch'] ) ? $block['attrs']['style']['layout']['selfStretch'] : null;
    559 
    560     if ( ! $block_supports_layout && ! $layout_from_parent ) {
     561    $child_layout          = isset( $block['attrs']['style']['layout'] ) ? $block['attrs']['style']['layout'] : null;
     562
     563    if ( ! $block_supports_layout && ! $child_layout ) {
    561564        return $block_content;
    562565    }
     
    564567    $outer_class_names = array();
    565568
    566     if ( 'fixed' === $layout_from_parent || 'fill' === $layout_from_parent ) {
    567         $container_content_class = wp_unique_id( 'wp-container-content-' );
    568 
    569         $child_layout_styles = array();
    570 
    571         if ( 'fixed' === $layout_from_parent && isset( $block['attrs']['style']['layout']['flexSize'] ) ) {
     569    // Child layout specific logic.
     570    if ( $child_layout ) {
     571        $container_content_class   = wp_unique_prefixed_id( 'wp-container-content-' );
     572        $child_layout_declarations = array();
     573        $child_layout_styles       = array();
     574
     575        $self_stretch = isset( $child_layout['selfStretch'] ) ? $child_layout['selfStretch'] : null;
     576
     577        if ( 'fixed' === $self_stretch && isset( $child_layout['flexSize'] ) ) {
     578            $child_layout_declarations['flex-basis'] = $child_layout['flexSize'];
     579            $child_layout_declarations['box-sizing'] = 'border-box';
     580        } elseif ( 'fill' === $self_stretch ) {
     581            $child_layout_declarations['flex-grow'] = '1';
     582        }
     583
     584        if ( isset( $child_layout['columnSpan'] ) ) {
     585            $column_span                              = $child_layout['columnSpan'];
     586            $child_layout_declarations['grid-column'] = "span $column_span";
     587        }
     588        if ( isset( $child_layout['rowSpan'] ) ) {
     589            $row_span                              = $child_layout['rowSpan'];
     590            $child_layout_declarations['grid-row'] = "span $row_span";
     591        }
     592        $child_layout_styles[] = array(
     593            'selector'     => ".$container_content_class",
     594            'declarations' => $child_layout_declarations,
     595        );
     596
     597        /*
     598         * If columnSpan is set, and the parent grid is responsive, i.e. if it has a minimumColumnWidth set,
     599         * the columnSpan should be removed on small grids. If there's a minimumColumnWidth, the grid is responsive.
     600         * But if the minimumColumnWidth value wasn't changed, it won't be set. In that case, if columnCount doesn't
     601         * exist, we can assume that the grid is responsive.
     602         */
     603        if ( isset( $child_layout['columnSpan'] ) && ( isset( $block['parentLayout']['minimumColumnWidth'] ) || ! isset( $block['parentLayout']['columnCount'] ) ) ) {
     604            $column_span_number  = floatval( $child_layout['columnSpan'] );
     605            $parent_column_width = isset( $block['parentLayout']['minimumColumnWidth'] ) ? $block['parentLayout']['minimumColumnWidth'] : '12rem';
     606            $parent_column_value = floatval( $parent_column_width );
     607            $parent_column_unit  = explode( $parent_column_value, $parent_column_width );
     608
     609            /*
     610             * If there is no unit, the width has somehow been mangled so we reset both unit and value
     611             * to defaults.
     612             * Additionally, the unit should be one of px, rem or em, so that also needs to be checked.
     613             */
     614            if ( count( $parent_column_unit ) <= 1 ) {
     615                $parent_column_unit  = 'rem';
     616                $parent_column_value = 12;
     617            } else {
     618                $parent_column_unit = $parent_column_unit[1];
     619
     620                if ( ! in_array( $parent_column_unit, array( 'px', 'rem', 'em' ), true ) ) {
     621                    $parent_column_unit = 'rem';
     622                }
     623            }
     624
     625            /*
     626             * A default gap value is used for this computation because custom gap values may not be
     627             * viable to use in the computation of the container query value.
     628             */
     629            $default_gap_value     = 'px' === $parent_column_unit ? 24 : 1.5;
     630            $container_query_value = $column_span_number * $parent_column_value + ( $column_span_number - 1 ) * $default_gap_value;
     631            $container_query_value = $container_query_value . $parent_column_unit;
     632
    572633            $child_layout_styles[] = array(
     634                'rules_group'  => "@container (max-width: $container_query_value )",
    573635                'selector'     => ".$container_content_class",
    574636                'declarations' => array(
    575                     'flex-basis' => $block['attrs']['style']['layout']['flexSize'],
    576                     'box-sizing' => 'border-box',
     637                    'grid-column' => '1/-1',
    577638                ),
    578639            );
    579         } elseif ( 'fill' === $layout_from_parent ) {
    580             $child_layout_styles[] = array(
    581                 'selector'     => ".$container_content_class",
    582                 'declarations' => array(
    583                     'flex-grow' => '1',
    584                 ),
    585             );
    586         }
    587 
    588         wp_style_engine_get_stylesheet_from_css_rules(
     640        }
     641
     642        /*
     643         * Add to the style engine store to enqueue and render layout styles.
     644         * Return styles here just to check if any exist.
     645         */
     646        $child_css = wp_style_engine_get_stylesheet_from_css_rules(
    589647            $child_layout_styles,
    590648            array(
     
    594652        );
    595653
    596         $outer_class_names[] = $container_content_class;
     654        if ( $child_css ) {
     655            $outer_class_names[] = $container_content_class;
     656        }
    597657    }
    598658
     
    851911    return $processor->get_updated_html();
    852912}
     913
     914/**
     915 * Check if the parent block exists and if it has a layout attribute.
     916 * If it does, add the parent layout to the parsed block
     917 *
     918 * @since 6.6.0
     919 * @access private
     920 *
     921 * @param array    $parsed_block The parsed block.
     922 * @param array    $source_block The source block.
     923 * @param WP_Block $parent_block The parent block.
     924 * @return array The parsed block with parent layout attribute if it exists.
     925 */
     926function wp_add_parent_layout_to_parsed_block( $parsed_block, $source_block, $parent_block ) {
     927    if ( $parent_block && isset( $parent_block->parsed_block['attrs']['layout'] ) ) {
     928        $parsed_block['parentLayout'] = $parent_block->parsed_block['attrs']['layout'];
     929    }
     930    return $parsed_block;
     931}
     932
     933add_filter( 'render_block_data', 'wp_add_parent_layout_to_parsed_block', 10, 3 );
    853934
    854935// Register the block support.
  • trunk/src/wp-includes/kses.php

    r57228 r58170  
    24422442            'grid-column-start',
    24432443            'grid-column-end',
     2444            'grid-column',
    24442445            'grid-column-gap',
    24452446            'grid-template-rows',
     
    24472448            'grid-row-start',
    24482449            'grid-row-end',
     2450            'grid-row',
    24492451            'grid-row-gap',
    24502452            'grid-gap',
     
    24762478            'box-shadow',
    24772479            'aspect-ratio',
     2480            'container-type',
    24782481
    24792482            // Custom CSS properties.
  • trunk/tests/phpunit/tests/block-supports/layout.php

    r57328 r58170  
    173173     * @ticket 58548
    174174     * @ticket 60292
     175     * @ticket 61111
    175176     *
    176177     * @dataProvider data_layout_support_flag_renders_classnames_on_wrapper
     
    182183     */
    183184    public function test_layout_support_flag_renders_classnames_on_wrapper( $args, $expected_output ) {
     185        switch_theme( 'default' );
    184186        $actual_output = wp_render_layout_support_flag( $args['block_content'], $args['block'] );
    185187        $this->assertSame( $expected_output, $actual_output );
     
    251253                ),
    252254                'expected_output' => '<div class="wp-block-group"><div class="wp-block-group__inner-wrapper is-layout-flow wp-block-group-is-layout-flow"></div></div>',
     255            ),
     256            'block with child layout'                      => array(
     257                'args'            => array(
     258                    'block_content' => '<p>Some text.</p>',
     259                    'block'         => array(
     260                        'blockName'    => 'core/paragraph',
     261                        'attrs'        => array(
     262                            'style' => array(
     263                                'layout' => array(
     264                                    'columnSpan' => '2',
     265                                ),
     266                            ),
     267                        ),
     268                        'innerBlocks'  => array(),
     269                        'innerHTML'    => '<p>Some text.</p>',
     270                        'innerContent' => array(
     271                            '<p>Some text.</p>',
     272                        ),
     273                    ),
     274                ),
     275                'expected_output' => '<p class="wp-container-content-1">Some text.</p>', // The generated classname number assumes `wp_unique_prefixed_id( 'wp-container-content-' )` will not have run previously in this test.
    253276            ),
    254277            'skip classname output if block does not support layout and there are no child layout classes to be output' => array(
     
    363386        );
    364387    }
     388
     389    /**
     390     * Checks that `wp_add_parent_layout_to_parsed_block` adds the parent layout attribute to the block object.
     391     *
     392     * @ticket 61111
     393     *
     394     * @covers ::wp_add_parent_layout_to_parsed_block
     395     *
     396     * @dataProvider data_wp_add_parent_layout_to_parsed_block
     397     *
     398     * @param array    $block        The block object.
     399     * @param WP_Block $parent_block The parent block object.
     400     * @param array    $expected     The expected block object.
     401     */
     402    public function test_wp_add_parent_layout_to_parsed_block( $block, $parent_block, $expected ) {
     403        $actual = wp_add_parent_layout_to_parsed_block( $block, array(), $parent_block );
     404        $this->assertSame( $expected, $actual );
     405    }
     406
     407    /**
     408     * Data provider for test_wp_add_parent_layout_to_parsed_block.
     409     *
     410     * @return array
     411     */
     412    public function data_wp_add_parent_layout_to_parsed_block() {
     413        return array(
     414            'block with no parent layout' => array(
     415                'block'        => array(
     416                    'blockName' => 'core/group',
     417                    'attrs'     => array(
     418                        'layout' => array(
     419                            'type' => 'default',
     420                        ),
     421                    ),
     422                ),
     423                'parent_block' => array(),
     424                'expected'     => array(
     425                    'blockName' => 'core/group',
     426                    'attrs'     => array(
     427                        'layout' => array(
     428                            'type' => 'default',
     429                        ),
     430                    ),
     431                ),
     432            ),
     433            'block with parent layout'    => array(
     434                'block'        => array(
     435                    'blockName' => 'core/group',
     436                    'attrs'     => array(
     437                        'layout' => array(
     438                            'type' => 'default',
     439                        ),
     440                    ),
     441                ),
     442                'parent_block' => new WP_Block(
     443                    array(
     444                        'attrs' => array(
     445                            'layout' => array(
     446                                'type' => 'grid',
     447                            ),
     448                        ),
     449                    )
     450                ),
     451                'expected'     => array(
     452                    'blockName'    => 'core/group',
     453                    'attrs'        => array(
     454                        'layout' => array(
     455                            'type' => 'default',
     456                        ),
     457                    ),
     458                    'parentLayout' => array(
     459                        'type' => 'grid',
     460                    ),
     461                ),
     462            ),
     463        );
     464    }
    365465}
Note: See TracChangeset for help on using the changeset viewer.