@wordpress/block-editor 12.19.3 → 12.19.5

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 (165) 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-edit/context.js +2 -1
  6. package/build/components/block-edit/context.js.map +1 -1
  7. package/build/components/block-edit/index.js +8 -3
  8. package/build/components/block-edit/index.js.map +1 -1
  9. package/build/components/block-inspector/index.js +5 -4
  10. package/build/components/block-inspector/index.js.map +1 -1
  11. package/build/components/block-list/use-block-props/index.js +8 -1
  12. package/build/components/block-list/use-block-props/index.js.map +1 -1
  13. package/build/components/block-list/use-block-props/use-selected-block-event-handlers.js +3 -3
  14. package/build/components/block-list/use-block-props/use-selected-block-event-handlers.js.map +1 -1
  15. package/build/components/block-preview/index.js +4 -0
  16. package/build/components/block-preview/index.js.map +1 -1
  17. package/build/components/block-settings-menu/block-settings-dropdown.js +12 -10
  18. package/build/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  19. package/build/components/block-toolbar/index.js +14 -5
  20. package/build/components/block-toolbar/index.js.map +1 -1
  21. package/build/components/global-styles/border-panel.js +21 -8
  22. package/build/components/global-styles/border-panel.js.map +1 -1
  23. package/build/components/global-styles/index.js +6 -0
  24. package/build/components/global-styles/index.js.map +1 -1
  25. package/build/components/global-styles/shadow-panel-components.js +80 -23
  26. package/build/components/global-styles/shadow-panel-components.js.map +1 -1
  27. package/build/components/inspector-controls-tabs/styles-tab.js +1 -1
  28. package/build/components/inspector-controls-tabs/styles-tab.js.map +1 -1
  29. package/build/components/link-control/link-preview.js +4 -1
  30. package/build/components/link-control/link-preview.js.map +1 -1
  31. package/build/components/list-view/block-select-button.js +10 -2
  32. package/build/components/list-view/block-select-button.js.map +1 -1
  33. package/build/components/list-view/use-clipboard-handler.js +2 -1
  34. package/build/components/list-view/use-clipboard-handler.js.map +1 -1
  35. package/build/components/rich-text/index.js +46 -26
  36. package/build/components/rich-text/index.js.map +1 -1
  37. package/build/components/rich-text/use-enter.js +3 -0
  38. package/build/components/rich-text/use-enter.js.map +1 -1
  39. package/build/components/url-popover/index.js +3 -3
  40. package/build/components/url-popover/index.js.map +1 -1
  41. package/build/components/writing-flow/use-clipboard-handler.js +2 -1
  42. package/build/components/writing-flow/use-clipboard-handler.js.map +1 -1
  43. package/build/components/writing-flow/utils.js +23 -6
  44. package/build/components/writing-flow/utils.js.map +1 -1
  45. package/build/hooks/block-hooks.js +34 -8
  46. package/build/hooks/block-hooks.js.map +1 -1
  47. package/build/hooks/border.js +6 -4
  48. package/build/hooks/border.js.map +1 -1
  49. package/build/hooks/use-bindings-attributes.js +171 -48
  50. package/build/hooks/use-bindings-attributes.js.map +1 -1
  51. package/build/private-apis.js +5 -1
  52. package/build/private-apis.js.map +1 -1
  53. package/build/store/actions.js +40 -6
  54. package/build/store/actions.js.map +1 -1
  55. package/build/store/private-actions.js +0 -10
  56. package/build/store/private-actions.js.map +1 -1
  57. package/build/store/private-selectors.js +0 -8
  58. package/build/store/private-selectors.js.map +1 -1
  59. package/build/store/reducer.js +1 -16
  60. package/build/store/reducer.js.map +1 -1
  61. package/build-module/components/block-actions/index.js +45 -32
  62. package/build-module/components/block-actions/index.js.map +1 -1
  63. package/build-module/components/block-bindings-toolbar-indicator/index.js +18 -0
  64. package/build-module/components/block-bindings-toolbar-indicator/index.js.map +1 -0
  65. package/build-module/components/block-edit/context.js +1 -0
  66. package/build-module/components/block-edit/context.js.map +1 -1
  67. package/build-module/components/block-edit/index.js +9 -4
  68. package/build-module/components/block-edit/index.js.map +1 -1
  69. package/build-module/components/block-inspector/index.js +6 -5
  70. package/build-module/components/block-inspector/index.js.map +1 -1
  71. package/build-module/components/block-list/use-block-props/index.js +9 -2
  72. package/build-module/components/block-list/use-block-props/index.js.map +1 -1
  73. package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.js +3 -3
  74. package/build-module/components/block-list/use-block-props/use-selected-block-event-handlers.js.map +1 -1
  75. package/build-module/components/block-preview/index.js +4 -0
  76. package/build-module/components/block-preview/index.js.map +1 -1
  77. package/build-module/components/block-settings-menu/block-settings-dropdown.js +12 -10
  78. package/build-module/components/block-settings-menu/block-settings-dropdown.js.map +1 -1
  79. package/build-module/components/block-toolbar/index.js +14 -5
  80. package/build-module/components/block-toolbar/index.js.map +1 -1
  81. package/build-module/components/global-styles/border-panel.js +22 -10
  82. package/build-module/components/global-styles/border-panel.js.map +1 -1
  83. package/build-module/components/global-styles/index.js +1 -1
  84. package/build-module/components/global-styles/index.js.map +1 -1
  85. package/build-module/components/global-styles/shadow-panel-components.js +82 -24
  86. package/build-module/components/global-styles/shadow-panel-components.js.map +1 -1
  87. package/build-module/components/inspector-controls-tabs/styles-tab.js +2 -2
  88. package/build-module/components/inspector-controls-tabs/styles-tab.js.map +1 -1
  89. package/build-module/components/link-control/link-preview.js +5 -2
  90. package/build-module/components/link-control/link-preview.js.map +1 -1
  91. package/build-module/components/list-view/block-select-button.js +11 -3
  92. package/build-module/components/list-view/block-select-button.js.map +1 -1
  93. package/build-module/components/list-view/use-clipboard-handler.js +3 -2
  94. package/build-module/components/list-view/use-clipboard-handler.js.map +1 -1
  95. package/build-module/components/rich-text/index.js +47 -28
  96. package/build-module/components/rich-text/index.js.map +1 -1
  97. package/build-module/components/rich-text/use-enter.js +3 -0
  98. package/build-module/components/rich-text/use-enter.js.map +1 -1
  99. package/build-module/components/url-popover/index.js +3 -3
  100. package/build-module/components/url-popover/index.js.map +1 -1
  101. package/build-module/components/writing-flow/use-clipboard-handler.js +3 -2
  102. package/build-module/components/writing-flow/use-clipboard-handler.js.map +1 -1
  103. package/build-module/components/writing-flow/utils.js +22 -7
  104. package/build-module/components/writing-flow/utils.js.map +1 -1
  105. package/build-module/hooks/block-hooks.js +34 -8
  106. package/build-module/hooks/block-hooks.js.map +1 -1
  107. package/build-module/hooks/border.js +7 -5
  108. package/build-module/hooks/border.js.map +1 -1
  109. package/build-module/hooks/use-bindings-attributes.js +172 -49
  110. package/build-module/hooks/use-bindings-attributes.js.map +1 -1
  111. package/build-module/private-apis.js +5 -1
  112. package/build-module/private-apis.js.map +1 -1
  113. package/build-module/store/actions.js +40 -6
  114. package/build-module/store/actions.js.map +1 -1
  115. package/build-module/store/private-actions.js +0 -9
  116. package/build-module/store/private-actions.js.map +1 -1
  117. package/build-module/store/private-selectors.js +0 -6
  118. package/build-module/store/private-selectors.js.map +1 -1
  119. package/build-module/store/reducer.js +1 -16
  120. package/build-module/store/reducer.js.map +1 -1
  121. package/build-style/content-rtl.css +1 -0
  122. package/build-style/content.css +1 -0
  123. package/build-style/default-editor-styles-rtl.css +1 -0
  124. package/build-style/default-editor-styles.css +1 -0
  125. package/build-style/style-rtl.css +70 -14
  126. package/build-style/style.css +70 -14
  127. package/package.json +8 -8
  128. package/src/components/block-actions/index.js +57 -47
  129. package/src/components/block-bindings-toolbar-indicator/index.js +20 -0
  130. package/src/components/block-bindings-toolbar-indicator/style.scss +14 -0
  131. package/src/components/block-edit/context.js +1 -0
  132. package/src/components/block-edit/index.js +5 -1
  133. package/src/components/block-inspector/index.js +7 -5
  134. package/src/components/block-list/use-block-props/index.js +12 -2
  135. package/src/components/block-list/use-block-props/use-selected-block-event-handlers.js +3 -7
  136. package/src/components/block-preview/index.js +6 -1
  137. package/src/components/block-settings-menu/block-settings-dropdown.js +12 -9
  138. package/src/components/block-toolbar/index.js +14 -4
  139. package/src/components/block-toolbar/style.scss +11 -6
  140. package/src/components/global-styles/border-panel.js +33 -22
  141. package/src/components/global-styles/index.js +5 -1
  142. package/src/components/global-styles/shadow-panel-components.js +92 -23
  143. package/src/components/global-styles/style.scss +33 -10
  144. package/src/components/inspector-controls-tabs/styles-tab.js +2 -2
  145. package/src/components/link-control/link-preview.js +9 -2
  146. package/src/components/link-control/style.scss +9 -0
  147. package/src/components/list-view/block-select-button.js +16 -2
  148. package/src/components/list-view/style.scss +8 -0
  149. package/src/components/list-view/use-clipboard-handler.js +3 -2
  150. package/src/components/rich-text/index.js +75 -52
  151. package/src/components/rich-text/use-enter.js +4 -0
  152. package/src/components/url-popover/index.js +5 -5
  153. package/src/components/url-popover/style.scss +1 -0
  154. package/src/components/writing-flow/use-clipboard-handler.js +3 -2
  155. package/src/components/writing-flow/utils.js +31 -16
  156. package/src/hooks/block-hooks.js +46 -8
  157. package/src/hooks/block-hooks.scss +6 -0
  158. package/src/hooks/border.js +16 -4
  159. package/src/hooks/use-bindings-attributes.js +215 -65
  160. package/src/private-apis.js +4 -0
  161. package/src/store/actions.js +54 -14
  162. package/src/store/private-actions.js +0 -10
  163. package/src/store/private-selectors.js +0 -8
  164. package/src/store/reducer.js +0 -15
  165. package/src/style.scss +1 -0
