@wordpress/block-library 10.4.0 → 10.5.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 (239) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/build/accordion/view.cjs +2 -5
  3. package/build/accordion/view.cjs.map +2 -2
  4. package/build/accordion-heading/block.json +1 -0
  5. package/build/audio/edit.cjs.map +2 -2
  6. package/build/avatar/edit.cjs.map +2 -2
  7. package/build/block/block.json +2 -1
  8. package/build/column/edit.cjs +1 -1
  9. package/build/column/edit.cjs.map +2 -2
  10. package/build/columns/edit.cjs.map +2 -2
  11. package/build/columns/transforms.cjs +161 -2
  12. package/build/columns/transforms.cjs.map +2 -2
  13. package/build/cover/edit/block-controls.cjs +1 -1
  14. package/build/cover/edit/block-controls.cjs.map +2 -2
  15. package/build/cover/edit/index.cjs +1 -1
  16. package/build/cover/edit/index.cjs.map +2 -2
  17. package/build/cover/edit/inspector-controls.cjs.map +3 -3
  18. package/build/embed/embed-placeholder.cjs.map +2 -2
  19. package/build/gallery/transforms.cjs +8 -0
  20. package/build/gallery/transforms.cjs.map +2 -2
  21. package/build/group/block.json +1 -1
  22. package/build/heading/transforms.cjs +36 -0
  23. package/build/heading/transforms.cjs.map +2 -2
  24. package/build/heading/variations.cjs +13 -1
  25. package/build/heading/variations.cjs.map +2 -2
  26. package/build/home-link/edit.cjs.map +3 -3
  27. package/build/icon/edit.cjs +7 -1
  28. package/build/icon/edit.cjs.map +2 -2
  29. package/build/image/image.cjs +1 -1
  30. package/build/image/image.cjs.map +3 -3
  31. package/build/list/block.json +1 -0
  32. package/build/math/edit.cjs +4 -5
  33. package/build/math/edit.cjs.map +3 -3
  34. package/build/media-text/edit.cjs.map +3 -3
  35. package/build/more/block.json +1 -1
  36. package/build/navigation-link/shared/controls.cjs.map +3 -3
  37. package/build/playlist/block.json +0 -1
  38. package/build/playlist/edit.cjs +46 -22
  39. package/build/playlist/edit.cjs.map +2 -2
  40. package/build/playlist-track/block.json +16 -8
  41. package/build/playlist-track/edit.cjs +74 -67
  42. package/build/playlist-track/edit.cjs.map +3 -3
  43. package/build/post-template/edit.cjs +5 -1
  44. package/build/post-template/edit.cjs.map +2 -2
  45. package/build/post-title/edit.cjs +3 -8
  46. package/build/post-title/edit.cjs.map +2 -2
  47. package/build/private-apis.cjs +0 -12
  48. package/build/private-apis.cjs.map +3 -3
  49. package/build/query/block.json +3 -0
  50. package/build/query-no-results/block.json +16 -1
  51. package/build/rss/edit.cjs.map +2 -2
  52. package/build/site-logo/edit.cjs +1 -1
  53. package/build/site-logo/edit.cjs.map +2 -2
  54. package/build/site-title/edit.cjs +2 -6
  55. package/build/site-title/edit.cjs.map +2 -2
  56. package/build/table-of-contents/block.json +2 -1
  57. package/build/table-of-contents/deprecated.cjs +165 -0
  58. package/build/table-of-contents/deprecated.cjs.map +7 -0
  59. package/build/table-of-contents/index.cjs +2 -2
  60. package/build/table-of-contents/index.cjs.map +3 -3
  61. package/build/tabs/view.cjs +32 -2
  62. package/build/tabs/view.cjs.map +2 -2
  63. package/build/term-template/edit.cjs +5 -1
  64. package/build/term-template/edit.cjs.map +2 -2
  65. package/build-module/accordion/view.mjs +2 -5
  66. package/build-module/accordion/view.mjs.map +2 -2
  67. package/build-module/accordion-heading/block.json +1 -0
  68. package/build-module/audio/edit.mjs.map +2 -2
  69. package/build-module/avatar/edit.mjs.map +2 -2
  70. package/build-module/block/block.json +2 -1
  71. package/build-module/column/edit.mjs +1 -1
  72. package/build-module/column/edit.mjs.map +2 -2
  73. package/build-module/columns/edit.mjs.map +2 -2
  74. package/build-module/columns/transforms.mjs +164 -3
  75. package/build-module/columns/transforms.mjs.map +2 -2
  76. package/build-module/cover/edit/block-controls.mjs +1 -1
  77. package/build-module/cover/edit/block-controls.mjs.map +2 -2
  78. package/build-module/cover/edit/index.mjs +1 -1
  79. package/build-module/cover/edit/index.mjs.map +2 -2
  80. package/build-module/cover/edit/inspector-controls.mjs +2 -2
  81. package/build-module/cover/edit/inspector-controls.mjs.map +2 -2
  82. package/build-module/embed/embed-placeholder.mjs +2 -2
  83. package/build-module/embed/embed-placeholder.mjs.map +1 -1
  84. package/build-module/gallery/transforms.mjs +8 -0
  85. package/build-module/gallery/transforms.mjs.map +2 -2
  86. package/build-module/group/block.json +1 -1
  87. package/build-module/heading/transforms.mjs +36 -0
  88. package/build-module/heading/transforms.mjs.map +2 -2
  89. package/build-module/heading/variations.mjs +13 -1
  90. package/build-module/heading/variations.mjs.map +2 -2
  91. package/build-module/home-link/edit.mjs +2 -2
  92. package/build-module/home-link/edit.mjs.map +2 -2
  93. package/build-module/icon/edit.mjs +7 -1
  94. package/build-module/icon/edit.mjs.map +2 -2
  95. package/build-module/image/image.mjs +4 -4
  96. package/build-module/image/image.mjs.map +2 -2
  97. package/build-module/list/block.json +1 -0
  98. package/build-module/math/edit.mjs +4 -8
  99. package/build-module/math/edit.mjs.map +2 -2
  100. package/build-module/media-text/edit.mjs +2 -2
  101. package/build-module/media-text/edit.mjs.map +2 -2
  102. package/build-module/more/block.json +1 -1
  103. package/build-module/navigation-link/shared/controls.mjs +2 -2
  104. package/build-module/navigation-link/shared/controls.mjs.map +2 -2
  105. package/build-module/playlist/block.json +0 -1
  106. package/build-module/playlist/edit.mjs +46 -22
  107. package/build-module/playlist/edit.mjs.map +2 -2
  108. package/build-module/playlist-track/block.json +16 -8
  109. package/build-module/playlist-track/edit.mjs +76 -69
  110. package/build-module/playlist-track/edit.mjs.map +2 -2
  111. package/build-module/post-template/edit.mjs +5 -1
  112. package/build-module/post-template/edit.mjs.map +2 -2
  113. package/build-module/post-title/edit.mjs +3 -8
  114. package/build-module/post-title/edit.mjs.map +2 -2
  115. package/build-module/private-apis.mjs +0 -2
  116. package/build-module/private-apis.mjs.map +2 -2
  117. package/build-module/query/block.json +3 -0
  118. package/build-module/query-no-results/block.json +16 -1
  119. package/build-module/rss/edit.mjs +2 -2
  120. package/build-module/rss/edit.mjs.map +1 -1
  121. package/build-module/site-logo/edit.mjs +1 -1
  122. package/build-module/site-logo/edit.mjs.map +2 -2
  123. package/build-module/site-title/edit.mjs +2 -6
  124. package/build-module/site-title/edit.mjs.map +2 -2
  125. package/build-module/table-of-contents/block.json +2 -1
  126. package/build-module/table-of-contents/deprecated.mjs +144 -0
  127. package/build-module/table-of-contents/deprecated.mjs.map +7 -0
  128. package/build-module/table-of-contents/index.mjs +2 -2
  129. package/build-module/table-of-contents/index.mjs.map +2 -2
  130. package/build-module/tabs/view.mjs +32 -2
  131. package/build-module/tabs/view.mjs.map +2 -2
  132. package/build-module/term-template/edit.mjs +5 -1
  133. package/build-module/term-template/edit.mjs.map +2 -2
  134. package/build-style/categories/style-rtl.css +2 -1
  135. package/build-style/categories/style.css +2 -1
  136. package/build-style/comments/editor-rtl.css +8 -10
  137. package/build-style/comments/editor.css +8 -10
  138. package/build-style/comments/style-rtl.css +8 -7
  139. package/build-style/comments/style.css +8 -7
  140. package/build-style/editor-rtl.css +8 -10
  141. package/build-style/editor.css +8 -10
  142. package/build-style/form-input/style-rtl.css +7 -7
  143. package/build-style/form-input/style.css +7 -7
  144. package/build-style/post-comments-form/style-rtl.css +7 -6
  145. package/build-style/post-comments-form/style.css +7 -6
  146. package/build-style/query-no-results/style-rtl.css +3 -0
  147. package/build-style/query-no-results/style.css +3 -0
  148. package/build-style/search/style-rtl.css +1 -1
  149. package/build-style/search/style.css +1 -1
  150. package/build-style/search/theme-rtl.css +1 -1
  151. package/build-style/search/theme.css +1 -1
  152. package/build-style/style-rtl.css +34 -23
  153. package/build-style/style.css +34 -23
  154. package/build-style/tab-panel/style-rtl.css +5 -1
  155. package/build-style/tab-panel/style.css +5 -1
  156. package/build-style/theme-rtl.css +1 -1
  157. package/build-style/theme.css +1 -1
  158. package/package.json +43 -43
  159. package/src/accordion/view.js +2 -5
  160. package/src/accordion-heading/README.md +1 -0
  161. package/src/accordion-heading/block.json +1 -0
  162. package/src/audio/edit.js +13 -0
  163. package/src/avatar/edit.js +78 -0
  164. package/src/block/README.md +1 -0
  165. package/src/block/block.json +2 -1
  166. package/src/categories/style.scss +4 -4
  167. package/src/column/edit.js +15 -1
  168. package/src/columns/edit.js +18 -0
  169. package/src/columns/test/transforms.js +517 -1
  170. package/src/columns/transforms.js +207 -2
  171. package/src/comments/style.scss +7 -10
  172. package/src/cover/edit/block-controls.js +1 -1
  173. package/src/cover/edit/index.js +1 -1
  174. package/src/cover/edit/inspector-controls.js +2 -2
  175. package/src/embed/embed-placeholder.js +2 -2
  176. package/src/form-input/style.scss +2 -2
  177. package/src/gallery/test/edit.js +57 -0
  178. package/src/gallery/test/transforms.js +57 -0
  179. package/src/gallery/transforms.js +8 -0
  180. package/src/group/README.md +1 -1
  181. package/src/group/block.json +1 -1
  182. package/src/heading/transforms.js +36 -0
  183. package/src/heading/variations.js +12 -0
  184. package/src/home-link/edit.js +2 -2
  185. package/src/icon/edit.js +9 -1
  186. package/src/image/image.js +4 -4
  187. package/src/list/README.md +1 -0
  188. package/src/list/block.json +1 -0
  189. package/src/math/edit.js +4 -9
  190. package/src/media-text/edit.js +2 -2
  191. package/src/more/README.md +1 -1
  192. package/src/more/block.json +1 -1
  193. package/src/navigation/index.php +8 -2
  194. package/src/navigation-link/shared/controls.js +2 -2
  195. package/src/playlist/block.json +0 -1
  196. package/src/playlist/edit.js +54 -21
  197. package/src/playlist/test/edit-component.js +78 -27
  198. package/src/playlist-track/README.md +8 -8
  199. package/src/playlist-track/block.json +16 -8
  200. package/src/playlist-track/edit.js +56 -27
  201. package/src/playlist-track/test/edit.js +145 -41
  202. package/src/post-comments-form/style.scss +7 -9
  203. package/src/post-template/edit.js +10 -1
  204. package/src/post-title/edit.js +2 -9
  205. package/src/private-apis.js +0 -2
  206. package/src/query/README.md +2 -0
  207. package/src/query/block.json +3 -0
  208. package/src/query-no-results/README.md +3 -0
  209. package/src/query-no-results/block.json +16 -1
  210. package/src/query-no-results/style.scss +5 -0
  211. package/src/rss/edit.js +2 -2
  212. package/src/search/style.scss +1 -1
  213. package/src/search/theme.scss +2 -4
  214. package/src/site-logo/edit.js +1 -1
  215. package/src/site-title/edit.js +1 -10
  216. package/src/social-link/index.php +6 -13
  217. package/src/style.scss +1 -0
  218. package/src/tab-panel/index.php +14 -5
  219. package/src/tab-panel/style.scss +7 -1
  220. package/src/table-of-contents/README.md +6 -6
  221. package/src/table-of-contents/block.json +2 -1
  222. package/src/table-of-contents/deprecated.js +173 -0
  223. package/src/table-of-contents/index.js +2 -2
  224. package/src/table-of-contents/index.php +16 -3
  225. package/src/tabs/index.php +5 -5
  226. package/src/tabs/view.js +32 -2
  227. package/src/term-description/index.php +1 -1
  228. package/src/term-template/edit.js +10 -1
  229. package/src/utils/test/waveform-player-dependency.js +0 -74
  230. package/build/block-keyboard-shortcuts/index.cjs +0 -131
  231. package/build/block-keyboard-shortcuts/index.cjs.map +0 -7
  232. package/build/table-of-contents/save.cjs +0 -55
  233. package/build/table-of-contents/save.cjs.map +0 -7
  234. package/build-module/block-keyboard-shortcuts/index.mjs +0 -113
  235. package/build-module/block-keyboard-shortcuts/index.mjs.map +0 -7
  236. package/build-module/table-of-contents/save.mjs +0 -24
  237. package/build-module/table-of-contents/save.mjs.map +0 -7
  238. package/src/block-keyboard-shortcuts/index.js +0 -135
  239. package/src/table-of-contents/save.js +0 -22
