@gechiui/block-editor
Version:
147 lines (131 loc) • 3.69 kB
JavaScript
/**
* GeChiUI dependencies
*/
import { __ } from '@gechiui/i18n';
import { Platform } from '@gechiui/element';
import { getBlockSupport } from '@gechiui/blocks';
import {
__experimentalUseCustomUnits as useCustomUnits,
__experimentalUnitControl as UnitControl,
} from '@gechiui/components';
/**
* Internal dependencies
*/
import { __unstableUseBlockRef as useBlockRef } from '../components/block-list/use-block-props/use-block-refs';
import useSetting from '../components/use-setting';
import { SPACING_SUPPORT_KEY } from './dimensions';
import { cleanEmptyObject } from './utils';
/**
* Determines if there is gap support.
*
* @param {string|Object} blockType Block name or Block Type object.
* @return {boolean} Whether there is support.
*/
export function hasGapSupport( blockType ) {
const support = getBlockSupport( blockType, SPACING_SUPPORT_KEY );
return !! ( true === support || support?.blockGap );
}
/**
* Checks if there is a current value in the gap block support attributes.
*
* @param {Object} props Block props.
* @return {boolean} Whether or not the block has a gap value set.
*/
export function hasGapValue( props ) {
return props.attributes.style?.spacing?.blockGap !== undefined;
}
/**
* Resets the gap block support attribute. This can be used when disabling
* the gap support controls for a block via a progressive discovery panel.
*
* @param {Object} props Block props.
* @param {Object} props.attributes Block's attributes.
* @param {Object} props.setAttributes Function to set block's attributes.
*/
export function resetGap( { attributes = {}, setAttributes } ) {
const { style } = attributes;
setAttributes( {
style: {
...style,
spacing: {
...style?.spacing,
blockGap: undefined,
},
},
} );
}
/**
* Custom hook that checks if gap settings have been disabled.
*
* @param {string} name The name of the block.
* @return {boolean} Whether the gap setting is disabled.
*/
export function useIsGapDisabled( { name: blockName } = {} ) {
const isDisabled = ! useSetting( 'spacing.blockGap' );
return ! hasGapSupport( blockName ) || isDisabled;
}
/**
* Inspector control panel containing the gap related configuration
*
* @param {Object} props
*
* @return {GCElement} Gap edit element.
*/
export function GapEdit( props ) {
const {
clientId,
attributes: { style },
setAttributes,
} = props;
const units = useCustomUnits( {
availableUnits: useSetting( 'spacing.units' ) || [
'%',
'px',
'em',
'rem',
'vw',
],
} );
const ref = useBlockRef( clientId );
if ( useIsGapDisabled( props ) ) {
return null;
}
const onChange = ( next ) => {
const newStyle = {
...style,
spacing: {
...style?.spacing,
blockGap: next,
},
};
setAttributes( {
style: cleanEmptyObject( newStyle ),
} );
// In Safari, changing the `gap` CSS value on its own will not trigger the layout
// to be recalculated / re-rendered. To force the updated gap to re-render, here
// we replace the block's node with itself.
const isSafari =
window?.navigator.userAgent &&
window.navigator.userAgent.includes( 'Safari' ) &&
! window.navigator.userAgent.includes( 'Chrome ' ) &&
! window.navigator.userAgent.includes( 'Chromium ' );
if ( ref.current && isSafari ) {
ref.current.parentNode?.replaceChild( ref.current, ref.current );
}
};
return Platform.select( {
web: (
<>
<UnitControl
label={ __( '块间距' ) }
__unstableInputWidth="80px"
min={ 0 }
onChange={ onChange }
units={ units }
value={ style?.spacing?.blockGap }
/>
</>
),
native: null,
} );
}