Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions packages/block-editor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,48 @@ _Related_

- <https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/url-popover/README.md>

### useBlockBindingsUtils

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.

_Usage_

```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();
```

_Returns_

- `?WPBlockBindingsUtils`: Object containing the block bindings utils.

### useBlockCommands

Undocumented declaration.
Expand Down
4 changes: 1 addition & 3 deletions packages/block-editor/src/components/rich-text/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
removeFormat,
} from '@wordpress/rich-text';
import { Popover } from '@wordpress/components';
import { store as blocksStore } from '@wordpress/blocks';
import { getBlockBindingsSource } from '@wordpress/blocks';
import deprecated from '@wordpress/deprecated';
import { __, sprintf } from '@wordpress/i18n';

Expand All @@ -39,7 +39,6 @@ import FormatEdit from './format-edit';
import { getAllowedFormats } from './utils';
import { Content, valueToHTMLString } from './content';
import { withDeprecations } from './with-deprecations';
import { unlock } from '../../lock-unlock';
import { canBindBlock } from '../../hooks/use-bindings-attributes';
import BlockContext from '../block-context';

Expand Down Expand Up @@ -175,7 +174,6 @@ export function RichTextWrapper(
}

const relatedBinding = blockBindings[ identifier ];
const { getBlockBindingsSource } = unlock( select( blocksStore ) );
const blockBindingsSource = getBlockBindingsSource(
relatedBinding.source
);
Expand Down
10 changes: 5 additions & 5 deletions packages/block-editor/src/hooks/block-bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { privateApis as blocksPrivateApis } from '@wordpress/blocks';
import {
getBlockBindingsSource,
getBlockBindingsSources,
} from '@wordpress/blocks';
import {
__experimentalItemGroup as ItemGroup,
__experimentalItem as Item,
Expand Down Expand Up @@ -47,7 +50,6 @@ const useToolsPanelDropdownMenuProps = () => {
};

function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) {
const { getBlockBindingsSources } = unlock( blocksPrivateApis );
const registeredSources = getBlockBindingsSources();
const { updateBlockBindings } = useBlockBindingsUtils();
const currentKey = binding?.args?.key;
Expand Down Expand Up @@ -96,8 +98,7 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) {

function BlockBindingsAttribute( { attribute, binding, fieldsList } ) {
const { source: sourceName, args } = binding || {};
const sourceProps =
unlock( blocksPrivateApis ).getBlockBindingsSource( sourceName );
const sourceProps = getBlockBindingsSource( sourceName );
const isSourceInvalid = ! sourceProps;
return (
<VStack className="block-editor-bindings__item" spacing={ 0 }>
Expand Down Expand Up @@ -200,7 +201,6 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
if ( ! bindableAttributes || bindableAttributes.length === 0 ) {
return EMPTY_OBJECT;
}
const { getBlockBindingsSources } = unlock( blocksPrivateApis );
const registeredSources = getBlockBindingsSources();
Object.entries( registeredSources ).forEach(
( [ sourceName, { getFieldsList, usesContext } ] ) => {
Expand Down
2 changes: 0 additions & 2 deletions packages/block-editor/src/private-apis.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import { PrivatePublishDateTimePicker } from './components/publish-date-time-pic
import useSpacingSizes from './components/spacing-sizes-control/hooks/use-spacing-sizes';
import useBlockDisplayTitle from './components/block-title/use-block-display-title';
import TabbedSidebar from './components/tabbed-sidebar';
import { useBlockBindingsUtils } from './utils/block-bindings';

/**
* Private @wordpress/block-editor APIs.
Expand Down Expand Up @@ -92,6 +91,5 @@ lock( privateApis, {
useBlockDisplayTitle,
__unstableBlockStyleVariationOverridesWithConfig,
setBackgroundStyleDefaults,
useBlockBindingsUtils,
sectionRootClientIdKey,
} );
47 changes: 47 additions & 0 deletions packages/block-editor/src/utils/block-bindings.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,53 @@ 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.
*
* @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 function useBlockBindingsUtils() {
const { clientId } = useBlockEditContext();
const { updateBlockAttributes } = useDispatch( blockEditorStore );
Expand Down
1 change: 1 addition & 0 deletions packages/block-editor/src/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as transformStyles } from './transform-styles';
export { default as getPxFromCssUnit } from './get-px-from-css-unit';
export { useBlockBindingsUtils } from './block-bindings';
3 changes: 1 addition & 2 deletions packages/block-library/src/block/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
InnerBlocks,
} from '@wordpress/block-editor';
import { privateApis as patternsPrivateApis } from '@wordpress/patterns';
import { store as blocksStore } from '@wordpress/blocks';
import { getBlockBindingsSource } from '@wordpress/blocks';

/**
* Internal dependencies
Expand Down Expand Up @@ -196,7 +196,6 @@ function ReusableBlockEdit( {
( select ) => {
const { getBlocks, getSettings, getBlockEditingMode } =
select( blockEditorStore );
const { getBlockBindingsSource } = unlock( select( blocksStore ) );
// For editing link to the site editor if the theme and user permissions support it.
return {
innerBlocks: getBlocks( patternClientId ),
Expand Down
9 changes: 4 additions & 5 deletions packages/block-library/src/button/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import clsx from 'clsx';
import { NEW_TAB_TARGET, NOFOLLOW_REL } from './constants';
import { getUpdatedLinkAttributes } from './get-updated-link-attributes';
import removeAnchorTag from '../utils/remove-anchor-tag';
import { unlock } from '../lock-unlock';

/**
* WordPress dependencies
Expand Down Expand Up @@ -45,7 +44,7 @@ import {
createBlock,
cloneBlock,
getDefaultBlockName,
store as blocksStore,
getBlockBindingsSource,
} from '@wordpress/blocks';
import { useMergeRefs, useRefEffect } from '@wordpress/compose';
import { useSelect, useDispatch } from '@wordpress/data';
Expand Down Expand Up @@ -240,9 +239,9 @@ function ButtonEdit( props ) {
return {};
}

const blockBindingsSource = unlock(
select( blocksStore )
).getBlockBindingsSource( metadata?.bindings?.url?.source );
const blockBindingsSource = getBlockBindingsSource(
metadata?.bindings?.url?.source
);

return {
lockUrlControls:
Expand Down
9 changes: 4 additions & 5 deletions packages/block-library/src/image/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import clsx from 'clsx';
* WordPress dependencies
*/
import { isBlobURL, createBlobURL } from '@wordpress/blob';
import { store as blocksStore, createBlock } from '@wordpress/blocks';
import { createBlock, getBlockBindingsSource } from '@wordpress/blocks';
import { Placeholder } from '@wordpress/components';
import { useDispatch, useSelect } from '@wordpress/data';
import {
Expand All @@ -28,7 +28,6 @@ import { useResizeObserver } from '@wordpress/compose';
/**
* Internal dependencies
*/
import { unlock } from '../lock-unlock';
import { useUploadMediaFromBlobURL } from '../utils/hooks';
import Image from './image';
import { isValidFileType } from './utils';
Expand Down Expand Up @@ -372,9 +371,9 @@ export function ImageEdit( {
return {};
}

const blockBindingsSource = unlock(
select( blocksStore )
).getBlockBindingsSource( metadata?.bindings?.url?.source );
const blockBindingsSource = getBlockBindingsSource(
metadata?.bindings?.url?.source
);

return {
lockUrlControls:
Expand Down
3 changes: 1 addition & 2 deletions packages/block-library/src/image/image.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import { useEffect, useMemo, useState, useRef } from '@wordpress/element';
import { __, _x, sprintf, isRTL } from '@wordpress/i18n';
import { DOWN } from '@wordpress/keycodes';
import { getFilename } from '@wordpress/url';
import { switchToBlockType, store as blocksStore } from '@wordpress/blocks';
import { getBlockBindingsSource, switchToBlockType } from '@wordpress/blocks';
import { crop, overlayText, upload } from '@wordpress/icons';
import { store as noticesStore } from '@wordpress/notices';
import { store as coreStore } from '@wordpress/core-data';
Expand Down Expand Up @@ -476,7 +476,6 @@ export default function Image( {
if ( ! isSingleSelected ) {
return {};
}
const { getBlockBindingsSource } = unlock( select( blocksStore ) );
const {
url: urlBinding,
alt: altBinding,
Expand Down
66 changes: 66 additions & 0 deletions packages/blocks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,26 @@ _Returns_

- `string[]`: The attribute names that have the provided role.

### getBlockBindingsSource

Returns a registered block bindings source by its name.

_Parameters_

- _name_ `string`: Block bindings source name.

_Returns_

- `?Object`: Block bindings source.

### getBlockBindingsSources

Returns all registered block bindings sources.

_Returns_

- `Array`: Block bindings sources.

### getBlockContent

Given a block object, returns the Block's Inner HTML markup.
Expand Down Expand Up @@ -492,6 +512,36 @@ _Returns_

- `Array`: A list of blocks.

### registerBlockBindingsSource

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.

_Usage_

```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,
} );
```

_Parameters_

- _source_ `Object`: Properties of the source to be registered.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are all of the properties mandatory?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, they are not. I wrapped the optional ones with [] because I thought that was the way to do it. Should I clarify it in the description anyway?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I missed that nuance. I would welcome the update to the description of the parameters to make it easier to discover that some params are optional.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in this commit: a5792ef

- _source.name_ `string`: The unique and machine-readable name.
- _source.label_ `[string]`: Human-readable label. Optional when it is defined in the server.
- _source.usesContext_ `[Array]`: Optional array of context needed by the source only in the editor.
- _source.getValues_ `[Function]`: Optional function to get the values from the source.
- _source.setValues_ `[Function]`: Optional function to update multiple values connected to the source.
- _source.canUserEditValue_ `[Function]`: Optional function to determine if the user can edit the value.

### registerBlockCollection

Registers a new block collection to group blocks in the same namespace in the inserter.
Expand Down Expand Up @@ -793,6 +843,22 @@ _Returns_

- `Array`: Updated Block list.

### unregisterBlockBindingsSource

Unregisters a block bindings source by providing its name.

_Usage_

```js
import { unregisterBlockBindingsSource } from '@wordpress/blocks';

unregisterBlockBindingsSource( 'plugin/my-custom-source' );
```

_Parameters_

- _name_ `string`: The name of the block bindings source to unregister.

### unregisterBlockStyle

Unregisters a block style for the given block.
Expand Down
Loading