@plone/volto 17.0.0-alpha.8 → 17.0.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 (365) hide show
  1. package/.eslintrc +26 -3
  2. package/CHANGELOG.md +488 -5
  3. package/CONTRIBUTING.md +5 -1
  4. package/README.md +12 -9
  5. package/addon-registry.js +10 -1
  6. package/create-addons-loader.js +1 -1
  7. package/cypress/support/commands.js +70 -14
  8. package/cypress/support/e2e.js +1 -2
  9. package/cypress/support/volto-slate.js +4 -5
  10. package/cypress.config.js +1 -0
  11. package/docker-compose.yml +1 -1
  12. package/locales/ca/LC_MESSAGES/volto.po +276 -53
  13. package/locales/ca.json +1 -1
  14. package/locales/de/LC_MESSAGES/volto.po +284 -61
  15. package/locales/de.json +1 -1
  16. package/locales/en/LC_MESSAGES/volto.po +274 -51
  17. package/locales/en.json +1 -1
  18. package/locales/es/LC_MESSAGES/volto.po +313 -90
  19. package/locales/es.json +1 -1
  20. package/locales/eu/LC_MESSAGES/volto.po +275 -52
  21. package/locales/eu.json +1 -1
  22. package/locales/fi/LC_MESSAGES/volto.po +275 -52
  23. package/locales/fi.json +1 -1
  24. package/locales/fr/LC_MESSAGES/volto.po +276 -53
  25. package/locales/fr.json +1 -1
  26. package/locales/it/LC_MESSAGES/volto.po +469 -246
  27. package/locales/it.json +1 -1
  28. package/locales/ja/LC_MESSAGES/volto.po +275 -52
  29. package/locales/ja.json +1 -1
  30. package/locales/nl/LC_MESSAGES/volto.po +276 -53
  31. package/locales/nl.json +1 -1
  32. package/locales/pt/LC_MESSAGES/volto.po +276 -53
  33. package/locales/pt.json +1 -1
  34. package/locales/pt_BR/LC_MESSAGES/volto.po +309 -86
  35. package/locales/pt_BR.json +1 -1
  36. package/locales/ro/LC_MESSAGES/volto.po +276 -53
  37. package/locales/ro.json +1 -1
  38. package/locales/volto.pot +279 -52
  39. package/locales/zh_CN/LC_MESSAGES/volto.po +276 -53
  40. package/locales/zh_CN.json +1 -1
  41. package/package.json +44 -34
  42. package/packages/volto-slate/package.json +1 -1
  43. package/packages/volto-slate/src/actions/index.js +1 -1
  44. package/packages/volto-slate/src/blocks/Table/TableBlockEdit.jsx +21 -212
  45. package/packages/volto-slate/src/blocks/Table/schema.js +122 -0
  46. package/packages/volto-slate/src/blocks/Text/DefaultTextBlockEditor.jsx +8 -3
  47. package/packages/volto-slate/src/blocks/Text/TextBlockView.jsx +21 -16
  48. package/packages/volto-slate/src/blocks/Text/extensions/withDeserializers.js +3 -1
  49. package/packages/volto-slate/src/blocks/Text/index.js +10 -7
  50. package/packages/volto-slate/src/editor/config.jsx +5 -4
  51. package/packages/volto-slate/src/editor/index.js +4 -4
  52. package/packages/volto-slate/src/editor/less/slate.less +28 -0
  53. package/packages/volto-slate/src/editor/plugins/Link/render.jsx +5 -6
  54. package/packages/volto-slate/src/editor/plugins/StyleMenu/StyleMenu.jsx +14 -4
  55. package/packages/volto-slate/src/editor/plugins/StyleMenu/utils.js +14 -5
  56. package/packages/volto-slate/src/editor/render.jsx +77 -8
  57. package/packages/volto-slate/src/editor/ui/SlateContextToolbar.jsx +2 -2
  58. package/packages/volto-slate/src/editor/ui/index.js +15 -15
  59. package/packages/volto-slate/src/index.js +2 -2
  60. package/packages/volto-slate/src/utils/blocks.js +7 -0
  61. package/packages/volto-slate/src/widgets/RichTextWidget.jsx +15 -8
  62. package/razzle.config.js +4 -6
  63. package/src/actions/index.js +4 -0
  64. package/src/actions/navroot/navroot.js +16 -0
  65. package/src/actions/navroot/navroot.test.js +15 -0
  66. package/src/actions/relations/rebuild.js +7 -7
  67. package/src/actions/relations/relations.js +17 -0
  68. package/src/actions/site/site.js +16 -0
  69. package/src/actions/site/site.test.js +15 -0
  70. package/src/actions/userSession/userSession.js +17 -1
  71. package/src/components/index.js +194 -192
  72. package/src/components/manage/Actions/Actions.jsx +133 -243
  73. package/src/components/manage/Add/Add.jsx +7 -8
  74. package/src/components/manage/AnchorPlugin/index.jsx +2 -2
  75. package/src/components/manage/AnchorPlugin/utils/EditorUtils.js +3 -1
  76. package/src/components/manage/Blocks/Block/BlocksForm.jsx +19 -2
  77. package/src/components/manage/Blocks/Block/Edit.jsx +1 -1
  78. package/src/components/manage/Blocks/Block/Settings.jsx +2 -0
  79. package/src/components/manage/Blocks/Block/Settings.test.jsx +92 -0
  80. package/src/components/manage/Blocks/Block/Style.jsx +2 -2
  81. package/src/components/manage/Blocks/Container/Data.jsx +32 -0
  82. package/src/components/manage/Blocks/Container/Edit.jsx +177 -0
  83. package/src/components/manage/Blocks/Container/EditBlockWrapper.jsx +121 -0
  84. package/src/components/manage/Blocks/Container/NewBlockAddButton.jsx +84 -0
  85. package/src/components/manage/Blocks/Container/SimpleContainerToolbar.jsx +54 -0
  86. package/src/components/manage/Blocks/Grid/Edit.jsx +47 -0
  87. package/src/components/manage/Blocks/Grid/View.jsx +43 -0
  88. package/src/components/manage/Blocks/Grid/adapter.js +14 -0
  89. package/src/components/manage/Blocks/Grid/grid-1.svg +6 -0
  90. package/src/components/manage/Blocks/Grid/grid-2.svg +9 -0
  91. package/src/components/manage/Blocks/Grid/grid-3.svg +10 -0
  92. package/src/components/manage/Blocks/Grid/grid-4.svg +11 -0
  93. package/src/components/manage/Blocks/Grid/schema.js +35 -0
  94. package/src/components/manage/Blocks/Grid/templates.js +47 -0
  95. package/src/components/manage/Blocks/HTML/Edit.jsx +8 -8
  96. package/src/components/manage/Blocks/HeroImageLeft/Edit.jsx +36 -26
  97. package/src/components/manage/Blocks/Image/Edit.jsx +51 -12
  98. package/src/components/manage/Blocks/Image/Edit.test.jsx +2 -0
  99. package/src/components/manage/Blocks/Image/ImageSidebar.jsx +66 -16
  100. package/src/components/manage/Blocks/Image/View.jsx +26 -5
  101. package/src/components/manage/Blocks/Image/View.test.jsx +20 -0
  102. package/src/components/manage/Blocks/Image/schema.js +17 -10
  103. package/src/components/manage/Blocks/Image/utils.js +14 -0
  104. package/src/components/manage/Blocks/LeadImage/Edit.jsx +32 -10
  105. package/src/components/manage/Blocks/LeadImage/Edit.test.jsx +11 -1
  106. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.jsx +28 -9
  107. package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.test.jsx +8 -2
  108. package/src/components/manage/Blocks/LeadImage/View.jsx +50 -38
  109. package/src/components/manage/Blocks/LeadImage/View.test.jsx +11 -1
  110. package/src/components/manage/Blocks/Listing/DefaultTemplate.jsx +18 -3
  111. package/src/components/manage/Blocks/Listing/ListingBody.jsx +32 -8
  112. package/src/components/manage/Blocks/Listing/ListingBody.test.jsx +20 -0
  113. package/src/components/manage/Blocks/Listing/SummaryTemplate.jsx +1 -1
  114. package/src/components/manage/Blocks/Listing/getAsyncData.js +3 -5
  115. package/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +27 -17
  116. package/src/components/manage/Blocks/Maps/Edit.jsx +135 -209
  117. package/src/components/manage/Blocks/Maps/Edit.test.jsx +1 -2
  118. package/src/components/manage/Blocks/Maps/View.test.jsx +1 -2
  119. package/src/components/manage/Blocks/Search/SearchBlockView.jsx +3 -2
  120. package/src/components/manage/Blocks/Search/components/Facets.jsx +66 -7
  121. package/src/components/manage/Blocks/Search/components/FilterList.jsx +4 -6
  122. package/src/components/manage/Blocks/Search/components/SearchInput.jsx +9 -2
  123. package/src/components/manage/Blocks/Search/components/SelectFacet.jsx +2 -9
  124. package/src/components/manage/Blocks/Search/components/index.js +13 -13
  125. package/src/components/manage/Blocks/Search/hocs/index.js +2 -2
  126. package/src/components/manage/Blocks/Search/hocs/withQueryString.jsx +5 -2
  127. package/src/components/manage/Blocks/Search/hocs/withSearch.jsx +70 -36
  128. package/src/components/manage/Blocks/Search/layout/LeftColumnFacets.jsx +17 -5
  129. package/src/components/manage/Blocks/Search/layout/RightColumnFacets.jsx +17 -5
  130. package/src/components/manage/Blocks/Search/layout/TopSideFacets.jsx +21 -5
  131. package/src/components/manage/Blocks/Search/schema.js +29 -14
  132. package/src/components/manage/Blocks/Table/Cell.jsx +2 -3
  133. package/src/components/manage/Blocks/Teaser/Body.jsx +0 -1
  134. package/src/components/manage/Blocks/Teaser/DefaultBody.jsx +5 -10
  135. package/src/components/manage/Blocks/Teaser/schema.js +5 -0
  136. package/src/components/manage/Blocks/Text/Edit.jsx +2 -3
  137. package/src/components/manage/Blocks/Title/View.jsx +0 -23
  138. package/src/components/manage/Blocks/Title/View.test.jsx +16 -1
  139. package/src/components/manage/Blocks/ToC/Schema.jsx +40 -7
  140. package/src/components/manage/Blocks/ToC/View.jsx +84 -14
  141. package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.jsx +8 -3
  142. package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.test.jsx +44 -0
  143. package/src/components/manage/Blocks/ToC/variations/HorizontalMenu.jsx +149 -10
  144. package/src/components/manage/Blocks/ToC/variations/index.js +3 -1
  145. package/src/components/manage/Contents/Contents.jsx +285 -114
  146. package/src/components/manage/Contents/ContentsPropertiesModal.jsx +90 -166
  147. package/src/components/manage/Contents/ContentsRenameModal.jsx +88 -139
  148. package/src/components/manage/Contents/ContentsRenameModal.stories.jsx +61 -0
  149. package/src/components/manage/Contents/ContentsTagsModal.jsx +83 -130
  150. package/src/components/manage/Contents/ContentsTagsModal.stories.jsx +68 -0
  151. package/src/components/manage/Contents/ContentsUploadModal.jsx +11 -7
  152. package/src/components/manage/Contents/ContentsWorkflowModal.jsx +87 -154
  153. package/src/components/manage/Controlpanels/Aliases.jsx +4 -12
  154. package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.jsx +65 -38
  155. package/src/components/manage/Controlpanels/Groups/RenderGroups.jsx +2 -2
  156. package/src/components/manage/Controlpanels/Relations/BrokenRelations.jsx +38 -13
  157. package/src/components/manage/Controlpanels/Relations/Relations.jsx +5 -5
  158. package/src/components/manage/Controlpanels/Relations/RelationsListing.jsx +8 -7
  159. package/src/components/manage/Controlpanels/Relations/RelationsMatrix.jsx +68 -68
  160. package/src/components/manage/Controlpanels/Rules/AddRule.jsx +3 -10
  161. package/src/components/manage/Controlpanels/Rules/EditRule.jsx +1 -1
  162. package/src/components/manage/Controlpanels/UndoControlpanel.jsx +6 -9
  163. package/src/components/manage/Controlpanels/Users/RenderUsers.jsx +97 -7
  164. package/src/components/manage/Controlpanels/Users/UsersControlpanel.jsx +127 -99
  165. package/src/components/manage/Delete/Delete.jsx +96 -171
  166. package/src/components/manage/Diff/DiffField.jsx +25 -1
  167. package/src/components/manage/DragDropList/DragDropList.jsx +18 -13
  168. package/src/components/manage/Form/BlockDataForm.jsx +3 -2
  169. package/src/components/manage/Form/BlockDataForm.test.jsx +51 -17
  170. package/src/components/manage/Form/Form.jsx +7 -6
  171. package/src/components/manage/Form/InlineForm.test.jsx +16 -14
  172. package/src/components/manage/History/History.jsx +11 -1
  173. package/src/components/manage/LinksToItem/LinksToItem.jsx +209 -0
  174. package/src/components/manage/LinksToItem/LinksToItem.test.jsx +100 -0
  175. package/src/components/manage/LockingToastsFactory/LockingToastsFactory.jsx +1 -2
  176. package/src/components/manage/Messages/Messages.jsx +32 -99
  177. package/src/components/manage/Messages/Messages.test.jsx +0 -1
  178. package/src/components/manage/Preferences/ChangePassword.jsx +2 -2
  179. package/src/components/manage/Sharing/Sharing.jsx +62 -22
  180. package/src/components/manage/Sidebar/AlignBlock.jsx +1 -1
  181. package/src/components/manage/Sidebar/Sidebar.jsx +139 -220
  182. package/src/components/manage/TemplateChooser/TemplateChooser.jsx +38 -0
  183. package/src/components/manage/TemplateChooser/TemplateChooser.test.jsx +34 -0
  184. package/src/components/manage/TemplateChooser/template.svg +10 -0
  185. package/src/components/manage/Toast/Toast.jsx +1 -1
  186. package/src/components/manage/Toolbar/More.jsx +17 -2
  187. package/src/components/manage/Toolbar/PersonalTools.jsx +97 -155
  188. package/src/components/manage/Toolbar/Toolbar.jsx +2 -2
  189. package/src/components/manage/UniversalLink/UniversalLink.jsx +6 -12
  190. package/src/components/manage/UniversalLink/UniversalLink.test.jsx +37 -0
  191. package/src/components/manage/Widgets/AlignWidget.jsx +2 -4
  192. package/src/components/manage/Widgets/ArrayWidget.jsx +3 -1
  193. package/src/components/manage/Widgets/ArrayWidget.test.jsx +45 -1
  194. package/src/components/manage/Widgets/ColorPickerWidget.jsx +6 -1
  195. package/src/components/manage/Widgets/ColorPickerWidget.test.jsx +9 -7
  196. package/src/components/manage/Widgets/DatetimeWidget.jsx +2 -8
  197. package/src/components/manage/Widgets/FileWidget.jsx +2 -1
  198. package/src/components/manage/Widgets/FormFieldWrapper.jsx +1 -1
  199. package/src/components/manage/Widgets/IdWidget.jsx +1 -2
  200. package/src/components/manage/Widgets/ObjectBrowserWidget.jsx +2 -9
  201. package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.jsx +3 -10
  202. package/src/components/manage/Widgets/RecurrenceWidget/WeekdayOfTheMonthIndexField.jsx +4 -4
  203. package/src/components/manage/Widgets/RegistryImageWidget.jsx +210 -0
  204. package/src/components/manage/Widgets/RegistryImageWidget.test.jsx +91 -0
  205. package/src/components/manage/Widgets/SchemaWidget.jsx +6 -9
  206. package/src/components/manage/Widgets/SelectUtils.js +1 -1
  207. package/src/components/manage/Widgets/SelectWidget.jsx +15 -1
  208. package/src/components/manage/Widgets/SelectWidget.test.jsx +45 -1
  209. package/src/components/manage/Widgets/WysiwygWidget.jsx +2 -9
  210. package/src/components/manage/Workflow/Workflow.jsx +75 -184
  211. package/src/components/theme/Anontools/Anontools.jsx +44 -72
  212. package/src/components/theme/Anontools/Anontools.stories.jsx +16 -6
  213. package/src/components/theme/Anontools/Anontools.test.jsx +16 -2
  214. package/src/components/theme/Breadcrumbs/Breadcrumbs.jsx +52 -99
  215. package/src/components/theme/Breadcrumbs/Breadcrumbs.stories.jsx +14 -13
  216. package/src/components/theme/Comments/Comment.stories.jsx +84 -0
  217. package/src/components/theme/Comments/CommentEditModal.jsx +63 -115
  218. package/src/components/theme/Comments/Comments.jsx +268 -380
  219. package/src/components/theme/Component/Component.jsx +1 -1
  220. package/src/components/theme/ContactForm/ContactForm.jsx +108 -192
  221. package/src/components/theme/ContactForm/ContactForm.stories.jsx +1 -1
  222. package/src/components/theme/ContactForm/ContactForm.test.jsx +2 -3
  223. package/src/components/theme/ContentMetadataTags/ContentMetadataTags.jsx +41 -3
  224. package/src/components/theme/Error/ServerError.jsx +29 -0
  225. package/src/components/theme/Header/Header.jsx +37 -63
  226. package/src/components/theme/Header/Header.test.jsx +18 -0
  227. package/src/components/theme/Image/Image.jsx +96 -0
  228. package/src/components/theme/Image/Image.test.jsx +125 -0
  229. package/src/components/theme/Login/Login.jsx +160 -243
  230. package/src/components/theme/Logo/Logo.Multilingual.test.jsx +131 -1
  231. package/src/components/theme/Logo/Logo.jsx +35 -27
  232. package/src/components/theme/Logo/Logo.test.jsx +135 -1
  233. package/src/components/theme/Logout/Logout.jsx +36 -83
  234. package/src/components/theme/Navigation/Navigation.jsx +86 -171
  235. package/src/components/theme/NotFound/NotFound.jsx +55 -41
  236. package/src/components/theme/PasswordReset/PasswordReset.jsx +7 -5
  237. package/src/components/theme/PasswordReset/RequestPasswordReset.jsx +95 -170
  238. package/src/components/theme/PreviewImage/PreviewImage.jsx +31 -15
  239. package/src/components/theme/PreviewImage/PreviewImage.test.js +53 -13
  240. package/src/components/theme/Register/Register.jsx +2 -4
  241. package/src/components/theme/Search/SearchTags.jsx +30 -60
  242. package/src/components/theme/SearchWidget/SearchWidget.jsx +49 -97
  243. package/src/components/theme/SearchWidget/SearchWidget.test.jsx +8 -0
  244. package/src/components/theme/Sitemap/Sitemap.jsx +24 -13
  245. package/src/components/theme/Sitemap/Sitemap.test.jsx +23 -2
  246. package/src/components/theme/TsTest/TsTest.test.tsx +11 -0
  247. package/src/components/theme/TsTest/TsTest.tsx +15 -0
  248. package/src/components/theme/View/AlbumView.jsx +21 -16
  249. package/src/components/theme/View/EventView.jsx +36 -25
  250. package/src/components/theme/View/FileView.jsx +23 -18
  251. package/src/components/theme/View/ImageView.jsx +40 -32
  252. package/src/components/theme/View/ImageView.test.jsx +4 -0
  253. package/src/components/theme/View/LinkView.jsx +53 -78
  254. package/src/components/theme/View/ListingView.jsx +36 -28
  255. package/src/components/theme/View/NewsItemView.jsx +16 -17
  256. package/src/components/theme/View/RenderBlocks.jsx +56 -21
  257. package/src/components/theme/View/RenderEmptyBlock.jsx +5 -0
  258. package/src/components/theme/View/SummaryView.jsx +49 -39
  259. package/src/components/theme/View/TabularView.jsx +59 -53
  260. package/src/components/theme/View/View.jsx +2 -0
  261. package/src/components/theme/Widgets/ImageWidget.stories.jsx +1 -2
  262. package/src/config/Blocks.jsx +46 -0
  263. package/src/config/Components.jsx +3 -1
  264. package/src/config/ControlPanels.js +0 -1
  265. package/src/config/Loadables.jsx +1 -1
  266. package/src/config/NonContentRoutes.jsx +1 -0
  267. package/src/config/RichTextEditor/Blocks.jsx +4 -5
  268. package/src/config/RichTextEditor/FromHTML.jsx +2 -2
  269. package/src/config/RichTextEditor/Plugins.jsx +2 -3
  270. package/src/config/RichTextEditor/Styles.jsx +1 -1
  271. package/src/config/RichTextEditor/ToHTML.jsx +12 -10
  272. package/src/config/RichTextEditor/index.js +2 -3
  273. package/src/config/Views.jsx +6 -4
  274. package/src/config/Widgets.jsx +3 -0
  275. package/src/config/index.js +36 -2
  276. package/src/config/server.js +2 -0
  277. package/src/constants/ActionTypes.js +4 -0
  278. package/src/constants/Indexes.js +3 -1
  279. package/src/express-middleware/devproxy.js +1 -1
  280. package/src/express-middleware/files.js +11 -9
  281. package/src/express-middleware/images.js +12 -5
  282. package/src/express-middleware/ok.js +16 -0
  283. package/src/express-middleware/robotstxt.js +1 -1
  284. package/src/express-middleware/sitemap.js +1 -1
  285. package/src/express-middleware/static.js +3 -3
  286. package/src/helpers/Api/Api.js +1 -1
  287. package/src/helpers/Blocks/Blocks.js +52 -6
  288. package/src/helpers/Blocks/Blocks.test.js +92 -13
  289. package/src/helpers/Extensions/index.js +2 -1
  290. package/src/helpers/Extensions/withBlockSchemaEnhancer.js +63 -61
  291. package/src/helpers/Extensions/withBlockSchemaEnhancer.test.js +145 -0
  292. package/src/helpers/FormValidation/FormValidation.js +37 -7
  293. package/src/helpers/FormValidation/FormValidation.test.js +32 -0
  294. package/src/helpers/Html/Html.jsx +2 -8
  295. package/src/helpers/Loadable/__mocks__/Loadable.js +18 -18
  296. package/src/helpers/MessageLabels/MessageLabels.js +39 -4
  297. package/src/helpers/ScrollToTop/ScrollToTop.jsx +5 -3
  298. package/src/helpers/Site/index.js +21 -0
  299. package/src/helpers/Url/Url.js +22 -1
  300. package/src/helpers/Url/Url.test.js +41 -0
  301. package/src/helpers/Utils/UseDetectClickOutside.stories.jsx +190 -0
  302. package/src/helpers/Utils/Utils.js +35 -0
  303. package/src/helpers/Utils/Utils.test.js +13 -0
  304. package/src/helpers/Utils/usePagination.js +67 -14
  305. package/src/helpers/Utils/usePagination.test.js +115 -0
  306. package/src/helpers/index.js +15 -8
  307. package/src/hooks/client/useClient.js +11 -0
  308. package/src/hooks/clipboard/useClipboard.js +26 -0
  309. package/src/hooks/index.js +2 -0
  310. package/src/icons/grid-block.svg +11 -0
  311. package/src/middleware/api.js +203 -173
  312. package/src/middleware/blacklistRoutes.js +25 -22
  313. package/src/middleware/index.js +2 -2
  314. package/src/middleware/storeProtectLoadUtils.js +61 -62
  315. package/src/middleware/storeProtectLoadUtils.test.js +47 -43
  316. package/src/reducers/actions/actions.js +7 -5
  317. package/src/reducers/actions/actions.test.js +70 -0
  318. package/src/reducers/content/content.test.js +4 -4
  319. package/src/reducers/index.js +4 -0
  320. package/src/reducers/navigation/navigation.js +5 -5
  321. package/src/reducers/navigation/navigation.test.js +30 -0
  322. package/src/reducers/navroot/navroot.js +79 -0
  323. package/src/reducers/navroot/navroot.test.js +110 -0
  324. package/src/reducers/relations/relations.js +74 -46
  325. package/src/reducers/site/site.js +51 -0
  326. package/src/reducers/site/site.test.js +67 -0
  327. package/src/reducers/userSession/userSession.js +15 -1
  328. package/src/registry.js +2 -2
  329. package/src/routes.js +9 -0
  330. package/src/server.jsx +9 -0
  331. package/src/start-server.js +2 -2
  332. package/src/storybook.jsx +24 -38
  333. package/test-setup-config.js +11 -1
  334. package/theme/themes/pastanaga/collections/form.overrides +46 -0
  335. package/theme/themes/pastanaga/collections/menu.overrides +3 -2
  336. package/theme/themes/pastanaga/elements/container.overrides +5 -2
  337. package/theme/themes/pastanaga/elements/input.overrides +11 -1
  338. package/theme/themes/pastanaga/elements/label.overrides +10 -0
  339. package/theme/themes/pastanaga/elements/step.overrides +2 -1
  340. package/theme/themes/pastanaga/extras/blocks.less +25 -15
  341. package/theme/themes/pastanaga/extras/color-picker-widget.less +1 -1
  342. package/theme/themes/pastanaga/extras/contents.less +6 -1
  343. package/theme/themes/pastanaga/extras/draftjs.less +4 -4
  344. package/theme/themes/pastanaga/extras/grid.less +427 -0
  345. package/theme/themes/pastanaga/extras/login.less +3 -0
  346. package/theme/themes/pastanaga/extras/main.less +14 -7
  347. package/theme/themes/pastanaga/extras/react-dates-overrides.less +4 -2
  348. package/theme/themes/pastanaga/extras/search.less +7 -1
  349. package/theme/themes/pastanaga/extras/sidebar.less +5 -4
  350. package/theme/themes/pastanaga/extras/time-picker-overrides.less +5 -3
  351. package/theme/themes/pastanaga/extras/toc.less +29 -0
  352. package/theme/themes/pastanaga/extras/toolbar.less +6 -2
  353. package/theme/themes/pastanaga/extras/userscontrolpanel.less +17 -9
  354. package/theme/themes/pastanaga/extras/widgets.less +1 -1
  355. package/theme/themes/pastanaga/modules/rating.overrides +2 -1
  356. package/theme/themes/pastanaga-cms-ui/elements/container.overrides +2 -1
  357. package/theme/themes/pastanaga-cms-ui/extras/cms-ui.elements.container.less +6 -2
  358. package/theme/themes/pastanaga-cms-ui/extras/cms-ui.site.less +2 -2
  359. package/tsconfig.json +33 -0
  360. package/webpack-plugins/webpack-less-plugin.js +19 -0
  361. package/.yarn/install-state.gz +0 -0
  362. package/.yarn/releases/yarn-3.2.3.cjs +0 -783
  363. package/src/components/manage/Blocks/Teaser/utils.js +0 -44
  364. package/src/components/manage/Blocks/Teaser/utils.test.jsx +0 -229
  365. package/src/components/theme/Header/Header.md +0 -27