@@ -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' ) {
@@ -19,13 +19,14 @@ import {
19
19
  removeFormat,
20
20
  } from '@wordpress/rich-text';
21
21
  import { Popover } from '@wordpress/components';
22
- import { getBlockType } from '@wordpress/blocks';
22
+ import { getBlockType, store as blocksStore } from '@wordpress/blocks';
23
23
 
24
24
  /**
25
25
  * Internal dependencies
26
26
  */
27
27
  import { useBlockEditorAutocompleteProps } from '../autocomplete';
28
28
  import { useBlockEditContext } from '../block-edit';
29
+ import { blockBindingsKey } from '../block-edit/context';
29
30
  import FormatToolbarContainer from './format-toolbar-container';
30
31
  import { store as blockEditorStore } from '../../store';
31
32
  import { useUndoAutomaticChange } from './use-undo-automatic-change';
@@ -46,7 +47,7 @@ import { getAllowedFormats } from './utils';
46
47
  import { Content } from './content';
47
48
  import { withDeprecations } from './with-deprecations';
48
49
  import { unlock } from '../../lock-unlock';
49
- import { BLOCK_BINDINGS_ALLOWED_BLOCKS } from '../../hooks/use-bindings-attributes';
50
+ import { canBindBlock } from '../../hooks/use-bindings-attributes';
50
51
 
