@@ -758,3 +758,178 @@ export const registerBlockVariation = ( blockName, variation ) => {
758
758
export const unregisterBlockVariation = ( blockName , variationName ) => {
759
759
dispatch ( blocksStore ) . removeBlockVariations ( blockName , variationName ) ;
760
760
} ;
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 - z 0 - 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 - z 0 - 9 - ] + \/ [ a - z 0 - 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