@wordpress/block-editor 12.19.4 → 12.19.6

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 (100) hide show
  1. package/build/components/block-actions/index.js +45 -32
  2. package/build/components/block-actions/index.js.map +1 -1
  3. package/build/components/block-bindings-toolbar-indicator/index.js +25 -0
  4. package/build/components/block-bindings-toolbar-indicator/index.js.map +1 -0
  5. package/build/components/block-list/use-block-props/index.js +8 -1
  6. package/build/components/block-list/use-block-props/index.js.map +1 -1
  7. package/build/components/block-list/use-block-props/use-selected-block-event-handlers.js +3 -3
  8. package/build/components/block-list/use-block-props/use-selected-block-event-handlers.js.map +1 -1
  9. package/build/components/block-settings-menu/block-settings-dropdown.js +12 -10
  10. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  11. package/build/components/block-toolbar/index.js +14 -5
  12. package/build/components/block-toolbar/index.js.map +1 -1
  13. package/build/components/global-styles/use-global-styles-output.js +13 -13
  14. package/build/components/global-styles/use-global-styles-output.js.map +1 -1
  15. package/build/components/list-view/block-select-button.js +10 -2
  16. package/build/components/list-view/block-select-button.js.map +1 -1
  17. package/build/components/list-view/use-clipboard-handler.js +2 -1
  18. package/build/components/list-view/use-clipboard-handler.js.map +1 -1
  19. package/build/components/rich-text/index.js +1 -1
  20. package/build/components/rich-text/index.js.map +1 -1
  21. package/build/components/url-popover/index.js +3 -3
  22. package/build/components/url-popover/index.js.map +1 -1
  23. package/build/components/use-moving-animation/index.js +4 -0
  24. package/build/components/use-moving-animation/index.js.map +1 -1
  25. package/build/components/writing-flow/use-clipboard-handler.js +2 -1
  26. package/build/components/writing-flow/use-clipboard-handler.js.map +1 -1
  27. package/build/components/writing-flow/utils.js +23 -6
  28. package/build/components/writing-flow/utils.js.map +1 -1
  29. package/build/hooks/block-hooks.js +26 -2
  30. package/build/hooks/block-hooks.js.map +1 -1
  31. package/build/hooks/use-bindings-attributes.js +171 -46
  32. package/build/hooks/use-bindings-attributes.js.map +1 -1
  33. package/build/private-apis.js +2 -0
  34. package/build/private-apis.js.map +1 -1
  35. package/build/store/actions.js +40 -6
  36. package/build/store/actions.js.map +1 -1
  37. package/build-module/components/block-actions/index.js +45 -32
  38. package/build-module/components/block-actions/index.js.map +1 -1
  39. package/build-module/components/block-bindings-toolbar-indicator/index.js +18 -0
  40. package/build-module/components/block-bindings-toolbar-indicator/index.js.map +1 -0
  41. package/build-module/components/block-list/use-block-props/index.js +9 -2
  42. package/build-module/components/block-list/use-block-props/index.js.map +1 -1
  43. package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.js +3 -3
  44. package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.js.map +1 -1
  45. package/build-module/components/block-settings-menu/block-settings-dropdown.js +12 -10
  46. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  47. package/build-module/components/block-toolbar/index.js +14 -5
  48. package/build-module/components/block-toolbar/index.js.map +1 -1
  49. package/build-module/components/global-styles/use-global-styles-output.js +13 -13
  50. package/build-module/components/global-styles/use-global-styles-output.js.map +1 -1
  51. package/build-module/components/list-view/block-select-button.js +11 -3
  52. package/build-module/components/list-view/block-select-button.js.map +1 -1
  53. package/build-module/components/list-view/use-clipboard-handler.js +3 -2
  54. package/build-module/components/list-view/use-clipboard-handler.js.map +1 -1
  55. package/build-module/components/rich-text/index.js +2 -2
  56. package/build-module/components/rich-text/index.js.map +1 -1
  57. package/build-module/components/url-popover/index.js +3 -3
  58. package/build-module/components/url-popover/index.js.map +1 -1
  59. package/build-module/components/use-moving-animation/index.js +4 -0
  60. package/build-module/components/use-moving-animation/index.js.map +1 -1
  61. package/build-module/components/writing-flow/use-clipboard-handler.js +3 -2
  62. package/build-module/components/writing-flow/use-clipboard-handler.js.map +1 -1
  63. package/build-module/components/writing-flow/utils.js +22 -7
  64. package/build-module/components/writing-flow/utils.js.map +1 -1
  65. package/build-module/hooks/block-hooks.js +26 -2
  66. package/build-module/hooks/block-hooks.js.map +1 -1
  67. package/build-module/hooks/use-bindings-attributes.js +171 -46
  68. package/build-module/hooks/use-bindings-attributes.js.map +1 -1
  69. package/build-module/private-apis.js +2 -0
  70. package/build-module/private-apis.js.map +1 -1
  71. package/build-module/store/actions.js +40 -6
  72. package/build-module/store/actions.js.map +1 -1
  73. package/build-style/content-rtl.css +1 -0
  74. package/build-style/content.css +1 -0
  75. package/build-style/default-editor-styles-rtl.css +1 -0
  76. package/build-style/default-editor-styles.css +1 -0
  77. package/build-style/style-rtl.css +23 -0
  78. package/build-style/style.css +23 -0
  79. package/package.json +8 -8
  80. package/src/components/block-actions/index.js +57 -47
  81. package/src/components/block-bindings-toolbar-indicator/index.js +20 -0
  82. package/src/components/block-bindings-toolbar-indicator/style.scss +14 -0
  83. package/src/components/block-list/use-block-props/index.js +12 -2
  84. package/src/components/block-list/use-block-props/use-selected-block-event-handlers.js +3 -7
  85. package/src/components/block-settings-menu/block-settings-dropdown.js +12 -9
  86. package/src/components/block-toolbar/index.js +14 -4
  87. package/src/components/global-styles/use-global-styles-output.js +11 -11
  88. package/src/components/list-view/block-select-button.js +16 -2
  89. package/src/components/list-view/style.scss +8 -0
  90. package/src/components/list-view/use-clipboard-handler.js +3 -2
  91. package/src/components/rich-text/index.js +2 -2
  92. package/src/components/url-popover/index.js +5 -5
  93. package/src/components/use-moving-animation/index.js +1 -0
  94. package/src/components/writing-flow/use-clipboard-handler.js +3 -2
  95. package/src/components/writing-flow/utils.js +31 -16
  96. package/src/hooks/block-hooks.js +36 -3
  97. package/src/hooks/use-bindings-attributes.js +214 -62
  98. package/src/private-apis.js +2 -0
  99. package/src/store/actions.js +54 -14
  100. package/src/style.scss +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/block-editor",
