@wordpress/block-library 8.20.1 → 8.21.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 (277) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +12 -0
  3. package/build/block/index.js +2 -1
  4. package/build/block/index.js.map +1 -1
  5. package/build/code/edit.native.js +8 -2
  6. package/build/code/edit.native.js.map +1 -1
  7. package/build/cover/deprecated.js +110 -1
  8. package/build/cover/deprecated.js.map +1 -1
  9. package/build/cover/edit/index.js +9 -3
  10. package/build/cover/edit/index.js.map +1 -1
  11. package/build/cover/edit/inspector-controls.js +1 -2
  12. package/build/cover/edit/inspector-controls.js.map +1 -1
  13. package/build/cover/index.js +0 -3
  14. package/build/cover/index.js.map +1 -1
  15. package/build/cover/save.js +2 -1
  16. package/build/cover/save.js.map +1 -1
  17. package/build/cover/shared.js +1 -1
  18. package/build/cover/shared.js.map +1 -1
  19. package/build/footnotes/index.js +1 -0
  20. package/build/footnotes/index.js.map +1 -1
  21. package/build/form/edit.js +138 -0
  22. package/build/form/edit.js.map +1 -0
  23. package/build/form/index.js +92 -0
  24. package/build/form/index.js.map +1 -0
  25. package/build/form/init.js +13 -0
  26. package/build/form/init.js.map +1 -0
  27. package/build/form/save.js +28 -0
  28. package/build/form/save.js.map +1 -0
  29. package/build/form/utils.js +24 -0
  30. package/build/form/utils.js.map +1 -0
  31. package/build/form/variations.js +95 -0
  32. package/build/form/variations.js.map +1 -0
  33. package/build/form/view.js +42 -0
  34. package/build/form/view.js.map +1 -0
  35. package/build/form-input/edit.js +124 -0
  36. package/build/form-input/edit.js.map +1 -0
  37. package/build/form-input/index.js +105 -0
  38. package/build/form-input/index.js.map +1 -0
  39. package/build/form-input/init.js +13 -0
  40. package/build/form-input/init.js.map +1 -0
  41. package/build/form-input/save.js +87 -0
  42. package/build/form-input/save.js.map +1 -0
  43. package/build/form-input/variations.js +93 -0
  44. package/build/form-input/variations.js.map +1 -0
  45. package/build/form-submission-notification/edit.js +59 -0
  46. package/build/form-submission-notification/edit.js.map +1 -0
  47. package/build/form-submission-notification/index.js +56 -0
  48. package/build/form-submission-notification/index.js.map +1 -0
  49. package/build/form-submission-notification/init.js +13 -0
  50. package/build/form-submission-notification/init.js.map +1 -0
  51. package/build/form-submission-notification/save.js +33 -0
  52. package/build/form-submission-notification/save.js.map +1 -0
  53. package/build/form-submission-notification/variations.js +63 -0
  54. package/build/form-submission-notification/variations.js.map +1 -0
  55. package/build/form-submit-button/edit.js +32 -0
  56. package/build/form-submit-button/edit.js.map +1 -0
  57. package/build/form-submit-button/index.js +44 -0
  58. package/build/form-submit-button/index.js.map +1 -0
  59. package/build/form-submit-button/init.js +13 -0
  60. package/build/form-submit-button/init.js.map +1 -0
  61. package/build/form-submit-button/save.js +22 -0
  62. package/build/form-submit-button/save.js.map +1 -0
  63. package/build/group/index.js +0 -1
  64. package/build/group/index.js.map +1 -1
  65. package/build/heading/index.js +3 -2
  66. package/build/heading/index.js.map +1 -1
  67. package/build/image/image.js +4 -1
  68. package/build/image/image.js.map +1 -1
  69. package/build/image/view.js +82 -40
  70. package/build/image/view.js.map +1 -1
  71. package/build/index.js +10 -0
  72. package/build/index.js.map +1 -1
  73. package/build/latest-posts/edit.js +6 -2
  74. package/build/latest-posts/edit.js.map +1 -1
  75. package/build/list-item/hooks/use-merge.js +15 -15
  76. package/build/list-item/hooks/use-merge.js.map +1 -1
  77. package/build/lock-unlock.js +1 -1
  78. package/build/lock-unlock.js.map +1 -1
  79. package/build/missing/edit.native.js +14 -62
  80. package/build/missing/edit.native.js.map +1 -1
  81. package/build/navigation/edit/index.js +0 -1
  82. package/build/navigation/edit/index.js.map +1 -1
  83. package/build/navigation/index.js +2 -1
  84. package/build/navigation/index.js.map +1 -1
  85. package/build/navigation/view.js +27 -5
  86. package/build/navigation/view.js.map +1 -1
  87. package/build/page-list-item/edit.js +3 -1
  88. package/build/page-list-item/edit.js.map +1 -1
  89. package/build/paragraph/index.js +7 -0
  90. package/build/paragraph/index.js.map +1 -1
  91. package/build/pattern/index.js +2 -1
  92. package/build/pattern/index.js.map +1 -1
  93. package/build/template-part/index.js +2 -1
  94. package/build/template-part/index.js.map +1 -1
  95. package/build-module/block/index.js +2 -1
  96. package/build-module/block/index.js.map +1 -1
  97. package/build-module/code/edit.native.js +8 -2
  98. package/build-module/code/edit.native.js.map +1 -1
  99. package/build-module/cover/deprecated.js +110 -1
  100. package/build-module/cover/deprecated.js.map +1 -1
  101. package/build-module/cover/edit/index.js +9 -3
  102. package/build-module/cover/edit/index.js.map +1 -1
  103. package/build-module/cover/edit/inspector-controls.js +1 -2
  104. package/build-module/cover/edit/inspector-controls.js.map +1 -1
  105. package/build-module/cover/index.js +0 -3
  106. package/build-module/cover/index.js.map +1 -1
  107. package/build-module/cover/save.js +2 -1
  108. package/build-module/cover/save.js.map +1 -1
  109. package/build-module/cover/shared.js +1 -1
  110. package/build-module/cover/shared.js.map +1 -1
  111. package/build-module/footnotes/index.js +1 -0
  112. package/build-module/footnotes/index.js.map +1 -1
  113. package/build-module/form/edit.js +130 -0
  114. package/build-module/form/edit.js.map +1 -0
  115. package/build-module/form/index.js +82 -0
  116. package/build-module/form/index.js.map +1 -0
  117. package/build-module/form/init.js +6 -0
  118. package/build-module/form/init.js.map +1 -0
  119. package/build-module/form/save.js +20 -0
  120. package/build-module/form/save.js.map +1 -0
  121. package/build-module/form/utils.js +15 -0
  122. package/build-module/form/utils.js.map +1 -0
  123. package/build-module/form/variations.js +86 -0
  124. package/build-module/form/variations.js.map +1 -0
  125. package/build-module/form/view.js +40 -0
  126. package/build-module/form/view.js.map +1 -0
  127. package/build-module/form-input/edit.js +115 -0
  128. package/build-module/form-input/edit.js.map +1 -0
  129. package/build-module/form-input/index.js +95 -0
  130. package/build-module/form-input/index.js.map +1 -0
  131. package/build-module/form-input/init.js +6 -0
  132. package/build-module/form-input/init.js.map +1 -0
  133. package/build-module/form-input/save.js +80 -0
  134. package/build-module/form-input/save.js.map +1 -0
  135. package/build-module/form-input/variations.js +85 -0
  136. package/build-module/form-input/variations.js.map +1 -0
  137. package/build-module/form-submission-notification/edit.js +50 -0
  138. package/build-module/form-submission-notification/edit.js.map +1 -0
  139. package/build-module/form-submission-notification/index.js +47 -0
  140. package/build-module/form-submission-notification/index.js.map +1 -0
  141. package/build-module/form-submission-notification/init.js +6 -0
  142. package/build-module/form-submission-notification/init.js.map +1 -0
  143. package/build-module/form-submission-notification/save.js +25 -0
  144. package/build-module/form-submission-notification/save.js.map +1 -0
  145. package/build-module/form-submission-notification/variations.js +55 -0
  146. package/build-module/form-submission-notification/variations.js.map +1 -0
  147. package/build-module/form-submit-button/edit.js +24 -0
  148. package/build-module/form-submit-button/edit.js.map +1 -0
  149. package/build-module/form-submit-button/index.js +34 -0
  150. package/build-module/form-submit-button/index.js.map +1 -0
  151. package/build-module/form-submit-button/init.js +6 -0
  152. package/build-module/form-submit-button/init.js.map +1 -0
  153. package/build-module/form-submit-button/save.js +14 -0
  154. package/build-module/form-submit-button/save.js.map +1 -0
  155. package/build-module/group/index.js +0 -1
  156. package/build-module/group/index.js.map +1 -1
  157. package/build-module/heading/index.js +3 -2
  158. package/build-module/heading/index.js.map +1 -1
  159. package/build-module/image/image.js +4 -1
  160. package/build-module/image/image.js.map +1 -1
  161. package/build-module/image/view.js +82 -40
  162. package/build-module/image/view.js.map +1 -1
  163. package/build-module/index.js +10 -0
  164. package/build-module/index.js.map +1 -1
  165. package/build-module/latest-posts/edit.js +6 -2
  166. package/build-module/latest-posts/edit.js.map +1 -1
  167. package/build-module/list-item/hooks/use-merge.js +15 -15
  168. package/build-module/list-item/hooks/use-merge.js.map +1 -1
  169. package/build-module/lock-unlock.js +1 -1
  170. package/build-module/lock-unlock.js.map +1 -1
  171. package/build-module/missing/edit.native.js +17 -65
  172. package/build-module/missing/edit.native.js.map +1 -1
  173. package/build-module/navigation/edit/index.js +0 -1
  174. package/build-module/navigation/edit/index.js.map +1 -1
  175. package/build-module/navigation/index.js +2 -1
  176. package/build-module/navigation/index.js.map +1 -1
  177. package/build-module/navigation/view.js +27 -5
  178. package/build-module/navigation/view.js.map +1 -1
  179. package/build-module/page-list-item/edit.js +3 -1
  180. package/build-module/page-list-item/edit.js.map +1 -1
  181. package/build-module/paragraph/index.js +7 -0
  182. package/build-module/paragraph/index.js.map +1 -1
  183. package/build-module/pattern/index.js +2 -1
  184. package/build-module/pattern/index.js.map +1 -1
  185. package/build-module/template-part/index.js +2 -1
  186. package/build-module/template-part/index.js.map +1 -1
  187. package/build-style/editor-rtl.css +50 -0
  188. package/build-style/editor.css +50 -0
  189. package/build-style/form-input/editor-rtl.css +106 -0
  190. package/build-style/form-input/editor.css +106 -0
  191. package/build-style/form-input/style-rtl.css +135 -0
  192. package/build-style/form-input/style.css +135 -0
  193. package/build-style/form-submission-notification/editor-rtl.css +118 -0
  194. package/build-style/form-submission-notification/editor.css +118 -0
  195. package/build-style/form-submit-button/style-rtl.css +91 -0
  196. package/build-style/form-submit-button/style.css +91 -0
  197. package/build-style/image/style-rtl.css +39 -5
  198. package/build-style/image/style.css +39 -5
  199. package/build-style/query/style-rtl.css +0 -10
  200. package/build-style/query/style.css +0 -10
  201. package/build-style/style-rtl.css +87 -5
  202. package/build-style/style.css +87 -5
  203. package/package.json +32 -32
  204. package/src/block/block.json +2 -1
  205. package/src/code/edit.native.js +15 -1
  206. package/src/cover/block.json +0 -3
  207. package/src/cover/deprecated.js +151 -1
  208. package/src/cover/edit/index.js +12 -3
  209. package/src/cover/edit/inspector-controls.js +19 -25
  210. package/src/cover/save.js +2 -1
  211. package/src/cover/shared.js +1 -1
  212. package/src/editor.scss +2 -0
  213. package/src/footnotes/block.json +1 -0
  214. package/src/form/block.json +60 -0
  215. package/src/form/edit.js +179 -0
  216. package/src/form/index.js +20 -0
  217. package/src/form/index.php +214 -0
  218. package/src/form/init.js +6 -0
  219. package/src/form/save.js +20 -0
  220. package/src/form/utils.js +39 -0
  221. package/src/form/variations.js +139 -0
  222. package/src/form/view.js +41 -0
  223. package/src/form-input/block.json +73 -0
  224. package/src/form-input/edit.js +151 -0
  225. package/src/form-input/editor.scss +24 -0
  226. package/src/form-input/index.js +20 -0
  227. package/src/form-input/index.php +45 -0
  228. package/src/form-input/init.js +6 -0
  229. package/src/form-input/save.js +83 -0
  230. package/src/form-input/style.scss +61 -0
  231. package/src/form-input/variations.js +82 -0
  232. package/src/form-submission-notification/block.json +19 -0
  233. package/src/form-submission-notification/edit.js +63 -0
  234. package/src/form-submission-notification/editor.scss +45 -0
  235. package/src/form-submission-notification/index.js +26 -0
  236. package/src/form-submission-notification/index.php +48 -0
  237. package/src/form-submission-notification/init.js +6 -0
  238. package/src/form-submission-notification/save.js +28 -0
  239. package/src/form-submission-notification/variations.js +59 -0
  240. package/src/form-submit-button/block.json +14 -0
  241. package/src/form-submit-button/edit.js +33 -0
  242. package/src/form-submit-button/index.js +18 -0
  243. package/src/form-submit-button/init.js +6 -0
  244. package/src/form-submit-button/save.js +14 -0
  245. package/src/form-submit-button/style.scss +3 -0
  246. package/src/group/block.json +0 -1
  247. package/src/heading/index.js +4 -2
  248. package/src/image/image.js +10 -0
  249. package/src/image/index.php +128 -82
  250. package/src/image/style.scss +49 -5
  251. package/src/image/view.js +100 -52
  252. package/src/index.js +10 -0
  253. package/src/latest-posts/edit.js +11 -2
  254. package/src/latest-posts/index.php +17 -8
  255. package/src/list-item/hooks/use-merge.js +20 -23
  256. package/src/lock-unlock.js +1 -1
  257. package/src/missing/edit.native.js +17 -115
  258. package/src/missing/style.native.scss +0 -67
  259. package/src/missing/test/edit-integration.native.js +135 -49
  260. package/src/missing/test/edit.native.js +0 -41
  261. package/src/navigation/block.json +2 -1
  262. package/src/navigation/edit/index.js +0 -1
  263. package/src/navigation/index.php +28 -8
  264. package/src/navigation/view.js +25 -6
  265. package/src/page-list-item/edit.js +2 -0
  266. package/src/paragraph/index.js +10 -0
  267. package/src/pattern/block.json +2 -1
  268. package/src/pattern/index.php +0 -3
  269. package/src/post-navigation-link/index.php +2 -1
  270. package/src/preformatted/test/edit.native.js +38 -0
  271. package/src/query/index.php +3 -2
  272. package/src/query/style.scss +0 -11
  273. package/src/search/index.php +0 -4
  274. package/src/style.scss +1 -0
  275. package/src/template-part/block.json +2 -1
  276. package/src/template-part/index.php +4 -7
  277. package/src/verse/test/edit.native.js +37 -0
