@xiwebdesign/xicms-core 6.4.7 → 7.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 (373) hide show
  1. package/dist/SiteChrome.d.ts +12 -0
  2. package/dist/SiteChrome.js +24 -0
  3. package/dist/SiteChrome.js.map +1 -0
  4. package/dist/XiCMSProvider.d.ts +16 -8
  5. package/dist/XiCMSProvider.js +83 -58
  6. package/dist/XiCMSProvider.js.map +1 -1
  7. package/dist/admin/AdminApp.d.ts +1 -1
  8. package/dist/admin/AdminApp.js +79 -35
  9. package/dist/admin/AdminApp.js.map +1 -1
  10. package/dist/admin/AdminHelp.d.ts +8 -1
  11. package/dist/admin/AdminHelp.js +2 -2
  12. package/dist/admin/AdminHelp.js.map +1 -1
  13. package/dist/admin/NewsEditor.js +9 -9
  14. package/dist/admin/SuperadminPanel.js +5 -5
  15. package/dist/admin/blockEditors/GenericEditor.d.ts +2 -2
  16. package/dist/admin/blockEditors/GenericEditor.js +12 -11
  17. package/dist/admin/blockEditors/GenericEditor.js.map +1 -1
  18. package/dist/admin/blockEditors/StyleEditor.d.ts +1 -1
  19. package/dist/admin/blockEditors/StyleEditor.js +2 -2
  20. package/dist/admin/blockEditors/SymbolRefEditor.d.ts +1 -1
  21. package/dist/admin/blockEditors/SymbolRefEditor.js +5 -5
  22. package/dist/admin/blockEditors/index.d.ts +1 -1
  23. package/dist/admin/blockEditors/index.js +10 -10
  24. package/dist/admin/customBlocks/CustomBlocksPanel.js +7 -7
  25. package/dist/admin/editors/RichTextEditor.js +8 -7
  26. package/dist/admin/editors/RichTextEditor.js.map +1 -1
  27. package/dist/admin/editors/fontSizeExtension.js +1 -1
  28. package/dist/admin/editors/fontSizeExtension.js.map +1 -1
  29. package/dist/admin/forms/FormsPanel.js +9 -9
  30. package/dist/admin/index.d.ts +16 -16
  31. package/dist/admin/index.js +16 -16
  32. package/dist/admin/lib/mediaUsage.js +1 -1
  33. package/dist/admin/lib/pagesClient.d.ts +1 -1
  34. package/dist/admin/lib/pagesClient.js +11 -7
  35. package/dist/admin/lib/pagesClient.js.map +1 -1
  36. package/dist/admin/lib/sanitizeDraft.d.ts +9 -0
  37. package/dist/admin/lib/sanitizeDraft.js +28 -0
  38. package/dist/admin/lib/sanitizeDraft.js.map +1 -0
  39. package/dist/admin/lib/symbolsClient.d.ts +1 -1
  40. package/dist/admin/lib/symbolsClient.js +3 -3
  41. package/dist/admin/lib/upload.js +3 -3
  42. package/dist/admin/lib/useNestedDialog.d.ts +15 -0
  43. package/dist/admin/lib/useNestedDialog.js +23 -0
  44. package/dist/admin/lib/useNestedDialog.js.map +1 -0
  45. package/dist/admin/lib/zodFields.d.ts +4 -18
  46. package/dist/admin/lib/zodFields.js +54 -35
  47. package/dist/admin/lib/zodFields.js.map +1 -1
  48. package/dist/admin/media/MediaManager.js +7 -7
  49. package/dist/admin/media/MediaPicker.js +7 -7
  50. package/dist/admin/media/MediaPicker.js.map +1 -1
  51. package/dist/admin/pages/PageEditor.d.ts +1 -1
  52. package/dist/admin/pages/PageEditor.js +13 -13
  53. package/dist/admin/pages/PagesPanel.js +30 -30
  54. package/dist/admin/pages/PagesPanel.js.map +1 -1
  55. package/dist/admin/panelRegistry.js +7 -7
  56. package/dist/admin/patterns/PatternInserter.d.ts +1 -1
  57. package/dist/admin/patterns/PatternInserter.js +5 -5
  58. package/dist/admin/patterns/PatternInserter.js.map +1 -1
  59. package/dist/admin/settings/MailSettings.js +5 -5
  60. package/dist/admin/settings/MailTemplates.d.ts +1 -1
  61. package/dist/admin/settings/MailTemplates.js +5 -5
  62. package/dist/admin/settings/SettingsPanel.js +20 -20
  63. package/dist/admin/settings/SettingsPanel.js.map +1 -1
  64. package/dist/admin/settings/SnapshotsCard.js +5 -5
  65. package/dist/admin/settings/moduleSettingsForm.d.ts +1 -1
  66. package/dist/admin/settings/moduleSettingsForm.js +4 -4
  67. package/dist/admin/settings/moduleSettingsForm.js.map +1 -1
  68. package/dist/admin/shop/CategoriesTab.js +8 -8
  69. package/dist/admin/shop/ConnectionsTab.js +3 -3
  70. package/dist/admin/shop/DiscountsTab.js +8 -8
  71. package/dist/admin/shop/OrdersTab.js +10 -10
  72. package/dist/admin/shop/OrdersTab.js.map +1 -1
  73. package/dist/admin/shop/ProductsTab.js +10 -10
  74. package/dist/admin/shop/ShopPanel.js +9 -9
  75. package/dist/admin/shop/ShopSettingsTab.js +4 -4
  76. package/dist/admin/shop/index.d.ts +2 -2
  77. package/dist/admin/shop/index.js +2 -2
  78. package/dist/admin/shop/lib.js +2 -2
  79. package/dist/admin/stats/StatsPanel.js +2 -2
  80. package/dist/admin/ui/ArrayEditor.js +1 -1
  81. package/dist/admin/ui/PanelIcon.d.ts +3 -0
  82. package/dist/admin/ui/PanelIcon.js +34 -0
  83. package/dist/admin/ui/PanelIcon.js.map +1 -0
  84. package/dist/admin/ui/dialog.d.ts +21 -6
  85. package/dist/admin/ui/dialog.js +55 -34
  86. package/dist/admin/ui/dialog.js.map +1 -1
  87. package/dist/admin/ui/index.d.ts +7 -7
  88. package/dist/admin/ui/index.js +7 -7
  89. package/dist/admin/ui/primitives.js +1 -1
  90. package/dist/admin/ui/tabs.js +1 -1
  91. package/dist/admin/visual/TranslationPanel.d.ts +1 -1
  92. package/dist/admin/visual/TranslationPanel.js +3 -3
  93. package/dist/admin/visual/VisualEditor.js +47 -25
  94. package/dist/admin/visual/VisualEditor.js.map +1 -1
  95. package/dist/admin.css +2 -1
  96. package/dist/agentFiles/catalog.d.ts +2 -2
  97. package/dist/agentFiles/catalog.js +6 -5
  98. package/dist/agentFiles/catalog.js.map +1 -1
  99. package/dist/agentFiles/files.d.ts +5 -5
  100. package/dist/agentFiles/files.js +17 -17
  101. package/dist/agentFiles/files.js.map +1 -1
  102. package/dist/all.d.ts +4 -4
  103. package/dist/all.js +6 -6
  104. package/dist/auth/AuthProvider.d.ts +2 -2
  105. package/dist/auth/AuthProvider.js +51 -28
  106. package/dist/auth/AuthProvider.js.map +1 -1
  107. package/dist/auth/LoginForm.js +1 -1
  108. package/dist/auth/roles.js +4 -1
  109. package/dist/auth/roles.js.map +1 -1
  110. package/dist/blocks/BlockRenderer.d.ts +1 -1
  111. package/dist/blocks/BlockRenderer.js +3 -3
  112. package/dist/blocks/blockStyle.d.ts +1 -1
  113. package/dist/blocks/builtins/Accordion.d.ts +1 -1
  114. package/dist/blocks/builtins/Accordion.js +13 -6
  115. package/dist/blocks/builtins/Accordion.js.map +1 -1
  116. package/dist/blocks/builtins/Agenda.d.ts +1 -1
  117. package/dist/blocks/builtins/Agenda.js +5 -5
  118. package/dist/blocks/builtins/Banner.d.ts +1 -1
  119. package/dist/blocks/builtins/Banner.js +2 -2
  120. package/dist/blocks/builtins/BeforeAfter.d.ts +1 -1
  121. package/dist/blocks/builtins/BeforeAfter.js +4 -4
  122. package/dist/blocks/builtins/BeforeAfter.js.map +1 -1
  123. package/dist/blocks/builtins/Booking.d.ts +1 -1
  124. package/dist/blocks/builtins/Booking.js +5 -5
  125. package/dist/blocks/builtins/Breadcrumbs.d.ts +1 -1
  126. package/dist/blocks/builtins/Breadcrumbs.js +3 -3
  127. package/dist/blocks/builtins/Cards.d.ts +1 -1
  128. package/dist/blocks/builtins/Cards.js +5 -5
  129. package/dist/blocks/builtins/Cards.js.map +1 -1
  130. package/dist/blocks/builtins/Columns.d.ts +1 -1
  131. package/dist/blocks/builtins/Columns.js +4 -4
  132. package/dist/blocks/builtins/Contact.d.ts +3 -3
  133. package/dist/blocks/builtins/Contact.js +4 -4
  134. package/dist/blocks/builtins/Countdown.d.ts +1 -1
  135. package/dist/blocks/builtins/Countdown.js +4 -4
  136. package/dist/blocks/builtins/Countdown.js.map +1 -1
  137. package/dist/blocks/builtins/Cta.d.ts +1 -1
  138. package/dist/blocks/builtins/Cta.js +3 -3
  139. package/dist/blocks/builtins/Downloads.d.ts +1 -1
  140. package/dist/blocks/builtins/Downloads.js +4 -4
  141. package/dist/blocks/builtins/Elements.d.ts +3 -3
  142. package/dist/blocks/builtins/Elements.js +3 -3
  143. package/dist/blocks/builtins/Embed.d.ts +1 -1
  144. package/dist/blocks/builtins/Embed.js +3 -3
  145. package/dist/blocks/builtins/Faq.d.ts +1 -1
  146. package/dist/blocks/builtins/Faq.js +14 -6
  147. package/dist/blocks/builtins/Faq.js.map +1 -1
  148. package/dist/blocks/builtins/FormBlock.d.ts +1 -1
  149. package/dist/blocks/builtins/FormBlock.js +28 -18
  150. package/dist/blocks/builtins/FormBlock.js.map +1 -1
  151. package/dist/blocks/builtins/Gallery.d.ts +2 -2
  152. package/dist/blocks/builtins/Gallery.js +5 -5
  153. package/dist/blocks/builtins/Hero.d.ts +1 -1
  154. package/dist/blocks/builtins/Hero.js +4 -4
  155. package/dist/blocks/builtins/ImageBlock.d.ts +1 -1
  156. package/dist/blocks/builtins/ImageBlock.js +3 -3
  157. package/dist/blocks/builtins/Jobs.d.ts +2 -2
  158. package/dist/blocks/builtins/Jobs.js +5 -5
  159. package/dist/blocks/builtins/Layout.d.ts +2 -2
  160. package/dist/blocks/builtins/Layout.js +4 -4
  161. package/dist/blocks/builtins/MapBlock.d.ts +1 -1
  162. package/dist/blocks/builtins/MapBlock.js +3 -3
  163. package/dist/blocks/builtins/NewsListBlock.d.ts +1 -1
  164. package/dist/blocks/builtins/NewsListBlock.js +4 -4
  165. package/dist/blocks/builtins/Newsletter.d.ts +1 -1
  166. package/dist/blocks/builtins/Newsletter.js +7 -7
  167. package/dist/blocks/builtins/Newsletter.js.map +1 -1
  168. package/dist/blocks/builtins/OpenNowBadge.d.ts +1 -1
  169. package/dist/blocks/builtins/OpenNowBadge.js +8 -3
  170. package/dist/blocks/builtins/OpenNowBadge.js.map +1 -1
  171. package/dist/blocks/builtins/OpeningHours.d.ts +1 -1
  172. package/dist/blocks/builtins/OpeningHours.js +6 -6
  173. package/dist/blocks/builtins/PdfBlock.d.ts +1 -1
  174. package/dist/blocks/builtins/PdfBlock.js +3 -3
  175. package/dist/blocks/builtins/Portfolio.d.ts +1 -1
  176. package/dist/blocks/builtins/Portfolio.js +5 -5
  177. package/dist/blocks/builtins/Pricing.d.ts +2 -2
  178. package/dist/blocks/builtins/Pricing.js +5 -5
  179. package/dist/blocks/builtins/Pricing.js.map +1 -1
  180. package/dist/blocks/builtins/RichTextBlock.d.ts +1 -1
  181. package/dist/blocks/builtins/RichTextBlock.js +2 -2
  182. package/dist/blocks/builtins/RichTextBlock.js.map +1 -1
  183. package/dist/blocks/builtins/Search.d.ts +1 -1
  184. package/dist/blocks/builtins/Search.js +9 -7
  185. package/dist/blocks/builtins/Search.js.map +1 -1
  186. package/dist/blocks/builtins/Sections.d.ts +4 -4
  187. package/dist/blocks/builtins/Sections.js +4 -4
  188. package/dist/blocks/builtins/Slider.d.ts +1 -1
  189. package/dist/blocks/builtins/Slider.js +3 -3
  190. package/dist/blocks/builtins/Spacer.d.ts +1 -1
  191. package/dist/blocks/builtins/Spacer.js +2 -2
  192. package/dist/blocks/builtins/SymbolRef.d.ts +1 -1
  193. package/dist/blocks/builtins/SymbolRef.js +31 -17
  194. package/dist/blocks/builtins/SymbolRef.js.map +1 -1
  195. package/dist/blocks/builtins/Team.d.ts +1 -1
  196. package/dist/blocks/builtins/Team.js +4 -4
  197. package/dist/blocks/builtins/Testimonials.d.ts +2 -2
  198. package/dist/blocks/builtins/Testimonials.js +4 -4
  199. package/dist/blocks/builtins/Video.d.ts +2 -2
  200. package/dist/blocks/builtins/Video.js +4 -4
  201. package/dist/blocks/builtins/Video.js.map +1 -1
  202. package/dist/blocks/builtins/WhatsappChat.d.ts +1 -1
  203. package/dist/blocks/builtins/WhatsappChat.js +2 -2
  204. package/dist/blocks/builtins/Widgets.d.ts +12 -12
  205. package/dist/blocks/builtins/Widgets.js +19 -19
  206. package/dist/blocks/builtins/Widgets.js.map +1 -1
  207. package/dist/blocks/builtins/consentEmbed.js +2 -2
  208. package/dist/blocks/builtins/index.d.ts +40 -40
  209. package/dist/blocks/builtins/index.js +40 -40
  210. package/dist/blocks/builtins/lib/submitForm.js +5 -3
  211. package/dist/blocks/builtins/lib/submitForm.js.map +1 -1
  212. package/dist/blocks/context.d.ts +1 -1
  213. package/dist/blocks/customTemplate/definition.d.ts +3 -3
  214. package/dist/blocks/customTemplate/definition.js +6 -6
  215. package/dist/blocks/customTemplate/definition.js.map +1 -1
  216. package/dist/blocks/customTemplate/interpret.js +1 -1
  217. package/dist/blocks/index.d.ts +5 -5
  218. package/dist/blocks/index.js +5 -5
  219. package/dist/blocks/registry.d.ts +17 -7
  220. package/dist/blocks/registry.js +2 -1
  221. package/dist/blocks/registry.js.map +1 -1
  222. package/dist/components/EditBar.js +3 -3
  223. package/dist/components/FeedbackWidget.js +4 -4
  224. package/dist/components/News.d.ts +1 -1
  225. package/dist/components/News.js +50 -37
  226. package/dist/components/News.js.map +1 -1
  227. package/dist/components/PageView.js +11 -8
  228. package/dist/components/PageView.js.map +1 -1
  229. package/dist/components/ResponsiveImage.d.ts +1 -1
  230. package/dist/components/site/SiteFooter.d.ts +1 -1
  231. package/dist/components/site/SiteFooter.js +2 -2
  232. package/dist/config.d.ts +1 -1
  233. package/dist/demo/DemoStudio.js +3 -3
  234. package/dist/demo/demoStore.d.ts +3 -3
  235. package/dist/demo/index.d.ts +2 -2
  236. package/dist/demo/index.js +2 -2
  237. package/dist/editor/EditorProvider.js +1 -1
  238. package/dist/firebase/admin.d.ts +0 -2
  239. package/dist/firebase/admin.js +0 -6
  240. package/dist/firebase/admin.js.map +1 -1
  241. package/dist/firebase/appcheck.d.ts +1 -1
  242. package/dist/firebase/appcheck.js +5 -3
  243. package/dist/firebase/appcheck.js.map +1 -1
  244. package/dist/firebase/client.d.ts +2 -1
  245. package/dist/firebase/client.js +2 -14
  246. package/dist/firebase/client.js.map +1 -1
  247. package/dist/firebase/config.d.ts +31 -0
  248. package/dist/firebase/config.js +39 -0
  249. package/dist/firebase/config.js.map +1 -0
  250. package/dist/firebase/feedback.js +5 -3
  251. package/dist/firebase/feedback.js.map +1 -1
  252. package/dist/i18n/overlay.d.ts +2 -2
  253. package/dist/i18n/overlay.js +6 -4
  254. package/dist/i18n/overlay.js.map +1 -1
  255. package/dist/index.d.ts +45 -44
  256. package/dist/index.js +35 -33
  257. package/dist/index.js.map +1 -1
  258. package/dist/lock/DemoLock.js +1 -1
  259. package/dist/modules/builtins.d.ts +1 -1
  260. package/dist/modules/builtins.js +53 -55
  261. package/dist/modules/builtins.js.map +1 -1
  262. package/dist/modules/consent/ConsentBanner.js +1 -1
  263. package/dist/modules/consent/useConsent.js +1 -1
  264. package/dist/modules/context.d.ts +1 -1
  265. package/dist/modules/contract.d.ts +1 -1
  266. package/dist/modules/defineModule.d.ts +1 -1
  267. package/dist/modules/index.d.ts +9 -9
  268. package/dist/modules/index.js +8 -8
  269. package/dist/modules/overrides.d.ts +1 -1
  270. package/dist/modules/registry.d.ts +2 -7
  271. package/dist/modules/registry.js +2 -1
  272. package/dist/modules/registry.js.map +1 -1
  273. package/dist/modules/shop/blocks/Cart.d.ts +1 -1
  274. package/dist/modules/shop/blocks/Cart.js +6 -6
  275. package/dist/modules/shop/blocks/Checkout.d.ts +1 -1
  276. package/dist/modules/shop/blocks/Checkout.js +6 -6
  277. package/dist/modules/shop/blocks/Donation.d.ts +1 -1
  278. package/dist/modules/shop/blocks/Donation.js +5 -5
  279. package/dist/modules/shop/blocks/OrderStatus.d.ts +1 -1
  280. package/dist/modules/shop/blocks/OrderStatus.js +5 -5
  281. package/dist/modules/shop/blocks/ProductDetail.d.ts +1 -1
  282. package/dist/modules/shop/blocks/ProductDetail.js +8 -8
  283. package/dist/modules/shop/blocks/ProductGrid.d.ts +3 -3
  284. package/dist/modules/shop/blocks/ProductGrid.js +7 -7
  285. package/dist/modules/shop/blocks/ShopCategories.d.ts +1 -1
  286. package/dist/modules/shop/blocks/ShopCategories.js +6 -6
  287. package/dist/modules/shop/index.d.ts +5 -5
  288. package/dist/modules/shop/index.js +5 -5
  289. package/dist/modules/shop/lib.d.ts +2 -2
  290. package/dist/modules/shop/lib.js +18 -13
  291. package/dist/modules/shop/lib.js.map +1 -1
  292. package/dist/modules/shop/module.d.ts +1 -1
  293. package/dist/modules/shop/module.js +9 -9
  294. package/dist/modules/shop/settings.d.ts +18 -50
  295. package/dist/modules/shop/settings.js +16 -16
  296. package/dist/modules/shop/settings.js.map +1 -1
  297. package/dist/modules/shop/strings.js +1 -1
  298. package/dist/modules/shop/types.d.ts +1 -1
  299. package/dist/modules/types.d.ts +2 -2
  300. package/dist/patterns/builtins.d.ts +1 -1
  301. package/dist/patterns/builtins.js +1 -1
  302. package/dist/patterns/index.d.ts +2 -2
  303. package/dist/patterns/index.js +2 -2
  304. package/dist/render/PageRenderer.d.ts +2 -2
  305. package/dist/render/PageRenderer.js +1 -1
  306. package/dist/render/PublishedPage.d.ts +1 -1
  307. package/dist/render/PublishedPage.js +2 -2
  308. package/dist/schema/blocks.d.ts +6793 -15095
  309. package/dist/schema/blocks.js +335 -355
  310. package/dist/schema/blocks.js.map +1 -1
  311. package/dist/schema/customBlocks.d.ts +10 -29
  312. package/dist/schema/customBlocks.js +14 -13
  313. package/dist/schema/customBlocks.js.map +1 -1
  314. package/dist/schema/fields.d.ts +10 -16
  315. package/dist/schema/fields.js +37 -37
  316. package/dist/schema/fields.js.map +1 -1
  317. package/dist/schema/forms.d.ts +62 -111
  318. package/dist/schema/forms.js +17 -17
  319. package/dist/schema/forms.js.map +1 -1
  320. package/dist/schema/index.d.ts +7 -7
  321. package/dist/schema/index.js +7 -7
  322. package/dist/schema/mail.d.ts +39 -87
  323. package/dist/schema/mail.js +4 -4
  324. package/dist/schema/mail.js.map +1 -1
  325. package/dist/schema/pages.d.ts +152 -674
  326. package/dist/schema/pages.js +26 -15
  327. package/dist/schema/pages.js.map +1 -1
  328. package/dist/schema/seo.d.ts +9 -27
  329. package/dist/schema/seo.js +7 -7
  330. package/dist/schema/seo.js.map +1 -1
  331. package/dist/schema/settings.d.ts +218 -1074
  332. package/dist/schema/settings.js +55 -55
  333. package/dist/schema/settings.js.map +1 -1
  334. package/dist/schema/shop.d.ts +470 -1214
  335. package/dist/schema/shop.js +124 -124
  336. package/dist/schema/shop.js.map +1 -1
  337. package/dist/schema/siteConfig.d.ts +73 -597
  338. package/dist/schema/siteConfig.js +17 -17
  339. package/dist/schema/siteConfig.js.map +1 -1
  340. package/dist/schema/symbols.d.ts +34 -191
  341. package/dist/schema/symbols.js +8 -8
  342. package/dist/schema/symbols.js.map +1 -1
  343. package/dist/server/auth.d.ts +17 -0
  344. package/dist/server/auth.js +11 -0
  345. package/dist/server/auth.js.map +1 -0
  346. package/dist/server/bundle.d.ts +15 -6
  347. package/dist/server/bundle.js +5 -1
  348. package/dist/server/bundle.js.map +1 -1
  349. package/dist/server/draft.d.ts +16 -0
  350. package/dist/server/draft.js +12 -0
  351. package/dist/server/draft.js.map +1 -0
  352. package/dist/server/env.js +8 -8
  353. package/dist/server/env.js.map +1 -1
  354. package/dist/server/index.d.ts +10 -8
  355. package/dist/server/index.js +12 -9
  356. package/dist/server/index.js.map +1 -1
  357. package/dist/server/pages.d.ts +14 -7
  358. package/dist/server/pages.js +183 -17
  359. package/dist/server/pages.js.map +1 -1
  360. package/dist/server/revalidate.d.ts +6 -0
  361. package/dist/server/revalidate.js +40 -0
  362. package/dist/server/revalidate.js.map +1 -0
  363. package/dist/server/seo.d.ts +3 -3
  364. package/dist/server/seo.js +1 -1
  365. package/dist/server/shop.d.ts +3 -3
  366. package/dist/server/shop.js +6 -3
  367. package/dist/server/shop.js.map +1 -1
  368. package/dist/settings/useSiteSettings.d.ts +2 -2
  369. package/dist/settings/useSiteSettings.js +48 -28
  370. package/dist/settings/useSiteSettings.js.map +1 -1
  371. package/dist/styles.css +4 -1
  372. package/dist/theme/presets.d.ts +1 -1
  373. package/package.json +35 -34