3
- "version": "12.19.4",
3
+ "version": "12.19.6",
4
4
  "description": "Generic block editor.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -38,9 +38,9 @@
38
38
  "@wordpress/a11y": "^3.51.1",
39
39
  "@wordpress/api-fetch": "^6.48.1",
40
40
  "@wordpress/blob": "^3.51.1",
41
- "@wordpress/blocks": "^12.28.4",
42
- "@wordpress/commands": "^0.22.3",
43
- "@wordpress/components": "^26.0.3",
41
+ "@wordpress/blocks": "^12.28.6",
42
+ "@wordpress/commands": "^0.22.5",
43
+ "@wordpress/components": "^26.0.5",
44
44
  "@wordpress/compose": "^6.28.1",
45
45
  "@wordpress/data": "^9.21.1",
46
46
  "@wordpress/date": "^4.51.1",
@@ -51,14 +51,14 @@
51
51
  "@wordpress/hooks": "^3.51.1",
52
52
  "@wordpress/html-entities": "^3.51.1",
53
53
  "@wordpress/i18n": "^4.51.1",
54
- "@wordpress/icons": "^9.42.2",
54
+ "@wordpress/icons": "^9.42.4",
55
55
  "@wordpress/is-shallow-equal": "^4.51.1",
56
56
  "@wordpress/keyboard-shortcuts": "^4.28.1",
57
57
  "@wordpress/keycodes": "^3.51.1",
58
58
  "@wordpress/notices": "^4.19.1",
59
- "@wordpress/preferences": "^3.28.3",
59
+ "@wordpress/preferences": "^3.28.5",
60
60
  "@wordpress/private-apis": "^0.33.1",
61
- "@wordpress/rich-text": "^6.28.2",
61
+ "@wordpress/rich-text": "^6.28.4",
62
62
  "@wordpress/style-engine": "^1.34.1",
63
63
  "@wordpress/token-list": "^2.51.1",
64
64
  "@wordpress/url": "^3.52.1",
@@ -87,5 +87,5 @@
87
87
  "publishConfig": {
88
88
  "access": "public"
89
89
  },
90
- "gitHead": "864c1c553cb284def3bd5c907998da45f5c143ea"
90
+ "gitHead": "7d2a00f1998a0a696694802725e523628f994cfc"
91
91
  }
