@wordpress/block-editor 14.3.2 → 14.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (128) hide show
  1. package/README.md +42 -0
  2. package/build/components/block-heading-level-dropdown/index.js +3 -1
  3. package/build/components/block-heading-level-dropdown/index.js.map +1 -1
  4. package/build/components/block-list/block.js +27 -4
  5. package/build/components/block-list/block.js.map +1 -1
  6. package/build/components/block-list/use-block-props/use-focus-first-element.js +0 -1
  7. package/build/components/block-list/use-block-props/use-focus-first-element.js.map +1 -1
  8. package/build/components/block-list/zoom-out-separator.js +18 -1
  9. package/build/components/block-list/zoom-out-separator.js.map +1 -1
  10. package/build/components/block-switcher/utils.js +1 -1
  11. package/build/components/block-switcher/utils.js.map +1 -1
  12. package/build/components/block-variation-transforms/index.js +6 -3
  13. package/build/components/block-variation-transforms/index.js.map +1 -1
  14. package/build/components/media-placeholder/index.js +17 -19
  15. package/build/components/media-placeholder/index.js.map +1 -1
  16. package/build/components/rich-text/event-listeners/paste-handler.js +2 -13
  17. package/build/components/rich-text/event-listeners/paste-handler.js.map +1 -1
  18. package/build/components/rich-text/index.js +35 -25
  19. package/build/components/rich-text/index.js.map +1 -1
  20. package/build/components/writing-flow/index.js +1 -2
  21. package/build/components/writing-flow/index.js.map +1 -1
  22. package/build/components/writing-flow/use-arrow-nav.js +1 -4
  23. package/build/components/writing-flow/use-arrow-nav.js.map +1 -1
  24. package/build/components/writing-flow/use-input.js +1 -31
  25. package/build/components/writing-flow/use-input.js.map +1 -1
  26. package/build/components/writing-flow/use-select-all.js +1 -14
  27. package/build/components/writing-flow/use-select-all.js.map +1 -1
  28. package/build/components/writing-flow/use-selection-observer.js +2 -6
  29. package/build/components/writing-flow/use-selection-observer.js.map +1 -1
  30. package/build/components/writing-flow/utils.js +0 -27
  31. package/build/components/writing-flow/utils.js.map +1 -1
  32. package/build/hooks/block-bindings.js +6 -13
  33. package/build/hooks/block-bindings.js.map +1 -1
  34. package/build/hooks/layout.js +12 -8
  35. package/build/hooks/layout.js.map +1 -1
  36. package/build/hooks/use-bindings-attributes.js +24 -29
  37. package/build/hooks/use-bindings-attributes.js.map +1 -1
  38. package/build/private-apis.js +0 -2
  39. package/build/private-apis.js.map +1 -1
  40. package/build/store/selectors.js +6 -3
  41. package/build/store/selectors.js.map +1 -1
  42. package/build/utils/block-bindings.js +48 -0
  43. package/build/utils/block-bindings.js.map +1 -1
  44. package/build/utils/index.js +7 -0
  45. package/build/utils/index.js.map +1 -1
  46. package/build-module/components/block-heading-level-dropdown/index.js +3 -1
  47. package/build-module/components/block-heading-level-dropdown/index.js.map +1 -1
  48. package/build-module/components/block-list/block.js +28 -7
  49. package/build-module/components/block-list/block.js.map +1 -1
  50. package/build-module/components/block-list/use-block-props/use-focus-first-element.js +0 -1
  51. package/build-module/components/block-list/use-block-props/use-focus-first-element.js.map +1 -1
  52. package/build-module/components/block-list/zoom-out-separator.js +18 -1
  53. package/build-module/components/block-list/zoom-out-separator.js.map +1 -1
  54. package/build-module/components/block-switcher/utils.js +1 -1
  55. package/build-module/components/block-switcher/utils.js.map +1 -1
  56. package/build-module/components/block-variation-transforms/index.js +6 -3
  57. package/build-module/components/block-variation-transforms/index.js.map +1 -1
  58. package/build-module/components/media-placeholder/index.js +18 -20
  59. package/build-module/components/media-placeholder/index.js.map +1 -1
  60. package/build-module/components/rich-text/event-listeners/paste-handler.js +2 -13
  61. package/build-module/components/rich-text/event-listeners/paste-handler.js.map +1 -1
  62. package/build-module/components/rich-text/index.js +35 -25
  63. package/build-module/components/rich-text/index.js.map +1 -1
  64. package/build-module/components/writing-flow/index.js +1 -2
  65. package/build-module/components/writing-flow/index.js.map +1 -1
  66. package/build-module/components/writing-flow/use-arrow-nav.js +1 -4
  67. package/build-module/components/writing-flow/use-arrow-nav.js.map +1 -1
  68. package/build-module/components/writing-flow/use-input.js +1 -31
  69. package/build-module/components/writing-flow/use-input.js.map +1 -1
  70. package/build-module/components/writing-flow/use-select-all.js +1 -14
  71. package/build-module/components/writing-flow/use-select-all.js.map +1 -1
  72. package/build-module/components/writing-flow/use-selection-observer.js +2 -6
  73. package/build-module/components/writing-flow/use-selection-observer.js.map +1 -1
  74. package/build-module/components/writing-flow/utils.js +0 -26
  75. package/build-module/components/writing-flow/utils.js.map +1 -1
  76. package/build-module/hooks/block-bindings.js +6 -13
  77. package/build-module/hooks/block-bindings.js.map +1 -1
  78. package/build-module/hooks/layout.js +13 -9
  79. package/build-module/hooks/layout.js.map +1 -1
  80. package/build-module/hooks/use-bindings-attributes.js +24 -29
  81. package/build-module/hooks/use-bindings-attributes.js.map +1 -1
  82. package/build-module/private-apis.js +0 -2
  83. package/build-module/private-apis.js.map +1 -1
  84. package/build-module/store/selectors.js +6 -3
  85. package/build-module/store/selectors.js.map +1 -1
  86. package/build-module/utils/block-bindings.js +48 -0
  87. package/build-module/utils/block-bindings.js.map +1 -1
  88. package/build-module/utils/index.js +1 -0
  89. package/build-module/utils/index.js.map +1 -1
  90. package/build-style/content-rtl.css +12 -14
  91. package/build-style/content.css +12 -14
  92. package/build-style/style-rtl.css +4 -0
  93. package/build-style/style.css +4 -0
  94. package/package.json +20 -20
  95. package/src/components/block-heading-level-dropdown/index.js +7 -1
  96. package/src/components/block-list/block.js +47 -11
  97. package/src/components/block-list/content.scss +12 -0
  98. package/src/components/block-list/use-block-props/use-focus-first-element.js +0 -1
  99. package/src/components/block-list/zoom-out-separator.js +14 -1
  100. package/src/components/block-switcher/test/use-transformed.patterns.js +3 -3
  101. package/src/components/block-switcher/test/utils.js +3 -3
  102. package/src/components/block-switcher/utils.js +1 -1
  103. package/src/components/block-toolbar/style.scss +7 -0
  104. package/src/components/block-variation-transforms/index.js +6 -7
  105. package/src/components/media-placeholder/content.scss +3 -19
  106. package/src/components/media-placeholder/index.js +17 -17
  107. package/src/components/rich-text/event-listeners/paste-handler.js +2 -7
  108. package/src/components/rich-text/index.js +37 -33
  109. package/src/components/writing-flow/index.js +0 -2
  110. package/src/components/writing-flow/use-arrow-nav.js +2 -9
  111. package/src/components/writing-flow/use-input.js +1 -36
  112. package/src/components/writing-flow/use-select-all.js +1 -18
  113. package/src/components/writing-flow/use-selection-observer.js +3 -14
  114. package/src/components/writing-flow/utils.js +0 -30
  115. package/src/hooks/block-bindings.js +9 -10
  116. package/src/hooks/layout.js +17 -12
  117. package/src/hooks/use-bindings-attributes.js +74 -76
  118. package/src/private-apis.js +0 -2
  119. package/src/store/selectors.js +6 -6
  120. package/src/store/test/private-selectors.js +2 -2
  121. package/src/store/test/selectors.js +10 -6
  122. package/src/utils/block-bindings.js +47 -0
  123. package/src/utils/index.js +1 -0
  124. package/build/components/writing-flow/use-event-redirect.js +0 -66
  125. package/build/components/writing-flow/use-event-redirect.js.map +0 -1
  126. package/build-module/components/writing-flow/use-event-redirect.js +0 -60
  127. package/build-module/components/writing-flow/use-event-redirect.js.map +0 -1
  128. package/src/components/writing-flow/use-event-redirect.js +0 -72
