UNPKG

@wordpress/block-editor

Version:
157 lines (145 loc) 4.75 kB
/** * WordPress dependencies */ import { useDispatch, useRegistry } from '@wordpress/data'; /** * Internal dependencies */ import { store as blockEditorStore } from '../../store'; import { useBlockEditContext } from '../block-edit'; /** * Checks if the given object is empty. * * @param {?Object} object The object to check. * * @return {boolean} Whether the object is empty. */ function isObjectEmpty( object ) { return ! object || Object.keys( object ).length === 0; } /** * Contains utils to update the block `bindings` metadata. * * @typedef {Object} WPBlockBindingsUtils * * @property {Function} updateBlockBindings Updates the value of the bindings connected to block attributes. * @property {Function} removeAllBlockBindings Removes the bindings property of the `metadata` attribute. */ /** * Retrieves the existing utils needed to update the block `bindings` metadata. * They can be used to create, modify, or remove connections from the existing block attributes. * * It contains the following utils: * - `updateBlockBindings`: Updates the value of the bindings connected to block attributes. It can be used to remove a specific binding by setting the value to `undefined`. * - `removeAllBlockBindings`: Removes the bindings property of the `metadata` attribute. * * @since 6.7.0 Introduced in WordPress core. * * @param {?string} clientId Optional block client ID. If not set, it will use the current block client ID from the context. * * @return {?WPBlockBindingsUtils} Object containing the block bindings utils. * * @example * ```js * import { useBlockBindingsUtils } from '@wordpress/block-editor' * const { updateBlockBindings, removeAllBlockBindings } = useBlockBindingsUtils(); * * // Update url and alt attributes. * updateBlockBindings( { * url: { * source: 'core/post-meta', * args: { * key: 'url_custom_field', * }, * }, * alt: { * source: 'core/post-meta', * args: { * key: 'text_custom_field', * }, * }, * } ); * * // Remove binding from url attribute. * updateBlockBindings( { url: undefined } ); * * // Remove bindings from all attributes. * removeAllBlockBindings(); * ``` */ export default function useBlockBindingsUtils( clientId ) { const { clientId: contextClientId } = useBlockEditContext(); const blockClientId = clientId || contextClientId; const { updateBlockAttributes } = useDispatch( blockEditorStore ); const { getBlockAttributes } = useRegistry().select( blockEditorStore ); /** * Updates the value of the bindings connected to block attributes. * It removes the binding when the new value is `undefined`. * * @param {Object} bindings Bindings including the attributes to update and the new object. * @param {string} bindings.source The source name to connect to. * @param {Object} [bindings.args] Object containing the arguments needed by the source. * * @example * ```js * import { useBlockBindingsUtils } from '@wordpress/block-editor' * * const { updateBlockBindings } = useBlockBindingsUtils(); * updateBlockBindings( { * url: { * source: 'core/post-meta', * args: { * key: 'url_custom_field', * }, * }, * alt: { * source: 'core/post-meta', * args: { * key: 'text_custom_field', * }, * } * } ); * ``` */ const updateBlockBindings = ( bindings ) => { const { metadata: { bindings: currentBindings, ...metadata } = {} } = getBlockAttributes( blockClientId ); const newBindings = { ...currentBindings }; Object.entries( bindings ).forEach( ( [ attribute, binding ] ) => { if ( ! binding && newBindings[ attribute ] ) { delete newBindings[ attribute ]; return; } newBindings[ attribute ] = binding; } ); const newMetadata = { ...metadata, bindings: newBindings, }; if ( isObjectEmpty( newMetadata.bindings ) ) { delete newMetadata.bindings; } updateBlockAttributes( blockClientId, { metadata: isObjectEmpty( newMetadata ) ? undefined : newMetadata, } ); }; /** * Removes the bindings property of the `metadata` attribute. * * @example * ```js * import { useBlockBindingsUtils } from '@wordpress/block-editor' * * const { removeAllBlockBindings } = useBlockBindingsUtils(); * removeAllBlockBindings(); * ``` */ const removeAllBlockBindings = () => { const { metadata: { bindings, ...metadata } = {} } = getBlockAttributes( blockClientId ); updateBlockAttributes( blockClientId, { metadata: isObjectEmpty( metadata ) ? undefined : metadata, } ); }; return { updateBlockBindings, removeAllBlockBindings }; }