@wordpress/blocks
Version:
Block API for WordPress.
891 lines (839 loc) • 32 kB
JavaScript
/**
* WordPress dependencies
*/
import { select, dispatch } from '@wordpress/data';
import { _x } from '@wordpress/i18n';
import warning from '@wordpress/warning';
/**
* Internal dependencies
*/
const i18nBlockSchema = {
title: "block title",
description: "block description",
keywords: ["block keyword"],
styles: [{
label: "block style label"
}],
variations: [{
title: "block variation title",
description: "block variation description",
keywords: ["block variation keyword"]
}]
};
import { store as blocksStore } from '../store';
import { unlock } from '../lock-unlock';
/**
* An icon type definition. One of a Dashicon slug, an element,
* or a component.
*
* @typedef {(string|Element|Component)} WPIcon
*
* @see https://developer.wordpress.org/resource/dashicons/
*/
/**
* Render behavior of a block type icon; one of a Dashicon slug, an element,
* or a component.
*
* @typedef {WPIcon} WPBlockTypeIconRender
*/
/**
* An object describing a normalized block type icon.
*
* @typedef {Object} WPBlockTypeIconDescriptor
*
* @property {WPBlockTypeIconRender} src Render behavior of the icon,
* one of a Dashicon slug, an
* element, or a component.
* @property {string} background Optimal background hex string
* color when displaying icon.
* @property {string} foreground Optimal foreground hex string
* color when displaying icon.
* @property {string} shadowColor Optimal shadow hex string
* color when displaying icon.
*/
/**
* Value to use to render the icon for a block type in an editor interface,
* either a Dashicon slug, an element, a component, or an object describing
* the icon.
*
* @typedef {(WPBlockTypeIconDescriptor|WPBlockTypeIconRender)} WPBlockTypeIcon
*/
/**
* Named block variation scopes.
*
* @typedef {'block'|'inserter'|'transform'} WPBlockVariationScope
*/
/**
* An object describing a variation defined for the block type.
*
* @typedef {Object} WPBlockVariation
*
* @property {string} name The unique and machine-readable name.
* @property {string} title A human-readable variation title.
* @property {string} [description] A detailed variation description.
* @property {string} [category] Block type category classification,
* used in search interfaces to arrange
* block types by category.
* @property {WPIcon} [icon] An icon helping to visualize the variation.
* @property {boolean} [isDefault] Indicates whether the current variation is
* the default one. Defaults to `false`.
* @property {Object} [attributes] Values which override block attributes.
* @property {Array[]} [innerBlocks] Initial configuration of nested blocks.
* @property {Object} [example] Example provides structured data for
* the block preview. You can set to
* `undefined` to disable the preview shown
* for the block type.
* @property {WPBlockVariationScope[]} [scope] The list of scopes where the variation
* is applicable. When not provided, it
* assumes all available scopes.
* @property {string[]} [keywords] An array of terms (which can be translated)
* that help users discover the variation
* while searching.
* @property {Function|string[]} [isActive] This can be a function or an array of block attributes.
* Function that accepts a block's attributes and the
* variation's attributes and determines if a variation is active.
* This function doesn't try to find a match dynamically based
* on all block's attributes, as in many cases some attributes are irrelevant.
* An example would be for `embed` block where we only care
* about `providerNameSlug` attribute's value.
* We can also use a `string[]` to tell which attributes
* should be compared as a shorthand. Each attributes will
* be matched and the variation will be active if all of them are matching.
*/
/**
* Defined behavior of a block type.
*
* @typedef {Object} WPBlockType
*
* @property {string} name Block type's namespaced name.
* @property {string} title Human-readable block type label.
* @property {string} [description] A detailed block type description.
* @property {string} [category] Block type category classification,
* used in search interfaces to arrange
* block types by category.
* @property {WPBlockTypeIcon} [icon] Block type icon.
* @property {string[]} [keywords] Additional keywords to produce block
* type as result in search interfaces.
* @property {Object} [attributes] Block type attributes.
* @property {Component} [save] Optional component describing
* serialized markup structure of a
* block type.
* @property {Component} edit Component rendering an element to
* manipulate the attributes of a block
* in the context of an editor.
* @property {WPBlockVariation[]} [variations] The list of block variations.
* @property {Object} [example] Example provides structured data for
* the block preview. When not defined
* then no preview is shown.
*/
/**
* An object describing a Block Bindings source.
*
* @typedef {Object} WPBlockBindingsSource
*
* @property {string} name The unique and machine-readable name.
* @property {string} [label] Human-readable label. Optional when it is defined in the server.
* @property {Array} [usesContext] Optional array of context needed by the source only in the editor.
* @property {Function} [getValues] Optional function to get the values from the source.
* @property {Function} [setValues] Optional function to update multiple values connected to the source.
* @property {Function} [canUserEditValue] Optional function to determine if the user can edit the value.
*/
function isObject(object) {
return object !== null && typeof object === 'object';
}
/**
* Sets the server side block definition of blocks.
*
* Ignored from documentation due to being marked as unstable.
*
* @ignore
*
* @param {Object} definitions Server-side block definitions
*/
// eslint-disable-next-line camelcase
export function unstable__bootstrapServerSideBlockDefinitions(definitions) {
const {
addBootstrappedBlockType
} = unlock(dispatch(blocksStore));
for (const [name, blockType] of Object.entries(definitions)) {
addBootstrappedBlockType(name, blockType);
}
}
/**
* Gets block settings from metadata loaded from `block.json` file
*
* @param {Object} metadata Block metadata loaded from `block.json`.
* @param {string} metadata.textdomain Textdomain to use with translations.
*
* @return {Object} Block settings.
*/
function getBlockSettingsFromMetadata({
textdomain,
...metadata
}) {
const allowedFields = ['apiVersion', 'title', 'category', 'parent', 'ancestor', 'icon', 'description', 'keywords', 'attributes', 'providesContext', 'usesContext', 'selectors', 'supports', 'styles', 'example', 'variations', 'blockHooks', 'allowedBlocks'];
const settings = Object.fromEntries(Object.entries(metadata).filter(([key]) => allowedFields.includes(key)));
if (textdomain) {
Object.keys(i18nBlockSchema).forEach(key => {
if (!settings[key]) {
return;
}
settings[key] = translateBlockSettingUsingI18nSchema(i18nBlockSchema[key], settings[key], textdomain);
});
}
return settings;
}
/**
* Registers a new block provided a unique name and an object defining its
* behavior. Once registered, the block is made available as an option to any
* editor interface where blocks are implemented.
*
* For more in-depth information on registering a custom block see the
* [Create a block tutorial](https://developer.wordpress.org/block-editor/getting-started/create-block/).
*
* @param {string|Object} blockNameOrMetadata Block type name or its metadata.
* @param {Object} settings Block settings.
*
* @example
* ```js
* import { __ } from '@wordpress/i18n';
* import { registerBlockType } from '@wordpress/blocks'
*
* registerBlockType( 'namespace/block-name', {
* title: __( 'My First Block' ),
* edit: () => <div>{ __( 'Hello from the editor!' ) }</div>,
* save: () => <div>Hello from the saved content!</div>,
* } );
* ```
*
* @return {WPBlockType | undefined} The block, if it has been successfully registered;
* otherwise `undefined`.
*/
export function registerBlockType(blockNameOrMetadata, settings) {
const name = isObject(blockNameOrMetadata) ? blockNameOrMetadata.name : blockNameOrMetadata;
if (typeof name !== 'string') {
globalThis.SCRIPT_DEBUG === true ? warning('Block names must be strings.') : void 0;
return;
}
if (!/^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/.test(name)) {
globalThis.SCRIPT_DEBUG === true ? warning('Block names must contain a namespace prefix, include only lowercase alphanumeric characters or dashes, and start with a letter. Example: my-plugin/my-custom-block') : void 0;
return;
}
if (select(blocksStore).getBlockType(name)) {
globalThis.SCRIPT_DEBUG === true ? warning('Block "' + name + '" is already registered.') : void 0;
return;
}
const {
addBootstrappedBlockType,
addUnprocessedBlockType
} = unlock(dispatch(blocksStore));
if (isObject(blockNameOrMetadata)) {
const metadata = getBlockSettingsFromMetadata(blockNameOrMetadata);
addBootstrappedBlockType(name, metadata);
}
addUnprocessedBlockType(name, settings);
return select(blocksStore).getBlockType(name);
}
/**
* Translates block settings provided with metadata using the i18n schema.
*
* @param {string|string[]|Object[]} i18nSchema I18n schema for the block setting.
* @param {string|string[]|Object[]} settingValue Value for the block setting.
* @param {string} textdomain Textdomain to use with translations.
*
* @return {string|string[]|Object[]} Translated setting.
*/
function translateBlockSettingUsingI18nSchema(i18nSchema, settingValue, textdomain) {
if (typeof i18nSchema === 'string' && typeof settingValue === 'string') {
// eslint-disable-next-line @wordpress/i18n-no-variables, @wordpress/i18n-text-domain
return _x(settingValue, i18nSchema, textdomain);
}
if (Array.isArray(i18nSchema) && i18nSchema.length && Array.isArray(settingValue)) {
return settingValue.map(value => translateBlockSettingUsingI18nSchema(i18nSchema[0], value, textdomain));
}
if (isObject(i18nSchema) && Object.entries(i18nSchema).length && isObject(settingValue)) {
return Object.keys(settingValue).reduce((accumulator, key) => {
if (!i18nSchema[key]) {
accumulator[key] = settingValue[key];
return accumulator;
}
accumulator[key] = translateBlockSettingUsingI18nSchema(i18nSchema[key], settingValue[key], textdomain);
return accumulator;
}, {});
}
return settingValue;
}
/**
* Registers a new block collection to group blocks in the same namespace in the inserter.
*
* @param {string} namespace The namespace to group blocks by in the inserter; corresponds to the block namespace.
* @param {Object} settings The block collection settings.
* @param {string} settings.title The title to display in the block inserter.
* @param {Object} [settings.icon] The icon to display in the block inserter.
*
* @example
* ```js
* import { __ } from '@wordpress/i18n';
* import { registerBlockCollection, registerBlockType } from '@wordpress/blocks';
*
* // Register the collection.
* registerBlockCollection( 'my-collection', {
* title: __( 'Custom Collection' ),
* } );
*
* // Register a block in the same namespace to add it to the collection.
* registerBlockType( 'my-collection/block-name', {
* title: __( 'My First Block' ),
* edit: () => <div>{ __( 'Hello from the editor!' ) }</div>,
* save: () => <div>'Hello from the saved content!</div>,
* } );
* ```
*/
export function registerBlockCollection(namespace, {
title,
icon
}) {
dispatch(blocksStore).addBlockCollection(namespace, title, icon);
}
/**
* Unregisters a block collection
*
* @param {string} namespace The namespace to group blocks by in the inserter; corresponds to the block namespace
*
* @example
* ```js
* import { unregisterBlockCollection } from '@wordpress/blocks';
*
* unregisterBlockCollection( 'my-collection' );
* ```
*/
export function unregisterBlockCollection(namespace) {
dispatch(blocksStore).removeBlockCollection(namespace);
}
/**
* Unregisters a block.
*
* @param {string} name Block name.
*
* @example
* ```js
* import { __ } from '@wordpress/i18n';
* import { unregisterBlockType } from '@wordpress/blocks';
*
* const ExampleComponent = () => {
* return (
* <Button
* onClick={ () =>
* unregisterBlockType( 'my-collection/block-name' )
* }
* >
* { __( 'Unregister my custom block.' ) }
* </Button>
* );
* };
* ```
*
* @return {WPBlockType | undefined} The previous block value, if it has been successfully
* unregistered; otherwise `undefined`.
*/
export function unregisterBlockType(name) {
const oldBlock = select(blocksStore).getBlockType(name);
if (!oldBlock) {
globalThis.SCRIPT_DEBUG === true ? warning('Block "' + name + '" is not registered.') : void 0;
return;
}
dispatch(blocksStore).removeBlockTypes(name);
return oldBlock;
}
/**
* Assigns name of block for handling non-block content.
*
* @param {string} blockName Block name.
*/
export function setFreeformContentHandlerName(blockName) {
dispatch(blocksStore).setFreeformFallbackBlockName(blockName);
}
/**
* Retrieves name of block handling non-block content, or undefined if no
* handler has been defined.
*
* @return {?string} Block name.
*/
export function getFreeformContentHandlerName() {
return select(blocksStore).getFreeformFallbackBlockName();
}
/**
* Retrieves name of block used for handling grouping interactions.
*
* @return {?string} Block name.
*/
export function getGroupingBlockName() {
return select(blocksStore).getGroupingBlockName();
}
/**
* Assigns name of block handling unregistered block types.
*
* @param {string} blockName Block name.
*/
export function setUnregisteredTypeHandlerName(blockName) {
dispatch(blocksStore).setUnregisteredFallbackBlockName(blockName);
}
/**
* Retrieves name of block handling unregistered block types, or undefined if no
* handler has been defined.
*
* @return {?string} Block name.
*/
export function getUnregisteredTypeHandlerName() {
return select(blocksStore).getUnregisteredFallbackBlockName();
}
/**
* Assigns the default block name.
*
* @param {string} name Block name.
*
* @example
* ```js
* import { setDefaultBlockName } from '@wordpress/blocks';
*
* const ExampleComponent = () => {
*
* return (
* <Button onClick={ () => setDefaultBlockName( 'core/heading' ) }>
* { __( 'Set the default block to Heading' ) }
* </Button>
* );
* };
* ```
*/
export function setDefaultBlockName(name) {
dispatch(blocksStore).setDefaultBlockName(name);
}
/**
* Assigns name of block for handling block grouping interactions.
*
* This function lets you select a different block to group other blocks in instead of the
* default `core/group` block. This function must be used in a component or when the DOM is fully
* loaded. See https://developer.wordpress.org/block-editor/reference-guides/packages/packages-dom-ready/
*
* @param {string} name Block name.
*
* @example
* ```js
* import { setGroupingBlockName } from '@wordpress/blocks';
*
* const ExampleComponent = () => {
*
* return (
* <Button onClick={ () => setGroupingBlockName( 'core/columns' ) }>
* { __( 'Wrap in columns' ) }
* </Button>
* );
* };
* ```
*/
export function setGroupingBlockName(name) {
dispatch(blocksStore).setGroupingBlockName(name);
}
/**
* Retrieves the default block name.
*
* @return {?string} Block name.
*/
export function getDefaultBlockName() {
return select(blocksStore).getDefaultBlockName();
}
/**
* Returns a registered block type.
*
* @param {string} name Block name.
*
* @return {?Object} Block type.
*/
export function getBlockType(name) {
return select(blocksStore)?.getBlockType(name);
}
/**
* Returns all registered blocks.
*
* @return {Array} Block settings.
*/
export function getBlockTypes() {
return select(blocksStore).getBlockTypes();
}
/**
* Returns the block support value for a feature, if defined.
*
* @param {(string|Object)} nameOrType Block name or type object
* @param {string} feature Feature to retrieve
* @param {*} defaultSupports Default value to return if not
* explicitly defined
*
* @return {?*} Block support value
*/
export function getBlockSupport(nameOrType, feature, defaultSupports) {
return select(blocksStore).getBlockSupport(nameOrType, feature, defaultSupports);
}
/**
* Returns true if the block defines support for a feature, or false otherwise.
*
* @param {(string|Object)} nameOrType Block name or type object.
* @param {string} feature Feature to test.
* @param {boolean} defaultSupports Whether feature is supported by
* default if not explicitly defined.
*
* @return {boolean} Whether block supports feature.
*/
export function hasBlockSupport(nameOrType, feature, defaultSupports) {
return select(blocksStore).hasBlockSupport(nameOrType, feature, defaultSupports);
}
/**
* Determines whether or not the given block is a reusable block. This is a
* special block type that is used to point to a global block stored via the
* API.
*
* @param {Object} blockOrType Block or Block Type to test.
*
* @return {boolean} Whether the given block is a reusable block.
*/
export function isReusableBlock(blockOrType) {
return blockOrType?.name === 'core/block';
}
/**
* Determines whether or not the given block is a template part. This is a
* special block type that allows composing a page template out of reusable
* design elements.
*
* @param {Object} blockOrType Block or Block Type to test.
*
* @return {boolean} Whether the given block is a template part.
*/
export function isTemplatePart(blockOrType) {
return blockOrType?.name === 'core/template-part';
}
/**
* Returns an array with the child blocks of a given block.
*
* @param {string} blockName Name of block (example: “latest-posts”).
*
* @return {Array} Array of child block names.
*/
export const getChildBlockNames = blockName => {
return select(blocksStore).getChildBlockNames(blockName);
};
/**
* Returns a boolean indicating if a block has child blocks or not.
*
* @param {string} blockName Name of block (example: “latest-posts”).
*
* @return {boolean} True if a block contains child blocks and false otherwise.
*/
export const hasChildBlocks = blockName => {
return select(blocksStore).hasChildBlocks(blockName);
};
/**
* Returns a boolean indicating if a block has at least one child block with inserter support.
*
* @param {string} blockName Block type name.
*
* @return {boolean} True if a block contains at least one child blocks with inserter support
* and false otherwise.
*/
export const hasChildBlocksWithInserterSupport = blockName => {
return select(blocksStore).hasChildBlocksWithInserterSupport(blockName);
};
/**
* Registers a new block style for the given block types.
*
* For more information on connecting the styles with CSS
* [the official documentation](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-styles/#styles).
*
* @param {string|Array} blockNames Name of blocks e.g. “core/latest-posts” or `["core/group", "core/columns"]`.
* @param {Object} styleVariation Object containing `name` which is the class name applied to the block and `label` which identifies the variation to the user.
*
* @example
* ```js
* import { __ } from '@wordpress/i18n';
* import { registerBlockStyle } from '@wordpress/blocks';
* import { Button } from '@wordpress/components';
*
*
* const ExampleComponent = () => {
* return (
* <Button
* onClick={ () => {
* registerBlockStyle( 'core/quote', {
* name: 'fancy-quote',
* label: __( 'Fancy Quote' ),
* } );
* } }
* >
* { __( 'Add a new block style for core/quote' ) }
* </Button>
* );
* };
* ```
*/
export const registerBlockStyle = (blockNames, styleVariation) => {
dispatch(blocksStore).addBlockStyles(blockNames, styleVariation);
};
/**
* Unregisters a block style for the given block.
*
* @param {string} blockName Name of block (example: “core/latest-posts”).
* @param {string} styleVariationName Name of class applied to the block.
*
* @example
* ```js
* import { __ } from '@wordpress/i18n';
* import { unregisterBlockStyle } from '@wordpress/blocks';
* import { Button } from '@wordpress/components';
*
* const ExampleComponent = () => {
* return (
* <Button
* onClick={ () => {
* unregisterBlockStyle( 'core/quote', 'plain' );
* } }
* >
* { __( 'Remove the "Plain" block style for core/quote' ) }
* </Button>
* );
* };
* ```
*/
export const unregisterBlockStyle = (blockName, styleVariationName) => {
dispatch(blocksStore).removeBlockStyles(blockName, styleVariationName);
};
/**
* Returns an array with the variations of a given block type.
* Ignored from documentation as the recommended usage is via useSelect from @wordpress/data.
*
* @ignore
*
* @param {string} blockName Name of block (example: “core/columns”).
* @param {WPBlockVariationScope} [scope] Block variation scope name.
*
* @return {(WPBlockVariation[]|void)} Block variations.
*/
export const getBlockVariations = (blockName, scope) => {
return select(blocksStore).getBlockVariations(blockName, scope);
};
/**
* Registers a new block variation for the given block type.
*
* For more information on block variations see
* [the official documentation ](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-variations/).
*
* @param {string} blockName Name of the block (example: “core/columns”).
* @param {WPBlockVariation} variation Object describing a block variation.
*
* @example
* ```js
* import { __ } from '@wordpress/i18n';
* import { registerBlockVariation } from '@wordpress/blocks';
* import { Button } from '@wordpress/components';
*
* const ExampleComponent = () => {
* return (
* <Button
* onClick={ () => {
* registerBlockVariation( 'core/embed', {
* name: 'custom',
* title: __( 'My Custom Embed' ),
* attributes: { providerNameSlug: 'custom' },
* } );
* } }
* >
* __( 'Add a custom variation for core/embed' ) }
* </Button>
* );
* };
* ```
*/
export const registerBlockVariation = (blockName, variation) => {
if (typeof variation.name !== 'string') {
globalThis.SCRIPT_DEBUG === true ? warning('Variation names must be unique strings.') : void 0;
}
dispatch(blocksStore).addBlockVariations(blockName, variation);
};
/**
* Unregisters a block variation defined for the given block type.
*
* @param {string} blockName Name of the block (example: “core/columns”).
* @param {string} variationName Name of the variation defined for the block.
*
* @example
* ```js
* import { __ } from '@wordpress/i18n';
* import { unregisterBlockVariation } from '@wordpress/blocks';
* import { Button } from '@wordpress/components';
*
* const ExampleComponent = () => {
* return (
* <Button
* onClick={ () => {
* unregisterBlockVariation( 'core/embed', 'youtube' );
* } }
* >
* { __( 'Remove the YouTube variation from core/embed' ) }
* </Button>
* );
* };
* ```
*/
export const unregisterBlockVariation = (blockName, variationName) => {
dispatch(blocksStore).removeBlockVariations(blockName, variationName);
};
/**
* Registers a new block bindings source with an object defining its
* behavior. Once registered, the source is available to be connected
* to the supported block attributes.
*
* @since 6.7.0 Introduced in WordPress core.
*
* @param {WPBlockBindingsSource} source Object describing a block bindings source.
*
* @example
* ```js
* import { _x } from '@wordpress/i18n';
* import { registerBlockBindingsSource } from '@wordpress/blocks'
*
* registerBlockBindingsSource( {
* name: 'plugin/my-custom-source',
* label: _x( 'My Custom Source', 'block bindings source' ),
* usesContext: [ 'postType' ],
* getValues: getSourceValues,
* setValues: updateMyCustomValuesInBatch,
* canUserEditValue: () => true,
* } );
* ```
*/
export const registerBlockBindingsSource = source => {
const {
name,
label,
usesContext,
getValues,
setValues,
canUserEditValue,
getFieldsList
} = source;
const existingSource = unlock(select(blocksStore)).getBlockBindingsSource(name);
/*
* Check if the source has been already registered on the client.
* If any property expected to be "client-only" is defined, return a warning.
*/
const serverProps = ['label', 'usesContext'];
for (const prop in existingSource) {
if (!serverProps.includes(prop) && existingSource[prop]) {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source "' + name + '" is already registered.') : void 0;
return;
}
}
// Check the `name` property is correct.
if (!name) {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source must contain a name.') : void 0;
return;
}
if (typeof name !== 'string') {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source name must be a string.') : void 0;
return;
}
if (/[A-Z]+/.test(name)) {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source name must not contain uppercase characters.') : void 0;
return;
}
if (!/^[a-z0-9/-]+$/.test(name)) {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source name must contain only valid characters: lowercase characters, hyphens, or digits. Example: my-plugin/my-custom-source.') : void 0;
return;
}
if (!/^[a-z0-9-]+\/[a-z0-9-]+$/.test(name)) {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source name must contain a namespace and valid characters. Example: my-plugin/my-custom-source.') : void 0;
return;
}
// Check the `label` property is correct.
if (!label && !existingSource?.label) {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source must contain a label.') : void 0;
return;
}
if (label && typeof label !== 'string') {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source label must be a string.') : void 0;
return;
}
if (label && existingSource?.label && label !== existingSource?.label) {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings "' + name + '" source label was overridden.') : void 0;
}
// Check the `usesContext` property is correct.
if (usesContext && !Array.isArray(usesContext)) {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source usesContext must be an array.') : void 0;
return;
}
// Check the `getValues` property is correct.
if (getValues && typeof getValues !== 'function') {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source getValues must be a function.') : void 0;
return;
}
// Check the `setValues` property is correct.
if (setValues && typeof setValues !== 'function') {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source setValues must be a function.') : void 0;
return;
}
// Check the `canUserEditValue` property is correct.
if (canUserEditValue && typeof canUserEditValue !== 'function') {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source canUserEditValue must be a function.') : void 0;
return;
}
// Check the `getFieldsList` property is correct.
if (getFieldsList && typeof getFieldsList !== 'function') {
// eslint-disable-next-line no-console
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source getFieldsList must be a function.') : void 0;
return;
}
return unlock(dispatch(blocksStore)).addBlockBindingsSource(source);
};
/**
* Unregisters a block bindings source by providing its name.
*
* @since 6.7.0 Introduced in WordPress core.
*
* @param {string} name The name of the block bindings source to unregister.
*
* @example
* ```js
* import { unregisterBlockBindingsSource } from '@wordpress/blocks';
*
* unregisterBlockBindingsSource( 'plugin/my-custom-source' );
* ```
*/
export function unregisterBlockBindingsSource(name) {
const oldSource = getBlockBindingsSource(name);
if (!oldSource) {
globalThis.SCRIPT_DEBUG === true ? warning('Block bindings source "' + name + '" is not registered.') : void 0;
return;
}
unlock(dispatch(blocksStore)).removeBlockBindingsSource(name);
}
/**
* Returns a registered block bindings source by its name.
*
* @since 6.7.0 Introduced in WordPress core.
*
* @param {string} name Block bindings source name.
*
* @return {?Object} Block bindings source.
*/
export function getBlockBindingsSource(name) {
return unlock(select(blocksStore)).getBlockBindingsSource(name);
}
/**
* Returns all registered block bindings sources.
*
* @since 6.7.0 Introduced in WordPress core.
*
* @return {Array} Block bindings sources.
*/
export function getBlockBindingsSources() {
return unlock(select(blocksStore)).getAllBlockBindingsSources();
}
//# sourceMappingURL=registration.js.map