UNPKG

@wordpress/block-editor

Version:
278 lines (264 loc) 7.43 kB
/** * WordPress dependencies */ import { __experimentalUseCustomUnits as useCustomUnits, __experimentalUnitControl as UnitControl, __experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOptionIcon as ToggleGroupControlOptionIcon, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { Icon, positionCenter, stretchWide, justifyLeft, justifyCenter, justifyRight, } from '@wordpress/icons'; import { getCSSRules } from '@wordpress/style-engine'; /** * Internal dependencies */ import useSetting from '../components/use-setting'; import { appendSelectors, getBlockGapCSS, getAlignmentsInfo } from './utils'; import { getGapCSSValue } from '../hooks/gap'; import { shouldSkipSerialization } from '../hooks/utils'; export default { name: 'constrained', label: __( 'Constrained' ), inspectorControls: function DefaultLayoutInspectorControls( { layout, onChange, layoutBlockSupport = {}, } ) { const { wideSize, contentSize, justifyContent = 'center' } = layout; const { allowJustification = true } = layoutBlockSupport; const onJustificationChange = ( value ) => { onChange( { ...layout, justifyContent: value, } ); }; const justificationOptions = [ { value: 'left', icon: justifyLeft, label: __( 'Justify items left' ), }, { value: 'center', icon: justifyCenter, label: __( 'Justify items center' ), }, { value: 'right', icon: justifyRight, label: __( 'Justify items right' ), }, ]; const units = useCustomUnits( { availableUnits: useSetting( 'spacing.units' ) || [ '%', 'px', 'em', 'rem', 'vw', ], } ); return ( <> <div className="block-editor-hooks__layout-controls"> <div className="block-editor-hooks__layout-controls-unit"> <UnitControl className="block-editor-hooks__layout-controls-unit-input" label={ __( 'Content' ) } labelPosition="top" __unstableInputWidth="80px" value={ contentSize || wideSize || '' } onChange={ ( nextWidth ) => { nextWidth = 0 > parseFloat( nextWidth ) ? '0' : nextWidth; onChange( { ...layout, contentSize: nextWidth, } ); } } units={ units } /> <Icon icon={ positionCenter } /> </div> <div className="block-editor-hooks__layout-controls-unit"> <UnitControl className="block-editor-hooks__layout-controls-unit-input" label={ __( 'Wide' ) } labelPosition="top" __unstableInputWidth="80px" value={ wideSize || contentSize || '' } onChange={ ( nextWidth ) => { nextWidth = 0 > parseFloat( nextWidth ) ? '0' : nextWidth; onChange( { ...layout, wideSize: nextWidth, } ); } } units={ units } /> <Icon icon={ stretchWide } /> </div> </div> <p className="block-editor-hooks__layout-controls-helptext"> { __( 'Customize the width for all elements that are assigned to the center or wide columns.' ) } </p> { allowJustification && ( <ToggleGroupControl __nextHasNoMarginBottom label={ __( 'Justification' ) } value={ justifyContent } onChange={ onJustificationChange } > { justificationOptions.map( ( { value, icon, label } ) => { return ( <ToggleGroupControlOptionIcon key={ value } value={ value } icon={ icon } label={ label } /> ); } ) } </ToggleGroupControl> ) } </> ); }, toolBarControls: function DefaultLayoutToolbarControls() { return null; }, getLayoutStyle: function getLayoutStyle( { selector, layout = {}, style, blockName, hasBlockGapSupport, layoutDefinitions, } ) { const { contentSize, wideSize, justifyContent } = layout; const blockGapStyleValue = getGapCSSValue( style?.spacing?.blockGap ); // If a block's block.json skips serialization for spacing or // spacing.blockGap, don't apply the user-defined value to the styles. let blockGapValue = ''; if ( ! shouldSkipSerialization( blockName, 'spacing', 'blockGap' ) ) { // If an object is provided only use the 'top' value for this kind of gap. if ( blockGapStyleValue?.top ) { blockGapValue = getGapCSSValue( blockGapStyleValue?.top ); } else if ( typeof blockGapStyleValue === 'string' ) { blockGapValue = getGapCSSValue( blockGapStyleValue ); } } const marginLeft = justifyContent === 'left' ? '0 !important' : 'auto !important'; const marginRight = justifyContent === 'right' ? '0 !important' : 'auto !important'; let output = !! contentSize || !! wideSize ? ` ${ appendSelectors( selector, '> :where(:not(.alignleft):not(.alignright):not(.alignfull))' ) } { max-width: ${ contentSize ?? wideSize }; margin-left: ${ marginLeft }; margin-right: ${ marginRight }; } ${ appendSelectors( selector, '> .alignwide' ) } { max-width: ${ wideSize ?? contentSize }; } ${ appendSelectors( selector, '> .alignfull' ) } { max-width: none; } ` : ''; if ( justifyContent === 'left' ) { output += `${ appendSelectors( selector, '> :where(:not(.alignleft):not(.alignright):not(.alignfull))' ) } { margin-left: ${ marginLeft }; }`; } else if ( justifyContent === 'right' ) { output += `${ appendSelectors( selector, '> :where(:not(.alignleft):not(.alignright):not(.alignfull))' ) } { margin-right: ${ marginRight }; }`; } // If there is custom padding, add negative margins for alignfull blocks. if ( style?.spacing?.padding ) { // The style object might be storing a preset so we need to make sure we get a usable value. const paddingValues = getCSSRules( style ); paddingValues.forEach( ( rule ) => { if ( rule.key === 'paddingRight' ) { output += ` ${ appendSelectors( selector, '> .alignfull' ) } { margin-right: calc(${ rule.value } * -1); } `; } else if ( rule.key === 'paddingLeft' ) { output += ` ${ appendSelectors( selector, '> .alignfull' ) } { margin-left: calc(${ rule.value } * -1); } `; } } ); } // Output blockGap styles based on rules contained in layout definitions in theme.json. if ( hasBlockGapSupport && blockGapValue ) { output += getBlockGapCSS( selector, layoutDefinitions, 'constrained', blockGapValue ); } return output; }, getOrientation() { return 'vertical'; }, getAlignments( layout ) { const alignmentInfo = getAlignmentsInfo( layout ); if ( layout.alignments !== undefined ) { if ( ! layout.alignments.includes( 'none' ) ) { layout.alignments.unshift( 'none' ); } return layout.alignments.map( ( alignment ) => ( { name: alignment, info: alignmentInfo[ alignment ], } ) ); } const { contentSize, wideSize } = layout; const alignments = [ { name: 'left' }, { name: 'center' }, { name: 'right' }, ]; if ( contentSize ) { alignments.unshift( { name: 'full' } ); } if ( wideSize ) { alignments.unshift( { name: 'wide', info: alignmentInfo.wide } ); } alignments.unshift( { name: 'none', info: alignmentInfo.none } ); return alignments; }, };