@wordpress/block-library
Version:
Block library for the WordPress editor.
158 lines (143 loc) • 4.36 kB
JavaScript
/**
* 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;