@wordpress/block-editor 12.4.0 → 12.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +5 -0
  3. package/build/components/block-heading-level-dropdown/heading-level-icon.js +10 -2
  4. package/build/components/block-heading-level-dropdown/heading-level-icon.js.map +1 -1
  5. package/build/components/block-heading-level-dropdown/index.native.js +4 -3
  6. package/build/components/block-heading-level-dropdown/index.native.js.map +1 -1
  7. package/build/components/block-lock/toolbar.js +25 -6
  8. package/build/components/block-lock/toolbar.js.map +1 -1
  9. package/build/components/block-mobile-toolbar/block-actions-menu.native.js +3 -6
  10. package/build/components/block-mobile-toolbar/block-actions-menu.native.js.map +1 -1
  11. package/build/components/block-parent-selector/index.js +8 -5
  12. package/build/components/block-parent-selector/index.js.map +1 -1
  13. package/build/components/block-removal-warning-modal/index.js +18 -25
  14. package/build/components/block-removal-warning-modal/index.js.map +1 -1
  15. package/build/components/block-toolbar/index.js +8 -5
  16. package/build/components/block-toolbar/index.js.map +1 -1
  17. package/build/components/block-tools/block-contextual-toolbar.js +7 -11
  18. package/build/components/block-tools/block-contextual-toolbar.js.map +1 -1
  19. package/build/components/dimensions-tool/aspect-ratio-tool.js +99 -0
  20. package/build/components/dimensions-tool/aspect-ratio-tool.js.map +1 -0
  21. package/build/components/dimensions-tool/index.js +207 -0
  22. package/build/components/dimensions-tool/index.js.map +1 -0
  23. package/build/components/dimensions-tool/scale-tool.js +111 -0
  24. package/build/components/dimensions-tool/scale-tool.js.map +1 -0
  25. package/build/components/dimensions-tool/width-height-tool.js +125 -0
  26. package/build/components/dimensions-tool/width-height-tool.js.map +1 -0
  27. package/build/components/global-styles/color-panel.js +1 -1
  28. package/build/components/global-styles/color-panel.js.map +1 -1
  29. package/build/components/global-styles/filters-panel.js +1 -1
  30. package/build/components/global-styles/filters-panel.js.map +1 -1
  31. package/build/components/global-styles/hooks.js +2 -2
  32. package/build/components/global-styles/hooks.js.map +1 -1
  33. package/build/components/global-styles/typography-panel.js +34 -2
  34. package/build/components/global-styles/typography-panel.js.map +1 -1
  35. package/build/components/image-editor/aspect-ratio-dropdown.js +1 -1
  36. package/build/components/image-editor/aspect-ratio-dropdown.js.map +1 -1
  37. package/build/components/image-editor/use-save-image.js +1 -2
  38. package/build/components/image-editor/use-save-image.js.map +1 -1
  39. package/build/components/image-size-control/index.js +6 -0
  40. package/build/components/image-size-control/index.js.map +1 -1
  41. package/build/components/index.js +19 -1
  42. package/build/components/index.js.map +1 -1
  43. package/build/components/inserter/block-patterns-explorer/patterns-list.js +2 -2
  44. package/build/components/inserter/block-patterns-explorer/patterns-list.js.map +1 -1
  45. package/build/components/inserter/block-patterns-tab.js +7 -35
  46. package/build/components/inserter/block-patterns-tab.js.map +1 -1
  47. package/build/components/inserter/hooks/use-block-types-state.js +3 -4
  48. package/build/components/inserter/hooks/use-block-types-state.js.map +1 -1
  49. package/build/components/inserter/hooks/use-patterns-state.js +9 -3
  50. package/build/components/inserter/hooks/use-patterns-state.js.map +1 -1
  51. package/build/components/inserter/media-tab/hooks.js +2 -21
  52. package/build/components/inserter/media-tab/hooks.js.map +1 -1
  53. package/build/components/inserter/reusable-block-rename-hint.js +62 -0
  54. package/build/components/inserter/reusable-block-rename-hint.js.map +1 -0
  55. package/build/components/inserter/reusable-blocks-tab.js +6 -2
  56. package/build/components/inserter/reusable-blocks-tab.js.map +1 -1
  57. package/build/components/inserter/reusable-blocks-tab.native.js +2 -2
  58. package/build/components/inserter/reusable-blocks-tab.native.js.map +1 -1
  59. package/build/components/inserter/tabs.native.js +1 -1
  60. package/build/components/inserter/tabs.native.js.map +1 -1
  61. package/build/components/inserter-draggable-blocks/index.js +9 -1
  62. package/build/components/inserter-draggable-blocks/index.js.map +1 -1
  63. package/build/components/link-control/constants.js +1 -1
  64. package/build/components/link-control/constants.js.map +1 -1
  65. package/build/components/link-control/index.js +17 -15
  66. package/build/components/link-control/index.js.map +1 -1
  67. package/build/components/link-control/search-create-button.js +5 -21
  68. package/build/components/link-control/search-create-button.js.map +1 -1
  69. package/build/components/link-control/search-input.js +4 -4
  70. package/build/components/link-control/search-input.js.map +1 -1
  71. package/build/components/link-control/search-item.js +13 -30
  72. package/build/components/link-control/search-item.js.map +1 -1
  73. package/build/components/link-control/search-results.js +2 -2
  74. package/build/components/link-control/search-results.js.map +1 -1
  75. package/build/components/link-control/settings-drawer.js +2 -3
  76. package/build/components/link-control/settings-drawer.js.map +1 -1
  77. package/build/components/list-view/appender.js +2 -6
  78. package/build/components/list-view/appender.js.map +1 -1
  79. package/build/components/provider/index.js +5 -2
  80. package/build/components/provider/index.js.map +1 -1
  81. package/build/components/provider/use-block-sync.js +21 -0
  82. package/build/components/provider/use-block-sync.js.map +1 -1
  83. package/build/components/resolution-tool/index.js +55 -0
  84. package/build/components/resolution-tool/index.js.map +1 -0
  85. package/build/components/url-input/index.js +4 -2
  86. package/build/components/url-input/index.js.map +1 -1
  87. package/build/components/writing-flow/use-tab-nav.js +10 -27
  88. package/build/components/writing-flow/use-tab-nav.js.map +1 -1
  89. package/build/components/writing-mode-control/index.js +70 -0
  90. package/build/components/writing-mode-control/index.js.map +1 -0
  91. package/build/hooks/behaviors.js +25 -20
  92. package/build/hooks/behaviors.js.map +1 -1
  93. package/build/hooks/supports.js +7 -1
  94. package/build/hooks/supports.js.map +1 -1
  95. package/build/hooks/typography.js +2 -1
  96. package/build/hooks/typography.js.map +1 -1
  97. package/build/hooks/utils.js +4 -2
  98. package/build/hooks/utils.js.map +1 -1
  99. package/build/private-apis.js +10 -1
  100. package/build/private-apis.js.map +1 -1
  101. package/build/private-apis.native.js +3 -0
  102. package/build/private-apis.native.js.map +1 -1
  103. package/build/store/actions.js +195 -1
  104. package/build/store/actions.js.map +1 -1
  105. package/build/store/defaults.js +1 -0
  106. package/build/store/defaults.js.map +1 -1
  107. package/build/store/index.js +10 -1
  108. package/build/store/index.js.map +1 -1
  109. package/build/store/private-actions.js +46 -40
  110. package/build/store/private-actions.js.map +1 -1
  111. package/build/store/private-selectors.js +3 -3
  112. package/build/store/private-selectors.js.map +1 -1
  113. package/build/store/reducer.js +22 -8
  114. package/build/store/reducer.js.map +1 -1
  115. package/build/store/selectors.js +33 -15
  116. package/build/store/selectors.js.map +1 -1
  117. package/build-module/components/block-heading-level-dropdown/heading-level-icon.js +9 -2
  118. package/build-module/components/block-heading-level-dropdown/heading-level-icon.js.map +1 -1
  119. package/build-module/components/block-heading-level-dropdown/index.native.js +4 -3
  120. package/build-module/components/block-heading-level-dropdown/index.native.js.map +1 -1
  121. package/build-module/components/block-lock/toolbar.js +25 -7
  122. package/build-module/components/block-lock/toolbar.js.map +1 -1
  123. package/build-module/components/block-mobile-toolbar/block-actions-menu.native.js +4 -6
  124. package/build-module/components/block-mobile-toolbar/block-actions-menu.native.js.map +1 -1
  125. package/build-module/components/block-parent-selector/index.js +7 -5
  126. package/build-module/components/block-parent-selector/index.js.map +1 -1
  127. package/build-module/components/block-removal-warning-modal/index.js +20 -24
  128. package/build-module/components/block-removal-warning-modal/index.js.map +1 -1
  129. package/build-module/components/block-toolbar/index.js +8 -5
  130. package/build-module/components/block-toolbar/index.js.map +1 -1
  131. package/build-module/components/block-tools/block-contextual-toolbar.js +8 -11
  132. package/build-module/components/block-tools/block-contextual-toolbar.js.map +1 -1
  133. package/build-module/components/dimensions-tool/aspect-ratio-tool.js +87 -0
  134. package/build-module/components/dimensions-tool/aspect-ratio-tool.js.map +1 -0
  135. package/build-module/components/dimensions-tool/index.js +195 -0
  136. package/build-module/components/dimensions-tool/index.js.map +1 -0
  137. package/build-module/components/dimensions-tool/scale-tool.js +103 -0
  138. package/build-module/components/dimensions-tool/scale-tool.js.map +1 -0
  139. package/build-module/components/dimensions-tool/width-height-tool.js +122 -0
  140. package/build-module/components/dimensions-tool/width-height-tool.js.map +1 -0
  141. package/build-module/components/global-styles/color-panel.js +1 -1
  142. package/build-module/components/global-styles/color-panel.js.map +1 -1
  143. package/build-module/components/global-styles/filters-panel.js +2 -2
  144. package/build-module/components/global-styles/filters-panel.js.map +1 -1
  145. package/build-module/components/global-styles/hooks.js +2 -2
  146. package/build-module/components/global-styles/hooks.js.map +1 -1
  147. package/build-module/components/global-styles/typography-panel.js +33 -2
  148. package/build-module/components/global-styles/typography-panel.js.map +1 -1
  149. package/build-module/components/image-editor/aspect-ratio-dropdown.js +1 -1
  150. package/build-module/components/image-editor/aspect-ratio-dropdown.js.map +1 -1
  151. package/build-module/components/image-editor/use-save-image.js +1 -2
  152. package/build-module/components/image-editor/use-save-image.js.map +1 -1
  153. package/build-module/components/image-size-control/index.js +5 -0
  154. package/build-module/components/image-size-control/index.js.map +1 -1
  155. package/build-module/components/index.js +6 -0
  156. package/build-module/components/index.js.map +1 -1
  157. package/build-module/components/inserter/block-patterns-explorer/patterns-list.js +2 -2
  158. package/build-module/components/inserter/block-patterns-explorer/patterns-list.js.map +1 -1
  159. package/build-module/components/inserter/block-patterns-tab.js +7 -33
  160. package/build-module/components/inserter/block-patterns-tab.js.map +1 -1
  161. package/build-module/components/inserter/hooks/use-block-types-state.js +3 -4
  162. package/build-module/components/inserter/hooks/use-block-types-state.js.map +1 -1
  163. package/build-module/components/inserter/hooks/use-patterns-state.js +9 -3
  164. package/build-module/components/inserter/hooks/use-patterns-state.js.map +1 -1
  165. package/build-module/components/inserter/media-tab/hooks.js +2 -21
  166. package/build-module/components/inserter/media-tab/hooks.js.map +1 -1
  167. package/build-module/components/inserter/reusable-block-rename-hint.js +48 -0
  168. package/build-module/components/inserter/reusable-block-rename-hint.js.map +1 -0
  169. package/build-module/components/inserter/reusable-blocks-tab.js +5 -2
  170. package/build-module/components/inserter/reusable-blocks-tab.js.map +1 -1
  171. package/build-module/components/inserter/reusable-blocks-tab.native.js +2 -2
  172. package/build-module/components/inserter/reusable-blocks-tab.native.js.map +1 -1
  173. package/build-module/components/inserter/tabs.native.js +1 -1
  174. package/build-module/components/inserter/tabs.native.js.map +1 -1
  175. package/build-module/components/inserter-draggable-blocks/index.js +9 -2
  176. package/build-module/components/inserter-draggable-blocks/index.js.map +1 -1
  177. package/build-module/components/link-control/constants.js +1 -1
  178. package/build-module/components/link-control/constants.js.map +1 -1
  179. package/build-module/components/link-control/index.js +17 -15
  180. package/build-module/components/link-control/index.js.map +1 -1
  181. package/build-module/components/link-control/search-create-button.js +7 -20
  182. package/build-module/components/link-control/search-create-button.js.map +1 -1
  183. package/build-module/components/link-control/search-input.js +4 -4
  184. package/build-module/components/link-control/search-input.js.map +1 -1
  185. package/build-module/components/link-control/search-item.js +14 -28
  186. package/build-module/components/link-control/search-item.js.map +1 -1
  187. package/build-module/components/link-control/search-results.js +3 -3
  188. package/build-module/components/link-control/search-results.js.map +1 -1
  189. package/build-module/components/link-control/settings-drawer.js +4 -5
  190. package/build-module/components/link-control/settings-drawer.js.map +1 -1
  191. package/build-module/components/list-view/appender.js +2 -6
  192. package/build-module/components/list-view/appender.js.map +1 -1
  193. package/build-module/components/provider/index.js +5 -2
  194. package/build-module/components/provider/index.js.map +1 -1
  195. package/build-module/components/provider/use-block-sync.js +21 -0
  196. package/build-module/components/provider/use-block-sync.js.map +1 -1
  197. package/build-module/components/resolution-tool/index.js +45 -0
  198. package/build-module/components/resolution-tool/index.js.map +1 -0
  199. package/build-module/components/url-input/index.js +4 -2
  200. package/build-module/components/url-input/index.js.map +1 -1
  201. package/build-module/components/writing-flow/use-tab-nav.js +8 -26
  202. package/build-module/components/writing-flow/use-tab-nav.js.map +1 -1
  203. package/build-module/components/writing-mode-control/index.js +57 -0
  204. package/build-module/components/writing-mode-control/index.js.map +1 -0
  205. package/build-module/hooks/behaviors.js +26 -20
  206. package/build-module/hooks/behaviors.js.map +1 -1
  207. package/build-module/hooks/supports.js +7 -1
  208. package/build-module/hooks/supports.js.map +1 -1
  209. package/build-module/hooks/typography.js +2 -1
  210. package/build-module/hooks/typography.js.map +1 -1
  211. package/build-module/hooks/utils.js +4 -2
  212. package/build-module/hooks/utils.js.map +1 -1
  213. package/build-module/private-apis.js +7 -1
  214. package/build-module/private-apis.js.map +1 -1
  215. package/build-module/private-apis.native.js +2 -0
  216. package/build-module/private-apis.native.js.map +1 -1
  217. package/build-module/store/actions.js +191 -1
  218. package/build-module/store/actions.js.map +1 -1
  219. package/build-module/store/defaults.js +1 -0
  220. package/build-module/store/defaults.js.map +1 -1
  221. package/build-module/store/index.js +10 -1
  222. package/build-module/store/index.js.map +1 -1
  223. package/build-module/store/private-actions.js +45 -36
  224. package/build-module/store/private-actions.js.map +1 -1
  225. package/build-module/store/private-selectors.js +2 -2
  226. package/build-module/store/private-selectors.js.map +1 -1
  227. package/build-module/store/reducer.js +22 -8
  228. package/build-module/store/reducer.js.map +1 -1
  229. package/build-module/store/selectors.js +33 -15
  230. package/build-module/store/selectors.js.map +1 -1
  231. package/build-style/content-rtl.css +3 -0
  232. package/build-style/content.css +3 -0
  233. package/build-style/style-rtl.css +131 -129
  234. package/build-style/style.css +131 -129
  235. package/package.json +32 -31
  236. package/src/components/alignment-control/test/__snapshots__/index.js.snap +6 -6
  237. package/src/components/block-alignment-control/test/__snapshots__/index.js.snap +5 -5
  238. package/src/components/block-draggable/style.scss +1 -0
  239. package/src/components/block-heading-level-dropdown/heading-level-icon.js +6 -1
  240. package/src/components/block-heading-level-dropdown/index.native.js +8 -4
  241. package/src/components/block-inspector/style.scss +2 -1
  242. package/src/components/block-lock/toolbar.js +34 -6
  243. package/src/components/block-mobile-toolbar/block-actions-menu.native.js +4 -8
  244. package/src/components/block-parent-selector/index.js +13 -8
  245. package/src/components/block-removal-warning-modal/index.js +20 -33
  246. package/src/components/block-toolbar/index.js +9 -6
  247. package/src/components/block-tools/block-contextual-toolbar.js +5 -11
  248. package/src/components/block-tools/style.scss +73 -26
  249. package/src/components/default-block-appender/content.scss +11 -0
  250. package/src/components/dimensions-tool/aspect-ratio-tool.js +124 -0
  251. package/src/components/dimensions-tool/index.js +212 -0
  252. package/src/components/dimensions-tool/scale-tool.js +124 -0
  253. package/src/components/dimensions-tool/stories/aspect-ratio-tool.js +52 -0
  254. package/src/components/dimensions-tool/stories/index.js +54 -0
  255. package/src/components/dimensions-tool/stories/scale-tool.js +48 -0
  256. package/src/components/dimensions-tool/stories/width-height-tool.js +54 -0
  257. package/src/components/dimensions-tool/test/index.js +641 -0
  258. package/src/components/dimensions-tool/width-height-tool.js +113 -0
  259. package/src/components/font-family/README.md +71 -0
  260. package/src/components/global-styles/color-panel.js +1 -1
  261. package/src/components/global-styles/filters-panel.js +2 -2
  262. package/src/components/global-styles/hooks.js +2 -0
  263. package/src/components/global-styles/typography-panel.js +40 -0
  264. package/src/components/image-editor/aspect-ratio-dropdown.js +1 -1
  265. package/src/components/image-editor/use-save-image.js +0 -1
  266. package/src/components/image-size-control/index.js +6 -0
  267. package/src/components/index.js +6 -0
  268. package/src/components/inserter/block-patterns-explorer/patterns-list.js +8 -2
  269. package/src/components/inserter/block-patterns-tab.js +8 -56
  270. package/src/components/inserter/hooks/use-block-types-state.js +3 -4
  271. package/src/components/inserter/hooks/use-patterns-state.js +35 -19
  272. package/src/components/inserter/media-tab/hooks.js +2 -22
  273. package/src/components/inserter/reusable-block-rename-hint.js +52 -0
  274. package/src/components/inserter/reusable-blocks-tab.js +5 -1
  275. package/src/components/inserter/reusable-blocks-tab.native.js +2 -2
  276. package/src/components/inserter/style.scss +28 -0
  277. package/src/components/inserter/tabs.native.js +5 -1
  278. package/src/components/inserter-draggable-blocks/index.js +13 -2
  279. package/src/components/link-control/constants.js +1 -1
  280. package/src/components/link-control/index.js +32 -28
  281. package/src/components/link-control/search-create-button.js +8 -26
  282. package/src/components/link-control/search-input.js +4 -3
  283. package/src/components/link-control/search-item.js +21 -43
  284. package/src/components/link-control/search-results.js +48 -46
  285. package/src/components/link-control/settings-drawer.js +6 -5
  286. package/src/components/link-control/style.scss +51 -123
  287. package/src/components/link-control/test/index.js +135 -123
  288. package/src/components/list-view/appender.js +5 -6
  289. package/src/components/list-view/style.scss +1 -2
  290. package/src/components/media-replace-flow/test/index.js +1 -1
  291. package/src/components/panel-color-settings/README.md +98 -0
  292. package/src/components/provider/index.js +9 -2
  293. package/src/components/provider/test/use-block-sync.js +21 -6
  294. package/src/components/provider/use-block-sync.js +19 -0
  295. package/src/components/recursion-provider/README.md +101 -0
  296. package/src/components/resolution-tool/index.js +56 -0
  297. package/src/components/resolution-tool/stories/index.js +48 -0
  298. package/src/components/url-input/index.js +2 -0
  299. package/src/components/writing-flow/use-tab-nav.js +10 -33
  300. package/src/components/writing-mode-control/index.js +68 -0
  301. package/src/components/writing-mode-control/style.scss +18 -0
  302. package/src/hooks/behaviors.js +25 -16
  303. package/src/hooks/supports.js +7 -0
  304. package/src/hooks/typography.js +2 -0
  305. package/src/hooks/utils.js +3 -0
  306. package/src/private-apis.js +6 -0
  307. package/src/private-apis.native.js +2 -0
  308. package/src/store/actions.js +194 -1
  309. package/src/store/defaults.js +1 -0
  310. package/src/store/index.js +10 -0
  311. package/src/store/private-actions.js +39 -39
  312. package/src/store/private-selectors.js +2 -2
  313. package/src/store/reducer.js +22 -8
  314. package/src/store/selectors.js +54 -20
  315. package/src/store/test/actions.js +111 -0
  316. package/src/store/test/private-actions.js +56 -0
