@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
@@ -1,81 +1,167 @@
1
1
  /**
2
2
  * External dependencies
3
3
  */
4
- import { initializeEditor, fireEvent, within } from 'test/helpers';
4
+ import {
5
+ fireEvent,
6
+ getBlock,
7
+ initializeEditor,
8
+ screen,
9
+ setupCoreBlocks,
10
+ withFakeTimers,
11
+ within,
12
+ } from 'test/helpers';
13
+ import { Platform } from 'react-native';
5
14
 
6
15
  /**
7
16
  * WordPress dependencies
8
17
  */
9
- import { getBlockTypes, unregisterBlockType } from '@wordpress/blocks';
18
+ import { unregisterBlockType } from '@wordpress/blocks';
10
19
  import { setLocaleData } from '@wordpress/i18n';
20
+ import { requestUnsupportedBlockFallback } from '@wordpress/react-native-bridge';
21
+
22
+ // Override modal mock to prevent unmounting it when is not visible.
23
+ // This is required to be able to trigger onClose and onDismiss events when
24
+ // the modal is dismissed.
25
+ jest.mock( 'react-native-modal', () => {
26
+ const mockComponent = require( 'react-native/jest/mockComponent' );
27
+ return mockComponent( 'react-native-modal' );
28
+ } );
11
29
 
12
- /**
13
- * Internal dependencies
14
- */
15
- import { registerCoreBlocks } from '../..';
30
+ const TABLE_BLOCK_HTML = `<!-- wp:table -->
31
+ <figure class="wp-block-table"><table><tbody><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></tbody></table></figure>
32
+ <!-- /wp:table -->`;
33
+ const MODAL_DISMISS_EVENT = Platform.OS === 'ios' ? 'onDismiss' : 'onModalHide';
16
34
 