51
52
  export const keyboardShortcutContext = createContext();
52
53
  export const inputEventContext = createContext();
@@ -109,6 +110,7 @@ export function RichTextWrapper(
109
110
  __unstableDisableFormats: disableFormats,
110
111
  disableLineBreaks,
111
112
  __unstableAllowPrefixTransformations,
113
+ disableEditing,
112
114
  ...props
113
115
  },
114
116
  forwardedRef
@@ -116,11 +118,9 @@ export function RichTextWrapper(
116
118
  props = removeNativeProps( props );
117
119
 
118
120
  const anchorRef = useRef();
119
- const {
120
- clientId,
121
- isSelected: isBlockSelected,
122
- name: blockName,
123
- } = useBlockEditContext();
121
+ const context = useBlockEditContext();
122
+ const { clientId, isSelected: isBlockSelected, name: blockName } = context;
123
+ const blockBindings = context[ blockBindingsKey ];
124
124
  const selector = ( select ) => {
125
125
  // Avoid subscribing to the block editor store if the block is not
126
126
  // selected.
@@ -128,12 +128,10 @@ export function RichTextWrapper(
128
128
  return { isSelected: false };
129
129
  }
130
130
 
131
- const { getSelectionStart, getSelectionEnd, getBlockAttributes } =
131
+ const { getSelectionStart, getSelectionEnd } =
132
132
  select( blockEditorStore );
133
133
  const selectionStart = getSelectionStart();
134
134
  const selectionEnd = getSelectionEnd();
135
- const blockBindings =
136
- getBlockAttributes( clientId )?.metadata?.bindings;
137
135
 
138
136
  let isSelected;
139
137
 
@@ -146,50 +144,60 @@ export function RichTextWrapper(
146
144
  isSelected = selectionStart.clientId === clientId;
147
145
  }
148
146
 
149
- // Disable Rich Text editing if block bindings specify that.
150
- let shouldDisableEditing = false;
151
- if ( blockBindings && blockName in BLOCK_BINDINGS_ALLOWED_BLOCKS ) {
152
- const blockTypeAttributes = getBlockType( blockName ).attributes;
153
- const { getBlockBindingsSource } = unlock(
154
- select( blockEditorStore )
155
- );
156
- for ( const [ attribute, args ] of Object.entries(
157
- blockBindings
158
- ) ) {
159
- if (
160
- blockTypeAttributes?.[ attribute ]?.source !== 'rich-text'
161
- ) {
162
- break;
163
- }
164
-
165
- // If the source is not defined, or if its value of `lockAttributesEditing` is `true`, disable it.
166
- const blockBindingsSource = getBlockBindingsSource(
167
- args.source
168
- );
169
- if (
170
- ! blockBindingsSource ||
171
- blockBindingsSource.lockAttributesEditing
172
- ) {
173
- shouldDisableEditing = true;
174
- break;
175
- }
176
- }
177
- }
178
-
179
147
  return {
180
148
  selectionStart: isSelected ? selectionStart.offset : undefined,
181
149
  selectionEnd: isSelected ? selectionEnd.offset : undefined,
182
150
  isSelected,
183
- shouldDisableEditing,
184
151
  };
185
152
  };
186
- const { selectionStart, selectionEnd, isSelected, shouldDisableEditing } =
187
- useSelect( selector, [
188
- clientId,
189
- identifier,
190
- originalIsSelected,
191
- isBlockSelected,
192
- ] );
153
+ const { selectionStart, selectionEnd, isSelected } = useSelect( selector, [
154
+ clientId,
155
+ identifier,
156
+ originalIsSelected,
157
+ isBlockSelected,
158
+ ] );
159
+
160
+ const disableBoundBlocks = useSelect(
161
+ ( select ) => {
162
+ // Disable Rich Text editing if block bindings specify that.
163
+ let _disableBoundBlocks = false;
164
+ if ( blockBindings && canBindBlock( blockName ) ) {
165
+ const blockTypeAttributes =
166
+ getBlockType( blockName ).attributes;
167
+ const { getBlockBindingsSource } = unlock(
168
+ select( blocksStore )
169
+ );
170
+ for ( const [ attribute, args ] of Object.entries(
171
+ blockBindings
172
+ ) ) {
173
+ if (
174
+ blockTypeAttributes?.[ attribute ]?.source !==
175
+ 'rich-text'
176
+ ) {
177
+ break;
178
+ }
179
+
180
+ // If the source is not defined, or if its value of `lockAttributesEditing` is `true`, disable it.
181
+ const blockBindingsSource = getBlockBindingsSource(
182
+ args.source
183
+ );
184
+ if (
185
+ ! blockBindingsSource ||
186
+ blockBindingsSource.lockAttributesEditing
187
+ ) {
188
+ _disableBoundBlocks = true;
189
+ break;
190
+ }
191
+ }
192
+ }
193
+
194
+ return _disableBoundBlocks;
195
+ },
196
+ [ blockBindings, blockName ]
197
+ );
198
+
199
+ const shouldDisableEditing = disableEditing || disableBoundBlocks;
200
+
193
201
  const { getSelectionStart, getSelectionEnd, getBlockRootClientId } =
194
202
  useSelect( blockEditorStore );
195
203
  const { selectionChange } = useDispatch( blockEditorStore );
@@ -442,19 +450,34 @@ export function RichTextWrapper(
442
450
  );
443
451
  }
