Skip to content

Commit 4730e12

Browse files
SantosGuillamotyouknowriadartemiomoralescbravobernalgziolo
authored
Block Bindings: Improve the way block bindings sources are registered (#63117)
* Move bindings registration to editor provider * Remove old bindings import * Remove sources from editor provider * Create registerBlockBindingsSource * Export function as private * Create `registerCoreBlockBindingsSources` function * Register core sources in edit-post and edit-site * Don't reuse existing source * Add comment explaining function * Change the object in registration * Add a few checks more * Add more registration functions * Add private action to remove binding source * Add unit tests * Export all functions as private Co-authored-by: SantosGuillamot <santosguillamot@git.wordpress.org> Co-authored-by: youknowriad <youknowriad@git.wordpress.org> Co-authored-by: artemiomorales <artemiosans@git.wordpress.org> Co-authored-by: cbravobernal <cbravobernal@git.wordpress.org> Co-authored-by: gziolo <gziolo@git.wordpress.org>
1 parent e64a666 commit 4730e12

File tree

12 files changed

+475
-34
lines changed

12 files changed

+475
-34
lines changed

packages/blocks/README.md

+4
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,10 @@ _Returns_
462462

463463
- `Array|string`: A list of blocks or a string, depending on `handlerMode`.
464464

465+
### privateApis
466+
467+
Undocumented declaration.
468+
465469
### rawHandler
466470

467471
Converts an HTML string to known blocks.

packages/blocks/src/api/index.js

+19
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
/**
2+
* Internal dependencies
3+
*/
4+
import { lock } from '../lock-unlock';
5+
import {
6+
registerBlockBindingsSource,
7+
unregisterBlockBindingsSource,
8+
getBlockBindingsSource,
9+
getBlockBindingsSources,
10+
} from './registration';
11+
112
// The blocktype is the most important concept within the block API. It defines
213
// all aspects of the block configuration and its interfaces, including `edit`
314
// and `save`. The transforms specification allows converting one blocktype to
@@ -164,3 +175,11 @@ export {
164175
__EXPERIMENTAL_ELEMENTS,
165176
__EXPERIMENTAL_PATHS_WITH_OVERRIDE,
166177
} from './constants';
178+
179+
export const privateApis = {};
180+
lock( privateApis, {
181+
registerBlockBindingsSource,
182+
unregisterBlockBindingsSource,
183+
getBlockBindingsSource,
184+
getBlockBindingsSources,
185+
} );

packages/blocks/src/api/registration.js

+175
Original file line numberDiff line numberDiff line change
@@ -758,3 +758,178 @@ export const registerBlockVariation = ( blockName, variation ) => {
758758
export const unregisterBlockVariation = ( blockName, variationName ) => {
759759
dispatch( blocksStore ).removeBlockVariations( blockName, variationName );
760760
};
761+
762+
/**
763+
* Registers a new block bindings source with an object defining its
764+
* behavior. Once registered, the source is available to be connected
765+
* to the supported block attributes.
766+
*
767+
* @param {Object} source Properties of the source to be registered.
768+
* @param {string} source.name The unique and machine-readable name.
769+
* @param {string} source.label Human-readable label.
770+
* @param {Function} [source.getValue] Function to get the value of the source.
771+
* @param {Function} [source.setValue] Function to update the value of the source.
772+
* @param {Function} [source.setValues] Function to update multiple values connected to the source.
773+
* @param {Function} [source.getPlaceholder] Function to get the placeholder when the value is undefined.
774+
* @param {Function} [source.canUserEditValue] Function to determine if the user can edit the value.
775+
*
776+
* @example
777+
* ```js
778+
* import { _x } from '@wordpress/i18n';
779+
* import { registerBlockBindingsSource } from '@wordpress/blocks'
780+
*
781+
* registerBlockBindingsSource( {
782+
* name: 'plugin/my-custom-source',
783+
* label: _x( 'My Custom Source', 'block bindings source' ),
784+
* getValue: () => 'Value to place in the block attribute',
785+
* setValue: () => updateMyCustomValue(),
786+
* setValues: () => updateMyCustomValuesInBatch(),
787+
* getPlaceholder: () => 'Placeholder text when the value is undefined',
788+
* canUserEditValue: () => true,
789+
* } );
790+
* ```
791+
*/
792+
export const registerBlockBindingsSource = ( source ) => {
793+
const {
794+
name,
795+
label,
796+
getValue,
797+
setValue,
798+
setValues,
799+
getPlaceholder,
800+
canUserEditValue,
801+
} = source;
802+
803+
// Check if the source is already registered.
804+
const existingSource = unlock(
805+
select( blocksStore )
806+
).getBlockBindingsSource( name );
807+
if ( existingSource ) {
808+
console.error(
809+
'Block bindings source "' + name + '" is already registered.'
810+
);
811+
return;
812+
}
813+
814+
// Check the `name` property is correct.
815+
if ( ! name ) {
816+
console.error( 'Block bindings source must contain a name.' );
817+
return;
818+
}
819+
820+
if ( typeof name !== 'string' ) {
821+
console.error( 'Block bindings source name must be a string.' );
822+
return;
823+
}
824+
825+
if ( /[A-Z]+/.test( name ) ) {
826+
console.error(
827+
'Block bindings source name must not contain uppercase characters.'
828+
);
829+
return;
830+
}
831+
832+
if ( ! /^[a-z0-9/-]+$/.test( name ) ) {
833+
console.error(
834+
'Block bindings source name must contain only valid characters: lowercase characters, hyphens, or digits. Example: my-plugin/my-custom-source.'
835+
);
836+
return;
837+
}
838+
839+
if ( ! /^[a-z0-9-]+\/[a-z0-9-]+$/.test( name ) ) {
840+
console.error(
841+
'Block bindings source name must contain a namespace and valid characters. Example: my-plugin/my-custom-source.'
842+
);
843+
return;
844+
}
845+
846+
// Check the `label` property is correct.
847+
if ( ! label ) {
848+
console.error( 'Block bindings source must contain a label.' );
849+
return;
850+
}
851+
852+
if ( typeof label !== 'string' ) {
853+
console.error( 'Block bindings source label must be a string.' );
854+
return;
855+
}
856+
857+
// Check the `getValue` property is correct.
858+
if ( getValue && typeof getValue !== 'function' ) {
859+
console.error( 'Block bindings source getValue must be a function.' );
860+
return;
861+
}
862+
863+
// Check the `setValue` property is correct.
864+
if ( setValue && typeof setValue !== 'function' ) {
865+
console.error( 'Block bindings source setValue must be a function.' );
866+
return;
867+
}
868+
869+
// Check the `setValues` property is correct.
870+
if ( setValues && typeof setValues !== 'function' ) {
871+
console.error( 'Block bindings source setValues must be a function.' );
872+
return;
873+
}
874+
875+
// Check the `getPlaceholder` property is correct.
876+
if ( getPlaceholder && typeof getPlaceholder !== 'function' ) {
877+
console.error(
878+
'Block bindings source getPlaceholder must be a function.'
879+
);
880+
return;
881+
}
882+
883+
// Check the `getPlaceholder` property is correct.
884+
if ( canUserEditValue && typeof canUserEditValue !== 'function' ) {
885+
console.error(
886+
'Block bindings source canUserEditValue must be a function.'
887+
);
888+
return;
889+
}
890+
891+
return unlock( dispatch( blocksStore ) ).addBlockBindingsSource( source );
892+
};
893+
894+
/**
895+
* Unregisters a block bindings source
896+
*
897+
* @param {string} name The name of the block bindings source to unregister.
898+
*
899+
* @example
900+
* ```js
901+
* import { unregisterBlockBindingsSource } from '@wordpress/blocks';
902+
*
903+
* unregisterBlockBindingsSource( 'plugin/my-custom-source' );
904+
* ```
905+
*/
906+
export function unregisterBlockBindingsSource( name ) {
907+
const oldSource = getBlockBindingsSource( name );
908+
if ( ! oldSource ) {
909+
console.error(
910+
'Block bindings source "' + name + '" is not registered.'
911+
);
912+
return;
913+
}
914+
unlock( dispatch( blocksStore ) ).removeBlockBindingsSource( name );
915+
}
916+
917+
/**
918+
* Returns a registered block bindings source.
919+
*
920+
* @param {string} name Block bindings source name.
921+
*
922+
* @return {?Object} Block bindings source.
923+
*/
924+
export function getBlockBindingsSource( name ) {
925+
return unlock( select( blocksStore ) ).getBlockBindingsSource( name );
926+
}
927+
928+
/**
929+
* Returns all registered block bindings sources.
930+
*
931+
* @return {Array} Block bindings sources.
932+
*/
933+
export function getBlockBindingsSources() {
934+
return unlock( select( blocksStore ) ).getAllBlockBindingsSources();
935+
}

0 commit comments

Comments
 (0)