@@ -1,9 +1,15 @@
1
1
  import express from 'express';
2
2
  import { getAPIResourceWithAuth } from '@plone/volto/helpers';
3
3
 
4
- const HEADERS = ['content-type', 'content-disposition', 'cache-control'];
4
+ const HEADERS = [
5
+ 'content-type',
6
+ 'content-disposition',
7
+ 'cache-control',
8
+ 'x-sendfile',
9
+ 'x-accel-redirect',
10
+ ];
5
11
 
6
- function imageMiddleware(req, res, next) {
12
+ function imageMiddlewareFn(req, res, next) {
7
13
  getAPIResourceWithAuth(req)
8
14
  .then((resource) => {
9
15
  // Just forward the headers that we need
@@ -17,11 +23,12 @@ function imageMiddleware(req, res, next) {
17
23
  .catch(next);
18
24
  }
19
25
 
20
- export default function () {
26
+ export default function imagesMiddleware() {
21
27
  const middleware = express.Router();
22
28
 
23
- middleware.all(['**/@@images/*'], imageMiddleware);
24
- middleware.all(['/@portrait/*'], imageMiddleware);
29
+ middleware.all(['**/@@images/*'], imageMiddlewareFn);
30
+ middleware.all(['/@portrait/*'], imageMiddlewareFn);
31
+ middleware.all(['/@@site-logo/*'], imageMiddlewareFn);
25
32
  middleware.id = 'imageResourcesProcessor';
26
33
  return middleware;
27
34
  }
@@ -0,0 +1,16 @@
1
+ import express from 'express';
2
+ import config from '@plone/volto/registry';
3
+
4
+ const ok = function (req, res, next) {
5
+ res.type('text/plain');
6
+ res.set('Expires', 'Sat, 1 Jan 2000 00:00:00 GMT');
7
+ res.set('Cache-Control', 'max-age=0, must-revalidate, private');
8
+ res.send('ok');
9
+ };
10
+
11
+ export default function okRouteMiddleware() {
12
+ const middleware = express.Router();
13
+ middleware.all(config?.settings?.okRoute || '/ok', ok);
14
+ middleware.id = 'ok';
15
+ return middleware;
16
+ }
@@ -22,7 +22,7 @@ const envRobots = function (req, res, next) {
22
22
  res.send(process.env.VOLTO_ROBOTSTXT);
23
23
  };
24
24
 
25
- export default function () {
25
+ export default function robotstxtMiddleware() {
26
26
  const middleware = express.Router();
27
27
  if (process.env.VOLTO_ROBOTSTXT) {
28
28
  middleware.all('**/robots.txt', envRobots);
@@ -47,7 +47,7 @@ export const sitemapIndex = function (req, res, next) {
47
47
  });
48
48
  };
49
49
 
50
- export default function () {
50
+ export default function sitemapMiddleware() {
51
51
  const middleware = express.Router();
52
52
 
53
53
  middleware.all('**/sitemap.xml.gz', sitemap);
@@ -2,7 +2,7 @@ import express from 'express';
2
2
  import path from 'path';
3
3
  import config from '@plone/volto/registry';
4
4
 
5
- const staticMiddleware = express.static(
5
+ const staticMiddlewareFn = express.static(
6
6
  process.env.BUILD_DIR
7
7
  ? path.join(process.env.BUILD_DIR, 'public')
8
8
  : process.env.RAZZLE_PUBLIC_DIR,
@@ -24,9 +24,9 @@ const staticMiddleware = express.static(
24
24
  },
25
25
  );
26
26
 
27
- export default function () {
27
+ export default function staticsMiddleware() {
28
28
  const middleware = express.Router();
29
- middleware.all('*', staticMiddleware);
29
+ middleware.all('*', staticMiddlewareFn);
30
30
  middleware.id = 'staticResourcesProcessor';
31
31
  return middleware;
32
32
  }
@@ -89,7 +89,7 @@ class Api {
89
89
  checkUrl &&
90
90
  request.url &&
91
91
  request.xhr &&
92
- stripQuerystring(request.url) !==
92
+ encodeURI(stripQuerystring(request.url)) !==
93
93
  stripQuerystring(request.xhr.responseURL)
94
94
  ) {
95
95
  if (request.xhr.responseURL?.length === 0) {
@@ -290,9 +290,8 @@ export function changeBlock(formData, id, value) {
290
290
  */
291
291
  export function nextBlockId(formData, currentBlock) {
292
292
  const blocksLayoutFieldname = getBlocksLayoutFieldname(formData);
293
- const currentIndex = formData[blocksLayoutFieldname].items.indexOf(
294
- currentBlock,
295
- );
293
+ const currentIndex =
294
+ formData[blocksLayoutFieldname].items.indexOf(currentBlock);
296
295
 
297
296
  if (currentIndex === formData[blocksLayoutFieldname].items.length - 1) {
298
297
  // We are already at the bottom block don't do anything
@@ -312,9 +311,8 @@ export function nextBlockId(formData, currentBlock) {
312
311
  */
313
312
  export function previousBlockId(formData, currentBlock) {
314
313
  const blocksLayoutFieldname = getBlocksLayoutFieldname(formData);
315
- const currentIndex = formData[blocksLayoutFieldname].items.indexOf(
316
- currentBlock,
317
- );
314
+ const currentIndex =
315
+ formData[blocksLayoutFieldname].items.indexOf(currentBlock);
318
316
 
319
317
  if (currentIndex === 0) {
320
318
  // We are already at the top block don't do anything
@@ -343,6 +341,32 @@ export function emptyBlocksForm() {
343
341
  };
344
342
  }
345
343
 
344
+ /**
345
+ * Generate empty blocks blocks/blocks_layout pair given the type
346
+ * (could be empty, if not type given) and the number of blocks
347
+ * @function blocksFormGenerator
348
+ * @param {number} number How many blocks to generate of the type (could be "empty", if no type provided)
349
+ * @param {number} type The type of the blocks
350
+ * @return {Object} blocks/blocks_layout pair filled with the generated blocks
351
+ */
352
+ export function blocksFormGenerator(number, type) {
353
+ const idMap = [...Array(number).keys()].map(() => uuid());
354
+ const start = {
355
+ blocks: {},
356
+ blocks_layout: { items: idMap },
357
+ };
358
+
359
+ return {
360
+ ...start,
361
+ blocks: Object.fromEntries(
362
+ start.blocks_layout.items.map((item) => [
363
+ item,
364
+ { '@type': type || 'empty' },
365
+ ]),
366
+ ),
367
+ };
368
+ }
369
+
346
370
  /**
347
371
  * Recursively discover blocks in data and call the provided callback
348
372
  * @function visitBlocks
@@ -524,3 +548,25 @@ export const getPreviousNextBlock = ({ content, block }) => {
524
548
 
525
549
  return [previousBlock, nextBlock];
526
550
  };
551
+
552
+ /**
553
+ * Given a `block` object and a list of block types, return a list of block ids matching the types
554
+ *
555
+ * @function findBlocks
556
+ * @param {Object} types A list with the list of types to be matched
557
+ * @return {Array} An array of block ids
558
+ */
559
+ export function findBlocks(blocks, types, result = []) {
560
+ const containerBlockTypes = config.settings.containerBlockTypes;
561
+
562
+ Object.keys(blocks).forEach((blockId) => {
563
+ const block = blocks[blockId];
564
+ if (types.includes(block['@type'])) {
565
+ result.push(blockId);
566
+ } else if (containerBlockTypes.includes(block['@type']) || block.blocks) {
567
+ findBlocks(block.blocks, types, result);
568
+ }
569
+ });
570
+
571
+ return result;
572
+ }
@@ -19,6 +19,8 @@ import {
19
19
  buildStyleClassNamesFromData,
20
20
  buildStyleClassNamesExtenders,
21
21
  getPreviousNextBlock,
22
+ blocksFormGenerator,
23
+ findBlocks,
22
24
  } from './Blocks';
23
25
 
24
26
  import config from '@plone/volto/registry';
@@ -586,26 +588,26 @@ describe('Blocks', () => {
586
588
  const d = {
587
589
  data: {
588
590
  blocks: {
589
- '1': {
591
+ 1: {
590
592
  blocks: {
591
- '2': {},
592
- '3': {
593
+ 2: {},
594
+ 3: {
593
595
  data: {
594
596
  blocks: {
595
- '11': {},
596
- '12': {},
597
- '13': {},
597
+ 11: {},
598
+ 12: {},
599
+ 13: {},
598
600
  },
599
601
  blocks_layout: {
600
602
  items: ['11', '12', '13'],
601
603
  },
602
604
  },
603
605
  },
604
- '7': {
606
+ 7: {
605
607
  blocks: {
606
- '8': {},
607
- '9': {},
608
- '10': {},
608
+ 8: {},
609
+ 9: {},
610
+ 10: {},
609
611
  },
610
612
  blocks_layout: {
611
613
  items: ['8', '9', '10'],
@@ -616,10 +618,10 @@ describe('Blocks', () => {
616
618
  items: ['2', '3', '7'],
617
619
  },
618
620
  },
619
- '4': {
621
+ 4: {
620
622
  blocks: {
621
- '5': {},
622
- '6': {},
623
+ 5: {},
624
+ 6: {},
623
625
  },
624
626
  blocks_layout: {
625
627
  items: ['5', '6'],
@@ -1275,4 +1277,81 @@ describe('Blocks', () => {
1275
1277
  ]);
1276
1278
  });
1277
1279
  });
1280
+
1281
+ describe('blocksFormGenerator', () => {
1282
+ it('Returns an empty blocks/blocks_layout pair', () => {
1283
+ expect(blocksFormGenerator(0, '')).toEqual({
1284
+ blocks: {},
1285
+ blocks_layout: { items: [] },
1286
+ });
1287
+ });
1288
+ it('Returns a filled blocks/blocks_layout pair with type block', () => {
1289
+ const result = blocksFormGenerator(2, 'teaser');
1290
+ expect(Object.keys(result.blocks).length).toEqual(2);
1291
+ expect(result.blocks_layout.items.length).toEqual(2);
1292
+ expect(result.blocks[result.blocks_layout.items[0]]['@type']).toEqual(
1293
+ 'teaser',
1294
+ );
1295
+ expect(result.blocks[result.blocks_layout.items[1]]['@type']).toEqual(
1296
+ 'teaser',
1297
+ );
1298
+ });
1299
+ });
1300
+ });
1301
+
1302
+ describe('findBlocks', () => {
1303
+ it('Get all blocks in the first level (main block container)', () => {
1304
+ const blocks = {
1305
+ 1: { title: 'title', '@type': 'title' },
1306
+ 2: { title: 'an image', '@type': 'image' },
1307
+ 3: { title: 'description', '@type': 'description' },
1308
+ 4: { title: 'a text', '@type': 'slate' },
1309
+ };
1310
+ const types = ['description'];
1311
+ expect(findBlocks(blocks, types)).toStrictEqual(['3']);
1312
+ });
1313
+
1314
+ it('Get all blocks in the first level (main block container) given a list', () => {
1315
+ const blocks = {
1316
+ 1: { title: 'title', '@type': 'title' },
1317
+ 2: { title: 'an image', '@type': 'image' },
1318
+ 3: { title: 'description', '@type': 'description' },
1319
+ 4: { title: 'a text', '@type': 'slate' },
1320
+ };
1321
+ const types = ['description', 'slate'];
1322
+ expect(findBlocks(blocks, types)).toStrictEqual(['3', '4']);
1323
+ });
1324
+
1325
+ it('Get all blocks in the first level (main block container) given a list', () => {
1326
+ const blocks = {
1327
+ 1: { title: 'title', '@type': 'title' },
1328
+ 2: { title: 'an image', '@type': 'image' },
1329
+ 3: { title: 'description', '@type': 'description' },
1330
+ 4: { title: 'a text', '@type': 'slate' },
1331
+ 5: { title: 'a text', '@type': 'slate' },
1332
+ };
1333
+ const types = ['description', 'slate'];
1334
+ expect(findBlocks(blocks, types)).toStrictEqual(['3', '4', '5']);
1335
+ });
1336
+
1337
+ it('Get all blocks, including containers, given a list', () => {
1338
+ const blocks = {
1339
+ 1: { title: 'title', '@type': 'title' },
1340
+ 2: { title: 'an image', '@type': 'image' },
1341
+ 3: { title: 'description', '@type': 'description' },
1342
+ 4: { title: 'a text', '@type': 'slate' },
1343
+ 5: {
1344
+ title: 'a container',
1345
+ '@type': 'gridBlock',
1346
+ blocks: {
1347
+ 6: { title: 'title', '@type': 'title' },
1348
+ 7: { title: 'an image', '@type': 'image' },
1349
+ 8: { title: 'description', '@type': 'description' },
1350
+ 9: { title: 'a text', '@type': 'slate' },
1351
+ },
1352
+ },
1353
+ };
1354
+ const types = ['description', 'slate'];
1355
+ expect(findBlocks(blocks, types)).toStrictEqual(['3', '4', '8', '9']);
1356
+ });
1278
1357
  });
@@ -1,5 +1,6 @@
1
1
  export * from './withBlockSchemaEnhancer';
2
- export withBlockExtensions, {
2
+ export {
3
+ default as withBlockExtensions,
3
4
  resolveExtension,
4
5
  resolveBlockExtensions,
5
6
  } from './withBlockExtensions';
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { defineMessages } from 'react-intl';
3
3
  import { useIntl } from 'react-intl';
4
+ import { find, isEmpty } from 'lodash';
4
5
  import config from '@plone/volto/registry';
5
6
  import { cloneDeepSchema } from '@plone/volto/helpers/Utils/Utils';
6
7
 
@@ -109,61 +110,59 @@ export const addExtensionFieldToSchema = ({
109
110
  * }
110
111
  * ```
111
112
  */
112
- export const withBlockSchemaEnhancer = (
113
- FormComponent,
114
- extensionName = 'vendor',
115
- insertFieldToOrder = _addField,
116
- ) => ({ ...props }) => {
117
- const { formData, schema: originalSchema } = props;
118
- const intl = useIntl();
113
+ export const withBlockSchemaEnhancer =
114
+ (FormComponent, extensionName = 'vendor', insertFieldToOrder = _addField) =>
115
+ ({ ...props }) => {
116
+ const { formData, schema: originalSchema } = props;
117
+ const intl = useIntl();
119
118
 
120
- const blocksConfig = getBlocksConfig(props);
119
+ const blocksConfig = getBlocksConfig(props);
121
120
 
122
- const blockType = formData['@type'];
123
- const extensionConfig =
124
- blocksConfig?.[blockType]?.extensions?.[extensionName];
125
-
126
- if (!extensionConfig)
127
- return <FormComponent {...props} schema={originalSchema} />;
128
-
129
- const activeItemName = formData?.[extensionName];
130
- let activeItem = extensionConfig.items?.find(
131
- (item) => item.id === activeItemName,
132
- );
133
- if (!activeItem)
134
- activeItem = extensionConfig.items?.find((item) => item.isDefault);
135
-
136
- const schemaEnhancer =
137
- // For the main "variation" of blocks, allow simply passing a
138
- // schemaEnhancer in the block configuration
139
- activeItem?.['schemaEnhancer'] ||
140
- (extensionName === 'variation' &&
141
- blocksConfig?.[blockType]?.schemaEnhancer);
142
-
143
- let schema = schemaEnhancer
144
- ? schemaEnhancer({
145
- schema: cloneDeepSchema(originalSchema),
146
- formData,
147
- intl,
148
- })
149
- : cloneDeepSchema(originalSchema);
121
+ const blockType = formData['@type'];
122
+ const extensionConfig =
123
+ blocksConfig?.[blockType]?.extensions?.[extensionName];
150
124
 
151
- const { title = messages.variation, description } = extensionConfig;
125
+ if (!extensionConfig)
126
+ return <FormComponent {...props} schema={originalSchema} />;
152
127
 
153
- if (extensionConfig.items?.length > 1) {
154
- addExtensionFieldToSchema({
155
- schema,
156
- name: extensionName,
157
- items: extensionConfig.items || [],
158
- intl,
159
- title,
160
- description,
161
- insertFieldToOrder,
162
- });
163
- }
128
+ const activeItemName = formData?.[extensionName];
129
+ let activeItem = extensionConfig.items?.find(
130
+ (item) => item.id === activeItemName,
131
+ );
132
+ if (!activeItem)
133
+ activeItem = extensionConfig.items?.find((item) => item.isDefault);
134
+
135
+ const schemaEnhancer =
136
+ // For the main "variation" of blocks, allow simply passing a
137
+ // schemaEnhancer in the block configuration
138
+ activeItem?.['schemaEnhancer'] ||
139
+ (extensionName === 'variation' &&
140
+ blocksConfig?.[blockType]?.schemaEnhancer);
141
+
142
+ let schema = schemaEnhancer
143
+ ? schemaEnhancer({
144
+ schema: cloneDeepSchema(originalSchema),
145
+ formData,
146
+ intl,
147
+ })
148
+ : cloneDeepSchema(originalSchema);
149
+
150
+ const { title = messages.variation, description } = extensionConfig;
151
+
152
+ if (extensionConfig.items?.length > 1) {
153
+ addExtensionFieldToSchema({
154
+ schema,
155
+ name: extensionName,
156
+ items: extensionConfig.items || [],
157
+ intl,
158
+ title,
159
+ description,
160
+ insertFieldToOrder,
161
+ });
162
+ }
164
163
 
165
- return <FormComponent {...props} schema={schema} />;
166
- };
164
+ return <FormComponent {...props} schema={schema} />;
165
+ };
167
166
 
168
167
  /**
169
168
  * Apply block variation schema enhancers to the provided schema, using block
@@ -291,20 +290,23 @@ export const EMPTY_STYLES_SCHEMA = {
291
290
  };
292
291
 
293
292
  /**
294
- * Creates the `styles` field and fieldset in a schema
293
+ * Adds the `styles` field and 'styling' fieldset in a given schema
295
294
  */
296
295
  export const addStyling = ({ schema, formData, intl }) => {
297
- schema.fieldsets.push({
298
- id: 'styling',
299
- title: intl.formatMessage(messages.styling),
300
- fields: ['styles'],
301
- });
296
+ if (isEmpty(find(schema.fieldsets, { id: 'styling' }))) {
297
+ schema.fieldsets.push({
298
+ id: 'styling',
299
+ title: intl.formatMessage(messages.styling),
300
+ fields: ['styles'],
301
+ });
302
+
303
+ schema.properties.styles = {
304
+ widget: 'object',
305
+ title: intl.formatMessage(messages.styling),
306
+ schema: cloneDeepSchema(EMPTY_STYLES_SCHEMA),
307
+ };
308
+ }
302
309
 
303
- schema.properties.styles = {
304
- widget: 'object',
305
- title: intl.formatMessage(messages.styling),
306
- schema: EMPTY_STYLES_SCHEMA,
307
- };
308
310
  return schema;
309
311
  };
310
312
 
@@ -2,6 +2,7 @@ import {
2
2
  addExtensionFieldToSchema,
3
3
  applySchemaEnhancer,
4
4
  composeSchema,
5
+ addStyling,
5
6
  } from './withBlockSchemaEnhancer';
6
7
 
7
8
  import config from '@plone/volto/registry';
@@ -246,3 +247,147 @@ describe('composeSchema', () => {
246
247
  expect(res).toStrictEqual([6, 9]);
247
248
  });
248
249
  });
250
+
251
+ describe('addStyling', () => {
252
+ it('returns an enhanced schema with the styling wrapper object on it', () => {
253
+ const intl = { formatMessage: () => 'Styling' };
254
+
255
+ const schema = {
256
+ fieldsets: [
257
+ {
258
+ id: 'default',
259
+ title: 'Default',
260
+ fields: [],
261
+ },
262
+ ],
263
+ properties: {},
264
+ required: [],
265
+ };
266
+
267
+ const result = addStyling({ schema, intl });
268
+
269
+ expect(result).toStrictEqual({
270
+ fieldsets: [
271
+ { id: 'default', title: 'Default', fields: [] },
272
+ { id: 'styling', title: 'Styling', fields: ['styles'] },
273
+ ],
274
+ properties: {
275
+ styles: {
276
+ widget: 'object',
277
+ title: 'Styling',
278
+ schema: {
279
+ fieldsets: [
280
+ {
281
+ fields: [],
282
+ id: 'default',
283
+ title: 'Default',
284
+ },
285
+ ],
286
+ properties: {},
287
+ required: [],
288
+ },
289
+ },
290
+ },
291
+ required: [],
292
+ });
293
+ });
294
+
295
+ it('multiple schema enhancers', () => {
296
+ const intl = { formatMessage: () => 'Styling' };
297
+
298
+ const schema1 = {
299
+ fieldsets: [
300
+ {
301
+ id: 'default',
302
+ title: 'Default',
303
+ fields: [],
304
+ },
305
+ ],
306
+ properties: {},
307
+ required: [],
308
+ };
309
+
310
+ const schema2 = {
311
+ fieldsets: [
312
+ {
313
+ id: 'default',
314
+ title: 'Default',
315
+ fields: [],
316
+ },
317
+ ],
318
+ properties: {},
319
+ required: [],
320
+ };
321
+
322
+ const result = addStyling({ schema: schema1, intl });
323
+
324
+ // We add some fields to the styling schema
325
+ result.properties.styles.schema.properties.align = {
326
+ widget: 'align',
327
+ title: 'align',
328
+ actions: ['left', 'right', 'center'],
329
+ default: 'left',
330
+ };
331
+
332
+ result.properties.styles.schema.fieldsets[0].fields = ['align'];
333
+
334
+ const result2 = addStyling({ schema: schema2, intl });
335
+
336
+ expect(result).toStrictEqual({
337
+ fieldsets: [
338
+ { id: 'default', title: 'Default', fields: [] },
339
+ { id: 'styling', title: 'Styling', fields: ['styles'] },
340
+ ],
341
+ properties: {
342
+ styles: {
343
+ widget: 'object',
344
+ title: 'Styling',
345
+ schema: {
346
+ fieldsets: [
347
+ {
348
+ fields: ['align'],
349
+ id: 'default',
350
+ title: 'Default',
351
+ },
352
+ ],
353
+ properties: {
354
+ align: {
355
+ widget: 'align',
356
+ title: 'align',
357
+ actions: ['left', 'right', 'center'],
358
+ default: 'left',
359
+ },
360
+ },
361
+ required: [],
362
+ },
363
+ },
364
+ },
365
+ required: [],
366
+ });
367
+
368
+ expect(result2).toStrictEqual({
369
+ fieldsets: [
370
+ { id: 'default', title: 'Default', fields: [] },
371
+ { id: 'styling', title: 'Styling', fields: ['styles'] },
372
+ ],
373
+ properties: {
374
+ styles: {
375
+ widget: 'object',
376
+ title: 'Styling',
377
+ schema: {
378
+ fieldsets: [
379
+ {
380
+ fields: [],
381
+ id: 'default',
382
+ title: 'Default',
383
+ },
384
+ ],
385
+ properties: {},
386
+ required: [],
387
+ },
388
+ },
389
+ },
390
+ required: [],
391
+ });
392
+ });
393
+ });