package/src/image/view.js CHANGED
@@ -103,9 +103,10 @@ store(
103
103
  context.core.image.lastFocusedElement =
104
104
  window.document.activeElement;
105
105
  context.core.image.scrollDelta = 0;
106
+ context.core.image.pointerType = event.pointerType;
106
107
 
107
108
  context.core.image.lightboxEnabled = true;
108
- setStyles( context, event );
109
+ setStyles( context, context.core.image.imageRef );
109
110
 
110
111
  context.core.image.scrollTopReset =
111
112
  window.pageYOffset ||
@@ -134,7 +135,7 @@ store(
134
135
  false
135
136
  );
136
137
  },
137
- hideLightbox: async ( { context } ) => {
138
+ hideLightbox: async ( { context, event } ) => {
138
139
  context.core.image.hideAnimationEnabled = true;
139
140
  if ( context.core.image.lightboxEnabled ) {
140
141
  // We want to wait until the close animation is completed
@@ -151,9 +152,16 @@ store(
151
152
  }, 450 );
152
153
 
153
154
  context.core.image.lightboxEnabled = false;
154
- context.core.image.lastFocusedElement.focus( {
155
- preventScroll: true,
156
- } );
155
+
156
+ // We want to avoid drawing attention to the button
157
+ // after the lightbox closes for mouse and touch users.
158
+ // Note that the `event.pointerType` property returns
159
+ // as an empty string if a keyboard fired the event.
160
+ if ( event.pointerType === '' ) {
161
+ context.core.image.lastFocusedElement.focus( {
162
+ preventScroll: true,
163
+ } );
164
+ }
157
165
  }
158
166
  },
