@wordpress/block-library 8.25.1-next.79a6196f.0 → 8.27.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 (242) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/build/avatar/edit.js +2 -2
  3. package/build/avatar/edit.js.map +1 -1
  4. package/build/block/edit.js +75 -12
  5. package/build/block/edit.js.map +1 -1
  6. package/build/block/{v1/edit.native.js → edit.native.js} +4 -4
  7. package/build/block/edit.native.js.map +1 -0
  8. package/build/block/index.js +5 -3
  9. package/build/block/index.js.map +1 -1
  10. package/build/button/edit.js +24 -6
  11. package/build/button/edit.js.map +1 -1
  12. package/build/button/index.js +1 -0
  13. package/build/button/index.js.map +1 -1
  14. package/build/button/save.js +3 -1
  15. package/build/button/save.js.map +1 -1
  16. package/build/embed/edit.js +3 -2
  17. package/build/embed/edit.js.map +1 -1
  18. package/build/file/index.js +0 -1
  19. package/build/file/index.js.map +1 -1
  20. package/build/footnotes/edit.js +2 -1
  21. package/build/footnotes/edit.js.map +1 -1
  22. package/build/footnotes/format.js +17 -19
  23. package/build/footnotes/format.js.map +1 -1
  24. package/build/heading/edit.js +2 -1
  25. package/build/heading/edit.js.map +1 -1
  26. package/build/heading/edit.native.js +141 -0
  27. package/build/heading/edit.native.js.map +1 -0
  28. package/build/heading/index.js +1 -0
  29. package/build/heading/index.js.map +1 -1
  30. package/build/image/edit.js +8 -4
  31. package/build/image/edit.js.map +1 -1
  32. package/build/image/image.js +33 -7
  33. package/build/image/image.js.map +1 -1
  34. package/build/image/index.js +6 -3
  35. package/build/image/index.js.map +1 -1
  36. package/build/more/index.js +4 -0
  37. package/build/more/index.js.map +1 -1
  38. package/build/navigation/edit/index.js +2 -2
  39. package/build/navigation/edit/index.js.map +1 -1
  40. package/build/navigation/index.js +0 -1
  41. package/build/navigation/index.js.map +1 -1
  42. package/build/paragraph/edit.js +2 -1
  43. package/build/paragraph/edit.js.map +1 -1
  44. package/build/paragraph/index.js +1 -1
  45. package/build/paragraph/transforms.js +1 -1
  46. package/build/post-content/edit.js +2 -2
  47. package/build/post-content/edit.js.map +1 -1
  48. package/build/post-date/edit.js +1 -1
  49. package/build/post-date/edit.js.map +1 -1
  50. package/build/post-navigation-link/edit.js +43 -2
  51. package/build/post-navigation-link/edit.js.map +1 -1
  52. package/build/post-navigation-link/index.js +8 -0
  53. package/build/post-navigation-link/index.js.map +1 -1
  54. package/build/pullquote/index.js +4 -0
  55. package/build/pullquote/index.js.map +1 -1
  56. package/build/query/edit/inspector-controls/index.js +3 -3
  57. package/build/query/edit/inspector-controls/index.js.map +1 -1
  58. package/build/query/edit/query-content.js +2 -2
  59. package/build/query/edit/query-content.js.map +1 -1
  60. package/build/query/edit/query-placeholder.js +6 -7
  61. package/build/query/edit/query-placeholder.js.map +1 -1
  62. package/build/query/index.js +1 -2
  63. package/build/query/index.js.map +1 -1
  64. package/build/query/variations.js +8 -1
  65. package/build/query/variations.js.map +1 -1
  66. package/build/query/view.js +31 -12
  67. package/build/query/view.js.map +1 -1
  68. package/build/search/index.js +0 -1
  69. package/build/search/index.js.map +1 -1
  70. package/build/table-of-contents/hooks.js +2 -2
  71. package/build/table-of-contents/hooks.js.map +1 -1
  72. package/build/template-part/edit/advanced-controls.js +1 -4
  73. package/build/template-part/edit/advanced-controls.js.map +1 -1
  74. package/build/template-part/edit/index.js +39 -17
  75. package/build/template-part/edit/index.js.map +1 -1
  76. package/build/video/edit.native.js +7 -2
  77. package/build/video/edit.native.js.map +1 -1
  78. package/build/video/transforms.js +17 -0
  79. package/build/video/transforms.js.map +1 -1
  80. package/build-module/avatar/edit.js +2 -2
  81. package/build-module/avatar/edit.js.map +1 -1
  82. package/build-module/block/edit.js +74 -11
  83. package/build-module/block/edit.js.map +1 -1
  84. package/build-module/block/{v1/edit.native.js → edit.native.js} +3 -3
  85. package/build-module/block/edit.native.js.map +1 -0
  86. package/build-module/block/index.js +5 -3
  87. package/build-module/block/index.js.map +1 -1
  88. package/build-module/button/edit.js +25 -7
  89. package/build-module/button/edit.js.map +1 -1
  90. package/build-module/button/index.js +1 -0
  91. package/build-module/button/index.js.map +1 -1
  92. package/build-module/button/save.js +4 -2
  93. package/build-module/button/save.js.map +1 -1
  94. package/build-module/embed/edit.js +3 -2
  95. package/build-module/embed/edit.js.map +1 -1
  96. package/build-module/file/index.js +0 -1
  97. package/build-module/file/index.js.map +1 -1
  98. package/build-module/footnotes/edit.js +2 -1
  99. package/build-module/footnotes/edit.js.map +1 -1
  100. package/build-module/footnotes/format.js +17 -19
  101. package/build-module/footnotes/format.js.map +1 -1
  102. package/build-module/heading/edit.js +3 -2
  103. package/build-module/heading/edit.js.map +1 -1
  104. package/build-module/heading/edit.native.js +132 -0
  105. package/build-module/heading/edit.native.js.map +1 -0
  106. package/build-module/heading/index.js +1 -0
  107. package/build-module/heading/index.js.map +1 -1
  108. package/build-module/image/edit.js +9 -5
  109. package/build-module/image/edit.js.map +1 -1
  110. package/build-module/image/image.js +33 -7
  111. package/build-module/image/image.js.map +1 -1
  112. package/build-module/image/index.js +6 -3
  113. package/build-module/image/index.js.map +1 -1
  114. package/build-module/more/index.js +4 -0
  115. package/build-module/more/index.js.map +1 -1
  116. package/build-module/navigation/edit/index.js +1 -1
  117. package/build-module/navigation/edit/index.js.map +1 -1
  118. package/build-module/navigation/index.js +0 -1
  119. package/build-module/navigation/index.js.map +1 -1
  120. package/build-module/paragraph/edit.js +3 -2
  121. package/build-module/paragraph/edit.js.map +1 -1
  122. package/build-module/paragraph/index.js +1 -1
  123. package/build-module/paragraph/transforms.js +1 -1
  124. package/build-module/post-content/edit.js +1 -1
  125. package/build-module/post-content/edit.js.map +1 -1
  126. package/build-module/post-date/edit.js +1 -1
  127. package/build-module/post-date/edit.js.map +1 -1
  128. package/build-module/post-navigation-link/edit.js +44 -3
  129. package/build-module/post-navigation-link/edit.js.map +1 -1
  130. package/build-module/post-navigation-link/index.js +8 -0
  131. package/build-module/post-navigation-link/index.js.map +1 -1
  132. package/build-module/pullquote/index.js +4 -0
  133. package/build-module/pullquote/index.js.map +1 -1
  134. package/build-module/query/edit/inspector-controls/index.js +4 -4
  135. package/build-module/query/edit/inspector-controls/index.js.map +1 -1
  136. package/build-module/query/edit/query-content.js +2 -2
  137. package/build-module/query/edit/query-content.js.map +1 -1
  138. package/build-module/query/edit/query-placeholder.js +7 -8
  139. package/build-module/query/edit/query-placeholder.js.map +1 -1
  140. package/build-module/query/index.js +1 -2
  141. package/build-module/query/index.js.map +1 -1
  142. package/build-module/query/variations.js +8 -1
  143. package/build-module/query/variations.js.map +1 -1
  144. package/build-module/query/view.js +30 -9
  145. package/build-module/query/view.js.map +1 -1
  146. package/build-module/search/index.js +0 -1
  147. package/build-module/search/index.js.map +1 -1
  148. package/build-module/table-of-contents/hooks.js +2 -2
  149. package/build-module/table-of-contents/hooks.js.map +1 -1
  150. package/build-module/template-part/edit/advanced-controls.js +1 -4
  151. package/build-module/template-part/edit/advanced-controls.js.map +1 -1
  152. package/build-module/template-part/edit/index.js +38 -16
  153. package/build-module/template-part/edit/index.js.map +1 -1
  154. package/build-module/video/edit.native.js +7 -2
  155. package/build-module/video/edit.native.js.map +1 -1
  156. package/build-module/video/transforms.js +17 -0
  157. package/build-module/video/transforms.js.map +1 -1
  158. package/build-style/common-rtl.css +4 -2
  159. package/build-style/common.css +4 -2
  160. package/build-style/cover/style-rtl.css +1 -2
  161. package/build-style/cover/style.css +1 -2
  162. package/build-style/editor-rtl.css +6 -4
  163. package/build-style/editor.css +6 -4
  164. package/build-style/gallery/style-rtl.css +2 -4
  165. package/build-style/gallery/style.css +2 -4
  166. package/build-style/image/editor-rtl.css +6 -0
  167. package/build-style/image/editor.css +6 -0
  168. package/build-style/page-list/editor-rtl.css +0 -4
  169. package/build-style/page-list/editor.css +0 -4
  170. package/build-style/pullquote/style-rtl.css +10 -1
  171. package/build-style/pullquote/style.css +10 -1
  172. package/build-style/search/style-rtl.css +2 -1
  173. package/build-style/search/style.css +2 -1
  174. package/build-style/style-rtl.css +19 -11
  175. package/build-style/style.css +19 -11
  176. package/build-style/video/style-rtl.css +1 -2
  177. package/build-style/video/style.css +1 -2
  178. package/package.json +34 -32
  179. package/src/avatar/edit.js +16 -18
  180. package/src/block/block.json +3 -0
  181. package/src/block/edit.js +96 -14
  182. package/src/block/{v1/edit.native.js → edit.native.js} +4 -4
  183. package/src/block/index.js +2 -3
  184. package/src/block/index.php +3 -31
  185. package/src/button/block.json +1 -0
  186. package/src/button/edit.js +76 -43
  187. package/src/button/save.js +3 -0
  188. package/src/embed/edit.js +3 -2
  189. package/src/file/block.json +0 -1
  190. package/src/file/index.php +11 -57
  191. package/src/footnotes/edit.js +2 -1
  192. package/src/footnotes/format.js +34 -31
  193. package/src/footnotes/index.php +20 -11
  194. package/src/heading/block.json +1 -0
  195. package/src/heading/edit.js +18 -14
  196. package/src/heading/edit.native.js +144 -0
  197. package/src/image/block.json +7 -3
  198. package/src/image/edit.js +19 -6
  199. package/src/image/editor.scss +6 -1
  200. package/src/image/image.js +101 -42
  201. package/src/image/index.js +6 -0
  202. package/src/image/index.php +14 -51
  203. package/src/more/index.js +6 -0
  204. package/src/navigation/block.json +0 -1
  205. package/src/navigation/edit/index.js +2 -2
  206. package/src/navigation/index.php +777 -28
  207. package/src/navigation-link/index.php +78 -16
  208. package/src/page-list/editor.scss +0 -4
  209. package/src/paragraph/block.json +1 -1
  210. package/src/paragraph/edit.js +23 -19
  211. package/src/post-content/edit.js +2 -2
  212. package/src/post-date/edit.js +38 -33
  213. package/src/post-navigation-link/block.json +8 -0
  214. package/src/post-navigation-link/edit.js +63 -1
  215. package/src/post-navigation-link/index.php +17 -3
  216. package/src/post-terms/index.php +13 -4
  217. package/src/pullquote/block.json +4 -0
  218. package/src/pullquote/style.scss +13 -1
  219. package/src/query/block.json +1 -2
  220. package/src/query/edit/inspector-controls/index.js +137 -146
  221. package/src/query/edit/query-content.js +9 -7
  222. package/src/query/edit/query-placeholder.js +11 -11
  223. package/src/query/index.php +33 -71
  224. package/src/query/variations.js +4 -0
  225. package/src/query/view.js +24 -19
  226. package/src/search/block.json +0 -1
  227. package/src/search/index.php +18 -36
  228. package/src/table-of-contents/hooks.js +2 -2
  229. package/src/template-part/edit/advanced-controls.js +2 -3
  230. package/src/template-part/edit/index.js +77 -50
  231. package/src/template-part/index.php +2 -2
  232. package/src/video/edit.native.js +5 -2
  233. package/src/video/test/edit.native.js +38 -0
  234. package/src/video/transforms.js +32 -0
  235. package/tsconfig.json +1 -0
  236. package/build/block/v1/edit.js +0 -116
  237. package/build/block/v1/edit.js.map +0 -1
  238. package/build/block/v1/edit.native.js.map +0 -1
  239. package/build-module/block/v1/edit.js +0 -108
  240. package/build-module/block/v1/edit.js.map +0 -1
  241. package/build-module/block/v1/edit.native.js.map +0 -1
  242. package/src/block/v1/edit.js +0 -163