17
- beforeAll( () => {
18
- // Mock translations.
19
- setLocaleData( {
20
- 'block title\u0004Table': [ 'Tabla' ],
21
- "'%s' is not fully-supported": [ '«%s» no es totalmente compatible' ],
22
- } );
35
+ setupCoreBlocks();
23
36
 
24
- // Register all core blocks.
25
- registerCoreBlocks();
37
+ beforeAll( () => {
38
+ // For the purpose of this test suite we consider Reusable blocks/Patterns as unsupported.
39
+ // For this reason we unregister it to force it to be rendered as an unsupported block.
40
+ unregisterBlockType( 'core/block' );
26
41
  } );
27
42
 
28
- afterAll( () => {
29
- // Clean up translations.
30
- setLocaleData( {} );
43
+ describe( 'Unsupported block', () => {
44
+ describe( 'localized elements', () => {
45
+ beforeEach( () => {
46
+ // Mock translations.
47
+ setLocaleData( {
48
+ 'block title\u0004Table': [ 'Tabla' ],
49
+ "'%s' is not fully-supported": [
50
+ '«%s» no es totalmente compatible',
51
+ ],
52
+ } );
53
+ } );
54
+
55
+ afterEach( () => {
56
+ // Clean up translations.
57
+ setLocaleData( {} );
58
+ } );
59
+
60
+ it( 'requests translated block title in block placeholder', async () => {
61
+ await initializeEditor( {
62
+ initialHtml: TABLE_BLOCK_HTML,
63
+ } );
64
+
65
+ const missingBlock = getBlock( screen, 'Unsupported' );
66
+
67
+ const translatedTableTitle =
68
+ within( missingBlock ).getByText( 'Tabla' );
69
+
70
+ expect( translatedTableTitle ).toBeDefined();
71
+ } );
72
+
73
+ it( 'requests translated block title in bottom sheet', async () => {
74
+ await initializeEditor( {
75
+ initialHtml: TABLE_BLOCK_HTML,
76
+ } );
77
+
78
+ const missingBlock = getBlock( screen, 'Unsupported' );
79
+
80
+ fireEvent.press( missingBlock );
31
81
 
32
- // Clean up registered blocks.
33
- getBlockTypes().forEach( ( block ) => {
34
- unregisterBlockType( block.name );
82
+ const [ helpButton ] =
83
+ await screen.findAllByLabelText( 'Help button' );
84
+
85
+ fireEvent.press( helpButton );
86
+
87
+ const bottomSheetTitle = await screen.findByText(
88
+ '«Tabla» no es totalmente compatible'
89
+ );
90
+
91
+ expect( bottomSheetTitle ).toBeDefined();
92
+ } );
35
93
  } );
36
- } );
37
94
 
38
- describe( 'Unsupported block', () => {
39
- it( 'requests translated block title in block placeholder', async () => {
40
- const initialHtml = `<!-- wp:table -->
41
- <figure class="wp-block-table"><table><tbody><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></tbody></table></figure>
42
- <!-- /wp:table -->`;
43
- const screen = await initializeEditor( {
44
- initialHtml,
95
+ it( 'requests web editor when UBE is available', async () => {
96
+ await initializeEditor( {
97
+ initialHtml: TABLE_BLOCK_HTML,
98
+ capabilities: {
99
+ unsupportedBlockEditor: true,
100
+ canEnableUnsupportedBlockEditor: true,
101
+ },
45
102
  } );
46
103
 
47
- const [ missingBlock ] = await screen.findAllByLabelText(
48
- /Unsupported Block\. Row 1/
49
- );
104
+ const missingBlock = getBlock( screen, 'Unsupported' );
105
+ fireEvent.press( missingBlock );
106
+
107
+ // Tap the block to open the unsupported block details
108
+ fireEvent.press( within( missingBlock ).getByText( 'Unsupported' ) );
50
109
 
51
- const translatedTableTitle =
52
- within( missingBlock ).getByText( 'Tabla' );
110
+ const actionButton = screen.getByText( 'Edit using web editor' );
111
+ expect( actionButton ).toBeVisible();
53
112
 
54
- expect( translatedTableTitle ).toBeDefined();
113
+ // UBE is requested after the modal hides and running a timeout
114
+ await withFakeTimers( async () => {
115
+ fireEvent.press( actionButton );
116
+ fireEvent(
117
+ screen.getByTestId( 'bottom-sheet' ),
118
+ MODAL_DISMISS_EVENT
119
+ );
120
+ jest.runOnlyPendingTimers();
121
+ } );
122
+ expect( requestUnsupportedBlockFallback ).toHaveBeenCalled();
55
123
  } );
56
124
 
57
- it( 'requests translated block title in bottom sheet', async () => {
58
- const initialHtml = `<!-- wp:table -->
59
- <figure class="wp-block-table"><table><tbody><tr><td>1</td><td>2</td></tr><tr><td>3</td><td>4</td></tr></tbody></table></figure>
60
- <!-- /wp:table -->`;
61
- const screen = await initializeEditor( {
62
- initialHtml,
125
+ it( 'does not show web editor option when UBE is not available', async () => {
126
+ await initializeEditor( {
127
+ initialHtml: TABLE_BLOCK_HTML,
128
+ capabilities: {
129
+ unsupportedBlockEditor: false,
130
+ canEnableUnsupportedBlockEditor: false,
131
+ },
63
132
  } );
64
133
 
65
- const [ missingBlock ] = await screen.findAllByLabelText(
66
- /Unsupported Block\. Row 1/
134
+ const missingBlock = getBlock( screen, 'Unsupported' );
135
+ fireEvent.press( missingBlock );
136
+
137
+ // Tap the block to open the unsupported block details
138
+ fireEvent.press( within( missingBlock ).getByText( 'Unsupported' ) );
139
+
140
+ const actionButton = await screen.queryByText(
141
+ 'Edit using web editor'
67
142
  );
143
+ expect( actionButton ).toBeNull();
144
+ } );
68
145
 
69
- fireEvent.press( missingBlock );
146
+ it( 'does not show web editor option when block is incompatible with UBE', async () => {
147
+ await initializeEditor( {
148
+ // Reusable blocks/Patterns is a block type unsupported by UBE
149
+ initialHtml: '<!-- wp:block {"ref":7387} /-->',
150
+ capabilities: {
151
+ unsupportedBlockEditor: true,
152
+ canEnableUnsupportedBlockEditor: true,
153
+ },
154
+ } );
70
155
 
71
- const [ helpButton ] = await screen.findAllByLabelText( 'Help button' );
156
+ const missingBlock = getBlock( screen, 'Unsupported' );
157
+ fireEvent.press( missingBlock );
72
158
 
73
- fireEvent.press( helpButton );
159
+ // Tap the block to open the unsupported block details
160
+ fireEvent.press( within( missingBlock ).getByText( 'Unsupported' ) );
74
161
 
75
- const bottomSheetTitle = await screen.findByText(
76
- '«Tabla» no es totalmente compatible'
162
+ const actionButton = await screen.queryByText(
163
+ 'Edit using web editor'
77
164
  );
78
-
79
- expect( bottomSheetTitle ).toBeDefined();
165
+ expect( actionButton ).toBeNull();
80
166
  } );
81
167
  } );
@@ -63,47 +63,6 @@ describe( 'Missing block', () => {
63
63
  "' is not fully-supported"
64
64
  );
65
65
  } );
66
-
67
- describe( 'Unsupported block editor (UBE)', () => {
68
- beforeEach( () => {
69
- // By default we set the web editor as available.
70
- storeConfig.selectors.getSettings.mockReturnValue( {
71
- capabilities: { unsupportedBlockEditor: true },
72
- } );
73
- } );
74
-
75
- it( 'renders edit action if UBE is available', () => {
76
- const testInstance = getTestComponentWithContent();
77
- const bottomSheet =
78
- testInstance.UNSAFE_getByType( BottomSheet );
79
- const bottomSheetCells = bottomSheet.props.children[ 1 ];
80
- expect( bottomSheetCells ).toBeTruthy();
81
- expect( bottomSheetCells.props.children.length ).toBe( 2 );
82
- expect( bottomSheetCells.props.children[ 0 ].props.label ).toBe(
83
- 'Edit using web editor'
84
- );
85
- } );
86
-
87
- it( 'does not render edit action if UBE is not available', () => {
88
- storeConfig.selectors.getSettings.mockReturnValue( {
89
- capabilities: { unsupportedBlockEditor: false },
90
- } );
91
-
92
- const testInstance = getTestComponentWithContent();
93
- const bottomSheet =
94
- testInstance.UNSAFE_getByType( BottomSheet );
95
- expect( bottomSheet.props.children[ 1 ] ).toBeFalsy();
96
- } );
97
-
98
- it( 'does not render edit action if the block is incompatible with UBE', () => {
99
- const testInstance = getTestComponentWithContent( {
100
- originalName: 'core/block',
101
- } );
102
- const bottomSheet =
103
- testInstance.UNSAFE_getByType( BottomSheet );
104
- expect( bottomSheet.props.children[ 1 ] ).toBeFalsy();
105
- } );
106
- } );
107
66
  } );
108
67
 
109
68
  it( 'renders admin plugins icon', () => {
@@ -133,7 +133,8 @@
133
133
  }
134
134
  }
135
135
  },
136
- "interactivity": true
136
+ "interactivity": true,
137
+ "renaming": false
137
138
  },
138
139
  "viewScript": "file:./view.min.js",
139
140
  "editorStyle": "wp-block-navigation-editor",
@@ -884,7 +884,6 @@ function Navigation( {
884
884
  <ResponsiveWrapper
885
885
  id={ clientId }
886
886
  onToggle={ setResponsiveMenuVisibility }
887
- label={ __( 'Menu' ) }
888
887
  hasIcon={ hasIcon }
889
888
  icon={ icon }
890
889
  isOpen={ isResponsiveMenuOpen }
@@ -72,8 +72,8 @@ if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
72
72
  * Add Interactivity API directives to the navigation-submenu and page-list
73
73
  * blocks markup using the Tag Processor.
74
74
  *
75
- * @param string $w Markup of the navigation block.
76
- * @param array $block_attributes Block attributes.
75
+ * @param WP_HTML_Tag_Processor $w Markup of the navigation block.
76
+ * @param array $block_attributes Block attributes.
77
77
  *
78
78
  * @return string Submenu markup with the directives injected.
79
79
  */
@@ -90,6 +90,13 @@ function block_core_navigation_add_directives_to_submenu( $w, $block_attributes
90
90
  $w->set_attribute( 'data-wp-effect', 'effects.core.navigation.initMenu' );
91
91
  $w->set_attribute( 'data-wp-on--focusout', 'actions.core.navigation.handleMenuFocusout' );
92
92
  $w->set_attribute( 'data-wp-on--keydown', 'actions.core.navigation.handleMenuKeydown' );
93
+
94
+ // This is a fix for Safari. Without it, Safari doesn't change the active
95
+ // element when the user clicks on a button. It can be removed once we add
96
+ // an overlay to capture the clicks, instead of relying on the focusout
97
+ // event.
98
+ $w->set_attribute( 'tabindex', '-1' );
99
+
93
100
  if ( ! isset( $block_attributes['openSubmenusOnClick'] ) || false === $block_attributes['openSubmenusOnClick'] ) {
94
101
  $w->set_attribute( 'data-wp-on--mouseenter', 'actions.core.navigation.openMenuOnHover' );
95
102
  $w->set_attribute( 'data-wp-on--mouseleave', 'actions.core.navigation.closeMenuOnHover' );
@@ -696,9 +703,22 @@ function render_block_core_navigation( $attributes, $content, $block ) {
696
703
  $responsive_dialog_directives = '';
697
704
  $close_button_directives = '';
698
705
  if ( $should_load_view_script ) {
706
+ $nav_element_context = wp_json_encode(
707
+ array(
708
+ 'core' => array(
709
+ 'navigation' => array(
710
+ 'overlayOpenedBy' => array(),
711
+ 'type' => 'overlay',
712
+ 'roleAttribute' => '',
713
+ 'ariaLabel' => __( 'Menu' ),
714
+ ),
715
+ ),
716
+ ),
717
+ JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP
718
+ );
699
719
  $nav_element_directives = '
700
720
  data-wp-interactive
701
- data-wp-context=\'{ "core": { "navigation": { "overlayOpenedBy": {}, "type": "overlay", "roleAttribute": "" } } }\'
721
+ data-wp-context=\'' . $nav_element_context . '\'
702
722
  ';
703
723
  $open_button_directives = '
704
724
  data-wp-on--click="actions.core.navigation.openMenuOnClick"
@@ -714,6 +734,7 @@ function render_block_core_navigation( $attributes, $content, $block ) {
714
734
  ';
715
735
  $responsive_dialog_directives = '
716
736
  data-wp-bind--aria-modal="selectors.core.navigation.ariaModal"
737
+ data-wp-bind--aria-label="selectors.core.navigation.ariaLabel"
717
738
  data-wp-bind--role="selectors.core.navigation.roleAttribute"
718
739
  data-wp-effect="effects.core.navigation.focusFirstElement"
719
740
  ';
@@ -723,11 +744,11 @@ function render_block_core_navigation( $attributes, $content, $block ) {
723
744
  }
724
745
 
725
746
  $responsive_container_markup = sprintf(
726
- '<button aria-haspopup="true" %3$s class="%6$s" %11$s>%9$s</button>
727
- <div class="%5$s" style="%7$s" id="%1$s" %12$s>
747
+ '<button aria-haspopup="true" %3$s class="%6$s" %10$s>%8$s</button>
748
+ <div class="%5$s" style="%7$s" id="%1$s" %11$s>
728
749
  <div class="wp-block-navigation__responsive-close" tabindex="-1">
729
- <div class="wp-block-navigation__responsive-dialog" aria-label="%8$s" %13$s>
730
- <button %4$s class="wp-block-navigation__responsive-container-close" %14$s>%10$s</button>
750
+ <div class="wp-block-navigation__responsive-dialog" %12$s>
751
+ <button %4$s class="wp-block-navigation__responsive-container-close" %13$s>%9$s</button>
731
752
  <div class="wp-block-navigation__responsive-container-content" id="%1$s-content">
732
753
  %2$s
733
754
  </div>
@@ -741,7 +762,6 @@ function render_block_core_navigation( $attributes, $content, $block ) {
741
762
  esc_attr( implode( ' ', $responsive_container_classes ) ),
742
763
  esc_attr( implode( ' ', $open_button_classes ) ),
743
764
  esc_attr( safecss_filter_attr( $colors['overlay_inline_styles'] ) ),
744
- __( 'Menu' ),
745
765
  $toggle_button_content,
746
766
  $toggle_close_button_content,
747
767
  $open_button_directives,
@@ -13,10 +13,14 @@ const focusableSelectors = [
13
13
  '[tabindex]:not([tabindex^="-"])',
14
14
  ];
15
15
 
16
+ // This is a fix for Safari in iOS/iPadOS. Without it, Safari doesn't focus out
17
+ // when the user taps in the body. It can be removed once we add an overlay to
18
+ // capture the clicks, instead of relying on the focusout event.
19
+ document.addEventListener( 'click', () => {} );
20
+
16
21
  const openMenu = ( store, menuOpenedOn ) => {
17
- const { context, ref, selectors } = store;
22
+ const { context, selectors } = store;
18
23
  selectors.core.navigation.menuOpenedBy( store )[ menuOpenedOn ] = true;
19
- context.core.navigation.previousFocus = ref;
20
24
  if ( context.core.navigation.type === 'overlay' ) {
21
25
  // Add a `has-modal-open` class to the <html> root.
22
26
  document.documentElement.classList.add( 'has-modal-open' );
@@ -33,7 +37,7 @@ const closeMenu = ( store, menuClosedOn ) => {
33
37
  window.document.activeElement
34
38
  )
35
39
  ) {
36
- context.core.navigation.previousFocus.focus();
40
+ context.core.navigation.previousFocus?.focus();
37
41
  }
38
42
  context.core.navigation.modal = null;
39
43
  context.core.navigation.previousFocus = null;
@@ -87,6 +91,13 @@ wpStore( {
87
91
  ? 'true'
88
92
  : null;
89
93
  },
94
+ ariaLabel: ( store ) => {
95
+ const { context, selectors } = store;
96
+ return context.core.navigation.type === 'overlay' &&
97
+ selectors.core.navigation.isMenuOpen( store )
98
+ ? context.core.navigation.ariaLabel
99
+ : null;
100
+ },
90
101
  isMenuOpen: ( { context } ) =>
91
102
  // The menu is opened if either `click`, `hover` or `focus` is true.
92
103
  Object.values(
@@ -123,6 +134,8 @@ wpStore( {
123
134
  closeMenu( store, 'hover' );
124
135
  },
125
136
  openMenuOnClick( store ) {
137
+ const { context, ref } = store;
138
+ context.core.navigation.previousFocus = ref;
126
139
  openMenu( store, 'click' );
127
140
  },
128
141
  closeMenuOnClick( store ) {
@@ -133,13 +146,16 @@ wpStore( {
133
146
  openMenu( store, 'focus' );
134
147
  },
135
148
  toggleMenuOnClick: ( store ) => {
136
- const { selectors } = store;
149
+ const { selectors, context, ref } = store;
150
+ // Safari won't send focus to the clicked element, so we need to manually place it: https://bugs.webkit.org/show_bug.cgi?id=22261
151
+ if ( window.document.activeElement !== ref ) ref.focus();
137
152
  const menuOpenedBy =
138
153
  selectors.core.navigation.menuOpenedBy( store );
139
154
  if ( menuOpenedBy.click || menuOpenedBy.focus ) {
140
155
  closeMenu( store, 'click' );
141
156
  closeMenu( store, 'focus' );
142
157
  } else {
158
+ context.core.navigation.previousFocus = ref;
143
159
  openMenu( store, 'click' );
144
160
  }
145
161
  },
@@ -187,11 +203,14 @@ wpStore( {
187
203
  // event.relatedTarget === The element receiving focus (if any)
188
204
  // When focusout is outsite the document,
189
205
  // `window.document.activeElement` doesn't change.
206
+
207
+ // The event.relatedTarget is null when something outside the navigation menu is clicked. This is only necessary for Safari.
190
208
  if (
191
- ! context.core.navigation.modal?.contains(
209
+ event.relatedTarget === null ||
210
+ ( ! context.core.navigation.modal?.contains(
192
211
  event.relatedTarget
193
212
  ) &&
194
- event.target !== window.document.activeElement
213
+ event.target !== window.document.activeElement )
195
214
  ) {
196
215
  closeMenu( store, 'click' );
197
216
  closeMenu( store, 'focus' );
@@ -64,6 +64,7 @@ export default function PageListItemEdit( { context, attributes } ) {
64
64
  { hasChildren && context.openSubmenusOnClick ? (
65
65
  <>
66
66
  <button
67
+ type="button"
67
68
  className="wp-block-navigation-item__content wp-block-navigation-submenu__toggle"
68
69
  aria-expanded="false"
69
70
  >
@@ -90,6 +91,7 @@ export default function PageListItemEdit( { context, attributes } ) {
90
91
  <button
91
92
  className="wp-block-navigation-item__content wp-block-navigation-submenu__toggle wp-block-page-list__submenu-icon wp-block-navigation__submenu-icon"
92
93
  aria-expanded="false"
94
+ type="button"
93
95
  >
94
96
  <ItemSubmenuIcon />
95
97
  </button>
@@ -28,7 +28,17 @@ export const settings = {
28
28
  },
29
29
  },
30
30
  __experimentalLabel( attributes, { context } ) {
31
+ const customName = attributes?.metadata?.name;
32
+
33
+ if ( context === 'list-view' && customName ) {
34
+ return customName;
35
+ }
36
+
31
37
  if ( context === 'accessibility' ) {
38
+ if ( customName ) {
39
+ return customName;
40
+ }
41
+
32
42
  const { content } = attributes;
33
43
  return ! content || content.length === 0 ? __( 'Empty' ) : content;
34
44
  }
@@ -7,7 +7,8 @@
7
7
  "description": "Show a block pattern.",
8
8
  "supports": {
9
9
  "html": false,
10
- "inserter": false
10
+ "inserter": false,
11
+ "renaming": false
11
12
  },
12
13
  "textdomain": "default",
13
14
  "attributes": {
@@ -7,8 +7,6 @@
7
7
 
8
8
  /**
9
9
  * Registers the `core/pattern` block on the server.
10
- *
11
- * @return void
12
10
  */
13
11
  function register_block_core_pattern() {
14
12
  register_block_type_from_metadata(
@@ -46,7 +44,6 @@ function render_block_core_pattern( $attributes ) {
46
44
  // Backward compatibility for handling Block Hooks and injecting the theme attribute in the Gutenberg plugin.
47
45
  // This can be removed when the minimum supported WordPress is >= 6.4.
48
46
  if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN && ! function_exists( 'traverse_and_serialize_blocks' ) ) {
49
- $content = _inject_theme_attribute_in_block_template_content( $content );
50
47
  $blocks = parse_blocks( $content );
51
48
  $content = gutenberg_serialize_blocks( $blocks );
52
49
  }
@@ -38,6 +38,7 @@ function render_block_core_post_navigation_link( $attributes, $content ) {
38
38
  $link = 'next' === $navigation_type ? _x( 'Next', 'label for next post link' ) : _x( 'Previous', 'label for previous post link' );
39
39
  $label = '';
40
40
 
41
+ // Only use hardcoded values here, otherwise we need to add escaping where these values are used.
41
42
  $arrow_map = array(
42
43
  'none' => '',
43
44
  'arrow' => array(
@@ -88,7 +89,7 @@ function render_block_core_post_navigation_link( $attributes, $content ) {
88
89
  }
89
90
 
90
91
  // Display arrows.
91
- if ( isset( $attributes['arrow'] ) && ! empty( $attributes['arrow'] ) && 'none' !== $attributes['arrow'] ) {
92
+ if ( isset( $attributes['arrow'] ) && 'none' !== $attributes['arrow'] && isset( $arrow_map[ $attributes['arrow'] ] ) ) {
92
93
  $arrow = $arrow_map[ $attributes['arrow'] ][ $navigation_type ];
93
94
 
94
95
  if ( 'next' === $navigation_type ) {
@@ -70,4 +70,42 @@ describe( 'Preformatted', () => {
70
70
  <!-- /wp:preformatted -->"
71
71
  ` );
72
72
  } );
73
+
74
+ it( 'should split on triple Enter', async () => {
75
+ // Arrange
76
+ const screen = await initializeEditor();
77
+
78
+ // Act
79
+ await addBlock( screen, 'Preformatted' );
80
+ const preformattedTextInput = await screen.findByPlaceholderText(
81
+ 'Write preformatted text…'
82
+ );
83
+ typeInRichText( preformattedTextInput, 'Hello' );
84
+ fireEvent( preformattedTextInput, 'onKeyDown', {
85
+ nativeEvent: {},
86
+ preventDefault() {},
87
+ keyCode: ENTER,
88
+ } );
89
+ fireEvent( preformattedTextInput, 'onKeyDown', {
90
+ nativeEvent: {},
91
+ preventDefault() {},
92
+ keyCode: ENTER,
93
+ } );
94
+ fireEvent( preformattedTextInput, 'onKeyDown', {
95
+ nativeEvent: {},
96
+ preventDefault() {},
97
+ keyCode: ENTER,
98
+ } );
99
+
100
+ // Assert
101
+ expect( getEditorHtml() ).toMatchInlineSnapshot( `
102
+ "<!-- wp:preformatted -->
103
+ <pre class="wp-block-preformatted">Hello</pre>
104
+ <!-- /wp:preformatted -->
105
+
106
+ <!-- wp:paragraph -->
107
+ <p></p>
108
+ <!-- /wp:paragraph -->"
109
+ ` );
110
+ } );
73
111
  } );
@@ -34,7 +34,8 @@ function render_block_core_query( $attributes, $content, $block ) {
34
34
  'loadedText' => __( 'Page Loaded.' ),
35
35
  ),
36
36
  ),
37
- )
37
+ ),
38
+ JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP
38
39
  )
39
40
  );
40
41
  $content = $p->get_updated_html();
@@ -47,7 +48,7 @@ function render_block_core_query( $attributes, $content, $block ) {
47
48
  $content = substr_replace(
48
49
  $content,
49
50
  '<div
50
- class="wp-block-query__enhanced-pagination-navigation-announce"
51
+ class="screen-reader-text"
51
52
  aria-live="polite"
52
53
  data-wp-text="context.core.query.message"
53
54
  ></div>
@@ -50,14 +50,3 @@
50
50
  opacity: 0;
51
51
  }
52
52
  }
53
-
54
- .wp-block-query__enhanced-pagination-navigation-announce {
55
- position: absolute;
56
- clip: rect(0, 0, 0, 0);
57
- width: 1px;
58
- height: 1px;
59
- padding: 0;
60
- margin: -1px;
61
- overflow: hidden;
62
- border: 0;
63
- }
@@ -281,8 +281,6 @@ function classnames_for_block_core_search( $attributes ) {
281
281
  * @param array $wrapper_styles Current collection of wrapper styles.
282
282
  * @param array $button_styles Current collection of button styles.
283
283
  * @param array $input_styles Current collection of input styles.
284
- *
285
- * @return void
286
284
  */
287
285
  function apply_block_core_search_border_style( $attributes, $property, $side, &$wrapper_styles, &$button_styles, &$input_styles ) {
288
286
  $is_button_inside = isset( $attributes['buttonPosition'] ) && 'button-inside' === $attributes['buttonPosition'];
@@ -327,8 +325,6 @@ function apply_block_core_search_border_style( $attributes, $property, $side, &$
327
325
  * @param array $wrapper_styles Current collection of wrapper styles.
328
326
  * @param array $button_styles Current collection of button styles.
329
327
  * @param array $input_styles Current collection of input styles.
330
- *
331
- * @return void
332
328
  */
333
329
  function apply_block_core_search_border_styles( $attributes, $property, &$wrapper_styles, &$button_styles, &$input_styles ) {
334
330
  apply_block_core_search_border_style( $attributes, $property, null, $wrapper_styles, $button_styles, $input_styles );
package/src/style.scss CHANGED
@@ -14,6 +14,7 @@
14
14
  @import "./details/style.scss";
15
15
  @import "./embed/style.scss";
16
16
  @import "./file/style.scss";
17
+ @import "./form-input/style.scss";
17
18
  @import "./gallery/style.scss";
18
19
  @import "./group/style.scss";
19
20
  @import "./heading/style.scss";
@@ -23,7 +23,8 @@
23
23
  "supports": {
24
24
  "align": true,
25
25
  "html": false,
26
- "reusable": false
26
+ "reusable": false,
27
+ "renaming": false
27
28
  },
28
29
  "editorStyle": "wp-block-template-part-editor"
29
30
  }