159
167
  handleKeydown: ( { context, actions, event } ) => {
@@ -188,11 +196,12 @@ store(
188
196
  }
189
197
  }
190
198
  },
191
- handleLoad: ( { state, context, effects, ref } ) => {
199
+ // This is fired just by lazily loaded
200
+ // images on the page, not all images.
201
+ handleLoad: ( { context, effects, ref } ) => {
192
202
  context.core.image.imageLoaded = true;
193
203
  context.core.image.imageCurrentSrc = ref.currentSrc;
194
204
  effects.core.image.setButtonStyles( {
195
- state,
196
205
  context,
197
206
  ref,
198
207
  } );
@@ -227,7 +236,17 @@ store(
227
236
  roleAttribute: ( { context } ) => {
228
237
  return context.core.image.lightboxEnabled
229
238
  ? 'dialog'
230
- : '';
239
+ : null;
240
+ },
241
+ ariaModal: ( { context } ) => {
242
+ return context.core.image.lightboxEnabled
243
+ ? 'true'
244
+ : null;
245
+ },
246
+ dialogLabel: ( { context } ) => {
247
+ return context.core.image.lightboxEnabled
248
+ ? context.core.image.dialogLabel
249
+ : null;
231
250
  },
232
251
  lightboxObjectFit: ( { context } ) => {
233
252
  if ( context.core.image.initialized ) {
@@ -237,7 +256,7 @@ store(
237
256
  enlargedImgSrc: ( { context } ) => {
238
257
  return context.core.image.initialized
239
258
  ? context.core.image.imageUploadedSrc
240
- : '';
259
+ : 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
241
260
  },
242
261
  },
243
262
  },
@@ -245,17 +264,14 @@ store(
245
264
  effects: {
246
265
  core: {
247
266
  image: {
248
- setCurrentSrc: ( { context, ref } ) => {
267
+ initOriginImage: ( { context, ref } ) => {
268
+ context.core.image.imageRef = ref;
249
269
  if ( ref.complete ) {
250
270
  context.core.image.imageLoaded = true;
251
271
  context.core.image.imageCurrentSrc = ref.currentSrc;
252
272
  }
253
273
  },
254
274
  initLightbox: async ( { context, ref } ) => {
255
- context.core.image.figureRef =
256
- ref.querySelector( 'figure' );
257
- context.core.image.imageRef =
258
- ref.querySelector( 'img' );
259
275
  if ( context.core.image.lightboxEnabled ) {
260
276
  const focusableElements =
261
277
  ref.querySelectorAll( focusableSelectors );
@@ -266,10 +282,17 @@ store(
266
282
  focusableElements.length - 1
267
283
  ];
268
284
 
269
- ref.querySelector( '.close-button' ).focus();
285
+ // We want to avoid drawing unnecessary attention to the close
286
+ // button for mouse and touch users. Note that even if opening
287
+ // the lightbox via keyboard, the event fired is of type
288
+ // `pointerEvent`, so we need to rely on the `event.pointerType`
289
+ // property, which returns an empty string for keyboard events.
290
+ if ( context.core.image.pointerType === '' ) {
291
+ ref.querySelector( '.close-button' ).focus();
292
+ }
270
293
  }
271
294
  },
272
- setButtonStyles: ( { state, context, ref } ) => {
295
+ setButtonStyles: ( { context, ref } ) => {
273
296
  const {
274
297
  naturalWidth,
275
298
  naturalHeight,
@@ -278,54 +301,80 @@ store(
278
301
  } = ref;
279
302
 
280
303
  // If the image isn't loaded yet, we can't
281
- // calculate how big the button should be.
304
+ // calculate where the button should be.
282
305
  if ( naturalWidth === 0 || naturalHeight === 0 ) {
283
306
  return;
284
307
  }
285
308
 
286
- // Subscribe to the window dimensions so we can
287
- // recalculate the styles if the window is resized.
288
- if (
289
- ( state.core.image.windowWidth ||
290
- state.core.image.windowHeight ) &&
291
- context.core.image.scaleAttr === 'contain'
292
- ) {
293
- // In the case of an image with object-fit: contain, the
294
- // size of the img element can be larger than the image itself,
295
- // so we need to calculate the size of the button to match.
309
+ const figure = ref.parentElement;
310
+ const figureWidth = ref.parentElement.clientWidth;
311
+
312
+ // We need special handling for the height because
313
+ // a caption will cause the figure to be taller than
314
+ // the image, which means we need to account for that
315
+ // when calculating the placement of the button in the
316
+ // top right corner of the image.
317
+ let figureHeight = ref.parentElement.clientHeight;
318
+ const caption = figure.querySelector( 'figcaption' );
319
+ if ( caption ) {
320
+ const captionComputedStyle =
321
+ window.getComputedStyle( caption );
322
+ figureHeight =
323
+ figureHeight -
324
+ caption.offsetHeight -
325
+ parseFloat( captionComputedStyle.marginTop ) -
326
+ parseFloat( captionComputedStyle.marginBottom );
327
+ }
328
+
329
+ const buttonOffsetTop = figureHeight - offsetHeight;
330
+ const buttonOffsetRight = figureWidth - offsetWidth;
296
331
 
332
+ // In the case of an image with object-fit: contain, the
333
+ // size of the <img> element can be larger than the image itself,
334
+ // so we need to calculate where to place the button.
335
+ if ( context.core.image.scaleAttr === 'contain' ) {
297
336
  // Natural ratio of the image.
298
337
  const naturalRatio = naturalWidth / naturalHeight;
299
338
  // Offset ratio of the image.
300
339
  const offsetRatio = offsetWidth / offsetHeight;
301
340
 
302
- if ( naturalRatio > offsetRatio ) {
341
+ if ( naturalRatio >= offsetRatio ) {
303
342
  // If it reaches the width first, keep
304
- // the width and recalculate the height.
305
- context.core.image.imageButtonWidth =
306
- offsetWidth;
307
- const buttonHeight = offsetWidth / naturalRatio;
308
- context.core.image.imageButtonHeight =
309
- buttonHeight;
343
+ // the width and compute the height.
344
+ const referenceHeight =
345
+ offsetWidth / naturalRatio;
310
346
  context.core.image.imageButtonTop =
311
- ( offsetHeight - buttonHeight ) / 2;
347
+ ( offsetHeight - referenceHeight ) / 2 +
348
+ buttonOffsetTop +
349
+ 10;
350
+ context.core.image.imageButtonRight =
351
+ buttonOffsetRight + 10;
312
352
  } else {
313
353
  // If it reaches the height first, keep
314
- // the height and recalculate the width.
315
- context.core.image.imageButtonHeight =
316
- offsetHeight;
317
- const buttonWidth = offsetHeight * naturalRatio;
318
- context.core.image.imageButtonWidth =
319
- buttonWidth;
320
- context.core.image.imageButtonLeft =
321
- ( offsetWidth - buttonWidth ) / 2;
354
+ // the height and compute the width.
355
+ const referenceWidth =
356
+ offsetHeight * naturalRatio;
357
+ context.core.image.imageButtonTop =
358
+ buttonOffsetTop + 10;
359
+ context.core.image.imageButtonRight =
360
+ ( offsetWidth - referenceWidth ) / 2 +
361
+ buttonOffsetRight +
362
+ 10;
322
363
  }
323
364
  } else {
324
- // In all other cases, we can trust that the size of
325
- // the image is the right size for the button as well.
326
-
327
- context.core.image.imageButtonWidth = offsetWidth;
328
- context.core.image.imageButtonHeight = offsetHeight;
365
+ context.core.image.imageButtonTop =
366
+ buttonOffsetTop + 10;
367
+ context.core.image.imageButtonRight =
368
+ buttonOffsetRight + 10;
369
+ }
370
+ },
371
+ setStylesOnResize: ( { state, context, ref } ) => {
372
+ if (
373
+ context.core.image.lightboxEnabled &&
374
+ ( state.core.image.windowWidth ||
375
+ state.core.image.windowHeight )
376
+ ) {
377
+ setStyles( context, ref );
329
378
  }
330
379
  },
331
380
  },
@@ -352,7 +401,7 @@ store(
352
401
  * @param {Object} context - An Interactivity API context
353
402
  * @param {Object} event - A triggering event
354
403
  */
355
- function setStyles( context, event ) {
404
+ function setStyles( context, ref ) {
356
405
  // The reference img element lies adjacent
357
406
  // to the event target button in the DOM.
358
407
  let {
@@ -360,9 +409,8 @@ function setStyles( context, event ) {
360
409
  naturalHeight,
361
410
  offsetWidth: originalWidth,
362
411
  offsetHeight: originalHeight,
363
- } = event.target.nextElementSibling;
364
- let { x: screenPosX, y: screenPosY } =
365
- event.target.nextElementSibling.getBoundingClientRect();
412
+ } = ref;
413
+ let { x: screenPosX, y: screenPosY } = ref.getBoundingClientRect();
366
414
 
367
415
  // Natural ratio of the image clicked to open the lightbox.
368
416
  const naturalRatio = naturalWidth / naturalHeight;
package/src/index.js CHANGED
@@ -48,6 +48,10 @@ import * as cover from './cover';
48
48
  import * as details from './details';
49
49
  import * as embed from './embed';
50
50
  import * as file from './file';
51
+ import * as form from './form';
52
+ import * as formInput from './form-input';
53
+ import * as formSubmitButton from './form-submit-button';
54
+ import * as formSubmissionNotification from './form-submission-notification';
51
55
  import * as gallery from './gallery';
52
56
  import * as group from './group';
53
57
  import * as heading from './heading';
@@ -228,6 +232,12 @@ const getAllBlocks = () => {
228
232
  queryTitle,
229
233
  postAuthorBiography,
230
234
  ];
235
+ if ( window?.__experimentalEnableFormBlocks ) {
236
+ blocks.push( form );
237
+ blocks.push( formInput );
238
+ blocks.push( formSubmitButton );
239
+ blocks.push( formSubmissionNotification );
240
+ }
231
241
 
232
242
  // When in a WordPress context, conditionally
233
243
  // add the classic block and TinyMCE editor
@@ -483,12 +483,18 @@ export default function LatestPostsEdit( { attributes, setAttributes } ) {
483
483
  .split( ' ', excerptLength )
484
484
  .join( ' ' ) }
485
485
  { createInterpolateElement(
486
- /* translators: excerpt truncation character, default … */
487
- __( ' <a>Read more</a>' ),
486
+ sprintf(
487
+ /* translators: 1: Hidden accessibility text: Post title */
488
+ __(
489
+ '… <a>Read more<span>: %1$s</span></a>'
490
+ ),
491
+ titleTrimmed || __( '(no title)' )
492
+ ),
488
493
  {
489
494
  a: (
490
495
  // eslint-disable-next-line jsx-a11y/anchor-has-content
491
496
  <a
497
+ className="wp-block-latest-posts__read-more"
492
498
  href={ post.link }
493
499
  rel="noopener noreferrer"
494
500
  onClick={
@@ -496,6 +502,9 @@ export default function LatestPostsEdit( { attributes, setAttributes } ) {
496
502
  }
497
503
  />
498
504
  ),
505
+ span: (
506
+ <span className="screen-reader-text" />
507
+ ),
499
508
  }
500
509
  ) }
501
510
  </>
@@ -48,14 +48,6 @@ function render_block_core_latest_posts( $attributes ) {
48
48
  $block_core_latest_posts_excerpt_length = $attributes['excerptLength'];
49
49
  add_filter( 'excerpt_length', 'block_core_latest_posts_get_excerpt_length', 20 );
50
50
 
51
- $filter_latest_posts_excerpt_more = static function ( $more ) use ( $attributes ) {
52
- $use_excerpt = 'excerpt' === $attributes['displayPostContentRadio'];
53
- /* translators: %1$s is a URL to a post, excerpt truncation character, default … */
54
- return $use_excerpt ? sprintf( __( ' … <a href="%1$s" rel="noopener noreferrer">Read more</a>' ), esc_url( get_permalink() ) ) : $more;
55
- };
56
-
57
- add_filter( 'excerpt_more', $filter_latest_posts_excerpt_more );
58
-
59
51
  if ( ! empty( $attributes['categories'] ) ) {
60
52
  $args['category__in'] = array_column( $attributes['categories'], 'id' );
61
53
  }
@@ -151,6 +143,23 @@ function render_block_core_latest_posts( $attributes ) {
151
143
 
152
144
  $trimmed_excerpt = get_the_excerpt( $post );
153
145
 
146
+ /*
147
+ * Adds a "Read more" link with screen reader text.
148
+ * [&hellip;] is the default excerpt ending from wp_trim_excerpt() in Core.
149
+ */
150
+ if ( str_ends_with( $trimmed_excerpt, ' [&hellip;]' ) ) {
151
+ $excerpt_length = (int) apply_filters( 'excerpt_length', $block_core_latest_posts_excerpt_length );
152
+ if ( $excerpt_length <= $block_core_latest_posts_excerpt_length ) {
153
+ $trimmed_excerpt = substr( $trimmed_excerpt, 0, -11 );
154
+ $trimmed_excerpt .= sprintf(
155
+ /* translators: 1: A URL to a post, 2: Hidden accessibility text: Post title */
156
+ __( '… <a href="%1$s" rel="noopener noreferrer">Read more<span class="screen-reader-text">: %2$s</span></a>' ),
157
+ esc_url( $post_link ),
158
+ esc_html( $title )
159
+ );
160
+ }
161
+ }
162
+
154
163
  if ( post_password_required( $post ) ) {
155
164
  $trimmed_excerpt = __( 'This content is password protected.' );
156
165
  }
@@ -76,6 +76,24 @@ export default function useMerge( clientId, onMerge ) {
76
76
  }
77
77
 
78
78
  return ( forward ) => {
79
+ function mergeWithNested( clientIdA, clientIdB ) {
80
+ registry.batch( () => {
81
+ // When merging a sub list item with a higher next list item, we
82
+ // also need to move any nested list items. Check if there's a
83
+ // listed list, and append its nested list items to the current
84
+ // list.
85
+ const [ nestedListClientId ] = getBlockOrder( clientIdB );
86
+ if ( nestedListClientId ) {
87
+ moveBlocksToPosition(
88
+ getBlockOrder( nestedListClientId ),
89
+ nestedListClientId,
90
+ getBlockRootClientId( clientIdA )
91
+ );
92
+ }
93
+ mergeBlocks( clientIdA, clientIdB );
94
+ } );
95
+ }
96
+
79
97
  if ( forward ) {
80
98
  const nextBlockClientId = getNextId( clientId );
81
99
 
@@ -87,14 +105,7 @@ export default function useMerge( clientId, onMerge ) {
87
105
  if ( getParentListItemId( nextBlockClientId ) ) {
88
106
  outdentListItem( nextBlockClientId );
89
107
  } else {
90
- registry.batch( () => {
91
- moveBlocksToPosition(
92
- getBlockOrder( nextBlockClientId ),
93
- nextBlockClientId,
94
- getPreviousBlockClientId( nextBlockClientId )
95
- );
96
- mergeBlocks( clientId, nextBlockClientId );
97
- } );
108
+ mergeWithNested( clientId, nextBlockClientId );
98
109
  }
99
110
  } else {
100
111
  // Merging is only done from the top level. For lowel levels, the
@@ -104,21 +115,7 @@ export default function useMerge( clientId, onMerge ) {
104
115
  outdentListItem( clientId );
105
116
  } else if ( previousBlockClientId ) {
106
117
  const trailingId = getTrailingId( previousBlockClientId );
107
- registry.batch( () => {
108
- // When merging a list item with a previous trailing list
109
- // item, we also need to move any nested list items. First,
110
- // check if there's a listed list. If there's a nested list,
111
- // append its nested list items to the trailing list.
112
- const [ nestedListClientId ] = getBlockOrder( clientId );
113
- if ( nestedListClientId ) {
114
- moveBlocksToPosition(
115
- getBlockOrder( nestedListClientId ),
116
- nestedListClientId,
117
- getBlockRootClientId( trailingId )
118
- );
119
- }
120
- mergeBlocks( trailingId, clientId );
121
- } );
118
+ mergeWithNested( trailingId, clientId );
122
119
  } else {
123
120
  onMerge( forward );
124
121
  }
@@ -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-library'
10
10
  );
@@ -11,12 +11,7 @@ import {
11
11
  /**
12
12
  * WordPress dependencies
13
13
  */
14
- import {
15
- requestUnsupportedBlockFallback,
16
- sendActionButtonPressedAction,
17
- actionButtons,
18
- } from '@wordpress/react-native-bridge';
19
- import { BottomSheet, Icon, TextControl } from '@wordpress/components';
14
+ import { Icon } from '@wordpress/components';
20
15
  import { compose, withPreferredColorScheme } from '@wordpress/compose';
21
16
  import { coreBlocks } from '@wordpress/block-library';
22
17
  import { normalizeIconObject } from '@wordpress/blocks';
@@ -25,7 +20,10 @@ import { __, _x, sprintf } from '@wordpress/i18n';
25
20
  import { help, plugins } from '@wordpress/icons';
26
21
  import { withSelect, withDispatch } from '@wordpress/data';
27
22
  import { applyFilters } from '@wordpress/hooks';
28
- import { store as blockEditorStore } from '@wordpress/block-editor';
23
+ import {
24
+ UnsupportedBlockDetails,
25
+ store as blockEditorStore,
26
+ } from '@wordpress/block-editor';
29
27
 
30
28
  /**
31
29
  * Internal dependencies
@@ -121,122 +119,26 @@ export class UnsupportedBlockEdit extends Component {
121
119
  }
122
120
 
123
121
  renderSheet( blockTitle, blockName ) {
124
- const {
125
- getStylesFromColorScheme,
126
- attributes,
127
- clientId,
128
- isUnsupportedBlockEditorSupported,
129
- canEnableUnsupportedBlockEditor,
130
- isEditableInUnsupportedBlockEditor,
131
- } = this.props;
132
- const infoTextStyle = getStylesFromColorScheme(
133
- styles.infoText,
134
- styles.infoTextDark
135
- );
136
- const infoTitleStyle = getStylesFromColorScheme(
137
- styles.infoTitle,
138
- styles.infoTitleDark
139
- );
140
- const infoDescriptionStyle = getStylesFromColorScheme(
141
- styles.infoDescription,
142
- styles.infoDescriptionDark
143
- );
144
- const infoSheetIconStyle = getStylesFromColorScheme(
145
- styles.infoSheetIcon,
146
- styles.infoSheetIconDark
147
- );
148
-
122
+ const { clientId } = this.props;
123
+ const { showHelp } = this.state;
149
124
  /* translators: Missing block alert title. %s: The localized block name */
150
125
  const titleFormat = __( "'%s' is not fully-supported" );
151
- const infoTitle = sprintf( titleFormat, blockTitle );
152
- const missingBlockDetail = applyFilters(
126
+ const title = sprintf( titleFormat, blockTitle );
127
+ const description = applyFilters(
153
128
  'native.missing_block_detail',
154
129
  __( 'We are working hard to add more blocks with each release.' ),
155
130
  blockName
156
131
  );
157
- const missingBlockActionButton = applyFilters(
158
- 'native.missing_block_action_button',
159
- __( 'Edit using web editor' )
160
- );
161
-
162
- const actionButtonStyle = getStylesFromColorScheme(
163
- styles.actionButton,
164
- styles.actionButtonDark
165
- );
166
132
 
167
133
  return (
168
- <BottomSheet
169
- isVisible={ this.state.showHelp }
170
- hideHeader
171
- onClose={ this.closeSheet }
172
- onModalHide={ () => {
173
- if ( this.state.sendFallbackMessage ) {
174
- // On iOS, onModalHide is called when the controller is still part of the hierarchy.
175
- // A small delay will ensure that the controller has already been removed.
176
- this.timeout = setTimeout( () => {
177
- // For the Classic block, the content is kept in the `content` attribute.
178
- const content =
179
- blockName === 'core/freeform'
180
- ? attributes.content
181
- : attributes.originalContent;
182
- requestUnsupportedBlockFallback(
183
- content,
184
- clientId,
185
- blockName,
186
- blockTitle
187
- );
188
- }, 100 );
189
- this.setState( { sendFallbackMessage: false } );
190
- } else if ( this.state.sendButtonPressMessage ) {
191
- this.timeout = setTimeout( () => {
192
- sendActionButtonPressedAction(
193
- actionButtons.missingBlockAlertActionButton
194
- );
195
- }, 100 );
196
- this.setState( { sendButtonPressMessage: false } );
197
- }
198
- } }
199
- >
200
- <View style={ styles.infoContainer }>
201
- <Icon
202
- icon={ help }
203
- color={ infoSheetIconStyle.color }
204
- size={ styles.infoSheetIcon.size }
205
- />
206
- <Text style={ [ infoTextStyle, infoTitleStyle ] }>
207
- { infoTitle }
208
- </Text>
209
- { isEditableInUnsupportedBlockEditor &&
210
- missingBlockDetail && (
211
- <Text
212
- style={ [
213
- infoTextStyle,
214
- infoDescriptionStyle,
215
- ] }
216
- >
217
- { missingBlockDetail }
218
- </Text>
219
- ) }
220
- </View>
221
- { ( isUnsupportedBlockEditorSupported ||
222
- canEnableUnsupportedBlockEditor ) &&
223
- isEditableInUnsupportedBlockEditor && (
224
- <>
225
- <TextControl
226
- label={ missingBlockActionButton }
227
- separatorType="topFullWidth"
228
- onPress={ this.requestFallback }
229
- labelStyle={ actionButtonStyle }
230
- />
231
- <TextControl
232
- label={ __( 'Dismiss' ) }
233
- separatorType="topFullWidth"
234
- onPress={ this.toggleSheet }
235
- labelStyle={ actionButtonStyle }
236
- />
237
- </>
238
- ) }
239
- </BottomSheet>
134
+ <UnsupportedBlockDetails
135
+ clientId={ clientId }
136
+ showSheet={ showHelp }
137
+ onCloseSheet={ this.closeSheet }
138
+ customBlockTitle={ blockTitle }
139
+ title={ title }
140
+ description={ description }
141
+ />
240
142
  );
241
143
  }
242
144
 
@@ -1,13 +1,3 @@
1
- /** @format */
2
- .content {
3
- padding-top: 8;
4
- padding-bottom: 0;
5
- padding-left: 24;
6
- padding-right: 24;
7
- align-items: center;
8
- justify-content: space-evenly;
9
- }
10
-
11
1
  .helpIconContainer {
12
2
  position: absolute;
13
3
  top: 0;
@@ -20,12 +10,6 @@
20
10
  align-items: flex-end;
21
11
  }
22
12
 
23
- .infoContainer {
24
- flex-direction: column;
25
- align-items: center;
26
- justify-content: flex-end;
27
- }
28
-
29
13
  .infoIcon {
30
14
  size: 36;
31
15
  height: 36;
@@ -38,49 +22,6 @@
38
22
  color: $dark-tertiary;
39
23
  }
40
24
 
41
- .infoSheetIcon {
42
- size: 36;
43
- height: 36;
44
- padding-top: 8;
45
- padding-bottom: 8;
46
- color: $gray;
47
- }
48
-
49
- .infoSheetIconDark {
50
- color: $gray-20;
51
- }
52
-
53
- .infoText {
54
- text-align: center;
55
- color: $gray-dark;
56
- }
57
-
58
- .infoTextDark {
59
- color: $white;
60
- }
61
-
62
- .infoTitle {
63
- padding-top: 8;
64
- padding-bottom: 12;
65
- font-size: 20;
66
- font-weight: bold;
67
- color: $gray-dark;
68
- }
69
-
70
- .infoTitleDark {
71
- color: $white;
72
- }
73
-
74
- .infoDescription {
75
- padding-bottom: 24;
76
- font-size: 16;
77
- color: $gray-darken-20;
78
- }
79
-
80
- .infoDescriptionDark {
81
- color: $gray-20;
82
- }
83
-
84
25
  .unsupportedBlock {
85
26
  height: 142;
86
27
  background-color: #e0e0e0; // $light-dim
@@ -136,11 +77,3 @@
136
77
  .unsupportedBlockSubtitleDark {
137
78
  color: $gray-20;
138
79
  }
139
-
140
- .actionButton {
141
- color: $blue-50;
142
- }
143
-
144
- .actionButtonDark {
145
- color: $blue-30;
146
- }