UNPKG

@wordpress/block-editor

Version:
123 lines (110 loc) 3.67 kB
/** * WordPress dependencies */ import { getBlockType, store as blocksStore } from '@wordpress/blocks'; import { PanelBody } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { DataForm } from '@wordpress/dataviews'; import { useContext, useMemo } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; /** * Internal dependencies */ import InspectorControls from '../components/inspector-controls'; import { useBlockEditingMode } from '../components/block-editing-mode'; import { store as blockEditorStore } from '../store'; import { unlock } from '../lock-unlock'; import BlockContext from '../components/block-context'; import { generateFieldsFromAttributes } from './generate-fields-from-attributes'; /** * Checks if a block has any attributes marked for auto-generated inspector controls. * * @param {Object} blockTypeAttributes - The block type's attributes object. * @return {boolean} True if any attribute has autoGenerateControl marker. */ function hasAutoGenerateControl( blockTypeAttributes ) { if ( ! blockTypeAttributes ) { return false; } return Object.values( blockTypeAttributes ).some( ( attr ) => attr?.autoGenerateControl ); } /** * Renders DataForm-based inspector controls for auto-registered PHP-only blocks. * * Fields are generated on-the-fly from attributes marked with `autoGenerateControl` * during PHP registration. * * @param {Object} props Component props. * @param {string} props.name Block name. * @param {string} props.clientId Block client ID. * @param {Function} props.setAttributes Function to update block attributes. */ function AutoRegisterControls( { name, clientId, setAttributes } ) { const blockEditingMode = useBlockEditingMode(); const blockContext = useContext( BlockContext ); const attributes = useSelect( ( select ) => { const _attributes = select( blockEditorStore ).getBlockAttributes( clientId ); if ( ! _attributes?.metadata?.bindings ) { return _attributes; } const { getBlockBindingsSource } = unlock( select( blocksStore ) ); return Object.entries( _attributes.metadata.bindings ).reduce( ( acc, [ attribute, binding ] ) => { const source = getBlockBindingsSource( binding.source ); if ( ! source ) { return acc; } const values = source.getValues( { select, context: blockContext, bindings: { [ attribute ]: binding }, } ); return { ...acc, ...values }; }, _attributes ); }, [ blockContext, clientId ] ); const blockType = getBlockType( name ); // Generate fields from user-defined attributes marked by PHP. // The autoGenerateControl marker excludes block support attributes // (which have their own UI) and internal state (role: 'local'). // Memoized since blockType.attributes don't change after registration. const { fields, form } = useMemo( () => { if ( ! blockType?.attributes ) { return { fields: [], form: { fields: [] } }; } return generateFieldsFromAttributes( blockType.attributes ); }, [ blockType?.attributes ] ); if ( blockEditingMode !== 'default' ) { return null; } if ( ! fields || fields.length === 0 ) { return null; } return ( <InspectorControls> <PanelBody title={ __( 'Settings' ) }> <DataForm data={ attributes } fields={ fields } form={ form } onChange={ setAttributes } /> </PanelBody> </InspectorControls> ); } export default { edit: AutoRegisterControls, attributeKeys: [], hasSupport( name ) { const blockType = getBlockType( name ); return hasAutoGenerateControl( blockType?.attributes ); }, };