@@ -1,9 +1,42 @@
1
1
  import {
2
+ cloneSanitizedBlock,
2
3
  createBlock,
3
4
  createBlocksFromInnerBlocksTemplate,
5
+ getBlockType,
4
6
  } from '@wordpress/blocks';
5
7
 
6
8
  const MAXIMUM_SELECTED_BLOCKS = 6;
9
+ const COLUMN_VERTICAL_ALIGNMENTS = [ 'top', 'center', 'bottom' ];
10
+ const ROW_VERTICAL_ALIGNMENTS = [ ...COLUMN_VERTICAL_ALIGNMENTS, 'stretch' ];
11
+ const FLEX_SIZE_LAYOUT_VALUES = [ 'fixed', 'fixedNoShrink' ];
12
+ const DEFAULT_COLUMN_LAYOUT = { type: 'default' };
13
+
14
+ const getObjectValue = ( value ) =>
15
+ value && typeof value === 'object' && ! Array.isArray( value ) ? value : {};
16
+
17
+ const getGroupAttributes = ( attributes ) => {
18
+ const groupAttributeDefinitions = getBlockType( 'core/group' )?.attributes;
19
+ if ( ! groupAttributeDefinitions ) {
20
+ return {};
21
+ }
22
+ const normalizedAttributes = getObjectValue( attributes );
23
+
24
+ return Object.fromEntries(
25
+ Object.entries( normalizedAttributes ).filter( ( [ name ] ) =>
26
+ Object.hasOwn( groupAttributeDefinitions, name )
27
+ )
28
+ );
29
+ };
30
+
31
+ const getColumnWidth = ( width ) => {
32
+ if ( Number.isFinite( width ) ) {
33
+ return `${ width }%`;
34
+ }
35
+ if ( typeof width === 'string' && /\d/.test( width ) ) {
36
+ return width;
37
+ }
38
+ return undefined;
39
+ };
7
40
 