@@ -95,8 +95,7 @@
95
95
  }
96
96
  @supports (position: sticky) {
97
97
  .wp-block-video [poster] {
98
- -o-object-fit: cover;
99
- object-fit: cover;
98
+ object-fit: cover;
100
99
  }
101
100
  }
102
101
  .wp-block-video.aligncenter {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wordpress/block-library",
3
- "version": "8.25.1-next.79a6196f.0",
3
+ "version": "8.27.0",
4
4
  "description": "Block library for the WordPress editor.",
5
5
  "author": "The WordPress Contributors",
6
6
  "license": "GPL-2.0-or-later",
@@ -31,36 +31,38 @@
31
31
  ],
32
32
  "dependencies": {
33
33
  "@babel/runtime": "^7.16.0",
34
- "@wordpress/a11y": "^3.48.1-next.79a6196f.0",
35
- "@wordpress/api-fetch": "^6.45.1-next.79a6196f.0",
36
- "@wordpress/autop": "^3.48.1-next.79a6196f.0",
37
- "@wordpress/blob": "^3.48.1-next.79a6196f.0",
38
- "@wordpress/block-editor": "^12.16.1-next.79a6196f.0",
39
- "@wordpress/blocks": "^12.25.1-next.79a6196f.0",
40
- "@wordpress/components": "^25.15.1-next.79a6196f.0",
41
- "@wordpress/compose": "^6.25.1-next.79a6196f.0",
42
- "@wordpress/core-data": "^6.25.1-next.79a6196f.0",
43
- "@wordpress/data": "^9.18.1-next.79a6196f.0",
44
- "@wordpress/date": "^4.48.1-next.79a6196f.0",
45
- "@wordpress/deprecated": "^3.48.1-next.79a6196f.0",
46
- "@wordpress/dom": "^3.48.1-next.79a6196f.0",
47
- "@wordpress/element": "^5.25.1-next.79a6196f.0",
48
- "@wordpress/escape-html": "^2.48.1-next.79a6196f.0",
49
- "@wordpress/hooks": "^3.48.1-next.79a6196f.0",
50
- "@wordpress/html-entities": "^3.48.1-next.79a6196f.0",
51
- "@wordpress/i18n": "^4.48.1-next.79a6196f.0",
52
- "@wordpress/icons": "^9.39.1-next.79a6196f.0",
53
- "@wordpress/interactivity": "^3.1.2-next.79a6196f.0",
54
- "@wordpress/keycodes": "^3.48.1-next.79a6196f.0",
55
- "@wordpress/notices": "^4.16.1-next.79a6196f.0",
56
- "@wordpress/primitives": "^3.46.1-next.79a6196f.0",
57
- "@wordpress/private-apis": "^0.30.1-next.79a6196f.0",
58
- "@wordpress/reusable-blocks": "^4.25.1-next.79a6196f.0",
59
- "@wordpress/rich-text": "^6.25.1-next.79a6196f.0",
60
- "@wordpress/server-side-render": "^4.25.1-next.79a6196f.0",
61
- "@wordpress/url": "^3.49.1-next.79a6196f.0",
62
- "@wordpress/viewport": "^5.25.1-next.79a6196f.0",
63
- "@wordpress/wordcount": "^3.48.1-next.79a6196f.0",
34
+ "@wordpress/a11y": "^3.50.0",
35
+ "@wordpress/api-fetch": "^6.47.0",
36
+ "@wordpress/autop": "^3.50.0",
37
+ "@wordpress/blob": "^3.50.0",
38
+ "@wordpress/block-editor": "^12.18.0",
39
+ "@wordpress/blocks": "^12.27.0",
40
+ "@wordpress/components": "^25.16.0",
41
+ "@wordpress/compose": "^6.27.0",
42
+ "@wordpress/core-data": "^6.27.0",
43
+ "@wordpress/data": "^9.20.0",
44
+ "@wordpress/date": "^4.50.0",
45
+ "@wordpress/deprecated": "^3.50.0",
46
+ "@wordpress/dom": "^3.50.0",
47
+ "@wordpress/element": "^5.27.0",
48
+ "@wordpress/escape-html": "^2.50.0",
49
+ "@wordpress/hooks": "^3.50.0",
50
+ "@wordpress/html-entities": "^3.50.0",
51
+ "@wordpress/i18n": "^4.50.0",
52
+ "@wordpress/icons": "^9.41.0",
53
+ "@wordpress/interactivity": "^4.0.0",
54
+ "@wordpress/interactivity-router": "^1.0.0",
55
+ "@wordpress/keycodes": "^3.50.0",
56
+ "@wordpress/notices": "^4.18.0",
57
+ "@wordpress/patterns": "^1.11.0",
58
+ "@wordpress/primitives": "^3.48.0",
59
+ "@wordpress/private-apis": "^0.32.0",
60
+ "@wordpress/reusable-blocks": "^4.27.0",
61
+ "@wordpress/rich-text": "^6.27.0",
62
+ "@wordpress/server-side-render": "^4.27.0",
63
+ "@wordpress/url": "^3.51.0",
64
+ "@wordpress/viewport": "^5.27.0",
65
+ "@wordpress/wordcount": "^3.50.0",
64
66
  "change-case": "^4.1.2",
65
67
  "classnames": "^2.3.1",
66
68
  "colord": "^2.7.0",
@@ -78,5 +80,5 @@
78
80
  "publishConfig": {
79
81
  "access": "public"
80
82
  },
81
- "gitHead": "1e74b942ac0119a22ceaaf5c9594263f3ec516ab"
83
+ "gitHead": "45de2cb4212fed7f2763e95f10300d1ff9d0ec08"
82
84
  }