444
452
 
445
- const ForwardedRichTextContainer = withDeprecations(
453
+ // This is the private API for the RichText component.
454
+ // It allows access to all props, not just the public ones.
455
+ export const PrivateRichText = withDeprecations(
446
456
  forwardRef( RichTextWrapper )
447
457
  );
448
458
 
449
- ForwardedRichTextContainer.Content = Content;
450
- ForwardedRichTextContainer.isEmpty = ( value ) => {
459
+ PrivateRichText.Content = Content;
460
+ PrivateRichText.isEmpty = ( value ) => {
451
461
  return ! value || value.length === 0;
452
462
  };
453
463
 
464
+ // This is the public API for the RichText component.
465
+ // We wrap the PrivateRichText component to hide some props from the public API.
454
466
  /**
455
467
  * @see https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/rich-text/README.md
456
468
  */
457
- export default ForwardedRichTextContainer;
469
+ const PublicForwardedRichTextContainer = forwardRef( ( props, ref ) => {
470
+ return (
471
+ <PrivateRichText ref={ ref } { ...props } disableEditing={ false } />
472
+ );
473
+ } );
474
+
475
+ PublicForwardedRichTextContainer.Content = Content;
476
+ PublicForwardedRichTextContainer.isEmpty = ( value ) => {
477
+ return ! value || value.length === 0;
478
+ };
479
+
480
+ export default PublicForwardedRichTextContainer;
458
481
  export { RichTextShortcut } from './shortcut';
459
482
  export { RichTextToolbarButton } from './toolbar-button';
460
483
  export { __unstableRichTextInputEvent } from './input-event';
@@ -21,6 +21,10 @@ export function useEnter( props ) {
21
21
  propsRef.current = props;
22
22
  return useRefEffect( ( element ) => {
23
23
  function onKeyDown( event ) {
24
+ if ( event.target.contentEditable !== 'true' ) {
25
+ return;
26
+ }
27
+
24
28
  if ( event.defaultPrevented ) {
25
29
  return;
26
30
  }
@@ -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 }
@@ -58,6 +58,7 @@
58
58
  text-overflow: ellipsis;
59
59
  white-space: nowrap;
60
60
  margin-right: $grid-unit-10;
61
+ min-width: 150px;
61
62
  // Avoids the popover from growing too wide when the URL is long.
62
63
  // See https://github.com/WordPress/gutenberg/issues/58599
63
64
  max-width: $modal-min-width;
@@ -5,7 +5,7 @@ import {
5
5
  documentHasSelection,
6
6
  documentHasUncollapsedSelection,
7
7
  } from '@wordpress/dom';
8
- import { useDispatch, useSelect } from '@wordpress/data';
8
+ import { useDispatch, useRegistry, useSelect } from '@wordpress/data';
9
9
  import { useRefEffect } from '@wordpress/compose';
10
10
 
11
11
  /**
@@ -16,6 +16,7 @@ import { useNotifyCopy } from '../../utils/use-notify-copy';
16
16
  import { getPasteBlocks, setClipboardBlocks } from './utils';
17
17
 
18
18
  export default function useClipboardHandler() {
19
+ const registry = useRegistry();
19
20
  const {
20
21
  getBlocksByClientId,
21
22
  getSelectedBlockClientIds,
@@ -104,7 +105,7 @@ export default function useClipboardHandler() {
104
105
  blocks = [ head, ...inBetweenBlocks, tail ];
105
106
  }
106
107
 
107
- setClipboardBlocks( event, blocks );
108
+ setClipboardBlocks( event, blocks, registry );
108
109
  }
109
110
  }
110
111
 
@@ -8,36 +8,51 @@ import {
8
8
  pasteHandler,
9
9
  findTransform,
10
10
  getBlockTransforms,
11
+ store as blocksStore,
11
12
  } from '@wordpress/blocks';
12
13
 
13
14
  /**
14
15
  * Internal dependencies
15
16
  */
16
17
  import { getPasteEventData } from '../../utils/pasting';
18
+ import { store as blockEditorStore } from '../../store';
19
+
20
+ export const requiresWrapperOnCopy = Symbol( 'requiresWrapperOnCopy' );
17
21
 
18
22
  /**
19
23
  * Sets the clipboard data for the provided blocks, with both HTML and plain
20
24
  * text representations.
21
25
  *
22
- * @param {ClipboardEvent} event Clipboard event.
23
- * @param {WPBlock[]} blocks Blocks to set as clipboard data.
26
+ * @param {ClipboardEvent} event Clipboard event.
27
+ * @param {WPBlock[]} blocks Blocks to set as clipboard data.
28
+ * @param {Object} registry The registry to select from.
24
29
  */
25
- export function setClipboardBlocks( event, blocks ) {
30
+ export function setClipboardBlocks( event, blocks, registry ) {
26
31
  let _blocks = blocks;
27
- const wrapperBlockName = event.clipboardData.getData(
28
- '__unstableWrapperBlockName'
29
- );
30
32
 
31
- if ( wrapperBlockName ) {
32
- _blocks = createBlock(
33
- wrapperBlockName,
34
- JSON.parse(
35
- event.clipboardData.getData(
36
- '__unstableWrapperBlockAttributes'
37
- )
38
- ),
39
- _blocks
40
- );
33
+ const [ firstBlock ] = blocks;
34
+
35
+ if ( firstBlock ) {
36
+ const firstBlockType = registry
37
+ .select( blocksStore )
38
+ .getBlockType( firstBlock.name );
39
+
40
+ if ( firstBlockType[ requiresWrapperOnCopy ] ) {
41
+ const { getBlockRootClientId, getBlockName, getBlockAttributes } =
42
+ registry.select( blockEditorStore );
43
+ const wrapperBlockClientId = getBlockRootClientId(
44
+ firstBlock.clientId
45
+ );
46
+ const wrapperBlockName = getBlockName( wrapperBlockClientId );
47
+
48
+ if ( wrapperBlockName ) {
49
+ _blocks = createBlock(
50
+ wrapperBlockName,
51
+ getBlockAttributes( wrapperBlockClientId ),
52
+ _blocks
53
+ );
54
+ }
55
+ }
41
56
  }
42
57
 
43
58
  const serialized = serialize( _blocks );
@@ -19,28 +19,38 @@ import { store as blockEditorStore } from '../store';
19
19
 
20
20
  const EMPTY_OBJECT = {};
21
21
 
22
- function BlockHooksControlPure( { name, clientId } ) {
22
+ function BlockHooksControlPure( {
23
+ name,
24
+ clientId,
25
+ metadata: { ignoredHookedBlocks = [] } = {},
26
+ } ) {
23
27
  const blockTypes = useSelect(
24
28
  ( select ) => select( blocksStore ).getBlockTypes(),
25
29
  []
26
30
  );
27
31
 
32
+ // A hooked block added via a filter will not be exposed through a block
33
+ // type's `blockHooks` property; however, if the containing layout has been
34
+ // modified, it will be present in the anchor block's `ignoredHookedBlocks`
35
+ // metadata.
28
36
  const hookedBlocksForCurrentBlock = useMemo(
29
37
  () =>
30
38
  blockTypes?.filter(
31
- ( { blockHooks } ) => blockHooks && name in blockHooks
39
+ ( { name: blockName, blockHooks } ) =>
40
+ ( blockHooks && name in blockHooks ) ||
41
+ ignoredHookedBlocks.includes( blockName )
32
42
  ),
33
- [ blockTypes, name ]
43
+ [ blockTypes, name, ignoredHookedBlocks ]
34
44
  );
35
45
 
36
46
  const { blockIndex, rootClientId, innerBlocksLength } = useSelect(
37
47
  ( select ) => {
38
- const { getBlock, getBlockIndex, getBlockRootClientId } =
48
+ const { getBlocks, getBlockIndex, getBlockRootClientId } =
39
49
  select( blockEditorStore );
40
50
 
41
51
  return {
42
52
  blockIndex: getBlockIndex( clientId ),
43
- innerBlocksLength: getBlock( clientId )?.innerBlocks?.length,
53
+ innerBlocksLength: getBlocks( clientId )?.length,
44
54
  rootClientId: getBlockRootClientId( clientId ),
45
55
  };
46
56
  },
@@ -49,7 +59,7 @@ function BlockHooksControlPure( { name, clientId } ) {
49
59
 
50
60
  const hookedBlockClientIds = useSelect(
51
61
  ( select ) => {
52
- const { getBlock, getGlobalBlockCount } =
62
+ const { getBlocks, getGlobalBlockCount } =
53
63
  select( blockEditorStore );
54
64
 
55
65
  const _hookedBlockClientIds = hookedBlocksForCurrentBlock.reduce(
@@ -69,7 +79,7 @@ function BlockHooksControlPure( { name, clientId } ) {
69
79
  // Any of the current block's siblings (with the right block type) qualifies
70
80
  // as a hooked block (inserted `before` or `after` the current one), as the block
71
81
  // might've been automatically inserted and then moved around a bit by the user.
72
- candidates = getBlock( rootClientId )?.innerBlocks;
82
+ candidates = getBlocks( rootClientId );
73
83
  break;
74
84
 
75
85
  case 'first_child':
@@ -77,7 +87,17 @@ function BlockHooksControlPure( { name, clientId } ) {
77
87
  // Any of the current block's child blocks (with the right block type) qualifies
78
88
  // as a hooked first or last child block, as the block might've been automatically
79
89
  // inserted and then moved around a bit by the user.
80
- candidates = getBlock( clientId ).innerBlocks;
90
+ candidates = getBlocks( clientId );
91
+ break;
92
+
93
+ case undefined:
94
+ // If we haven't found a blockHooks field with a relative position for the hooked
95
+ // block, it means that it was added by a filter. In this case, we look for the block
96
+ // both among the current block's siblings and its children.
97
+ candidates = [
98
+ ...getBlocks( rootClientId ),
99
+ ...getBlocks( clientId ),
100
+ ];
81
101
  break;
82
102
  }
83
103
 
@@ -151,6 +171,18 @@ function BlockHooksControlPure( { name, clientId } ) {
151
171
  false
152
172
  );
153
173
  break;
174
+
175
+ case undefined:
176
+ // If we do not know the relative position, it is because the block was
177
+ // added via a filter. In this case, we default to inserting it after the
178
+ // current block.
179
+ insertBlock(
180
+ block,
181
+ blockIndex + 1,
182
+ rootClientId, // Insert as a child of the current block's parent
183
+ false
184
+ );
185
+ break;
154
186
  }
155
187
  };
156
188
 
@@ -161,6 +193,11 @@ function BlockHooksControlPure( { name, clientId } ) {
161
193
  title={ __( 'Plugins' ) }
162
194
  initialOpen={ true }
163
195
  >
196
+ <p className="block-editor-hooks__block-hooks-helptext">
197
+ { __(
198
+ 'Manage the inclusion of blocks added automatically by plugins.'
199
+ ) }
200
+ </p>
164
201
  { Object.keys( groupedHookedBlocks ).map( ( vendor ) => {
165
202
  return (
166
203
  <Fragment key={ vendor }>
@@ -214,6 +251,7 @@ function BlockHooksControlPure( { name, clientId } ) {
214
251
 
215
252
  export default {
216
253
  edit: BlockHooksControlPure,
254
+ attributeKeys: [ 'metadata' ],
217
255
  hasSupport() {
218
256
  return true;
219
257
  },
@@ -13,4 +13,10 @@
13
13
  .components-toggle-control .components-h-stack .components-h-stack {
14
14
  flex-direction: row;
15
15
  }
16
+
17
+ .block-editor-hooks__block-hooks-helptext {
18
+ color: $gray-700;
19
+ font-size: $helptext-font-size;
20
+ margin-bottom: $grid-unit-20;
21
+ }
16
22
  }
@@ -18,9 +18,14 @@ import { useSelect } from '@wordpress/data';
18
18
  import { getColorClassName } from '../components/colors';
19
19
  import InspectorControls from '../components/inspector-controls';
20
20
  import useMultipleOriginColorsAndGradients from '../components/colors-gradients/use-multiple-origin-colors-and-gradients';
21
- import { cleanEmptyObject, shouldSkipSerialization } from './utils';
21
+ import {
22
+ cleanEmptyObject,
23
+ shouldSkipSerialization,
24
+ useBlockSettings,
25
+ } from './utils';
22
26
  import {
23
27
  useHasBorderPanel,
28
+ useHasBorderPanelControls,
24
29
  BorderPanel as StylesBorderPanel,
25
30
  } from '../components/global-styles';
26
31
  import { store as blockEditorStore } from '../store';
@@ -220,14 +225,21 @@ export function hasShadowSupport( blockName ) {
220
225
  return hasBlockSupport( blockName, SHADOW_SUPPORT_KEY );
221
226
  }
222
227
 
223
- export function getBorderPanelLabel( {
228
+ export function useBorderPanelLabel( {
224
229
  blockName,
225
230
  hasBorderControl,
226
231
  hasShadowControl,
227
232
  } = {} ) {
233
+ const settings = useBlockSettings( blockName );
234
+ const controls = useHasBorderPanelControls( settings );
235
+
228
236
  if ( ! hasBorderControl && ! hasShadowControl && blockName ) {
229
- hasBorderControl = hasBorderSupport( blockName );
230
- hasShadowControl = hasShadowSupport( blockName );
237
+ hasBorderControl =
238
+ controls?.hasBorderColor ||
239
+ controls?.hasBorderStyle ||
240
+ controls?.hasBorderWidth ||
241
+ controls?.hasBorderRadius;
242
+ hasShadowControl = controls?.hasShadow;
231
243
  }
232
244
 
233
245
  if ( hasBorderControl && hasShadowControl ) {