@@ -26,15 +26,10 @@ export default ( props ) => ( element ) => {
26
26
  preserveWhiteSpace,
27
27
  pastePlainText,
28
28
  } = props.current;
29
- const { ownerDocument } = element;
30
- const { defaultView } = ownerDocument;
31
- const { anchorNode, focusNode } = defaultView.getSelection();
32
- const containsSelection =
33
- element.contains( anchorNode ) && element.contains( focusNode );
34
29
 
35
30
  // The event listener is attached to the window, so we need to check if
36
- // the target is the element.
37
- if ( ! containsSelection ) {
31
+ // the target is the element or inside the element.
32
+ if ( ! element.contains( event.target ) ) {
38
33
  return;
39
34
  }
40
35
 
@@ -20,7 +20,7 @@ import {
20
20
  removeFormat,
21
21
  } from '@wordpress/rich-text';
22
22
  import { Popover } from '@wordpress/components';
23
- import { store as blocksStore } from '@wordpress/blocks';
23
+ import { getBlockBindingsSource } from '@wordpress/blocks';
24
24
  import deprecated from '@wordpress/deprecated';
25
25
  import { __, sprintf } from '@wordpress/i18n';
26
26
 
@@ -39,7 +39,6 @@ import FormatEdit from './format-edit';
39
39
  import { getAllowedFormats } from './utils';
40
40
  import { Content, valueToHTMLString } from './content';
41
41
  import { withDeprecations } from './with-deprecations';
42
- import { unlock } from '../../lock-unlock';
43
42
  import { canBindBlock } from '../../hooks/use-bindings-attributes';
44
43
  import BlockContext from '../block-context';
45
44
 
@@ -165,7 +164,7 @@ export function RichTextWrapper(
165
164
  isBlockSelected,
166
165
  ] );
