Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add support for column and row spans in grid children.
  • Loading branch information
tellthemachines committed May 3, 2024
commit c9a0514b5b760e2956f18662a48bed34e68cd8bd
131 changes: 103 additions & 28 deletions src/wp-includes/block-supports/layout.php
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,10 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false

$layout_styles[] = array(
'selector' => $selector,
'declarations' => array( 'grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))' ),
'declarations' => array(
'grid-template-columns' => 'repeat(auto-fill, minmax(min(' . $minimum_column_width . ', 100%), 1fr))',
'container-type' => 'inline-size',
),
);
}

Expand Down Expand Up @@ -555,44 +558,97 @@ function wp_get_layout_style( $selector, $layout, $has_block_gap_support = false
function wp_render_layout_support_flag( $block_content, $block ) {
$block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
$block_supports_layout = block_has_support( $block_type, 'layout', false ) || block_has_support( $block_type, '__experimentalLayout', false );
$layout_from_parent = isset( $block['attrs']['style']['layout']['selfStretch'] ) ? $block['attrs']['style']['layout']['selfStretch'] : null;
$child_layout = isset( $block['attrs']['style']['layout'] ) ? $block['attrs']['style']['layout'] : null;

if ( ! $block_supports_layout && ! $layout_from_parent ) {
if ( ! $block_supports_layout && ! $child_layout ) {
return $block_content;
}

$outer_class_names = array();
$outer_class_names = array();
$container_content_class = wp_unique_id( 'wp-container-content-' );
$child_layout_declarations = array();
$child_layout_styles = array();

if ( 'fixed' === $layout_from_parent || 'fill' === $layout_from_parent ) {
$container_content_class = wp_unique_id( 'wp-container-content-' );
$self_stretch = isset( $child_layout['selfStretch'] ) ? $child_layout['selfStretch'] : null;

$child_layout_styles = array();
if ( 'fixed' === $self_stretch && isset( $child_layout['flexSize'] ) ) {
$child_layout_declarations['flex-basis'] = $child_layout['flexSize'];
$child_layout_declarations['box-sizing'] = 'border-box';
} elseif ( 'fill' === $self_stretch ) {
$child_layout_declarations['flex-grow'] = '1';
}

if ( 'fixed' === $layout_from_parent && isset( $block['attrs']['style']['layout']['flexSize'] ) ) {
$child_layout_styles[] = array(
'selector' => ".$container_content_class",
'declarations' => array(
'flex-basis' => $block['attrs']['style']['layout']['flexSize'],
'box-sizing' => 'border-box',
),
);
} elseif ( 'fill' === $layout_from_parent ) {
$child_layout_styles[] = array(
'selector' => ".$container_content_class",
'declarations' => array(
'flex-grow' => '1',
),
);
if ( isset( $child_layout['columnSpan'] ) ) {
$column_span = $child_layout['columnSpan'];
$child_layout_declarations['grid-column'] = "span $column_span";
}
if ( isset( $child_layout['rowSpan'] ) ) {
$row_span = $child_layout['rowSpan'];
$child_layout_declarations['grid-row'] = "span $row_span";
}
$child_layout_styles[] = array(
'selector' => ".$container_content_class",
'declarations' => $child_layout_declarations,
);

/*
* If columnSpan is set, and the parent grid is responsive, i.e. if it has a minimumColumnWidth set,
* the columnSpan should be removed on small grids. If there's a minimumColumnWidth, the grid is responsive.
* But if the minimumColumnWidth value wasn't changed, it won't be set. In that case, if columnCount doesn't
* exist, we can assume that the grid is responsive.
*/
if ( isset( $child_layout['columnSpan'] ) && ( isset( $block['parentLayout']['minimumColumnWidth'] ) || ! isset( $block['parentLayout']['columnCount'] ) ) ) {
$column_span_number = floatval( $child_layout['columnSpan'] );
$parent_column_width = isset( $block['parentLayout']['minimumColumnWidth'] ) ? $block['parentLayout']['minimumColumnWidth'] : '12rem';
$parent_column_value = floatval( $parent_column_width );
$parent_column_unit = explode( $parent_column_value, $parent_column_width );

/*
* If there is no unit, the width has somehow been mangled so we reset both unit and value
* to defaults.
* Additionally, the unit should be one of px, rem or em, so that also needs to be checked.
*/
if ( count( $parent_column_unit ) <= 1 ) {
$parent_column_unit = 'rem';
$parent_column_value = 12;
} else {
$parent_column_unit = $parent_column_unit[1];

if ( ! in_array( $parent_column_unit, array( 'px', 'rem', 'em' ), true ) ) {
$parent_column_unit = 'rem';
}
}

wp_style_engine_get_stylesheet_from_css_rules(
$child_layout_styles,
array(
'context' => 'block-supports',
'prettify' => false,
)
/*
* A default gap value is used for this computation because custom gap values may not be
* viable to use in the computation of the container query value.
*/
$default_gap_value = 'px' === $parent_column_unit ? 24 : 1.5;
$container_query_value = $column_span_number * $parent_column_value + ( $column_span_number - 1 ) * $default_gap_value;
$container_query_value = $container_query_value . $parent_column_unit;

$child_layout_styles[] = array(
'rules_group' => "@container (max-width: $container_query_value )",
'selector' => ".$container_content_class",
'declarations' => array(
'grid-column' => '1/-1',
),
);
}

/*
* Add to the style engine store to enqueue and render layout styles.
* Return styles here just to check if any exist.
*/
$child_css = wp_style_engine_get_stylesheet_from_css_rules(
$child_layout_styles,
array(
'context' => 'block-supports',
'prettify' => false,
)
);

if ( $child_css ) {
$outer_class_names[] = $container_content_class;
}

Expand Down Expand Up @@ -851,6 +907,25 @@ function wp_render_layout_support_flag( $block_content, $block ) {
return $processor->get_updated_html();
}

/*
* Add a `render_block_data` filter to fetch the parent block layout data.
*/
add_filter(
'render_block_data',
function ( $parsed_block, $source_block, $parent_block ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just double-checked the WP coding standards, and it looks like it's discouraged to use anonymous functions in filters:

Closures should not be passed as filter or action callbacks, as removing these via remove_action() / remove_filter() is complex (at this time) (see #46635 for a proposal to address this).

Should we move this to a named function so that plugins (if they really wanted to) are able to remove_filter this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done!

/*
* Check if the parent block exists and if it has a layout attribute.
* If it does, add the parent layout to the parsed block.
*/
if ( $parent_block && isset( $parent_block->parsed_block['attrs']['layout'] ) ) {
$parsed_block['parentLayout'] = $parent_block->parsed_block['attrs']['layout'];
}
return $parsed_block;
},
10,
3
);

// Register the block support.
WP_Block_Supports::get_instance()->register(
'layout',
Expand Down
3 changes: 3 additions & 0 deletions src/wp-includes/kses.php
Original file line number Diff line number Diff line change
Expand Up @@ -2441,11 +2441,13 @@ function safecss_filter_attr( $css, $deprecated = '' ) {
'grid-auto-columns',
'grid-column-start',
'grid-column-end',
'grid-column',
'grid-column-gap',
'grid-template-rows',
'grid-auto-rows',
'grid-row-start',
'grid-row-end',
'grid-row',
'grid-row-gap',
'grid-gap',

Expand Down Expand Up @@ -2475,6 +2477,7 @@ function safecss_filter_attr( $css, $deprecated = '' ) {
'z-index',
'box-shadow',
'aspect-ratio',
'container-type',

// Custom CSS properties.
'--*',
Expand Down