UNPKG

@wordpress/block-library

Version:
158 lines (143 loc) 4.36 kB
/** * WordPress dependencies */ import { useDispatch, useSelect } from '@wordpress/data'; import { InnerBlocks, useBlockProps, InspectorControls, useInnerBlocksProps, store as blockEditorStore, privateApis as blockEditorPrivateApis, } from '@wordpress/block-editor'; import { useRef } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; import { View } from '@wordpress/primitives'; /** * Internal dependencies */ import GroupPlaceHolder, { useShouldShowPlaceHolder } from './placeholder'; import { unlock } from '../lock-unlock'; const { HTMLElementControl } = unlock( blockEditorPrivateApis ); /** * Render inspector controls for the Group block. * * @param {Object} props Component props. * @param {string} props.tagName The HTML tag name. * @param {Function} props.onSelectTagName onChange function for the SelectControl. * @param {string} props.clientId The client ID of the current block. * * @return {JSX.Element} The control group. */ function GroupEditControls( { tagName, onSelectTagName, clientId } ) { return ( <InspectorControls group="advanced"> <HTMLElementControl tagName={ tagName } onChange={ onSelectTagName } clientId={ clientId } options={ [ { label: __( 'Default (<div>)' ), value: 'div' }, { label: '<header>', value: 'header' }, { label: '<main>', value: 'main' }, { label: '<section>', value: 'section' }, { label: '<article>', value: 'article' }, { label: '<aside>', value: 'aside' }, { label: '<footer>', value: 'footer' }, ] } /> </InspectorControls> ); } function GroupEdit( { attributes, name, setAttributes, clientId } ) { const { hasInnerBlocks, themeSupportsLayout } = useSelect( ( select ) => { const { getBlock, getSettings } = select( blockEditorStore ); const block = getBlock( clientId ); return { hasInnerBlocks: !! ( block && block.innerBlocks.length ), themeSupportsLayout: getSettings()?.supportsLayout, }; }, [ clientId ] ); const { tagName: TagName = 'div', templateLock, allowedBlocks, layout = {}, } = attributes; // Layout settings. const { type = 'default' } = layout; const layoutSupportEnabled = themeSupportsLayout || type === 'flex' || type === 'grid'; // Hooks. const ref = useRef(); const blockProps = useBlockProps( { ref } ); const [ showPlaceholder, setShowPlaceholder ] = useShouldShowPlaceHolder( { attributes, usedLayoutType: type, hasInnerBlocks, } ); // Default to the regular appender being rendered. let renderAppender; if ( showPlaceholder ) { // In the placeholder state, ensure the appender is not rendered. // This is needed because `...innerBlocksProps` is used in the placeholder // state so that blocks can dragged onto the placeholder area // from both the list view and in the editor canvas. renderAppender = false; } else if ( ! hasInnerBlocks ) { // When there is no placeholder, but the block is also empty, // use the larger button appender. renderAppender = InnerBlocks.ButtonBlockAppender; } const innerBlocksProps = useInnerBlocksProps( layoutSupportEnabled ? blockProps : { className: 'wp-block-group__inner-container' }, { dropZoneElement: ref.current, templateLock, allowedBlocks, renderAppender, } ); const { selectBlock } = useDispatch( blockEditorStore ); const selectVariation = ( nextVariation ) => { setAttributes( nextVariation.attributes ); selectBlock( clientId, -1 ); setShowPlaceholder( false ); }; return ( <> <GroupEditControls tagName={ TagName } onSelectTagName={ ( value ) => setAttributes( { tagName: value } ) } clientId={ clientId } /> { showPlaceholder && ( <View> { innerBlocksProps.children } <GroupPlaceHolder name={ name } onSelect={ selectVariation } /> </View> ) } { layoutSupportEnabled && ! showPlaceholder && ( <TagName { ...innerBlocksProps } /> ) } { /* Ideally this is not needed but it's there for backward compatibility reason to keep this div for themes that might rely on its presence */ } { ! layoutSupportEnabled && ! showPlaceholder && ( <TagName { ...blockProps }> <div { ...innerBlocksProps } /> </TagName> ) } </> ); } export default GroupEdit;