@@ -192,22 +192,12 @@ const UserEdit = ( { attributes, context, setAttributes, isSelected } ) => {
192
192
  avatar={ avatar }
193
193
  setAttributes={ setAttributes }
194
194
  />
195
- <div>
196
- { attributes.isLink ? (
197
- <a
198
- href="#avatar-pseudo-link"
199
- className="wp-block-avatar__link"
200
- onClick={ ( event ) => event.preventDefault() }
201
- >
202
- <ResizableAvatar
203
- attributes={ attributes }
204
- avatar={ avatar }
205
- blockProps={ blockProps }
206
- isSelected={ isSelected }
207
- setAttributes={ setAttributes }
208
- />
209
- </a>
210
- ) : (
195
+ { attributes.isLink ? (
196
+ <a
197
+ href="#avatar-pseudo-link"
198
+ className="wp-block-avatar__link"
199
+ onClick={ ( event ) => event.preventDefault() }
200
+ >
211
201
  <ResizableAvatar
212
202
  attributes={ attributes }
213
203
  avatar={ avatar }
@@ -215,8 +205,16 @@ const UserEdit = ( { attributes, context, setAttributes, isSelected } ) => {
215
205
  isSelected={ isSelected }
216
206
  setAttributes={ setAttributes }
217
207
  />
218
- ) }
219
- </div>
208
+ </a>
209
+ ) : (
210
+ <ResizableAvatar
211
+ attributes={ attributes }
212
+ avatar={ avatar }
213
+ blockProps={ blockProps }
214
+ isSelected={ isSelected }
215
+ setAttributes={ setAttributes }
216
+ />
217
+ ) }
220
218
  </>
221
219
  );
222
220
  };