@@ -1,46 +1,46 @@
1
- import type { BlockDefinition } from "../registry";
1
+ import type { BlockDefinition } from "../registry.js";
2
2
  /**
3
3
  * Alle ingebouwde blokken. AFGELEID van `builtinModules` (de enige bron van waarheid): een nieuw
4
4
  * blok registreer je alleen in zijn module — het verschijnt hier automatisch. Zo kan deze lijst
5
5
  * nooit uit de pas lopen met wat de modules leveren. Klant-blokken komen erbij via `mergeRegistry`.
6
6
  */
7
7
  export declare const builtinBlocks: BlockDefinition[];
8
- export { heroBlock } from "./Hero";
9
- export { richTextBlock } from "./RichTextBlock";
10
- export { imageBlock } from "./ImageBlock";
11
- export { galleryBlock } from "./Gallery";
12
- export { ctaBlock } from "./Cta";
13
- export { faqBlock } from "./Faq";
14
- export { openingHoursBlock } from "./OpeningHours";
15
- export { pricingBlock } from "./Pricing";
16
- export { spacerBlock } from "./Spacer";
17
- export { columnsBlock } from "./Columns";
18
- export { newsListBlock } from "./NewsListBlock";
19
- export { formBlock } from "./FormBlock";
20
- export { testimonialsBlock } from "./Testimonials";
21
- export { teamBlock } from "./Team";
22
- export { agendaBlock } from "./Agenda";
23
- export { searchBlock } from "./Search";
24
- export { featureBlock, countersBlock, logosBlock, timelineBlock } from "./Sections";
25
- export { videoBlock } from "./Video";
26
- export { bannerBlock } from "./Banner";
27
- export { contactBlock, socialBlock } from "./Contact";
28
- export { mapBlock } from "./MapBlock";
29
- export { newsletterBlock } from "./Newsletter";
30
- export { bookingBlock } from "./Booking";
31
- export { buttonsBlock, quoteBlock, dividerBlock } from "./Elements";
32
- export { accordionBlock } from "./Accordion";
33
- export { embedBlock } from "./Embed";
34
- export { withSidebarBlock, tabsBlock } from "./Layout";
35
- export { cardsBlock } from "./Cards";
36
- export { downloadsBlock } from "./Downloads";
37
- export { pdfBlock } from "./PdfBlock";
38
- export { countdownBlock } from "./Countdown";
39
- export { sliderBlock } from "./Slider";
40
- export { whatsappChatBlock } from "./WhatsappChat";
41
- export { beforeAfterBlock } from "./BeforeAfter";
42
- export { portfolioBlock } from "./Portfolio";
43
- export { jobsBlock } from "./Jobs";
44
- export { breadcrumbsBlock } from "./Breadcrumbs";
45
- export { newsWidget, agendaWidget, openingHoursWidget, contactWidget, socialWidget, newsletterWidget, ctaWidget, galleryWidget, testimonialsWidget, cardsWidget, downloadsWidget, countdownWidget, } from "./Widgets";
46
- export { ConsentEmbed } from "./consentEmbed";
8
+ export { heroBlock } from "./Hero.js";
9
+ export { richTextBlock } from "./RichTextBlock.js";
10
+ export { imageBlock } from "./ImageBlock.js";
11
+ export { galleryBlock } from "./Gallery.js";
12
+ export { ctaBlock } from "./Cta.js";
13
+ export { faqBlock } from "./Faq.js";
14
+ export { openingHoursBlock } from "./OpeningHours.js";
15
+ export { pricingBlock } from "./Pricing.js";
16
+ export { spacerBlock } from "./Spacer.js";
17
+ export { columnsBlock } from "./Columns.js";
18
+ export { newsListBlock } from "./NewsListBlock.js";
19
+ export { formBlock } from "./FormBlock.js";
20
+ export { testimonialsBlock } from "./Testimonials.js";
21
+ export { teamBlock } from "./Team.js";
22
+ export { agendaBlock } from "./Agenda.js";
23
+ export { searchBlock } from "./Search.js";
24
+ export { featureBlock, countersBlock, logosBlock, timelineBlock } from "./Sections.js";
25
+ export { videoBlock } from "./Video.js";
26
+ export { bannerBlock } from "./Banner.js";
27
+ export { contactBlock, socialBlock } from "./Contact.js";
28
+ export { mapBlock } from "./MapBlock.js";
29
+ export { newsletterBlock } from "./Newsletter.js";
30
+ export { bookingBlock } from "./Booking.js";
31
+ export { buttonsBlock, quoteBlock, dividerBlock } from "./Elements.js";
32
+ export { accordionBlock } from "./Accordion.js";
33
+ export { embedBlock } from "./Embed.js";
34
+ export { withSidebarBlock, tabsBlock } from "./Layout.js";
35
+ export { cardsBlock } from "./Cards.js";
36
+ export { downloadsBlock } from "./Downloads.js";
37
+ export { pdfBlock } from "./PdfBlock.js";
38
+ export { countdownBlock } from "./Countdown.js";
39
+ export { sliderBlock } from "./Slider.js";
40
+ export { whatsappChatBlock } from "./WhatsappChat.js";
41
+ export { beforeAfterBlock } from "./BeforeAfter.js";
42
+ export { portfolioBlock } from "./Portfolio.js";
43
+ export { jobsBlock } from "./Jobs.js";
44
+ export { breadcrumbsBlock } from "./Breadcrumbs.js";
45
+ export { newsWidget, agendaWidget, openingHoursWidget, contactWidget, socialWidget, newsletterWidget, ctaWidget, galleryWidget, testimonialsWidget, cardsWidget, downloadsWidget, countdownWidget, } from "./Widgets.js";
46
+ export { ConsentEmbed } from "./consentEmbed.js";
@@ -1,4 +1,4 @@
1
- import { builtinModules } from "../../modules/builtins";
1
+ import { builtinModules } from "../../modules/builtins.js";
2
2
  const builtinBlocks = dedupeByType(
3
3
  builtinModules.flatMap((m) => m.blocks ?? [])
4
4
  );
