@wordpress/block-library 8.22.0 → 8.24.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 (266) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/block/edit.js +11 -13
  3. package/build/block/edit.js.map +1 -1
  4. package/build/block/edit.native.js +3 -4
  5. package/build/block/edit.native.js.map +1 -1
  6. package/build/button/edit.js +61 -9
  7. package/build/button/edit.js.map +1 -1
  8. package/build/code/transforms.js +20 -7
  9. package/build/code/transforms.js.map +1 -1
  10. package/build/column/edit.js +1 -1
  11. package/build/column/edit.js.map +1 -1
  12. package/build/column/edit.native.js +1 -1
  13. package/build/column/edit.native.js.map +1 -1
  14. package/build/comments/edit/comments-inspector-controls.js +1 -0
  15. package/build/comments/edit/comments-inspector-controls.js.map +1 -1
  16. package/build/cover/edit/index.js +2 -1
  17. package/build/cover/edit/index.js.map +1 -1
  18. package/build/cover/edit/inspector-controls.js +1 -0
  19. package/build/cover/edit/inspector-controls.js.map +1 -1
  20. package/build/details/edit.js +1 -2
  21. package/build/details/edit.js.map +1 -1
  22. package/build/file/edit.js +8 -9
  23. package/build/file/edit.js.map +1 -1
  24. package/build/file/view.js +4 -6
  25. package/build/file/view.js.map +1 -1
  26. package/build/form/index.js +1 -1
  27. package/build/form/index.js.map +1 -1
  28. package/build/form-submit-button/edit.js +2 -1
  29. package/build/form-submit-button/edit.js.map +1 -1
  30. package/build/gallery/gap-styles.js +12 -7
  31. package/build/gallery/gap-styles.js.map +1 -1
  32. package/build/group/edit.js +4 -7
  33. package/build/group/edit.js.map +1 -1
  34. package/build/html/transforms.js +7 -2
  35. package/build/html/transforms.js.map +1 -1
  36. package/build/image/deprecated.js +8 -0
  37. package/build/image/deprecated.js.map +1 -1
  38. package/build/image/edit.js +17 -18
  39. package/build/image/edit.js.map +1 -1
  40. package/build/image/edit.native.js +22 -15
  41. package/build/image/edit.native.js.map +1 -1
  42. package/build/image/image.js +35 -27
  43. package/build/image/image.js.map +1 -1
  44. package/build/image/index.js +2 -3
  45. package/build/image/index.js.map +1 -1
  46. package/build/image/view.js +234 -266
  47. package/build/image/view.js.map +1 -1
  48. package/build/missing/index.js +1 -1
  49. package/build/navigation/edit/overlay-menu-preview.js +1 -1
  50. package/build/navigation/edit/overlay-menu-preview.js.map +1 -1
  51. package/build/navigation/use-template-part-area-label.js +2 -1
  52. package/build/navigation/use-template-part-area-label.js.map +1 -1
  53. package/build/navigation/view.js +153 -176
  54. package/build/navigation/view.js.map +1 -1
  55. package/build/navigation-link/edit.js +1 -1
  56. package/build/navigation-link/edit.js.map +1 -1
  57. package/build/navigation-link/index.js +2 -1
  58. package/build/navigation-link/index.js.map +1 -1
  59. package/build/pattern/edit.js +2 -4
  60. package/build/pattern/edit.js.map +1 -1
  61. package/build/post-author/edit.js +0 -1
  62. package/build/post-author/edit.js.map +1 -1
  63. package/build/post-featured-image/edit.js +21 -6
  64. package/build/post-featured-image/edit.js.map +1 -1
  65. package/build/post-template/edit.js +2 -8
  66. package/build/post-template/edit.js.map +1 -1
  67. package/build/post-template/index.js +1 -1
  68. package/build/post-terms/edit.js +0 -2
  69. package/build/post-terms/edit.js.map +1 -1
  70. package/build/preformatted/transforms.js +1 -4
  71. package/build/preformatted/transforms.js.map +1 -1
  72. package/build/query/edit/query-content.js +1 -0
  73. package/build/query/edit/query-content.js.map +1 -1
  74. package/build/query/view.js +52 -60
  75. package/build/query/view.js.map +1 -1
  76. package/build/quote/index.js +6 -0
  77. package/build/quote/index.js.map +1 -1
  78. package/build/search/view.js +66 -74
  79. package/build/search/view.js.map +1 -1
  80. package/build/template-part/edit/advanced-controls.js +1 -0
  81. package/build/template-part/edit/advanced-controls.js.map +1 -1
  82. package/build/template-part/edit/index.js +3 -7
  83. package/build/template-part/edit/index.js.map +1 -1
  84. package/build/template-part/index.js +6 -2
  85. package/build/template-part/index.js.map +1 -1
  86. package/build/template-part/variations.js +5 -1
  87. package/build/template-part/variations.js.map +1 -1
  88. package/build/utils/remove-anchor-tag.js +17 -0
  89. package/build/utils/remove-anchor-tag.js.map +1 -0
  90. package/build-module/block/edit.js +11 -13
  91. package/build-module/block/edit.js.map +1 -1
  92. package/build-module/block/edit.native.js +3 -4
  93. package/build-module/block/edit.native.js.map +1 -1
  94. package/build-module/button/edit.js +65 -13
  95. package/build-module/button/edit.js.map +1 -1
  96. package/build-module/code/transforms.js +20 -7
  97. package/build-module/code/transforms.js.map +1 -1
  98. package/build-module/column/edit.js +1 -1
  99. package/build-module/column/edit.js.map +1 -1
  100. package/build-module/column/edit.native.js +1 -1
  101. package/build-module/column/edit.native.js.map +1 -1
  102. package/build-module/comments/edit/comments-inspector-controls.js +1 -0
  103. package/build-module/comments/edit/comments-inspector-controls.js.map +1 -1
  104. package/build-module/cover/edit/index.js +2 -1
  105. package/build-module/cover/edit/index.js.map +1 -1
  106. package/build-module/cover/edit/inspector-controls.js +1 -0
  107. package/build-module/cover/edit/inspector-controls.js.map +1 -1
  108. package/build-module/details/edit.js +1 -2
  109. package/build-module/details/edit.js.map +1 -1
  110. package/build-module/file/edit.js +8 -9
  111. package/build-module/file/edit.js.map +1 -1
  112. package/build-module/file/view.js +5 -7
  113. package/build-module/file/view.js.map +1 -1
  114. package/build-module/form/index.js +1 -1
  115. package/build-module/form/index.js.map +1 -1
  116. package/build-module/form-submit-button/edit.js +2 -1
  117. package/build-module/form-submit-button/edit.js.map +1 -1
  118. package/build-module/gallery/gap-styles.js +13 -8
  119. package/build-module/gallery/gap-styles.js.map +1 -1
  120. package/build-module/group/edit.js +4 -7
  121. package/build-module/group/edit.js.map +1 -1
  122. package/build-module/html/transforms.js +7 -2
  123. package/build-module/html/transforms.js.map +1 -1
  124. package/build-module/image/deprecated.js +8 -0
  125. package/build-module/image/deprecated.js.map +1 -1
  126. package/build-module/image/edit.js +18 -19
  127. package/build-module/image/edit.js.map +1 -1
  128. package/build-module/image/edit.native.js +23 -16
  129. package/build-module/image/edit.native.js.map +1 -1
  130. package/build-module/image/image.js +36 -28
  131. package/build-module/image/image.js.map +1 -1
  132. package/build-module/image/index.js +2 -3
  133. package/build-module/image/index.js.map +1 -1
  134. package/build-module/image/view.js +235 -267
  135. package/build-module/image/view.js.map +1 -1
  136. package/build-module/missing/index.js +1 -1
  137. package/build-module/navigation/edit/overlay-menu-preview.js +1 -1
  138. package/build-module/navigation/edit/overlay-menu-preview.js.map +1 -1
  139. package/build-module/navigation/use-template-part-area-label.js +2 -1
  140. package/build-module/navigation/use-template-part-area-label.js.map +1 -1
  141. package/build-module/navigation/view.js +154 -177
  142. package/build-module/navigation/view.js.map +1 -1
  143. package/build-module/navigation-link/edit.js +2 -2
  144. package/build-module/navigation-link/edit.js.map +1 -1
  145. package/build-module/navigation-link/index.js +2 -1
  146. package/build-module/navigation-link/index.js.map +1 -1
  147. package/build-module/pattern/edit.js +2 -4
  148. package/build-module/pattern/edit.js.map +1 -1
  149. package/build-module/post-author/edit.js +0 -1
  150. package/build-module/post-author/edit.js.map +1 -1
  151. package/build-module/post-featured-image/edit.js +21 -6
  152. package/build-module/post-featured-image/edit.js.map +1 -1
  153. package/build-module/post-template/edit.js +2 -8
  154. package/build-module/post-template/edit.js.map +1 -1
  155. package/build-module/post-template/index.js +1 -1
  156. package/build-module/post-terms/edit.js +0 -2
  157. package/build-module/post-terms/edit.js.map +1 -1
  158. package/build-module/preformatted/transforms.js +1 -4
  159. package/build-module/preformatted/transforms.js.map +1 -1
  160. package/build-module/query/edit/query-content.js +1 -0
  161. package/build-module/query/edit/query-content.js.map +1 -1
  162. package/build-module/query/view.js +53 -61
  163. package/build-module/query/view.js.map +1 -1
  164. package/build-module/quote/index.js +6 -0
  165. package/build-module/quote/index.js.map +1 -1
  166. package/build-module/search/view.js +67 -75
  167. package/build-module/search/view.js.map +1 -1
  168. package/build-module/template-part/edit/advanced-controls.js +1 -0
  169. package/build-module/template-part/edit/advanced-controls.js.map +1 -1
  170. package/build-module/template-part/edit/index.js +5 -9
  171. package/build-module/template-part/edit/index.js.map +1 -1
  172. package/build-module/template-part/index.js +6 -2
  173. package/build-module/template-part/index.js.map +1 -1
  174. package/build-module/template-part/variations.js +5 -1
  175. package/build-module/template-part/variations.js.map +1 -1
  176. package/build-module/utils/remove-anchor-tag.js +11 -0
  177. package/build-module/utils/remove-anchor-tag.js.map +1 -0
  178. package/build-style/cover/style-rtl.css +14 -14
  179. package/build-style/cover/style.css +14 -14
  180. package/build-style/editor-rtl.css +15 -6
  181. package/build-style/editor.css +15 -6
  182. package/build-style/gallery/style-rtl.css +28 -0
  183. package/build-style/gallery/style.css +28 -0
  184. package/build-style/image/style-rtl.css +19 -13
  185. package/build-style/image/style.css +19 -13
  186. package/build-style/post-featured-image/editor-rtl.css +9 -0
  187. package/build-style/post-featured-image/editor.css +9 -0
  188. package/build-style/quote/style-rtl.css +3 -0
  189. package/build-style/quote/style.css +3 -0
  190. package/build-style/read-more/style-rtl.css +2 -2
  191. package/build-style/read-more/style.css +2 -2
  192. package/build-style/style-rtl.css +66 -29
  193. package/build-style/style.css +66 -29
  194. package/package.json +32 -32
  195. package/src/block/edit.js +20 -20
  196. package/src/block/edit.native.js +5 -13
  197. package/src/button/edit.js +76 -10
  198. package/src/buttons/test/__snapshots__/edit.native.js.snap +0 -6
  199. package/src/buttons/test/edit.native.js +0 -27
  200. package/src/code/transforms.js +14 -8
  201. package/src/column/edit.js +1 -1
  202. package/src/column/edit.native.js +1 -1
  203. package/src/comments/edit/comments-inspector-controls.js +1 -0
  204. package/src/cover/edit/index.js +1 -0
  205. package/src/cover/edit/inspector-controls.js +1 -0
  206. package/src/cover/style.scss +1 -1
  207. package/src/cover/test/edit.js +1 -1
  208. package/src/details/edit.js +0 -1
  209. package/src/editor.scss +6 -6
  210. package/src/file/edit.js +11 -10
  211. package/src/file/index.php +30 -11
  212. package/src/file/view.js +5 -7
  213. package/src/form/index.js +1 -1
  214. package/src/form-submit-button/edit.js +1 -0
  215. package/src/gallery/gap-styles.js +10 -9
  216. package/src/gallery/style.scss +1 -0
  217. package/src/group/edit.js +4 -11
  218. package/src/heading/test/__snapshots__/index.native.js.snap +6 -0
  219. package/src/heading/test/index.native.js +40 -0
  220. package/src/html/transforms.js +5 -2
  221. package/src/image/block.json +2 -3
  222. package/src/image/deprecated.js +8 -0
  223. package/src/image/edit.js +16 -21
  224. package/src/image/edit.native.js +17 -18
  225. package/src/image/image.js +48 -51
  226. package/src/image/index.php +57 -49
  227. package/src/image/style.scss +18 -13
  228. package/src/image/view.js +281 -324
  229. package/src/missing/block.json +1 -1
  230. package/src/navigation/edit/overlay-menu-preview.js +1 -1
  231. package/src/navigation/index.php +46 -402
  232. package/src/navigation/use-template-part-area-label.js +4 -2
  233. package/src/navigation/view.js +159 -192
  234. package/src/navigation-link/block.json +2 -1
  235. package/src/navigation-link/edit.js +2 -2
  236. package/src/navigation-link/index.php +57 -0
  237. package/src/paragraph/test/__snapshots__/transforms.native.js.snap +6 -0
  238. package/src/paragraph/test/edit.native.js +37 -1
  239. package/src/paragraph/test/transforms.native.js +1 -0
  240. package/src/pattern/edit.js +7 -4
  241. package/src/pattern/index.php +6 -1
  242. package/src/post-author/edit.js +0 -1
  243. package/src/post-featured-image/edit.js +38 -5
  244. package/src/post-featured-image/editor.scss +19 -0
  245. package/src/post-template/block.json +0 -1
  246. package/src/post-template/edit.js +1 -5
  247. package/src/post-terms/edit.js +0 -2
  248. package/src/preformatted/transforms.js +1 -4
  249. package/src/query/edit/query-content.js +1 -0
  250. package/src/query/index.php +42 -24
  251. package/src/query/view.js +58 -65
  252. package/src/query-pagination-next/index.php +3 -3
  253. package/src/query-pagination-numbers/index.php +1 -1
  254. package/src/query-pagination-previous/index.php +3 -3
  255. package/src/quote/block.json +6 -0
  256. package/src/quote/style.scss +4 -0
  257. package/src/read-more/style.scss +1 -1
  258. package/src/search/index.php +40 -40
  259. package/src/search/view.js +58 -63
  260. package/src/template-part/edit/advanced-controls.js +1 -0
  261. package/src/template-part/edit/index.js +7 -14
  262. package/src/template-part/index.js +4 -3
  263. package/src/template-part/index.php +4 -4
  264. package/src/template-part/variations.js +4 -2
  265. package/src/utils/remove-anchor-tag.js +10 -0
  266. package/tsconfig.json +1 -0
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * WordPress dependencies
3
3
  */
