UNPKG

@wordpress/block-editor

Version:
161 lines (147 loc) 4.26 kB
/** * WordPress dependencies */ import { addFilter } from '@wordpress/hooks'; import { SelectControl, Button, __experimentalHStack as HStack, } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { hasBlockSupport } from '@wordpress/blocks'; import { createHigherOrderComponent } from '@wordpress/compose'; import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ import { store as blockEditorStore } from '../store'; import { InspectorControls } from '../components'; /** * External dependencies */ import merge from 'deepmerge'; function BehaviorsControl( { blockName, blockBehaviors, onChange, disabled = false, } ) { const { settings, themeBehaviors } = useSelect( ( select ) => { const { getBehaviors, getSettings } = select( blockEditorStore ); return { settings: getSettings()?.__experimentalFeatures?.blocks?.[ blockName ] ?.behaviors, themeBehaviors: getBehaviors()?.blocks?.[ blockName ], }; }, [ blockName ] ); const noBehaviorsOption = { value: '', label: __( 'No behaviors' ), }; const behaviorsOptions = Object.entries( settings ) .filter( ( [ behaviorName, behaviorValue ] ) => hasBlockSupport( blockName, 'behaviors.' + behaviorName ) && behaviorValue ) // Filter out behaviors that are disabled. .map( ( [ behaviorName ] ) => ( { value: behaviorName, label: // Capitalize the first letter of the behavior name. behaviorName[ 0 ].toUpperCase() + behaviorName.slice( 1 ).toLowerCase(), } ) ); // If every behavior is disabled, do not show the behaviors inspector control. if ( behaviorsOptions.length === 0 ) return null; const options = [ noBehaviorsOption, ...behaviorsOptions ]; // Block behaviors take precedence over theme behaviors. const behaviors = merge( themeBehaviors, blockBehaviors || {} ); const helpText = disabled ? __( 'The lightbox behavior is disabled for linked images.' ) : __( 'Add behaviors.' ); return ( <InspectorControls group="advanced"> { /* This div is needed to prevent a margin bottom between the dropdown and the button. */ } <div> <SelectControl label={ __( 'Behaviors' ) } // At the moment we are only supporting one behavior (Lightbox) value={ behaviors?.lightbox ? 'lightbox' : '' } options={ options } onChange={ onChange } hideCancelButton={ true } help={ helpText } size="__unstable-large" disabled={ disabled } /> </div> <HStack justify="flex-end"> <Button isSmall disabled={ disabled } onClick={ () => onChange( undefined ) } > { __( 'Reset' ) } </Button> </HStack> </InspectorControls> ); } /** * Override the default edit UI to include a new block inspector control for * assigning behaviors to blocks if behaviors are enabled in the theme.json. * * Currently, only the `core/image` block is supported. * * @param {WPComponent} BlockEdit Original component. * * @return {WPComponent} Wrapped component. */ export const withBehaviors = createHigherOrderComponent( ( BlockEdit ) => { return ( props ) => { const blockEdit = <BlockEdit key="edit" { ...props } />; // Only add behaviors to blocks with support. if ( ! hasBlockSupport( props.name, 'behaviors' ) ) { return blockEdit; } const blockHasLink = typeof props.attributes?.linkDestination !== 'undefined' && props.attributes?.linkDestination !== 'none'; return ( <> { blockEdit } <BehaviorsControl blockName={ props.name } blockBehaviors={ props.attributes.behaviors } onChange={ ( nextValue ) => { if ( nextValue === undefined ) { props.setAttributes( { behaviors: undefined, } ); } else { // If the user selects something, it means that they want to // change the default value (true) so we save it in the attributes. props.setAttributes( { behaviors: { lightbox: nextValue === 'lightbox', }, } ); } } } disabled={ blockHasLink } /> </> ); }; }, 'withBehaviors' ); if ( window?.__experimentalInteractivityAPI ) { addFilter( 'editor.BlockEdit', 'core/behaviors/with-inspector-control', withBehaviors ); }