@xiwebdesign/xicms-core 7.30.0 → 8.15.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 (463) hide show
  1. package/dist/XiCMSProvider.js +22 -7
  2. package/dist/XiCMSProvider.js.map +1 -1
  3. package/dist/admin/AdminApp.js +175 -93
  4. package/dist/admin/AdminApp.js.map +1 -1
  5. package/dist/admin/AdminHelp.d.ts +1 -1
  6. package/dist/admin/AdminHelp.js +44 -36
  7. package/dist/admin/AdminHelp.js.map +1 -1
  8. package/dist/admin/CoreVersion.d.ts +6 -3
  9. package/dist/admin/CoreVersion.js +60 -24
  10. package/dist/admin/CoreVersion.js.map +1 -1
  11. package/dist/admin/NewsEditor.d.ts +7 -0
  12. package/dist/admin/NewsEditor.js +117 -75
  13. package/dist/admin/NewsEditor.js.map +1 -1
  14. package/dist/admin/SuperadminPanel.js +1 -1
  15. package/dist/admin/SuperadminPanel.js.map +1 -1
  16. package/dist/admin/ZoekPalet.d.ts +15 -0
  17. package/dist/admin/ZoekPalet.js +123 -0
  18. package/dist/admin/ZoekPalet.js.map +1 -0
  19. package/dist/admin/blockEditors/GenericEditor.js +36 -18
  20. package/dist/admin/blockEditors/GenericEditor.js.map +1 -1
  21. package/dist/admin/blockEditors/StyleEditor.js +37 -3
  22. package/dist/admin/blockEditors/StyleEditor.js.map +1 -1
  23. package/dist/admin/blockEditors/SymbolRefEditor.js +44 -2
  24. package/dist/admin/blockEditors/SymbolRefEditor.js.map +1 -1
  25. package/dist/admin/blockEditors/index.js +154 -73
  26. package/dist/admin/blockEditors/index.js.map +1 -1
  27. package/dist/admin/customBlocks/CustomBlocksPanel.js +18 -7
  28. package/dist/admin/customBlocks/CustomBlocksPanel.js.map +1 -1
  29. package/dist/admin/dashboard/DashboardPanel.js +26 -16
  30. package/dist/admin/dashboard/DashboardPanel.js.map +1 -1
  31. package/dist/admin/editors/RichTextEditor.d.ts +4 -3
  32. package/dist/admin/editors/RichTextEditor.js +19 -56
  33. package/dist/admin/editors/RichTextEditor.js.map +1 -1
  34. package/dist/admin/editors/fontSizeExtension.js +7 -1
  35. package/dist/admin/editors/fontSizeExtension.js.map +1 -1
  36. package/dist/admin/editors/slashMenu.d.ts +18 -0
  37. package/dist/admin/editors/slashMenu.js +34 -0
  38. package/dist/admin/editors/slashMenu.js.map +1 -0
  39. package/dist/admin/editors/useRijkeTekst.d.ts +48 -0
  40. package/dist/admin/editors/useRijkeTekst.js +310 -0
  41. package/dist/admin/editors/useRijkeTekst.js.map +1 -0
  42. package/dist/admin/forms/FormsPanel.d.ts +11 -2
  43. package/dist/admin/forms/FormsPanel.js +218 -65
  44. package/dist/admin/forms/FormsPanel.js.map +1 -1
  45. package/dist/admin/lib/blokInfo.d.ts +17 -0
  46. package/dist/admin/lib/blokInfo.js +80 -0
  47. package/dist/admin/lib/blokInfo.js.map +1 -0
  48. package/dist/admin/lib/foutNaarMens.d.ts +1 -0
  49. package/dist/admin/lib/foutNaarMens.js +22 -0
  50. package/dist/admin/lib/foutNaarMens.js.map +1 -0
  51. package/dist/admin/lib/gewisteVelden.d.ts +13 -0
  52. package/dist/admin/lib/gewisteVelden.js +31 -0
  53. package/dist/admin/lib/gewisteVelden.js.map +1 -0
  54. package/dist/admin/lib/heroHulp.d.ts +11 -0
  55. package/dist/admin/lib/heroHulp.js +18 -0
  56. package/dist/admin/lib/heroHulp.js.map +1 -0
  57. package/dist/admin/lib/kleur.js +2 -3
  58. package/dist/admin/lib/kleur.js.map +1 -1
  59. package/dist/admin/lib/leesbaarheid.d.ts +34 -0
  60. package/dist/admin/lib/leesbaarheid.js +82 -0
  61. package/dist/admin/lib/leesbaarheid.js.map +1 -0
  62. package/dist/admin/lib/lengteAdvies.d.ts +1 -0
  63. package/dist/admin/lib/lengteAdvies.js +16 -0
  64. package/dist/admin/lib/lengteAdvies.js.map +1 -0
  65. package/dist/admin/lib/mediaLijst.d.ts +26 -0
  66. package/dist/admin/lib/mediaLijst.js +42 -0
  67. package/dist/admin/lib/mediaLijst.js.map +1 -0
  68. package/dist/admin/lib/mediaUsage.d.ts +12 -1
  69. package/dist/admin/lib/mediaUsage.js +43 -33
  70. package/dist/admin/lib/mediaUsage.js.map +1 -1
  71. package/dist/admin/lib/menuHulp.d.ts +16 -0
  72. package/dist/admin/lib/menuHulp.js +41 -0
  73. package/dist/admin/lib/menuHulp.js.map +1 -0
  74. package/dist/admin/lib/onopgeslagen.d.ts +10 -0
  75. package/dist/admin/lib/onopgeslagen.js +35 -0
  76. package/dist/admin/lib/onopgeslagen.js.map +1 -0
  77. package/dist/admin/lib/pagesClient.d.ts +55 -2
  78. package/dist/admin/lib/pagesClient.js +126 -28
  79. package/dist/admin/lib/pagesClient.js.map +1 -1
  80. package/dist/admin/lib/paginaGebruik.d.ts +56 -0
  81. package/dist/admin/lib/paginaGebruik.js +109 -0
  82. package/dist/admin/lib/paginaGebruik.js.map +1 -0
  83. package/dist/admin/lib/publicatieCheck.d.ts +25 -0
  84. package/dist/admin/lib/publicatieCheck.js +114 -0
  85. package/dist/admin/lib/publicatieCheck.js.map +1 -0
  86. package/dist/admin/lib/scrollNaarDetail.d.ts +6 -0
  87. package/dist/admin/lib/scrollNaarDetail.js +20 -0
  88. package/dist/admin/lib/scrollNaarDetail.js.map +1 -0
  89. package/dist/admin/lib/symbolsClient.d.ts +10 -0
  90. package/dist/admin/lib/symbolsClient.js +14 -1
  91. package/dist/admin/lib/symbolsClient.js.map +1 -1
  92. package/dist/admin/lib/tekstVeld.d.ts +8 -0
  93. package/dist/admin/lib/tekstVeld.js +10 -0
  94. package/dist/admin/lib/tekstVeld.js.map +1 -0
  95. package/dist/admin/lib/useIsSuperadmin.d.ts +2 -0
  96. package/dist/admin/lib/useIsSuperadmin.js +13 -0
  97. package/dist/admin/lib/useIsSuperadmin.js.map +1 -0
  98. package/dist/admin/lib/veldTaal.d.ts +14 -0
  99. package/dist/admin/lib/veldTaal.js +247 -0
  100. package/dist/admin/lib/veldTaal.js.map +1 -0
  101. package/dist/admin/lib/versieVergelijk.d.ts +17 -0
  102. package/dist/admin/lib/versieVergelijk.js +24 -0
  103. package/dist/admin/lib/versieVergelijk.js.map +1 -0
  104. package/dist/admin/lib/zodFields.js +22 -4
  105. package/dist/admin/lib/zodFields.js.map +1 -1
  106. package/dist/admin/lib/zodFout.d.ts +9 -0
  107. package/dist/admin/lib/zodFout.js +63 -0
  108. package/dist/admin/lib/zodFout.js.map +1 -0
  109. package/dist/admin/media/MediaManager.js +162 -32
  110. package/dist/admin/media/MediaManager.js.map +1 -1
  111. package/dist/admin/media/MediaPicker.d.ts +3 -0
  112. package/dist/admin/media/MediaPicker.js +84 -31
  113. package/dist/admin/media/MediaPicker.js.map +1 -1
  114. package/dist/admin/menu/MenuPanel.js +144 -83
  115. package/dist/admin/menu/MenuPanel.js.map +1 -1
  116. package/dist/admin/navContext.d.ts +3 -0
  117. package/dist/admin/navContext.js +13 -1
  118. package/dist/admin/navContext.js.map +1 -1
  119. package/dist/admin/pages/PageEditor.js +146 -30
  120. package/dist/admin/pages/PageEditor.js.map +1 -1
  121. package/dist/admin/pages/PagesPanel.js +215 -61
  122. package/dist/admin/pages/PagesPanel.js.map +1 -1
  123. package/dist/admin/pages/StarterKiezer.d.ts +12 -0
  124. package/dist/admin/pages/StarterKiezer.js +113 -0
  125. package/dist/admin/pages/StarterKiezer.js.map +1 -0
  126. package/dist/admin/panelRegistry.d.ts +1 -1
  127. package/dist/admin/panelRegistry.js +2 -1
  128. package/dist/admin/panelRegistry.js.map +1 -1
  129. package/dist/admin/patterns/PatternInserter.js +1 -1
  130. package/dist/admin/patterns/PatternInserter.js.map +1 -1
  131. package/dist/admin/settings/BedrijfInstellingen.d.ts +20 -0
  132. package/dist/admin/settings/BedrijfInstellingen.js +144 -0
  133. package/dist/admin/settings/BedrijfInstellingen.js.map +1 -0
  134. package/dist/admin/settings/MailSettings.js +2 -2
  135. package/dist/admin/settings/MailSettings.js.map +1 -1
  136. package/dist/admin/settings/MailTemplates.js +5 -4
  137. package/dist/admin/settings/MailTemplates.js.map +1 -1
  138. package/dist/admin/settings/SettingsPanel.js +120 -78
  139. package/dist/admin/settings/SettingsPanel.js.map +1 -1
  140. package/dist/admin/settings/SnapshotsCard.js +4 -4
  141. package/dist/admin/settings/SnapshotsCard.js.map +1 -1
  142. package/dist/admin/settings/VorigeTerugzetten.d.ts +15 -0
  143. package/dist/admin/settings/VorigeTerugzetten.js +89 -0
  144. package/dist/admin/settings/VorigeTerugzetten.js.map +1 -0
  145. package/dist/admin/shop/CategoriesTab.js +6 -4
  146. package/dist/admin/shop/CategoriesTab.js.map +1 -1
  147. package/dist/admin/shop/DiscountsTab.js +4 -2
  148. package/dist/admin/shop/DiscountsTab.js.map +1 -1
  149. package/dist/admin/shop/OrdersTab.js +57 -19
  150. package/dist/admin/shop/OrdersTab.js.map +1 -1
  151. package/dist/admin/shop/ProductPaneel.js +2 -1
  152. package/dist/admin/shop/ProductPaneel.js.map +1 -1
  153. package/dist/admin/shop/ProductsTab.js +40 -19
  154. package/dist/admin/shop/ProductsTab.js.map +1 -1
  155. package/dist/admin/shop/ShopPanel.js +13 -1
  156. package/dist/admin/shop/ShopPanel.js.map +1 -1
  157. package/dist/admin/shop/ShopSettingsTab.js +27 -1
  158. package/dist/admin/shop/ShopSettingsTab.js.map +1 -1
  159. package/dist/admin/shop/productClient.js +7 -3
  160. package/dist/admin/shop/productClient.js.map +1 -1
  161. package/dist/admin/stats/NietGevonden.d.ts +10 -0
  162. package/dist/admin/stats/NietGevonden.js +78 -0
  163. package/dist/admin/stats/NietGevonden.js.map +1 -0
  164. package/dist/admin/stats/StatsPanel.js +6 -1
  165. package/dist/admin/stats/StatsPanel.js.map +1 -1
  166. package/dist/admin/stats/lib.d.ts +2 -0
  167. package/dist/admin/stats/lib.js.map +1 -1
  168. package/dist/admin/ui/ConfirmDialog.js +10 -1
  169. package/dist/admin/ui/ConfirmDialog.js.map +1 -1
  170. package/dist/admin/ui/Icon.d.ts +34 -0
  171. package/dist/admin/ui/Icon.js +44 -0
  172. package/dist/admin/ui/Icon.js.map +1 -0
  173. package/dist/admin/ui/ImageField.d.ts +15 -0
  174. package/dist/admin/ui/ImageField.js +67 -0
  175. package/dist/admin/ui/ImageField.js.map +1 -0
  176. package/dist/admin/ui/KleurVeld.d.ts +25 -0
  177. package/dist/admin/ui/KleurVeld.js +76 -0
  178. package/dist/admin/ui/KleurVeld.js.map +1 -0
  179. package/dist/admin/ui/LaadStaat.d.ts +21 -0
  180. package/dist/admin/ui/LaadStaat.js +43 -0
  181. package/dist/admin/ui/LaadStaat.js.map +1 -0
  182. package/dist/admin/ui/LeesbaarheidPaneel.d.ts +10 -0
  183. package/dist/admin/ui/LeesbaarheidPaneel.js +68 -0
  184. package/dist/admin/ui/LeesbaarheidPaneel.js.map +1 -0
  185. package/dist/admin/ui/LinkDialog.d.ts +22 -0
  186. package/dist/admin/ui/LinkDialog.js +131 -0
  187. package/dist/admin/ui/LinkDialog.js.map +1 -0
  188. package/dist/admin/ui/LinkVeld.d.ts +14 -0
  189. package/dist/admin/ui/LinkVeld.js +49 -0
  190. package/dist/admin/ui/LinkVeld.js.map +1 -0
  191. package/dist/admin/ui/PreviewLinkResultaat.d.ts +14 -0
  192. package/dist/admin/ui/PreviewLinkResultaat.js +52 -0
  193. package/dist/admin/ui/PreviewLinkResultaat.js.map +1 -0
  194. package/dist/admin/ui/charts.js +5 -5
  195. package/dist/admin/ui/charts.js.map +1 -1
  196. package/dist/admin/ui/primitives.d.ts +16 -6
  197. package/dist/admin/ui/primitives.js +98 -26
  198. package/dist/admin/ui/primitives.js.map +1 -1
  199. package/dist/admin/ui/select.js +5 -2
  200. package/dist/admin/ui/select.js.map +1 -1
  201. package/dist/admin/ui/switch.d.ts +3 -1
  202. package/dist/admin/ui/switch.js +6 -3
  203. package/dist/admin/ui/switch.js.map +1 -1
  204. package/dist/admin/ui/toast.d.ts +2 -1
  205. package/dist/admin/ui/toast.js +17 -11
  206. package/dist/admin/ui/toast.js.map +1 -1
  207. package/dist/admin/visual/BlokKiezer.d.ts +34 -0
  208. package/dist/admin/visual/BlokKiezer.js +225 -0
  209. package/dist/admin/visual/BlokKiezer.js.map +1 -0
  210. package/dist/admin/visual/InlineGereedschap.d.ts +52 -0
  211. package/dist/admin/visual/InlineGereedschap.js +356 -0
  212. package/dist/admin/visual/InlineGereedschap.js.map +1 -0
  213. package/dist/admin/visual/InlineRijkeTekst.d.ts +23 -0
  214. package/dist/admin/visual/InlineRijkeTekst.js +152 -0
  215. package/dist/admin/visual/InlineRijkeTekst.js.map +1 -0
  216. package/dist/admin/visual/VisualEditor.js +273 -125
  217. package/dist/admin/visual/VisualEditor.js.map +1 -1
  218. package/dist/admin.css +1 -1
  219. package/dist/bedrijf/bedrijf.d.ts +36 -0
  220. package/dist/bedrijf/bedrijf.js +110 -0
  221. package/dist/bedrijf/bedrijf.js.map +1 -0
  222. package/dist/blocks/BlockRenderer.js +11 -1
  223. package/dist/blocks/BlockRenderer.js.map +1 -1
  224. package/dist/blocks/blockStyle.d.ts +7 -0
  225. package/dist/blocks/blockStyle.js +16 -3
  226. package/dist/blocks/blockStyle.js.map +1 -1
  227. package/dist/blocks/builtinSchemas.js +6 -0
  228. package/dist/blocks/builtinSchemas.js.map +1 -1
  229. package/dist/blocks/builtins/AgendaRender.d.ts +22 -0
  230. package/dist/blocks/builtins/AgendaRender.js +69 -9
  231. package/dist/blocks/builtins/AgendaRender.js.map +1 -1
  232. package/dist/blocks/builtins/Availability.d.ts +1 -0
  233. package/dist/blocks/builtins/Availability.js +23 -0
  234. package/dist/blocks/builtins/Availability.js.map +1 -0
  235. package/dist/blocks/builtins/AvailabilityRender.d.ts +12 -0
  236. package/dist/blocks/builtins/AvailabilityRender.js +105 -0
  237. package/dist/blocks/builtins/AvailabilityRender.js.map +1 -0
  238. package/dist/blocks/builtins/BeforeAfterRender.js +4 -3
  239. package/dist/blocks/builtins/BeforeAfterRender.js.map +1 -1
  240. package/dist/blocks/builtins/Booking.js +1 -1
  241. package/dist/blocks/builtins/Booking.js.map +1 -1
  242. package/dist/blocks/builtins/BreadcrumbsRender.d.ts +4 -3
  243. package/dist/blocks/builtins/BreadcrumbsRender.js +14 -8
  244. package/dist/blocks/builtins/BreadcrumbsRender.js.map +1 -1
  245. package/dist/blocks/builtins/ColumnsRender.d.ts +1 -1
  246. package/dist/blocks/builtins/ColumnsRender.js +3 -1
  247. package/dist/blocks/builtins/ColumnsRender.js.map +1 -1
  248. package/dist/blocks/builtins/Contact.js +1 -1
  249. package/dist/blocks/builtins/Contact.js.map +1 -1
  250. package/dist/blocks/builtins/ContactRender.d.ts +1 -1
  251. package/dist/blocks/builtins/ContactRender.js +29 -8
  252. package/dist/blocks/builtins/ContactRender.js.map +1 -1
  253. package/dist/blocks/builtins/Cta.js +1 -1
  254. package/dist/blocks/builtins/Cta.js.map +1 -1
  255. package/dist/blocks/builtins/CtaRender.d.ts +1 -1
  256. package/dist/blocks/builtins/CtaRender.js +5 -4
  257. package/dist/blocks/builtins/CtaRender.js.map +1 -1
  258. package/dist/blocks/builtins/Embed.js +1 -1
  259. package/dist/blocks/builtins/Embed.js.map +1 -1
  260. package/dist/blocks/builtins/FormBlock.js +1 -0
  261. package/dist/blocks/builtins/FormBlock.js.map +1 -1
  262. package/dist/blocks/builtins/FormBlockRender.d.ts +6 -0
  263. package/dist/blocks/builtins/FormBlockRender.js +88 -16
  264. package/dist/blocks/builtins/FormBlockRender.js.map +1 -1
  265. package/dist/blocks/builtins/GalleryRender.js +3 -2
  266. package/dist/blocks/builtins/GalleryRender.js.map +1 -1
  267. package/dist/blocks/builtins/Hero.js +1 -1
  268. package/dist/blocks/builtins/Hero.js.map +1 -1
  269. package/dist/blocks/builtins/HeroRender.js +7 -3
  270. package/dist/blocks/builtins/HeroRender.js.map +1 -1
  271. package/dist/blocks/builtins/OpenNowBadge.d.ts +4 -2
  272. package/dist/blocks/builtins/OpenNowBadge.js +6 -6
  273. package/dist/blocks/builtins/OpenNowBadge.js.map +1 -1
  274. package/dist/blocks/builtins/OpeningHoursRender.d.ts +8 -2
  275. package/dist/blocks/builtins/OpeningHoursRender.js +27 -6
  276. package/dist/blocks/builtins/OpeningHoursRender.js.map +1 -1
  277. package/dist/blocks/builtins/PriceList.d.ts +1 -0
  278. package/dist/blocks/builtins/PriceList.js +25 -0
  279. package/dist/blocks/builtins/PriceList.js.map +1 -0
  280. package/dist/blocks/builtins/PriceListRender.d.ts +17 -0
  281. package/dist/blocks/builtins/PriceListRender.js +87 -0
  282. package/dist/blocks/builtins/PriceListRender.js.map +1 -0
  283. package/dist/blocks/builtins/RichTextBlockRender.js +6 -1
  284. package/dist/blocks/builtins/RichTextBlockRender.js.map +1 -1
  285. package/dist/blocks/builtins/SectionHeading.d.ts +1 -0
  286. package/dist/blocks/builtins/SectionHeading.js +14 -0
  287. package/dist/blocks/builtins/SectionHeading.js.map +1 -0
  288. package/dist/blocks/builtins/SectionHeadingRender.d.ts +7 -0
  289. package/dist/blocks/builtins/SectionHeadingRender.js +14 -0
  290. package/dist/blocks/builtins/SectionHeadingRender.js.map +1 -0
  291. package/dist/blocks/builtins/SliderRender.js +3 -2
  292. package/dist/blocks/builtins/SliderRender.js.map +1 -1
  293. package/dist/blocks/builtins/SymbolRef.js +1 -1
  294. package/dist/blocks/builtins/SymbolRef.js.map +1 -1
  295. package/dist/blocks/builtins/TeamRender.js +6 -1
  296. package/dist/blocks/builtins/TeamRender.js.map +1 -1
  297. package/dist/blocks/builtins/Testimonials.js +3 -1
  298. package/dist/blocks/builtins/Testimonials.js.map +1 -1
  299. package/dist/blocks/builtins/TestimonialsRender.js +4 -0
  300. package/dist/blocks/builtins/TestimonialsRender.js.map +1 -1
  301. package/dist/blocks/builtins/WhatsappChatRender.d.ts +1 -1
  302. package/dist/blocks/builtins/WhatsappChatRender.js +1 -1
  303. package/dist/blocks/builtins/WhatsappChatRender.js.map +1 -1
  304. package/dist/blocks/builtins/Widgets.js +2 -2
  305. package/dist/blocks/builtins/Widgets.js.map +1 -1
  306. package/dist/blocks/builtins/WidgetsRender.js +3 -1
  307. package/dist/blocks/builtins/WidgetsRender.js.map +1 -1
  308. package/dist/blocks/builtins/index.d.ts +3 -0
  309. package/dist/blocks/builtins/index.js +6 -0
  310. package/dist/blocks/builtins/index.js.map +1 -1
  311. package/dist/blocks/builtins/lib/autoComplete.d.ts +7 -0
  312. package/dist/blocks/builtins/lib/autoComplete.js +20 -0
  313. package/dist/blocks/builtins/lib/autoComplete.js.map +1 -0
  314. package/dist/blocks/builtins/lib/bookingUrl.d.ts +2 -2
  315. package/dist/blocks/builtins/lib/bookingUrl.js +1 -1
  316. package/dist/blocks/builtins/lib/bookingUrl.js.map +1 -1
  317. package/dist/blocks/builtins/lib/ical.d.ts +24 -0
  318. package/dist/blocks/builtins/lib/ical.js +82 -0
  319. package/dist/blocks/builtins/lib/ical.js.map +1 -0
  320. package/dist/blocks/builtins/lib/vandaag.d.ts +8 -0
  321. package/dist/blocks/builtins/lib/vandaag.js +22 -0
  322. package/dist/blocks/builtins/lib/vandaag.js.map +1 -0
  323. package/dist/blocks/registry.d.ts +6 -0
  324. package/dist/blocks/registry.js.map +1 -1
  325. package/dist/blocks/ui/index.js +1 -0
  326. package/dist/blocks/ui/index.js.map +1 -1
  327. package/dist/components/EditBar.js +2 -4
  328. package/dist/components/EditBar.js.map +1 -1
  329. package/dist/components/News.js +26 -18
  330. package/dist/components/News.js.map +1 -1
  331. package/dist/components/PageView.d.ts +7 -1
  332. package/dist/components/PageView.js +17 -0
  333. package/dist/components/PageView.js.map +1 -1
  334. package/dist/components/ResponsiveImage.js +18 -20
  335. package/dist/components/ResponsiveImage.js.map +1 -1
  336. package/dist/components/site/SiteFooter.d.ts +6 -1
  337. package/dist/components/site/SiteFooter.js +61 -9
  338. package/dist/components/site/SiteFooter.js.map +1 -1
  339. package/dist/components/site/SiteHeader.d.ts +15 -0
  340. package/dist/components/site/SiteHeader.js +70 -0
  341. package/dist/components/site/SiteHeader.js.map +1 -0
  342. package/dist/components/site/SiteNav.d.ts +2 -0
  343. package/dist/components/site/SiteNav.js +29 -5
  344. package/dist/components/site/SiteNav.js.map +1 -1
  345. package/dist/demo/DemoStudio.js +2 -2
  346. package/dist/demo/DemoStudio.js.map +1 -1
  347. package/dist/demo/demoStore.d.ts +13 -0
  348. package/dist/demo/demoStore.js +36 -0
  349. package/dist/demo/demoStore.js.map +1 -1
  350. package/dist/editor/EditorProvider.js +15 -4
  351. package/dist/editor/EditorProvider.js.map +1 -1
  352. package/dist/index.d.ts +4 -1
  353. package/dist/index.js +16 -1
  354. package/dist/index.js.map +1 -1
  355. package/dist/media/ImageContext.d.ts +17 -0
  356. package/dist/media/ImageContext.js +65 -20
  357. package/dist/media/ImageContext.js.map +1 -1
  358. package/dist/media/altInHtml.d.ts +9 -0
  359. package/dist/media/altInHtml.js +17 -0
  360. package/dist/media/altInHtml.js.map +1 -0
  361. package/dist/media/srcset.d.ts +12 -0
  362. package/dist/media/srcset.js +13 -0
  363. package/dist/media/srcset.js.map +1 -0
  364. package/dist/modules/builtins.d.ts +1 -0
  365. package/dist/modules/builtins.js +16 -3
  366. package/dist/modules/builtins.js.map +1 -1
  367. package/dist/modules/shop/blocks/Cart.js +5 -3
  368. package/dist/modules/shop/blocks/Cart.js.map +1 -1
  369. package/dist/modules/shop/blocks/Checkout.js +56 -35
  370. package/dist/modules/shop/blocks/Checkout.js.map +1 -1
  371. package/dist/modules/shop/blocks/Donation.js +4 -4
  372. package/dist/modules/shop/blocks/Donation.js.map +1 -1
  373. package/dist/modules/shop/blocks/ProductDetail.js +19 -3
  374. package/dist/modules/shop/blocks/ProductDetail.js.map +1 -1
  375. package/dist/modules/shop/blocks/ProductGrid.d.ts +3 -1
  376. package/dist/modules/shop/blocks/ProductGrid.js +8 -4
  377. package/dist/modules/shop/blocks/ProductGrid.js.map +1 -1
  378. package/dist/modules/shop/blocks/ShopCategories.js +4 -3
  379. package/dist/modules/shop/blocks/ShopCategories.js.map +1 -1
  380. package/dist/modules/shop/lib.d.ts +4 -0
  381. package/dist/modules/shop/lib.js +14 -0
  382. package/dist/modules/shop/lib.js.map +1 -1
  383. package/dist/modules/shop/settings.d.ts +3 -0
  384. package/dist/modules/shop/settings.js +14 -0
  385. package/dist/modules/shop/settings.js.map +1 -1
  386. package/dist/modules/shop/strings.d.ts +4 -0
  387. package/dist/modules/shop/strings.js +8 -0
  388. package/dist/modules/shop/strings.js.map +1 -1
  389. package/dist/next/envCheck.d.ts +42 -0
  390. package/dist/next/envCheck.js +106 -0
  391. package/dist/next/envCheck.js.map +1 -0
  392. package/dist/next/index.cjs +185 -2
  393. package/dist/next/index.d.ts +2 -0
  394. package/dist/next/index.js +8 -1
  395. package/dist/next/index.js.map +1 -1
  396. package/dist/next/securityHeaders.d.ts +36 -0
  397. package/dist/next/securityHeaders.js +74 -0
  398. package/dist/next/securityHeaders.js.map +1 -0
  399. package/dist/patterns/builtins.d.ts +7 -0
  400. package/dist/patterns/builtins.js +138 -3
  401. package/dist/patterns/builtins.js.map +1 -1
  402. package/dist/releaseNotes.js +140 -0
  403. package/dist/releaseNotes.js.map +1 -1
  404. package/dist/render/PublishedPage.d.ts +2 -1
  405. package/dist/render/PublishedPage.js +10 -4
  406. package/dist/render/PublishedPage.js.map +1 -1
  407. package/dist/schema/blocks.d.ts +470 -0
  408. package/dist/schema/blocks.js +102 -4
  409. package/dist/schema/blocks.js.map +1 -1
  410. package/dist/schema/business.d.ts +117 -0
  411. package/dist/schema/business.js +73 -0
  412. package/dist/schema/business.js.map +1 -0
  413. package/dist/schema/fields.d.ts +2 -1
  414. package/dist/schema/fields.js.map +1 -1
  415. package/dist/schema/forms.d.ts +18 -0
  416. package/dist/schema/forms.js +18 -3
  417. package/dist/schema/forms.js.map +1 -1
  418. package/dist/schema/mail.d.ts +10 -0
  419. package/dist/schema/mail.js +7 -0
  420. package/dist/schema/mail.js.map +1 -1
  421. package/dist/schema/settings.d.ts +101 -0
  422. package/dist/schema/settings.js +24 -3
  423. package/dist/schema/settings.js.map +1 -1
  424. package/dist/schema/shop.d.ts +2 -0
  425. package/dist/schema/shop.js +4 -0
  426. package/dist/schema/shop.js.map +1 -1
  427. package/dist/schema/shopGeld.d.ts +1 -0
  428. package/dist/schema/shopGeld.js +1 -0
  429. package/dist/schema/shopGeld.js.map +1 -1
  430. package/dist/schema/siteConfig.d.ts +68 -1
  431. package/dist/schema/siteConfig.js +7 -2
  432. package/dist/schema/siteConfig.js.map +1 -1
  433. package/dist/server/blockData.d.ts +1 -1
  434. package/dist/server/blockData.js +74 -18
  435. package/dist/server/blockData.js.map +1 -1
  436. package/dist/server/cspRapport.d.ts +20 -0
  437. package/dist/server/cspRapport.js +56 -0
  438. package/dist/server/cspRapport.js.map +1 -0
  439. package/dist/server/fonts.d.ts +3 -0
  440. package/dist/server/fonts.js +39 -0
  441. package/dist/server/fonts.js.map +1 -0
  442. package/dist/server/index.d.ts +3 -0
  443. package/dist/server/index.js +8 -0
  444. package/dist/server/index.js.map +1 -1
  445. package/dist/server/sanitize.js +15 -2
  446. package/dist/server/sanitize.js.map +1 -1
  447. package/dist/settings/useSiteSettings.js +4 -1
  448. package/dist/settings/useSiteSettings.js.map +1 -1
  449. package/dist/starters/starters.d.ts +69 -0
  450. package/dist/starters/starters.js +171 -0
  451. package/dist/starters/starters.js.map +1 -0
  452. package/dist/styles.css +1149 -208
  453. package/dist/theme/color.d.ts +10 -0
  454. package/dist/theme/color.js +17 -1
  455. package/dist/theme/color.js.map +1 -1
  456. package/dist/theme/fontFallback.d.ts +23 -0
  457. package/dist/theme/fontFallback.js +58 -0
  458. package/dist/theme/fontFallback.js.map +1 -0
  459. package/dist/theme/fonts.d.ts +11 -0
  460. package/dist/theme/fonts.js +16 -0
  461. package/dist/theme/fonts.js.map +1 -0
  462. package/dist/version.js +1 -1
  463. package/package.json +6 -4
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/builtins/Contact.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const contactBlock = defineBlock({\n type: \"contact\",\n Render: dynamic(() => import(\"./ContactRender\").then((m) => m.ContactRender)),\n label: \"Contactgegevens\",\n icon: \"📇\",\n defaults: () => ({ heading: \"Contact\", jsonLd: true }),\n});\n\nexport const socialBlock = defineBlock({\n type: \"social\",\n Render: dynamic(() => import(\"./ContactRender\").then((m) => m.SocialRender)),\n label: \"Social-links\",\n icon: \"🔗\",\n defaults: () => ({ items: [{ platform: \"Instagram\", href: \"\" }] }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,eAAe,YAAY;AAAA,EACtC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,iBAAiB,EAAE,KAAK,CAAC,MAAM,EAAE,aAAa,CAAC;AAAA,EAC5E,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,SAAS,WAAW,QAAQ,KAAK;AACtD,CAAC;AAEM,MAAM,cAAc,YAAY;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,iBAAiB,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC;AAAA,EAC3E,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,OAAO,CAAC,EAAE,UAAU,aAAa,MAAM,GAAG,CAAC,EAAE;AAClE,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/builtins/Contact.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const contactBlock = defineBlock({\n type: \"contact\",\n Render: dynamic(() => import(\"./ContactRender\").then((m) => m.ContactRender)),\n label: \"Contactgegevens\",\n icon: \"📇\",\n defaults: () => ({ heading: \"Contact\", jsonLd: true }),\n});\n\nexport const socialBlock = defineBlock({\n type: \"social\",\n Render: dynamic(() => import(\"./ContactRender\").then((m) => m.SocialRender)),\n label: \"Sociale media\",\n icon: \"🔗\",\n defaults: () => ({ items: [{ platform: \"Instagram\", href: \"\" }] }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,eAAe,YAAY;AAAA,EACtC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,iBAAiB,EAAE,KAAK,CAAC,MAAM,EAAE,aAAa,CAAC;AAAA,EAC5E,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,SAAS,WAAW,QAAQ,KAAK;AACtD,CAAC;AAEM,MAAM,cAAc,YAAY;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,iBAAiB,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC;AAAA,EAC3E,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,OAAO,CAAC,EAAE,UAAU,aAAa,MAAM,GAAG,CAAC,EAAE;AAClE,CAAC;","names":[]}
@@ -3,7 +3,7 @@ import type { ContactBlockSchema, SocialBlockSchema } from "../../schema/blocks.
3
3
  import type { BlockRenderProps } from "../registry.js";
4
4
  type Contact = z.infer<typeof ContactBlockSchema>;
5
5
  export declare function contactJsonLd(b: Contact): Record<string, unknown>;
6
- export declare function ContactRender({ block }: BlockRenderProps<Contact>): import("react").JSX.Element;
6
+ export declare function ContactRender({ block, mode }: BlockRenderProps<Contact>): import("react").JSX.Element | null;
7
7
  type Social = z.infer<typeof SocialBlockSchema>;
8
8
  export declare function SocialRender({ block }: BlockRenderProps<Social>): import("react").JSX.Element | null;
9
9
  export {};
@@ -1,6 +1,9 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
3
  import { jsonLdHtml } from "./jsonld.js";
3
4
  import { Heading } from "../ui/index.js";
5
+ import { useMergedSiteConfig } from "../../settings/useSiteSettings.js";
6
+ import { adresRegels, routeLink, telLink } from "../../bedrijf/bedrijf.js";
4
7
  function contactJsonLd(b) {
5
8
  return {
6
9
  "@context": "https://schema.org",
@@ -16,21 +19,39 @@ function contactJsonLd(b) {
16
19
  ...b.geo ? { geo: { "@type": "GeoCoordinates", latitude: b.geo.lat, longitude: b.geo.lng } } : {}
17
20
  };
18
21
  }
19
- function ContactRender({ block }) {
22
+ function ContactRender({ block, mode }) {
23
+ const b = useMergedSiteConfig().business;
24
+ const adres = block.address || adresRegels(b).join(", ");
25
+ const telefoon = block.phone || b?.phone;
26
+ const email = block.email || b?.email;
27
+ const route = !block.address ? routeLink(b) : void 0;
28
+ if (!adres && !telefoon && !email && !block.hours && !block.heading) {
29
+ return mode === "preview" ? /* @__PURE__ */ jsx("p", { className: "xicms-ve__hint", children: "Contact: vul je gegevens \xE9\xE9n keer in bij Instellingen \u2192 Bedrijf, of geef dit blok eigen gegevens." }) : null;
30
+ }
20
31
  return /* @__PURE__ */ jsxs("section", { className: "xicms-contact", children: [
21
32
  block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
22
33
  /* @__PURE__ */ jsxs("dl", { className: "xicms-contact__list", children: [
23
- block.address && /* @__PURE__ */ jsxs("div", { className: "xicms-contact__row", children: [
34
+ adres && /* @__PURE__ */ jsxs("div", { className: "xicms-contact__row", children: [
24
35
  /* @__PURE__ */ jsx("dt", { children: "Adres" }),
25
- /* @__PURE__ */ jsx("dd", { "data-xicms-edit": "address", children: block.address })
36
+ /* @__PURE__ */ jsxs("dd", { children: [
37
+ /* @__PURE__ */ jsx("span", { "data-xicms-edit": block.address ? "address" : void 0, children: adres }),
38
+ route && /* @__PURE__ */ jsxs(Fragment, { children: [
39
+ " \xB7 ",
40
+ /* @__PURE__ */ jsx("a", { href: route, target: "_blank", rel: "noopener noreferrer", children: "Route plannen" })
41
+ ] })
42
+ ] })
26
43
  ] }),
27
- block.phone && /* @__PURE__ */ jsxs("div", { className: "xicms-contact__row", children: [
44
+ telefoon && /* @__PURE__ */ jsxs("div", { className: "xicms-contact__row", children: [
28
45
  /* @__PURE__ */ jsx("dt", { children: "Telefoon" }),
29
- /* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx("a", { href: `tel:${block.phone.replace(/\s+/g, "")}`, "data-xicms-edit": "phone", children: block.phone }) })
46
+ /* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx("a", { href: telLink(telefoon), "data-xicms-edit": block.phone ? "phone" : void 0, children: telefoon }) })
30
47
  ] }),
31
- block.email && /* @__PURE__ */ jsxs("div", { className: "xicms-contact__row", children: [
48
+ email && /* @__PURE__ */ jsxs("div", { className: "xicms-contact__row", children: [
32
49
  /* @__PURE__ */ jsx("dt", { children: "E-mail" }),
33
- /* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx("a", { href: `mailto:${block.email}`, "data-xicms-edit": "email", children: block.email }) })
50
+ /* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx("a", { href: `mailto:${email}`, "data-xicms-edit": block.email ? "email" : void 0, children: email }) })
51
+ ] }),
52
+ !block.phone && b?.whatsapp && /* @__PURE__ */ jsxs("div", { className: "xicms-contact__row", children: [
53
+ /* @__PURE__ */ jsx("dt", { children: "WhatsApp" }),
54
+ /* @__PURE__ */ jsx("dd", { children: /* @__PURE__ */ jsx("a", { href: `https://wa.me/${b.whatsapp.replace(/[^\d]/g, "")}`, target: "_blank", rel: "noopener noreferrer", children: b.whatsapp }) })
34
55
  ] }),
35
56
  block.hours && /* @__PURE__ */ jsxs("div", { className: "xicms-contact__row", children: [
36
57
  /* @__PURE__ */ jsx("dt", { children: "Openingstijden" }),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/builtins/ContactRender.tsx"],"sourcesContent":["import type { z } from \"zod\";\nimport { jsonLdHtml } from \"./jsonld\";\nimport type { ContactBlockSchema, SocialBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { Heading } from \"../ui\";\n\n/* ── Contact ─────────────────────────────────────────────────────────────── */\ntype Contact = z.infer<typeof ContactBlockSchema>;\nexport function contactJsonLd(b: Contact): Record<string, unknown> {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"LocalBusiness\",\n // Gedeeld relatief @id: contact-, openingstijden- en layout-JSON-LD beschrijven hetzelfde\n // bedrijf; zonder @id ziet Google drie conflicterende LocalBusiness-entiteiten per pagina.\n \"@id\": \"#business\",\n // Bewust géén `name: heading` — de blokkop is meestal \"Contact\" en zou als bedrijfsnaam in de\n // samengevoegde #business-entiteit belanden; de naam komt uit de layout-brede businessJsonLd.\n ...(b.address ? { address: b.address } : {}),\n ...(b.phone ? { telephone: b.phone } : {}),\n ...(b.email ? { email: b.email } : {}),\n ...(b.geo ? { geo: { \"@type\": \"GeoCoordinates\", latitude: b.geo.lat, longitude: b.geo.lng } } : {}),\n };\n}\nexport function ContactRender({ block }: BlockRenderProps<Contact>) {\n return (\n <section className=\"xicms-contact\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n <dl className=\"xicms-contact__list\">\n {block.address && (\n <div className=\"xicms-contact__row\">\n <dt>Adres</dt>\n <dd data-xicms-edit=\"address\">{block.address}</dd>\n </div>\n )}\n {block.phone && (\n <div className=\"xicms-contact__row\">\n <dt>Telefoon</dt>\n <dd><a href={`tel:${block.phone.replace(/\\s+/g, \"\")}`} data-xicms-edit=\"phone\">{block.phone}</a></dd>\n </div>\n )}\n {block.email && (\n <div className=\"xicms-contact__row\">\n <dt>E-mail</dt>\n <dd><a href={`mailto:${block.email}`} data-xicms-edit=\"email\">{block.email}</a></dd>\n </div>\n )}\n {block.hours && (\n <div className=\"xicms-contact__row\">\n <dt>Openingstijden</dt>\n <dd data-xicms-edit=\"hours\">{block.hours}</dd>\n </div>\n )}\n </dl>\n {block.jsonLd && (\n <script\n type=\"application/ld+json\"\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: jsonLdHtml(contactJsonLd(block)) }}\n />\n )}\n </section>\n );\n}\n/* ── Social ──────────────────────────────────────────────────────────────── */\ntype Social = z.infer<typeof SocialBlockSchema>;\n\n/**\n * Minimalistische, monochrome merk-iconen (currentColor) — geen icon-dependency nodig.\n * Onbekende platformen vallen terug op de tekstweergave, dus niets breekt.\n */\nfunction SocialIcon({ platform }: { platform: string }) {\n const p = platform.toLowerCase();\n const common = { width: 22, height: 22, viewBox: \"0 0 24 24\", \"aria-hidden\": true } as const;\n if (p.includes(\"instagram\")) {\n return (\n <svg {...common} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\">\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"4.5\" />\n <circle cx=\"12\" cy=\"12\" r=\"3.6\" />\n <circle cx=\"16.7\" cy=\"7.3\" r=\"1.1\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n );\n }\n if (p.includes(\"facebook\")) {\n return (\n <svg {...common} fill=\"currentColor\">\n <path d=\"M13.5 20v-6.2h2.1l.4-2.6h-2.5V9.6c0-.8.3-1.3 1.3-1.3h1.3V6c-.3 0-1-.1-1.9-.1-2 0-3.3 1.2-3.3 3.4v1.9H8.7v2.6h2.2V20h2.6z\" />\n </svg>\n );\n }\n if (p.includes(\"linkedin\")) {\n return (\n <svg {...common} fill=\"currentColor\">\n <circle cx=\"6\" cy=\"6.4\" r=\"1.8\" />\n <rect x=\"4.6\" y=\"9.6\" width=\"2.8\" height=\"9.9\" />\n <path d=\"M10.4 9.6h2.7v1.4c.5-.9 1.6-1.7 3.1-1.7 2.4 0 3.7 1.5 3.7 4.3v5.9h-2.8v-5.4c0-1.5-.6-2.3-1.7-2.3-1.2 0-2.2.8-2.2 2.4v5.3h-2.8V9.6z\" />\n </svg>\n );\n }\n if (p.includes(\"twitter\") || p === \"x\" || p.startsWith(\"x \") || p.includes(\"(x)\")) {\n return (\n <svg {...common} fill=\"currentColor\">\n <path d=\"M4.5 4.5h3.6l4.1 5.6 4.7-5.6h2.6l-6.1 7.2 6.4 8.4h-3.6l-4.4-6-5 6H4.2l6.5-7.7-6.2-7.9z\" />\n </svg>\n );\n }\n if (p.includes(\"youtube\")) {\n return (\n <svg {...common} fill=\"currentColor\">\n <rect x=\"3.2\" y=\"6.2\" width=\"17.6\" height=\"11.6\" rx=\"3.2\" />\n <path d=\"M10.4 9.4v5.2l4.8-2.6z\" fill=\"var(--xicms-surface, #fff)\" />\n </svg>\n );\n }\n if (p.includes(\"whatsapp\")) {\n return (\n <svg {...common} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\">\n <path d=\"M12 4.2a7.8 7.8 0 0 0-6.7 11.8L4.4 19.6l3.7-.9A7.8 7.8 0 1 0 12 4.2z\" />\n <path d=\"M9.3 8.9c.7 2.4 2.6 4.4 5 5l1-1.2 2 1.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n }\n if (p.includes(\"tiktok\")) {\n return (\n <svg {...common} fill=\"currentColor\">\n <path d=\"M14.5 4h2.6c.2 1.7 1.3 3 3 3.3v2.6a6.6 6.6 0 0 1-3.2-1v5.7a5.4 5.4 0 1 1-5.4-5.4c.2 0 .5 0 .7.1v2.8a2.6 2.6 0 1 0 2.3 2.6V4z\" />\n </svg>\n );\n }\n return null;\n}\n\nexport function SocialRender({ block }: BlockRenderProps<Social>) {\n const items = (block.items ?? []).filter((i) => i.href && i.platform);\n if (items.length === 0) return null;\n return (\n <section className=\"xicms-social\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n <ul className=\"xicms-social__list\">\n {items.map((it, i) => {\n // Als functie aangeroepen (geen hooks) zodat `null` echt null is — een JSX-element\n // zou altijd truthy zijn en de tekst-fallback nooit tonen.\n const icon = SocialIcon({ platform: it.platform });\n return (\n <li key={i}>\n <a href={it.href} rel=\"noopener noreferrer\" target=\"_blank\" aria-label={it.platform} title={it.platform} className={icon ? \"xicms-social__iconlink\" : undefined}>\n {icon ?? <span data-xicms-edit={`items.${i}.platform`}>{it.platform}</span>}\n </a>\n </li>\n );\n })}\n </ul>\n </section>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/builtins/ContactRender.tsx"],"sourcesContent":["\"use client\";\n\nimport type { z } from \"zod\";\nimport { jsonLdHtml } from \"./jsonld\";\nimport type { ContactBlockSchema, SocialBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { Heading } from \"../ui\";\nimport { useMergedSiteConfig } from \"../../settings/useSiteSettings\";\nimport { adresRegels, routeLink, telLink } from \"../../bedrijf/bedrijf\";\n\n/* ── Contact ─────────────────────────────────────────────────────────────── */\ntype Contact = z.infer<typeof ContactBlockSchema>;\nexport function contactJsonLd(b: Contact): Record<string, unknown> {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"LocalBusiness\",\n // Gedeeld relatief @id: contact-, openingstijden- en layout-JSON-LD beschrijven hetzelfde\n // bedrijf; zonder @id ziet Google drie conflicterende LocalBusiness-entiteiten per pagina.\n \"@id\": \"#business\",\n // Bewust géén `name: heading` — de blokkop is meestal \"Contact\" en zou als bedrijfsnaam in de\n // samengevoegde #business-entiteit belanden; de naam komt uit de layout-brede businessJsonLd.\n ...(b.address ? { address: b.address } : {}),\n ...(b.phone ? { telephone: b.phone } : {}),\n ...(b.email ? { email: b.email } : {}),\n ...(b.geo ? { geo: { \"@type\": \"GeoCoordinates\", latitude: b.geo.lat, longitude: b.geo.lng } } : {}),\n };\n}\nexport function ContactRender({ block, mode }: BlockRenderProps<Contact>) {\n /**\n * 8.13: een leeg veld valt terug op het bedrijfsprofiel (Instellingen → Bedrijf). Een eigen\n * waarde in het blok wint en blijft op de pagina bewerkbaar; een waarde uit het profiel niet\n * (dan zou je hier iets wijzigen dat elders blijft staan).\n */\n const b = useMergedSiteConfig().business;\n const adres = block.address || adresRegels(b).join(\", \");\n const telefoon = block.phone || b?.phone;\n const email = block.email || b?.email;\n const route = !block.address ? routeLink(b) : undefined;\n if (!adres && !telefoon && !email && !block.hours && !block.heading) {\n return mode === \"preview\" ? <p className=\"xicms-ve__hint\">Contact: vul je gegevens één keer in bij Instellingen → Bedrijf, of geef dit blok eigen gegevens.</p> : null;\n }\n return (\n <section className=\"xicms-contact\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n <dl className=\"xicms-contact__list\">\n {adres && (\n <div className=\"xicms-contact__row\">\n <dt>Adres</dt>\n <dd>\n <span data-xicms-edit={block.address ? \"address\" : undefined}>{adres}</span>\n {route && (\n <>\n {\" · \"}\n <a href={route} target=\"_blank\" rel=\"noopener noreferrer\">Route plannen</a>\n </>\n )}\n </dd>\n </div>\n )}\n {telefoon && (\n <div className=\"xicms-contact__row\">\n <dt>Telefoon</dt>\n <dd><a href={telLink(telefoon)} data-xicms-edit={block.phone ? \"phone\" : undefined}>{telefoon}</a></dd>\n </div>\n )}\n {email && (\n <div className=\"xicms-contact__row\">\n <dt>E-mail</dt>\n <dd><a href={`mailto:${email}`} data-xicms-edit={block.email ? \"email\" : undefined}>{email}</a></dd>\n </div>\n )}\n {!block.phone && b?.whatsapp && (\n <div className=\"xicms-contact__row\">\n <dt>WhatsApp</dt>\n <dd><a href={`https://wa.me/${b.whatsapp.replace(/[^\\d]/g, \"\")}`} target=\"_blank\" rel=\"noopener noreferrer\">{b.whatsapp}</a></dd>\n </div>\n )}\n {block.hours && (\n <div className=\"xicms-contact__row\">\n <dt>Openingstijden</dt>\n <dd data-xicms-edit=\"hours\">{block.hours}</dd>\n </div>\n )}\n </dl>\n {block.jsonLd && (\n <script\n type=\"application/ld+json\"\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: jsonLdHtml(contactJsonLd(block)) }}\n />\n )}\n </section>\n );\n}\n/* ── Social ──────────────────────────────────────────────────────────────── */\ntype Social = z.infer<typeof SocialBlockSchema>;\n\n/**\n * Minimalistische, monochrome merk-iconen (currentColor) — geen icon-dependency nodig.\n * Onbekende platformen vallen terug op de tekstweergave, dus niets breekt.\n */\nfunction SocialIcon({ platform }: { platform: string }) {\n const p = platform.toLowerCase();\n const common = { width: 22, height: 22, viewBox: \"0 0 24 24\", \"aria-hidden\": true } as const;\n if (p.includes(\"instagram\")) {\n return (\n <svg {...common} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\">\n <rect x=\"4\" y=\"4\" width=\"16\" height=\"16\" rx=\"4.5\" />\n <circle cx=\"12\" cy=\"12\" r=\"3.6\" />\n <circle cx=\"16.7\" cy=\"7.3\" r=\"1.1\" fill=\"currentColor\" stroke=\"none\" />\n </svg>\n );\n }\n if (p.includes(\"facebook\")) {\n return (\n <svg {...common} fill=\"currentColor\">\n <path d=\"M13.5 20v-6.2h2.1l.4-2.6h-2.5V9.6c0-.8.3-1.3 1.3-1.3h1.3V6c-.3 0-1-.1-1.9-.1-2 0-3.3 1.2-3.3 3.4v1.9H8.7v2.6h2.2V20h2.6z\" />\n </svg>\n );\n }\n if (p.includes(\"linkedin\")) {\n return (\n <svg {...common} fill=\"currentColor\">\n <circle cx=\"6\" cy=\"6.4\" r=\"1.8\" />\n <rect x=\"4.6\" y=\"9.6\" width=\"2.8\" height=\"9.9\" />\n <path d=\"M10.4 9.6h2.7v1.4c.5-.9 1.6-1.7 3.1-1.7 2.4 0 3.7 1.5 3.7 4.3v5.9h-2.8v-5.4c0-1.5-.6-2.3-1.7-2.3-1.2 0-2.2.8-2.2 2.4v5.3h-2.8V9.6z\" />\n </svg>\n );\n }\n if (p.includes(\"twitter\") || p === \"x\" || p.startsWith(\"x \") || p.includes(\"(x)\")) {\n return (\n <svg {...common} fill=\"currentColor\">\n <path d=\"M4.5 4.5h3.6l4.1 5.6 4.7-5.6h2.6l-6.1 7.2 6.4 8.4h-3.6l-4.4-6-5 6H4.2l6.5-7.7-6.2-7.9z\" />\n </svg>\n );\n }\n if (p.includes(\"youtube\")) {\n return (\n <svg {...common} fill=\"currentColor\">\n <rect x=\"3.2\" y=\"6.2\" width=\"17.6\" height=\"11.6\" rx=\"3.2\" />\n <path d=\"M10.4 9.4v5.2l4.8-2.6z\" fill=\"var(--xicms-surface, #fff)\" />\n </svg>\n );\n }\n if (p.includes(\"whatsapp\")) {\n return (\n <svg {...common} fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.8\">\n <path d=\"M12 4.2a7.8 7.8 0 0 0-6.7 11.8L4.4 19.6l3.7-.9A7.8 7.8 0 1 0 12 4.2z\" />\n <path d=\"M9.3 8.9c.7 2.4 2.6 4.4 5 5l1-1.2 2 1.2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n );\n }\n if (p.includes(\"tiktok\")) {\n return (\n <svg {...common} fill=\"currentColor\">\n <path d=\"M14.5 4h2.6c.2 1.7 1.3 3 3 3.3v2.6a6.6 6.6 0 0 1-3.2-1v5.7a5.4 5.4 0 1 1-5.4-5.4c.2 0 .5 0 .7.1v2.8a2.6 2.6 0 1 0 2.3 2.6V4z\" />\n </svg>\n );\n }\n return null;\n}\n\nexport function SocialRender({ block }: BlockRenderProps<Social>) {\n const items = (block.items ?? []).filter((i) => i.href && i.platform);\n if (items.length === 0) return null;\n return (\n <section className=\"xicms-social\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n <ul className=\"xicms-social__list\">\n {items.map((it, i) => {\n // Als functie aangeroepen (geen hooks) zodat `null` echt null is — een JSX-element\n // zou altijd truthy zijn en de tekst-fallback nooit tonen.\n const icon = SocialIcon({ platform: it.platform });\n return (\n <li key={i}>\n <a href={it.href} rel=\"noopener noreferrer\" target=\"_blank\" aria-label={it.platform} title={it.platform} className={icon ? \"xicms-social__iconlink\" : undefined}>\n {icon ?? <span data-xicms-edit={`items.${i}.platform`}>{it.platform}</span>}\n </a>\n </li>\n );\n })}\n </ul>\n </section>\n );\n}\n"],"mappings":"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","names":[]}
@@ -4,7 +4,7 @@ const ctaBlock = defineBlock({
4
4
  type: "cta",
5
5
  fields: { buttonVariant: { type: "select", options: [{ value: "primary", label: "Primair" }, { value: "secondary", label: "Secundair" }, { value: "outline", label: "Outline" }] } },
6
6
  Render: dynamic(() => import("./CtaRender.js").then((m) => m.CtaRender)),
7
- label: "Call-to-action",
7
+ label: "Oproep met knop",
8
8
  icon: "\u{1F4E3}",
9
9
  defaults: () => ({ title: "Klaar om te starten?", buttonLabel: "Neem contact op", buttonHref: "#contact", buttonVariant: "primary" })
10
10
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/builtins/Cta.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const ctaBlock = defineBlock({\n type: \"cta\",\n fields: { buttonVariant: { type: \"select\", options: [{ value: \"primary\", label: \"Primair\" }, { value: \"secondary\", label: \"Secundair\" }, { value: \"outline\", label: \"Outline\" }] } },\n Render: dynamic(() => import(\"./CtaRender\").then((m) => m.CtaRender)),\n label: \"Call-to-action\",\n icon: \"📣\",\n defaults: () => ({ title: \"Klaar om te starten?\", buttonLabel: \"Neem contact op\", buttonHref: \"#contact\", buttonVariant: \"primary\" }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,WAAW,YAAY;AAAA,EAClC,MAAM;AAAA,EACN,QAAQ,EAAE,eAAe,EAAE,MAAM,UAAU,SAAS,CAAC,EAAE,OAAO,WAAW,OAAO,UAAU,GAAG,EAAE,OAAO,aAAa,OAAO,YAAY,GAAG,EAAE,OAAO,WAAW,OAAO,UAAU,CAAC,EAAE,EAAE;AAAA,EACnL,QAAQ,QAAQ,MAAM,OAAO,aAAa,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC;AAAA,EACpE,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,OAAO,wBAAwB,aAAa,mBAAmB,YAAY,YAAY,eAAe,UAAU;AACrI,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/builtins/Cta.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const ctaBlock = defineBlock({\n type: \"cta\",\n fields: { buttonVariant: { type: \"select\", options: [{ value: \"primary\", label: \"Primair\" }, { value: \"secondary\", label: \"Secundair\" }, { value: \"outline\", label: \"Outline\" }] } },\n Render: dynamic(() => import(\"./CtaRender\").then((m) => m.CtaRender)),\n label: \"Oproep met knop\",\n icon: \"📣\",\n defaults: () => ({ title: \"Klaar om te starten?\", buttonLabel: \"Neem contact op\", buttonHref: \"#contact\", buttonVariant: \"primary\" }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,WAAW,YAAY;AAAA,EAClC,MAAM;AAAA,EACN,QAAQ,EAAE,eAAe,EAAE,MAAM,UAAU,SAAS,CAAC,EAAE,OAAO,WAAW,OAAO,UAAU,GAAG,EAAE,OAAO,aAAa,OAAO,YAAY,GAAG,EAAE,OAAO,WAAW,OAAO,UAAU,CAAC,EAAE,EAAE;AAAA,EACnL,QAAQ,QAAQ,MAAM,OAAO,aAAa,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC;AAAA,EACpE,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,OAAO,wBAAwB,aAAa,mBAAmB,YAAY,YAAY,eAAe,UAAU;AACrI,CAAC;","names":[]}
@@ -2,5 +2,5 @@ import type { z } from "zod";
2
2
  import type { CtaBlockSchema } from "../../schema/blocks.js";
3
3
  import type { BlockRenderProps } from "../registry.js";
4
4
  type Cta = z.infer<typeof CtaBlockSchema>;
5
- export declare function CtaRender({ block }: BlockRenderProps<Cta>): import("react").JSX.Element;
5
+ export declare function CtaRender({ block, mode }: BlockRenderProps<Cta>): import("react").JSX.Element;
6
6
  export {};
@@ -1,7 +1,8 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { VStack, HStack, Card, Heading, Text, Btn } from "../ui/index.js";
4
- function CtaRender({ block }) {
4
+ function CtaRender({ block, mode }) {
5
+ const toon = (label) => Boolean(label?.trim()) || mode === "preview";
5
6
  if (block.sticky) {
6
7
  return /* @__PURE__ */ jsxs(
7
8
  HStack,
@@ -14,7 +15,7 @@ function CtaRender({ block }) {
14
15
  style: { position: "sticky", bottom: 0, zIndex: 30, padding: "0.75rem 1rem", background: "var(--color-background-card)", borderTop: "1px solid var(--color-border)", flexWrap: "wrap" },
15
16
  children: [
16
17
  /* @__PURE__ */ jsx(Text, { weight: "bold", children: block.title || block.text }),
17
- /* @__PURE__ */ jsx(Btn, { label: block.buttonLabel, href: block.buttonHref, variant: block.buttonVariant, size: "md", editField: "buttonLabel" })
18
+ toon(block.buttonLabel) && /* @__PURE__ */ jsx(Btn, { label: block.buttonLabel, href: block.buttonHref, variant: block.buttonVariant, size: "md", editField: "buttonLabel" })
18
19
  ]
19
20
  }
20
21
  );
@@ -29,8 +30,8 @@ function CtaRender({ block }) {
29
30
  block.title && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "title", children: block.title }),
30
31
  block.text && /* @__PURE__ */ jsx(Text, { type: "large", color: "secondary", "data-xicms-edit": "text", children: block.text }),
31
32
  /* @__PURE__ */ jsxs(HStack, { gap: 2, hAlign: "center", style: { flexWrap: "wrap" }, children: [
32
- /* @__PURE__ */ jsx(Btn, { label: block.buttonLabel, href: block.buttonHref, variant: block.buttonVariant, editField: "buttonLabel" }),
33
- block.button2Label && /* @__PURE__ */ jsx(Btn, { label: block.button2Label, href: block.button2Href ?? "#", variant: "outline", editField: "button2Label" })
33
+ toon(block.buttonLabel) && /* @__PURE__ */ jsx(Btn, { label: block.buttonLabel, href: block.buttonHref, variant: block.buttonVariant, editField: "buttonLabel" }),
34
+ block.button2Label?.trim() && /* @__PURE__ */ jsx(Btn, { label: block.button2Label, href: block.button2Href ?? "#", variant: "outline", editField: "button2Label" })
34
35
  ] })
35
36
  ] })
36
37
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/builtins/CtaRender.tsx"],"sourcesContent":["\"use client\";\n\nimport type { z } from \"zod\";\nimport type { CtaBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { VStack, HStack, Card, Heading, Text, Btn } from \"../ui\";\n\ntype Cta = z.infer<typeof CtaBlockSchema>;\n\nexport function CtaRender({ block }: BlockRenderProps<Cta>) {\n if (block.sticky) {\n return (\n <HStack\n gap={3}\n vAlign=\"center\"\n hAlign=\"between\"\n role=\"region\"\n aria-label={block.title || \"Call-to-action\"}\n style={{ position: \"sticky\", bottom: 0, zIndex: 30, padding: \"0.75rem 1rem\", background: \"var(--color-background-card)\", borderTop: \"1px solid var(--color-border)\", flexWrap: \"wrap\" }}\n >\n <Text weight=\"bold\">{block.title || block.text}</Text>\n <Btn label={block.buttonLabel} href={block.buttonHref} variant={block.buttonVariant} size=\"md\" editField=\"buttonLabel\" />\n </HStack>\n );\n }\n return (\n <Card\n padding={6}\n variant={block.backgroundColor ? \"default\" : \"muted\"}\n style={block.backgroundColor ? { background: block.backgroundColor } : undefined}\n >\n <VStack gap={3} hAlign=\"center\" style={{ textAlign: \"center\" }}>\n {block.title && <Heading level={2} data-xicms-edit=\"title\">{block.title}</Heading>}\n {block.text && <Text type=\"large\" color=\"secondary\" data-xicms-edit=\"text\">{block.text}</Text>}\n <HStack gap={2} hAlign=\"center\" style={{ flexWrap: \"wrap\" }}>\n <Btn label={block.buttonLabel} href={block.buttonHref} variant={block.buttonVariant} editField=\"buttonLabel\" />\n {block.button2Label && (\n <Btn label={block.button2Label} href={block.button2Href ?? \"#\"} variant=\"outline\" editField=\"button2Label\" />\n )}\n </HStack>\n </VStack>\n </Card>\n );\n}\n"],"mappings":";AAYM,SAQE,KARF;AAPN,SAAS,QAAQ,QAAQ,MAAM,SAAS,MAAM,WAAW;AAIlD,SAAS,UAAU,EAAE,MAAM,GAA0B;AAC1D,MAAI,MAAM,QAAQ;AAChB,WACE;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,QAAO;AAAA,QACP,QAAO;AAAA,QACP,MAAK;AAAA,QACL,cAAY,MAAM,SAAS;AAAA,QAC3B,OAAO,EAAE,UAAU,UAAU,QAAQ,GAAG,QAAQ,IAAI,SAAS,gBAAgB,YAAY,gCAAgC,WAAW,iCAAiC,UAAU,OAAO;AAAA,QAEtL;AAAA,8BAAC,QAAK,QAAO,QAAQ,gBAAM,SAAS,MAAM,MAAK;AAAA,UAC/C,oBAAC,OAAI,OAAO,MAAM,aAAa,MAAM,MAAM,YAAY,SAAS,MAAM,eAAe,MAAK,MAAK,WAAU,eAAc;AAAA;AAAA;AAAA,IACzH;AAAA,EAEJ;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT,SAAS,MAAM,kBAAkB,YAAY;AAAA,MAC7C,OAAO,MAAM,kBAAkB,EAAE,YAAY,MAAM,gBAAgB,IAAI;AAAA,MAEvE,+BAAC,UAAO,KAAK,GAAG,QAAO,UAAS,OAAO,EAAE,WAAW,SAAS,GAC1D;AAAA,cAAM,SAAS,oBAAC,WAAQ,OAAO,GAAG,mBAAgB,SAAS,gBAAM,OAAM;AAAA,QACvE,MAAM,QAAQ,oBAAC,QAAK,MAAK,SAAQ,OAAM,aAAY,mBAAgB,QAAQ,gBAAM,MAAK;AAAA,QACvF,qBAAC,UAAO,KAAK,GAAG,QAAO,UAAS,OAAO,EAAE,UAAU,OAAO,GACxD;AAAA,8BAAC,OAAI,OAAO,MAAM,aAAa,MAAM,MAAM,YAAY,SAAS,MAAM,eAAe,WAAU,eAAc;AAAA,UAC5G,MAAM,gBACL,oBAAC,OAAI,OAAO,MAAM,cAAc,MAAM,MAAM,eAAe,KAAK,SAAQ,WAAU,WAAU,gBAAe;AAAA,WAE/G;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/builtins/CtaRender.tsx"],"sourcesContent":["\"use client\";\n\nimport type { z } from \"zod\";\nimport type { CtaBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { VStack, HStack, Card, Heading, Text, Btn } from \"../ui\";\n\ntype Cta = z.infer<typeof CtaBlockSchema>;\n\nexport function CtaRender({ block, mode }: BlockRenderProps<Cta>) {\n // 8.10: een knop zonder tekst is voor bezoekers een leeg vlakje. In de editor blijft hij staan,\n // anders kun je hem op de pagina niet meer invullen.\n const toon = (label?: string) => Boolean(label?.trim()) || mode === \"preview\";\n if (block.sticky) {\n return (\n <HStack\n gap={3}\n vAlign=\"center\"\n hAlign=\"between\"\n role=\"region\"\n aria-label={block.title || \"Call-to-action\"}\n style={{ position: \"sticky\", bottom: 0, zIndex: 30, padding: \"0.75rem 1rem\", background: \"var(--color-background-card)\", borderTop: \"1px solid var(--color-border)\", flexWrap: \"wrap\" }}\n >\n <Text weight=\"bold\">{block.title || block.text}</Text>\n {toon(block.buttonLabel) && <Btn label={block.buttonLabel} href={block.buttonHref} variant={block.buttonVariant} size=\"md\" editField=\"buttonLabel\" />}\n </HStack>\n );\n }\n return (\n <Card\n padding={6}\n variant={block.backgroundColor ? \"default\" : \"muted\"}\n style={block.backgroundColor ? { background: block.backgroundColor } : undefined}\n >\n <VStack gap={3} hAlign=\"center\" style={{ textAlign: \"center\" }}>\n {block.title && <Heading level={2} data-xicms-edit=\"title\">{block.title}</Heading>}\n {block.text && <Text type=\"large\" color=\"secondary\" data-xicms-edit=\"text\">{block.text}</Text>}\n <HStack gap={2} hAlign=\"center\" style={{ flexWrap: \"wrap\" }}>\n {toon(block.buttonLabel) && <Btn label={block.buttonLabel} href={block.buttonHref} variant={block.buttonVariant} editField=\"buttonLabel\" />}\n {block.button2Label?.trim() && (\n <Btn label={block.button2Label} href={block.button2Href ?? \"#\"} variant=\"outline\" editField=\"button2Label\" />\n )}\n </HStack>\n </VStack>\n </Card>\n );\n}\n"],"mappings":";AAeM,SAQE,KARF;AAVN,SAAS,QAAQ,QAAQ,MAAM,SAAS,MAAM,WAAW;AAIlD,SAAS,UAAU,EAAE,OAAO,KAAK,GAA0B;AAGhE,QAAM,OAAO,CAAC,UAAmB,QAAQ,OAAO,KAAK,CAAC,KAAK,SAAS;AACpE,MAAI,MAAM,QAAQ;AAChB,WACE;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,QAAO;AAAA,QACP,QAAO;AAAA,QACP,MAAK;AAAA,QACL,cAAY,MAAM,SAAS;AAAA,QAC3B,OAAO,EAAE,UAAU,UAAU,QAAQ,GAAG,QAAQ,IAAI,SAAS,gBAAgB,YAAY,gCAAgC,WAAW,iCAAiC,UAAU,OAAO;AAAA,QAEtL;AAAA,8BAAC,QAAK,QAAO,QAAQ,gBAAM,SAAS,MAAM,MAAK;AAAA,UAC9C,KAAK,MAAM,WAAW,KAAK,oBAAC,OAAI,OAAO,MAAM,aAAa,MAAM,MAAM,YAAY,SAAS,MAAM,eAAe,MAAK,MAAK,WAAU,eAAc;AAAA;AAAA;AAAA,IACrJ;AAAA,EAEJ;AACA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,SAAS;AAAA,MACT,SAAS,MAAM,kBAAkB,YAAY;AAAA,MAC7C,OAAO,MAAM,kBAAkB,EAAE,YAAY,MAAM,gBAAgB,IAAI;AAAA,MAEvE,+BAAC,UAAO,KAAK,GAAG,QAAO,UAAS,OAAO,EAAE,WAAW,SAAS,GAC1D;AAAA,cAAM,SAAS,oBAAC,WAAQ,OAAO,GAAG,mBAAgB,SAAS,gBAAM,OAAM;AAAA,QACvE,MAAM,QAAQ,oBAAC,QAAK,MAAK,SAAQ,OAAM,aAAY,mBAAgB,QAAQ,gBAAM,MAAK;AAAA,QACvF,qBAAC,UAAO,KAAK,GAAG,QAAO,UAAS,OAAO,EAAE,UAAU,OAAO,GACvD;AAAA,eAAK,MAAM,WAAW,KAAK,oBAAC,OAAI,OAAO,MAAM,aAAa,MAAM,MAAM,YAAY,SAAS,MAAM,eAAe,WAAU,eAAc;AAAA,UACxI,MAAM,cAAc,KAAK,KACxB,oBAAC,OAAI,OAAO,MAAM,cAAc,MAAM,MAAM,eAAe,KAAK,SAAQ,WAAU,WAAU,gBAAe;AAAA,WAE/G;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -3,7 +3,7 @@ import { defineBlock } from "../registry.js";
3
3
  const embedBlock = defineBlock({
4
4
  type: "embed",
5
5
  Render: dynamic(() => import("./EmbedRender.js").then((m) => m.EmbedRender)),
6
- label: "Embed (iframe)",
6
+ label: "Externe inhoud (insluiten)",
7
7
  icon: "\u{1F9E9}",
8
8
  defaults: () => ({ url: "", height: 420, consentGated: true })
9
9
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/builtins/Embed.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const embedBlock = defineBlock({\n type: \"embed\",\n Render: dynamic(() => import(\"./EmbedRender\").then((m) => m.EmbedRender)),\n label: \"Embed (iframe)\",\n icon: \"🧩\",\n defaults: () => ({ url: \"\", height: 420, consentGated: true }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,aAAa,YAAY;AAAA,EACpC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,eAAe,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC;AAAA,EACxE,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,KAAK,IAAI,QAAQ,KAAK,cAAc,KAAK;AAC9D,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/builtins/Embed.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const embedBlock = defineBlock({\n type: \"embed\",\n Render: dynamic(() => import(\"./EmbedRender\").then((m) => m.EmbedRender)),\n label: \"Externe inhoud (insluiten)\",\n icon: \"🧩\",\n defaults: () => ({ url: \"\", height: 420, consentGated: true }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,aAAa,YAAY;AAAA,EACpC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,eAAe,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC;AAAA,EACxE,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,KAAK,IAAI,QAAQ,KAAK,cAAc,KAAK;AAC9D,CAAC;","names":[]}
@@ -5,6 +5,7 @@ const formBlock = defineBlock({
5
5
  Render: dynamic(() => import("./FormBlockRender.js").then((m) => m.FormRender)),
6
6
  label: "Formulier",
7
7
  icon: "\u2709\uFE0F",
8
+ essentieel: "Bezoekers kunnen dit formulier dan niet meer invullen; je ontvangt geen berichten meer via deze pagina.",
8
9
  defaults: () => ({ formId: "" })
9
10
  });
10
11
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/builtins/FormBlock.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const formBlock = defineBlock({\n type: \"form\",\n Render: dynamic(() => import(\"./FormBlockRender\").then((m) => m.FormRender)),\n label: \"Formulier\",\n icon: \"✉️\",\n defaults: () => ({ formId: \"\" }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,YAAY,YAAY;AAAA,EACnC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,mBAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC;AAAA,EAC3E,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,QAAQ,GAAG;AAChC,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/builtins/FormBlock.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const formBlock = defineBlock({\n type: \"form\",\n Render: dynamic(() => import(\"./FormBlockRender\").then((m) => m.FormRender)),\n label: \"Formulier\",\n icon: \"✉️\",\n essentieel: \"Bezoekers kunnen dit formulier dan niet meer invullen; je ontvangt geen berichten meer via deze pagina.\",\n defaults: () => ({ formId: \"\" }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,YAAY,YAAY;AAAA,EACnC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,mBAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC;AAAA,EAC3E,OAAO;AAAA,EACP,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,UAAU,OAAO,EAAE,QAAQ,GAAG;AAChC,CAAC;","names":[]}
@@ -2,5 +2,11 @@ import type { z } from "zod";
2
2
  import type { FormBlockSchema } from "../../schema/blocks.js";
3
3
  import type { BlockRenderProps } from "../registry.js";
4
4
  type FormBlk = z.infer<typeof FormBlockSchema>;
5
+ /** Voorbeeldformulier voor de demo wanneer er geen specifieke definitie is geregistreerd. */
6
+ /**
7
+ * Een begrijpelijke melding per oorzaak (8.1). Eerst kreeg de bezoeker bij élke fout "Versturen
8
+ * mislukt", ook als hij alleen een verplicht veld vergat of te vaak verstuurde.
9
+ */
10
+ export declare function foutmeldingVoor(err: unknown): string;
5
11
  export declare function FormRender({ block, siteId, mode }: BlockRenderProps<FormBlk>): import("react").JSX.Element;
6
12
  export {};
@@ -1,8 +1,10 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useState, useRef } from "react";
4
+ import { isVeiligPad } from "../../schema/forms.js";
4
5
  import { useBlockData } from "../context.js";
5
6
  import { submitFormValues } from "./lib/submitForm.js";
7
+ import { autoCompleteVoor } from "./lib/autoComplete.js";
6
8
  import { trackEvent } from "../../components/PageView.js";
7
9
  import { isDemoActive, getDemoForm } from "../../demo/demoStore.js";
8
10
  import { useSiteConfig } from "../../config.js";
@@ -10,9 +12,20 @@ import { TextInput } from "@astryxdesign/core/TextInput";
10
12
  import { TextArea } from "@astryxdesign/core/TextArea";
11
13
  import { Selector } from "@astryxdesign/core/Selector";
12
14
  import { CheckboxInput } from "@astryxdesign/core/CheckboxInput";
15
+ import { RadioList, RadioListItem } from "@astryxdesign/core/RadioList";
13
16
  import { Spinner } from "@astryxdesign/core/Spinner";
14
17
  import { Button } from "@astryxdesign/core/Button";
15
18
  import { VStack, Card, Heading, Text } from "../ui/index.js";
19
+ function foutmeldingVoor(err) {
20
+ const code = String(err?.code ?? "");
21
+ const message = String(err?.message ?? "");
22
+ if (code.endsWith("invalid-argument") && message && !/^ongeldige invoer/i.test(message)) return message;
23
+ if (code.endsWith("resource-exhausted")) return "Je hebt het formulier net al een paar keer verstuurd. Probeer het over een minuut opnieuw.";
24
+ if (code.endsWith("unavailable") || typeof navigator !== "undefined" && navigator.onLine === false) {
25
+ return "Geen verbinding. Controleer je internet en probeer het opnieuw.";
26
+ }
27
+ return "Versturen mislukt. Probeer het later opnieuw.";
28
+ }
16
29
  const DEMO_FALLBACK_FORM = {
17
30
  name: "Contact",
18
31
  submitLabel: "Versturen",
@@ -27,6 +40,7 @@ function FormRender({ block, siteId, mode }) {
27
40
  const siteMode = useSiteConfig().mode;
28
41
  const serverForms = useBlockData("forms");
29
42
  const serverDef = serverForms?.[block.formId] ?? null;
43
+ const serverZegtOntbreekt = serverForms !== void 0 && serverForms !== null && block.formId in serverForms && serverForms[block.formId] === null;
30
44
  const [def, setDef] = useState(serverDef);
31
45
  const [unavailable, setUnavailable] = useState(false);
32
46
  const [values, setValues] = useState({});
@@ -46,6 +60,16 @@ function FormRender({ block, siteId, mode }) {
46
60
  return;
47
61
  }
48
62
  if (serverDef) return;
63
+ if (serverZegtOntbreekt) {
64
+ const reg = getDemoForm(siteId, block.formId) ?? (siteMode === "demo" ? DEMO_FALLBACK_FORM : null);
65
+ if (reg) {
66
+ setDef(reg);
67
+ setLocalOnly(true);
68
+ } else {
69
+ setUnavailable(true);
70
+ }
71
+ return;
72
+ }
49
73
  void (async () => {
50
74
  const [{ getDb }, { doc, getDoc }] = await Promise.all([
51
75
  import("../../firebase/client.js"),
@@ -70,7 +94,7 @@ function FormRender({ block, siteId, mode }) {
70
94
  setUnavailable(true);
71
95
  }
72
96
  })();
73
- }, [demo, siteId, block.formId, siteMode, serverDef]);
97
+ }, [demo, siteId, block.formId, siteMode, serverDef, serverZegtOntbreekt]);
74
98
  if (unavailable) {
75
99
  return /* @__PURE__ */ jsx(Card, { padding: 4, variant: "muted", children: /* @__PURE__ */ jsxs(Text, { children: [
76
100
  block.heading ? `${block.heading}: ` : "",
@@ -93,15 +117,15 @@ function FormRender({ block, siteId, mode }) {
93
117
  try {
94
118
  await submitFormValues(siteId, block.formId, values, hp, geopend.current || void 0);
95
119
  trackEvent(siteId, "formulier");
96
- if (def?.successRedirect) {
120
+ if (isVeiligPad(def?.successRedirect)) {
97
121
  window.location.assign(def.successRedirect);
98
122
  return;
99
123
  }
100
124
  setStatus("ok");
101
125
  setValues({});
102
- } catch {
126
+ } catch (err) {
103
127
  setStatus("error");
104
- setError("Versturen mislukt. Probeer het later opnieuw.");
128
+ setError(foutmeldingVoor(err));
105
129
  }
106
130
  }
107
131
  if (status === "ok") {
@@ -111,6 +135,19 @@ function FormRender({ block, siteId, mode }) {
111
135
  );
112
136
  }
113
137
  const setVal = (name, v) => setValues((prev) => ({ ...prev, [name]: v }));
138
+ useEffect(() => {
139
+ if (!def) return;
140
+ const q = new URLSearchParams(window.location.search);
141
+ setValues((prev) => {
142
+ const next = { ...prev };
143
+ for (const f of def.fields) {
144
+ const uitLink = q.get(f.name);
145
+ if (uitLink !== null && next[f.name] === void 0) next[f.name] = uitLink.slice(0, 500);
146
+ else if (f.type === "hidden" && next[f.name] === void 0 && f.placeholder) next[f.name] = f.placeholder;
147
+ }
148
+ return next;
149
+ });
150
+ }, [def]);
114
151
  return /* @__PURE__ */ jsx("form", { className: "xicms-form", onSubmit: submit, children: /* @__PURE__ */ jsxs(VStack, { gap: 3, children: [
115
152
  block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
116
153
  def.fields.map((f) => {
@@ -123,6 +160,7 @@ function FormRender({ block, siteId, mode }) {
123
160
  isRequired: f.required,
124
161
  placeholder: f.placeholder,
125
162
  rows: 4,
163
+ autoComplete: autoCompleteVoor(f),
126
164
  value: sv,
127
165
  onChange: (v) => setVal(f.name, v)
128
166
  },
@@ -156,25 +194,55 @@ function FormRender({ block, siteId, mode }) {
156
194
  );
157
195
  }
158
196
  if (f.type === "radio") {
159
- return /* @__PURE__ */ jsxs("fieldset", { className: "xicms-form__radios", children: [
160
- /* @__PURE__ */ jsxs("legend", { children: [
197
+ return /* @__PURE__ */ jsx(
198
+ RadioList,
199
+ {
200
+ label: f.label,
201
+ isRequired: f.required,
202
+ htmlName: f.name,
203
+ containerClassName: "xicms-form__radios",
204
+ value: sv,
205
+ onChange: (v) => setVal(f.name, v),
206
+ children: (f.options ?? []).map((opt) => /* @__PURE__ */ jsx(RadioListItem, { label: opt, value: opt }, opt))
207
+ },
208
+ f.name
209
+ );
210
+ }
211
+ if (f.type === "hidden") return null;
212
+ if (f.type === "dateRange") {
213
+ const [van = "", tot = ""] = sv.split("/");
214
+ return /* @__PURE__ */ jsxs("fieldset", { className: "xicms-form__periode", children: [
215
+ /* @__PURE__ */ jsxs("legend", { className: "xicms-form__native-label", children: [
161
216
  f.label,
162
217
  f.required && " *"
163
218
  ] }),
164
- (f.options ?? []).map((opt) => /* @__PURE__ */ jsxs("label", { className: "xicms-form__radio", children: [
219
+ /* @__PURE__ */ jsxs("label", { className: "xicms-form__native", children: [
220
+ /* @__PURE__ */ jsx("span", { children: "Van" }),
221
+ /* @__PURE__ */ jsx(
222
+ "input",
223
+ {
224
+ className: "xicms-input",
225
+ type: "date",
226
+ required: f.required,
227
+ value: van,
228
+ onChange: (e) => setVal(f.name, `${e.target.value}/${tot && tot < e.target.value ? "" : tot}`)
229
+ }
230
+ )
231
+ ] }),
232
+ /* @__PURE__ */ jsxs("label", { className: "xicms-form__native", children: [
233
+ /* @__PURE__ */ jsx("span", { children: "Tot" }),
165
234
  /* @__PURE__ */ jsx(
166
235
  "input",
167
236
  {
168
- type: "radio",
169
- name: f.name,
170
- value: opt,
237
+ className: "xicms-input",
238
+ type: "date",
171
239
  required: f.required,
172
- checked: sv === opt,
173
- onChange: () => setVal(f.name, opt)
240
+ min: van || void 0,
241
+ value: tot,
242
+ onChange: (e) => setVal(f.name, `${van}/${e.target.value}`)
174
243
  }
175
- ),
176
- opt
177
- ] }, opt))
244
+ )
245
+ ] })
178
246
  ] }, f.name);
179
247
  }
180
248
  if (f.type === "date" || f.type === "number") {
@@ -189,6 +257,7 @@ function FormRender({ block, siteId, mode }) {
189
257
  className: "xicms-input",
190
258
  type: f.type,
191
259
  required: f.required,
260
+ autoComplete: autoCompleteVoor(f),
192
261
  placeholder: f.placeholder,
193
262
  value: sv,
194
263
  onChange: (e) => setVal(f.name, e.target.value)
@@ -201,8 +270,10 @@ function FormRender({ block, siteId, mode }) {
201
270
  {
202
271
  label: f.label,
203
272
  type: f.type === "email" ? "email" : "text",
273
+ ref: f.type === "tel" ? (el) => el?.setAttribute("inputmode", "tel") : void 0,
204
274
  isRequired: f.required,
205
275
  placeholder: f.placeholder,
276
+ autoComplete: autoCompleteVoor(f),
206
277
  value: sv,
207
278
  onChange: (v) => setVal(f.name, v)
208
279
  },
@@ -226,6 +297,7 @@ function FormRender({ block, siteId, mode }) {
226
297
  ] }) });
227
298
  }
228
299
  export {
229
- FormRender
300
+ FormRender,
301
+ foutmeldingVoor
230
302
  };
231
303
  //# sourceMappingURL=FormBlockRender.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/builtins/FormBlockRender.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState, type FormEvent , useRef} from \"react\";\nimport type { z } from \"zod\";\nimport type { FormBlockSchema } from \"../../schema/blocks\";\nimport type { FormDefinition } from \"../../schema/forms\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { useBlockData } from \"../context\";\nimport { submitFormValues } from \"./lib/submitForm\";\nimport { trackEvent } from \"../../components/PageView\";\nimport { isDemoActive, getDemoForm } from \"../../demo/demoStore\";\nimport { useSiteConfig } from \"../../config\";\nimport { TextInput } from \"@astryxdesign/core/TextInput\";\nimport { TextArea } from \"@astryxdesign/core/TextArea\";\nimport { Selector } from \"@astryxdesign/core/Selector\";\nimport { CheckboxInput } from \"@astryxdesign/core/CheckboxInput\";\nimport { Spinner } from \"@astryxdesign/core/Spinner\";\nimport { Button } from \"@astryxdesign/core/Button\";\nimport { VStack, Card, Heading, Text } from \"../ui\";\n\ntype FormBlk = z.infer<typeof FormBlockSchema>;\n\n/** Voorbeeldformulier voor de demo wanneer er geen specifieke definitie is geregistreerd. */\nconst DEMO_FALLBACK_FORM: FormDefinition = {\n name: \"Contact\",\n submitLabel: \"Versturen\",\n successMessage: \"Bedankt! Dit is een demo — je bericht is niet echt verstuurd.\",\n fields: [\n { name: \"naam\", label: \"Naam\", type: \"text\", required: true },\n { name: \"email\", label: \"E-mail\", type: \"email\", required: true },\n { name: \"bericht\", label: \"Bericht\", type: \"textarea\", required: false, placeholder: \"Waarmee kunnen we je helpen?\" },\n ],\n};\n\nexport function FormRender({ block, siteId, mode }: BlockRenderProps<FormBlk>) {\n const siteMode = useSiteConfig().mode;\n // Server-seed (7.12): de route leest formulierdefinities server-side (getPageBlockData) en\n // geeft ze mee als blockData. Het formulier staat dan al in de SSR-HTML en de per-bezoeker\n // `getDoc` hieronder vervalt. Zonder seed (oudere site, admin-preview) werkt het oude pad.\n const serverForms = useBlockData<Record<string, FormDefinition>>(\"forms\");\n const serverDef = serverForms?.[block.formId] ?? null;\n const [def, setDef] = useState<FormDefinition | null>(serverDef);\n const [unavailable, setUnavailable] = useState(false);\n const [values, setValues] = useState<Record<string, string | boolean>>({});\n const [hp, setHp] = useState(\"\");\n // Tijdsval (7.24): wanneer kwam het formulier in beeld? Bots posten binnen een seconde.\n const geopend = useRef<number>(0);\n useEffect(() => {\n geopend.current = Date.now();\n }, []);\n const [status, setStatus] = useState<\"idle\" | \"busy\" | \"ok\" | \"error\">(\"idle\");\n const [error, setError] = useState<string | null>(null);\n\n const demo = isDemoActive();\n // \"Lokaal\" inzenden (geen Firebase-call) bij demo OF wanneer er geen Firebase is maar wél een\n // geregistreerd voorbeeldformulier — zo werkt een statische referentiesite z'n formulier ook.\n const [localOnly, setLocalOnly] = useState(demo);\n\n useEffect(() => {\n if (demo) {\n setDef(getDemoForm(siteId, block.formId) ?? DEMO_FALLBACK_FORM);\n setLocalOnly(true);\n return;\n }\n if (serverDef) return; // definitie kwam al server-side mee\n // Firestore dynamisch: alleen een pagina die écht een formulier toont haalt de SDK binnen.\n void (async () => {\n const [{ getDb }, { doc, getDoc }] = await Promise.all([\n import(\"../../firebase/client\"),\n import(\"firebase/firestore\"),\n ]);\n const db = getDb();\n if (!db) {\n // Geen Firebase: val terug op een geregistreerd formulier, of (op een mode:\"demo\"-site) op\n // het ingebouwde voorbeeld; beide zenden lokaal in. Anders een nette \"niet beschikbaar\".\n const reg = getDemoForm(siteId, block.formId) ?? (siteMode === \"demo\" ? DEMO_FALLBACK_FORM : null);\n if (reg) { setDef(reg); setLocalOnly(true); } else { setUnavailable(true); }\n return;\n }\n try {\n const snap = await getDoc(doc(db, \"sites\", siteId, \"forms\", block.formId));\n if (snap.exists()) setDef(snap.data() as FormDefinition);\n else setUnavailable(true);\n } catch {\n setUnavailable(true);\n }\n })();\n }, [demo, siteId, block.formId, siteMode, serverDef]);\n\n if (unavailable) {\n return (\n <Card padding={4} variant=\"muted\">\n <Text>{block.heading ? `${block.heading}: ` : \"\"}neem contact met ons op — we reageren snel.</Text>\n </Card>\n );\n }\n if (!def) {\n return (\n <div style={{ display: \"grid\", placeItems: \"center\", minHeight: 120 }}>\n <Spinner label=\"Formulier laden…\" />\n </div>\n );\n }\n\n async function submit(e: FormEvent) {\n e.preventDefault();\n if (mode === \"preview\") return;\n if (localOnly) {\n // Lokaal (demo / geen backend): niets versturen, alleen de successtaat tonen.\n setStatus(\"ok\");\n setValues({});\n return;\n }\n setStatus(\"busy\");\n setError(null);\n try {\n await submitFormValues(siteId, block.formId, values, hp, geopend.current || undefined);\n trackEvent(siteId, \"formulier\");\n // Optioneel doorsturen naar een bedankt-pagina (conversiemeting/advertenties).\n if (def?.successRedirect) {\n window.location.assign(def.successRedirect);\n return;\n }\n setStatus(\"ok\");\n setValues({});\n } catch {\n setStatus(\"error\");\n setError(\"Versturen mislukt. Probeer het later opnieuw.\");\n }\n }\n\n if (status === \"ok\") {\n return (\n // role=\"status\": screenreaders melden de succesboodschap wanneer het formulier verdwijnt.\n <Card padding={4} variant=\"muted\" role=\"status\">\n <Text>{def.successMessage}</Text>\n </Card>\n );\n }\n\n const setVal = (name: string, v: string | boolean) => setValues((prev) => ({ ...prev, [name]: v }));\n\n return (\n <form className=\"xicms-form\" onSubmit={submit}>\n <VStack gap={3}>\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n {def.fields.map((f) => {\n const sv = (values[f.name] as string) ?? \"\";\n if (f.type === \"textarea\") {\n return (\n <TextArea key={f.name} label={f.label} isRequired={f.required} placeholder={f.placeholder} rows={4}\n value={sv} onChange={(v) => setVal(f.name, v)} />\n );\n }\n if (f.type === \"select\") {\n return (\n <Selector key={f.name} label={f.label} isRequired={f.required} placeholder=\"Kies…\"\n options={f.options ?? []} value={sv} onChange={(v) => setVal(f.name, (v as string) ?? \"\")} />\n );\n }\n if (f.type === \"checkbox\") {\n return (\n <CheckboxInput key={f.name} label={f.label} isRequired={f.required}\n value={Boolean(values[f.name])} onChange={(checked) => setVal(f.name, checked)} />\n );\n }\n if (f.type === \"radio\") {\n return (\n <fieldset key={f.name} className=\"xicms-form__radios\">\n <legend>{f.label}{f.required && \" *\"}</legend>\n {(f.options ?? []).map((opt) => (\n <label key={opt} className=\"xicms-form__radio\">\n <input\n type=\"radio\"\n name={f.name}\n value={opt}\n required={f.required}\n checked={sv === opt}\n onChange={() => setVal(f.name, opt)}\n />\n {opt}\n </label>\n ))}\n </fieldset>\n );\n }\n if (f.type === \"date\" || f.type === \"number\") {\n // Astryx TextInput kent geen date/number → native input in dezelfde stijl.\n return (\n <label key={f.name} className=\"xicms-form__native\">\n <span className=\"xicms-form__native-label\">{f.label}{f.required && \" *\"}</span>\n <input\n className=\"xicms-input\"\n type={f.type}\n required={f.required}\n placeholder={f.placeholder}\n value={sv}\n onChange={(e) => setVal(f.name, e.target.value)}\n />\n </label>\n );\n }\n return (\n <TextInput key={f.name} label={f.label} type={f.type === \"email\" ? \"email\" : \"text\"}\n isRequired={f.required} placeholder={f.placeholder}\n value={sv} onChange={(v) => setVal(f.name, v)} />\n );\n })}\n {/* Honeypot — verborgen voor mensen, bots vullen 'm vaak wel in. */}\n <input\n type=\"text\"\n tabIndex={-1}\n autoComplete=\"off\"\n value={hp}\n onChange={(e) => setHp(e.target.value)}\n style={{ position: \"absolute\", left: \"-9999px\", width: 1, height: 1 }}\n aria-hidden\n />\n {error && <Text role=\"alert\" style={{ color: \"var(--color-error, #c0392b)\" }}>{error}</Text>}\n <div>\n <Button label={status === \"busy\" ? \"Versturen…\" : def.submitLabel} variant=\"primary\" size=\"lg\" type=\"submit\" isLoading={status === \"busy\"} />\n </div>\n </VStack>\n </form>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/builtins/FormBlockRender.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState, type FormEvent , useRef} from \"react\";\nimport type { z } from \"zod\";\nimport type { FormBlockSchema } from \"../../schema/blocks\";\nimport { isVeiligPad, type FormDefinition } from \"../../schema/forms\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { useBlockData } from \"../context\";\nimport { submitFormValues } from \"./lib/submitForm\";\nimport { autoCompleteVoor } from \"./lib/autoComplete\";\nimport { trackEvent } from \"../../components/PageView\";\nimport { isDemoActive, getDemoForm } from \"../../demo/demoStore\";\nimport { useSiteConfig } from \"../../config\";\nimport { TextInput } from \"@astryxdesign/core/TextInput\";\nimport { TextArea } from \"@astryxdesign/core/TextArea\";\nimport { Selector } from \"@astryxdesign/core/Selector\";\nimport { CheckboxInput } from \"@astryxdesign/core/CheckboxInput\";\nimport { RadioList, RadioListItem } from \"@astryxdesign/core/RadioList\";\nimport { Spinner } from \"@astryxdesign/core/Spinner\";\nimport { Button } from \"@astryxdesign/core/Button\";\nimport { VStack, Card, Heading, Text } from \"../ui\";\n\ntype FormBlk = z.infer<typeof FormBlockSchema>;\n\n/** Voorbeeldformulier voor de demo wanneer er geen specifieke definitie is geregistreerd. */\n/**\n * Een begrijpelijke melding per oorzaak (8.1). Eerst kreeg de bezoeker bij élke fout \"Versturen\n * mislukt\", ook als hij alleen een verplicht veld vergat of te vaak verstuurde.\n */\nexport function foutmeldingVoor(err: unknown): string {\n const code = String((err as { code?: string })?.code ?? \"\");\n const message = String((err as { message?: string })?.message ?? \"\");\n if (code.endsWith(\"invalid-argument\") && message && !/^ongeldige invoer/i.test(message)) return message;\n if (code.endsWith(\"resource-exhausted\")) return \"Je hebt het formulier net al een paar keer verstuurd. Probeer het over een minuut opnieuw.\";\n if (code.endsWith(\"unavailable\") || (typeof navigator !== \"undefined\" && navigator.onLine === false)) {\n return \"Geen verbinding. Controleer je internet en probeer het opnieuw.\";\n }\n return \"Versturen mislukt. Probeer het later opnieuw.\";\n}\n\nconst DEMO_FALLBACK_FORM: FormDefinition = {\n name: \"Contact\",\n submitLabel: \"Versturen\",\n successMessage: \"Bedankt! Dit is een demo — je bericht is niet echt verstuurd.\",\n fields: [\n { name: \"naam\", label: \"Naam\", type: \"text\", required: true },\n { name: \"email\", label: \"E-mail\", type: \"email\", required: true },\n { name: \"bericht\", label: \"Bericht\", type: \"textarea\", required: false, placeholder: \"Waarmee kunnen we je helpen?\" },\n ],\n};\n\nexport function FormRender({ block, siteId, mode }: BlockRenderProps<FormBlk>) {\n const siteMode = useSiteConfig().mode;\n // Server-seed (7.12): de route leest formulierdefinities server-side (getPageBlockData) en\n // geeft ze mee als blockData. Het formulier staat dan al in de SSR-HTML en de per-bezoeker\n // `getDoc` hieronder vervalt. Zonder seed (oudere site, admin-preview) werkt het oude pad.\n const serverForms = useBlockData<Record<string, FormDefinition | null>>(\"forms\");\n const serverDef = serverForms?.[block.formId] ?? null;\n // 8.9: de server heeft gekeken en het formulier bestaat niet (`null`): niets meer ophalen.\n const serverZegtOntbreekt = serverForms !== undefined && serverForms !== null && block.formId in serverForms && serverForms[block.formId] === null;\n const [def, setDef] = useState<FormDefinition | null>(serverDef);\n const [unavailable, setUnavailable] = useState(false);\n const [values, setValues] = useState<Record<string, string | boolean>>({});\n const [hp, setHp] = useState(\"\");\n // Tijdsval (7.24): wanneer kwam het formulier in beeld? Bots posten binnen een seconde.\n const geopend = useRef<number>(0);\n useEffect(() => {\n geopend.current = Date.now();\n }, []);\n const [status, setStatus] = useState<\"idle\" | \"busy\" | \"ok\" | \"error\">(\"idle\");\n const [error, setError] = useState<string | null>(null);\n\n const demo = isDemoActive();\n // \"Lokaal\" inzenden (geen Firebase-call) bij demo OF wanneer er geen Firebase is maar wél een\n // geregistreerd voorbeeldformulier — zo werkt een statische referentiesite z'n formulier ook.\n const [localOnly, setLocalOnly] = useState(demo);\n\n useEffect(() => {\n if (demo) {\n setDef(getDemoForm(siteId, block.formId) ?? DEMO_FALLBACK_FORM);\n setLocalOnly(true);\n return;\n }\n if (serverDef) return; // definitie kwam al server-side mee\n if (serverZegtOntbreekt) {\n // Zelfde terugval als zonder Firebase hieronder, maar zonder de SDK te downloaden.\n const reg = getDemoForm(siteId, block.formId) ?? (siteMode === \"demo\" ? DEMO_FALLBACK_FORM : null);\n if (reg) { setDef(reg); setLocalOnly(true); } else { setUnavailable(true); }\n return;\n }\n // Firestore dynamisch: alleen een pagina die écht een formulier toont haalt de SDK binnen.\n void (async () => {\n const [{ getDb }, { doc, getDoc }] = await Promise.all([\n import(\"../../firebase/client\"),\n import(\"firebase/firestore\"),\n ]);\n const db = getDb();\n if (!db) {\n // Geen Firebase: val terug op een geregistreerd formulier, of (op een mode:\"demo\"-site) op\n // het ingebouwde voorbeeld; beide zenden lokaal in. Anders een nette \"niet beschikbaar\".\n const reg = getDemoForm(siteId, block.formId) ?? (siteMode === \"demo\" ? DEMO_FALLBACK_FORM : null);\n if (reg) { setDef(reg); setLocalOnly(true); } else { setUnavailable(true); }\n return;\n }\n try {\n const snap = await getDoc(doc(db, \"sites\", siteId, \"forms\", block.formId));\n if (snap.exists()) setDef(snap.data() as FormDefinition);\n else setUnavailable(true);\n } catch {\n setUnavailable(true);\n }\n })();\n }, [demo, siteId, block.formId, siteMode, serverDef, serverZegtOntbreekt]);\n\n if (unavailable) {\n return (\n <Card padding={4} variant=\"muted\">\n <Text>{block.heading ? `${block.heading}: ` : \"\"}neem contact met ons op — we reageren snel.</Text>\n </Card>\n );\n }\n if (!def) {\n return (\n <div style={{ display: \"grid\", placeItems: \"center\", minHeight: 120 }}>\n <Spinner label=\"Formulier laden…\" />\n </div>\n );\n }\n\n async function submit(e: FormEvent) {\n e.preventDefault();\n if (mode === \"preview\") return;\n if (localOnly) {\n // Lokaal (demo / geen backend): niets versturen, alleen de successtaat tonen.\n setStatus(\"ok\");\n setValues({});\n return;\n }\n setStatus(\"busy\");\n setError(null);\n try {\n await submitFormValues(siteId, block.formId, values, hp, geopend.current || undefined);\n trackEvent(siteId, \"formulier\");\n // Optioneel doorsturen naar een bedankt-pagina (conversiemeting/advertenties).\n // Alleen een pad op de eigen site — nooit een extern adres of `javascript:` (8.1).\n if (isVeiligPad(def?.successRedirect)) {\n window.location.assign(def.successRedirect);\n return;\n }\n setStatus(\"ok\");\n setValues({});\n } catch (err) {\n setStatus(\"error\");\n setError(foutmeldingVoor(err));\n }\n }\n\n if (status === \"ok\") {\n return (\n // role=\"status\": screenreaders melden de succesboodschap wanneer het formulier verdwijnt.\n <Card padding={4} variant=\"muted\" role=\"status\">\n <Text>{def.successMessage}</Text>\n </Card>\n );\n }\n\n const setVal = (name: string, v: string | boolean) => setValues((prev) => ({ ...prev, [name]: v }));\n\n /**\n * 8.14: vooraf invullen vanuit het webadres. Een knop \"Boek Huisje A\" kan naar\n * /contact?huisje=Huisje%20A wijzen; een veld met de naam `huisje` staat dan al ingevuld. Een\n * verborgen veld zonder waarde in de link houdt zijn vaste waarde (de placeholder).\n */\n useEffect(() => {\n if (!def) return;\n const q = new URLSearchParams(window.location.search);\n setValues((prev) => {\n const next = { ...prev };\n for (const f of def.fields) {\n const uitLink = q.get(f.name);\n if (uitLink !== null && next[f.name] === undefined) next[f.name] = uitLink.slice(0, 500);\n else if (f.type === \"hidden\" && next[f.name] === undefined && f.placeholder) next[f.name] = f.placeholder;\n }\n return next;\n });\n }, [def]);\n\n return (\n <form className=\"xicms-form\" onSubmit={submit}>\n <VStack gap={3}>\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n {def.fields.map((f) => {\n const sv = (values[f.name] as string) ?? \"\";\n if (f.type === \"textarea\") {\n return (\n <TextArea key={f.name} label={f.label} isRequired={f.required} placeholder={f.placeholder} rows={4}\n autoComplete={autoCompleteVoor(f)} value={sv} onChange={(v) => setVal(f.name, v)} />\n );\n }\n if (f.type === \"select\") {\n return (\n <Selector key={f.name} label={f.label} isRequired={f.required} placeholder=\"Kies…\"\n options={f.options ?? []} value={sv} onChange={(v) => setVal(f.name, (v as string) ?? \"\")} />\n );\n }\n if (f.type === \"checkbox\") {\n return (\n <CheckboxInput key={f.name} label={f.label} isRequired={f.required}\n value={Boolean(values[f.name])} onChange={(checked) => setVal(f.name, checked)} />\n );\n }\n if (f.type === \"radio\") {\n // 8.0: Astryx RadioList i.p.v. losse native radio's — één groep met toegankelijke naam,\n // pijltjestoetsen en dezelfde focusstijl als de andere velden.\n return (\n <RadioList key={f.name} label={f.label} isRequired={f.required} htmlName={f.name}\n containerClassName=\"xicms-form__radios\" value={sv} onChange={(v) => setVal(f.name, v)}>\n {(f.options ?? []).map((opt) => (\n <RadioListItem key={opt} label={opt} value={opt} />\n ))}\n </RadioList>\n );\n }\n if (f.type === \"hidden\") return null;\n if (f.type === \"dateRange\") {\n const [van = \"\", tot = \"\"] = sv.split(\"/\");\n return (\n <fieldset key={f.name} className=\"xicms-form__periode\">\n <legend className=\"xicms-form__native-label\">{f.label}{f.required && \" *\"}</legend>\n <label className=\"xicms-form__native\">\n <span>Van</span>\n <input className=\"xicms-input\" type=\"date\" required={f.required} value={van}\n onChange={(e) => setVal(f.name, `${e.target.value}/${tot && tot < e.target.value ? \"\" : tot}`)} />\n </label>\n <label className=\"xicms-form__native\">\n <span>Tot</span>\n <input className=\"xicms-input\" type=\"date\" required={f.required} min={van || undefined} value={tot}\n onChange={(e) => setVal(f.name, `${van}/${e.target.value}`)} />\n </label>\n </fieldset>\n );\n }\n if (f.type === \"date\" || f.type === \"number\") {\n // Astryx TextInput kent geen date/number → native input in dezelfde stijl.\n return (\n <label key={f.name} className=\"xicms-form__native\">\n <span className=\"xicms-form__native-label\">{f.label}{f.required && \" *\"}</span>\n <input\n className=\"xicms-input\"\n type={f.type}\n required={f.required}\n autoComplete={autoCompleteVoor(f)}\n placeholder={f.placeholder}\n value={sv}\n onChange={(e) => setVal(f.name, e.target.value)}\n />\n </label>\n );\n }\n return (\n <TextInput key={f.name} label={f.label} type={f.type === \"email\" ? \"email\" : \"text\"}\n // Telefoon (8.4): wél het Astryx-veld (zelfde uiterlijk als de rest — de native variant\n // uit 8.0 stak op klantsites af), met `inputmode` voor het cijfertoetsenbord.\n ref={f.type === \"tel\" ? (el: HTMLInputElement | null) => el?.setAttribute(\"inputmode\", \"tel\") : undefined}\n isRequired={f.required} placeholder={f.placeholder} autoComplete={autoCompleteVoor(f)}\n value={sv} onChange={(v) => setVal(f.name, v)} />\n );\n })}\n {/* Honeypot — verborgen voor mensen, bots vullen 'm vaak wel in. */}\n <input\n type=\"text\"\n tabIndex={-1}\n autoComplete=\"off\"\n value={hp}\n onChange={(e) => setHp(e.target.value)}\n style={{ position: \"absolute\", left: \"-9999px\", width: 1, height: 1 }}\n aria-hidden\n />\n {error && <Text role=\"alert\" style={{ color: \"var(--color-error, #c0392b)\" }}>{error}</Text>}\n <div>\n <Button label={status === \"busy\" ? \"Versturen…\" : def.submitLabel} variant=\"primary\" size=\"lg\" type=\"submit\" isLoading={status === \"busy\"} />\n </div>\n </VStack>\n </form>\n );\n}\n"],"mappings":"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","names":[]}
@@ -4,7 +4,7 @@ import { useCallback, useEffect, useRef, useState } from "react";
4
4
  import { createPortal } from "react-dom";
5
5
  import { useModuleSettings } from "../../modules/context.js";
6
6
  import { Grid } from "../ui/index.js";
7
- import { Img } from "../../media/ImageContext.js";
7
+ import { Img, useGrootsteVariant } from "../../media/ImageContext.js";
8
8
  function LightboxOverlay({
9
9
  items,
10
10
  index,
@@ -12,6 +12,7 @@ function LightboxOverlay({
12
12
  onClose
13
13
  }) {
14
14
  const it = items[index];
15
+ const groot = useGrootsteVariant(it?.url ?? "");
15
16
  const total = items.length;
16
17
  const overlayRef = useRef(null);
17
18
  const prev = useCallback(() => onIndex((index - 1 + total) % total), [index, total, onIndex]);
@@ -94,7 +95,7 @@ function LightboxOverlay({
94
95
  onPointerUp,
95
96
  style: { touchAction: "pan-y" },
96
97
  children: [
97
- /* @__PURE__ */ jsx("img", { src: it.url, alt: it.alt ?? "" }),
98
+ /* @__PURE__ */ jsx("img", { src: groot, alt: it.alt ?? "" }),
98
99
  it.caption && /* @__PURE__ */ jsx("figcaption", { children: it.caption })
99
100
  ]
100
101
  }