4
- import { store as wpStore } from '@wordpress/interactivity';
4
+ import { store, getContext, getElement } from '@wordpress/interactivity';
5
5
 
6
6
  const focusableSelectors = [
7
7
  'a[href]',
@@ -18,205 +18,172 @@ const focusableSelectors = [
18
18
  // capture the clicks, instead of relying on the focusout event.
19
19
  document.addEventListener( 'click', () => {} );
20
20
 
21
- const openMenu = ( store, menuOpenedOn ) => {
22
- const { context, selectors } = store;
23
- selectors.core.navigation.menuOpenedBy( store )[ menuOpenedOn ] = true;
24
- if ( context.core.navigation.type === 'overlay' ) {
25
- // Add a `has-modal-open` class to the <html> root.
26
- document.documentElement.classList.add( 'has-modal-open' );
27
- }
28
- };
29
-
30
- const closeMenu = ( store, menuClosedOn ) => {
31
- const { context, selectors } = store;
32
- selectors.core.navigation.menuOpenedBy( store )[ menuClosedOn ] = false;
33
- // Check if the menu is still open or not.
34
- if ( ! selectors.core.navigation.isMenuOpen( store ) ) {
35
- if (
36
- context.core.navigation.modal?.contains(
37
- window.document.activeElement
38
- )
39
- ) {
40
- context.core.navigation.previousFocus?.focus();
41
- }
42
- context.core.navigation.modal = null;
43
- context.core.navigation.previousFocus = null;
44
- if ( context.core.navigation.type === 'overlay' ) {
45
- document.documentElement.classList.remove( 'has-modal-open' );
46
- }
47
- }
48
- };
49
-
50
- wpStore( {
51
- effects: {
52
- core: {
53
- navigation: {
54
- initMenu: ( store ) => {
55
- const { context, selectors, ref } = store;
56
- if ( selectors.core.navigation.isMenuOpen( store ) ) {
57
- const focusableElements =
58
- ref.querySelectorAll( focusableSelectors );
59
- context.core.navigation.modal = ref;
60
- context.core.navigation.firstFocusableElement =
61
- focusableElements[ 0 ];
62
- context.core.navigation.lastFocusableElement =
63
- focusableElements[ focusableElements.length - 1 ];
64
- }
65
- },
66
- focusFirstElement: ( store ) => {
67
- const { selectors, ref } = store;
68
- if ( selectors.core.navigation.isMenuOpen( store ) ) {
69
- ref.querySelector(
70
- '.wp-block-navigation-item > *:first-child'
71
- ).focus();
72
- }
73
- },
74
- },
21
+ const { state, actions } = store( 'core/navigation', {
22
+ state: {
23
+ get roleAttribute() {
24
+ const ctx = getContext();
25
+ return ctx.type === 'overlay' && state.isMenuOpen ? 'dialog' : null;
75
26
  },
76
- },
77
- selectors: {
78
- core: {
79
- navigation: {
80
- roleAttribute: ( store ) => {
81
- const { context, selectors } = store;
82
- return context.core.navigation.type === 'overlay' &&
83
- selectors.core.navigation.isMenuOpen( store )
84
- ? 'dialog'
85
- : null;
86
- },
87
- ariaModal: ( store ) => {
88
- const { context, selectors } = store;
89
- return context.core.navigation.type === 'overlay' &&
90
- selectors.core.navigation.isMenuOpen( store )
91
- ? 'true'
92
- : null;
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
- },
101
- isMenuOpen: ( { context } ) =>
102
- // The menu is opened if either `click`, `hover` or `focus` is true.
103
- Object.values(
104
- context.core.navigation[
105
- context.core.navigation.type === 'overlay'
106
- ? 'overlayOpenedBy'
107
- : 'submenuOpenedBy'
108
- ]
109
- ).filter( Boolean ).length > 0,
110
- menuOpenedBy: ( { context } ) =>
111
- context.core.navigation[
112
- context.core.navigation.type === 'overlay'
113
- ? 'overlayOpenedBy'
114
- : 'submenuOpenedBy'
115
- ],
116
- },
27
+ get ariaModal() {
28
+ const ctx = getContext();
29
+ return ctx.type === 'overlay' && state.isMenuOpen ? 'true' : null;
30
+ },
31
+ get ariaLabel() {
32
+ const ctx = getContext();
33
+ return ctx.type === 'overlay' && state.isMenuOpen
34
+ ? ctx.ariaLabel
35
+ : null;
36
+ },
37
+ get isMenuOpen() {
38
+ // The menu is opened if either `click`, `hover` or `focus` is true.
39
+ return (
40
+ Object.values( state.menuOpenedBy ).filter( Boolean ).length > 0
41
+ );
42
+ },
43
+ get menuOpenedBy() {
44
+ const ctx = getContext();
45
+ return ctx.type === 'overlay'
46
+ ? ctx.overlayOpenedBy
47
+ : ctx.submenuOpenedBy;
117
48
  },
118
49
  },
119
50
  actions: {
120
- core: {
121
- navigation: {
122
- openMenuOnHover( store ) {
123
- const { navigation } = store.context.core;
124
- if (
125
- navigation.type === 'submenu' &&
126
- // Only open on hover if the overlay is closed.
127
- Object.values(
128
- navigation.overlayOpenedBy || {}
129
- ).filter( Boolean ).length === 0
130
- )
131
- openMenu( store, 'hover' );
132
- },
133
- closeMenuOnHover( store ) {
134
- closeMenu( store, 'hover' );
135
- },
136
- openMenuOnClick( store ) {
137
- const { context, ref } = store;
138
- context.core.navigation.previousFocus = ref;
139
- openMenu( store, 'click' );
140
- },
141
- closeMenuOnClick( store ) {
142
- closeMenu( store, 'click' );
143
- closeMenu( store, 'focus' );
144
- },
145
- openMenuOnFocus( store ) {
146
- openMenu( store, 'focus' );
147
- },
148
- toggleMenuOnClick: ( 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();
152
- const menuOpenedBy =
153
- selectors.core.navigation.menuOpenedBy( store );
154
- if ( menuOpenedBy.click || menuOpenedBy.focus ) {
155
- closeMenu( store, 'click' );
156
- closeMenu( store, 'focus' );
157
- } else {
158
- context.core.navigation.previousFocus = ref;
159
- openMenu( store, 'click' );
160
- }
161
- },
162
- handleMenuKeydown: ( store ) => {
163
- const { context, selectors, event } = store;
164
- if (
165
- selectors.core.navigation.menuOpenedBy( store ).click
166
- ) {
167
- // If Escape close the menu.
168
- if ( event?.key === 'Escape' ) {
169
- closeMenu( store, 'click' );
170
- closeMenu( store, 'focus' );
171
- return;
172
- }
173
-
174
- // Trap focus if it is an overlay (main menu).
175
- if (
176
- context.core.navigation.type === 'overlay' &&
177
- event.key === 'Tab'
178
- ) {
179
- // If shift + tab it change the direction.
180
- if (
181
- event.shiftKey &&
182
- window.document.activeElement ===
183
- context.core.navigation
184
- .firstFocusableElement
185
- ) {
186
- event.preventDefault();
187
- context.core.navigation.lastFocusableElement.focus();
188
- } else if (
189
- ! event.shiftKey &&
190
- window.document.activeElement ===
191
- context.core.navigation.lastFocusableElement
192
- ) {
193
- event.preventDefault();
194
- context.core.navigation.firstFocusableElement.focus();
195
- }
196
- }
197
- }
198
- },
199
- handleMenuFocusout: ( store ) => {
200
- const { context, event } = store;
201
- // If focus is outside modal, and in the document, close menu
202
- // event.target === The element losing focus
203
- // event.relatedTarget === The element receiving focus (if any)
204
- // When focusout is outsite the document,
205
- // `window.document.activeElement` doesn't change.
51
+ openMenuOnHover() {
52
+ const { type, overlayOpenedBy } = getContext();
53
+ if (
54
+ type === 'submenu' &&
55
+ // Only open on hover if the overlay is closed.
56
+ Object.values( overlayOpenedBy || {} ).filter( Boolean )
57
+ .length === 0
58
+ )
59
+ actions.openMenu( 'hover' );
60
+ },
61
+ closeMenuOnHover() {
62
+ actions.closeMenu( 'hover' );
63
+ },
64
+ openMenuOnClick() {
65
+ const ctx = getContext();
66
+ const { ref } = getElement();
67
+ ctx.previousFocus = ref;
68
+ actions.openMenu( 'click' );
69
+ },
70
+ closeMenuOnClick() {
71
+ actions.closeMenu( 'click' );
72
+ actions.closeMenu( 'focus' );
73
+ },
74
+ openMenuOnFocus() {
75
+ actions.openMenu( 'focus' );
76
+ },
77
+ toggleMenuOnClick() {
78
+ const ctx = getContext();
79
+ const { ref } = getElement();
80
+ // 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
81
+ if ( window.document.activeElement !== ref ) ref.focus();
82
+ const { menuOpenedBy } = state;
83
+ if ( menuOpenedBy.click || menuOpenedBy.focus ) {
84
+ actions.closeMenu( 'click' );
85
+ actions.closeMenu( 'focus' );
86
+ } else {
87
+ ctx.previousFocus = ref;
88
+ actions.openMenu( 'click' );
89
+ }
90
+ },
91
+ handleMenuKeydown( event ) {
92
+ const { type, firstFocusableElement, lastFocusableElement } =
93
+ getContext();
94
+ if ( state.menuOpenedBy.click ) {
95
+ // If Escape close the menu.
96
+ if ( event?.key === 'Escape' ) {
97
+ actions.closeMenu( 'click' );
98
+ actions.closeMenu( 'focus' );
99
+ return;
100
+ }
206
101
 
207
- // The event.relatedTarget is null when something outside the navigation menu is clicked. This is only necessary for Safari.
102
+ // Trap focus if it is an overlay (main menu).
103
+ if ( type === 'overlay' && event.key === 'Tab' ) {
104
+ // If shift + tab it change the direction.
208
105
  if (
209
- event.relatedTarget === null ||
210
- ( ! context.core.navigation.modal?.contains(
211
- event.relatedTarget
212
- ) &&
213
- event.target !== window.document.activeElement )
106
+ event.shiftKey &&
107
+ window.document.activeElement === firstFocusableElement
214
108
  ) {
215
- closeMenu( store, 'click' );
216
- closeMenu( store, 'focus' );
109
+ event.preventDefault();
110
+ lastFocusableElement.focus();
111
+ } else if (
112
+ ! event.shiftKey &&
113
+ window.document.activeElement === lastFocusableElement
114
+ ) {
115
+ event.preventDefault();
116
+ firstFocusableElement.focus();
217
117
  }
218
- },
219
- },
118
+ }
119
+ }
120
+ },
121
+ handleMenuFocusout( event ) {
122
+ const { modal } = getContext();
123
+ // If focus is outside modal, and in the document, close menu
124
+ // event.target === The element losing focus
125
+ // event.relatedTarget === The element receiving focus (if any)
126
+ // When focusout is outsite the document,
127
+ // `window.document.activeElement` doesn't change.
128
+
129
+ // The event.relatedTarget is null when something outside the navigation menu is clicked. This is only necessary for Safari.
130
+ if (
131
+ event.relatedTarget === null ||
132
+ ( ! modal?.contains( event.relatedTarget ) &&
133
+ event.target !== window.document.activeElement )
134
+ ) {
135
+ actions.closeMenu( 'click' );
136
+ actions.closeMenu( 'focus' );
137
+ }
138
+ },
139
+
140
+ openMenu( menuOpenedOn = 'click' ) {
141
+ const { type } = getContext();
142
+ state.menuOpenedBy[ menuOpenedOn ] = true;
143
+ if ( type === 'overlay' ) {
144
+ // Add a `has-modal-open` class to the <html> root.
145
+ document.documentElement.classList.add( 'has-modal-open' );
146
+ }
147
+ },
148
+
149
+ closeMenu( menuClosedOn = 'click' ) {
150
+ const ctx = getContext();
151
+ state.menuOpenedBy[ menuClosedOn ] = false;
152
+ // Check if the menu is still open or not.
153
+ if ( ! state.isMenuOpen ) {
154
+ if ( ctx.modal?.contains( window.document.activeElement ) ) {
155
+ ctx.previousFocus?.focus();
156
+ }
157
+ ctx.modal = null;
158
+ ctx.previousFocus = null;
159
+ if ( ctx.type === 'overlay' ) {
160
+ document.documentElement.classList.remove(
161
+ 'has-modal-open'
162
+ );
163
+ }
164
+ }
165
+ },
166
+ },
167
+ callbacks: {
168
+ initMenu() {
169
+ const ctx = getContext();
170
+ const { ref } = getElement();
171
+ if ( state.isMenuOpen ) {
172
+ const focusableElements =
173
+ ref.querySelectorAll( focusableSelectors );
174
+ ctx.modal = ref;
175
+ ctx.firstFocusableElement = focusableElements[ 0 ];
176
+ ctx.lastFocusableElement =
177
+ focusableElements[ focusableElements.length - 1 ];
178
+ }
179
+ },
180
+ focusFirstElement() {
181
+ const { ref } = getElement();
182
+ if ( state.isMenuOpen ) {
183
+ ref.querySelector(
184
+ '.wp-block-navigation-item > *:first-child'
185
+ ).focus();
186
+ }
220
187
  },
221
188
  },
222
189
  } );
@@ -71,7 +71,8 @@
71
71
  "__experimentalDefaultControls": {
72
72
  "fontSize": true
73
73
  }
74
- }
74
+ },
75
+ "renaming": false
75
76
  },
76
77
  "editorStyle": "wp-block-navigation-link-editor",
77
78
  "style": "wp-block-navigation-link"
@@ -27,7 +27,7 @@ import {
27
27
  getColorClassName,
28
28
  useInnerBlocksProps,
29
29
  } from '@wordpress/block-editor';
30
- import { isURL, prependHTTP } from '@wordpress/url';
30
+ import { isURL, prependHTTP, safeDecodeURI } from '@wordpress/url';
31
31
  import { useState, useEffect, useRef } from '@wordpress/element';
32
32
  import {
33
33
  placeCaretAtHorizontalEdge,
@@ -432,7 +432,7 @@ export default function NavigationLinkEdit( {
432
432
  />
433
433
  <TextControl
434
434
  __nextHasNoMarginBottom
435
- value={ url || '' }
435
+ value={ url ? safeDecodeURI( url ) : '' }
436
436
  onChange={ ( urlValue ) => {
437
437
  updateAttributes(
438
438
  { url: urlValue },
@@ -322,6 +322,25 @@ function build_variation_for_navigation_link( $entity, $kind ) {
322
322
  return $variation;
323
323
  }
324
324
 
325
+ /**
326
+ * Register a variation for a post type / taxonomy for the navigation link block
327
+ *
328
+ * @param array $variation Variation array from build_variation_for_navigation_link.
329
+ * @return void
330
+ */
331
+ function register_block_core_navigation_link_variation( $variation ) {
332
+ // Directly set the variations on the registered block type
333
+ // because there's no server side registration for variations (see #47170).
334
+ $navigation_block_type = WP_Block_Type_Registry::get_instance()->get_registered( 'core/navigation-link' );
335
+ // If the block is not registered yet, bail early.
336
+ // Variation will be registered in register_block_core_navigation_link then.
337
+ if ( ! $navigation_block_type ) {
338
+ return;
339
+ }
340
+
341
+ $navigation_block_type->variations[] = $variation;
342
+ }
343
+
325
344
  /**
326
345
  * Register the navigation link block.
327
346
  *
@@ -329,6 +348,9 @@ function build_variation_for_navigation_link( $entity, $kind ) {
329
348
  * @throws WP_Error An WP_Error exception parsing the block definition.
330
349
  */
331
350
  function register_block_core_navigation_link() {
351
+ // This will only handle post types and taxonomies registered until this point (init on priority 9).
352
+ // See action hooks below for other post types and taxonomies.
353
+ // See https://github.com/WordPress/gutenberg/issues/53826 for details.
332
354
  $post_types = get_post_types( array( 'show_in_nav_menus' => true ), 'objects' );
333
355
  $taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'objects' );
334
356
 
@@ -369,3 +391,38 @@ function register_block_core_navigation_link() {
369
391
  );
370
392
  }
371
393
  add_action( 'init', 'register_block_core_navigation_link' );
394
+ // Register actions for all post types and taxonomies, to add variations when they are registered.
395
+ // All post types/taxonomies registered before register_block_core_navigation_link, will be handled by that function.
396
+ add_action( 'registered_post_type', 'register_block_core_navigation_link_post_type_variation', 10, 2 );
397
+ add_action( 'registered_taxonomy', 'register_block_core_navigation_link_taxonomy_variation', 10, 3 );
398
+
399
+ /**
400
+ * Register custom post type variations for navigation link on post type registration
401
+ * Handles all post types registered after the block is registered in register_navigation_link_post_type_variations
402
+ *
403
+ * @param string $post_type The post type name passed from registered_post_type filter.
404
+ * @param WP_Post_Type $post_type_object The post type object passed from registered_post_type.
405
+ * @return void
406
+ */
407
+ function register_block_core_navigation_link_post_type_variation( $post_type, $post_type_object ) {
408
+ if ( $post_type_object->show_in_nav_menus ) {
409
+ $variation = build_variation_for_navigation_link( $post_type_object, 'post-type' );
410
+ register_block_core_navigation_link_variation( $variation );
411
+ }
412
+ }
413
+
414
+ /**
415
+ * Register a custom taxonomy variation for navigation link on taxonomy registration
416
+ * Handles all taxonomies registered after the block is registered in register_navigation_link_post_type_variations
417
+ *
418
+ * @param string $taxonomy Taxonomy slug.
419
+ * @param array|string $object_type Object type or array of object types.
420
+ * @param array $args Array of taxonomy registration arguments.
421
+ * @return void
422
+ */
423
+ function register_block_core_navigation_link_taxonomy_variation( $taxonomy, $object_type, $args ) {
424
+ if ( isset( $args['show_in_nav_menus'] ) && $args['show_in_nav_menus'] ) {
425
+ $variation = build_variation_for_navigation_link( (object) $args, 'post-type' );
426
+ register_block_core_navigation_link_variation( $variation );
427
+ }
428
+ }
@@ -1,5 +1,11 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
+ exports[`Paragraph block transforms to Code block 1`] = `
4
+ "<!-- wp:code -->
5
+ <pre class="wp-block-code"><code>Example text</code></pre>
6
+ <!-- /wp:code -->"
7
+ `;
8
+
3
9
  exports[`Paragraph block transforms to Columns block 1`] = `
4
10
  "<!-- wp:columns -->
5
11
  <div class="wp-block-columns"><!-- wp:column {"width":"100%"} -->
@@ -17,11 +17,12 @@ import {
17
17
  waitForElementToBeRemoved,
18
18
  } from 'test/helpers';
19
19
  import Clipboard from '@react-native-clipboard/clipboard';
20
+ import TextInputState from 'react-native/Libraries/Components/TextInput/TextInputState';
20
21
 
21
22
  /**
22
23
  * WordPress dependencies
23
24
  */
24
- import { ENTER } from '@wordpress/keycodes';
25
+ import { BACKSPACE, ENTER } from '@wordpress/keycodes';
25
26
 
26
27
  /**
27
28
  * Internal dependencies
@@ -685,4 +686,39 @@ describe( 'Paragraph block', () => {
685
686
  <!-- /wp:paragraph -->"
686
687
  ` );
687
688
  } );
689
+
690
+ it( 'should focus on the previous Paragraph block when backspacing in an empty Paragraph block', async () => {
691
+ // Arrange
692
+ const screen = await initializeEditor();
693
+ await addBlock( screen, 'Paragraph' );
694
+
695
+ // Act
696
+ const paragraphBlock = getBlock( screen, 'Paragraph' );
697
+ fireEvent.press( paragraphBlock );
698
+ const paragraphTextInput =
699
+ within( paragraphBlock ).getByPlaceholderText( 'Start writing…' );
700
+ typeInRichText( paragraphTextInput, 'A quick brown fox jumps' );
701
+
702
+ await addBlock( screen, 'Paragraph' );
703
+ const secondParagraphBlock = getBlock( screen, 'Paragraph', {
704
+ rowIndex: 2,
705
+ } );
706
+ fireEvent.press( secondParagraphBlock );
707
+
708
+ // Clear mock history
709
+ TextInputState.focusTextInput.mockClear();
710
+
711
+ const secondParagraphTextInput =
712
+ within( secondParagraphBlock ).getByPlaceholderText(
713
+ 'Start writing…'
714
+ );
715
+ fireEvent( secondParagraphTextInput, 'onKeyDown', {
716
+ nativeEvent: {},
717
+ preventDefault() {},
718
+ keyCode: BACKSPACE,
719
+ } );
720
+
721
+ // Assert
722
+ expect( TextInputState.focusTextInput ).toHaveBeenCalled();
723
+ } );
688
724
  } );
@@ -23,6 +23,7 @@ const blockTransforms = [
23
23
  'Preformatted',
24
24
  'Pullquote',
25
25
  'Verse',
26
+ 'Code',
26
27
  ...transformsWithInnerBlocks,
27
28
  ];
28
29
 
@@ -20,12 +20,15 @@ const PatternEdit = ( { attributes, clientId } ) => {
20
20
  );
21
21
 
22
22
  const currentThemeStylesheet = useSelect(
23
- ( select ) => select( coreStore ).getCurrentTheme().stylesheet
23
+ ( select ) => select( coreStore ).getCurrentTheme()?.stylesheet,
24
+ []
24
25
  );
25
26
 
26
- const { replaceBlocks, __unstableMarkNextChangeAsNotPersistent } =
27
- useDispatch( blockEditorStore );
28
- const { setBlockEditingMode } = useDispatch( blockEditorStore );
27
+ const {
28
+ replaceBlocks,
29
+ setBlockEditingMode,
30
+ __unstableMarkNextChangeAsNotPersistent,
31
+ } = useDispatch( blockEditorStore );
29
32
  const { getBlockRootClientId, getBlockEditingMode } =
30
33
  useSelect( blockEditorStore );
31
34
 
@@ -48,7 +48,12 @@ function render_block_core_pattern( $attributes ) {
48
48
  $content = gutenberg_serialize_blocks( $blocks );
49
49
  }
50
50
 
51
- return do_blocks( $content );
51
+ $content = do_blocks( $content );
52
+
53
+ global $wp_embed;
54
+ $content = $wp_embed->autoembed( $content );
55
+
56
+ return $content;
52
57
  }
53
58
 
54
59
  add_action( 'init', 'register_block_core_pattern' );
@@ -196,7 +196,6 @@ function PostAuthorEdit( {
196
196
  { ( ! RichText.isEmpty( byline ) || isSelected ) && (
197
197
  <RichText
198
198
  className="wp-block-post-author__byline"
199
- multiline={ false }
200
199
  aria-label={ __( 'Post author byline text' ) }
201
200
  placeholder={ __( 'Write byline…' ) }
202
201
  value={ byline }
@@ -43,6 +43,11 @@ function getMediaSourceUrlBySizeSlug( media, slug ) {
43
43
  );
44
44
  }
45
45
 
46
+ const disabledClickProps = {
47
+ onClick: ( event ) => event.preventDefault(),
48
+ 'aria-disabled': true,
49
+ };
50
+
46
51
  export default function PostFeaturedImageEdit( {
47
52
  clientId,
48
53
  attributes,
@@ -67,9 +72,10 @@ export default function PostFeaturedImageEdit( {
67
72
  postId
68
73
  );
69
74
 
70
- const { media, postType } = useSelect(
75
+ const { media, postType, postPermalink } = useSelect(
71
76
  ( select ) => {
72
- const { getMedia, getPostType } = select( coreStore );
77
+ const { getMedia, getPostType, getEditedEntityRecord } =
78
+ select( coreStore );
73
79
  return {
74
80
  media:
75
81
  featuredImage &&
@@ -77,10 +83,16 @@ export default function PostFeaturedImageEdit( {
77
83
  context: 'view',
78
84
  } ),
79
85
  postType: postTypeSlug && getPostType( postTypeSlug ),
86
+ postPermalink: getEditedEntityRecord(
87
+ 'postType',
88
+ postTypeSlug,
89
+ postId
90
+ )?.link,
80
91
  };
81
92
  },
82
- [ featuredImage, postTypeSlug ]
93
+ [ featuredImage, postTypeSlug, postId ]
83
94
  );
95
+
84
96
  const mediaUrl = getMediaSourceUrlBySizeSlug( media, sizeSlug );
85
97
 
86
98
  const imageSizes = useSelect(
@@ -197,7 +209,17 @@ export default function PostFeaturedImageEdit( {
197
209
  <>
198
210
  { controls }
199
211
  <div { ...blockProps }>
200
- { placeholder() }
212
+ { !! isLink ? (
213
+ <a
214
+ href={ postPermalink }
215
+ target={ linkTarget }
216
+ { ...disabledClickProps }
217
+ >
218
+ { placeholder() }
219
+ </a>
220
+ ) : (
221
+ placeholder()
222
+ ) }
201
223
  <Overlay
202
224
  attributes={ attributes }
203
225
  setAttributes={ setAttributes }
@@ -295,7 +317,18 @@ export default function PostFeaturedImageEdit( {
295
317
  </BlockControls>
296
318
  ) }
297
319
  <figure { ...blockProps }>
298
- { image }
320
+ { /* If the featured image is linked, wrap in an <a /> tag to trigger any inherited link element styles */ }
321
+ { !! isLink ? (
322
+ <a
323
+ href={ postPermalink }
324
+ target={ linkTarget }
325
+ { ...disabledClickProps }
326
+ >
327
+ { image }
328
+ </a>
329
+ ) : (
330
+ image
331
+ ) }
299
332
  <Overlay
300
333
  attributes={ attributes }
301
334
  setAttributes={ setAttributes }