@@ -0,0 +1,98 @@
1
+ # PanelColorSettings
2
+
3
+ `PanelColorSettings` is a React component that renders a UI for managing various color settings.
4
+ It is essentially a wrapper around the `PanelColorGradientSettings` component, but specifically disables the gradient features.
5
+
6
+ ## Usage
7
+
8
+ ```jsx
9
+ /**
10
+ * WordPress dependencies
11
+ */
12
+ import { PanelColorSettings } from '@wordpress/block-editor';
13
+ import { useState } from '@wordpress/element';
14
+ import { __ } from '@wordpress/i18n';
15
+
16
+ // ...
17
+
18
+ const MyPanelColorSettings = () => {
19
+ const [ textColor, setTextColor ] = useState( { color: '#000' } );
20
+ const [ backgroundColor, setBackgroundColor ] = useState( {
21
+ color: '#fff',
22
+ } );
23
+ const [ overlayTextColor, setOverlayTextColor ] = useState( {
24
+ color: '#000',
25
+ } );
26
+ const [ overlayBackgroundColor, setOverlayBackgroundColor ] = useState( {
27
+ color: '#eee',
28
+ } );
29
+
30
+ return (
31
+ <PanelColorSettings
32
+ __experimentalIsRenderedInSidebar
33
+ title={ __( 'Color' ) }
34
+ colorSettings={ [
35
+ {
36
+ value: textColor.color,
37
+ onChange: setTextColor,
38
+ label: __( 'Text' ),
39
+ },
40
+ {
41
+ value: backgroundColor.color,
42
+ onChange: setBackgroundColor,
43
+ label: __( 'Background' ),
44
+ },
45
+ {
46
+ value: overlayTextColor.color,
47
+ onChange: setOverlayTextColor,
48
+ label: __( 'Submenu & overlay text' ),
49
+ },
50
+ {
51
+ value: overlayBackgroundColor.color,
52
+ onChange: setOverlayBackgroundColor,
53
+ label: __( 'Submenu & overlay background' ),
54
+ },
55
+ ] }
56
+ />
57
+ );
58
+ };
59
+
60
+ /// ...
61
+
62
+ <MyPanelColorSettings />;
63
+ ```
64
+
65
+ ## Props
66
+
67
+ The component accepts the following props:
68
+
69
+ ### colorSettings
70
+
71
+ A user-provided set of color settings.
72
+
73
+ - Type: `Array`
74
+ - Required: No
75
+
76
+ Colors settings are provided as an array of objects with the following schema:
77
+
78
+ | Property | Description | Type |
79
+ | -------- | --------------------------------- | -------- |
80
+ | value | The current color of the setting | string |
81
+ | onChange | Callback on change of the setting | Function |
82
+ | label | Label of the setting | string |
83
+
84
+ Additionally, the following `PanelColorGradientSettings` props are supported and directly passed down to the underlying `PanelColorGradientSettings` instance:
85
+
86
+ - `className` - added to the underlying `ToolsPanel` instance.
87
+ - `colors` - array of colors to be used.
88
+ - `gradients` - not recommended to be used since `PanelColorSettings` resets it.
89
+ - `disableCustomColors` - whether addition of custom colors is enabled
90
+ - `disableCustomGradients` - not recommended to be used since `PanelColorSettings` sets it.
91
+ - `children` - displayed below the underlying `PanelColorGradientSettings` instance.
92
+ - `settings` - not recommended to be used, since `PanelColorSettings` builds it from the `colorSettings` prop.
93
+ - `title` - title of the underlying `ToolsPanel`.
94
+ - `showTitle` - whether to show the title of the `ToolsPanel`.
95
+ - `__experimentalIsRenderedInSidebar`
96
+ - `enableAlpha` - whether to enable setting opacity when specifying a color.
97
+
98
+ Please refer to the `PanelColorGradientSettings` component for more information.
@@ -28,9 +28,16 @@ export const ExperimentalBlockEditorProvider = withRegistryProvider(
28
28
  ...settings,
29
29
  __internalIsInitialized: true,
30
30
  },
