UNPKG

@wordpress/block-editor

Version:
207 lines (183 loc) 5.64 kB
/** * External dependencies */ import clsx from 'clsx'; /** * WordPress dependencies */ import { Platform, useState, useEffect, useCallback } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; import { getBlockSupport } from '@wordpress/blocks'; import deprecated from '@wordpress/deprecated'; /** * Internal dependencies */ import InspectorControls from '../components/inspector-controls'; import { DimensionsPanel as StylesDimensionsPanel, useHasDimensionsPanel, } from '../components/global-styles'; import { MarginVisualizer, PaddingVisualizer } from './spacing-visualizer'; import { store as blockEditorStore } from '../store'; import { unlock } from '../lock-unlock'; import { cleanEmptyObject, shouldSkipSerialization } from './utils'; export const DIMENSIONS_SUPPORT_KEY = 'dimensions'; export const SPACING_SUPPORT_KEY = 'spacing'; export const ALL_SIDES = [ 'top', 'right', 'bottom', 'left' ]; export const AXIAL_SIDES = [ 'vertical', 'horizontal' ]; function useVisualizer() { const [ property, setProperty ] = useState( false ); const { hideBlockInterface, showBlockInterface } = unlock( useDispatch( blockEditorStore ) ); useEffect( () => { if ( ! property ) { showBlockInterface(); } else { hideBlockInterface(); } }, [ property, showBlockInterface, hideBlockInterface ] ); return [ property, setProperty ]; } function DimensionsInspectorControl( { children, resetAllFilter } ) { const attributesResetAllFilter = useCallback( ( attributes ) => { const existingStyle = attributes.style; const updatedStyle = resetAllFilter( existingStyle ); return { ...attributes, style: updatedStyle, }; }, [ resetAllFilter ] ); return ( <InspectorControls group="dimensions" resetAllFilter={ attributesResetAllFilter } > { children } </InspectorControls> ); } export function DimensionsPanel( { clientId, name, setAttributes, settings } ) { const isEnabled = useHasDimensionsPanel( settings ); const value = useSelect( ( select ) => select( blockEditorStore ).getBlockAttributes( clientId )?.style, [ clientId ] ); const [ visualizedProperty, setVisualizedProperty ] = useVisualizer(); const onChange = ( newStyle ) => { setAttributes( { style: cleanEmptyObject( newStyle ), } ); }; if ( ! isEnabled ) { return null; } const defaultDimensionsControls = getBlockSupport( name, [ DIMENSIONS_SUPPORT_KEY, '__experimentalDefaultControls', ] ); const defaultSpacingControls = getBlockSupport( name, [ SPACING_SUPPORT_KEY, '__experimentalDefaultControls', ] ); const defaultControls = { ...defaultDimensionsControls, ...defaultSpacingControls, }; return ( <> <StylesDimensionsPanel as={ DimensionsInspectorControl } panelId={ clientId } settings={ settings } value={ value } onChange={ onChange } defaultControls={ defaultControls } onVisualize={ setVisualizedProperty } /> { !! settings?.spacing?.padding && ( <PaddingVisualizer forceShow={ visualizedProperty === 'padding' } clientId={ clientId } value={ value } /> ) } { !! settings?.spacing?.margin && ( <MarginVisualizer forceShow={ visualizedProperty === 'margin' } clientId={ clientId } value={ value } /> ) } </> ); } /** * Determine whether there is block support for dimensions. * * @param {string} blockName Block name. * @param {string} feature Background image feature to check for. * * @return {boolean} Whether there is support. */ export function hasDimensionsSupport( blockName, feature = 'any' ) { if ( Platform.OS !== 'web' ) { return false; } const support = getBlockSupport( blockName, DIMENSIONS_SUPPORT_KEY ); if ( support === true ) { return true; } if ( feature === 'any' ) { return !! ( support?.aspectRatio || !! support?.minHeight ); } return !! support?.[ feature ]; } export default { useBlockProps, attributeKeys: [ 'minHeight', 'style' ], hasSupport( name ) { return hasDimensionsSupport( name, 'aspectRatio' ); }, }; function useBlockProps( { name, minHeight, style } ) { if ( ! hasDimensionsSupport( name, 'aspectRatio' ) || shouldSkipSerialization( name, DIMENSIONS_SUPPORT_KEY, 'aspectRatio' ) ) { return {}; } const className = clsx( { 'has-aspect-ratio': !! style?.dimensions?.aspectRatio, } ); // Allow dimensions-based inline style overrides to override any global styles rules that // might be set for the block, and therefore affect the display of the aspect ratio. const inlineStyleOverrides = {}; // Apply rules to unset incompatible styles. // Note that a set `aspectRatio` will win out if both an aspect ratio and a minHeight are set. // This is because the aspect ratio is a newer block support, so (in theory) any aspect ratio // that is set should be intentional and should override any existing minHeight. The Cover block // and dimensions controls have logic that will manually clear the aspect ratio if a minHeight // is set. if ( style?.dimensions?.aspectRatio ) { // To ensure the aspect ratio does not get overridden by `minHeight` unset any existing rule. inlineStyleOverrides.minHeight = 'unset'; } else if ( minHeight || style?.dimensions?.minHeight ) { // To ensure the minHeight does not get overridden by `aspectRatio` unset any existing rule. inlineStyleOverrides.aspectRatio = 'unset'; } return { className, style: inlineStyleOverrides }; } /** * @deprecated */ export function useCustomSides() { deprecated( 'wp.blockEditor.__experimentalUseCustomSides', { since: '6.3', version: '6.4', } ); }