167
166
 
168
- const { disableBoundBlock, bindingsPlaceholder } = useSelect(
167
+ const { disableBoundBlock, bindingsPlaceholder, bindingsLabel } = useSelect(
169
168
  ( select ) => {
170
169
  if (
171
170
  ! blockBindings?.[ identifier ] ||
@@ -175,22 +174,39 @@ export function RichTextWrapper(
175
174
  }
176
175
 
177
176
  const relatedBinding = blockBindings[ identifier ];
178
- const { getBlockBindingsSource } = unlock( select( blocksStore ) );
179
177
  const blockBindingsSource = getBlockBindingsSource(
180
178
  relatedBinding.source
181
179
  );
182
- const fieldsList = blockBindingsSource?.getFieldsList?.( {
183
- registry,
184
- context: blockContext,
185
- } );
180
+ const blockBindingsContext = {};
181
+ if ( blockBindingsSource?.usesContext?.length ) {
182
+ for ( const key of blockBindingsSource.usesContext ) {
183
+ blockBindingsContext[ key ] = blockContext[ key ];
184
+ }
185
+ }
186
186
 
187
187
  const _disableBoundBlock =
188
188
  ! blockBindingsSource?.canUserEditValue?.( {
189
189
  select,
190
- context: blockContext,
190
+ context: blockBindingsContext,
191
191
  args: relatedBinding.args,
192
192
  } );
193
193
 
194
+ // Don't modify placeholders if value is not empty.
195
+ if ( adjustedValue.length > 0 ) {
196
+ return {
197
+ disableBoundBlock: _disableBoundBlock,
198
+ // Null values will make them fall back to the default behavior.
199
+ bindingsPlaceholder: null,
200
+ bindingsLabel: null,
201
+ };
202
+ }
203
+
204
+ const { getBlockAttributes } = select( blockEditorStore );
205
+ const blockAttributes = getBlockAttributes( clientId );
206
+ const fieldsList = blockBindingsSource?.getFieldsList?.( {
207
+ select,
208
+ context: blockBindingsContext,
209
+ } );
194
210
  const bindingKey =
195
211
  fieldsList?.[ relatedBinding?.args?.key ]?.label ??
196
212
  blockBindingsSource?.label;
@@ -202,22 +218,22 @@ export function RichTextWrapper(
202
218
  __( 'Add %s' ),
203
219
  bindingKey
204
220
  );
221
+ const _bindingsLabel = _disableBoundBlock
222
+ ? relatedBinding?.args?.key || blockBindingsSource?.label
223
+ : sprintf(
224
+ /* translators: %s: source label or key */
225
+ __( 'Empty %s; start writing to edit its value' ),
226
+ relatedBinding?.args?.key || blockBindingsSource?.label
227
+ );
205
228
 
206
229
  return {
207
230
  disableBoundBlock: _disableBoundBlock,
208
231
  bindingsPlaceholder:
209
- ( ! adjustedValue || adjustedValue.length === 0 ) &&
210
- _bindingsPlaceholder,
232
+ blockAttributes?.placeholder || _bindingsPlaceholder,
233
+ bindingsLabel: _bindingsLabel,
211
234
  };
212
235
  },
213
- [
214
- blockBindings,
215
- identifier,
216
- blockName,
217
- blockContext,
218
- registry,
219
- adjustedValue,
220
- ]
236
+ [ blockBindings, identifier, blockName, blockContext, adjustedValue ]
221
237
  );
222
238
 
223
239
  const shouldDisableEditing = readOnly || disableBoundBlock;
@@ -372,19 +388,7 @@ export function RichTextWrapper(
372
388
  const inputEvents = useRef( new Set() );
373
389
 
374
390
  function onFocus() {
375
- let element = anchorRef.current;
376
-
377
- if ( ! element ) {
378
- return;
379
- }
380
-
381
- // Writing flow might be editable, so we should make sure focus goes to
382
- // the root editable element.
383
- while ( element.parentElement?.isContentEditable ) {
384
- element = element.parentElement;
385
- }
386
-
387
- element.focus();
391
+ anchorRef.current?.focus();
388
392
  }
389
393
 
390
394
  const TagName = tagName;
@@ -421,7 +425,7 @@ export function RichTextWrapper(
421
425
  aria-readonly={ shouldDisableEditing }
422
426
  { ...props }
423
427
  aria-label={
424
- bindingsPlaceholder || props[ 'aria-label' ] || placeholder
428
+ bindingsLabel || props[ 'aria-label' ] || placeholder
425
429
  }
426
430
  { ...autocompleteProps }
427
431
  ref={ useMergeRefs( [
@@ -23,7 +23,6 @@ import useSelectionObserver from './use-selection-observer';
23
23
  import useClickSelection from './use-click-selection';
24
24
  import useInput from './use-input';
25
25
  import useClipboardHandler from './use-clipboard-handler';
26
- import useEventRedirect from './use-event-redirect';
27
26
  import { store as blockEditorStore } from '../../store';
28
27
 
29
28
  export function useWritingFlow() {
@@ -66,7 +65,6 @@ export function useWritingFlow() {
66
65
  },
67
66
  [ hasMultiSelection ]
68
67
  ),
69
- useEventRedirect(),
70
68
  ] ),
71
69
  after,
72
70
  ];
@@ -19,7 +19,6 @@ import { useRefEffect } from '@wordpress/compose';
19
19
  */
20
20
  import { getBlockClientId, isInSameBlock } from '../../utils/dom';
21
21
  import { store as blockEditorStore } from '../../store';
22
- import { getSelectionRoot } from './utils';
23
22
 
24
23
  /**
25
24
  * Returns true if the element should consider edge navigation upon a keyboard
@@ -191,7 +190,8 @@ export default function useArrowNav() {
191
190
  return;
192
191
  }
193
192
 
194
- const { keyCode, shiftKey, ctrlKey, altKey, metaKey } = event;
193
+ const { keyCode, target, shiftKey, ctrlKey, altKey, metaKey } =
194
+ event;
195
195
  const isUp = keyCode === UP;
196
196
  const isDown = keyCode === DOWN;
197
197
  const isLeft = keyCode === LEFT;
@@ -233,11 +233,6 @@ export default function useArrowNav() {
233
233
  return;
234
234
  }
235
235
 
236
- const target =
237
- ownerDocument.activeElement === node
238
- ? getSelectionRoot( ownerDocument )
239
- : event.target;
240
-
241
236
  // Abort if our current target is not a candidate for navigation
242
237
  // (e.g. preserve native input behaviors).
243
238
  if ( ! isNavigationCandidate( target, keyCode, hasModifier ) ) {
@@ -279,7 +274,6 @@ export default function useArrowNav() {
279
274
  ( altKey ? isHorizontalEdge( target, isReverseDir ) : true ) &&
280
275
  ! keepCaretInsideBlock
281
276
  ) {
282
- node.contentEditable = false;
283
277
  const closestTabbable = getClosestTabbable(
284
278
  target,
285
279
  isReverse,
@@ -303,7 +297,6 @@ export default function useArrowNav() {
303
297
  isHorizontalEdge( target, isReverseDir ) &&
304
298
  ! keepCaretInsideBlock
305
299
  ) {
306
- node.contentEditable = false;
307
300
  const closestTabbable = getClosestTabbable(
308
301
  target,
309
302
  isReverseDir,
@@ -16,7 +16,6 @@ import {
16
16
  * Internal dependencies
17
17
  */
18
18
  import { store as blockEditorStore } from '../../store';
19
- import { getSelectionRoot } from './utils';
20
19
 
21
20
  /**
22
21
  * Handles input for selections across blocks.
@@ -50,24 +49,7 @@ export default function useInput() {
50
49
  // DOM. This will cause React errors (and the DOM should only be
51
50
  // altered in a controlled fashion).
52
51
  if ( node.contentEditable === 'true' ) {
53
- const selection = node.ownerDocument.defaultView.getSelection();
54
- const range = selection.rangeCount
55
- ? selection.getRangeAt( 0 )
56
- : null;
57
- const root = getSelectionRoot( node.ownerDocument );
58
-
59
- // If selection is contained within a nested editable, allow
60
- // input. We need to ensure that selection is maintained.
61
- if ( root ) {
62
- node.contentEditable = false;
63
- root.focus();
64
- selection.removeAllRanges();
65
- if ( range ) {
66
- selection.addRange( range );
67
- }
68
- } else {
69
- event.preventDefault();
70
- }
52
+ event.preventDefault();
71
53
  }
72
54
  }
73
55
 
@@ -77,23 +59,6 @@ export default function useInput() {
77
59
  }
78
60
 
79
61
  if ( ! hasMultiSelection() ) {
80
- const { ownerDocument } = node;
81
- if ( node === ownerDocument.activeElement ) {
82
- if ( event.key === 'End' || event.key === 'Home' ) {
83
- const selectionRoot = getSelectionRoot( ownerDocument );
84
- const selection =
85
- ownerDocument.defaultView.getSelection();
86
- selection.selectAllChildren( selectionRoot );
87
- const method =
88
- event.key === 'End'
89
- ? 'collapseToEnd'
90
- : 'collapseToStart';
91
- selection[ method ]();
92
- event.preventDefault();
93
- return;
94
- }
95
- }
96
-
97
62
  if ( event.keyCode === ENTER ) {
98
63
  if ( event.shiftKey || __unstableIsFullySelected() ) {
99
64
  return;
@@ -10,7 +10,6 @@ import { useRefEffect } from '@wordpress/compose';
10
10
  * Internal dependencies
11
11
  */
12
12
  import { store as blockEditorStore } from '../../store';
13
- import { getSelectionRoot } from './utils';
14
13
 
15
14
  export default function useSelectAll() {
16
15
  const { getBlockOrder, getSelectedBlockClientIds, getBlockRootClientId } =
@@ -24,27 +23,12 @@ export default function useSelectAll() {
24
23
  return;
25
24
  }
26
25
 
27
- const selectionRoot = getSelectionRoot( node.ownerDocument );
28
26
  const selectedClientIds = getSelectedBlockClientIds();
29
27
 
30
- // Abort if there is selection, but it is not within a block.
31
- if ( selectionRoot && ! selectedClientIds.length ) {
32
- return;
33
- }
34
-
35
28
  if (
36
- selectionRoot &&
37
29
  selectedClientIds.length < 2 &&
38
- ! isEntirelySelected( selectionRoot )
30
+ ! isEntirelySelected( event.target )
39
31
  ) {
40
- if ( node === node.ownerDocument.activeElement ) {
41
- event.preventDefault();
42
- node.ownerDocument.defaultView
43
- .getSelection()
44
- .selectAllChildren( selectionRoot );
45
- return;
46
- }
47
-
48
32
  return;
49
33
  }
50
34
 
@@ -61,7 +45,6 @@ export default function useSelectAll() {
61
45
  node.ownerDocument.defaultView
62
46
  .getSelection()
63
47
  .removeAllRanges();
64
- node.contentEditable = 'false';
65
48
  selectBlock( rootClientId );
66
49
  }
67
50
  return;
@@ -107,12 +107,8 @@ function getRichTextElement( node ) {
107
107
  export default function useSelectionObserver() {
108
108
  const { multiSelect, selectBlock, selectionChange } =
109
109
  useDispatch( blockEditorStore );
110
- const {
111
- getBlockParents,
112
- getBlockSelectionStart,
113
- isMultiSelecting,
114
- getSelectedBlockClientId,
115
- } = useSelect( blockEditorStore );
110
+ const { getBlockParents, getBlockSelectionStart, isMultiSelecting } =
111
+ useSelect( blockEditorStore );
116
112
  return useRefEffect(
117
113
  ( node ) => {
118
114
  const { ownerDocument } = node;
@@ -195,17 +191,10 @@ export default function useSelectionObserver() {
195
191
  return;
196
192
  }
197
193
 
198
- setContentEditableWrapper(
199
- node,
200
- !! ( startClientId && endClientId )
201
- );
202
-
203
194
  const isSingularSelection = startClientId === endClientId;
204
195
  if ( isSingularSelection ) {
205
196
  if ( ! isMultiSelecting() ) {
206
- if ( getSelectedBlockClientId() !== startClientId ) {
207
- selectBlock( startClientId );
208
- }
197
+ selectBlock( startClientId );
209
198
  } else {
210
199
  multiSelect( startClientId, startClientId );
211
200
  }
@@ -116,33 +116,3 @@ function toPlainText( html ) {
116
116
  // Merge any consecutive line breaks
117
117
  return plainText.replace( /\n\n+/g, '\n\n' );
118
118
  }
119
-
120
- /**
121
- * Gets the current content editable root element based on the selection.
122
- * @param {Document} ownerDocument
123
- * @return {Element|undefined} The content editable root element.
124
- */
125
- export function getSelectionRoot( ownerDocument ) {
126
- const { defaultView } = ownerDocument;
127
- const { anchorNode, focusNode } = defaultView.getSelection();
128
-
129
- if ( ! anchorNode || ! focusNode ) {
130
- return;
131
- }
132
-
133
- const anchorElement = (
134
- anchorNode.nodeType === anchorNode.ELEMENT_NODE
135
- ? anchorNode
136
- : anchorNode.parentElement
137
- ).closest( '[contenteditable]' );
138
-
139
- if ( ! anchorElement ) {
140
- return;
141
- }
142
-
143
- if ( ! anchorElement.contains( focusNode ) ) {
144
- return;
145
- }
146
-
147
- return anchorElement;
148
- }
@@ -2,7 +2,10 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { __ } from '@wordpress/i18n';
5
- import { privateApis as blocksPrivateApis } from '@wordpress/blocks';
5
+ import {
6
+ getBlockBindingsSource,
7
+ getBlockBindingsSources,
8
+ } from '@wordpress/blocks';
6
9
  import {
7
10
  __experimentalItemGroup as ItemGroup,
8
11
  __experimentalItem as Item,
@@ -12,7 +15,7 @@ import {
12
15
  __experimentalVStack as VStack,
13
16
  privateApis as componentsPrivateApis,
14
17
  } from '@wordpress/components';
15
- import { useRegistry, useSelect } from '@wordpress/data';
18
+ import { useSelect } from '@wordpress/data';
16
19
  import { useContext, Fragment } from '@wordpress/element';
17
20
  import { useViewportMatch } from '@wordpress/compose';
18
21
 
@@ -47,7 +50,6 @@ const useToolsPanelDropdownMenuProps = () => {
47
50
  };
48
51
 
49
52
  function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) {
50
- const { getBlockBindingsSources } = unlock( blocksPrivateApis );
51
53
  const registeredSources = getBlockBindingsSources();
52
54
  const { updateBlockBindings } = useBlockBindingsUtils();
53
55
  const currentKey = binding?.args?.key;
@@ -96,8 +98,7 @@ function BlockBindingsPanelDropdown( { fieldsList, attribute, binding } ) {
96
98
 
97
99
  function BlockBindingsAttribute( { attribute, binding, fieldsList } ) {
98
100
  const { source: sourceName, args } = binding || {};
99
- const sourceProps =
100
- unlock( blocksPrivateApis ).getBlockBindingsSource( sourceName );
101
+ const sourceProps = getBlockBindingsSource( sourceName );
101
102
  const isSourceInvalid = ! sourceProps;
102
103
  return (
103
104
  <VStack className="block-editor-bindings__item" spacing={ 0 }>
@@ -186,7 +187,6 @@ function EditableBlockBindingsPanelItems( {
186
187
  }
187
188
 
188
189
  export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
189
- const registry = useRegistry();
190
190
  const blockContext = useContext( BlockContext );
191
191
  const { removeAllBlockBindings } = useBlockBindingsUtils();
192
192
  const bindableAttributes = getBindableAttributes( blockName );
@@ -194,14 +194,13 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
194
194
 
195
195
  // `useSelect` is used purposely here to ensure `getFieldsList`
196
196
  // is updated whenever there are updates in block context.
197
- // `source.getFieldsList` may also call a selector via `registry.select`.
197
+ // `source.getFieldsList` may also call a selector via `select`.
198
198
  const _fieldsList = {};
199
199
  const { fieldsList, canUpdateBlockBindings } = useSelect(
200
200
  ( select ) => {
201
201
  if ( ! bindableAttributes || bindableAttributes.length === 0 ) {
202
202
  return EMPTY_OBJECT;
203
203
  }
204
- const { getBlockBindingsSources } = unlock( blocksPrivateApis );
205
204
  const registeredSources = getBlockBindingsSources();
206
205
  Object.entries( registeredSources ).forEach(
207
206
  ( [ sourceName, { getFieldsList, usesContext } ] ) => {
@@ -214,7 +213,7 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
214
213
  }
215
214
  }
216
215
  const sourceList = getFieldsList( {
217
- registry,
216
+ select,
218
217
  context,
219
218
  } );
220
219
  // Only add source if the list is not empty.
@@ -234,7 +233,7 @@ export const BlockBindingsPanel = ( { name: blockName, metadata } ) => {
234
233
  .canUpdateBlockBindings,
235
234
  };
236
235
  },
237
- [ blockContext, bindableAttributes, registry ]
236
+ [ blockContext, bindableAttributes ]
238
237
  );
239
238
  // Return early if there are no bindable attributes.
240
239
  if ( ! bindableAttributes || bindableAttributes.length === 0 ) {
@@ -11,8 +11,8 @@ import { addFilter } from '@wordpress/hooks';
11
11
  import { getBlockSupport, hasBlockSupport } from '@wordpress/blocks';
12
12
  import { useSelect } from '@wordpress/data';
13
13
  import {
14
- Button,
15
- ButtonGroup,
14
+ __experimentalToggleGroupControl as ToggleGroupControl,
15
+ __experimentalToggleGroupControlOption as ToggleGroupControlOption,
16
16
  ToggleControl,
17
17
  PanelBody,
18
18
  privateApis as componentsPrivateApis,
@@ -315,21 +315,26 @@ export default {
315
315
 
316
316
  function LayoutTypeSwitcher( { type, onChange } ) {
317
317
  return (
318
- <ButtonGroup>
318
+ <ToggleGroupControl
319
+ __next40pxDefaultSize
320
+ isBlock
321
+ label={ __( 'Layout type' ) }
322
+ __nextHasNoMarginBottom
323
+ hideLabelFromVision
324
+ isAdaptiveWidth
325
+ value={ type }
326
+ onChange={ onChange }
327
+ >
319
328
  { getLayoutTypes().map( ( { name, label } ) => {
320
329
  return (
321
- <Button
322
- // TODO: Switch to `true` (40px size) if possible
323
- __next40pxDefaultSize={ false }
330
+ <ToggleGroupControlOption
324
331
  key={ name }
325
- isPressed={ type === name }
326
- onClick={ () => onChange( name ) }
327
- >
328
- { label }
329
- </Button>
332
+ value={ name }
333
+ label={ label }
334
+ />
330
335
  );
331
336
  } ) }
332
- </ButtonGroup>
337
+ </ToggleGroupControl>
333
338
  );
334
339
  }
335
340