31
- stripExperimentalSettings
31
+ {
32
+ stripExperimentalSettings,
33
+ reset: true,
34
+ }
32
35
  );
33
- }, [ settings ] );
36
+ }, [
37
+ settings,
38
+ stripExperimentalSettings,
39
+ __experimentalUpdateSettings,
40
+ ] );
34
41
 
35
42
  // Syncs the entity provider with changes in the block-editor store.
36
43
  useBlockSync( props );
@@ -48,7 +48,7 @@ describe( 'useBlockSync hook', () => {
48
48
  jest.clearAllMocks();
49
49
  } );
50
50
 
51
- it( 'resets the block-editor blocks when the controll value changes', async () => {
51
+ it( 'resets the block-editor blocks when the controlled value changes', async () => {
52
52
  const fakeBlocks = [];
53
53
  const resetBlocks = jest.spyOn( blockEditorActions, 'resetBlocks' );
54
54
  const replaceInnerBlocks = jest.spyOn(
@@ -58,7 +58,7 @@ describe( 'useBlockSync hook', () => {
58
58
  const onChange = jest.fn();
59
59
  const onInput = jest.fn();
60
60
 
61
- const { rerender } = render(
61
+ const { rerender, unmount } = render(
62
62
  <TestWrapper
63
63
  value={ fakeBlocks }
64
64
  onChange={ onChange }
@@ -88,9 +88,16 @@ describe( 'useBlockSync hook', () => {
88
88
  expect( onInput ).not.toHaveBeenCalled();
89
89
  expect( replaceInnerBlocks ).not.toHaveBeenCalled();
90
90
  expect( resetBlocks ).toHaveBeenCalledWith( testBlocks );
91
+
92
+ unmount();
93
+
94
+ expect( onChange ).not.toHaveBeenCalled();
95
+ expect( onInput ).not.toHaveBeenCalled();
96
+ expect( replaceInnerBlocks ).not.toHaveBeenCalled();
97
+ expect( resetBlocks ).toHaveBeenCalledWith( [] );
91
98
  } );
92
99
 
93
- it( 'replaces the inner blocks of a block when the control value changes if a clientId is passed', async () => {
100
+ it( 'replaces the inner blocks of a block when the controlled value changes if a clientId is passed', async () => {
94
101
  const fakeBlocks = [];
95
102
  const replaceInnerBlocks = jest.spyOn(
96
103
  blockEditorActions,
@@ -100,7 +107,7 @@ describe( 'useBlockSync hook', () => {
100
107
  const onChange = jest.fn();
101
108
  const onInput = jest.fn();
102
109
 
103
- const { rerender } = render(
110
+ const { rerender, unmount } = render(
104
111
  <TestWrapper
105
112
  clientId="test"
106
113
  value={ fakeBlocks }
@@ -138,8 +145,16 @@ describe( 'useBlockSync hook', () => {
138
145
  expect( onChange ).not.toHaveBeenCalled();
139
146
  expect( onInput ).not.toHaveBeenCalled();
140
147
  expect( resetBlocks ).not.toHaveBeenCalled();
141
- // We can't check the args because the blocks are cloned.
142
- expect( replaceInnerBlocks ).toHaveBeenCalled();
148
+ expect( replaceInnerBlocks ).toHaveBeenCalledWith( 'test', [
149
+ expect.objectContaining( { name: 'test/test-block' } ),
150
+ ] );
151
+
152
+ unmount();
153
+
154
+ expect( onChange ).not.toHaveBeenCalled();
155
+ expect( onInput ).not.toHaveBeenCalled();
156
+ expect( resetBlocks ).not.toHaveBeenCalled();
157
+ expect( replaceInnerBlocks ).toHaveBeenCalledWith( 'test', [] );
143
158
  } );
144
159
 
145
160
  it( 'does not add the controlled blocks to the block-editor store if the store already contains them', async () => {
@@ -134,6 +134,19 @@ export default function useBlockSync( {
134
134
  }
135
135
  };
136
136
 
137
+ // Clean up the changes made by setControlledBlocks() when the component
138
+ // containing useBlockSync() unmounts.
139
+ const unsetControlledBlocks = () => {
140
+ __unstableMarkNextChangeAsNotPersistent();
141
+ if ( clientId ) {
142
+ setHasControlledInnerBlocks( clientId, false );
143
+ __unstableMarkNextChangeAsNotPersistent();
144
+ replaceInnerBlocks( clientId, [] );
145
+ } else {
146
+ resetBlocks( [] );
147
+ }
148
+ };
149
+
137
150
  // Add a subscription to the block-editor registry to detect when changes
138
151
  // have been made. This lets us inform the data source of changes. This
139
152
  // is an effect so that the subscriber can run synchronously without
@@ -287,4 +300,10 @@ export default function useBlockSync( {
287
300
  unsubscribe();
288
301
  };
289
302
  }, [ registry, clientId ] );
303
+
304
+ useEffect( () => {
305
+ return () => {
306
+ unsetControlledBlocks();
307
+ };
308
+ }, [] );
290
309
  }
@@ -0,0 +1,101 @@
1
+ # RecursionProvider
2
+
3
+ According to Gutenberg's block rendering architecture, any block type capable of recursion should be responsible for handling its own infinite loops.
4
+
5
+ To help with detecting infinite loops on the client, the `RecursionProvider` component and the `useHasRecursion()` hook are used to identify if a block has already been rendered.
6
+
7
+ ## Usage
8
+
9
+ ```jsx
10
+ /**
11
+ * WordPress dependencies
12
+ */
13
+ import {
14
+ __experimentalRecursionProvider as RecursionProvider,
15
+ __experimentalUseHasRecursion as useHasRecursion,
16
+ useBlockProps,
17
+ Warning,
18
+ } from '@wordpress/block-editor';
19
+ import { __ } from '@wordpress/i18n';
20
+
21
+ export default function MyRecursiveBlockEdit( { attributes: { ref } } ) {
22
+ const hasAlreadyRendered = useHasRecursion( ref );
23
+ const blockProps = useBlockProps( {
24
+ className: 'my-block__custom-class',
25
+ } );
26
+
27
+ if ( hasAlreadyRendered ) {
28
+ return (
29
+ <div { ...blockProps }>
30
+ <Warning>
31
+ { __( 'Block cannot be rendered inside itself.' ) }
32
+ </Warning>
33
+ </div>
34
+ );
35
+ }
36
+
37
+ return (
38
+ <RecursionProvider uniqueId={ ref }>
39
+ Block editing code here....
40
+ </RecursionProvider>
41
+ );
42
+ }
43
+
44
+ /// ...
45
+
46
+ <MyRecursiveBlockEdit />;
47
+ ```
48
+
49
+ ## Props
50
+
51
+ The component accepts the following props:
52
+
53
+ ### uniqueId
54
+
55
+ Any value that acts as a unique identifier for a block instance.
56
+
57
+ - Type: `any`
58
+ - Required: Yes
59
+
60
+ ### children
61
+
62
+ Components to be rendered as content.
63
+
64
+ - Type: `Element`
65
+ - Required: Yes.
66
+
67
+ ### blockName
68
+
69
+ Optional block name.
70
+
71
+ - Type: `String`
72
+ - Required: No
73
+ - Default: ''
74
+
75
+ # `useHasRecursion()`
76
+
77
+ Used in conjunction with `RecursionProvider`, this hook is used to identify if a block has already been rendered.
78
+
79
+ ## Usage
80
+
81
+ For example usage, refer to the example above.
82
+
83
+ ## Props
84
+
85
+ The component accepts the following props:
86
+
87
+ ### uniqueId
88
+
89
+ Any value that acts as a unique identifier for a block instance.
90
+
91
+ - Type: `any`
92
+ - Required: Yes
93
+
94
+ ### blockName
95
+
96
+ Optional block name.
97
+
98
+ - Type: `String`
99
+ - Required: No
100
+ - Default: ''
101
+
@@ -0,0 +1,56 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import {
5
+ SelectControl,
6
+ __experimentalToolsPanelItem as ToolsPanelItem,
7
+ } from '@wordpress/components';
8
+ import { __, _x } from '@wordpress/i18n';
9
+
10
+ const DEFAULT_SIZE_OPTIONS = [
11
+ {
12
+ label: _x( 'Thumbnail', 'Image size option for resolution control' ),
13
+ value: 'thumbnail',
14
+ },
15
+ {
16
+ label: _x( 'Medium', 'Image size option for resolution control' ),
17
+ value: 'medium',
18
+ },
19
+ {
20
+ label: _x( 'Large', 'Image size option for resolution control' ),
21
+ value: 'large',
22
+ },
23
+ {
24
+ label: _x( 'Full Size', 'Image size option for resolution control' ),
25
+ value: 'full',
26
+ },
27
+ ];
28
+
29
+ export default function ResolutionTool( {
30
+ panelId,
31
+ value,
32
+ onChange,
33
+ options = DEFAULT_SIZE_OPTIONS,
34
+ defaultValue = DEFAULT_SIZE_OPTIONS[ 0 ].value,
35
+ isShownByDefault = true,
36
+ } ) {
37
+ const displayValue = value ?? defaultValue;
38
+ return (
39
+ <ToolsPanelItem
40
+ hasValue={ () => displayValue !== defaultValue }
41
+ label={ __( 'Resolution' ) }
42
+ onDeselect={ () => onChange( defaultValue ) }
43
+ isShownByDefault={ isShownByDefault }
44
+ panelId={ panelId }
45
+ >
46
+ <SelectControl
47
+ label={ __( 'Resolution' ) }
48
+ value={ displayValue }
49
+ options={ options }
50
+ onChange={ onChange }
51
+ help={ __( 'Select the size of the source image.' ) }
52
+ size={ '__unstable-large' }
53
+ />
54
+ </ToolsPanelItem>
55
+ );
56
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { useState } from '@wordpress/element';
5
+ import {
6
+ Panel,
7
+ __experimentalToolsPanel as ToolsPanel,
8
+ } from '@wordpress/components';
9
+
10
+ /**
11
+ * Internal dependencies
12
+ */
13
+ import ResolutionTool from '..';
14
+
15
+ export default {
16
+ title: 'BlockEditor (Private APIs)/ResolutionControl',
17
+ component: ResolutionTool,
18
+ argTypes: {
19
+ panelId: { control: { type: null } },
20
+ onChange: { action: 'changed' },
21
+ },
22
+ };
23
+
24
+ export const Default = ( { panelId, onChange: onChangeProp, ...props } ) => {
25
+ const [ resolution, setResolution ] = useState( undefined );
26
+ const resetAll = () => {
27
+ setResolution( undefined );
28
+ onChangeProp( undefined );
29
+ };
30
+ return (
31
+ <Panel>
32
+ <ToolsPanel panelId={ panelId } resetAll={ resetAll }>
33
+ <ResolutionTool
34
+ panelId={ panelId }
35
+ onChange={ ( newValue ) => {
36
+ setResolution( newValue );
37
+ onChangeProp( newValue );
38
+ } }
39
+ value={ resolution }
40
+ { ...props }
41
+ />
42
+ </ToolsPanel>
43
+ </Panel>
44
+ );
45
+ };
46
+ Default.args = {
47
+ panelId: 'panel-id',
48
+ };
@@ -434,6 +434,7 @@ class URLInput extends Component {
434
434
  placeholder = __( 'Paste URL or type to search' ),
435
435
  __experimentalRenderControl: renderControl,
436
436
  value = '',
437
+ hideLabelFromVision = false,
437
438
  } = this.props;
438
439
 
439
440
  const {
@@ -452,6 +453,7 @@ class URLInput extends Component {
452
453
  className: classnames( 'block-editor-url-input', className, {
453
454
  'is-full-width': isFullWidth,
454
455
  } ),
456
+ hideLabelFromVision,
455
457
  };
456
458
 
457
459
  const inputProps = {
@@ -11,6 +11,7 @@ import { useRef } from '@wordpress/element';
11
11
  * Internal dependencies
12
12
  */
13
13
  import { store as blockEditorStore } from '../../store';
14
+ import { isInSameBlock, isInsideRootBlock } from '../../utils/dom';
14
15
 
15
16
  export default function useTabNav() {
16
17
  const container = useRef();
@@ -116,41 +117,20 @@ export default function useTabNav() {
116
117
  return;
117
118
  }
118
119
 
120
+ const nextTabbable = focus.tabbable[ direction ]( event.target );
121
+
119
122
  // We want to constrain the tabbing to the block and its child blocks.
120
123
  // If the preceding form element is within a different block,
121
124
  // such as two sibling image blocks in the placeholder state,
122
125
  // we want shift + tab from the first form element to move to the image
123
126
  // block toolbar and not the previous image block's form element.
124
- // TODO: Should this become a utility function?
125
- /**
126
- * Determine whether an element is part of or is the selected block.
127
- *
128
- * @param {Object} selectedBlockElement
129
- * @param {Object} element
130
- * @return {boolean} Whether the element is part of or is the selected block.
131
- */
132
- const isElementPartOfSelectedBlock = (
133
- selectedBlockElement,
134
- element
135
- ) => {
136
- // Check if the element is or is within the selected block by finding the
137
- // closest element with a data-block attribute and seeing if
138
- // it matches our current selected block ID
139
- const elementBlockId = element
140
- .closest( '[data-block]' )
141
- ?.getAttribute( 'data-block' );
142
- const isElementSameBlock =
143
- elementBlockId === getSelectedBlockClientId();
144
-
145
- // Check if the element is a child of the selected block. This could be a
146
- // child block in a group or column block, etc.
147
- const isElementChildOfBlock =
148
- selectedBlockElement.contains( element );
149
-
150
- return isElementSameBlock || isElementChildOfBlock;
151
- };
127
+ const currentBlock = event.target.closest( '[data-block]' );
128
+ const isElementPartOfSelectedBlock =
129
+ currentBlock &&
130
+ nextTabbable &&
131
+ ( isInSameBlock( currentBlock, nextTabbable ) ||
132
+ isInsideRootBlock( currentBlock, nextTabbable ) );
152
133
 
153
- const nextTabbable = focus.tabbable[ direction ]( event.target );
154
134
  // Allow tabbing from the block wrapper to a form element,
155
135
  // and between form elements rendered in a block and its child blocks,
156
136
  // such as inside a placeholder. Form elements are generally
@@ -159,10 +139,7 @@ export default function useTabNav() {
159
139
  // future they can be rendered in an iframe or shadow DOM.
160
140
  if (
161
141
  isFormElement( nextTabbable ) &&
162
- isElementPartOfSelectedBlock(
163
- event.target.closest( '[data-block]' ),
164
- nextTabbable
165
- )
142
+ isElementPartOfSelectedBlock
166
143
  ) {
167
144
  return;
168
145
  }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * External dependencies
3
+ */
4
+ import classnames from 'classnames';
5
+
6
+ /**
7
+ * WordPress dependencies
8
+ */
9
+ import { BaseControl, Button } from '@wordpress/components';
10
+ import { __, isRTL } from '@wordpress/i18n';
11
+ import { textHorizontal, textVertical } from '@wordpress/icons';
12
+
13
+ const WRITING_MODES = [
14
+ {
15
+ name: __( 'Horizontal' ),
16
+ value: 'horizontal-tb',
17
+ icon: textHorizontal,
18
+ },
19
+ {
20
+ name: __( 'Vertical' ),
21
+ value: isRTL() ? 'vertical-lr' : 'vertical-rl',
22
+ icon: textVertical,
23
+ },
24
+ ];
25
+
26
+ /**
27
+ * Control to facilitate writing mode selections.
28
+ *
29
+ * @param {Object} props Component props.
30
+ * @param {string} props.className Class name to add to the control.
31
+ * @param {string} props.value Currently selected writing mode.
32
+ * @param {Function} props.onChange Handles change in the writing mode selection.
33
+ *
34
+ * @return {WPElement} Writing Mode control.
35
+ */
36
+ export default function WritingModeControl( { className, value, onChange } ) {
37
+ return (
38
+ <fieldset
39
+ className={ classnames(
40
+ 'block-editor-writing-mode-control',
41
+ className
42
+ ) }
43
+ >
44
+ <BaseControl.VisualLabel as="legend">
45
+ { __( 'Orientation' ) }
46
+ </BaseControl.VisualLabel>
47
+ <div className="block-editor-writing-mode-control__buttons">
48
+ { WRITING_MODES.map( ( writingMode ) => {
49
+ return (
50
+ <Button
51
+ key={ writingMode.value }
52
+ icon={ writingMode.icon }
53
+ label={ writingMode.name }
54
+ isPressed={ writingMode.value === value }
55
+ onClick={ () => {
56
+ onChange(
57
+ writingMode.value === value
58
+ ? undefined
59
+ : writingMode.value
60
+ );
61
+ } }
62
+ />
63
+ );
64
+ } ) }
65
+ </div>
66
+ </fieldset>
67
+ );
68
+ }
@@ -0,0 +1,18 @@
1
+ .block-editor-writing-mode-control {
2
+ border: 0;
3
+ margin: 0;
4
+ padding: 0;
5
+
6
+ .block-editor-writing-mode-control__buttons {
7
+ // 4px of padding makes the row 40px high, same as an input.
8
+ padding: $grid-unit-05 0;
9
+ display: flex;
10
+ }
11
+
12
+ .components-button.has-icon {
13
+ height: $grid-unit-40;
14
+ margin-right: $grid-unit-05;
15
+ min-width: $grid-unit-40;
16
+ padding: 0;
17
+ }
18
+ }
@@ -7,6 +7,7 @@ import { __ } from '@wordpress/i18n';
7
7
  import { hasBlockSupport } from '@wordpress/blocks';
8
8
  import { createHigherOrderComponent } from '@wordpress/compose';
9
9
  import { useSelect } from '@wordpress/data';
10
+ import { useMemo } from '@wordpress/element';
10
11
 
11
12
  /**
12
13
  * Internal dependencies
@@ -65,35 +66,40 @@ function BehaviorsControl( {
65
66
  ...behaviorsOptions,
66
67
  ];
67
68
 
69
+ const { behaviors, behaviorsValue } = useMemo( () => {
70
+ const mergedBehaviors = {
71
+ ...themeBehaviors,
72
+ ...( blockBehaviors || {} ),
73
+ };
74
+
75
+ let value = '';
76
+ if ( blockBehaviors === undefined ) {
77
+ value = 'default';
78
+ }
79
+ if ( blockBehaviors?.lightbox.enabled ) {
80
+ value = 'lightbox';
81
+ }
82
+ return {
83
+ behaviors: mergedBehaviors,
84
+ behaviorsValue: value,
85
+ };
86
+ }, [ blockBehaviors, themeBehaviors ] );
68
87
  // If every behavior is disabled, do not show the behaviors inspector control.
69
88
  if ( behaviorsOptions.length === 0 ) {
70
89
  return null;
71
90
  }
72
- // Block behaviors take precedence over theme behaviors.
73
- const behaviors = { ...themeBehaviors, ...( blockBehaviors || {} ) };
74
91
 
75
92
  const helpText = disabled
76
93
  ? __( 'The lightbox behavior is disabled for linked images.' )
77
94
  : '';
78
95
 
79
- const value = () => {
80
- if ( blockBehaviors === undefined ) {
81
- return 'default';
82
- }
83
- if ( behaviors?.lightbox.enabled ) {
84
- return 'lightbox';
85
- }
86
- return '';
87
- };
88
-
89
96
  return (
90
97
  <InspectorControls group="advanced">
91
- { /* This div is needed to prevent a margin bottom between the dropdown and the button. */ }
92
98
  <div>
93
99
  <SelectControl
94
100
  label={ __( 'Behaviors' ) }
95
101
  // At the moment we are only supporting one behavior (Lightbox)
96
- value={ value() }
102
+ value={ behaviorsValue }
97
103
  options={ options }
98
104
  onChange={ onChangeBehavior }
99
105
  hideCancelButton={ true }
@@ -101,7 +107,7 @@ function BehaviorsControl( {
101
107
  size="__unstable-large"
102
108
  disabled={ disabled }
103
109
  />
104
- { behaviors?.lightbox.enabled && (
110
+ { behaviorsValue === 'lightbox' && (
105
111
  <SelectControl
106
112
  label={ __( 'Animation' ) }
107
113
  // At the moment we are only supporting one behavior (Lightbox)
@@ -115,7 +121,10 @@ function BehaviorsControl( {
115
121
  value: 'zoom',
116
122
  label: __( 'Zoom' ),
117
123
  },
118
- { value: 'fade', label: 'Fade' },
124
+ {
125
+ value: 'fade',
126
+ label: __( 'Fade' ),
127
+ },
119
128
  ] }
120
129
  onChange={ onChangeAnimation }
121
130
  hideCancelButton={ false }