Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Block Library: Move Column resizing to Columns #16077

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
64 changes: 1 addition & 63 deletions packages/block-library/src/column/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* External dependencies
*/
import classnames from 'classnames';
import { forEach, find, difference } from 'lodash';

/**
* WordPress dependencies
Expand All @@ -11,31 +10,16 @@ import {
InnerBlocks,
BlockControls,
BlockVerticalAlignmentToolbar,
InspectorControls,
} from '@wordpress/block-editor';
import { PanelBody, RangeControl } from '@wordpress/components';
import { withDispatch, withSelect } from '@wordpress/data';
import { compose } from '@wordpress/compose';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import {
toWidthPrecision,
getTotalColumnsWidth,
getColumnWidths,
getAdjacentBlocks,
getRedistributedColumnWidths,
} from '../columns/utils';

function ColumnEdit( {
attributes,
updateAlignment,
updateWidth,
hasChildBlocks,
} ) {
const { verticalAlignment, width } = attributes;
const { verticalAlignment } = attributes;

const classes = classnames( 'block-core-columns', {
[ `is-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment,
Expand All @@ -49,19 +33,6 @@ function ColumnEdit( {
value={ verticalAlignment }
/>
</BlockControls>
<InspectorControls>
<PanelBody title={ __( 'Column Settings' ) }>
<RangeControl
label={ __( 'Percentage width' ) }
value={ width || '' }
onChange={ updateWidth }
min={ 0 }
max={ 100 }
required
allowReset
/>
</PanelBody>
</InspectorControls>
<InnerBlocks
templateLock={ false }
renderAppender={ (
Expand Down Expand Up @@ -97,39 +68,6 @@ export default compose(
const rootClientId = getBlockRootClientId( clientId );
updateBlockAttributes( rootClientId, { verticalAlignment: null } );
},
updateWidth( width ) {
const { clientId } = ownProps;
const { updateBlockAttributes } = dispatch( 'core/block-editor' );
const { getBlockRootClientId, getBlocks } = registry.select( 'core/block-editor' );

// Constrain or expand siblings to account for gain or loss of
// total columns area.
const columns = getBlocks( getBlockRootClientId( clientId ) );
const adjacentColumns = getAdjacentBlocks( columns, clientId );

// The occupied width is calculated as the sum of the new width
// and the total width of blocks _not_ in the adjacent set.
const occupiedWidth = width + getTotalColumnsWidth(
difference( columns, [
find( columns, { clientId } ),
...adjacentColumns,
] )
);

// Compute _all_ next column widths, in case the updated column
// is in the middle of a set of columns which don't yet have
// any explicit widths assigned (include updates to those not
// part of the adjacent blocks).
const nextColumnWidths = {
...getColumnWidths( columns, columns.length ),
[ clientId ]: toWidthPrecision( width ),
...getRedistributedColumnWidths( adjacentColumns, 100 - occupiedWidth, columns.length ),
};

forEach( nextColumnWidths, ( nextColumnWidth, columnClientId ) => {
updateBlockAttributes( columnClientId, { width: nextColumnWidth } );
} );
},
};
} )
)( ColumnEdit );
77 changes: 71 additions & 6 deletions packages/block-library/src/columns/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
* External dependencies
*/
import classnames from 'classnames';
import { dropRight } from 'lodash';
import { dropRight, forEach, find, difference } from 'lodash';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { __, sprintf } from '@wordpress/i18n';
import {
PanelBody,
RangeControl,
Expand All @@ -18,7 +18,7 @@ import {
BlockControls,
BlockVerticalAlignmentToolbar,
} from '@wordpress/block-editor';
import { withDispatch } from '@wordpress/data';
import { withDispatch, useSelect } from '@wordpress/data';
import { createBlock } from '@wordpress/blocks';

/**
Expand All @@ -30,6 +30,9 @@ import {
getMappedColumnWidths,
getRedistributedColumnWidths,
toWidthPrecision,
getTotalColumnsWidth,
getColumnWidths,
getAdjacentBlocks,
} from './utils';

/**
Expand All @@ -44,17 +47,23 @@ import {
const ALLOWED_BLOCKS = [ 'core/column' ];

export function ColumnsEdit( {
clientId,
attributes,
className,
updateAlignment,
updateColumns,
updateColumnWidth,
} ) {
const { columns, verticalAlignment } = attributes;

const classes = classnames( className, `has-${ columns }-columns`, {
[ `are-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment,
} );

const columnBlocks = useSelect( ( select ) => (
select( 'core/block-editor' ).getBlocks( clientId )
) );

return (
<>
<InspectorControls>
Expand All @@ -67,6 +76,27 @@ export function ColumnsEdit( {
max={ 6 }
/>
</PanelBody>
<PanelBody title={ __( 'Column Settings' ) }>
{ columnBlocks.map( ( columnBlock, index ) => (
<fieldset
key={ columnBlock.clientId }
className="wp-block-columns__column-settings-column"
>
<legend>{ sprintf( __( 'Column %d' ), index + 1 ) }</legend>
<RangeControl
label={ __( 'Percentage width' ) }
value={ columnBlock.attributes.width || '' }
onChange={ ( nextWidth ) => {
updateColumnWidth( columnBlock.clientId, nextWidth );
} }
min={ 0 }
max={ 100 }
required
allowReset
/>
</fieldset>
) ) }
</PanelBody>
</InspectorControls>
<BlockControls>
<BlockVerticalAlignmentToolbar
Expand Down Expand Up @@ -113,10 +143,12 @@ export default withDispatch( ( dispatch, ownProps, registry ) => ( {
* Updates the column count, including necessary revisions to child Column
* blocks to grant required or redistribute available space.
*
* @param {number} columns New column count.
* @param {string} clientId Client ID of column block for which to update
* width attribute.
* @param {number} columns New column count.
*/
updateColumns( columns ) {
const { clientId, setAttributes, attributes } = ownProps;
updateColumns( clientId, columns ) {
const { setAttributes, attributes } = ownProps;
const { replaceInnerBlocks } = dispatch( 'core/block-editor' );
const { getBlocks } = registry.select( 'core/block-editor' );

Expand Down Expand Up @@ -159,4 +191,37 @@ export default withDispatch( ( dispatch, ownProps, registry ) => ( {

replaceInnerBlocks( clientId, innerBlocks, false );
},

updateColumnWidth( clientId, width ) {
const { updateBlockAttributes } = dispatch( 'core/block-editor' );
const { getBlockRootClientId, getBlocks } = registry.select( 'core/block-editor' );

// Constrain or expand siblings to account for gain or loss of
// total columns area.
const columns = getBlocks( getBlockRootClientId( clientId ) );
const adjacentColumns = getAdjacentBlocks( columns, clientId );

// The occupied width is calculated as the sum of the new width
// and the total width of blocks _not_ in the adjacent set.
const occupiedWidth = width + getTotalColumnsWidth(
difference( columns, [
find( columns, { clientId } ),
...adjacentColumns,
] )
);

// Compute _all_ next column widths, in case the updated column
// is in the middle of a set of columns which don't yet have
// any explicit widths assigned (include updates to those not
// part of the adjacent blocks).
const nextColumnWidths = {
...getColumnWidths( columns, columns.length ),
[ clientId ]: toWidthPrecision( width ),
...getRedistributedColumnWidths( adjacentColumns, 100 - occupiedWidth, columns.length ),
};

forEach( nextColumnWidths, ( nextColumnWidth, columnClientId ) => {
updateBlockAttributes( columnClientId, { width: nextColumnWidth } );
Copy link
Member

Choose a reason for hiding this comment

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

It would be great to make updateBlockAttributes more flexible or introduce some other action for batch updates like this one. In the case when there are 6 columns, it might trigger re-render 6 times for every atomic block update. Regardless of performance considerations, I anticipate that with nested blocks starting to be more and more popular we need to start thinking about batching actions to make APIs simpler to use.

Copy link
Member Author

@aduth aduth Jun 25, 2019

Choose a reason for hiding this comment

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

Another issue here might be that we add a number of Undo levels for each change (already affects master).

Copy link
Contributor

Choose a reason for hiding this comment

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

It feels like we need to start working on undo transactions soon. This has came up in other PRs recently.

Copy link
Member Author

Choose a reason for hiding this comment

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

It feels like we need to start working on undo transactions soon. This has came up in other PRs recently.

Yeah, it's similar to #8119, but I wonder if there might be some simple near-term solution:

wp.data.dispatch( 'core/editor' ).transact( () => {
	wp.data.dispatch( 'core/block-editor' ).updateBlockAttributes( /* ... */ );
	wp.data.dispatch( 'core/block-editor' ).updateBlockAttributes( /* ... */ );
} );
// `'START_TRANSACTION'`
// `'UPDATE_BLOCK_ATTRIBUTES'`
// `'UPDATE_BLOCK_ATTRIBUTES'`
// `'END_TRANSACTION'`

(or just startTransaction + endTransaction / toggleTransaction actions)

Probably worth a separate issue for tracking and discussion.

} );
},
} ) )( ColumnsEdit );
8 changes: 8 additions & 0 deletions packages/block-library/src/columns/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,11 @@ div.block-core-columns.is-vertically-aligned-bottom {
left: 0;
right: 0;
}

.wp-block-columns__column-settings-column {
legend {
font-weight: bold;
padding: 0;
margin-bottom: $grid-size-small;
}
}