@@ -10,6 +10,9 @@
10
10
  "attributes": {
11
11
  "ref": {
12
12
  "type": "number"
13
+ },
14
+ "overrides": {
15
+ "type": "object"
13
16
  }
14
17
  },
15
18
  "supports": {
package/src/block/edit.js CHANGED
@@ -18,8 +18,8 @@ import {
18
18
  import { __ } from '@wordpress/i18n';
19
19
  import {
20
20
  useInnerBlocksProps,
21
- __experimentalRecursionProvider as RecursionProvider,
22
- __experimentalUseHasRecursion as useHasRecursion,
21
+ RecursionProvider,
22
+ useHasRecursion,
23
23
  InnerBlocks,
24
24
  useBlockProps,
25
25
  Warning,
@@ -27,6 +27,7 @@ import {
27
27
  store as blockEditorStore,
28
28
  BlockControls,
29
29
  } from '@wordpress/block-editor';
30
+ import { privateApis as patternsPrivateApis } from '@wordpress/patterns';
30
31
  import { parse, cloneBlock } from '@wordpress/blocks';
31
32
 
32
33
  /**
@@ -35,10 +36,13 @@ import { parse, cloneBlock } from '@wordpress/blocks';
35
36
  import { unlock } from '../lock-unlock';
36
37
 
37
38
  const { useLayoutClasses } = unlock( blockEditorPrivateApis );
39
+ const { PARTIAL_SYNCING_SUPPORTED_BLOCKS } = unlock( patternsPrivateApis );
38
40
 
39
41
  function isPartiallySynced( block ) {
40
42
  return (
41
- 'core/paragraph' === block.name &&
43
+ Object.keys( PARTIAL_SYNCING_SUPPORTED_BLOCKS ).includes(
44
+ block.name
45
+ ) &&
42
46
  !! block.attributes.metadata?.bindings &&
43
47
  Object.values( block.attributes.metadata.bindings ).some(
44
48
  ( binding ) => binding.source.name === 'pattern_attributes'
@@ -84,6 +88,26 @@ const useInferredLayout = ( blocks, parentLayout ) => {
84
88
  }, [ blocks, parentLayout ] );
85
89
  };
86
90
 
91
+ /**
92
+ * Enum for patch operations.
93
+ * We use integers here to minimize the size of the serialized data.
94
+ * This has to be deserialized accordingly on the server side.
95
+ * See block-bindings/sources/pattern.php
96
+ */
97
+ const PATCH_OPERATIONS = {
98
+ /** @type {0} */
99
+ Remove: 0,
100
+ /** @type {1} */
101
+ Replace: 1,
102
+ // Other operations are reserved for future use. (e.g. Add)
103
+ };
104
+
105
+ /**
106
+ * @typedef {[typeof PATCH_OPERATIONS.Remove]} RemovePatch
107
+ * @typedef {[typeof PATCH_OPERATIONS.Replace, unknown]} ReplacePatch
108
+ * @typedef {RemovePatch | ReplacePatch} OverridePatch
109
+ */
110
+
87
111
  function applyInitialOverrides( blocks, overrides = {}, defaultValues ) {
88
112
  return blocks.map( ( block ) => {
89
113
  const innerBlocks = applyInitialOverrides(
@@ -100,9 +124,15 @@ function applyInitialOverrides( blocks, overrides = {}, defaultValues ) {
100
124
  defaultValues[ blockId ] ??= {};
101
125
  defaultValues[ blockId ][ attributeKey ] =
102
126
  block.attributes[ attributeKey ];
103
- if ( overrides[ blockId ] ) {
104
- newAttributes[ attributeKey ] =
105
- overrides[ blockId ][ attributeKey ];
127
+ /** @type {OverridePatch} */
128
+ const overrideAttribute = overrides[ blockId ]?.[ attributeKey ];
129
+ if ( ! overrideAttribute ) {
130
+ continue;
131
+ }
132
+ if ( overrideAttribute[ 0 ] === PATCH_OPERATIONS.Remove ) {
133
+ delete newAttributes[ attributeKey ];
134
+ } else if ( overrideAttribute[ 0 ] === PATCH_OPERATIONS.Replace ) {
135
+ newAttributes[ attributeKey ] = overrideAttribute[ 1 ];
106
136
  }
107
137
  }
108
138
  return {
@@ -114,13 +144,14 @@ function applyInitialOverrides( blocks, overrides = {}, defaultValues ) {
114
144
  }
115
145
 
116
146
  function getOverridesFromBlocks( blocks, defaultValues ) {
117
- /** @type {Record<string, Record<string, unknown>>} */
147
+ /** @type {Record<string, Record<string, OverridePatch>>} */
118
148
  const overrides = {};
119
149
  for ( const block of blocks ) {
120
150
  Object.assign(
121
151
  overrides,
122
152
  getOverridesFromBlocks( block.innerBlocks, defaultValues )
123
153
  );
154
+ /** @type {string} */
124
155
  const blockId = block.attributes.metadata?.id;
125
156
  if ( ! isPartiallySynced( block ) || ! blockId ) continue;
126
157
  const attributes = getPartiallySyncedAttributes( block );
@@ -130,8 +161,23 @@ function getOverridesFromBlocks( blocks, defaultValues ) {
130
161
  defaultValues[ blockId ][ attributeKey ]
131
162
  ) {
132
163
  overrides[ blockId ] ??= {};
133
- overrides[ blockId ][ attributeKey ] =
134
- block.attributes[ attributeKey ];
164
+ /**
165
+ * Create a patch operation for the binding attribute.
166
+ * We use a tuple here to minimize the size of the serialized data.
167
+ * The first item is the operation type, the second item is the value if any.
168
+ */
169
+ if ( block.attributes[ attributeKey ] === undefined ) {
170
+ /** @type {RemovePatch} */
171
+ overrides[ blockId ][ attributeKey ] = [
172
+ PATCH_OPERATIONS.Remove,
173
+ ];
174
+ } else {
175
+ /** @type {ReplacePatch} */
176
+ overrides[ blockId ][ attributeKey ] = [
177
+ PATCH_OPERATIONS.Replace,
178
+ block.attributes[ attributeKey ],
179
+ ];
180
+ }
135
181
  }
136
182
  }
137
183
  }
@@ -147,6 +193,13 @@ function setBlockEditMode( setEditMode, blocks, mode ) {
147
193
  } );
148
194
  }
149
195
 
196
+ function getHasOverridableBlocks( blocks ) {
197
+ return blocks.some( ( block ) => {
198
+ if ( isPartiallySynced( block ) ) return true;
199
+ return getHasOverridableBlocks( block.innerBlocks );
200
+ } );
201
+ }
202
+
150
203
  export default function ReusableBlockEdit( {
151
204
  name,
152
205
  attributes: { ref, overrides },
@@ -208,15 +261,23 @@ export default function ReusableBlockEdit( {
208
261
  [ innerBlocks, setBlockEditingMode ]
209
262
  );
210
263
 
211
- // Apply the initial overrides from the pattern block to the inner blocks.
212
- useEffect( () => {
213
- const initialBlocks =
264
+ const hasOverridableBlocks = useMemo(
265
+ () => getHasOverridableBlocks( innerBlocks ),
266
+ [ innerBlocks ]
267
+ );
268
+
269
+ const initialBlocks = useMemo(
270
+ () =>
214
271
  // Clone the blocks to generate new client IDs.
215
272
  editedRecord.blocks?.map( ( block ) => cloneBlock( block ) ) ??
216
273
  ( editedRecord.content && typeof editedRecord.content !== 'function'
217
274
  ? parse( editedRecord.content )
218
- : [] );
275
+ : [] ),
276
+ [ editedRecord.blocks, editedRecord.content ]
277
+ );
219
278
 
279
+ // Apply the initial overrides from the pattern block to the inner blocks.
280
+ useEffect( () => {
220
281
  defaultValuesRef.current = {};
221
282
  const editingMode = getBlockEditingMode( patternClientId );
222
283
  // Replace the contents of the blocks with the overrides.
@@ -237,7 +298,7 @@ export default function ReusableBlockEdit( {
237
298
  }, [
238
299
  __unstableMarkNextChangeAsNotPersistent,
239
300
  patternClientId,
240
- editedRecord,
301
+ initialBlocks,
241
302
  replaceInnerBlocks,
242
303
  registry,
243
304
  getBlockEditingMode,
@@ -293,6 +354,12 @@ export default function ReusableBlockEdit( {
293
354
  editOriginalProps.onClick( event );
294
355
  };
295
356
 
357
+ const resetOverrides = () => {
358
+ if ( overrides ) {
359
+ replaceInnerBlocks( patternClientId, initialBlocks );
360
+ }
361
+ };
362
+
296
363
  let children = null;
297
364
 
298
365
  if ( hasAlreadyRendered ) {
@@ -333,6 +400,21 @@ export default function ReusableBlockEdit( {
333
400
  </ToolbarGroup>
334
401
  </BlockControls>
335
402
  ) }
403
+
404
+ { hasOverridableBlocks && (
405
+ <BlockControls>
406
+ <ToolbarGroup>
407
+ <ToolbarButton
408
+ onClick={ resetOverrides }
409
+ disabled={ ! overrides }
410
+ __experimentalIsFocusable
411
+ >
412
+ { __( 'Reset to original' ) }
413
+ </ToolbarButton>
414
+ </ToolbarGroup>
415
+ </BlockControls>
416
+ ) }
417
+
336
418
  { children === null ? (
337
419
  <div { ...innerBlocksProps } />
338
420
  ) : (
@@ -27,8 +27,8 @@ import {
27
27
  import { useSelect, useDispatch } from '@wordpress/data';
28
28
  import { __, sprintf } from '@wordpress/i18n';
29
29
  import {
30
- __experimentalRecursionProvider as RecursionProvider,
31
- __experimentalUseHasRecursion as useHasRecursion,
30
+ RecursionProvider,
31
+ useHasRecursion,
32
32
  InnerBlocks,
33
33
  Warning,
34
34
  store as blockEditorStore,
@@ -42,8 +42,8 @@ import { store as noticesStore } from '@wordpress/notices';
42
42
  /**
43
43
  * Internal dependencies
44
44
  */
45
- import styles from '../editor.scss';
46
- import EditTitle from '../edit-title';
45
+ import styles from './editor.scss';
46
+ import EditTitle from './edit-title';
47
47
 
48
48
  export default function ReusableBlockEdit( {
49
49
  attributes: { ref },
@@ -8,15 +8,14 @@ import { symbol as icon } from '@wordpress/icons';
8
8
  */
9
9
  import initBlock from '../utils/init-block';
10
10
  import metadata from './block.json';
11
- import editV1 from './v1/edit';
12
- import editV2 from './edit';
11
+ import edit from './edit';
13
12
 
14
13
  const { name } = metadata;
15
14
 
16
15
  export { metadata, name };
17
16
 
18
17
  export const settings = {
19
- edit: window.__experimentalPatternPartialSyncing ? editV2 : editV1,
18
+ edit,
20
19
  icon,
21
20
  };
22
21
 
@@ -46,17 +46,14 @@ function render_block_core_block( $attributes ) {
46
46
  $content = $wp_embed->run_shortcode( $reusable_block->post_content );
47
47
  $content = $wp_embed->autoembed( $content );
48
48
 
49
- $gutenberg_experiments = get_option( 'gutenberg-experiments' );
50
- $has_partial_synced_overrides = $gutenberg_experiments
51
- && array_key_exists( 'gutenberg-pattern-partial-syncing', $gutenberg_experiments )
52
- && isset( $attributes['overrides'] );
49
+ $has_pattern_overrides = isset( $attributes['overrides'] );
53
50
 
54
51
  /**
55
52
  * We set the `pattern/overrides` context through the `render_block_context`
56
53
  * filter so that it is available when a pattern's inner blocks are
57
54
  * rendering via do_blocks given it only receives the inner content.
58
55
  */
59
- if ( $has_partial_synced_overrides ) {
56
+ if ( $has_pattern_overrides ) {
60
57
  $filter_block_context = static function ( $context ) use ( $attributes ) {
61
58
  $context['pattern/overrides'] = $attributes['overrides'];
62
59
  return $context;
@@ -67,7 +64,7 @@ function render_block_core_block( $attributes ) {
67
64
  $content = do_blocks( $content );
68
65
  unset( $seen_refs[ $attributes['ref'] ] );
69
66
 
70
- if ( $has_partial_synced_overrides ) {
67
+ if ( $has_pattern_overrides ) {
71
68
  remove_filter( 'render_block_context', $filter_block_context, 1 );
72
69
  }
73
70
 
@@ -86,28 +83,3 @@ function register_block_core_block() {
86
83
  );
87
84
  }
88
85
  add_action( 'init', 'register_block_core_block' );
89
-
90
- $gutenberg_experiments = get_option( 'gutenberg-experiments' );
91
- if ( $gutenberg_experiments && array_key_exists( 'gutenberg-pattern-partial-syncing', $gutenberg_experiments ) ) {
92
- /**
93
- * Registers the overrides attribute for core/block.
94
- *
95
- * @param array $args Array of arguments for registering a block type.
96
- * @param string $block_name Block name including namespace.
97
- * @return array $args
98
- */
99
- function register_block_core_block_args( $args, $block_name ) {
100
- if ( 'core/block' === $block_name ) {
101
- $args['attributes'] = array_merge(
102
- $args['attributes'],
103
- array(
104
- 'overrides' => array(
105
- 'type' => 'object',
106
- ),
107
- )
108
- );
109
- }
110
- return $args;
111
- }
112
- add_filter( 'register_block_type_args', 'register_block_core_block_args', 10, 2 );
113
- }
@@ -8,6 +8,7 @@
8
8
  "description": "Prompt visitors to take action with a button-style link.",
9
9
  "keywords": [ "link" ],
10
10
  "textdomain": "default",
11
+ "usesContext": [ "pattern/overrides" ],
11
12
  "attributes": {
12
13
  "tagName": {
13
14
  "type": "string",
@@ -9,6 +9,7 @@ import classnames from 'classnames';
9
9
  import { NEW_TAB_TARGET, NOFOLLOW_REL } from './constants';
10
10
  import { getUpdatedLinkAttributes } from './get-updated-link-attributes';
11
11
  import removeAnchorTag from '../utils/remove-anchor-tag';
12
+ import { unlock } from '../lock-unlock';
12
13
 
13
14
  /**
14
15
  * WordPress dependencies
@@ -32,9 +33,11 @@ import {
32
33
  __experimentalUseBorderProps as useBorderProps,
33
34
  __experimentalUseColorProps as useColorProps,
34
35
  __experimentalGetSpacingClassesAndStyles as useSpacingProps,
36
+ __experimentalUseShadowProps as useShadowProps,
35
37
  __experimentalLinkControl as LinkControl,
36
38
  __experimentalGetElementClassName,
37
39
  store as blockEditorStore,
40
+ useBlockEditingMode,
38
41
  } from '@wordpress/block-editor';
39
42
  import { displayShortcut, isKeyboardEvent, ENTER } from '@wordpress/keycodes';
40
43
  import { link, linkOff } from '@wordpress/icons';
@@ -163,6 +166,7 @@ function ButtonEdit( props ) {
163
166
  text,
164
167
  url,
165
168
  width,
169
+ metadata,
166
170
  } = attributes;
167
171
 
168
172
  const TagName = tagName || 'a';
@@ -183,12 +187,14 @@ function ButtonEdit( props ) {
183
187
  const borderProps = useBorderProps( attributes );
184
188
  const colorProps = useColorProps( attributes );
185
189
  const spacingProps = useSpacingProps( attributes );
190
+ const shadowProps = useShadowProps( attributes );
186
191
  const ref = useRef();
187
192
  const richTextRef = useRef();
188
193
  const blockProps = useBlockProps( {
189
194
  ref: useMergeRefs( [ setPopoverAnchor, ref ] ),
190
195
  onKeyDown,
191
196
  } );
197
+ const blockEditingMode = useBlockEditingMode();
192
198
 
193
199
  const [ isEditingURL, setIsEditingURL ] = useState( false );
194
200
  const isURLSet = !! url;
@@ -226,6 +232,27 @@ function ButtonEdit( props ) {
226
232
  const useEnterRef = useEnter( { content: text, clientId } );
227
233
  const mergedRef = useMergeRefs( [ useEnterRef, richTextRef ] );
228
234
 
235
+ const { lockUrlControls = false } = useSelect(
236
+ ( select ) => {
237
+ if ( ! isSelected ) {
238
+ return {};
239
+ }
240
+
241
+ const { getBlockBindingsSource } = unlock(
242
+ select( blockEditorStore )
243
+ );
244
+
245
+ return {
246
+ lockUrlControls:
247
+ !! metadata?.bindings?.url &&
248
+ getBlockBindingsSource(
249
+ metadata?.bindings?.url?.source?.name
250
+ )?.lockAttributesEditing === true,
251
+ };
252
+ },
253
+ [ isSelected ]
254
+ );
255
+
229
256
  return (
230
257
  <>
231
258
  <div
@@ -264,6 +291,7 @@ function ButtonEdit( props ) {
264
291
  ...borderProps.style,
265
292
  ...colorProps.style,
266
293
  ...spacingProps.style,
294
+ ...shadowProps.style,
267
295
  } }
268
296
  onSplit={ ( value ) =>
269
297
  createBlock( 'core/button', {
@@ -277,13 +305,15 @@ function ButtonEdit( props ) {
277
305
  />
278
306
  </div>
279
307
  <BlockControls group="block">
280
- <AlignmentControl
281
- value={ textAlign }
282
- onChange={ ( nextAlign ) => {
283
- setAttributes( { textAlign: nextAlign } );
284
- } }
285
- />
286
- { ! isURLSet && isLinkTag && (
308
+ { blockEditingMode === 'default' && (
309
+ <AlignmentControl
310
+ value={ textAlign }
311
+ onChange={ ( nextAlign ) => {
312
+ setAttributes( { textAlign: nextAlign } );
313
+ } }
314
+ />
315
+ ) }
316
+ { ! isURLSet && isLinkTag && ! lockUrlControls && (
287
317
  <ToolbarButton
288
318
  name="link"
289
319
  icon={ link }
@@ -292,7 +322,7 @@ function ButtonEdit( props ) {
292
322
  onClick={ startEditing }
293
323
  />
294
324
  ) }
295
- { isURLSet && isLinkTag && (
325
+ { isURLSet && isLinkTag && ! lockUrlControls && (
296
326
  <ToolbarButton
297
327
  name="link"
298
328
  icon={ linkOff }
@@ -303,43 +333,46 @@ function ButtonEdit( props ) {
303
333
  />
304
334
  ) }
305
335
  </BlockControls>
306
- { isLinkTag && isSelected && ( isEditingURL || isURLSet ) && (
307
- <Popover
308
- placement="bottom"
309
- onClose={ () => {
310
- setIsEditingURL( false );
311
- richTextRef.current?.focus();
312
- } }
313
- anchor={ popoverAnchor }
314
- focusOnMount={ isEditingURL ? 'firstElement' : false }
315
- __unstableSlotName={ '__unstable-block-tools-after' }
316
- shift
317
- >
318
- <LinkControl
319
- value={ linkValue }
320
- onChange={ ( {
321
- url: newURL,
322
- opensInNewTab: newOpensInNewTab,
323
- nofollow: newNofollow,
324
- } ) =>
325
- setAttributes(
326
- getUpdatedLinkAttributes( {
327
- rel,
328
- url: newURL,
329
- opensInNewTab: newOpensInNewTab,
330
- nofollow: newNofollow,
331
- } )
332
- )
333
- }
334
- onRemove={ () => {
335
- unlink();
336
+ { isLinkTag &&
337
+ isSelected &&
338
+ ( isEditingURL || isURLSet ) &&
339
+ ! lockUrlControls && (
340
+ <Popover
341
+ placement="bottom"
342
+ onClose={ () => {
343
+ setIsEditingURL( false );
336
344
  richTextRef.current?.focus();
337
345
  } }
338
- forceIsEditingLink={ isEditingURL }
339
- settings={ LINK_SETTINGS }
340
- />
341
- </Popover>
342
- ) }
346
+ anchor={ popoverAnchor }
347
+ focusOnMount={ isEditingURL ? 'firstElement' : false }
348
+ __unstableSlotName={ '__unstable-block-tools-after' }
349
+ shift
350
+ >
351
+ <LinkControl
352
+ value={ linkValue }
353
+ onChange={ ( {
354
+ url: newURL,
355
+ opensInNewTab: newOpensInNewTab,
356
+ nofollow: newNofollow,
357
+ } ) =>
358
+ setAttributes(
359
+ getUpdatedLinkAttributes( {
360
+ rel,
361
+ url: newURL,
362
+ opensInNewTab: newOpensInNewTab,
363
+ nofollow: newNofollow,
364
+ } )
365
+ )
366
+ }
367
+ onRemove={ () => {
368
+ unlink();
369
+ richTextRef.current?.focus();
370
+ } }
371
+ forceIsEditingLink={ isEditingURL }
372
+ settings={ LINK_SETTINGS }
373
+ />
374
+ </Popover>
375
+ ) }
343
376
  <InspectorControls>
344
377
  <WidthPanel
345
378
  selectedWidth={ width }
@@ -12,6 +12,7 @@ import {
12
12
  __experimentalGetBorderClassesAndStyles as getBorderClassesAndStyles,
13
13
  __experimentalGetColorClassesAndStyles as getColorClassesAndStyles,
14
14
  __experimentalGetSpacingClassesAndStyles as getSpacingClassesAndStyles,
15
+ __experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles,
15
16
  __experimentalGetElementClassName,
16
17
  } from '@wordpress/block-editor';
17
18
 
@@ -40,6 +41,7 @@ export default function save( { attributes, className } ) {
40
41
  const borderProps = getBorderClassesAndStyles( attributes );
41
42
  const colorProps = getColorClassesAndStyles( attributes );
42
43
  const spacingProps = getSpacingClassesAndStyles( attributes );
44
+ const shadowProps = getShadowClassesAndStyles( attributes );
43
45
  const buttonClasses = classnames(
44
46
  'wp-block-button__link',
45
47
  colorProps.className,
@@ -56,6 +58,7 @@ export default function save( { attributes, className } ) {
56
58
  ...borderProps.style,
57
59
  ...colorProps.style,
58
60
  ...spacingProps.style,
61
+ ...shadowProps.style,
59
62
  };
60
63
 
61
64
  // The use of a `title` attribute here is soft-deprecated, but still applied