8
41
  const getColumnBlocksFromGrid = ( innerBlocks, columnCount ) => {
9
42
  const columnWidth = +( 100 / columnCount ).toFixed( 2 );
@@ -22,14 +55,66 @@ const getColumnBlocksFromGrid = ( innerBlocks, columnCount ) => {
22
55
  return createBlocksFromInnerBlocksTemplate( innerBlocksTemplate );
23
56
  };
24
57
 
58
+ const getColumnBlocksFromRow = ( innerBlocks ) =>
59
+ innerBlocks.map( ( innerBlock ) => {
60
+ const style = getObjectValue( innerBlock?.attributes?.style );
61
+ const { selfStretch, flexSize, ...remainingLayout } = getObjectValue(
62
+ style.layout
63
+ );
64
+ const columnWidth = FLEX_SIZE_LAYOUT_VALUES.includes( selfStretch )
65
+ ? getColumnWidth( flexSize )
66
+ : undefined;
67
+
68
+ const updatedStyle = { ...style };
69
+ if ( Object.keys( remainingLayout ).length ) {
70
+ updatedStyle.layout = remainingLayout;
71
+ } else {
72
+ delete updatedStyle.layout;
73
+ }
74
+ const columnInnerBlock = cloneSanitizedBlock( innerBlock, {
75
+ style: Object.keys( updatedStyle ).length
76
+ ? updatedStyle
77
+ : undefined,
78
+ } );
79
+
80
+ return createBlock(
81
+ 'core/column',
82
+ columnWidth ? { width: columnWidth } : {},
83
+ [ columnInnerBlock ]
84
+ );
85
+ } );
86
+
25
87
  const getGridInnerBlocks = ( innerBlocks ) =>
26
88
  innerBlocks.flatMap( ( column ) => {
27
89
  const columnInnerBlocks = column.innerBlocks || [];
28
- if ( columnInnerBlocks.length > 1 ) {
90
+ const {
91
+ layout: layoutAttribute,
92
+ style: styleAttribute,
93
+ ...groupAttributes
94
+ } = getGroupAttributes( column?.attributes );
95
+ const columnStyle = getObjectValue( styleAttribute );
96
+ const columnLayout = getObjectValue( layoutAttribute );
97
+ const hasGroupAttributes = Object.keys( groupAttributes ).length > 0;
98
+ const hasColumnStyle = Object.keys( columnStyle ).length > 0;
99
+ const hasColumnLayout = Object.keys( columnLayout ).length > 0;
100
+ if (
101
+ columnInnerBlocks.length > 1 ||
102
+ hasGroupAttributes ||
103
+ hasColumnStyle ||
104
+ hasColumnLayout
105
+ ) {
29
106
  return [
30
107
  createBlock(
31
108
  'core/group',
32
- { layout: { type: 'constrained' } },
109
+ {
110
+ ...groupAttributes,
111
+ layout: hasColumnLayout
112
+ ? columnLayout
113
+ : DEFAULT_COLUMN_LAYOUT,
114
+ ...( hasColumnStyle && {
115
+ style: columnStyle,
116
+ } ),
117
+ },
33
118
  columnInnerBlocks
34
119
  ),
35
120
  ];
@@ -37,6 +122,78 @@ const getGridInnerBlocks = ( innerBlocks ) =>
37
122
  return columnInnerBlocks;
38
123
  } );
39
124
 
125
+ const getRowInnerBlocks = ( innerBlocks ) => {
126
+ const columnWidths = innerBlocks.map( ( column ) => {
127
+ return getColumnWidth( column?.attributes?.width );
128
+ } );
129
+ const allColumnWidthsUnavailable = columnWidths.every(
130
+ ( columnWidth ) => ! columnWidth
131
+ );
132
+ const equalColumnWidth = innerBlocks.length
133
+ ? `${ +( 100 / innerBlocks.length ).toFixed( 2 ) }%`
134
+ : undefined;
135
+
136
+ return innerBlocks.map( ( column, index ) => {
137
+ const columnInnerBlocks = Array.isArray( column?.innerBlocks )
138
+ ? column.innerBlocks
139
+ : [];
140
+ const columnWidth =
141
+ columnWidths[ index ] ||
142
+ ( allColumnWidthsUnavailable ? equalColumnWidth : undefined );
143
+ const childLayout = columnWidth
144
+ ? { selfStretch: 'fixed', flexSize: columnWidth }
145
+ : { selfStretch: 'fill' };
146
+ const {
147
+ layout: layoutAttribute,
148
+ style: styleAttribute,
149
+ ...groupAttributes
150
+ } = getGroupAttributes( column?.attributes );
151
+ const columnStyle = getObjectValue( styleAttribute );
152
+ const columnLayout = getObjectValue( layoutAttribute );
153
+ const hasGroupAttributes = Object.keys( groupAttributes ).length > 0;
154
+ const hasColumnStyle = Object.keys( columnStyle ).length > 0;
155
+ const hasColumnLayout = Object.keys( columnLayout ).length > 0;
156
+
157
+ if (
158
+ columnInnerBlocks.length === 1 &&
159
+ ! hasGroupAttributes &&
160
+ ! hasColumnStyle &&
161
+ ! hasColumnLayout
162
+ ) {
163
+ const innerBlock = columnInnerBlocks[ 0 ];
164
+ const style = getObjectValue( innerBlock.attributes?.style );
165
+ const layout = getObjectValue( style.layout );
166
+ const updatedLayout = { ...layout, ...childLayout };
167
+ if ( ! columnWidth ) {
168
+ delete updatedLayout.flexSize;
169
+ }
170
+
171
+ return cloneSanitizedBlock( innerBlock, {
172
+ style: {
173
+ ...style,
174
+ layout: updatedLayout,
175
+ },
176
+ } );
177
+ }
178
+
179
+ return createBlock(
180
+ 'core/group',
181
+ {
182
+ ...groupAttributes,
183
+ layout: hasColumnLayout ? columnLayout : DEFAULT_COLUMN_LAYOUT,
184
+ style: {
185
+ ...columnStyle,
186
+ layout: {
187
+ ...getObjectValue( columnStyle.layout ),
188
+ ...childLayout,
189
+ },
190
+ },
191
+ },
192
+ columnInnerBlocks
193
+ );
194
+ } );
195
+ };
196
+
40
197
  const transforms = {
41
198
  from: [
42
199
  {
@@ -58,6 +215,27 @@ const transforms = {
58
215
  Number.isInteger( layout?.columnCount ) &&
59
216
  layout.columnCount > 0,
60
217
  },
218
+ {
219
+ type: 'block',
220
+ blocks: [ 'core/group' ],
221
+ priority: 1,
222
+ transform: ( attributes, innerBlocks ) => {
223
+ const { layout, ...rest } = attributes;
224
+ const verticalAlignment = COLUMN_VERTICAL_ALIGNMENTS.includes(
225
+ layout?.verticalAlignment
226
+ )
227
+ ? layout.verticalAlignment
228
+ : undefined;
229
+
230
+ return createBlock(
231
+ 'core/columns',
232
+ { ...rest, verticalAlignment },
233
+ getColumnBlocksFromRow( innerBlocks )
234
+ );
235
+ },
236
+ isMatch: ( { layout } ) =>
237
+ layout?.type === 'flex' && layout?.orientation !== 'vertical',
238
+ },
61
239
  {
62
240
  type: 'block',
63
241
  isMultiBlock: true,
@@ -161,6 +339,33 @@ const transforms = {
161
339
  },
162
340
  ],
163
341
  to: [
342
+ {
343
+ type: 'block',
344
+ blocks: [ 'core/group' ],
345
+ variationName: 'group-row',
346
+ transform: ( attributes, innerBlocks ) => {
347
+ const { verticalAlignment } = attributes;
348
+ const rowVerticalAlignment = ROW_VERTICAL_ALIGNMENTS.includes(
349
+ verticalAlignment
350
+ )
351
+ ? verticalAlignment
352
+ : 'stretch';
353
+ return createBlock(
354
+ 'core/group',
355
+ {
356
+ ...attributes,
357
+ isStackedOnMobile: undefined,
358
+ verticalAlignment: undefined,
359
+ layout: {
360
+ type: 'flex',
361
+ flexWrap: 'nowrap',
362
+ verticalAlignment: rowVerticalAlignment,
363
+ },
364
+ },
365
+ getRowInnerBlocks( innerBlocks )
366
+ );
367
+ },
368
+ },
164
369
  {
165
370
  type: 'block',
166
371
  blocks: [ 'core/group' ],
@@ -84,16 +84,6 @@
84
84
  font-size: 0.875em;
85
85
  }
86
86
 
87
- .comment-form-comment,
88
- .comment-form-author,
89
- .comment-form-email,
90
- .comment-form-url {
91
- label {
92
- display: block;
93
- margin-bottom: 0.25em;
94
- }
95
- }
96
-
97
87
  .comment-form {
98
88
 
99
89
  textarea,
@@ -140,6 +130,13 @@
140
130
  }
141
131
  }
142
132
 
133
+ :where(.wp-block-post-comments .comment-form-comment label),
134
+ :where(.wp-block-post-comments .comment-form-author label),
135
+ :where(.wp-block-post-comments .comment-form-email label),
136
+ :where(.wp-block-post-comments .comment-form-url label) {
137
+ display: block;
138
+ margin-bottom: 0.25em;
139
+ }
143
140
 
144
141
  // Using :where to give this a low specificity so that element styles take precedence.
145
142
  // Needed for backwards compatibility.
@@ -113,7 +113,7 @@ export default function CoverBlockControls( {
113
113
  <ToolbarButton
114
114
  ref={ editMediaButtonRef }
115
115
  icon={ crop }
116
- label={ __( 'Crop background image' ) }
116
+ label={ __( 'Edit image' ) }
117
117
  onClick={ onEditMedia }
118
118
  aria-haspopup="dialog"
119
119
  // Disable rather than hide while the edited image
@@ -760,7 +760,7 @@ function CoverEdit( {
760
760
  value={ overlayColor.color }
761
761
  onChange={ onSetOverlayColor }
762
762
  clearable={ false }
763
- asButtons
763
+ presentation="toggle-buttons"
764
764
  aria-label={ __( 'Overlay color' ) }
765
765
  />
766
766
  </div>
@@ -2,7 +2,7 @@ import { useMemo } from '@wordpress/element';
2
2
  import {
3
3
  FocalPointPicker,
4
4
  RangeControl,
5
- TextareaControl,
5
+ TextareaControl as WCTextareaControl,
6
6
  ToggleControl,
7
7
  __experimentalUseCustomUnits as useCustomUnits,
8
8
  __experimentalToolsPanel as ToolsPanel,
@@ -377,7 +377,7 @@ export default function CoverInspectorControls( {
377
377
  setAttributes( { alt: '' } )
378
378
  }
379
379
  >
380
- <TextareaControl
380
+ <WCTextareaControl
381
381
  label={ __( 'Alternative text' ) }
382
382
  value={ alt }
383
383
  onChange={ ( newAlt ) =>
@@ -2,7 +2,7 @@ import { __, _x } from '@wordpress/i18n';
2
2
  import {
3
3
  Button,
4
4
  Placeholder,
5
- __experimentalInputControl as InputControl,
5
+ __experimentalInputControl as WCInputControl,
6
6
  } from '@wordpress/components';
7
7
  import { BlockIcon } from '@wordpress/block-editor';
8
8
  import { Link, Stack } from '@wordpress/ui';
@@ -27,7 +27,7 @@ export default function EmbedPlaceholder( {
27
27
  ) }
28
28
  >
29
29
  <form onSubmit={ onSubmit }>
30
- <InputControl
30
+ <WCInputControl
31
31
  type="url"
32
32
  value={ value || '' }
33
33
  className="wp-block-embed__placeholder-input"
@@ -1,4 +1,4 @@
1
- .wp-block-form-input__label {
1
+ :where(.wp-block-form-input__label) {
2
2
  width: 100%;
3
3
  display: flex;
4
4
  flex-direction: column;
@@ -30,7 +30,7 @@
30
30
  }
31
31
  }
32
32
 
33
- .wp-block-form-input__label-content {
33
+ :where(.wp-block-form-input__label-content) {
34
34
  width: fit-content;
35
35
  }
36
36
 
@@ -0,0 +1,57 @@
1
+ import { screen } from '@testing-library/react';
2
+ import { createBlock } from '@wordpress/blocks';
3
+ import {
4
+ initializeEditor,
5
+ selectBlock,
6
+ } from '@wordpress/integration-tests/helpers/integration-test-editor';
7
+ import { registerCoreBlocks } from '@wordpress/block-library';
8
+
9
+ const IMAGE_ATTRIBUTES = {
10
+ id: 1,
11
+ url: 'https://example.com/image.jpg',
12
+ alt: 'Example image',
13
+ };
14
+
15
+ /**
16
+ * Registers the core blocks up front so inner blocks can be created before the
17
+ * editor is initialized, then renders the given block.
18
+ *
19
+ * @param {Object} block Block to render, created with `createBlock`.
20
+ */
21
+ async function setup( block ) {
22
+ return initializeEditor( block, false );
23
+ }
24
+
25
+ describe( 'Gallery block', () => {
26
+ beforeEach( () => {
27
+ registerCoreBlocks();
28
+ } );
29
+
30
+ describe( 'Block toolbar', () => {
31
+ test( 'does not offer alignment for an image inside a gallery', async () => {
32
+ await setup(
33
+ createBlock( 'core/gallery', {}, [
34
+ createBlock( 'core/image', IMAGE_ATTRIBUTES ),
35
+ ] )
36
+ );
37
+
38
+ await selectBlock( 'Block: Image' );
39
+
40
+ // The gallery lays its images out with the flex layout, which
41
+ // permits no alignments, so the child image must not offer them.
42
+ expect(
43
+ screen.queryByRole( 'button', { name: 'Align block' } )
44
+ ).not.toBeInTheDocument();
45
+ } );
46
+
47
+ test( 'offers alignment for an image outside a gallery', async () => {
48
+ await setup( createBlock( 'core/image', IMAGE_ATTRIBUTES ) );
49
+
50
+ await selectBlock( 'Block: Image' );
51
+
52
+ expect(
53
+ screen.getByRole( 'button', { name: 'Align block' } )
54
+ ).toBeInTheDocument();
55
+ } );
56
+ } );
57
+ } );
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  createBlock,
3
3
  getBlockTypes,
4
+ getPossibleBlockTransformations,
4
5
  registerBlockType,
5
6
  switchToBlockType,
6
7
  unregisterBlockType,
@@ -13,6 +14,7 @@ import {
13
14
  metadata as groupMetadata,
14
15
  settings as groupSettings,
15
16
  } from '../../group';
17
+ import { ATTACHED_MEDIA } from '../dynamic-source';
16
18
 
17
19
  describe( 'transforms', () => {
18
20
  beforeAll( () => {
@@ -145,4 +147,59 @@ describe( 'transforms', () => {
145
147
  },
146
148
  } );
147
149
  } );
150
+ it( 'transforms an empty static Gallery to the Grid variation of Group', () => {
151
+ const block = createBlock( 'core/gallery', {}, [] );
152
+
153
+ const transformedBlocks = switchToBlockType(
154
+ block,
155
+ 'core/group',
156
+ 'group-grid'
157
+ );
158
+
159
+ expect( transformedBlocks[ 0 ] ).toMatchObject( {
160
+ name: 'core/group',
161
+ attributes: { layout: { type: 'grid' } },
162
+ } );
163
+ } );
164
+
165
+ describe( 'dynamic mode', () => {
166
+ const createDynamicGallery = () =>
167
+ createBlock(
168
+ 'core/gallery',
169
+ { dynamicContent: { source: ATTACHED_MEDIA } },
170
+ []
171
+ );
172
+
173
+ it( 'does not transform a dynamic Gallery to the Grid variation of Group', () => {
174
+ expect(
175
+ switchToBlockType(
176
+ createDynamicGallery(),
177
+ 'core/group',
178
+ 'group-grid'
179
+ )
180
+ ).toBeNull();
181
+ } );
182
+
183
+ it( 'does not transform a dynamic Gallery to Image', () => {
184
+ expect(
185
+ switchToBlockType( createDynamicGallery(), 'core/image' )
186
+ ).toBeNull();
187
+ } );
188
+
189
+ it( 'does not offer the Image or Grid transforms for a dynamic Gallery', () => {
190
+ const transformations = getPossibleBlockTransformations( [
191
+ createDynamicGallery(),
192
+ ] );
193
+
194
+ expect(
195
+ transformations.find( ( { name } ) => name === 'core/image' )
196
+ ).toBeUndefined();
197
+ expect(
198
+ transformations.find(
199
+ ( { name, variationName } ) =>
200
+ name === 'core/group' && variationName === 'group-grid'
201
+ )
202
+ ).toBeUndefined();
203
+ } );
204
+ } );
148
205
  } );
@@ -223,6 +223,10 @@ const transforms = {
223
223
  {
224
224
  type: 'block',
225
225
  blocks: [ 'core/image' ],
226
+ // A dynamic gallery has no inner blocks — its images are resolved
227
+ // from a source at render time — so this transform would produce a
228
+ // single empty image and drop the source.
229
+ isMatch: ( { dynamicContent } ) => ! dynamicContent,
226
230
  transform: ( { align }, innerBlocks ) => {
227
231
  if ( innerBlocks.length > 0 ) {
228
232
  return innerBlocks.map(
@@ -268,12 +272,16 @@ const transforms = {
268
272
  type: 'block',
269
273
  blocks: [ 'core/group' ],
270
274
  variationName: 'group-grid',
275
+ // As above: with no inner blocks to clone, a dynamic gallery would
276
+ // transform into an empty grid.
277
+ isMatch: ( { dynamicContent } ) => ! dynamicContent,
271
278
  transform: ( attributes, innerBlocks ) => {
272
279
  const {
273
280
  allowResize,
274
281
  aspectRatio,
275
282
  caption,
276
283
  columns,
284
+ dynamicContent,
277
285
  fixedHeight,
278
286
  ids,
279
287
  imageCrop,
@@ -39,7 +39,7 @@ _Defined via the [`supports`](https://developer.wordpress.org/block-editor/refer
39
39
  - [`spacing`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#spacing):
40
40
  - `margin`: `["top","bottom"]`
41
41
  - `padding`: `true`
42
- - `blockGap`: `true`
42
+ - `blockGap`: `["horizontal","vertical"]`
43
43
  - [`dimensions`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#dimensions):
44
44
  - `minHeight`: `true`
45
45
  - `minWidth`: `true`
@@ -47,7 +47,7 @@
47
47
  "spacing": {
48
48
  "margin": [ "top", "bottom" ],
49
49
  "padding": true,
50
- "blockGap": true,
50
+ "blockGap": [ "horizontal", "vertical" ],
51
51
  "__experimentalDefaultControls": {
52
52
  "padding": true,
53
53
  "blockGap": true
@@ -1,4 +1,5 @@
1
1
  import { createBlock, getBlockAttributes } from '@wordpress/blocks';
2
+ import { __, sprintf } from '@wordpress/i18n';
2
3
  import { getLevelFromHeadingNodeName } from './shared';
3
4
  import { getTransformedAttributes } from '../utils/get-transformed-attributes';
4
5
 
@@ -8,6 +9,23 @@ const transforms = {
8
9
  type: 'block',
9
10
  isMultiBlock: true,
10
11
  blocks: [ 'core/paragraph' ],
12
+ // The level shortcuts are declared here as well as on the
13
+ // variations, so that they reach a paragraph and not only a
14
+ // heading. Both declarations describe the same shortcut, and only
15
+ // one of them can apply to any given selection.
16
+ shortcuts: [ 1, 2, 3, 4, 5, 6 ].map( ( level ) => ( {
17
+ name: `core/block-editor/transform-to-heading-${ level }`,
18
+ description: sprintf(
19
+ /* translators: %d: heading level e.g: "1", "2", "3" */
20
+ __( 'Transform the selected block into a heading %d.' ),
21
+ level
22
+ ),
23
+ keyCombination: {
24
+ modifier: 'access',
25
+ character: `${ level }`,
26
+ },
27
+ variationName: `h${ level }`,
28
+ } ) ),
11
29
  transform: ( attributes ) =>
12
30
  attributes.map( ( _attributes ) => {
13
31
  const { content, anchor, style } = _attributes;
@@ -96,6 +114,24 @@ const transforms = {
96
114
  type: 'block',
97
115
  isMultiBlock: true,
98
116
  blocks: [ 'core/paragraph' ],
117
+ shortcuts: [
118
+ {
119
+ name: 'core/block-editor/transform-heading-to-paragraph',
120
+ description: __(
121
+ 'Transform the selected heading into a paragraph.'
122
+ ),
123
+ keyCombination: {
124
+ modifier: 'access',
125
+ character: '0',
126
+ },
127
+ aliases: [
128
+ {
129
+ modifier: 'access',
130
+ character: '7',
131
+ },
132
+ ],
133
+ },
134
+ ],
99
135
  transform: ( attributes ) =>
100
136
  attributes.map( ( _attributes ) => {
101
137
  const { content, style } = _attributes;
@@ -33,6 +33,18 @@ const variations = [
33
33
  scope: [ 'block', 'transform' ],
34
34
  keywords: [ `h${ level }` ],
35
35
  isActive: ( blockAttributes ) => blockAttributes.level === level,
36
+ shortcut: {
37
+ name: `core/block-editor/transform-to-heading-${ level }`,
38
+ description: sprintf(
39
+ /* translators: %d: heading level e.g: "1", "2", "3" */
40
+ __( 'Transform the selected block into a heading %d.' ),
41
+ level
42
+ ),
43
+ keyCombination: {
44
+ modifier: 'access',
45
+ character: `${ level }`,
46
+ },
47
+ },
36
48
  } ) ),
37
49
  ];
38
50
 
@@ -9,7 +9,7 @@ import {
9
9
  Button,
10
10
  CheckboxControl,
11
11
  TextControl,
12
- TextareaControl,
12
+ TextareaControl as WCTextareaControl,
13
13
  __experimentalToolsPanel as ToolsPanel,
14
14
  __experimentalToolsPanelItem as ToolsPanelItem,
15
15
  } from '@wordpress/components';
@@ -165,7 +165,7 @@ export default function HomeEdit( { attributes, setAttributes, context } ) {
165
165
  }
166
166
  isShownByDefault
167
167
  >
168
- <TextareaControl
168
+ <WCTextareaControl
169
169
  label={ __( 'Description' ) }
170
170
  value={ description || '' }
171
171
  onChange={ ( descriptionValue ) => {
package/src/icon/edit.js CHANGED
@@ -59,7 +59,15 @@ export function Edit( { attributes, setAttributes } ) {
59
59
  const isContentOnlyMode = useBlockEditingMode() === 'contentOnly';
60
60
 
61
61
  const colorProps = useColorProps( attributes );
62
- const spacingProps = useSpacingProps( attributes );
62
+ // Only padding is applied to the inner SVG element, matching the front
63
+ // end. The margin support is serialized to the block wrapper instead.
64
+ const spacingProps = useSpacingProps( {
65
+ style: {
66
+ spacing: {
67
+ padding: attributes.style?.spacing?.padding,
68
+ },
69
+ },
70
+ } );
63
71
  const borderProps = useBorderProps( attributes );
64
72
  const dimensionsProps = useDimensionsProps( attributes );
65
73
 
@@ -4,7 +4,7 @@ import {
4
4
  FocalPointPicker,
5
5
  ResizableBox,
6
6
  Spinner,
7
- TextareaControl,
7
+ TextareaControl as WCTextareaControl,
8
8
  TextControl,
9
9
  CheckboxControl,
10
10
  ToolbarButton,
@@ -185,7 +185,7 @@ function ContentOnlyControls( {
185
185
  variant="toolbar"
186
186
  >
187
187
  <div className="wp-block-image__toolbar_content_textarea__container">
188
- <TextareaControl
188
+ <WCTextareaControl
189
189
  className="wp-block-image__toolbar_content_textarea"
190
190
  label={ __( 'Alternative text' ) }
191
191
  value={ attributes.alt || '' }
@@ -918,7 +918,7 @@ export default function Image( {
918
918
  onClick={ openImageMediaEditorModal }
919
919
  aria-haspopup="dialog"
920
920
  icon={ crop }
921
- label={ __( 'Crop' ) }
921
+ label={ __( 'Edit image' ) }
922
922
  // Disable rather than hide while the edited image
923
923
  // loads, so the button keeps focus when the modal
924
924
  // closes instead of dropping it to the canvas.
@@ -1006,7 +1006,7 @@ export default function Image( {
1006
1006
  setAttributes( { alt: undefined } )
1007
1007
  }
1008
1008
  >
1009
- <TextareaControl
1009
+ <WCTextareaControl
1010
1010
  label={ __( 'Alternative text' ) }
1011
1011
  value={ alt || '' }
1012
1012
  onChange={ updateAlt }
@@ -32,6 +32,7 @@ _Defined via the [`attributes`](https://developer.wordpress.org/block-editor/ref
32
32
  _Defined via the [`supports`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/) property in block.json._
33
33
 
34
34
  - [`anchor`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#anchor): `true`
35
+ - [`align`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#align): `"wide"`, `"full"`
35
36
  - [`html`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#html): `false`
36
37
  - [`typography`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#typography):
37
38
  - [`fontSize`](https://developer.wordpress.org/block-editor/reference-guides/block-api/block-supports/#typography-fontsize): `true`