UNPKG

@wordpress/block-editor

Version:
199 lines (181 loc) 4.85 kB
/** * WordPress dependencies */ import { __ } from '@wordpress/i18n'; import { BaseControl, Flex, FlexItem, RangeControl, __experimentalUnitControl as UnitControl, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, } from '@wordpress/components'; /** * Internal dependencies */ import { appendSelectors, getBlockGapCSS } from './utils'; import { getGapCSSValue } from '../hooks/gap'; import { shouldSkipSerialization } from '../hooks/utils'; const RANGE_CONTROL_MAX_VALUES = { px: 600, '%': 100, vw: 100, vh: 100, em: 38, rem: 38, }; export default { name: 'grid', label: __( 'Grid' ), inspectorControls: function GridLayoutInspectorControls( { layout = {}, onChange, } ) { return layout?.columnCount ? ( <GridLayoutColumnsControl layout={ layout } onChange={ onChange } /> ) : ( <GridLayoutMinimumWidthControl layout={ layout } onChange={ onChange } /> ); }, toolBarControls: function DefaultLayoutToolbarControls() { return null; }, getLayoutStyle: function getLayoutStyle( { selector, layout, style, blockName, hasBlockGapSupport, layoutDefinitions, } ) { const { minimumColumnWidth = '12rem', columnCount = null } = layout; // If a block's block.json skips serialization for spacing or spacing.blockGap, // don't apply the user-defined value to the styles. const blockGapValue = style?.spacing?.blockGap && ! shouldSkipSerialization( blockName, 'spacing', 'blockGap' ) ? getGapCSSValue( style?.spacing?.blockGap, '0.5em' ) : undefined; let output = ''; const rules = []; if ( columnCount ) { rules.push( `grid-template-columns: repeat(${ columnCount }, minmax(0, 1fr))` ); } else if ( minimumColumnWidth ) { rules.push( `grid-template-columns: repeat(auto-fill, minmax(min(${ minimumColumnWidth }, 100%), 1fr))` ); } if ( rules.length ) { // Reason to disable: the extra line breaks added by prettier mess with the unit tests. // eslint-disable-next-line prettier/prettier output = `${ appendSelectors( selector ) } { ${ rules.join( '; ' ) }; }`; } // Output blockGap styles based on rules contained in layout definitions in theme.json. if ( hasBlockGapSupport && blockGapValue ) { output += getBlockGapCSS( selector, layoutDefinitions, 'grid', blockGapValue ); } return output; }, getOrientation() { return 'horizontal'; }, getAlignments() { return []; }, }; // Enables setting minimum width of grid items. function GridLayoutMinimumWidthControl( { layout, onChange } ) { const { minimumColumnWidth: value = '12rem' } = layout; const [ quantity, unit ] = parseQuantityAndUnitFromRawValue( value ); const handleSliderChange = ( next ) => { onChange( { ...layout, minimumColumnWidth: [ next, unit ].join( '' ), } ); }; // Mostly copied from HeightControl. const handleUnitChange = ( newUnit ) => { // Attempt to smooth over differences between currentUnit and newUnit. // This should slightly improve the experience of switching between unit types. let newValue; if ( [ 'em', 'rem' ].includes( newUnit ) && unit === 'px' ) { // Convert pixel value to an approximate of the new unit, assuming a root size of 16px. newValue = ( quantity / 16 ).toFixed( 2 ) + newUnit; } else if ( [ 'em', 'rem' ].includes( unit ) && newUnit === 'px' ) { // Convert to pixel value assuming a root size of 16px. newValue = Math.round( quantity * 16 ) + newUnit; } else if ( [ 'vh', 'vw', '%' ].includes( newUnit ) && quantity > 100 ) { // When converting to `vh`, `vw`, or `%` units, cap the new value at 100. newValue = 100 + newUnit; } onChange( { ...layout, minimumColumnWidth: newValue, } ); }; return ( <fieldset> <BaseControl.VisualLabel as="legend"> { __( 'Minimum column width' ) } </BaseControl.VisualLabel> <Flex gap={ 4 }> <FlexItem isBlock> <UnitControl size={ '__unstable-large' } onChange={ ( newValue ) => { onChange( { ...layout, minimumColumnWidth: newValue, } ); } } onUnitChange={ handleUnitChange } value={ value } min={ 0 } /> </FlexItem> <FlexItem isBlock> <RangeControl onChange={ handleSliderChange } value={ quantity } min={ 0 } max={ RANGE_CONTROL_MAX_VALUES[ unit ] || 600 } withInputField={ false } /> </FlexItem> </Flex> </fieldset> ); } // Enables setting number of grid columns function GridLayoutColumnsControl( { layout, onChange } ) { const { columnCount = 3 } = layout; return ( <RangeControl label={ __( 'Columns' ) } value={ columnCount } onChange={ ( value ) => onChange( { ...layout, columnCount: value, } ) } min={ 1 } max={ 6 } /> ); }