@@ -6,43 +6,43 @@ function dedupeByType(defs) {
6
6
  const seen = /* @__PURE__ */ new Set();
7
7
  return defs.filter((d) => seen.has(d.type) ? false : (seen.add(d.type), true));
8
8
  }
9
- import { heroBlock } from "./Hero";
10
- import { richTextBlock } from "./RichTextBlock";
11
- import { imageBlock } from "./ImageBlock";
12
- import { galleryBlock } from "./Gallery";
13
- import { ctaBlock } from "./Cta";
14
- import { faqBlock } from "./Faq";
15
- import { openingHoursBlock } from "./OpeningHours";
16
- import { pricingBlock } from "./Pricing";
17
- import { spacerBlock } from "./Spacer";
18
- import { columnsBlock } from "./Columns";
19
- import { newsListBlock } from "./NewsListBlock";
20
- import { formBlock } from "./FormBlock";
21
- import { testimonialsBlock } from "./Testimonials";
22
- import { teamBlock } from "./Team";
23
- import { agendaBlock } from "./Agenda";
24
- import { searchBlock } from "./Search";
25
- import { featureBlock, countersBlock, logosBlock, timelineBlock } from "./Sections";
26
- import { videoBlock } from "./Video";
27
- import { bannerBlock } from "./Banner";
28
- import { contactBlock, socialBlock } from "./Contact";
29
- import { mapBlock } from "./MapBlock";
30
- import { newsletterBlock } from "./Newsletter";
31
- import { bookingBlock } from "./Booking";
32
- import { buttonsBlock, quoteBlock, dividerBlock } from "./Elements";
33
- import { accordionBlock } from "./Accordion";
34
- import { embedBlock } from "./Embed";
35
- import { withSidebarBlock, tabsBlock } from "./Layout";
36
- import { cardsBlock } from "./Cards";
37
- import { downloadsBlock } from "./Downloads";
38
- import { pdfBlock } from "./PdfBlock";
39
- import { countdownBlock } from "./Countdown";
40
- import { sliderBlock } from "./Slider";
41
- import { whatsappChatBlock } from "./WhatsappChat";
42
- import { beforeAfterBlock } from "./BeforeAfter";
43
- import { portfolioBlock } from "./Portfolio";
44
- import { jobsBlock } from "./Jobs";
45
- import { breadcrumbsBlock } from "./Breadcrumbs";
9
+ import { heroBlock } from "./Hero.js";
10
+ import { richTextBlock } from "./RichTextBlock.js";
11
+ import { imageBlock } from "./ImageBlock.js";
12
+ import { galleryBlock } from "./Gallery.js";
13
+ import { ctaBlock } from "./Cta.js";
14
+ import { faqBlock } from "./Faq.js";
15
+ import { openingHoursBlock } from "./OpeningHours.js";
16
+ import { pricingBlock } from "./Pricing.js";
17
+ import { spacerBlock } from "./Spacer.js";
18
+ import { columnsBlock } from "./Columns.js";
19
+ import { newsListBlock } from "./NewsListBlock.js";
20
+ import { formBlock } from "./FormBlock.js";
21
+ import { testimonialsBlock } from "./Testimonials.js";
22
+ import { teamBlock } from "./Team.js";
23
+ import { agendaBlock } from "./Agenda.js";
24
+ import { searchBlock } from "./Search.js";
25
+ import { featureBlock, countersBlock, logosBlock, timelineBlock } from "./Sections.js";
26
+ import { videoBlock } from "./Video.js";
27
+ import { bannerBlock } from "./Banner.js";
28
+ import { contactBlock, socialBlock } from "./Contact.js";
29
+ import { mapBlock } from "./MapBlock.js";
30
+ import { newsletterBlock } from "./Newsletter.js";
31
+ import { bookingBlock } from "./Booking.js";
32
+ import { buttonsBlock, quoteBlock, dividerBlock } from "./Elements.js";
33
+ import { accordionBlock } from "./Accordion.js";
34
+ import { embedBlock } from "./Embed.js";
35
+ import { withSidebarBlock, tabsBlock } from "./Layout.js";
36
+ import { cardsBlock } from "./Cards.js";
37
+ import { downloadsBlock } from "./Downloads.js";
38
+ import { pdfBlock } from "./PdfBlock.js";
39
+ import { countdownBlock } from "./Countdown.js";
40
+ import { sliderBlock } from "./Slider.js";
41
+ import { whatsappChatBlock } from "./WhatsappChat.js";
42
+ import { beforeAfterBlock } from "./BeforeAfter.js";
43
+ import { portfolioBlock } from "./Portfolio.js";
44
+ import { jobsBlock } from "./Jobs.js";
45
+ import { breadcrumbsBlock } from "./Breadcrumbs.js";
46
46
  import {
47
47
  newsWidget,
48
48
  agendaWidget,
@@ -56,8 +56,8 @@ import {
56
56
  cardsWidget,
57
57
  downloadsWidget,
58
58
  countdownWidget
59
- } from "./Widgets";
60
- import { ConsentEmbed } from "./consentEmbed";
59
+ } from "./Widgets.js";
60
+ import { ConsentEmbed } from "./consentEmbed.js";
61
61
  export {
62
62
  ConsentEmbed,
63
63
  accordionBlock,
@@ -1,8 +1,10 @@
1
1
  "use client";
2
- import { getFunctions, httpsCallable } from "firebase/functions";
3
- import { getFirebaseApp } from "../../../firebase/client";
4
- import { functionsRegion } from "../../../firebase/region";
2
+ import { functionsRegion } from "../../../firebase/region.js";
5
3
  async function submitFormValues(siteId, formId, values, hp = "") {
4
+ const [{ getFirebaseApp }, { getFunctions, httpsCallable }] = await Promise.all([
5
+ import("../../../firebase/client.js"),
6
+ import("firebase/functions")
7
+ ]);
6
8
  const app = getFirebaseApp();
7
9
  if (!app) throw new Error("Niet beschikbaar.");
8
10
  const fn = httpsCallable(getFunctions(app, functionsRegion()), "submitForm");
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/blocks/builtins/lib/submitForm.ts"],"sourcesContent":["\"use client\";\n\nimport { getFunctions, httpsCallable } from \"firebase/functions\";\nimport { getFirebaseApp } from \"../../../firebase/client\";\nimport { functionsRegion } from \"../../../firebase/region\";\n\n/**\n * Verstuur een formulier-inzending via de `submitForm`-callable — gedeeld door het\n * formulier-blok en het nieuwsbrief-blok (formId-modus), zodat validatie/rate-limiting/\n * notificatie voor beide identiek server-side lopen.\n */\nexport async function submitFormValues(\n siteId: string,\n formId: string,\n values: Record<string, string | boolean>,\n hp = \"\",\n): Promise<void> {\n const app = getFirebaseApp();\n if (!app) throw new Error(\"Niet beschikbaar.\");\n const fn = httpsCallable(getFunctions(app, functionsRegion()), \"submitForm\");\n await fn({ siteId, formId, values, _hp: hp });\n}\n"],"mappings":";AAEA,SAAS,cAAc,qBAAqB;AAC5C,SAAS,sBAAsB;AAC/B,SAAS,uBAAuB;AAOhC,eAAsB,iBACpB,QACA,QACA,QACA,KAAK,IACU;AACf,QAAM,MAAM,eAAe;AAC3B,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,mBAAmB;AAC7C,QAAM,KAAK,cAAc,aAAa,KAAK,gBAAgB,CAAC,GAAG,YAAY;AAC3E,QAAM,GAAG,EAAE,QAAQ,QAAQ,QAAQ,KAAK,GAAG,CAAC;AAC9C;","names":[]}
1
+ {"version":3,"sources":["../../../../src/blocks/builtins/lib/submitForm.ts"],"sourcesContent":["\"use client\";\n\nimport { functionsRegion } from \"../../../firebase/region\";\n\n/**\n * Verstuur een formulier-inzending via de `submitForm`-callable — gedeeld door het\n * formulier-blok en het nieuwsbrief-blok (formId-modus), zodat validatie/rate-limiting/\n * notificatie voor beide identiek server-side lopen.\n */\nexport async function submitFormValues(\n siteId: string,\n formId: string,\n values: Record<string, string | boolean>,\n hp = \"\",\n): Promise<void> {\n // Dynamisch: een bezoeker die nooit een formulier verstuurt, hoeft de SDK niet te downloaden.\n const [{ getFirebaseApp }, { getFunctions, httpsCallable }] = await Promise.all([\n import(\"../../../firebase/client\"),\n import(\"firebase/functions\"),\n ]);\n const app = getFirebaseApp();\n if (!app) throw new Error(\"Niet beschikbaar.\");\n const fn = httpsCallable(getFunctions(app, functionsRegion()), \"submitForm\");\n await fn({ siteId, formId, values, _hp: hp });\n}\n"],"mappings":";AAEA,SAAS,uBAAuB;AAOhC,eAAsB,iBACpB,QACA,QACA,QACA,KAAK,IACU;AAEf,QAAM,CAAC,EAAE,eAAe,GAAG,EAAE,cAAc,cAAc,CAAC,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC9E,OAAO,0BAA0B;AAAA,IACjC,OAAO,oBAAoB;AAAA,EAC7B,CAAC;AACD,QAAM,MAAM,eAAe;AAC3B,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,mBAAmB;AAC7C,QAAM,KAAK,cAAc,aAAa,KAAK,gBAAgB,CAAC,GAAG,YAAY;AAC3E,QAAM,GAAG,EAAE,QAAQ,QAAQ,QAAQ,KAAK,GAAG,CAAC;AAC9C;","names":[]}
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from "react";
2
- import type { BlockRegistry } from "./registry";
2
+ import type { BlockRegistry } from "./registry.js";
3
3
  export declare function RegistryProvider({ registry, children, }: {
4
4
  registry: BlockRegistry;
5
5
  children: ReactNode;
@@ -1,6 +1,6 @@
1
- import { type Field } from "../../schema/fields";
2
- import type { CustomBlock } from "../../schema/customBlocks";
3
- import { type BlockDefinition } from "../registry";
1
+ import { type Field } from "../../schema/fields.js";
2
+ import type { CustomBlock } from "../../schema/customBlocks.js";
3
+ import { type BlockDefinition } from "../registry.js";
4
4
  /** Custom block-document → BlockDefinition (voor mergeRegistry, server én client). */
5
5
  export declare function customBlockToDefinition(def: CustomBlock): BlockDefinition & {
6
6
  customFields: Field[];
@@ -1,9 +1,9 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { z } from "zod";
3
- import { blockBase } from "../../schema/blocks";
4
- import { fieldsToZod, fieldsDefaults } from "../../schema/fields";
5
- import { defineBlock } from "../registry";
6
- import { interpretTemplate, scopeCss } from "./interpret";
2
+ import * as z from "zod/mini";
3
+ import { blockBase } from "../../schema/blocks.js";
4
+ import { fieldsToZod, fieldsDefaults } from "../../schema/fields.js";
5
+ import { defineBlock } from "../registry.js";
6
+ import { interpretTemplate, scopeCss } from "./interpret.js";
7
7
  function CustomBlockRender(def) {
8
8
  const scopedCss = def.css ? scopeCss(def.css, def.type) : "";
9
9
  return function Render({ block }) {
@@ -15,7 +15,7 @@ function CustomBlockRender(def) {
15
15
  };
16
16
  }
17
17
  function customBlockToDefinition(def) {
18
- const valueSchema = z.object({ ...blockBase, _type: z.literal(def.type) }).merge(fieldsToZod(def.fields));
18
+ const valueSchema = z.extend(z.object({ ...blockBase, _type: z.literal(def.type) }), fieldsToZod(def.fields).shape);
19
19
  const definition = defineBlock({
20
20
  type: def.type,
21
21
  schema: valueSchema,
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/customTemplate/definition.tsx"],"sourcesContent":["/**\n * Bouwt een volwaardige BlockDefinition uit een opgeslagen custom block (5.0). Server-safe:\n * de Render interpreteert de veilige template naar HTML (SSR-vriendelijk, geen hooks); de\n * waarden zijn gevalideerd via `fieldsToZod` — runtime-gedefinieerde blokken krijgen dus\n * dezelfde harde validatie als code-blokken. De editor is de generieke FieldsForm: GenericEditor\n * herkent `customFields` op de definitie (zie GenericEditor.tsx).\n */\nimport { z } from \"zod\";\nimport { blockBase } from \"../../schema/blocks\";\nimport { fieldsToZod, fieldsDefaults, type Field } from \"../../schema/fields\";\nimport type { CustomBlock } from \"../../schema/customBlocks\";\nimport { defineBlock, type BlockDefinition, type BlockRenderProps } from \"../registry\";\nimport { interpretTemplate, scopeCss } from \"./interpret\";\n\nfunction CustomBlockRender(def: CustomBlock) {\n const scopedCss = def.css ? scopeCss(def.css, def.type) : \"\";\n return function Render({ block }: BlockRenderProps<Record<string, unknown>>) {\n const html = interpretTemplate(def.template, block);\n return (\n <div data-xicms-cb={def.type} className={`xicms-custom xicms-${def.type}`}>\n {scopedCss ? <style dangerouslySetInnerHTML={{ __html: scopedCss }} /> : null}\n {/* Template is opslag-tijd gesanitized; interpolaties zijn render-tijd ge-escaped. */}\n <div dangerouslySetInnerHTML={{ __html: html }} />\n </div>\n );\n };\n}\n\n/** Custom block-document → BlockDefinition (voor mergeRegistry, server én client). */\nexport function customBlockToDefinition(def: CustomBlock): BlockDefinition & { customFields: Field[] } {\n const valueSchema = z.object({ ...blockBase, _type: z.literal(def.type) }).merge(fieldsToZod(def.fields));\n const definition = defineBlock({\n type: def.type,\n schema: valueSchema,\n Render: CustomBlockRender(def),\n label: def.label,\n icon: def.icon || \"🧩\",\n category: \"content\",\n defaults: () => fieldsDefaults(def.fields),\n }) as BlockDefinition & { customFields: Field[] };\n // De opgeslagen Field-IR meegeven zodat de GenericEditor die direct rendert (incl. showIf/date/\n // repeater-metadata die uit een Zod-schema niet volledig terug te winnen is).\n definition.customFields = def.fields;\n return definition;\n}\n"],"mappings":"AAmBM,SACe,KADf;AAZN,SAAS,SAAS;AAClB,SAAS,iBAAiB;AAC1B,SAAS,aAAa,sBAAkC;AAExD,SAAS,mBAAgE;AACzE,SAAS,mBAAmB,gBAAgB;AAE5C,SAAS,kBAAkB,KAAkB;AAC3C,QAAM,YAAY,IAAI,MAAM,SAAS,IAAI,KAAK,IAAI,IAAI,IAAI;AAC1D,SAAO,SAAS,OAAO,EAAE,MAAM,GAA8C;AAC3E,UAAM,OAAO,kBAAkB,IAAI,UAAU,KAAK;AAClD,WACE,qBAAC,SAAI,iBAAe,IAAI,MAAM,WAAW,sBAAsB,IAAI,IAAI,IACpE;AAAA,kBAAY,oBAAC,WAAM,yBAAyB,EAAE,QAAQ,UAAU,GAAG,IAAK;AAAA,MAEzE,oBAAC,SAAI,yBAAyB,EAAE,QAAQ,KAAK,GAAG;AAAA,OAClD;AAAA,EAEJ;AACF;AAGO,SAAS,wBAAwB,KAA+D;AACrG,QAAM,cAAc,EAAE,OAAO,EAAE,GAAG,WAAW,OAAO,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC,EAAE,MAAM,YAAY,IAAI,MAAM,CAAC;AACxG,QAAM,aAAa,YAAY;AAAA,IAC7B,MAAM,IAAI;AAAA,IACV,QAAQ;AAAA,IACR,QAAQ,kBAAkB,GAAG;AAAA,IAC7B,OAAO,IAAI;AAAA,IACX,MAAM,IAAI,QAAQ;AAAA,IAClB,UAAU;AAAA,IACV,UAAU,MAAM,eAAe,IAAI,MAAM;AAAA,EAC3C,CAAC;AAGD,aAAW,eAAe,IAAI;AAC9B,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/customTemplate/definition.tsx"],"sourcesContent":["/**\n * Bouwt een volwaardige BlockDefinition uit een opgeslagen custom block (5.0). Server-safe:\n * de Render interpreteert de veilige template naar HTML (SSR-vriendelijk, geen hooks); de\n * waarden zijn gevalideerd via `fieldsToZod` — runtime-gedefinieerde blokken krijgen dus\n * dezelfde harde validatie als code-blokken. De editor is de generieke FieldsForm: GenericEditor\n * herkent `customFields` op de definitie (zie GenericEditor.tsx).\n */\nimport * as z from \"zod/mini\";\nimport { blockBase } from \"../../schema/blocks\";\nimport { fieldsToZod, fieldsDefaults, type Field } from \"../../schema/fields\";\nimport type { CustomBlock } from \"../../schema/customBlocks\";\nimport { defineBlock, type BlockDefinition, type BlockRenderProps } from \"../registry\";\nimport { interpretTemplate, scopeCss } from \"./interpret\";\n\nfunction CustomBlockRender(def: CustomBlock) {\n const scopedCss = def.css ? scopeCss(def.css, def.type) : \"\";\n return function Render({ block }: BlockRenderProps<Record<string, unknown>>) {\n const html = interpretTemplate(def.template, block);\n return (\n <div data-xicms-cb={def.type} className={`xicms-custom xicms-${def.type}`}>\n {scopedCss ? <style dangerouslySetInnerHTML={{ __html: scopedCss }} /> : null}\n {/* Template is opslag-tijd gesanitized; interpolaties zijn render-tijd ge-escaped. */}\n <div dangerouslySetInnerHTML={{ __html: html }} />\n </div>\n );\n };\n}\n\n/** Custom block-document → BlockDefinition (voor mergeRegistry, server én client). */\nexport function customBlockToDefinition(def: CustomBlock): BlockDefinition & { customFields: Field[] } {\n // Zod 4 heeft `.merge()` afgeschaft; `z.extend(schema, shape)` is de opvolger.\n const valueSchema = z.extend(z.object({ ...blockBase, _type: z.literal(def.type) }), fieldsToZod(def.fields).shape);\n const definition = defineBlock({\n type: def.type,\n schema: valueSchema,\n Render: CustomBlockRender(def),\n label: def.label,\n icon: def.icon || \"🧩\",\n category: \"content\",\n defaults: () => fieldsDefaults(def.fields),\n }) as BlockDefinition & { customFields: Field[] };\n // De opgeslagen Field-IR meegeven zodat de GenericEditor die direct rendert (incl. showIf/date/\n // repeater-metadata die uit een Zod-schema niet volledig terug te winnen is).\n definition.customFields = def.fields;\n return definition;\n}\n"],"mappings":"AAmBM,SACe,KADf;AAZN,YAAY,OAAO;AACnB,SAAS,iBAAiB;AAC1B,SAAS,aAAa,sBAAkC;AAExD,SAAS,mBAAgE;AACzE,SAAS,mBAAmB,gBAAgB;AAE5C,SAAS,kBAAkB,KAAkB;AAC3C,QAAM,YAAY,IAAI,MAAM,SAAS,IAAI,KAAK,IAAI,IAAI,IAAI;AAC1D,SAAO,SAAS,OAAO,EAAE,MAAM,GAA8C;AAC3E,UAAM,OAAO,kBAAkB,IAAI,UAAU,KAAK;AAClD,WACE,qBAAC,SAAI,iBAAe,IAAI,MAAM,WAAW,sBAAsB,IAAI,IAAI,IACpE;AAAA,kBAAY,oBAAC,WAAM,yBAAyB,EAAE,QAAQ,UAAU,GAAG,IAAK;AAAA,MAEzE,oBAAC,SAAI,yBAAyB,EAAE,QAAQ,KAAK,GAAG;AAAA,OAClD;AAAA,EAEJ;AACF;AAGO,SAAS,wBAAwB,KAA+D;AAErG,QAAM,cAAc,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,WAAW,OAAO,EAAE,QAAQ,IAAI,IAAI,EAAE,CAAC,GAAG,YAAY,IAAI,MAAM,EAAE,KAAK;AAClH,QAAM,aAAa,YAAY;AAAA,IAC7B,MAAM,IAAI;AAAA,IACV,QAAQ;AAAA,IACR,QAAQ,kBAAkB,GAAG;AAAA,IAC7B,OAAO,IAAI;AAAA,IACX,MAAM,IAAI,QAAQ;AAAA,IAClB,UAAU;AAAA,IACV,UAAU,MAAM,eAAe,IAAI,MAAM;AAAA,EAC3C,CAAC;AAGD,aAAW,eAAe,IAAI;AAC9B,SAAO;AACT;","names":[]}
@@ -1,4 +1,4 @@
1
- import { isRichTextKey } from "../../schema/fields";
1
+ import { isRichTextKey } from "../../schema/fields.js";
2
2
  const ESC = { "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" };
3
3
  function escapeHtml(s) {
4
4
  return s.replace(/[&<>"']/g, (c) => ESC[c]);
@@ -2,8 +2,8 @@
2
2
  * @xiwebdesign/xicms-core/blocks — ingebouwde blokken + de registry-API.
3
3
  * Render-componenten zijn server-safe (waar mogelijk); admin-editors zitten in `/admin`.
4
4
  */
5
- export { defineBlock, createRegistry, mergeRegistry, validateBlocks, type BlockDefinition, type BlockRegistry, type BlockRenderProps, type BlockEditorProps, } from "./registry";
6
- export { BlockRenderer } from "./BlockRenderer";
7
- export { RegistryProvider, useRegistry, BlockDataProvider, useBlockData } from "./context";
8
- export { builtinBlocks } from "./builtins";
9
- export * from "./builtins";
5
+ export { defineBlock, createRegistry, mergeRegistry, validateBlocks, type BlockDefinition, type BlockRegistry, type BlockRenderProps, type BlockEditorProps, } from "./registry.js";
6
+ export { BlockRenderer } from "./BlockRenderer.js";
7
+ export { RegistryProvider, useRegistry, BlockDataProvider, useBlockData } from "./context.js";
8
+ export { builtinBlocks } from "./builtins/index.js";
9
+ export * from "./builtins/index.js";
@@ -3,11 +3,11 @@ import {
3
3
  createRegistry,
4
4
  mergeRegistry,
5
5
  validateBlocks
6
- } from "./registry";
7
- import { BlockRenderer } from "./BlockRenderer";
8
- import { RegistryProvider, useRegistry, BlockDataProvider, useBlockData } from "./context";
9
- import { builtinBlocks } from "./builtins";
10
- export * from "./builtins";
6
+ } from "./registry.js";
7
+ import { BlockRenderer } from "./BlockRenderer.js";
8
+ import { RegistryProvider, useRegistry, BlockDataProvider, useBlockData } from "./context.js";
9
+ import { builtinBlocks } from "./builtins/index.js";
10
+ export * from "./builtins/index.js";
11
11
  export {
12
12
  BlockDataProvider,
13
13
  BlockRenderer,
@@ -6,9 +6,18 @@
6
6
  * Pure logica + types (geen "use client"): bruikbaar op server en client.
7
7
  */
8
8
  import type { ComponentType } from "react";
9
- import type { ZodTypeAny, z } from "zod";
10
- import type { BlockBase } from "../schema/blocks";
11
- import type { FieldHints } from "../schema/fields";
9
+ import { type $ZodType } from "zod/v4/core";
10
+ import type { BlockBase } from "../schema/blocks.js";
11
+ import type { FieldHints } from "../schema/fields.js";
12
+ /**
13
+ * Het uitvoertype van een blok-schema, onafhankelijk van de Zod-façade.
14
+ *
15
+ * Core draait op `zod/mini` (zie schema/) omdat de classic-façade niet tree-shaket en ~300 KB aan
16
+ * de publieke bundel toevoegde. De grens hieronder is daarom `$ZodType` uit `zod/v4/core` — de
17
+ * gedeelde bovengrens van BEIDE smaken. Gevolg: een klantrepo mag zijn eigen blok-schema's zowel
18
+ * met `zod` als met `zod/mini` schrijven; `defineBlock` accepteert allebei.
19
+ */
20
+ type InferBlock<S extends $ZodType> = S["_zod"]["output"];
12
21
  export interface BlockRenderProps<T = unknown> {
13
22
  block: T;
14
23
  siteId: string;
@@ -28,15 +37,15 @@ export interface BlockEditorProps<T = unknown> {
28
37
  * - `layout`: een indelingsblok dat andere blokken bevat (kolommen, zijbalk, tabs).
29
38
  */
30
39
  export type BlockCategory = "content" | "widget" | "layout";
31
- export interface BlockDefinition<S extends ZodTypeAny = ZodTypeAny> {
40
+ export interface BlockDefinition<S extends $ZodType = $ZodType> {
32
41
  type: string;
33
42
  schema: S;
34
- Render: ComponentType<BlockRenderProps<z.infer<S>>>;
43
+ Render: ComponentType<BlockRenderProps<InferBlock<S>>>;
35
44
  /**
36
45
  * Admin-editor (lazy/client). Optioneel; ontbreekt = automatische schema-editor (GenericEditor):
37
46
  * die genereert een formulier uit het Zod-schema, dus een blok zonder eigen editor blijft bewerkbaar.
38
47
  */
39
- Editor?: ComponentType<BlockEditorProps<z.infer<S>>>;
48
+ Editor?: ComponentType<BlockEditorProps<InferBlock<S>>>;
40
49
  label: string;
41
50
  icon?: string;
42
51
  /** Groep in het toevoeg-menu (content/widget/layout). Standaard "content". */
@@ -58,7 +67,7 @@ export interface BlockDefinition<S extends ZodTypeAny = ZodTypeAny> {
58
67
  * block-schema zonder `.default()` of `.optional()`. Anders faalt validatie op al opgeslagen
59
68
  * content en wordt die overgeslagen. Met defaults/optioneel blijft oude content gewoon werken.
60
69
  */
61
- export declare function defineBlock<S extends ZodTypeAny>(def: BlockDefinition<S>): BlockDefinition;
70
+ export declare function defineBlock<S extends $ZodType>(def: BlockDefinition<S>): BlockDefinition;
62
71
  export type BlockRegistry = Map<string, BlockDefinition>;
63
72
  /**
64
73
  * Bouwt de opties voor het "blok toevoegen"-menu, gegroepeerd op categorie: eerst gewone blokken,
@@ -81,3 +90,4 @@ export declare function mergeRegistry(base: BlockRegistry, extra: BlockDefinitio
81
90
  * (passthrough) zodat klant-blokken erin mogen; de strikte controle gebeurt hier.
82
91
  */
83
92
  export declare function validateBlocks(blocks: unknown[] | undefined, registry: BlockRegistry): BlockBase[];
93
+ export {};
@@ -1,3 +1,4 @@
1
+ import { safeParse } from "zod/v4/core";
1
2
  function defineBlock(def) {
2
3
  return def;
3
4
  }
@@ -25,7 +26,7 @@ function validateBlocks(blocks, registry) {
25
26
  warn(`onbekend block-type "${String(type)}" overgeslagen (geen registratie).`);
26
27
  continue;
27
28
  }
28
- const res = def.schema.safeParse(raw);
29
+ const res = safeParse(def.schema, raw);
29
30
  if (res.success) out.push(validateNestedBlocks(res.data, registry));
30
31
  else warn(`block "${type}" voldoet niet aan zijn schema en is overgeslagen.`, res.error.issues);
31
32
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/blocks/registry.ts"],"sourcesContent":["/**\n * Block-registry: koppelt een `_type` aan zijn Zod-schema, een (server-safe) Render-component\n * en een optionele (client/admin) Editor. Klant-blokken worden hier ingebracht via `defineBlock`\n * — zo blijft de core klant-onafhankelijk: de klant levert de render-component, core de structuur.\n *\n * Pure logica + types (geen \"use client\"): bruikbaar op server en client.\n */\nimport type { ComponentType } from \"react\";\nimport type { ZodTypeAny, z } from \"zod\";\nimport type { BlockBase } from \"../schema/blocks\";\nimport type { FieldHints } from \"../schema/fields\";\n\nexport interface BlockRenderProps<T = unknown> {\n block: T;\n siteId: string;\n /** \"view\" = publiek; \"preview\" = draft-weergave in de editor. */\n mode?: \"view\" | \"preview\";\n}\n\nexport interface BlockEditorProps<T = unknown> {\n block: T;\n siteId: string;\n onChange: (next: T) => void;\n}\n\n/**\n * Indeling van een block in het toevoeg-menu:\n * - `content` (default): een gewoon blok dat je op de pagina plaatst.\n * - `widget`: een compacte variant die je naast een blok (in een zijbalk/kolom) zet — haalt z'n\n * gegevens uit dezelfde module als de volwaardige versie (bv. \"laatste nieuws\", \"komende agenda\").\n * - `layout`: een indelingsblok dat andere blokken bevat (kolommen, zijbalk, tabs).\n */\nexport type BlockCategory = \"content\" | \"widget\" | \"layout\";\n\nexport interface BlockDefinition<S extends ZodTypeAny = ZodTypeAny> {\n type: string;\n schema: S;\n Render: ComponentType<BlockRenderProps<z.infer<S>>>;\n /**\n * Admin-editor (lazy/client). Optioneel; ontbreekt = automatische schema-editor (GenericEditor):\n * die genereert een formulier uit het Zod-schema, dus een blok zonder eigen editor blijft bewerkbaar.\n */\n Editor?: ComponentType<BlockEditorProps<z.infer<S>>>;\n label: string;\n icon?: string;\n /** Groep in het toevoeg-menu (content/widget/layout). Standaard \"content\". */\n category?: BlockCategory;\n /** Defaultwaarden voor een nieuw block (zonder _key/_type). */\n defaults?: () => Record<string, unknown>;\n /**\n * Optionele hints voor het automatisch gegenereerde formulier (GenericEditor 2.0, 5.0):\n * per (dotted) veldsleutel een verfijning van de uit het Zod-schema afgeleide Field-IR —\n * bv. `{ \"items.date\": { type: \"date\" }, cta: { showIf: { field: \"showCta\" } } }`.\n * Zie `introspectToFields` (admin/lib/zodFields.ts) en `schema/fields.ts`.\n */\n fields?: FieldHints;\n}\n\n/**\n * Registreert een block-type.\n *\n * UPDATE-VEILIGHEID: voeg in een nieuwe versie nooit een VERPLICHT veld toe aan een bestaand\n * block-schema zonder `.default()` of `.optional()`. Anders faalt validatie op al opgeslagen\n * content en wordt die overgeslagen. Met defaults/optioneel blijft oude content gewoon werken.\n */\nexport function defineBlock<S extends ZodTypeAny>(def: BlockDefinition<S>): BlockDefinition {\n // Type-erased return: het schema-type wordt alleen gebruikt om Render/Editor-props te\n // inferreren bij definitie. Daarna behandelen we blokken generiek in de registry.\n return def as unknown as BlockDefinition;\n}\n\nexport type BlockRegistry = Map<string, BlockDefinition>;\n\n/**\n * Bouwt de opties voor het \"blok toevoegen\"-menu, gegroepeerd op categorie: eerst gewone blokken,\n * dan indeling (kolommen/zijbalk/tabs), dan widgets. Widgets/indeling krijgen een suffix zodat de\n * groep duidelijk is in een platte keuzelijst.\n */\nexport function buildBlockAddOptions(defs: Iterable<BlockDefinition>): { value: string; label: string }[] {\n const order: Record<BlockCategory, number> = { content: 0, layout: 1, widget: 2 };\n const suffix: Record<BlockCategory, string> = { content: \"\", layout: \" · indeling\", widget: \" · widget\" };\n return [...defs]\n .map((d) => ({ def: d, cat: d.category ?? \"content\" }))\n .sort((a, b) => order[a.cat] - order[b.cat])\n .map(({ def, cat }) => ({ value: def.type, label: `${def.icon ?? \"▫\"} ${def.label}${suffix[cat]}` }));\n}\n\nexport function createRegistry(defs: BlockDefinition[]): BlockRegistry {\n const m: BlockRegistry = new Map();\n for (const d of defs) m.set(d.type, d);\n return m;\n}\n\nexport function mergeRegistry(base: BlockRegistry, extra: BlockDefinition[]): BlockRegistry {\n const m: BlockRegistry = new Map(base);\n for (const d of extra) m.set(d.type, d);\n return m;\n}\n\n/**\n * Strikte per-type validatie van een blocks-array tegen de registry. Onbekende types en\n * blocks die hun schema niet halen worden weggelaten (defensief — nooit half-rendered content).\n * Gebruikt bij publiceren (server) en vóór renderen.\n *\n * Recursief: geneste blokken in de indelingsblokken (kolommen, \"Met zijbalk\", tabs) worden óók\n * per-type gevalideerd. Hun schema's valideren kinderen bewust alleen als `BlockBaseSchema`\n * (passthrough) zodat klant-blokken erin mogen; de strikte controle gebeurt hier.\n */\nexport function validateBlocks(blocks: unknown[] | undefined, registry: BlockRegistry): BlockBase[] {\n const out: BlockBase[] = [];\n for (const raw of blocks ?? []) {\n const type = (raw as { _type?: unknown } | null)?._type;\n const def = typeof type === \"string\" ? registry.get(type) : undefined;\n if (!def) {\n warn(`onbekend block-type \"${String(type)}\" overgeslagen (geen registratie).`);\n continue;\n }\n const res = def.schema.safeParse(raw);\n if (res.success) out.push(validateNestedBlocks(res.data as BlockBase, registry));\n else warn(`block \"${type}\" voldoet niet aan zijn schema en is overgeslagen.`, res.error.issues);\n }\n return out;\n}\n\n/** Valideert de geneste blok-lijsten van de bekende indelingsvormen (immutable). */\nfunction validateNestedBlocks(block: BlockBase, registry: BlockRegistry): BlockBase {\n const b = block as BlockBase & Record<string, unknown>;\n if (b._type === \"columns\" && Array.isArray(b.columns)) {\n return {\n ...b,\n columns: b.columns.map((col) =>\n col && typeof col === \"object\" && Array.isArray((col as { blocks?: unknown }).blocks)\n ? { ...col, blocks: validateBlocks((col as { blocks: unknown[] }).blocks, registry) }\n : col,\n ),\n };\n }\n if (b._type === \"withSidebar\" && (Array.isArray(b.main) || Array.isArray(b.aside))) {\n return {\n ...b,\n main: Array.isArray(b.main) ? validateBlocks(b.main, registry) : b.main,\n aside: Array.isArray(b.aside) ? validateBlocks(b.aside, registry) : b.aside,\n };\n }\n if (b._type === \"tabs\" && Array.isArray(b.tabs)) {\n return {\n ...b,\n tabs: b.tabs.map((tab) =>\n tab && typeof tab === \"object\" && Array.isArray((tab as { blocks?: unknown }).blocks)\n ? { ...tab, blocks: validateBlocks((tab as { blocks: unknown[] }).blocks, registry) }\n : tab,\n ),\n };\n }\n return block;\n}\n\nfunction warn(msg: string, detail?: unknown): void {\n // Geen stil verlies: log waarom een block niet rendert (helpt bij schema-wijzigingen).\n if (typeof console !== \"undefined\") console.warn(`[xicms] ${msg}`, detail ?? \"\");\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/blocks/registry.ts"],"sourcesContent":["/**\n * Block-registry: koppelt een `_type` aan zijn Zod-schema, een (server-safe) Render-component\n * en een optionele (client/admin) Editor. Klant-blokken worden hier ingebracht via `defineBlock`\n * — zo blijft de core klant-onafhankelijk: de klant levert de render-component, core de structuur.\n *\n * Pure logica + types (geen \"use client\"): bruikbaar op server en client.\n */\nimport type { ComponentType } from \"react\";\nimport { safeParse, type $ZodType } from \"zod/v4/core\";\nimport type { BlockBase } from \"../schema/blocks\";\nimport type { FieldHints } from \"../schema/fields\";\n\n/**\n * Het uitvoertype van een blok-schema, onafhankelijk van de Zod-façade.\n *\n * Core draait op `zod/mini` (zie schema/) omdat de classic-façade niet tree-shaket en ~300 KB aan\n * de publieke bundel toevoegde. De grens hieronder is daarom `$ZodType` uit `zod/v4/core` — de\n * gedeelde bovengrens van BEIDE smaken. Gevolg: een klantrepo mag zijn eigen blok-schema's zowel\n * met `zod` als met `zod/mini` schrijven; `defineBlock` accepteert allebei.\n */\ntype InferBlock<S extends $ZodType> = S[\"_zod\"][\"output\"];\n\nexport interface BlockRenderProps<T = unknown> {\n block: T;\n siteId: string;\n /** \"view\" = publiek; \"preview\" = draft-weergave in de editor. */\n mode?: \"view\" | \"preview\";\n}\n\nexport interface BlockEditorProps<T = unknown> {\n block: T;\n siteId: string;\n onChange: (next: T) => void;\n}\n\n/**\n * Indeling van een block in het toevoeg-menu:\n * - `content` (default): een gewoon blok dat je op de pagina plaatst.\n * - `widget`: een compacte variant die je naast een blok (in een zijbalk/kolom) zet — haalt z'n\n * gegevens uit dezelfde module als de volwaardige versie (bv. \"laatste nieuws\", \"komende agenda\").\n * - `layout`: een indelingsblok dat andere blokken bevat (kolommen, zijbalk, tabs).\n */\nexport type BlockCategory = \"content\" | \"widget\" | \"layout\";\n\nexport interface BlockDefinition<S extends $ZodType = $ZodType> {\n type: string;\n schema: S;\n Render: ComponentType<BlockRenderProps<InferBlock<S>>>;\n /**\n * Admin-editor (lazy/client). Optioneel; ontbreekt = automatische schema-editor (GenericEditor):\n * die genereert een formulier uit het Zod-schema, dus een blok zonder eigen editor blijft bewerkbaar.\n */\n Editor?: ComponentType<BlockEditorProps<InferBlock<S>>>;\n label: string;\n icon?: string;\n /** Groep in het toevoeg-menu (content/widget/layout). Standaard \"content\". */\n category?: BlockCategory;\n /** Defaultwaarden voor een nieuw block (zonder _key/_type). */\n defaults?: () => Record<string, unknown>;\n /**\n * Optionele hints voor het automatisch gegenereerde formulier (GenericEditor 2.0, 5.0):\n * per (dotted) veldsleutel een verfijning van de uit het Zod-schema afgeleide Field-IR —\n * bv. `{ \"items.date\": { type: \"date\" }, cta: { showIf: { field: \"showCta\" } } }`.\n * Zie `introspectToFields` (admin/lib/zodFields.ts) en `schema/fields.ts`.\n */\n fields?: FieldHints;\n}\n\n/**\n * Registreert een block-type.\n *\n * UPDATE-VEILIGHEID: voeg in een nieuwe versie nooit een VERPLICHT veld toe aan een bestaand\n * block-schema zonder `.default()` of `.optional()`. Anders faalt validatie op al opgeslagen\n * content en wordt die overgeslagen. Met defaults/optioneel blijft oude content gewoon werken.\n */\nexport function defineBlock<S extends $ZodType>(def: BlockDefinition<S>): BlockDefinition {\n // Type-erased return: het schema-type wordt alleen gebruikt om Render/Editor-props te\n // inferreren bij definitie. Daarna behandelen we blokken generiek in de registry.\n return def as unknown as BlockDefinition;\n}\n\nexport type BlockRegistry = Map<string, BlockDefinition>;\n\n/**\n * Bouwt de opties voor het \"blok toevoegen\"-menu, gegroepeerd op categorie: eerst gewone blokken,\n * dan indeling (kolommen/zijbalk/tabs), dan widgets. Widgets/indeling krijgen een suffix zodat de\n * groep duidelijk is in een platte keuzelijst.\n */\nexport function buildBlockAddOptions(defs: Iterable<BlockDefinition>): { value: string; label: string }[] {\n const order: Record<BlockCategory, number> = { content: 0, layout: 1, widget: 2 };\n const suffix: Record<BlockCategory, string> = { content: \"\", layout: \" · indeling\", widget: \" · widget\" };\n return [...defs]\n .map((d) => ({ def: d, cat: d.category ?? \"content\" }))\n .sort((a, b) => order[a.cat] - order[b.cat])\n .map(({ def, cat }) => ({ value: def.type, label: `${def.icon ?? \"▫\"} ${def.label}${suffix[cat]}` }));\n}\n\nexport function createRegistry(defs: BlockDefinition[]): BlockRegistry {\n const m: BlockRegistry = new Map();\n for (const d of defs) m.set(d.type, d);\n return m;\n}\n\nexport function mergeRegistry(base: BlockRegistry, extra: BlockDefinition[]): BlockRegistry {\n const m: BlockRegistry = new Map(base);\n for (const d of extra) m.set(d.type, d);\n return m;\n}\n\n/**\n * Strikte per-type validatie van een blocks-array tegen de registry. Onbekende types en\n * blocks die hun schema niet halen worden weggelaten (defensief — nooit half-rendered content).\n * Gebruikt bij publiceren (server) en vóór renderen.\n *\n * Recursief: geneste blokken in de indelingsblokken (kolommen, \"Met zijbalk\", tabs) worden óók\n * per-type gevalideerd. Hun schema's valideren kinderen bewust alleen als `BlockBaseSchema`\n * (passthrough) zodat klant-blokken erin mogen; de strikte controle gebeurt hier.\n */\nexport function validateBlocks(blocks: unknown[] | undefined, registry: BlockRegistry): BlockBase[] {\n const out: BlockBase[] = [];\n for (const raw of blocks ?? []) {\n const type = (raw as { _type?: unknown } | null)?._type;\n const def = typeof type === \"string\" ? registry.get(type) : undefined;\n if (!def) {\n warn(`onbekend block-type \"${String(type)}\" overgeslagen (geen registratie).`);\n continue;\n }\n const res = safeParse(def.schema, raw);\n if (res.success) out.push(validateNestedBlocks(res.data as BlockBase, registry));\n else warn(`block \"${type}\" voldoet niet aan zijn schema en is overgeslagen.`, res.error.issues);\n }\n return out;\n}\n\n/** Valideert de geneste blok-lijsten van de bekende indelingsvormen (immutable). */\nfunction validateNestedBlocks(block: BlockBase, registry: BlockRegistry): BlockBase {\n const b = block as BlockBase & Record<string, unknown>;\n if (b._type === \"columns\" && Array.isArray(b.columns)) {\n return {\n ...b,\n columns: b.columns.map((col) =>\n col && typeof col === \"object\" && Array.isArray((col as { blocks?: unknown }).blocks)\n ? { ...col, blocks: validateBlocks((col as { blocks: unknown[] }).blocks, registry) }\n : col,\n ),\n };\n }\n if (b._type === \"withSidebar\" && (Array.isArray(b.main) || Array.isArray(b.aside))) {\n return {\n ...b,\n main: Array.isArray(b.main) ? validateBlocks(b.main, registry) : b.main,\n aside: Array.isArray(b.aside) ? validateBlocks(b.aside, registry) : b.aside,\n };\n }\n if (b._type === \"tabs\" && Array.isArray(b.tabs)) {\n return {\n ...b,\n tabs: b.tabs.map((tab) =>\n tab && typeof tab === \"object\" && Array.isArray((tab as { blocks?: unknown }).blocks)\n ? { ...tab, blocks: validateBlocks((tab as { blocks: unknown[] }).blocks, registry) }\n : tab,\n ),\n };\n }\n return block;\n}\n\nfunction warn(msg: string, detail?: unknown): void {\n // Geen stil verlies: log waarom een block niet rendert (helpt bij schema-wijzigingen).\n if (typeof console !== \"undefined\") console.warn(`[xicms] ${msg}`, detail ?? \"\");\n}\n"],"mappings":"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","names":[]}
@@ -1,8 +1,8 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useAuth } from "../auth/AuthProvider";
4
- import { canEdit } from "../auth/roles";
5
- import { useEditor } from "../editor/EditorProvider";
3
+ import { useAuth } from "../auth/AuthProvider.js";
4
+ import { canEdit } from "../auth/roles.js";
5
+ import { useEditor } from "../editor/EditorProvider.js";
6
6
  function EditBar() {
7
7
  const { user, role, signOut, demo } = useAuth();
8
8
  const { open, openEditor } = useEditor();
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useCallback, useEffect, useRef, useState } from "react";
4
- import { useAuth } from "../auth/AuthProvider";
5
- import { canEdit } from "../auth/roles";
6
- import { useEditor } from "../editor/EditorProvider";
7
- import { addFeedback, uploadFeedbackShot } from "../firebase/feedback";
4
+ import { useAuth } from "../auth/AuthProvider.js";
5
+ import { canEdit } from "../auth/roles.js";
6
+ import { useEditor } from "../editor/EditorProvider.js";
7
+ import { addFeedback, uploadFeedbackShot } from "../firebase/feedback.js";
8
8
  const ACCENT = "#4f46e5";
9
9
  function FeedbackWidget({ siteId }) {
10
10
  const { user, role } = useAuth();
@@ -1,4 +1,4 @@
1
- import type { NewsArticle } from "../content/types";
1
+ import type { NewsArticle } from "../content/types.js";
2
2
  /**
3
3
  * Lijst van nieuwsartikelen voor de huidige site.
4
4
  * - `live: false` (standaard publiek): één keer ophalen met getDocs → geen per-bezoeker listener
@@ -1,16 +1,14 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useState } from "react";
4
- import { collection, getDocs, limit as fbLimit, onSnapshot, orderBy, query, where } from "firebase/firestore";
5
- import { getDb } from "../firebase/client";
6
- import { useSiteConfig } from "../config";
4
+ import { useSiteConfig } from "../config.js";
7
5
  import DOMPurify from "dompurify";
8
- import { useAuth } from "../auth/AuthProvider";
9
- import { canEdit } from "../auth/roles";
10
- import { useBlockData } from "../blocks/context";
11
- import { isDemoActive, getDemoNews } from "../demo/demoStore";
12
- import { Img } from "../media/ImageContext";
13
- import { jsonLdHtml } from "../blocks/builtins/jsonld";
6
+ import { useAuth } from "../auth/AuthProvider.js";
7
+ import { canEdit } from "../auth/roles.js";
8
+ import { useBlockData } from "../blocks/context.js";
9
+ import { isDemoActive, getDemoNews } from "../demo/demoStore.js";
10
+ import { Img } from "../media/ImageContext.js";
11
+ import { jsonLdHtml } from "../blocks/builtins/jsonld.js";
14
12
  function useNews(opts = {}) {
15
13
  const { siteId } = useSiteConfig();
16
14
  const { role } = useAuth();
@@ -35,35 +33,46 @@ function useNews(opts = {}) {
35
33
  setLoading(false);
36
34
  return;
37
35
  }
38
- const db = getDb();
39
- if (!db) {
40
- setLoading(false);
41
- return;
42
- }
43
- const base = collection(db, "sites", siteId, "news");
44
- const q = onlyPublished ? query(base, where("published", "==", true), orderBy("date", "desc"), fbLimit(cap)) : query(base, orderBy("date", "desc"), fbLimit(cap));
45
- const map = (snap) => setArticles(snap.docs.map((d) => ({ id: d.id, ...d.data() })));
46
- if (!live) {
47
- let active = true;
48
- getDocs(q).then((snap) => {
49
- if (active) {
36
+ let afgebroken = false;
37
+ let unsub;
38
+ void (async () => {
39
+ const [{ getDb }, fs] = await Promise.all([
40
+ import("../firebase/client.js"),
41
+ import("firebase/firestore")
42
+ ]);
43
+ const db = getDb();
44
+ if (!db || afgebroken) {
45
+ setLoading(false);
46
+ return;
47
+ }
48
+ const base = fs.collection(db, "sites", siteId, "news");
49
+ const q = onlyPublished ? fs.query(base, fs.where("published", "==", true), fs.orderBy("date", "desc"), fs.limit(cap)) : fs.query(base, fs.orderBy("date", "desc"), fs.limit(cap));
50
+ const map = (snap) => setArticles(snap.docs.map((d) => ({ id: d.id, ...d.data() })));
51
+ if (!live) {
52
+ try {
53
+ const snap = await fs.getDocs(q);
54
+ if (!afgebroken) {
55
+ map(snap);
56
+ setLoading(false);
57
+ }
58
+ } catch {
59
+ if (!afgebroken) setLoading(false);
60
+ }
61
+ return;
62
+ }
63
+ unsub = fs.onSnapshot(
64
+ q,
65
+ (snap) => {
50
66
  map(snap);
51
67
  setLoading(false);
52
- }
53
- }).catch(() => active && setLoading(false));
54
- return () => {
55
- active = false;
56
- };
57
- }
58
- const unsub = onSnapshot(
59
- q,
60
- (snap) => {
61
- map(snap);
62
- setLoading(false);
63
- },
64
- () => setLoading(false)
65
- );
66
- return () => unsub();
68
+ },
69
+ () => setLoading(false)
70
+ );
71
+ })();
72
+ return () => {
73
+ afgebroken = true;
74
+ unsub?.();
75
+ };
67
76
  }, [siteId, onlyPublished, live, cap, serverNews]);
68
77
  return { articles, loading };
69
78
  }
@@ -107,7 +116,11 @@ function articleBlogPostingJsonLd(article, opts = {}) {
107
116
  }
108
117
  function NewsArticleView({ article, jsonLd = true }) {
109
118
  const { name } = useSiteConfig();
110
- const [html, setHtml] = useState(null);
119
+ const serverNews = useBlockData("news");
120
+ const trusted = Boolean(
121
+ article.bodyHtml && serverNews?.some((a) => a.slug === article.slug && a.bodyHtml === article.bodyHtml)
122
+ );
123
+ const [html, setHtml] = useState(trusted ? article.bodyHtml ?? null : null);
111
124
  useEffect(() => {
112
125
  setHtml(article.bodyHtml ? DOMPurify.sanitize(article.bodyHtml) : null);
113
126
  }, [article.bodyHtml]);