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: Avoid column width auto-adjustment when sibling width changes #19515

Merged
merged 11 commits into from
Feb 10, 2020
Merged
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
70 changes: 8 additions & 62 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 @@ -18,22 +17,11 @@ 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,
setAttributes,
className,
updateAlignment,
updateWidth,
hasChildBlocks,
} ) {
const { verticalAlignment, width } = attributes;
Expand All @@ -55,11 +43,17 @@ function ColumnEdit( {
<RangeControl
label={ __( 'Percentage width' ) }
value={ width || '' }
onChange={ updateWidth }
onChange={ ( nextWidth ) => {
setAttributes( { width: nextWidth } );
} }
min={ 0 }
max={ 100 }
step={ 0.1 }
required
allowReset
placeholder={
width === undefined ? __( 'Auto' ) : undefined
}
/>
</PanelBody>
</InspectorControls>
Expand Down Expand Up @@ -104,54 +98,6 @@ export default compose(
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 );
1 change: 1 addition & 0 deletions packages/block-library/src/column/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const settings = {
style: {
flexBasis: width + '%',
},
'data-has-explicit-width': true,
};
}
},
Expand Down
14 changes: 11 additions & 3 deletions packages/block-library/src/columns/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,18 @@
// Responsiveness: Show at most one columns on mobile.
flex-basis: 100%;

// Beyond mobile, allow 2 columns.
@include break-small() {
flex-basis: calc(50% - (#{$grid-size-large}));
flex-grow: 0;
flex-grow: 1;
flex-basis: auto;

// Beyond mobile, allow columns. Columns with an explicitly-
// assigned width should maintain their `flex-basis` width and
// not grow. All other blocks should automatically inherit the
// `flex-grow` to occupy the available space.
&[data-has-explicit-width] {
flex-grow: 0;
}

margin-left: 0;
margin-right: 0;
}
Expand Down
10 changes: 7 additions & 3 deletions packages/block-library/src/columns/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,13 @@

@include break-small() {

// Beyond mobile, allow 2 columns.
flex-basis: calc(50% - #{$grid-size-large});
flex-grow: 0;
// Beyond mobile, allow columns. Columns with an explicitly-assigned
// width should maintain their `flex-basis` width and not grow. All
// other blocks should automatically inherit the `flex-grow` to occupy
// the available space.
&[style] {
flex-grow: 0;
}

// Add space between the multiple columns. Themes can customize this if they wish to work differently.
// Only apply this beyond the mobile breakpoint, as there's only a single column on mobile.
Expand Down
44 changes: 23 additions & 21 deletions packages/block-library/src/columns/test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
*/
import {
toWidthPrecision,
getAdjacentBlocks,
getEffectiveColumnWidth,
getTotalColumnsWidth,
getColumnWidths,
Expand All @@ -25,25 +24,6 @@ describe( 'toWidthPrecision', () => {
} );
} );

describe( 'getAdjacentBlocks', () => {
const blockA = { clientId: 'a' };
const blockB = { clientId: 'b' };
const blockC = { clientId: 'c' };
const blocks = [ blockA, blockB, blockC ];

it( 'should return blocks after clientId', () => {
const result = getAdjacentBlocks( blocks, 'b' );

expect( result ).toEqual( [ blockC ] );
} );

it( 'should return blocks before clientId if clientId is last', () => {
const result = getAdjacentBlocks( blocks, 'c' );

expect( result ).toEqual( [ blockA, blockB ] );
} );
} );

describe( 'getEffectiveColumnWidth', () => {
it( 'should return attribute value if set, rounded to precision', () => {
const block = { attributes: { width: 50.108 } };
Expand Down Expand Up @@ -186,7 +166,29 @@ describe( 'hasExplicitColumnWidths', () => {
} );

it( 'returns true if a block has explicit width', () => {
const blocks = [ { attributes: { width: 10 } } ];
const blocks = [ { attributes: { width: 100 } } ];

const result = hasExplicitColumnWidths( blocks );

expect( result ).toBe( true );
} );

it( 'returns false if some, not all blocks have explicit width', () => {
const blocks = [
{ attributes: { width: 10 } },
{ attributes: { width: undefined } },
];

const result = hasExplicitColumnWidths( blocks );

expect( result ).toBe( false );
} );

it( 'returns true if all blocks have explicit width', () => {
const blocks = [
{ attributes: { width: 10 } },
{ attributes: { width: 90 } },
];

const result = hasExplicitColumnWidths( blocks );

Expand Down
22 changes: 2 additions & 20 deletions packages/block-library/src/columns/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { findIndex, sumBy, merge, mapValues } from 'lodash';
import { sumBy, merge, mapValues } from 'lodash';

/**
* Returns a column width attribute value rounded to standard precision.
Expand All @@ -14,24 +14,6 @@ import { findIndex, sumBy, merge, mapValues } from 'lodash';
export const toWidthPrecision = ( value ) =>
Number.isFinite( value ) ? parseFloat( value.toFixed( 2 ) ) : undefined;

/**
* Returns the considered adjacent to that of the specified `clientId` for
* resizing consideration. Adjacent blocks are those occurring after, except
* when the given block is the last block in the set. For the last block, the
* behavior is reversed.
*
* @param {WPBlock[]} blocks Block objects.
* @param {string} clientId Client ID to consider for adjacent blocks.
*
* @return {WPBlock[]} Adjacent block objects.
*/
export function getAdjacentBlocks( blocks, clientId ) {
const index = findIndex( blocks, { clientId } );
const isLastBlock = index === blocks.length - 1;

return isLastBlock ? blocks.slice( 0, index ) : blocks.slice( index + 1 );
}

/**
* Returns an effective width for a given block. An effective width is equal to
* its attribute value if set, or a computed value assuming equal distribution.
Expand Down Expand Up @@ -115,7 +97,7 @@ export function getRedistributedColumnWidths(
* @return {boolean} Whether columns have explicit widths.
*/
export function hasExplicitColumnWidths( blocks ) {
return blocks.some( ( block ) =>
return blocks.every( ( block ) =>
Number.isFinite( block.attributes.width )
);
}
Expand Down