@wordpress/block-editor 12.11.0 → 12.12.0

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 (215) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/build/components/block-controls/hook.js +4 -1
  3. package/build/components/block-controls/hook.js.map +1 -1
  4. package/build/components/block-list/block-outline.native.js +1 -1
  5. package/build/components/block-list/block-outline.native.js.map +1 -1
  6. package/build/components/block-list/block.js +2 -0
  7. package/build/components/block-list/block.js.map +1 -1
  8. package/build/components/block-preview/index.js +4 -1
  9. package/build/components/block-preview/index.js.map +1 -1
  10. package/build/components/block-styles/index.js +1 -2
  11. package/build/components/block-styles/index.js.map +1 -1
  12. package/build/components/block-switcher/pattern-transformations-menu.js +2 -4
  13. package/build/components/block-switcher/pattern-transformations-menu.js.map +1 -1
  14. package/build/components/block-tools/block-contextual-toolbar.js +1 -0
  15. package/build/components/block-tools/block-contextual-toolbar.js.map +1 -1
  16. package/build/components/dimensions-tool/index.js +22 -22
  17. package/build/components/dimensions-tool/index.js.map +1 -1
  18. package/build/components/dimensions-tool/scale-tool.js +1 -1
  19. package/build/components/dimensions-tool/scale-tool.js.map +1 -1
  20. package/build/components/height-control/index.js +90 -2
  21. package/build/components/height-control/index.js.map +1 -1
  22. package/build/components/iframe/index.js +9 -1
  23. package/build/components/iframe/index.js.map +1 -1
  24. package/build/components/image-editor/aspect-ratio-dropdown.js +0 -6
  25. package/build/components/image-editor/aspect-ratio-dropdown.js.map +1 -1
  26. package/build/components/index.native.js +8 -0
  27. package/build/components/index.native.js.map +1 -1
  28. package/build/components/link-control/link-preview.js +5 -2
  29. package/build/components/link-control/link-preview.js.map +1 -1
  30. package/build/components/link-control/use-internal-value.js +14 -8
  31. package/build/components/link-control/use-internal-value.js.map +1 -1
  32. package/build/components/list-view/index.js +6 -5
  33. package/build/components/list-view/index.js.map +1 -1
  34. package/build/components/media-replace-flow/index.js +2 -4
  35. package/build/components/media-replace-flow/index.js.map +1 -1
  36. package/build/components/provider/use-block-sync.js +2 -2
  37. package/build/components/provider/use-block-sync.js.map +1 -1
  38. package/build/components/rich-text/index.native.js +14 -3
  39. package/build/components/rich-text/index.native.js.map +1 -1
  40. package/build/components/rich-text/use-delete.js +1 -1
  41. package/build/components/rich-text/use-delete.js.map +1 -1
  42. package/build/components/rich-text/use-paste-handler.js +25 -22
  43. package/build/components/rich-text/use-paste-handler.js.map +1 -1
  44. package/build/components/spacing-sizes-control/input-controls/spacing-input-control.js +88 -0
  45. package/build/components/spacing-sizes-control/input-controls/spacing-input-control.js.map +1 -1
  46. package/build/components/tool-selector/index.js +1 -2
  47. package/build/components/tool-selector/index.js.map +1 -1
  48. package/build/components/use-block-commands/index.js +90 -46
  49. package/build/components/use-block-commands/index.js.map +1 -1
  50. package/build/components/use-setting/index.js +4 -2
  51. package/build/components/use-setting/index.js.map +1 -1
  52. package/build/components/writing-flow/use-arrow-nav.js +4 -0
  53. package/build/components/writing-flow/use-arrow-nav.js.map +1 -1
  54. package/build/hooks/block-rename-ui.js +5 -5
  55. package/build/hooks/block-rename-ui.js.map +1 -1
  56. package/build/hooks/{metadata-name.js → block-renaming.js} +3 -7
  57. package/build/hooks/block-renaming.js.map +1 -0
  58. package/build/hooks/custom-class-name.js +28 -21
  59. package/build/hooks/custom-class-name.js.map +1 -1
  60. package/build/hooks/duotone.js +28 -1
  61. package/build/hooks/duotone.js.map +1 -1
  62. package/build/hooks/index.js +1 -1
  63. package/build/hooks/index.js.map +1 -1
  64. package/build/hooks/layout.js +6 -6
  65. package/build/hooks/layout.js.map +1 -1
  66. package/build/hooks/metadata.js +6 -27
  67. package/build/hooks/metadata.js.map +1 -1
  68. package/build/hooks/utils.js +1 -1
  69. package/build/hooks/utils.js.map +1 -1
  70. package/build/layouts/grid.js +25 -3
  71. package/build/layouts/grid.js.map +1 -1
  72. package/build/layouts/utils.js +1 -1
  73. package/build/layouts/utils.js.map +1 -1
  74. package/build/lock-unlock.js +1 -1
  75. package/build/lock-unlock.js.map +1 -1
  76. package/build/store/actions.js +13 -5
  77. package/build/store/actions.js.map +1 -1
  78. package/build/utils/parse-css-unit-to-px.js +20 -0
  79. package/build/utils/parse-css-unit-to-px.js.map +1 -1
  80. package/build/utils/pasting.js +1 -1
  81. package/build/utils/pasting.js.map +1 -1
  82. package/build-module/components/block-controls/hook.js +4 -1
  83. package/build-module/components/block-controls/hook.js.map +1 -1
  84. package/build-module/components/block-list/block-outline.native.js +1 -1
  85. package/build-module/components/block-list/block-outline.native.js.map +1 -1
  86. package/build-module/components/block-list/block.js +2 -0
  87. package/build-module/components/block-list/block.js.map +1 -1
  88. package/build-module/components/block-preview/index.js +4 -1
  89. package/build-module/components/block-preview/index.js.map +1 -1
  90. package/build-module/components/block-styles/index.js +1 -2
  91. package/build-module/components/block-styles/index.js.map +1 -1
  92. package/build-module/components/block-switcher/pattern-transformations-menu.js +2 -4
  93. package/build-module/components/block-switcher/pattern-transformations-menu.js.map +1 -1
  94. package/build-module/components/block-tools/block-contextual-toolbar.js +1 -0
  95. package/build-module/components/block-tools/block-contextual-toolbar.js.map +1 -1
  96. package/build-module/components/dimensions-tool/index.js +22 -22
  97. package/build-module/components/dimensions-tool/index.js.map +1 -1
  98. package/build-module/components/dimensions-tool/scale-tool.js +1 -1
  99. package/build-module/components/dimensions-tool/scale-tool.js.map +1 -1
  100. package/build-module/components/height-control/index.js +90 -2
  101. package/build-module/components/height-control/index.js.map +1 -1
  102. package/build-module/components/iframe/index.js +9 -1
  103. package/build-module/components/iframe/index.js.map +1 -1
  104. package/build-module/components/image-editor/aspect-ratio-dropdown.js +0 -6
  105. package/build-module/components/image-editor/aspect-ratio-dropdown.js.map +1 -1
  106. package/build-module/components/index.native.js +1 -0
  107. package/build-module/components/index.native.js.map +1 -1
  108. package/build-module/components/link-control/link-preview.js +6 -3
  109. package/build-module/components/link-control/link-preview.js.map +1 -1
  110. package/build-module/components/link-control/use-internal-value.js +14 -9
  111. package/build-module/components/link-control/use-internal-value.js.map +1 -1
  112. package/build-module/components/list-view/index.js +7 -6
  113. package/build-module/components/list-view/index.js.map +1 -1
  114. package/build-module/components/media-replace-flow/index.js +3 -5
  115. package/build-module/components/media-replace-flow/index.js.map +1 -1
  116. package/build-module/components/provider/use-block-sync.js +2 -2
  117. package/build-module/components/provider/use-block-sync.js.map +1 -1
  118. package/build-module/components/rich-text/index.native.js +15 -4
  119. package/build-module/components/rich-text/index.native.js.map +1 -1
  120. package/build-module/components/rich-text/use-delete.js +1 -1
  121. package/build-module/components/rich-text/use-delete.js.map +1 -1
  122. package/build-module/components/rich-text/use-paste-handler.js +25 -22
  123. package/build-module/components/rich-text/use-paste-handler.js.map +1 -1
  124. package/build-module/components/spacing-sizes-control/input-controls/spacing-input-control.js +88 -0
  125. package/build-module/components/spacing-sizes-control/input-controls/spacing-input-control.js.map +1 -1
  126. package/build-module/components/tool-selector/index.js +1 -2
  127. package/build-module/components/tool-selector/index.js.map +1 -1
  128. package/build-module/components/use-block-commands/index.js +90 -46
  129. package/build-module/components/use-block-commands/index.js.map +1 -1
  130. package/build-module/components/use-setting/index.js +4 -2
  131. package/build-module/components/use-setting/index.js.map +1 -1
  132. package/build-module/components/writing-flow/use-arrow-nav.js +4 -0
  133. package/build-module/components/writing-flow/use-arrow-nav.js.map +1 -1
  134. package/build-module/hooks/block-rename-ui.js +6 -6
  135. package/build-module/hooks/block-rename-ui.js.map +1 -1
  136. package/build-module/hooks/{metadata-name.js → block-renaming.js} +3 -6
  137. package/build-module/hooks/block-renaming.js.map +1 -0
  138. package/build-module/hooks/custom-class-name.js +28 -21
  139. package/build-module/hooks/custom-class-name.js.map +1 -1
  140. package/build-module/hooks/duotone.js +28 -1
  141. package/build-module/hooks/duotone.js.map +1 -1
  142. package/build-module/hooks/index.js +1 -1
  143. package/build-module/hooks/index.js.map +1 -1
  144. package/build-module/hooks/layout.js +6 -6
  145. package/build-module/hooks/layout.js.map +1 -1
  146. package/build-module/hooks/metadata.js +6 -25
  147. package/build-module/hooks/metadata.js.map +1 -1
  148. package/build-module/hooks/utils.js +1 -1
  149. package/build-module/hooks/utils.js.map +1 -1
  150. package/build-module/layouts/grid.js +25 -3
  151. package/build-module/layouts/grid.js.map +1 -1
  152. package/build-module/layouts/utils.js +1 -1
  153. package/build-module/layouts/utils.js.map +1 -1
  154. package/build-module/lock-unlock.js +1 -1
  155. package/build-module/lock-unlock.js.map +1 -1
  156. package/build-module/store/actions.js +14 -6
  157. package/build-module/store/actions.js.map +1 -1
  158. package/build-module/utils/parse-css-unit-to-px.js +20 -0
  159. package/build-module/utils/parse-css-unit-to-px.js.map +1 -1
  160. package/build-module/utils/pasting.js +1 -1
  161. package/build-module/utils/pasting.js.map +1 -1
  162. package/build-style/style-rtl.css +11 -6
  163. package/build-style/style.css +11 -6
  164. package/package.json +31 -31
  165. package/src/components/block-controls/hook.js +6 -3
  166. package/src/components/block-list/block-outline.native.js +1 -1
  167. package/src/components/block-list/block.js +2 -0
  168. package/src/components/block-preview/index.js +7 -1
  169. package/src/components/block-styles/index.js +1 -4
  170. package/src/components/block-switcher/pattern-transformations-menu.js +1 -4
  171. package/src/components/block-switcher/style.scss +6 -0
  172. package/src/components/block-tools/block-contextual-toolbar.js +1 -0
  173. package/src/components/block-tools/style.scss +0 -1
  174. package/src/components/color-palette/test/__snapshots__/control.js.snap +3 -1
  175. package/src/components/colors-gradients/style.scss +4 -2
  176. package/src/components/dimensions-tool/index.js +25 -25
  177. package/src/components/dimensions-tool/scale-tool.js +1 -1
  178. package/src/components/height-control/index.js +50 -2
  179. package/src/components/iframe/index.js +8 -1
  180. package/src/components/image-editor/aspect-ratio-dropdown.js +0 -8
  181. package/src/components/index.native.js +1 -0
  182. package/src/components/link-control/README.md +43 -0
  183. package/src/components/link-control/link-preview.js +11 -5
  184. package/src/components/link-control/style.scss +3 -3
  185. package/src/components/link-control/test/index.js +19 -0
  186. package/src/components/link-control/use-internal-value.js +14 -10
  187. package/src/components/list-view/index.js +13 -3
  188. package/src/components/media-replace-flow/index.js +9 -14
  189. package/src/components/provider/test/use-block-sync.js +1 -1
  190. package/src/components/provider/use-block-sync.js +2 -2
  191. package/src/components/rich-text/index.native.js +19 -3
  192. package/src/components/rich-text/use-delete.js +1 -1
  193. package/src/components/rich-text/use-paste-handler.js +27 -24
  194. package/src/components/spacing-sizes-control/input-controls/spacing-input-control.js +22 -0
  195. package/src/components/tool-selector/index.js +1 -1
  196. package/src/components/use-block-commands/index.js +91 -46
  197. package/src/components/use-setting/index.js +6 -1
  198. package/src/components/writing-flow/use-arrow-nav.js +4 -0
  199. package/src/hooks/block-rename-ui.js +5 -14
  200. package/src/hooks/{metadata-name.js → block-renaming.js} +4 -7
  201. package/src/hooks/custom-class-name.js +36 -31
  202. package/src/hooks/duotone.js +33 -0
  203. package/src/hooks/index.js +1 -1
  204. package/src/hooks/layout.js +6 -6
  205. package/src/hooks/metadata.js +6 -38
  206. package/src/hooks/utils.js +2 -0
  207. package/src/layouts/grid.js +50 -2
  208. package/src/layouts/utils.js +2 -1
  209. package/src/lock-unlock.js +1 -1
  210. package/src/store/actions.js +25 -8
  211. package/src/utils/parse-css-unit-to-px.js +20 -0
  212. package/src/utils/pasting.js +1 -4
  213. package/src/utils/test/pasting.js +12 -19
  214. package/build/hooks/metadata-name.js.map +0 -1
  215. package/build-module/hooks/metadata-name.js.map +0 -1