@@ -20,42 +20,55 @@ export default function BlockActions( {
20
20
  children,
21
21
  __experimentalUpdateSelection: updateSelection,
22
22
  } ) {
23
- const {
24
- canInsertBlockType,
25
- getBlockRootClientId,
26
- getBlocksByClientId,
27
- canMoveBlocks,
28
- canRemoveBlocks,
29
- } = useSelect( blockEditorStore );
30
23
  const { getDefaultBlockName, getGroupingBlockName } =
31
24
  useSelect( blocksStore );
32
-
33
- const blocks = getBlocksByClientId( clientIds );
34
- const rootClientId = getBlockRootClientId( clientIds[ 0 ] );
35
-
36
- const canCopyStyles = blocks.every( ( block ) => {
37
- return (
38
- !! block &&
39
- ( hasBlockSupport( block.name, 'color' ) ||
40
- hasBlockSupport( block.name, 'typography' ) )
41
- );
42
- } );
43
-
44
- const canDuplicate = blocks.every( ( block ) => {
45
- return (
46
- !! block &&
47
- hasBlockSupport( block.name, 'multiple', true ) &&
48
- canInsertBlockType( block.name, rootClientId )
49
- );
50
- } );
51
-
52
- const canInsertDefaultBlock = canInsertBlockType(
53
- getDefaultBlockName(),
54
- rootClientId
25
+ const selected = useSelect(
26
+ ( select ) => {
27
+ const {
28
+ canInsertBlockType,
29
+ getBlockRootClientId,
30
+ getBlocksByClientId,
31
+ getDirectInsertBlock,
32
+ canMoveBlocks,
33
+ canRemoveBlocks,
34
+ } = select( blockEditorStore );
35
+
36
+ const blocks = getBlocksByClientId( clientIds );
37
+ const rootClientId = getBlockRootClientId( clientIds[ 0 ] );
38
+ const canInsertDefaultBlock = canInsertBlockType(
39
+ getDefaultBlockName(),
40
+ rootClientId
41
+ );
42
+ const directInsertBlock = rootClientId
43
+ ? getDirectInsertBlock( rootClientId )
44
+ : null;
45
+
46
+ return {
47
+ canMove: canMoveBlocks( clientIds, rootClientId ),
48
+ canRemove: canRemoveBlocks( clientIds, rootClientId ),
49
+ canInsertBlock: canInsertDefaultBlock || !! directInsertBlock,
50
+ canCopyStyles: blocks.every( ( block ) => {
51
+ return (
52
+ !! block &&
53
+ ( hasBlockSupport( block.name, 'color' ) ||
54
+ hasBlockSupport( block.name, 'typography' ) )
55
+ );
56
+ } ),
57
+ canDuplicate: blocks.every( ( block ) => {
58
+ return (
59
+ !! block &&
60
+ hasBlockSupport( block.name, 'multiple', true ) &&
61
+ canInsertBlockType( block.name, rootClientId )
62
+ );
63
+ } ),
64
+ };
65
+ },
66
+ [ clientIds, getDefaultBlockName ]
55
67
  );
68
+ const { getBlocksByClientId, getBlocks } = useSelect( blockEditorStore );
56
69
 
57
- const canMove = canMoveBlocks( clientIds, rootClientId );
58
- const canRemove = canRemoveBlocks( clientIds, rootClientId );
70
+ const { canMove, canRemove, canInsertBlock, canCopyStyles, canDuplicate } =
71
+ selected;
59
72
 
60
73
  const {
61
74
  removeBlocks,
@@ -75,11 +88,9 @@ export default function BlockActions( {
75
88
  return children( {
76
89
  canCopyStyles,
77
90
  canDuplicate,
78
- canInsertDefaultBlock,
91
+ canInsertBlock,
79
92
  canMove,
80
93
  canRemove,
81
- rootClientId,
82
- blocks,
83
94
  onDuplicate() {
84
95
  return duplicateBlocks( clientIds, updateSelection );
85
96
  },
@@ -104,14 +115,17 @@ export default function BlockActions( {
104
115
  setBlockMovingClientId( clientIds[ 0 ] );
105
116
  },
106
117
  onGroup() {
107
- if ( ! blocks.length ) {
118
+ if ( ! clientIds.length ) {
108
119
  return;
109
120
  }
110
121
 
111
122
  const groupingBlockName = getGroupingBlockName();
112
123
 
113
124
  // Activate the `transform` on `core/group` which does the conversion.
114
- const newBlocks = switchToBlockType( blocks, groupingBlockName );
125
+ const newBlocks = switchToBlockType(
126
+ getBlocksByClientId( clientIds ),
127
+ groupingBlockName
128
+ );
115
129
 
116
130
  if ( ! newBlocks ) {
117
131
  return;
@@ -119,12 +133,11 @@ export default function BlockActions( {
119
133
  replaceBlocks( clientIds, newBlocks );
120
134
  },
121
135
  onUngroup() {
122
- if ( ! blocks.length ) {
136
+ if ( ! clientIds.length ) {
123
137
  return;
124
138
  }
125
139
 
126
- const innerBlocks = blocks[ 0 ].innerBlocks;
127
-
140
+ const innerBlocks = getBlocks( clientIds[ 0 ] );
128
141
  if ( ! innerBlocks.length ) {
129
142
  return;
130
143
  }
@@ -132,16 +145,13 @@ export default function BlockActions( {
132
145
  replaceBlocks( clientIds, innerBlocks );
133
146
  },
134
147
  onCopy() {
135
- const selectedBlockClientIds = blocks.map(
136
- ( { clientId } ) => clientId
137
- );
138
- if ( blocks.length === 1 ) {
139
- flashBlock( selectedBlockClientIds[ 0 ] );
148
+ if ( clientIds.length === 1 ) {
149
+ flashBlock( clientIds[ 0 ] );
140
150
  }
141
- notifyCopy( 'copy', selectedBlockClientIds );
151
+ notifyCopy( 'copy', clientIds );
142
152
  },
143
153
  async onPasteStyles() {
144
- await pasteStyles( blocks );
154
+ await pasteStyles( getBlocksByClientId( clientIds ) );
145
155
  },
146
156
  } );
147
157
  }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { ToolbarItem, ToolbarGroup, Icon } from '@wordpress/components';
5
+ import { connection } from '@wordpress/icons';
6
+ import { _x } from '@wordpress/i18n';
7
+
8
+ export default function BlockBindingsToolbarIndicator() {
9
+ return (
10
+ <ToolbarGroup>
11
+ <ToolbarItem
12
+ as={ 'div' }
13
+ aria-label={ _x( 'Connected', 'block toolbar button label' ) }
14
+ className="block-editor-block-bindings-toolbar-indicator"
15
+ >
16
+ <Icon icon={ connection } size={ 24 } />
17
+ </ToolbarItem>
18
+ </ToolbarGroup>
19
+ );
20
+ }
@@ -0,0 +1,14 @@
1
+ .block-editor-block-bindings-toolbar-indicator {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ height: 48px;
5
+ padding: 6px;
6
+
7
+ svg g {
8
+ stroke: var(--wp-bound-block-color);
9
+ fill: transparent;
10
+ stroke-width: 1.5;
11
+ stroke-linecap: round;
12
+ stroke-linejoin: round;
13
+ }
14
+ }
@@ -19,13 +19,17 @@ import useMovingAnimation from '../../use-moving-animation';
19
19
  import { PrivateBlockContext } from '../private-block-context';
20
20
  import { useFocusFirstElement } from './use-focus-first-element';
21
21
  import { useIsHovered } from './use-is-hovered';
22
- import { useBlockEditContext } from '../../block-edit/context';
22
+ import {
23
+ blockBindingsKey,
24
+ useBlockEditContext,
25
+ } from '../../block-edit/context';
23
26
  import { useFocusHandler } from './use-focus-handler';
24
27
  import { useEventHandlers } from './use-selected-block-event-handlers';
25
28
  import { useNavModeExit } from './use-nav-mode-exit';
26
29
  import { useBlockRefProvider } from './use-block-refs';
27
30
  import { useIntersectionObserver } from './use-intersection-observer';
28
31
  import { useFlashEditableBlocks } from '../../use-flash-editable-blocks';
32
+ import { canBindBlock } from '../../../hooks/use-bindings-attributes';
29
33
 
30
34
  /**
31
35
  * This hook is used to lightly mark an element as a block element. The element
@@ -123,6 +127,12 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
123
127
  ] );
124
128
 
125
129
  const blockEditContext = useBlockEditContext();
130
+ const hasBlockBindings = !! blockEditContext[ blockBindingsKey ];
131
+ const bindingsStyle =
132
+ hasBlockBindings && canBindBlock( name )
133
+ ? { '--wp-admin-theme-color': 'var(--wp-bound-block-color)' }
134
+ : {};
135
+
126
136
  // Ensures it warns only inside the `edit` implementation for the block.
127
137
  if ( blockApiVersion < 2 && clientId === blockEditContext.clientId ) {
128
138
  warning(
@@ -168,7 +178,7 @@ export function useBlockProps( props = {}, { __unstableIsHtml } = {} ) {
168
178
  wrapperProps.className,
169
179
  defaultClassName
170
180
  ),
171
- style: { ...wrapperProps.style, ...props.style },
181
+ style: { ...wrapperProps.style, ...props.style, ...bindingsStyle },
172
182
  };
173
183
  }
174
184
 
@@ -22,7 +22,7 @@ import { store as blockEditorStore } from '../../../store';
22
22
  export function useEventHandlers( { clientId, isSelected } ) {
23
23
  const { getBlockRootClientId, getBlockIndex } =
24
24
  useSelect( blockEditorStore );
25
- const { insertDefaultBlock, removeBlock } = useDispatch( blockEditorStore );
25
+ const { insertAfterBlock, removeBlock } = useDispatch( blockEditorStore );
26
26
 
27
27
  return useRefEffect(
28
28
  ( node ) => {
@@ -57,11 +57,7 @@ export function useEventHandlers( { clientId, isSelected } ) {
57
57
  event.preventDefault();
58
58
 
59
59
  if ( keyCode === ENTER ) {
60
- insertDefaultBlock(
61
- {},
62
- getBlockRootClientId( clientId ),
63
- getBlockIndex( clientId ) + 1
64
- );
60
+ insertAfterBlock( clientId );
65
61
  } else {
66
62
  removeBlock( clientId );
67
63
  }
@@ -90,7 +86,7 @@ export function useEventHandlers( { clientId, isSelected } ) {
90
86
  isSelected,
91
87
  getBlockRootClientId,
92
88
  getBlockIndex,
93
- insertDefaultBlock,
89
+ insertAfterBlock,
94
90
  removeBlock,
95
91
  ]
96
92
  );
@@ -39,8 +39,12 @@ const POPOVER_PROPS = {
39
39
  placement: 'bottom-start',
40
40
  };
41
41
 
42
- function CopyMenuItem( { blocks, onCopy, label } ) {
43
- const ref = useCopyToClipboard( () => serialize( blocks ), onCopy );
42
+ function CopyMenuItem( { clientIds, onCopy, label } ) {
43
+ const { getBlocksByClientId } = useSelect( blockEditorStore );
44
+ const ref = useCopyToClipboard(
45
+ () => serialize( getBlocksByClientId( clientIds ) ),
46
+ onCopy
47
+ );
44
48
  const copyMenuItemLabel = label ? label : __( 'Copy' );
45
49
  return <MenuItem ref={ ref }>{ copyMenuItemLabel }</MenuItem>;
46
50
  }
@@ -239,7 +243,7 @@ export function BlockSettingsDropdown( {
239
243
  { ( {
240
244
  canCopyStyles,
241
245
  canDuplicate,
242
- canInsertDefaultBlock,
246
+ canInsertBlock,
243
247
  canMove,
244
248
  canRemove,
245
249
  onDuplicate,
@@ -249,7 +253,6 @@ export function BlockSettingsDropdown( {
249
253
  onCopy,
250
254
  onPasteStyles,
251
255
  onMoveTo,
252
- blocks,
253
256
  } ) => (
254
257
  <DropdownMenu
255
258
  icon={ moreVertical }
@@ -286,7 +289,7 @@ export function BlockSettingsDropdown( {
286
289
  'core/block-editor/insert-after',
287
290
  event
288
291
  ) &&
289
- canInsertDefaultBlock
292
+ canInsertBlock
290
293
  ) {
291
294
  event.preventDefault();
292
295
  setOpenedBlockSettingsMenu( undefined );
@@ -296,7 +299,7 @@ export function BlockSettingsDropdown( {
296
299
  'core/block-editor/insert-before',
297
300
  event
298
301
  ) &&
299
- canInsertDefaultBlock
302
+ canInsertBlock
300
303
  ) {
301
304
  event.preventDefault();
302
305
  setOpenedBlockSettingsMenu( undefined );
@@ -327,7 +330,7 @@ export function BlockSettingsDropdown( {
327
330
  />
328
331
  ) }
329
332
  <CopyMenuItem
330
- blocks={ blocks }
333
+ clientIds={ clientIds }
331
334
  onCopy={ onCopy }
332
335
  />
333
336
  { canDuplicate && (
@@ -342,7 +345,7 @@ export function BlockSettingsDropdown( {
342
345
  { __( 'Duplicate' ) }
343
346
  </MenuItem>
344
347
  ) }
345
- { canInsertDefaultBlock && (
348
+ { canInsertBlock && (
346
349
  <>
347
350
  <MenuItem
348
351
  onClick={ pipe(
@@ -368,7 +371,7 @@ export function BlockSettingsDropdown( {
368
371
  { canCopyStyles && (
369
372
  <MenuGroup>
370
373
  <CopyMenuItem
371
- blocks={ blocks }
374
+ clientIds={ clientIds }
372
375
  onCopy={ onCopy }
373
376
  label={ __( 'Copy styles' ) }
374
377
  />
@@ -35,6 +35,8 @@ import { store as blockEditorStore } from '../../store';
35
35
  import __unstableBlockNameContext from './block-name-context';
36
36
  import NavigableToolbar from '../navigable-toolbar';
37
37
  import { useHasAnyBlockControls } from '../block-controls/use-has-block-controls';
38
+ import BlockBindingsIndicator from '../block-bindings-toolbar-indicator';
39
+ import { canBindBlock } from '../../hooks/use-bindings-attributes';
38
40
 
39
41
  /**
40
42
  * Renders the block toolbar.
@@ -60,8 +62,10 @@ export function PrivateBlockToolbar( {
60
62
  blockClientIds,
61
63
  isDefaultEditingMode,
62
64
  blockType,
65
+ blockName,
63
66
  shouldShowVisualToolbar,
64
67
  showParentSelector,
68
+ isUsingBindings,
65
69
  } = useSelect( ( select ) => {
66
70
  const {
67
71
  getBlockName,
@@ -71,6 +75,7 @@ export function PrivateBlockToolbar( {
71
75
  isBlockValid,
72
76
  getBlockRootClientId,
73
77
  getBlockEditingMode,
78
+ getBlockAttributes,
74
79
  } = select( blockEditorStore );
75
80
  const selectedBlockClientIds = getSelectedBlockClientIds();
76
81
  const selectedBlockClientId = selectedBlockClientIds[ 0 ];
@@ -81,20 +86,21 @@ export function PrivateBlockToolbar( {
81
86
  const parentBlockType = getBlockType( parentBlockName );
82
87
  const _isDefaultEditingMode =
83
88
  getBlockEditingMode( selectedBlockClientId ) === 'default';
89
+ const _blockName = getBlockName( selectedBlockClientId );
84
90
  const isValid = selectedBlockClientIds.every( ( id ) =>
85
91
  isBlockValid( id )
86
92
  );
87
93
  const isVisual = selectedBlockClientIds.every(
88
94
  ( id ) => getBlockMode( id ) === 'visual'
89
95
  );
96
+ const _isUsingBindings = !! getBlockAttributes( selectedBlockClientId )
97
+ ?.metadata?.bindings;
90
98
  return {
91
99
  blockClientId: selectedBlockClientId,
92
100
  blockClientIds: selectedBlockClientIds,
93
101
  isDefaultEditingMode: _isDefaultEditingMode,
94
- blockType:
95
- selectedBlockClientId &&
96
- getBlockType( getBlockName( selectedBlockClientId ) ),
97
-
102
+ blockName: _blockName,
103
+ blockType: selectedBlockClientId && getBlockType( _blockName ),
98
104
  shouldShowVisualToolbar: isValid && isVisual,
99
105
  rootClientId: blockRootClientId,
100
106
  showParentSelector:
@@ -107,6 +113,7 @@ export function PrivateBlockToolbar( {
107
113
  ) &&
108
114
  selectedBlockClientIds.length === 1 &&
109
115
  _isDefaultEditingMode,
116
+ isUsingBindings: _isUsingBindings,
110
117
  };
111
118
  }, [] );
112
119
 
@@ -165,6 +172,9 @@ export function PrivateBlockToolbar( {
165
172
  { ! isMultiToolbar &&
166
173
  isLargeViewport &&
167
174
  isDefaultEditingMode && <BlockParentSelector /> }
175
+ { isUsingBindings && canBindBlock( blockName ) && (
176
+ <BlockBindingsIndicator />
177
+ ) }
168
178
  { ( shouldShowVisualToolbar || isMultiToolbar ) &&
169
179
  isDefaultEditingMode && (
170
180
  <div
@@ -1194,15 +1194,13 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) {
1194
1194
 
1195
1195
  const isTemplate = blockContext?.templateSlug !== undefined;
1196
1196
 
1197
- const getBlockStyles = useSelect( ( select ) => {
1198
- return select( blocksStore ).getBlockStyles;
1199
- }, [] );
1197
+ const { getBlockStyles } = useSelect( blocksStore );
1200
1198
 
1201
1199
  return useMemo( () => {
1202
1200
  if ( ! mergedConfig?.styles || ! mergedConfig?.settings ) {
1203
1201
  return [];
1204
1202
  }
1205
- mergedConfig = updateConfigWithSeparator( mergedConfig );
1203
+ const updatedConfig = updateConfigWithSeparator( mergedConfig );
1206
1204
 
1207
1205
  const blockSelectors = getBlockSelectors(
1208
1206
  getBlockTypes(),
@@ -1210,18 +1208,18 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) {
1210
1208
  );
1211
1209
 
1212
1210
  const customProperties = toCustomProperties(
1213
- mergedConfig,
1211
+ updatedConfig,
1214
1212
  blockSelectors
1215
1213
  );
1216
1214
  const globalStyles = toStyles(
1217
- mergedConfig,
1215
+ updatedConfig,
1218
1216
  blockSelectors,
1219
1217
  hasBlockGapSupport,
1220
1218
  hasFallbackGapSupport,
1221
1219
  disableLayoutStyles,
1222
1220
  isTemplate
1223
1221
  );
1224
- const svgs = toSvgFilters( mergedConfig, blockSelectors );
1222
+ const svgs = toSvgFilters( updatedConfig, blockSelectors );
1225
1223
 
1226
1224
  const styles = [
1227
1225
  {
@@ -1234,7 +1232,7 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) {
1234
1232
  },
1235
1233
  // Load custom CSS in own stylesheet so that any invalid CSS entered in the input won't break all the global styles in the editor.
1236
1234
  {
1237
- css: mergedConfig.styles.css ?? '',
1235
+ css: updatedConfig.styles.css ?? '',
1238
1236
  isGlobalStyles: true,
1239
1237
  },
1240
1238
  {
@@ -1248,11 +1246,11 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) {
1248
1246
  // If there are, get the block selector and push the selector together with
1249
1247
  // the CSS value to the 'stylesheets' array.
1250
1248
  getBlockTypes().forEach( ( blockType ) => {
1251
- if ( mergedConfig.styles.blocks[ blockType.name ]?.css ) {
1249
+ if ( updatedConfig.styles.blocks[ blockType.name ]?.css ) {
1252
1250
  const selector = blockSelectors[ blockType.name ].selector;
1253
1251
  styles.push( {
1254
1252
  css: processCSSNesting(
1255
- mergedConfig.styles.blocks[ blockType.name ]?.css,
1253
+ updatedConfig.styles.blocks[ blockType.name ]?.css,
1256
1254
  selector
1257
1255
  ),
1258
1256
  isGlobalStyles: true,
@@ -1260,12 +1258,14 @@ export function useGlobalStylesOutputWithConfig( mergedConfig = {} ) {
1260
1258
  }
1261
1259
  } );
1262
1260
 
1263
- return [ styles, mergedConfig.settings ];
1261
+ return [ styles, updatedConfig.settings ];
1264
1262
  }, [
1265
1263
  hasBlockGapSupport,
1266
1264
  hasFallbackGapSupport,
1267
1265
  mergedConfig,
1268
1266
  disableLayoutStyles,
1267
+ isTemplate,
1268
+ getBlockStyles,
1269
1269
  ] );
1270
1270
  }
1271
1271
 
@@ -14,7 +14,12 @@ import {
14
14
  Tooltip,
15
15
  } from '@wordpress/components';
16
16
  import { forwardRef } from '@wordpress/element';
17
- import { Icon, lockSmall as lock, pinSmall } from '@wordpress/icons';
17
+ import {
18
+ Icon,
19
+ connection,
20
+ lockSmall as lock,
21
+ pinSmall,
22
+ } from '@wordpress/icons';
18
23
  import { SPACE, ENTER, BACKSPACE, DELETE } from '@wordpress/keycodes';
19
24
  import { useSelect, useDispatch } from '@wordpress/data';
20
25
  import { __unstableUseShortcutEventMatch as useShortcutEventMatch } from '@wordpress/keyboard-shortcuts';
@@ -32,11 +37,12 @@ import { useBlockLock } from '../block-lock';
32
37
  import { store as blockEditorStore } from '../../store';
33
38
  import useListViewImages from './use-list-view-images';
34
39
  import { useListViewContext } from './context';
40
+ import { canBindBlock } from '../../hooks/use-bindings-attributes';
35
41
 
36
42
  function ListViewBlockSelectButton(
37
43
  {
38
44
  className,
39
- block: { clientId },
45
+ block: { clientId, name: blockName },
40
46
  onClick,
41
47
  onContextMenu,
42
48
  onMouseDown,
@@ -66,6 +72,7 @@ function ListViewBlockSelectButton(
66
72
  getBlockRootClientId,
67
73
  getBlockOrder,
68
74
  getBlocksByClientId,
75
+ getBlockAttributes,
69
76
  canRemoveBlocks,
70
77
  } = useSelect( blockEditorStore );
71
78
  const { duplicateBlocks, multiSelect, removeBlocks } =
@@ -75,6 +82,8 @@ function ListViewBlockSelectButton(
75
82
  const images = useListViewImages( { clientId, isExpanded } );
76
83
  const { rootClientId } = useListViewContext();
77
84
 
85
+ const isConnected = getBlockAttributes( clientId )?.metadata?.bindings;
86
+
78
87
  const positionLabel = blockInformation?.positionLabel
79
88
  ? sprintf(
80
89
  // translators: 1: Position of selected block, e.g. "Sticky" or "Fixed".
@@ -278,6 +287,11 @@ function ListViewBlockSelectButton(
278
287
  </Truncate>
279
288
  </span>
280
289
  ) }
290
+ { isConnected && canBindBlock( blockName ) && (
291
+ <span className="block-editor-list-view-block-select-button__bindings">
292
+ <Icon icon={ connection } />
293
+ </span>
294
+ ) }
281
295
  { positionLabel && isSticky && (
282
296
  <Tooltip text={ positionLabel }>
283
297
  <Icon icon={ pinSmall } />
@@ -557,3 +557,11 @@ $block-navigation-max-indent: 8;
557
557
  .list-view-appender__description {
558
558
  display: none;
559
559
  }
560
+
561
+ .block-editor-list-view-block-select-button__bindings svg g {
562
+ stroke: var(--wp-bound-block-color);
563
+ fill: transparent;
564
+ stroke-width: 1.5;
565
+ stroke-linecap: round;
566
+ stroke-linejoin: round;
567
+ }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { useDispatch, useSelect } from '@wordpress/data';
4
+ import { useDispatch, useRegistry, useSelect } from '@wordpress/data';
5
5
  import { useRefEffect } from '@wordpress/compose';
6
6
 
7
7
  /**
@@ -15,6 +15,7 @@ import { getPasteBlocks, setClipboardBlocks } from '../writing-flow/utils';
15
15
  // This hook borrows from useClipboardHandler in ../writing-flow/use-clipboard-handler.js
16
16
  // and adds behaviour for the list view, while skipping partial selection.
17
17
  export default function useClipboardHandler( { selectBlock } ) {
18
+ const registry = useRegistry();
18
19
  const {
19
20
  getBlockOrder,
20
21
  getBlockRootClientId,
@@ -106,7 +107,7 @@ export default function useClipboardHandler( { selectBlock } ) {
106
107
 
107
108
  notifyCopy( event.type, selectedBlockClientIds );
108
109
  const blocks = getBlocksByClientId( selectedBlockClientIds );
109
- setClipboardBlocks( event, blocks );
110
+ setClipboardBlocks( event, blocks, registry );
110
111
  }
111
112
 
112
113
  if ( event.type === 'cut' ) {
@@ -47,7 +47,7 @@ import { getAllowedFormats } from './utils';
47
47
  import { Content } from './content';
48
48
  import { withDeprecations } from './with-deprecations';
49
49
  import { unlock } from '../../lock-unlock';
50
- import { BLOCK_BINDINGS_ALLOWED_BLOCKS } from '../../hooks/use-bindings-attributes';
50
+ import { canBindBlock } from '../../hooks/use-bindings-attributes';
51
51
 
52
52
  export const keyboardShortcutContext = createContext();
53
53
  export const inputEventContext = createContext();
@@ -161,7 +161,7 @@ export function RichTextWrapper(
161
161
  ( select ) => {
162
162
  // Disable Rich Text editing if block bindings specify that.
163
163
  let _disableBoundBlocks = false;
164
- if ( blockBindings && blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS ) {
164
+ if ( blockBindings && canBindBlock( blockName ) ) {
165
165
  const blockTypeAttributes =
166
166
  getBlockType( blockName ).attributes;
167
167
  const { getBlockBindingsSource } = unlock(
@@ -92,12 +92,12 @@ const URLPopover = forwardRef(
92
92
  />
93
93
  ) }
94
94
  </div>
95
- { showSettings && (
96
- <div className="block-editor-url-popover__row block-editor-url-popover__settings">
97
- { renderSettings() }
98
- </div>
99
- ) }
100
95
  </div>
96
+ { showSettings && (
97
+ <div className="block-editor-url-popover__settings">
98
+ { renderSettings() }
99
+ </div>
100
+ ) }
101
101
  { additionalControls && ! showSettings && (
102
102
  <div className="block-editor-url-popover__additional-controls">
103
103
  { additionalControls }
@@ -142,6 +142,7 @@ function useMovingAnimation( { triggerAnimationOnChange, clientId } ) {
142
142
 
143
143
  return () => {
144
144
  controller.stop();
145
+ controller.set( { x: 0, y: 0 } );
145
146
  };
146
147
  }, [
147
148
  previous,