@@ -112,6 +112,60 @@ export const useTransformCommands = () => {
112
112
  };
113
113
 
114
114
  const useActionsCommands = () => {
115
+ const { clientIds } = useSelect( ( select ) => {
116
+ const { getSelectedBlockClientIds } = select( blockEditorStore );
117
+ const selectedBlockClientIds = getSelectedBlockClientIds();
118
+
119
+ return {
120
+ clientIds: selectedBlockClientIds,
121
+ };
122
+ }, [] );
123
+
124
+ const { getBlockRootClientId, canMoveBlocks, getBlockCount } =
125
+ useSelect( blockEditorStore );
126
+
127
+ const { setBlockMovingClientId, setNavigationMode, selectBlock } =
128
+ useDispatch( blockEditorStore );
129
+
130
+ if ( ! clientIds || clientIds.length < 1 ) {
131
+ return { isLoading: false, commands: [] };
132
+ }
133
+
134
+ const rootClientId = getBlockRootClientId( clientIds[ 0 ] );
135
+
136
+ const canMove =
137
+ canMoveBlocks( clientIds, rootClientId ) &&
138
+ getBlockCount( rootClientId ) !== 1;
139
+
140
+ const commands = [];
141
+
142
+ if ( canMove ) {
143
+ commands.push( {
144
+ name: 'move-to',
145
+ label: __( 'Move to' ),
146
+ callback: () => {
147
+ setNavigationMode( true );
148
+ selectBlock( clientIds[ 0 ] );
149
+ setBlockMovingClientId( clientIds[ 0 ] );
150
+ },
151
+ icon: move,
152
+ } );
153
+ }
154
+
155
+ return {
156
+ isLoading: false,
157
+ commands: commands.map( ( command ) => ( {
158
+ ...command,
159
+ name: 'core/block-editor/action-' + command.name,
160
+ callback: ( { close } ) => {
161
+ command.callback();
162
+ close();
163
+ },
164
+ } ) ),
165
+ };
166
+ };
167
+
168
+ const useQuickActionsCommands = () => {
115
169
  const { clientIds, isUngroupable, isGroupable } = useSelect( ( select ) => {
116
170
  const {
117
171
  getSelectedBlockClientIds,
@@ -130,9 +184,7 @@ const useActionsCommands = () => {
130
184
  canInsertBlockType,
131
185
  getBlockRootClientId,
132
186
  getBlocksByClientId,
133
- canMoveBlocks,
134
187
  canRemoveBlocks,
135
- getBlockCount,
136
188
  } = useSelect( blockEditorStore );
137
189
  const { getDefaultBlockName, getGroupingBlockName } =
138
190
  useSelect( blocksStore );
@@ -145,9 +197,6 @@ const useActionsCommands = () => {
145
197
  duplicateBlocks,
146
198
  insertAfterBlock,
147
199
  insertBeforeBlock,
148
- setBlockMovingClientId,
149
- setNavigationMode,
150
- selectBlock,
151
200
  } = useDispatch( blockEditorStore );
152
201
 
153
202
  const onGroup = () => {
@@ -196,65 +245,54 @@ const useActionsCommands = () => {
196
245
  );
197
246
  } );
198
247
  const canRemove = canRemoveBlocks( clientIds, rootClientId );
199
- const canMove =
200
- canMoveBlocks( clientIds, rootClientId ) &&
201
- getBlockCount( rootClientId ) !== 1;
202
248
 
203
249
  const commands = [];
250
+
251
+ if ( canDuplicate ) {
252
+ commands.push( {
253
+ name: 'duplicate',
254
+ label: __( 'Duplicate' ),
255
+ callback: () => duplicateBlocks( clientIds, true ),
256
+ icon: copy,
257
+ } );
258
+ }
259
+
204
260
  if ( canInsertDefaultBlock ) {
205
261
  commands.push(
206
262
  {
207
- name: 'add-after',
208
- label: __( 'Add after' ),
263
+ name: 'add-before',
264
+ label: __( 'Add before' ),
209
265
  callback: () => {
210
266
  const clientId = Array.isArray( clientIds )
211
- ? clientIds[ clientIds.length - 1 ]
267
+ ? clientIds[ 0 ]
212
268
  : clientId;
213
- insertAfterBlock( clientId );
269
+ insertBeforeBlock( clientId );
214
270
  },
215
271
  icon: add,
216
272
  },
217
273
  {
218
- name: 'add-before',
219
- label: __( 'Add before' ),
274
+ name: 'add-after',
275
+ label: __( 'Add after' ),
220
276
  callback: () => {
221
277
  const clientId = Array.isArray( clientIds )
222
- ? clientIds[ 0 ]
278
+ ? clientIds[ clientIds.length - 1 ]
223
279
  : clientId;
224
- insertBeforeBlock( clientId );
280
+ insertAfterBlock( clientId );
225
281
  },
226
282
  icon: add,
227
283
  }
228
284
  );
229
285
  }
230
- if ( canRemove ) {
231
- commands.push( {
232
- name: 'remove',
233
- label: __( 'Delete' ),
234
- callback: () => removeBlocks( clientIds, true ),
235
- icon: remove,
236
- } );
237
- }
238
- if ( canDuplicate ) {
239
- commands.push( {
240
- name: 'duplicate',
241
- label: __( 'Duplicate' ),
242
- callback: () => duplicateBlocks( clientIds, true ),
243
- icon: copy,
244
- } );
245
- }
246
- if ( canMove ) {
286
+
287
+ if ( isGroupable ) {
247
288
  commands.push( {
248
- name: 'move-to',
249
- label: __( 'Move to' ),
250
- callback: () => {
251
- setNavigationMode( true );
252
- selectBlock( clientIds[ 0 ] );
253
- setBlockMovingClientId( clientIds[ 0 ] );
254
- },
255
- icon: move,
289
+ name: 'Group',
290
+ label: __( 'Group' ),
291
+ callback: onGroup,
292
+ icon: group,
256
293
  } );
257
294
  }
295
+
258
296
  if ( isUngroupable ) {
259
297
  commands.push( {
260
298
  name: 'ungroup',
@@ -263,14 +301,16 @@ const useActionsCommands = () => {
263
301
  icon: ungroup,
264
302
  } );
265
303
  }
266
- if ( isGroupable ) {
304
+
305
+ if ( canRemove ) {
267
306
  commands.push( {
268
- name: 'Group',
269
- label: __( 'Group' ),
270
- callback: onGroup,
271
- icon: group,
307
+ name: 'remove',
308
+ label: __( 'Delete' ),
309
+ callback: () => removeBlocks( clientIds, true ),
310
+ icon: remove,
272
311
  } );
273
312
  }
313
+
274
314
  return {
275
315
  isLoading: false,
276
316
  commands: commands.map( ( command ) => ( {
@@ -293,4 +333,9 @@ export const useBlockCommands = () => {
293
333
  name: 'core/block-editor/blockActions',
294
334
  hook: useActionsCommands,
295
335
  } );
336
+ useCommandLoader( {
337
+ name: 'core/block-editor/blockQuickActions',
338
+ hook: useQuickActionsCommands,
339
+ context: 'block-selection-edit',
340
+ } );
296
341
  };
@@ -189,7 +189,12 @@ export default function useSetting( path ) {
189
189
  // Return if the setting was found in either the block instance or the store.
190
190
  if ( result !== undefined ) {
191
191
  if ( PATHS_WITH_MERGE[ normalizedPath ] ) {
192
- return result.custom ?? result.theme ?? result.default;
192
+ return [ 'default', 'theme', 'custom' ].reduce(
193
+ ( acc, key ) => {
194
+ return acc.concat( result[ key ] ?? [] );
195
+ },
196
+ []
197
+ );
193
198
  }
194
199
  return result;
195
200
  }
@@ -114,6 +114,10 @@ export function getClosestTabbable(
114
114
  }
115
115
 
116
116
  function isTabCandidate( node ) {
117
+ if ( node.closest( '[inert]' ) ) {
118
+ return;
119
+ }
120
+
117
121
  // Skip if there's only one child that is content editable (and thus a
118
122
  // better candidate).
119
123
  if (
@@ -4,7 +4,7 @@
4
4
  import { createHigherOrderComponent, useInstanceId } from '@wordpress/compose';
5
5
  import { addFilter } from '@wordpress/hooks';
6
6
  import { __, sprintf } from '@wordpress/i18n';
7
- import { getBlockSupport } from '@wordpress/blocks';
7
+ import { hasBlockSupport } from '@wordpress/blocks';
8
8
  import {
9
9
  MenuItem,
10
10
  __experimentalHStack as HStack,
@@ -189,21 +189,13 @@ function BlockRenameControl( props ) {
189
189
 
190
190
  export const withBlockRenameControl = createHigherOrderComponent(
191
191
  ( BlockEdit ) => ( props ) => {
192
- const { clientId, name, attributes, setAttributes } = props;
192
+ const { clientId, name, attributes, setAttributes, isSelected } = props;
193
193
 
194
- const metaDataSupport = getBlockSupport(
195
- name,
196
- '__experimentalMetadata',
197
- false
198
- );
199
-
200
- const supportsBlockNaming = !! (
201
- true === metaDataSupport || metaDataSupport?.name
202
- );
194
+ const supportsBlockNaming = hasBlockSupport( name, 'renaming', true );
203
195
 
204
196
  return (
205
197
  <>
206
- { supportsBlockNaming && (
198
+ { isSelected && supportsBlockNaming && (
207
199
  <>
208
200
  <BlockRenameControl
209
201
  clientId={ clientId }
@@ -211,8 +203,7 @@ export const withBlockRenameControl = createHigherOrderComponent(
211
203
  onChange={ ( newName ) => {
212
204
  setAttributes( {
213
205
  metadata: {
214
- ...( attributes?.metadata &&
215
- attributes?.metadata ),
206
+ ...attributes?.metadata,
216
207
  name: newName,
217
208
  },
218
209
  } );
@@ -2,10 +2,7 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { addFilter } from '@wordpress/hooks';
5
- /**
6
- * Internal dependencies
7
- */
8
- import { hasBlockMetadataSupport } from './metadata';
5
+ import { hasBlockSupport } from '@wordpress/blocks';
9
6
 
10
7
  /**
11
8
  * Filters registered block settings, adding an `__experimentalLabel` callback if one does not already exist.
@@ -20,10 +17,10 @@ export function addLabelCallback( settings ) {
20
17
  return settings;
21
18
  }
22
19
 
23
- const supportsBlockNaming = hasBlockMetadataSupport(
20
+ const supportsBlockNaming = hasBlockSupport(
24
21
  settings,
25
- 'name',
26
- false // default value
22
+ 'renaming',
23
+ true // default value
27
24
  );
28
25
 
29
26
  // Check whether block metadata is supported before using it.
@@ -39,6 +39,30 @@ export function addAttribute( settings ) {
39
39
  return settings;
40
40
  }
41
41
 
42
+ function CustomClassNameControls( { attributes, setAttributes } ) {
43
+ const blockEditingMode = useBlockEditingMode();
44
+ if ( blockEditingMode !== 'default' ) {
45
+ return null;
46
+ }
47
+
48
+ return (
49
+ <InspectorControls group="advanced">
50
+ <TextControl
51
+ __nextHasNoMarginBottom
52
+ autoComplete="off"
53
+ label={ __( 'Additional CSS class(es)' ) }
54
+ value={ attributes.className || '' }
55
+ onChange={ ( nextValue ) => {
56
+ setAttributes( {
57
+ className: nextValue !== '' ? nextValue : undefined,
58
+ } );
59
+ } }
60
+ help={ __( 'Separate multiple classes with spaces.' ) }
61
+ />
62
+ </InspectorControls>
63
+ );
64
+ }
65
+
42
66
  /**
43
67
  * Override the default edit UI to include a new block inspector control for
44
68
  * assigning the custom class name, if block supports custom class name.
@@ -51,42 +75,23 @@ export function addAttribute( settings ) {
51
75
  export const withInspectorControl = createHigherOrderComponent(
52
76
  ( BlockEdit ) => {
53
77
  return ( props ) => {
54
- const blockEditingMode = useBlockEditingMode();
55
78
  const hasCustomClassName = hasBlockSupport(
56
79
  props.name,
57
80
  'customClassName',
58
81
  true
59
82
  );
60
- if ( hasCustomClassName && props.isSelected ) {
61
- return (
62
- <>
63
- <BlockEdit { ...props } />
64
- { blockEditingMode === 'default' && (
65
- <InspectorControls group="advanced">
66
- <TextControl
67
- __nextHasNoMarginBottom
68
- autoComplete="off"
69
- label={ __( 'Additional CSS class(es)' ) }
70
- value={ props.attributes.className || '' }
71
- onChange={ ( nextValue ) => {
72
- props.setAttributes( {
73
- className:
74
- nextValue !== ''
75
- ? nextValue
76
- : undefined,
77
- } );
78
- } }
79
- help={ __(
80
- 'Separate multiple classes with spaces.'
81
- ) }
82
- />
83
- </InspectorControls>
84
- ) }
85
- </>
86
- );
87
- }
88
-
89
- return <BlockEdit { ...props } />;
83
+
84
+ return (
85
+ <>
86
+ <BlockEdit { ...props } />
87
+ { hasCustomClassName && props.isSelected && (
88
+ <CustomClassNameControls
89
+ attributes={ props.attributes }
90
+ setAttributes={ props.setAttributes }
91
+ />
92
+ ) }
93
+ </>
94
+ );
90
95
  };
91
96
  },
92
97
  'withInspectorControl'
@@ -37,11 +37,22 @@ import { scopeSelector } from '../components/global-styles/utils';
37
37
  import { useBlockSettings } from './utils';
38
38
  import { default as StylesFiltersPanel } from '../components/global-styles/filters-panel';
39
39
  import { useBlockEditingMode } from '../components/block-editing-mode';
40
+ import { __unstableUseBlockElement as useBlockElement } from '../components/block-list/use-block-props/use-block-refs';
40
41
  import { store as blockEditorStore } from '../store';
41
42
  import { unlock } from '../lock-unlock';
42
43
 
43
44
  const EMPTY_ARRAY = [];
44
45
 
46
+ // Safari does not always update the duotone filter when the duotone colors
47
+ // are changed. This browser check is later used to force a re-render of the block
48
+ // element to ensure the duotone filter is updated. The check is included at the
49
+ // root of this file as it only needs to be run once per page load.
50
+ const isSafari =
51
+ window?.navigator.userAgent &&
52
+ window.navigator.userAgent.includes( 'Safari' ) &&
53
+ ! window.navigator.userAgent.includes( 'Chrome' ) &&
54
+ ! window.navigator.userAgent.includes( 'Chromium' );
55
+
45
56
  extend( [ namesPlugin ] );
46
57
 
47
58
  function useMultiOriginPresets( { presetSetting, defaultSetting } ) {
@@ -223,6 +234,7 @@ const withDuotoneControls = createHigherOrderComponent(
223
234
  );
224
235
 
225
236
  function DuotoneStyles( {
237
+ clientId,
226
238
  id: filterId,
227
239
  selector: duotoneSelector,
228
240
  attribute: duotoneAttr,
@@ -278,6 +290,8 @@ function DuotoneStyles( {
278
290
  useDispatch( blockEditorStore )
279
291
  );
280
292
 
293
+ const blockElement = useBlockElement( clientId );
294
+
281
295
  useEffect( () => {
282
296
  if ( ! isValidFilter ) return;
283
297
 
@@ -294,12 +308,30 @@ function DuotoneStyles( {
294
308
  __unstableType: 'svgs',
295
309
  } );
296
310
 
311
+ // Safari does not always update the duotone filter when the duotone colors
312
+ // are changed. When using Safari, force the block element to be repainted by
313
+ // the browser to ensure any changes are reflected visually. This logic matches
314
+ // that used on the site frontend in `block-supports/duotone.php`.
315
+ if ( blockElement && isSafari ) {
316
+ const display = blockElement.style.display;
317
+ // Switch to `inline-block` to force a repaint. In the editor, `inline-block`
318
+ // is used instead of `none` to ensure that scroll position is not affected,
319
+ // as `none` results in the editor scrolling to the top of the block.
320
+ blockElement.style.display = 'inline-block';
321
+ // Simply accessing el.offsetHeight flushes layout and style
322
+ // changes in WebKit without having to wait for setTimeout.
323
+ // eslint-disable-next-line no-unused-expressions
324
+ blockElement.offsetHeight;
325
+ blockElement.style.display = display;
326
+ }
327
+
297
328
  return () => {
298
329
  deleteStyleOverride( filterId );
299
330
  deleteStyleOverride( `duotone-${ filterId }` );
300
331
  };
301
332
  }, [
302
333
  isValidFilter,
334
+ blockElement,
303
335
  colors,
304
336
  selector,
305
337
  filterId,
@@ -378,6 +410,7 @@ const withDuotoneStyles = createHigherOrderComponent(
378
410
  <>
379
411
  { shouldRender && (
380
412
  <DuotoneStyles
413
+ clientId={ props.clientId }
381
414
  id={ filterClass }
382
415
  selector={ selector }
383
416
  attribute={ attribute }
@@ -19,9 +19,9 @@ import './position';
19
19
  import './layout';
20
20
  import './content-lock-ui';
21
21
  import './metadata';
22
- import './metadata-name';
23
22
  import './custom-fields';
24
23
  import './block-hooks';
24
+ import './block-renaming';
25
25
  import './block-rename-ui';
26
26
 
27
27
  export { useCustomSides } from './dimensions';
@@ -408,11 +408,11 @@ export const withLayoutStyles = createHigherOrderComponent(
408
408
 
409
409
  useEffect( () => {
410
410
  if ( ! css ) return;
411
- setStyleOverride( id, { css } );
411
+ setStyleOverride( selector, { css } );
412
412
  return () => {
413
- deleteStyleOverride( id );
413
+ deleteStyleOverride( selector );
414
414
  };
415
- }, [ id, css, setStyleOverride, deleteStyleOverride ] );
415
+ }, [ selector, css, setStyleOverride, deleteStyleOverride ] );
416
416
 
417
417
  return (
418
418
  <BlockListBlock
@@ -472,11 +472,11 @@ export const withChildLayoutStyles = createHigherOrderComponent(
472
472
 
473
473
  useEffect( () => {
474
474
  if ( ! css ) return;
475
- setStyleOverride( id, { css } );
475
+ setStyleOverride( selector, { css } );
476
476
  return () => {
477
- deleteStyleOverride( id );
477
+ deleteStyleOverride( selector );
478
478
  };
479
- }, [ id, css, setStyleOverride, deleteStyleOverride ] );
479
+ }, [ selector, css, setStyleOverride, deleteStyleOverride ] );
480
480
 
481
481
  return <BlockListBlock { ...props } className={ className } />;
482
482
  },
@@ -2,19 +2,8 @@
2
2
  * WordPress dependencies
3
3
  */
4
4
  import { addFilter } from '@wordpress/hooks';
5
- import { getBlockSupport } from '@wordpress/blocks';
6
-
7
5
  const META_ATTRIBUTE_NAME = 'metadata';
8
6
 
9
- export function hasBlockMetadataSupport( blockType, feature = '' ) {
10
- // Only core blocks are allowed to use __experimentalMetadata until the fetaure is stablised.
11
- if ( ! blockType.name.startsWith( 'core/' ) ) {
12
- return false;
13
- }
14
- const support = getBlockSupport( blockType, '__experimentalMetadata' );
15
- return !! ( true === support || support?.[ feature ] );
16
- }
17
-
18
7
  /**
19
8
  * Filters registered block settings, extending attributes to include `metadata`.
20
9
  *
@@ -29,39 +18,18 @@ export function addMetaAttribute( blockTypeSettings ) {
29
18
  return blockTypeSettings;
30
19
  }
31
20
 
32
- const supportsBlockNaming = hasBlockMetadataSupport(
33
- blockTypeSettings,
34
- 'name'
35
- );
36
-
37
- if ( supportsBlockNaming ) {
38
- blockTypeSettings.attributes = {
39
- ...blockTypeSettings.attributes,
40
- [ META_ATTRIBUTE_NAME ]: {
41
- type: 'object',
42
- },
43
- };
44
- }
21
+ blockTypeSettings.attributes = {
22
+ ...blockTypeSettings.attributes,
23
+ [ META_ATTRIBUTE_NAME ]: {
24
+ type: 'object',
25
+ },
26
+ };
45
27
 
46
28
  return blockTypeSettings;
47
29
  }
48
30
 
49
- export function addSaveProps( extraProps, blockType, attributes ) {
50
- if ( hasBlockMetadataSupport( blockType ) ) {
51
- extraProps[ META_ATTRIBUTE_NAME ] = attributes[ META_ATTRIBUTE_NAME ];
52
- }
53
-
54
- return extraProps;
55
- }
56
-
57
31
  addFilter(
58
32
  'blocks.registerBlockType',
59
33
  'core/metadata/addMetaAttribute',
60
34
  addMetaAttribute
61
35
  );
62
-
63
- addFilter(
64
- 'blocks.getSaveContent.extraProps',
65
- 'core/metadata/save-props',
66
- addSaveProps
67
- );
@@ -279,6 +279,8 @@ export function useBlockSettings( name, parentLayout ) {
279
279
  isBackgroundEnabled,
280
280
  isLinkEnabled,
281
281
  isTextEnabled,
282
+ isHeadingEnabled,
283
+ isButtonEnabled,
282
284
  ] );
283
285
 
284
286
  return useSettingsForBlockElement( rawSettings, name );
@@ -27,6 +27,28 @@ const RANGE_CONTROL_MAX_VALUES = {
27
27
  vh: 100,
28
28
  em: 38,
29
29
  rem: 38,
30
+ svw: 100,
31
+ lvw: 100,
32
+ dvw: 100,
33
+ svh: 100,
34
+ lvh: 100,
35
+ dvh: 100,
36
+ vi: 100,
37
+ svi: 100,
38
+ lvi: 100,
39
+ dvi: 100,
40
+ vb: 100,
41
+ svb: 100,
42
+ lvb: 100,
43
+ dvb: 100,
44
+ vmin: 100,
45
+ svmin: 100,
46
+ lvmin: 100,
47
+ dvmin: 100,
48
+ vmax: 100,
49
+ svmax: 100,
50
+ lvmax: 100,
51
+ dvmax: 100,
30
52
  };
31
53
 
32
54
  export default {
@@ -131,10 +153,36 @@ function GridLayoutMinimumWidthControl( { layout, onChange } ) {
131
153
  // Convert to pixel value assuming a root size of 16px.
132
154
  newValue = Math.round( quantity * 16 ) + newUnit;
133
155
  } else if (
134
- [ 'vh', 'vw', '%' ].includes( newUnit ) &&
156
+ [
157
+ 'vh',
158
+ 'vw',
159
+ '%',
160
+ 'svw',
161
+ 'lvw',
162
+ 'dvw',
163
+ 'svh',
164
+ 'lvh',
165
+ 'dvh',
166
+ 'vi',
167
+ 'svi',
168
+ 'lvi',
169
+ 'dvi',
170
+ 'vb',
171
+ 'svb',
172
+ 'lvb',
173
+ 'dvb',
174
+ 'vmin',
175
+ 'svmin',
176
+ 'lvmin',
177
+ 'dvmin',
178
+ 'vmax',
179
+ 'svmax',
180
+ 'lvmax',
181
+ 'dvmax',
182
+ ].includes( newUnit ) &&
135
183
  quantity > 100
136
184
  ) {
137
- // When converting to `vh`, `vw`, or `%` units, cap the new value at 100.
185
+ // When converting to `%` or viewport-relative units, cap the new value at 100.
138
186
  newValue = 100 + newUnit;
139
187
  }
140
188
 
@@ -90,7 +90,8 @@ export function getBlockGapCSS(
90
90
  export function getAlignmentsInfo( layout ) {
91
91
  const { contentSize, wideSize, type = 'default' } = layout;
92
92
  const alignmentInfo = {};
93
- const sizeRegex = /^(?!0)\d+(px|em|rem|vw|vh|%)?$/i;
93
+ const sizeRegex =
94
+ /^(?!0)\d+(px|em|rem|vw|vh|%|svw|lvw|dvw|svh|lvh|dvh|vi|svi|lvi|dvi|vb|svb|lvb|dvb|vmin|svmin|lvmin|dvmin|vmax|svmax|lvmax|dvmax)?$/i;
94
95
  if ( sizeRegex.test( contentSize ) && type === 'constrained' ) {
95
96
  // translators: %s: container size (i.e. 600px etc)
96
97
  alignmentInfo.none = sprintf( __( 'Max %s wide' ), contentSize );
@@ -5,6 +5,6 @@ import { __dangerousOptInToUnstableAPIsOnlyForCoreModules } from '@wordpress/pri
5
5
 
6
6
  export const { lock, unlock } =
7
7
  __dangerousOptInToUnstableAPIsOnlyForCoreModules(
8
- 'I know using unstable features means my plugin or theme will inevitably break on the next WordPress release.',
8
+ 'I know using unstable features means my theme or plugin will inevitably break in the next version of WordPress.',
9
9
  '@wordpress/block-editor'
10
10
  );