@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
@@ -0,0 +1,73 @@
1
+ import * as z from "zod/mini";
2
+ const BEDRIJFSTYPES = [
3
+ { value: "LocalBusiness", label: "Lokaal bedrijf (algemeen)" },
4
+ { value: "HomeAndConstructionBusiness", label: "Bouw, klussen en tuin" },
5
+ { value: "ProfessionalService", label: "Zakelijke dienstverlening" },
6
+ { value: "HairSalon", label: "Kapper of barbier" },
7
+ { value: "BeautySalon", label: "Schoonheidssalon" },
8
+ { value: "Restaurant", label: "Restaurant" },
9
+ { value: "CafeOrCoffeeShop", label: "Caf\xE9 of koffiebar" },
10
+ { value: "Bakery", label: "Bakkerij" },
11
+ { value: "Store", label: "Winkel" },
12
+ { value: "LodgingBusiness", label: "Verhuur of overnachting" },
13
+ { value: "BedAndBreakfast", label: "Bed & breakfast" },
14
+ { value: "MedicalBusiness", label: "Zorg of praktijk" },
15
+ { value: "Physiotherapy", label: "Fysiotherapie" },
16
+ { value: "Dentist", label: "Tandarts" },
17
+ { value: "SportsActivityLocation", label: "Sport of fitness" },
18
+ { value: "EducationalOrganization", label: "Onderwijs of cursus" },
19
+ { value: "Church", label: "Kerk" },
20
+ { value: "NGO", label: "Stichting of vereniging" }
21
+ ];
22
+ const tekst = (max) => z.optional(z.string().check(z.maxLength(max)));
23
+ const BusinessHoursRowSchema = z.object({
24
+ day: z._default(z.string().check(z.maxLength(80)), ""),
25
+ hours: z._default(z.string().check(z.maxLength(80)), "")
26
+ });
27
+ const BusinessExceptionSchema = z.object({
28
+ /** "2026-12-25" */
29
+ date: z.string().check(z.regex(/^\d{4}-\d{2}-\d{2}$/)),
30
+ /** Laatste dag van een periode (vakantie); leeg = alleen `date`. */
31
+ until: z.optional(z.string().check(z.regex(/^\d{4}-\d{2}-\d{2}$/))),
32
+ /** "Gesloten" of "10:00 – 14:00". */
33
+ hours: z._default(z.string().check(z.maxLength(80)), "Gesloten"),
34
+ /** "Eerste Kerstdag", "Zomervakantie". */
35
+ label: tekst(80)
36
+ });
37
+ const BusinessSchema = z.object({
38
+ type: z.optional(z.string().check(z.maxLength(60))),
39
+ /** Naam als die afwijkt van de sitenaam (bv. met "B.V."). */
40
+ name: tekst(160),
41
+ description: tekst(500),
42
+ phone: tekst(40),
43
+ email: z.optional(z.union([z.email(), z.literal("")])),
44
+ /** Internationaal nummer voor WhatsApp, bv. +31612345678. */
45
+ whatsapp: tekst(40),
46
+ address: z.optional(
47
+ z.object({
48
+ street: tekst(160),
49
+ postalCode: tekst(20),
50
+ city: tekst(100),
51
+ country: tekst(60)
52
+ })
53
+ ),
54
+ geo: z.optional(z.object({ lat: z.number(), lng: z.number() })),
55
+ hours: z.optional(z.array(BusinessHoursRowSchema).check(z.maxLength(14))),
56
+ /** Korte toelichting onder de tijden ("Op afspraak ook 's avonds"). */
57
+ hoursNote: tekst(200),
58
+ exceptions: z.optional(z.array(BusinessExceptionSchema).check(z.maxLength(60))),
59
+ /** "€€", "€ 25 – € 45". */
60
+ priceRange: tekst(40),
61
+ kvk: tekst(20),
62
+ /** Link waar klanten een review achterlaten (Google-bedrijfsprofiel). */
63
+ reviewUrl: z.optional(z.string().check(z.maxLength(2e3))),
64
+ /** Profielen elders: Instagram, Facebook, LinkedIn … */
65
+ sameAs: z.optional(z.array(z.string().check(z.maxLength(2e3))).check(z.maxLength(12)))
66
+ });
67
+ export {
68
+ BEDRIJFSTYPES,
69
+ BusinessExceptionSchema,
70
+ BusinessHoursRowSchema,
71
+ BusinessSchema
72
+ };
73
+ //# sourceMappingURL=business.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/schema/business.ts"],"sourcesContent":["import * as z from \"zod/mini\";\n\n/**\n * Het bedrijfsprofiel (8.13): naam, adres, telefoon, openingstijden — één keer ingevuld in\n * /beheer → Instellingen → Bedrijf, en daarna overal gebruikt.\n *\n * Tot nu toe stonden deze gegevens op vier plekken tegelijk: hardcoded in de footer van de site,\n * hardcoded als LocalBusiness-JSON-LD in `app/layout.tsx`, en nog eens in een contact- en een\n * openingstijdenblok. Een klant die van telefoonnummer wisselde, kon er maar één van aanpassen. Nu:\n * - de JSON-LD voor Google komt automatisch uit dit profiel (`bedrijfJsonLd`);\n * - het contact- en openingstijdenblok vallen erop terug als ze zelf leeg zijn;\n * - de footer kan een contactkolom uit het profiel tonen.\n *\n * Openingstijden gebruiken hetzelfde rijmodel als het openingstijdenblok ({ day, hours } in gewone\n * taal: \"Maandag t/m vrijdag\" · \"09:00 – 17:00\"), dus dezelfde parser voor \"nu open\" en Google.\n */\n\n/** schema.org-types die een klant kan kiezen, met een Nederlandse naam. */\nexport const BEDRIJFSTYPES = [\n { value: \"LocalBusiness\", label: \"Lokaal bedrijf (algemeen)\" },\n { value: \"HomeAndConstructionBusiness\", label: \"Bouw, klussen en tuin\" },\n { value: \"ProfessionalService\", label: \"Zakelijke dienstverlening\" },\n { value: \"HairSalon\", label: \"Kapper of barbier\" },\n { value: \"BeautySalon\", label: \"Schoonheidssalon\" },\n { value: \"Restaurant\", label: \"Restaurant\" },\n { value: \"CafeOrCoffeeShop\", label: \"Café of koffiebar\" },\n { value: \"Bakery\", label: \"Bakkerij\" },\n { value: \"Store\", label: \"Winkel\" },\n { value: \"LodgingBusiness\", label: \"Verhuur of overnachting\" },\n { value: \"BedAndBreakfast\", label: \"Bed & breakfast\" },\n { value: \"MedicalBusiness\", label: \"Zorg of praktijk\" },\n { value: \"Physiotherapy\", label: \"Fysiotherapie\" },\n { value: \"Dentist\", label: \"Tandarts\" },\n { value: \"SportsActivityLocation\", label: \"Sport of fitness\" },\n { value: \"EducationalOrganization\", label: \"Onderwijs of cursus\" },\n { value: \"Church\", label: \"Kerk\" },\n { value: \"NGO\", label: \"Stichting of vereniging\" },\n] as const;\n\nconst tekst = (max: number) => z.optional(z.string().check(z.maxLength(max)));\n\nexport const BusinessHoursRowSchema = z.object({\n day: z._default(z.string().check(z.maxLength(80)), \"\"),\n hours: z._default(z.string().check(z.maxLength(80)), \"\"),\n});\n\n/** Een afwijkende dag of periode: feestdag, vakantie, koopavond. */\nexport const BusinessExceptionSchema = z.object({\n /** \"2026-12-25\" */\n date: z.string().check(z.regex(/^\\d{4}-\\d{2}-\\d{2}$/)),\n /** Laatste dag van een periode (vakantie); leeg = alleen `date`. */\n until: z.optional(z.string().check(z.regex(/^\\d{4}-\\d{2}-\\d{2}$/))),\n /** \"Gesloten\" of \"10:00 – 14:00\". */\n hours: z._default(z.string().check(z.maxLength(80)), \"Gesloten\"),\n /** \"Eerste Kerstdag\", \"Zomervakantie\". */\n label: tekst(80),\n});\n\nexport const BusinessSchema = z.object({\n type: z.optional(z.string().check(z.maxLength(60))),\n /** Naam als die afwijkt van de sitenaam (bv. met \"B.V.\"). */\n name: tekst(160),\n description: tekst(500),\n phone: tekst(40),\n email: z.optional(z.union([z.email(), z.literal(\"\")])),\n /** Internationaal nummer voor WhatsApp, bv. +31612345678. */\n whatsapp: tekst(40),\n address: z.optional(\n z.object({\n street: tekst(160),\n postalCode: tekst(20),\n city: tekst(100),\n country: tekst(60),\n }),\n ),\n geo: z.optional(z.object({ lat: z.number(), lng: z.number() })),\n hours: z.optional(z.array(BusinessHoursRowSchema).check(z.maxLength(14))),\n /** Korte toelichting onder de tijden (\"Op afspraak ook 's avonds\"). */\n hoursNote: tekst(200),\n exceptions: z.optional(z.array(BusinessExceptionSchema).check(z.maxLength(60))),\n /** \"€€\", \"€ 25 – € 45\". */\n priceRange: tekst(40),\n kvk: tekst(20),\n /** Link waar klanten een review achterlaten (Google-bedrijfsprofiel). */\n reviewUrl: z.optional(z.string().check(z.maxLength(2000))),\n /** Profielen elders: Instagram, Facebook, LinkedIn … */\n sameAs: z.optional(z.array(z.string().check(z.maxLength(2000))).check(z.maxLength(12))),\n});\nexport type Business = z.infer<typeof BusinessSchema>;\nexport type BusinessException = z.infer<typeof BusinessExceptionSchema>;\n"],"mappings":"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","names":[]}
@@ -52,7 +52,8 @@ export type Field = ({
52
52
  options: {
53
53
  value: string;
54
54
  label: string;
55
- }[];
55
+ }[]; /** Schema-default (8.10). */
56
+ standaard?: string;
56
57
  } & BaseShape) | ({
57
58
  type: "date";
58
59
  } & BaseShape) | ({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/schema/fields.ts"],"sourcesContent":["/**\n * Field-IR (\"intermediate representation\") — het declaratieve veldmodel dat formulieren aandrijft.\n *\n * Geport concept + modelvorm uit primo (github.com/primocms/primo, MIT © Matthew Morris) — zie\n * THIRD_PARTY_LICENSES.md. Primo definieert velden als een Zod discriminated union met een\n * `config`-blob per type, nesting zonder recursieve schema's en conditionele velden (`Condition`).\n * XiCMS gebruikt dit model op twee plekken:\n *\n * 1. **Afgeleid**: `introspectToFields()` (admin/lib/zodFields.ts) leidt een Field-IR af uit de\n * bestaande Zod-block-schema's — de GenericEditor rendert die IR. De Zod-schema's blijven de\n * bron van waarheid; dit is puur de formulier-beschrijving.\n * 2. **Als data**: custom blocks (sites/{siteId}/customBlocks) slaan hun velddefinities als\n * Field-IR op in Firestore. `fieldsToZod()` genereert daaruit een echt Zod-schema zodat ook\n * runtime-gedefinieerde blokken de harde XiCMS-validatie houden.\n *\n * Server-safe (geen React). Nesting gaat via een `fields`-array in group/repeater — documentvorm,\n * geen aparte rows (Firestore-vriendelijk, en `z.lazy` dekt de recursie).\n */\nimport * as z from \"zod/mini\";\n\n/** Zod 4 heeft `ZodTypeAny` afgeschaft; in mini is `z.ZodType` de losse bovengrens. */\ntype ZodTypeAny = z.ZodMiniType;\n\n/** Conditioneel tonen: veld is zichtbaar als `field` (sibling-sleutel) matcht. */\nexport const ShowIfSchema = z.object({\n /** Sleutel van het veld (zelfde niveau) waarvan de waarde bepaalt of dit veld toont. */\n field: z.string().check(z.minLength(1)),\n /** Toon alléén bij exact deze waarde. Weggelaten → toon bij een truthy waarde. */\n equals: z.optional(z.union([z.string(), z.number(), z.boolean()])),\n});\nexport type ShowIf = z.infer<typeof ShowIfSchema>;\n\nconst base = {\n /** Sleutel in het waarden-object (dotted paths niet toegestaan; nesting via group/repeater). */\n key: z.string().check(z.minLength(1)).check(z.regex(/^[a-zA-Z][a-zA-Z0-9]*$/, \"veldsleutel: letters/cijfers, begint met letter\")),\n /** Leesbaar label (NL). */\n label: z._default(z.string(), \"\"),\n /** Optionele hint onder het veld. */\n hint: z.optional(z.string()),\n /** Conditioneel tonen (primo's Condition). */\n showIf: z.optional(ShowIfSchema),\n};\n\n/** Selectie-optie voor `select`. */\nconst selectOption = z.object({ value: z.string(), label: z._default(z.string(), \"\") });\n\n// ── Veldtypes (primo: Text, RichText, Number, Slider, Switch, Select, Date, Icon, Image, Url,\n// Link, Group, Repeater, Page, Info — hier op XiCMS-conventies gebracht) ──────────────────────\n\nexport type Field =\n | ({ type: \"text\"; maxLength?: number; placeholder?: string } & BaseShape)\n | ({ type: \"textarea\"; maxLength?: number; rows?: number } & BaseShape)\n | ({ type: \"richtext\" } & BaseShape)\n | ({ type: \"number\"; min?: number; max?: number; step?: number } & BaseShape)\n | ({ type: \"slider\"; min: number; max: number; step?: number } & BaseShape)\n | ({ type: \"switch\" } & BaseShape)\n | ({ type: \"select\"; options: { value: string; label: string }[] } & BaseShape)\n | ({ type: \"date\" } & BaseShape)\n | ({ type: \"icon\" } & BaseShape)\n | ({ type: \"image\" } & BaseShape)\n | ({ type: \"url\" } & BaseShape)\n | ({ type: \"link\" } & BaseShape)\n | ({ type: \"group\"; fields: Field[] } & BaseShape)\n | ({ type: \"repeater\"; fields: Field[]; max?: number; itemLabel?: string } & BaseShape)\n | ({ type: \"pageRef\" } & BaseShape)\n | ({ type: \"info\"; text: string } & BaseShape)\n | ({ type: \"json\" } & BaseShape);\n\ntype BaseShape = { key: string; label: string; hint?: string; showIf?: ShowIf };\n\n/** Zod-schema voor één veld-definitie (recursief via z.lazy voor group/repeater). */\nexport const FieldSchema: z.ZodMiniType<Field> = z.lazy(() =>\n z.discriminatedUnion(\"type\", [\n z.object({ ...base, type: z.literal(\"text\"), maxLength: z.optional(z.int().check(z.positive())), placeholder: z.optional(z.string()) }),\n z.object({ ...base, type: z.literal(\"textarea\"), maxLength: z.optional(z.int().check(z.positive())), rows: z.optional(z.int().check(z.positive())) }),\n z.object({ ...base, type: z.literal(\"richtext\") }),\n z.object({ ...base, type: z.literal(\"number\"), min: z.optional(z.number()), max: z.optional(z.number()), step: z.optional(z.number()) }),\n z.object({ ...base, type: z.literal(\"slider\"), min: z.number(), max: z.number(), step: z.optional(z.number()) }),\n z.object({ ...base, type: z.literal(\"switch\") }),\n z.object({ ...base, type: z.literal(\"select\"), options: z.array(selectOption).check(z.minLength(1)).check(z.maxLength(50)) }),\n z.object({ ...base, type: z.literal(\"date\") }),\n z.object({ ...base, type: z.literal(\"icon\") }),\n z.object({ ...base, type: z.literal(\"image\") }),\n z.object({ ...base, type: z.literal(\"url\") }),\n z.object({ ...base, type: z.literal(\"link\") }),\n z.object({ ...base, type: z.literal(\"group\"), fields: z.array(FieldSchema).check(z.maxLength(30)) }),\n z.object({ ...base, type: z.literal(\"repeater\"), fields: z.array(FieldSchema).check(z.maxLength(30)), max: z.optional(z.int().check(z.positive())), itemLabel: z.optional(z.string()) }),\n z.object({ ...base, type: z.literal(\"pageRef\") }),\n z.object({ ...base, type: z.literal(\"info\"), text: z.string() }),\n z.object({ ...base, type: z.literal(\"json\") }),\n ]),\n) as z.ZodMiniType<Field>;\n\n/** Een lijst velddefinities (bv. van een custom block). Unieke sleutels afgedwongen. */\nexport const FieldsSchema = z.array(FieldSchema).check(z.maxLength(40)).check((ctx) => {\n const seen = new Set<string>();\n for (const f of ctx.value) {\n if (seen.has(f.key)) ctx.issues.push({ code: \"custom\", input: ctx.value, message: `dubbele veldsleutel \"${f.key}\"` });\n seen.add(f.key);\n }\n });\n\n/**\n * Rich-text-conventie (security): de sanitizer saneert alleen velden die `html` heten of op\n * `Html` eindigen. Een `richtext`-veld MOET dus zo'n sleutel hebben — afgedwongen waar Field-IR\n * als data binnenkomt (custom blocks), zodat er geen stored-XSS-gat ontstaat.\n */\nexport function isRichTextKey(key: string): boolean {\n return key === \"html\" || key.endsWith(\"Html\");\n}\n\n/** Waarde-sleutel van een link-veld: `{ label, href }`. */\nconst linkValue = z.object({ label: z._default(z.string().check(z.maxLength(200)), \"\"), href: z._default(z.string().check(z.maxLength(2000)), \"\") });\n\n/**\n * Genereert een Zod-waardenschema uit een Field-IR — de brug die runtime-gedefinieerde blokken\n * (custom blocks) dezelfde harde validatie geeft als code-gedefinieerde blokken. Alle velden\n * krijgen `.default()`/`.optional()` (update-veilig: bestaande content blijft geldig als er\n * velden bijkomen). `info`-velden zijn display-only en krijgen geen waarde.\n */\nexport function fieldsToZod(fields: Field[]): z.ZodMiniObject<Record<string, ZodTypeAny>> {\n const shape: Record<string, ZodTypeAny> = {};\n for (const f of fields) {\n const s = fieldToZod(f);\n if (s) shape[f.key] = f.label ? s.register(z.globalRegistry, { description: f.label }) : s;\n }\n return z.object(shape);\n}\n\nfunction fieldToZod(f: Field): ZodTypeAny | null {\n switch (f.type) {\n case \"text\":\n return z._default(z.string().check(z.maxLength(f.maxLength ?? 500)), \"\");\n case \"textarea\":\n return z._default(z.string().check(z.maxLength(f.maxLength ?? 5000)), \"\");\n case \"richtext\":\n return z._default(z.string().check(z.maxLength(50_000)), \"\");\n case \"number\": {\n let n = z.number();\n if (f.min != null) n = n.check(z.minimum(f.min));\n if (f.max != null) n = n.check(z.maximum(f.max));\n return z.optional(n);\n }\n case \"slider\":\n return z._default(z.number().check(z.minimum(f.min)).check(z.maximum(f.max)), f.min);\n case \"switch\":\n return z._default(z.boolean(), false);\n case \"select\": {\n const values = f.options.map((o) => o.value);\n return values.length > 0\n ? z._default(z.enum([values[0], ...values.slice(1)] as [string, ...string[]]), values[0])\n : z._default(z.string(), \"\");\n }\n case \"date\":\n // ISO-datum (yyyy-mm-dd) of leeg.\n return z._default(z.string().check(z.regex(/^(\\d{4}-\\d{2}-\\d{2})?$/, \"datum als jjjj-mm-dd\")), \"\");\n case \"icon\":\n return z._default(z.string().check(z.maxLength(16)), \"\");\n case \"image\":\n case \"url\":\n return z._default(z.string().check(z.maxLength(2000)), \"\");\n case \"link\":\n return z._default(linkValue, { label: \"\", href: \"\" });\n case \"group\":\n return z._default(fieldsToZod(f.fields), {});\n case \"repeater\":\n return z._default(z.array(fieldsToZod(f.fields)).check(z.maxLength(f.max ?? 100)), []);\n case \"pageRef\":\n // Pad van een pagina binnen de site (\"/\", \"/contact\", …).\n return z._default(z.string().check(z.maxLength(500)), \"\");\n case \"info\":\n return null;\n case \"json\":\n return z.optional(z.unknown());\n }\n}\n\n/** Default-waarden voor een Field-IR (bv. een nieuw repeater-item). */\nexport function fieldsDefaults(fields: Field[]): Record<string, unknown> {\n return fieldsToZod(fields).parse({});\n}\n\n/**\n * Hints per veldsleutel (dotted path voor geneste velden, bv. \"items.date\") — verfijnt de uit een\n * Zod-schema afgeleide Field-IR. Gebruikt door `defineBlock({ fields })` + `introspectToFields`.\n */\nexport type FieldHints = Record<string, Partial<Field> & { type?: Field[\"type\"] }>;\n\n/** Evalueert `showIf` tegen de huidige waarden (zelfde niveau). Zonder showIf → altijd tonen. */\nexport function isFieldVisible(f: Field, values: Record<string, unknown>): boolean {\n if (!f.showIf) return true;\n const v = values[f.showIf.field];\n if (f.showIf.equals !== undefined) return v === f.showIf.equals;\n return Boolean(v);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/schema/fields.ts"],"sourcesContent":["/**\n * Field-IR (\"intermediate representation\") — het declaratieve veldmodel dat formulieren aandrijft.\n *\n * Geport concept + modelvorm uit primo (github.com/primocms/primo, MIT © Matthew Morris) — zie\n * THIRD_PARTY_LICENSES.md. Primo definieert velden als een Zod discriminated union met een\n * `config`-blob per type, nesting zonder recursieve schema's en conditionele velden (`Condition`).\n * XiCMS gebruikt dit model op twee plekken:\n *\n * 1. **Afgeleid**: `introspectToFields()` (admin/lib/zodFields.ts) leidt een Field-IR af uit de\n * bestaande Zod-block-schema's — de GenericEditor rendert die IR. De Zod-schema's blijven de\n * bron van waarheid; dit is puur de formulier-beschrijving.\n * 2. **Als data**: custom blocks (sites/{siteId}/customBlocks) slaan hun velddefinities als\n * Field-IR op in Firestore. `fieldsToZod()` genereert daaruit een echt Zod-schema zodat ook\n * runtime-gedefinieerde blokken de harde XiCMS-validatie houden.\n *\n * Server-safe (geen React). Nesting gaat via een `fields`-array in group/repeater — documentvorm,\n * geen aparte rows (Firestore-vriendelijk, en `z.lazy` dekt de recursie).\n */\nimport * as z from \"zod/mini\";\n\n/** Zod 4 heeft `ZodTypeAny` afgeschaft; in mini is `z.ZodType` de losse bovengrens. */\ntype ZodTypeAny = z.ZodMiniType;\n\n/** Conditioneel tonen: veld is zichtbaar als `field` (sibling-sleutel) matcht. */\nexport const ShowIfSchema = z.object({\n /** Sleutel van het veld (zelfde niveau) waarvan de waarde bepaalt of dit veld toont. */\n field: z.string().check(z.minLength(1)),\n /** Toon alléén bij exact deze waarde. Weggelaten → toon bij een truthy waarde. */\n equals: z.optional(z.union([z.string(), z.number(), z.boolean()])),\n});\nexport type ShowIf = z.infer<typeof ShowIfSchema>;\n\nconst base = {\n /** Sleutel in het waarden-object (dotted paths niet toegestaan; nesting via group/repeater). */\n key: z.string().check(z.minLength(1)).check(z.regex(/^[a-zA-Z][a-zA-Z0-9]*$/, \"veldsleutel: letters/cijfers, begint met letter\")),\n /** Leesbaar label (NL). */\n label: z._default(z.string(), \"\"),\n /** Optionele hint onder het veld. */\n hint: z.optional(z.string()),\n /** Conditioneel tonen (primo's Condition). */\n showIf: z.optional(ShowIfSchema),\n};\n\n/** Selectie-optie voor `select`. */\nconst selectOption = z.object({ value: z.string(), label: z._default(z.string(), \"\") });\n\n// ── Veldtypes (primo: Text, RichText, Number, Slider, Switch, Select, Date, Icon, Image, Url,\n// Link, Group, Repeater, Page, Info — hier op XiCMS-conventies gebracht) ──────────────────────\n\nexport type Field =\n | ({ type: \"text\"; maxLength?: number; placeholder?: string } & BaseShape)\n | ({ type: \"textarea\"; maxLength?: number; rows?: number } & BaseShape)\n | ({ type: \"richtext\" } & BaseShape)\n | ({ type: \"number\"; min?: number; max?: number; step?: number } & BaseShape)\n | ({ type: \"slider\"; min: number; max: number; step?: number } & BaseShape)\n | ({ type: \"switch\" } & BaseShape)\n | ({ type: \"select\"; options: { value: string; label: string }[]; /** Schema-default (8.10). */ standaard?: string } & BaseShape)\n | ({ type: \"date\" } & BaseShape)\n | ({ type: \"icon\" } & BaseShape)\n | ({ type: \"image\" } & BaseShape)\n | ({ type: \"url\" } & BaseShape)\n | ({ type: \"link\" } & BaseShape)\n | ({ type: \"group\"; fields: Field[] } & BaseShape)\n | ({ type: \"repeater\"; fields: Field[]; max?: number; itemLabel?: string } & BaseShape)\n | ({ type: \"pageRef\" } & BaseShape)\n | ({ type: \"info\"; text: string } & BaseShape)\n | ({ type: \"json\" } & BaseShape);\n\ntype BaseShape = { key: string; label: string; hint?: string; showIf?: ShowIf };\n\n/** Zod-schema voor één veld-definitie (recursief via z.lazy voor group/repeater). */\nexport const FieldSchema: z.ZodMiniType<Field> = z.lazy(() =>\n z.discriminatedUnion(\"type\", [\n z.object({ ...base, type: z.literal(\"text\"), maxLength: z.optional(z.int().check(z.positive())), placeholder: z.optional(z.string()) }),\n z.object({ ...base, type: z.literal(\"textarea\"), maxLength: z.optional(z.int().check(z.positive())), rows: z.optional(z.int().check(z.positive())) }),\n z.object({ ...base, type: z.literal(\"richtext\") }),\n z.object({ ...base, type: z.literal(\"number\"), min: z.optional(z.number()), max: z.optional(z.number()), step: z.optional(z.number()) }),\n z.object({ ...base, type: z.literal(\"slider\"), min: z.number(), max: z.number(), step: z.optional(z.number()) }),\n z.object({ ...base, type: z.literal(\"switch\") }),\n z.object({ ...base, type: z.literal(\"select\"), options: z.array(selectOption).check(z.minLength(1)).check(z.maxLength(50)) }),\n z.object({ ...base, type: z.literal(\"date\") }),\n z.object({ ...base, type: z.literal(\"icon\") }),\n z.object({ ...base, type: z.literal(\"image\") }),\n z.object({ ...base, type: z.literal(\"url\") }),\n z.object({ ...base, type: z.literal(\"link\") }),\n z.object({ ...base, type: z.literal(\"group\"), fields: z.array(FieldSchema).check(z.maxLength(30)) }),\n z.object({ ...base, type: z.literal(\"repeater\"), fields: z.array(FieldSchema).check(z.maxLength(30)), max: z.optional(z.int().check(z.positive())), itemLabel: z.optional(z.string()) }),\n z.object({ ...base, type: z.literal(\"pageRef\") }),\n z.object({ ...base, type: z.literal(\"info\"), text: z.string() }),\n z.object({ ...base, type: z.literal(\"json\") }),\n ]),\n) as z.ZodMiniType<Field>;\n\n/** Een lijst velddefinities (bv. van een custom block). Unieke sleutels afgedwongen. */\nexport const FieldsSchema = z.array(FieldSchema).check(z.maxLength(40)).check((ctx) => {\n const seen = new Set<string>();\n for (const f of ctx.value) {\n if (seen.has(f.key)) ctx.issues.push({ code: \"custom\", input: ctx.value, message: `dubbele veldsleutel \"${f.key}\"` });\n seen.add(f.key);\n }\n });\n\n/**\n * Rich-text-conventie (security): de sanitizer saneert alleen velden die `html` heten of op\n * `Html` eindigen. Een `richtext`-veld MOET dus zo'n sleutel hebben — afgedwongen waar Field-IR\n * als data binnenkomt (custom blocks), zodat er geen stored-XSS-gat ontstaat.\n */\nexport function isRichTextKey(key: string): boolean {\n return key === \"html\" || key.endsWith(\"Html\");\n}\n\n/** Waarde-sleutel van een link-veld: `{ label, href }`. */\nconst linkValue = z.object({ label: z._default(z.string().check(z.maxLength(200)), \"\"), href: z._default(z.string().check(z.maxLength(2000)), \"\") });\n\n/**\n * Genereert een Zod-waardenschema uit een Field-IR — de brug die runtime-gedefinieerde blokken\n * (custom blocks) dezelfde harde validatie geeft als code-gedefinieerde blokken. Alle velden\n * krijgen `.default()`/`.optional()` (update-veilig: bestaande content blijft geldig als er\n * velden bijkomen). `info`-velden zijn display-only en krijgen geen waarde.\n */\nexport function fieldsToZod(fields: Field[]): z.ZodMiniObject<Record<string, ZodTypeAny>> {\n const shape: Record<string, ZodTypeAny> = {};\n for (const f of fields) {\n const s = fieldToZod(f);\n if (s) shape[f.key] = f.label ? s.register(z.globalRegistry, { description: f.label }) : s;\n }\n return z.object(shape);\n}\n\nfunction fieldToZod(f: Field): ZodTypeAny | null {\n switch (f.type) {\n case \"text\":\n return z._default(z.string().check(z.maxLength(f.maxLength ?? 500)), \"\");\n case \"textarea\":\n return z._default(z.string().check(z.maxLength(f.maxLength ?? 5000)), \"\");\n case \"richtext\":\n return z._default(z.string().check(z.maxLength(50_000)), \"\");\n case \"number\": {\n let n = z.number();\n if (f.min != null) n = n.check(z.minimum(f.min));\n if (f.max != null) n = n.check(z.maximum(f.max));\n return z.optional(n);\n }\n case \"slider\":\n return z._default(z.number().check(z.minimum(f.min)).check(z.maximum(f.max)), f.min);\n case \"switch\":\n return z._default(z.boolean(), false);\n case \"select\": {\n const values = f.options.map((o) => o.value);\n return values.length > 0\n ? z._default(z.enum([values[0], ...values.slice(1)] as [string, ...string[]]), values[0])\n : z._default(z.string(), \"\");\n }\n case \"date\":\n // ISO-datum (yyyy-mm-dd) of leeg.\n return z._default(z.string().check(z.regex(/^(\\d{4}-\\d{2}-\\d{2})?$/, \"datum als jjjj-mm-dd\")), \"\");\n case \"icon\":\n return z._default(z.string().check(z.maxLength(16)), \"\");\n case \"image\":\n case \"url\":\n return z._default(z.string().check(z.maxLength(2000)), \"\");\n case \"link\":\n return z._default(linkValue, { label: \"\", href: \"\" });\n case \"group\":\n return z._default(fieldsToZod(f.fields), {});\n case \"repeater\":\n return z._default(z.array(fieldsToZod(f.fields)).check(z.maxLength(f.max ?? 100)), []);\n case \"pageRef\":\n // Pad van een pagina binnen de site (\"/\", \"/contact\", …).\n return z._default(z.string().check(z.maxLength(500)), \"\");\n case \"info\":\n return null;\n case \"json\":\n return z.optional(z.unknown());\n }\n}\n\n/** Default-waarden voor een Field-IR (bv. een nieuw repeater-item). */\nexport function fieldsDefaults(fields: Field[]): Record<string, unknown> {\n return fieldsToZod(fields).parse({});\n}\n\n/**\n * Hints per veldsleutel (dotted path voor geneste velden, bv. \"items.date\") — verfijnt de uit een\n * Zod-schema afgeleide Field-IR. Gebruikt door `defineBlock({ fields })` + `introspectToFields`.\n */\nexport type FieldHints = Record<string, Partial<Field> & { type?: Field[\"type\"] }>;\n\n/** Evalueert `showIf` tegen de huidige waarden (zelfde niveau). Zonder showIf → altijd tonen. */\nexport function isFieldVisible(f: Field, values: Record<string, unknown>): boolean {\n if (!f.showIf) return true;\n const v = values[f.showIf.field];\n if (f.showIf.equals !== undefined) return v === f.showIf.equals;\n return Boolean(v);\n}\n"],"mappings":"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","names":[]}
@@ -2,7 +2,9 @@ import * as z from "zod/mini";
2
2
  export declare const FieldTypeSchema: z.ZodMiniEnum<{
3
3
  checkbox: "checkbox";
4
4
  date: "date";
5
+ dateRange: "dateRange";
5
6
  email: "email";
7
+ hidden: "hidden";
6
8
  number: "number";
7
9
  radio: "radio";
8
10
  select: "select";
@@ -17,7 +19,9 @@ export declare const FormFieldSchema: z.ZodMiniObject<{
17
19
  type: z.ZodMiniEnum<{
18
20
  checkbox: "checkbox";
19
21
  date: "date";
22
+ dateRange: "dateRange";
20
23
  email: "email";
24
+ hidden: "hidden";
21
25
  number: "number";
22
26
  radio: "radio";
23
27
  select: "select";
@@ -39,7 +43,9 @@ export declare const FormSchema: z.ZodMiniObject<{
39
43
  type: z.ZodMiniEnum<{
40
44
  checkbox: "checkbox";
41
45
  date: "date";
46
+ dateRange: "dateRange";
42
47
  email: "email";
48
+ hidden: "hidden";
43
49
  number: "number";
44
50
  radio: "radio";
45
51
  select: "select";
@@ -58,6 +64,18 @@ export declare const FormSchema: z.ZodMiniObject<{
58
64
  notifyTo: z.ZodMiniOptional<z.ZodMiniString<string>>;
59
65
  }, z.core.$strip>;
60
66
  export type FormDefinition = z.infer<typeof FormSchema>;
67
+ /**
68
+ * Mailinstellingen van een formulier (8.1) — `sites/{siteId}/forms/{formId}/private/mail`. Stond
69
+ * eerst op het publiek leesbare formulierdocument, waardoor iedereen het kopie-adres van de
70
+ * winkelier kon uitlezen. De Functions lezen hier, met de oude velden als terugval.
71
+ */
72
+ export declare const FormMailSchema: z.ZodMiniObject<{
73
+ notifyTo: z.ZodMiniOptional<z.ZodMiniString<string>>;
74
+ confirmSubmitter: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
75
+ }, z.core.$strip>;
76
+ export type FormMail = z.infer<typeof FormMailSchema>;
77
+ /** Alleen een pad op de eigen site: begint met één `/` (geen `//host`, geen `javascript:`). */
78
+ export declare function isVeiligPad(p: string | undefined): p is string;
61
79
  /** Payload van een inzending (callable input). Per-veld-validatie gebeurt server-side
62
80
  * tegen de opgeslagen formulierdefinitie. */
63
81
  export declare const SubmissionInputSchema: z.ZodMiniObject<{
@@ -1,4 +1,5 @@
1
1
  import * as z from "zod/mini";
2
+ const VEILIG_PAD = /^\/(?![\/\\])[^\s]*$/;
2
3
  const FieldTypeSchema = z.enum([
3
4
  "text",
4
5
  "email",
@@ -9,7 +10,12 @@ const FieldTypeSchema = z.enum([
9
10
  // 4.16: update-veilig toegevoegd (oude definities blijven geldig).
10
11
  "radio",
11
12
  "date",
12
- "number"
13
+ "number",
14
+ // 8.14: aankomst–vertrek (verhuur, inschrijving voor een periode): "2026-07-01/2026-07-08".
15
+ "dateRange",
16
+ // 8.14: verborgen veld met een vaste waarde (placeholder) of een waarde uit het webadres
17
+ // (?veldnaam=…) — bv. welk huisje of welke behandeling de bezoeker koos.
18
+ "hidden"
13
19
  ]);
14
20
  const FormFieldSchema = z.object({
15
21
  /** Stabiele sleutel; wordt de key in de inzending. */
@@ -27,7 +33,7 @@ const FormSchema = z.object({
27
33
  submitLabel: z._default(z.string().check(z.maxLength(80)), "Versturen"),
28
34
  successMessage: z._default(z.string().check(z.maxLength(500)), "Bedankt! We nemen snel contact op."),
29
35
  /** Stuur na een geslaagde inzending door naar deze pagina (bv. een bedankt-pagina). */
30
- successRedirect: z.optional(z.string().check(z.maxLength(400))),
36
+ successRedirect: z.optional(z.string().check(z.maxLength(400)).check(z.regex(VEILIG_PAD, "de bedankt-pagina moet een pad op je eigen site zijn, bv. /bedankt"))),
31
37
  /** Stuur de inzender een bevestigingsmail/kopie (naar het eerste e-mailveld van het formulier). */
32
38
  confirmSubmitter: z.optional(z.boolean()),
33
39
  /**
@@ -36,6 +42,13 @@ const FormSchema = z.object({
36
42
  */
37
43
  notifyTo: z.optional(z.string().check(z.maxLength(200)))
38
44
  });
45
+ const FormMailSchema = z.object({
46
+ notifyTo: z.optional(z.string().check(z.maxLength(200))),
47
+ confirmSubmitter: z.optional(z.boolean())
48
+ });
49
+ function isVeiligPad(p) {
50
+ return typeof p === "string" && VEILIG_PAD.test(p);
51
+ }
39
52
  const SubmissionInputSchema = z.object({
40
53
  siteId: z.string().check(z.minLength(1)).check(z.maxLength(80)),
41
54
  formId: z.string().check(z.minLength(1)).check(z.maxLength(80)),
@@ -46,7 +59,9 @@ const SubmissionInputSchema = z.object({
46
59
  export {
47
60
  FieldTypeSchema,
48
61
  FormFieldSchema,
62
+ FormMailSchema,
49
63
  FormSchema,
50
- SubmissionInputSchema
64
+ SubmissionInputSchema,
65
+ isVeiligPad
51
66
  };
52
67
  //# sourceMappingURL=forms.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/schema/forms.ts"],"sourcesContent":["import * as z from \"zod/mini\";\n\nexport const FieldTypeSchema = z.enum([\n \"text\",\n \"email\",\n \"tel\",\n \"textarea\",\n \"select\",\n \"checkbox\",\n // 4.16: update-veilig toegevoegd (oude definities blijven geldig).\n \"radio\",\n \"date\",\n \"number\",\n]);\nexport type FieldType = z.infer<typeof FieldTypeSchema>;\n\nexport const FormFieldSchema = z.object({\n /** Stabiele sleutel; wordt de key in de inzending. */\n name: z.string().check(z.minLength(1)).check(z.maxLength(60)).check(z.regex(/^[a-zA-Z][a-zA-Z0-9_]*$/, \"veldnaam moet met een letter beginnen en alleen letters/cijfers/_ bevatten\")),\n label: z.string().check(z.minLength(1)).check(z.maxLength(160)),\n type: FieldTypeSchema,\n required: z._default(z.boolean(), false),\n placeholder: z.optional(z.string().check(z.maxLength(200))),\n /** Opties voor type \"select\" en \"radio\". */\n options: z.optional(z.array(z.string().check(z.maxLength(200))).check(z.maxLength(50))),\n});\nexport type FormField = z.infer<typeof FormFieldSchema>;\n\n/** Een formulierdefinitie: `sites/{siteId}/forms/{formId}`. */\nexport const FormSchema = z.object({\n name: z.string().check(z.minLength(1)).check(z.maxLength(160)),\n fields: z.array(FormFieldSchema).check(z.minLength(1)).check(z.maxLength(40)),\n submitLabel: z._default(z.string().check(z.maxLength(80)), \"Versturen\"),\n successMessage: z._default(z.string().check(z.maxLength(500)), \"Bedankt! We nemen snel contact op.\"),\n /** Stuur na een geslaagde inzending door naar deze pagina (bv. een bedankt-pagina). */\n successRedirect: z.optional(z.string().check(z.maxLength(400))),\n /** Stuur de inzender een bevestigingsmail/kopie (naar het eerste e-mailveld van het formulier). */\n confirmSubmitter: z.optional(z.boolean()),\n /**\n * Kopie van elke inzending naar dit e-mailadres. Leeg = de site-brede notificatie-instelling\n * (Instellingen → E-mail → notificatie-adres, anders het contact-e-mailadres van de site).\n */\n notifyTo: z.optional(z.string().check(z.maxLength(200))),\n});\nexport type FormDefinition = z.infer<typeof FormSchema>;\n\n/** Payload van een inzending (callable input). Per-veld-validatie gebeurt server-side\n * tegen de opgeslagen formulierdefinitie. */\nexport const SubmissionInputSchema = z.object({\n siteId: z.string().check(z.minLength(1)).check(z.maxLength(80)),\n formId: z.string().check(z.minLength(1)).check(z.maxLength(80)),\n values: z.record(z.string(), z.union([z.string().check(z.maxLength(5000)), z.boolean()])),\n /** Honeypot — moet leeg zijn (bot-detectie). */\n _hp: z.optional(z.string().check(z.maxLength(0))),\n});\nexport type SubmissionInput = z.infer<typeof SubmissionInputSchema>;\n"],"mappings":"AAAA,YAAY,OAAO;AAEZ,MAAM,kBAAkB,EAAE,KAAK;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,MAAM,kBAAkB,EAAE,OAAO;AAAA;AAAA,EAEtC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,2BAA2B,4EAA4E,CAAC;AAAA,EACpL,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC;AAAA,EAC9D,MAAM;AAAA,EACN,UAAU,EAAE,SAAS,EAAE,QAAQ,GAAG,KAAK;AAAA,EACvC,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC;AAAA;AAAA,EAE1D,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AACxF,CAAC;AAIM,MAAM,aAAa,EAAE,OAAO;AAAA,EACjC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC;AAAA,EAC7D,QAAQ,EAAE,MAAM,eAAe,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAAA,EAC5E,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,GAAG,WAAW;AAAA,EACtE,gBAAgB,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,GAAG,oCAAoC;AAAA;AAAA,EAEnG,iBAAiB,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC;AAAA;AAAA,EAE9D,kBAAkB,EAAE,SAAS,EAAE,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxC,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC;AACzD,CAAC;AAKM,MAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAAA,EAC9D,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAAA,EAC9D,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;AAAA;AAAA,EAExF,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;AAClD,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/schema/forms.ts"],"sourcesContent":["import * as z from \"zod/mini\";\n\n/** Alleen een pad op de eigen site (8.1): geen open redirect via de bedankt-pagina. */\nconst VEILIG_PAD = /^\\/(?![\\/\\\\])[^\\s]*$/;\n\nexport const FieldTypeSchema = z.enum([\n \"text\",\n \"email\",\n \"tel\",\n \"textarea\",\n \"select\",\n \"checkbox\",\n // 4.16: update-veilig toegevoegd (oude definities blijven geldig).\n \"radio\",\n \"date\",\n \"number\",\n // 8.14: aankomst–vertrek (verhuur, inschrijving voor een periode): \"2026-07-01/2026-07-08\".\n \"dateRange\",\n // 8.14: verborgen veld met een vaste waarde (placeholder) of een waarde uit het webadres\n // (?veldnaam=…) — bv. welk huisje of welke behandeling de bezoeker koos.\n \"hidden\",\n]);\nexport type FieldType = z.infer<typeof FieldTypeSchema>;\n\nexport const FormFieldSchema = z.object({\n /** Stabiele sleutel; wordt de key in de inzending. */\n name: z.string().check(z.minLength(1)).check(z.maxLength(60)).check(z.regex(/^[a-zA-Z][a-zA-Z0-9_]*$/, \"veldnaam moet met een letter beginnen en alleen letters/cijfers/_ bevatten\")),\n label: z.string().check(z.minLength(1)).check(z.maxLength(160)),\n type: FieldTypeSchema,\n required: z._default(z.boolean(), false),\n placeholder: z.optional(z.string().check(z.maxLength(200))),\n /** Opties voor type \"select\" en \"radio\". */\n options: z.optional(z.array(z.string().check(z.maxLength(200))).check(z.maxLength(50))),\n});\nexport type FormField = z.infer<typeof FormFieldSchema>;\n\n/** Een formulierdefinitie: `sites/{siteId}/forms/{formId}`. */\nexport const FormSchema = z.object({\n name: z.string().check(z.minLength(1)).check(z.maxLength(160)),\n fields: z.array(FormFieldSchema).check(z.minLength(1)).check(z.maxLength(40)),\n submitLabel: z._default(z.string().check(z.maxLength(80)), \"Versturen\"),\n successMessage: z._default(z.string().check(z.maxLength(500)), \"Bedankt! We nemen snel contact op.\"),\n /** Stuur na een geslaagde inzending door naar deze pagina (bv. een bedankt-pagina). */\n successRedirect: z.optional(z.string().check(z.maxLength(400)).check(z.regex(VEILIG_PAD, \"de bedankt-pagina moet een pad op je eigen site zijn, bv. /bedankt\"))),\n /** Stuur de inzender een bevestigingsmail/kopie (naar het eerste e-mailveld van het formulier). */\n confirmSubmitter: z.optional(z.boolean()),\n /**\n * Kopie van elke inzending naar dit e-mailadres. Leeg = de site-brede notificatie-instelling\n * (Instellingen → E-mail → notificatie-adres, anders het contact-e-mailadres van de site).\n */\n notifyTo: z.optional(z.string().check(z.maxLength(200))),\n});\nexport type FormDefinition = z.infer<typeof FormSchema>;\n\n/**\n * Mailinstellingen van een formulier (8.1) — `sites/{siteId}/forms/{formId}/private/mail`. Stond\n * eerst op het publiek leesbare formulierdocument, waardoor iedereen het kopie-adres van de\n * winkelier kon uitlezen. De Functions lezen hier, met de oude velden als terugval.\n */\nexport const FormMailSchema = z.object({\n notifyTo: z.optional(z.string().check(z.maxLength(200))),\n confirmSubmitter: z.optional(z.boolean()),\n});\nexport type FormMail = z.infer<typeof FormMailSchema>;\n\n/** Alleen een pad op de eigen site: begint met één `/` (geen `//host`, geen `javascript:`). */\nexport function isVeiligPad(p: string | undefined): p is string {\n return typeof p === \"string\" && VEILIG_PAD.test(p);\n}\n\n/** Payload van een inzending (callable input). Per-veld-validatie gebeurt server-side\n * tegen de opgeslagen formulierdefinitie. */\nexport const SubmissionInputSchema = z.object({\n siteId: z.string().check(z.minLength(1)).check(z.maxLength(80)),\n formId: z.string().check(z.minLength(1)).check(z.maxLength(80)),\n values: z.record(z.string(), z.union([z.string().check(z.maxLength(5000)), z.boolean()])),\n /** Honeypot — moet leeg zijn (bot-detectie). */\n _hp: z.optional(z.string().check(z.maxLength(0))),\n});\nexport type SubmissionInput = z.infer<typeof SubmissionInputSchema>;\n"],"mappings":"AAAA,YAAY,OAAO;AAGnB,MAAM,aAAa;AAEZ,MAAM,kBAAkB,EAAE,KAAK;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA;AAAA;AAAA,EAGA;AACF,CAAC;AAGM,MAAM,kBAAkB,EAAE,OAAO;AAAA;AAAA,EAEtC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,2BAA2B,4EAA4E,CAAC;AAAA,EACpL,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC;AAAA,EAC9D,MAAM;AAAA,EACN,UAAU,EAAE,SAAS,EAAE,QAAQ,GAAG,KAAK;AAAA,EACvC,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC;AAAA;AAAA,EAE1D,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;AACxF,CAAC;AAIM,MAAM,aAAa,EAAE,OAAO;AAAA,EACjC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC;AAAA,EAC7D,QAAQ,EAAE,MAAM,eAAe,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAAA,EAC5E,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,GAAG,WAAW;AAAA,EACtE,gBAAgB,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,GAAG,oCAAoC;AAAA;AAAA,EAEnG,iBAAiB,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,YAAY,oEAAoE,CAAC,CAAC;AAAA;AAAA,EAE/J,kBAAkB,EAAE,SAAS,EAAE,QAAQ,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAKxC,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC;AACzD,CAAC;AAQM,MAAM,iBAAiB,EAAE,OAAO;AAAA,EACrC,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC;AAAA,EACvD,kBAAkB,EAAE,SAAS,EAAE,QAAQ,CAAC;AAC1C,CAAC;AAIM,SAAS,YAAY,GAAoC;AAC9D,SAAO,OAAO,MAAM,YAAY,WAAW,KAAK,CAAC;AACnD;AAIO,MAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAAA,EAC9D,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAAA,EAC9D,QAAQ,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;AAAA;AAAA,EAExF,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;AAClD,CAAC;","names":[]}
@@ -45,6 +45,12 @@ export declare const MAIL_TEMPLATE_DEFS: readonly [{
45
45
  readonly hint: "Naar de klant wanneer je de status op ‘verzonden’ zet.";
46
46
  readonly module: "shop";
47
47
  readonly placeholders: "{{naam}} {{ordernummer}} {{regels}} {{trackingUrl}} {{verzendadres}} {{sitenaam}}";
48
+ }, {
49
+ readonly key: "orderPickupReady";
50
+ readonly label: "Bestelling klaar om af te halen";
51
+ readonly hint: "Naar de klant wanneer je een af te halen bestelling op ‘verzonden’ zet.";
52
+ readonly module: "shop";
53
+ readonly placeholders: "{{naam}} {{ordernummer}} {{regels}} {{verzendadres}} {{sitenaam}}";
48
54
  }, {
49
55
  readonly key: "orderCancelled";
50
56
  readonly label: "Bestelling geannuleerd";
@@ -107,6 +113,10 @@ export declare const MailTemplatesSchema: z.ZodMiniObject<{
107
113
  subject: z.ZodMiniOptional<z.ZodMiniString<string>>;
108
114
  bodyText: z.ZodMiniOptional<z.ZodMiniString<string>>;
109
115
  }, z.core.$strip>>;
116
+ orderPickupReady: z.ZodMiniOptional<z.ZodMiniObject<{
117
+ subject: z.ZodMiniOptional<z.ZodMiniString<string>>;
118
+ bodyText: z.ZodMiniOptional<z.ZodMiniString<string>>;
119
+ }, z.core.$strip>>;
110
120
  orderRefunded: z.ZodMiniOptional<z.ZodMiniObject<{
111
121
  subject: z.ZodMiniOptional<z.ZodMiniString<string>>;
112
122
  bodyText: z.ZodMiniOptional<z.ZodMiniString<string>>;
@@ -35,6 +35,13 @@ const MAIL_TEMPLATE_DEFS = [
35
35
  module: "shop",
36
36
  placeholders: "{{naam}} {{ordernummer}} {{regels}} {{trackingUrl}} {{verzendadres}} {{sitenaam}}"
37
37
  },
38
+ {
39
+ key: "orderPickupReady",
40
+ label: "Bestelling klaar om af te halen",
41
+ hint: "Naar de klant wanneer je een af te halen bestelling op \u2018verzonden\u2019 zet.",
42
+ module: "shop",
43
+ placeholders: "{{naam}} {{ordernummer}} {{regels}} {{verzendadres}} {{sitenaam}}"
44
+ },
38
45
  {
39
46
  key: "orderCancelled",
40
47
  label: "Bestelling geannuleerd",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/schema/mail.ts"],"sourcesContent":["import * as z from \"zod/mini\";\n\n/**\n * E-mailtemplates (site-breed, 3.7) — `sites/{siteId}/settings/mailTemplates`. Per template een\n * onderwerp + platte-tekst-body met `{{placeholders}}`. Bewust géén HTML van beheerders; de\n * huisstijl-opmaak komt in de mail-pipeline (functions `mailLayout.ts`) om de tekst heen.\n *\n * De keys zijn getagd met de module waartoe ze horen (`core`/`shop`), zodat de editor in /beheer\n * shop-templates alleen toont op sites met de webwinkel. `core`-keys (formulieren) gelden altijd.\n */\n\nexport interface MailTemplateDef {\n key: string;\n label: string;\n hint: string;\n module: \"core\" | \"shop\";\n /** Beschikbare invulvelden, als tonende hint in de editor. */\n placeholders: string;\n}\n\nexport const MAIL_TEMPLATE_DEFS = [\n {\n key: \"formNotification\",\n label: \"Formulier-notificatie (naar jou)\",\n hint: \"Naar jou zodra iemand een formulier invult.\",\n module: \"core\",\n placeholders: \"{{sitenaam}} {{formulier}} {{regels}}\",\n },\n {\n key: \"formConfirmation\",\n label: \"Formulier-bevestiging (naar de inzender)\",\n hint: \"Ontvangstbevestiging naar wie het formulier invulde.\",\n module: \"core\",\n placeholders: \"{{sitenaam}} {{formulier}} {{regels}}\",\n },\n {\n key: \"orderConfirmation\",\n label: \"Bestelbevestiging\",\n hint: \"Naar de klant zodra de betaling binnen is — met factuur-PDF als bijlage.\",\n module: \"shop\",\n placeholders: \"{{naam}} {{ordernummer}} {{regels}} {{totaal}} {{verzendadres}} {{notitie}} {{sitenaam}}\",\n },\n {\n key: \"shopkeeperNotification\",\n label: \"Nieuwe-bestelling-notificatie (naar jou)\",\n hint: \"Naar jou bij elke nieuwe bestelling.\",\n module: \"shop\",\n placeholders: \"{{sitenaam}} {{ordernummer}} {{totaal}} {{klant}} {{regels}} {{verzendadres}} {{notitie}}\",\n },\n {\n key: \"orderShipped\",\n label: \"Bestelling verzonden\",\n hint: \"Naar de klant wanneer je de status op ‘verzonden’ zet.\",\n module: \"shop\",\n placeholders: \"{{naam}} {{ordernummer}} {{regels}} {{trackingUrl}} {{verzendadres}} {{sitenaam}}\",\n },\n {\n key: \"orderCancelled\",\n label: \"Bestelling geannuleerd\",\n hint: \"Naar de klant bij annulering.\",\n module: \"shop\",\n placeholders: \"{{naam}} {{ordernummer}} {{sitenaam}}\",\n },\n {\n key: \"shopkeeperOrderCancelled\",\n label: \"Bestelling geannuleerd (naar jou)\",\n hint: \"Naar jou bij elke annulering — ook automatisch (bv. een verlopen betaling).\",\n module: \"shop\",\n placeholders: \"{{sitenaam}} {{ordernummer}} {{totaal}} {{klant}} {{regels}}\",\n },\n {\n key: \"paymentRequest\",\n label: \"Betaalverzoek\",\n hint: \"Naar de klant als je vanuit een openstaande bestelling een betaallink verstuurt.\",\n module: \"shop\",\n placeholders: \"{{naam}} {{ordernummer}} {{betaallink}} {{regels}} {{totaal}} {{verzendadres}} {{sitenaam}}\",\n },\n {\n key: \"orderRefunded\",\n label: \"Terugbetaald\",\n hint: \"Naar de klant na een terugbetaling.\",\n module: \"shop\",\n placeholders: \"{{naam}} {{ordernummer}} {{totaal}} {{sitenaam}}\",\n },\n {\n key: \"donationThanks\",\n label: \"Donatie-bedankje\",\n hint: \"Naar de gever na een donatie.\",\n module: \"shop\",\n placeholders: \"{{naam}} {{regels}} {{sitenaam}}\",\n },\n] as const satisfies readonly MailTemplateDef[];\n\nexport const MAIL_TEMPLATE_KEYS = MAIL_TEMPLATE_DEFS.map((d) => d.key) as unknown as readonly MailTemplateKey[];\nexport type MailTemplateKey = (typeof MAIL_TEMPLATE_DEFS)[number][\"key\"];\n\n/** Formulier-mails — bewerkbaar in het Formulieren-gedeelte. */\nexport const FORM_TEMPLATE_KEYS = MAIL_TEMPLATE_DEFS.filter((d) => d.module === \"core\").map((d) => d.key) as readonly MailTemplateKey[];\n/** Shop-mails — bewerkbaar in het Webwinkel-gedeelte. */\nexport const SHOP_TEMPLATE_KEYS = MAIL_TEMPLATE_DEFS.filter((d) => d.module === \"shop\").map((d) => d.key) as readonly MailTemplateKey[];\n\nexport const MailTemplateSchema = z.object({\n subject: z.optional(z.string().check(z.maxLength(200))),\n bodyText: z.optional(z.string().check(z.maxLength(10_000))),\n});\nexport const MailTemplatesSchema = z.object(\n Object.fromEntries(MAIL_TEMPLATE_DEFS.map((d) => [d.key, z.optional(MailTemplateSchema)])) as Record<\n MailTemplateKey,\n z.ZodMiniOptional<typeof MailTemplateSchema>\n >,\n);\nexport type MailTemplates = z.infer<typeof MailTemplatesSchema>;\n"],"mappings":"AAAA,YAAY,OAAO;AAoBZ,MAAM,qBAAqB;AAAA,EAChC;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AACF;AAEO,MAAM,qBAAqB,mBAAmB,IAAI,CAAC,MAAM,EAAE,GAAG;AAI9D,MAAM,qBAAqB,mBAAmB,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG;AAEjG,MAAM,qBAAqB,mBAAmB,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG;AAEjG,MAAM,qBAAqB,EAAE,OAAO;AAAA,EACzC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC;AAAA,EACtD,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAM,CAAC,CAAC;AAC5D,CAAC;AACM,MAAM,sBAAsB,EAAE;AAAA,EACnC,OAAO,YAAY,mBAAmB,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,SAAS,kBAAkB,CAAC,CAAC,CAAC;AAI3F;","names":[]}
1
+ {"version":3,"sources":["../../src/schema/mail.ts"],"sourcesContent":["import * as z from \"zod/mini\";\n\n/**\n * E-mailtemplates (site-breed, 3.7) — `sites/{siteId}/settings/mailTemplates`. Per template een\n * onderwerp + platte-tekst-body met `{{placeholders}}`. Bewust géén HTML van beheerders; de\n * huisstijl-opmaak komt in de mail-pipeline (functions `mailLayout.ts`) om de tekst heen.\n *\n * De keys zijn getagd met de module waartoe ze horen (`core`/`shop`), zodat de editor in /beheer\n * shop-templates alleen toont op sites met de webwinkel. `core`-keys (formulieren) gelden altijd.\n */\n\nexport interface MailTemplateDef {\n key: string;\n label: string;\n hint: string;\n module: \"core\" | \"shop\";\n /** Beschikbare invulvelden, als tonende hint in de editor. */\n placeholders: string;\n}\n\nexport const MAIL_TEMPLATE_DEFS = [\n {\n key: \"formNotification\",\n label: \"Formulier-notificatie (naar jou)\",\n hint: \"Naar jou zodra iemand een formulier invult.\",\n module: \"core\",\n placeholders: \"{{sitenaam}} {{formulier}} {{regels}}\",\n },\n {\n key: \"formConfirmation\",\n label: \"Formulier-bevestiging (naar de inzender)\",\n hint: \"Ontvangstbevestiging naar wie het formulier invulde.\",\n module: \"core\",\n placeholders: \"{{sitenaam}} {{formulier}} {{regels}}\",\n },\n {\n key: \"orderConfirmation\",\n label: \"Bestelbevestiging\",\n hint: \"Naar de klant zodra de betaling binnen is — met factuur-PDF als bijlage.\",\n module: \"shop\",\n placeholders: \"{{naam}} {{ordernummer}} {{regels}} {{totaal}} {{verzendadres}} {{notitie}} {{sitenaam}}\",\n },\n {\n key: \"shopkeeperNotification\",\n label: \"Nieuwe-bestelling-notificatie (naar jou)\",\n hint: \"Naar jou bij elke nieuwe bestelling.\",\n module: \"shop\",\n placeholders: \"{{sitenaam}} {{ordernummer}} {{totaal}} {{klant}} {{regels}} {{verzendadres}} {{notitie}}\",\n },\n {\n key: \"orderShipped\",\n label: \"Bestelling verzonden\",\n hint: \"Naar de klant wanneer je de status op ‘verzonden’ zet.\",\n module: \"shop\",\n placeholders: \"{{naam}} {{ordernummer}} {{regels}} {{trackingUrl}} {{verzendadres}} {{sitenaam}}\",\n },\n {\n key: \"orderPickupReady\",\n label: \"Bestelling klaar om af te halen\",\n hint: \"Naar de klant wanneer je een af te halen bestelling op ‘verzonden’ zet.\",\n module: \"shop\",\n placeholders: \"{{naam}} {{ordernummer}} {{regels}} {{verzendadres}} {{sitenaam}}\",\n },\n {\n key: \"orderCancelled\",\n label: \"Bestelling geannuleerd\",\n hint: \"Naar de klant bij annulering.\",\n module: \"shop\",\n placeholders: \"{{naam}} {{ordernummer}} {{sitenaam}}\",\n },\n {\n key: \"shopkeeperOrderCancelled\",\n label: \"Bestelling geannuleerd (naar jou)\",\n hint: \"Naar jou bij elke annulering — ook automatisch (bv. een verlopen betaling).\",\n module: \"shop\",\n placeholders: \"{{sitenaam}} {{ordernummer}} {{totaal}} {{klant}} {{regels}}\",\n },\n {\n key: \"paymentRequest\",\n label: \"Betaalverzoek\",\n hint: \"Naar de klant als je vanuit een openstaande bestelling een betaallink verstuurt.\",\n module: \"shop\",\n placeholders: \"{{naam}} {{ordernummer}} {{betaallink}} {{regels}} {{totaal}} {{verzendadres}} {{sitenaam}}\",\n },\n {\n key: \"orderRefunded\",\n label: \"Terugbetaald\",\n hint: \"Naar de klant na een terugbetaling.\",\n module: \"shop\",\n placeholders: \"{{naam}} {{ordernummer}} {{totaal}} {{sitenaam}}\",\n },\n {\n key: \"donationThanks\",\n label: \"Donatie-bedankje\",\n hint: \"Naar de gever na een donatie.\",\n module: \"shop\",\n placeholders: \"{{naam}} {{regels}} {{sitenaam}}\",\n },\n] as const satisfies readonly MailTemplateDef[];\n\nexport const MAIL_TEMPLATE_KEYS = MAIL_TEMPLATE_DEFS.map((d) => d.key) as unknown as readonly MailTemplateKey[];\nexport type MailTemplateKey = (typeof MAIL_TEMPLATE_DEFS)[number][\"key\"];\n\n/** Formulier-mails — bewerkbaar in het Formulieren-gedeelte. */\nexport const FORM_TEMPLATE_KEYS = MAIL_TEMPLATE_DEFS.filter((d) => d.module === \"core\").map((d) => d.key) as readonly MailTemplateKey[];\n/** Shop-mails — bewerkbaar in het Webwinkel-gedeelte. */\nexport const SHOP_TEMPLATE_KEYS = MAIL_TEMPLATE_DEFS.filter((d) => d.module === \"shop\").map((d) => d.key) as readonly MailTemplateKey[];\n\nexport const MailTemplateSchema = z.object({\n subject: z.optional(z.string().check(z.maxLength(200))),\n bodyText: z.optional(z.string().check(z.maxLength(10_000))),\n});\nexport const MailTemplatesSchema = z.object(\n Object.fromEntries(MAIL_TEMPLATE_DEFS.map((d) => [d.key, z.optional(MailTemplateSchema)])) as Record<\n MailTemplateKey,\n z.ZodMiniOptional<typeof MailTemplateSchema>\n >,\n);\nexport type MailTemplates = z.infer<typeof MailTemplatesSchema>;\n"],"mappings":"AAAA,YAAY,OAAO;AAoBZ,MAAM,qBAAqB;AAAA,EAChC;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AAAA,EACA;AAAA,IACE,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,cAAc;AAAA,EAChB;AACF;AAEO,MAAM,qBAAqB,mBAAmB,IAAI,CAAC,MAAM,EAAE,GAAG;AAI9D,MAAM,qBAAqB,mBAAmB,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG;AAEjG,MAAM,qBAAqB,mBAAmB,OAAO,CAAC,MAAM,EAAE,WAAW,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,GAAG;AAEjG,MAAM,qBAAqB,EAAE,OAAO;AAAA,EACzC,SAAS,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC;AAAA,EACtD,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAM,CAAC,CAAC;AAC5D,CAAC;AACM,MAAM,sBAAsB,EAAE;AAAA,EACnC,OAAO,YAAY,mBAAmB,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,SAAS,kBAAkB,CAAC,CAAC,CAAC;AAI3F;","names":[]}
@@ -199,6 +199,21 @@ export declare const FooterSettingsSchema: z.ZodMiniObject<{
199
199
  showAdminLink: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
200
200
  }, z.core.$strip>;
201
201
  export type FooterSettings = z.infer<typeof FooterSettingsSchema>;
202
+ /**
203
+ * De kop van de site (8.13), voor `SiteHeader`: logo, één actieknop, en op een telefoon een vaste
204
+ * balk onderaan met bellen en de actie. Sites met een eigen header negeren dit gewoon.
205
+ */
206
+ export declare const HeaderSettingsSchema: z.ZodMiniObject<{
207
+ logo: z.ZodMiniOptional<z.ZodMiniString<string>>;
208
+ logoHoogte: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
209
+ cta: z.ZodMiniOptional<z.ZodMiniObject<{
210
+ label: z.ZodMiniString<string>;
211
+ href: z.ZodMiniString<string>;
212
+ }, z.core.$strip>>;
213
+ sticky: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
214
+ mobielBalk: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
215
+ }, z.core.$strip>;
216
+ export type HeaderSettings = z.infer<typeof HeaderSettingsSchema>;
202
217
  /** Per-module activatie/instellingen (spiegelt ModulesSiteConfig; permissief gehouden). */
203
218
  export declare const ModulesSettingsSchema: z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniObject<{
204
219
  enabled: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
@@ -310,6 +325,16 @@ export declare const SiteSettingsSchema: z.ZodMiniObject<{
310
325
  copyright: z.ZodMiniOptional<z.ZodMiniString<string>>;
311
326
  showAdminLink: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
312
327
  }, z.core.$strip>>;
328
+ header: z.ZodMiniOptional<z.ZodMiniObject<{
329
+ logo: z.ZodMiniOptional<z.ZodMiniString<string>>;
330
+ logoHoogte: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
331
+ cta: z.ZodMiniOptional<z.ZodMiniObject<{
332
+ label: z.ZodMiniString<string>;
333
+ href: z.ZodMiniString<string>;
334
+ }, z.core.$strip>>;
335
+ sticky: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
336
+ mobielBalk: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
337
+ }, z.core.$strip>>;
313
338
  modules: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniObject<{
314
339
  enabled: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
315
340
  config: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnknown>>;
@@ -322,6 +347,39 @@ export declare const SiteSettingsSchema: z.ZodMiniObject<{
322
347
  from: z.ZodMiniString<string>;
323
348
  to: z.ZodMiniString<string>;
324
349
  }, z.core.$strip>>>;
350
+ business: z.ZodMiniOptional<z.ZodMiniObject<{
351
+ type: z.ZodMiniOptional<z.ZodMiniString<string>>;
352
+ name: z.ZodMiniOptional<z.ZodMiniString<string>>;
353
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
354
+ phone: z.ZodMiniOptional<z.ZodMiniString<string>>;
355
+ email: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniEmail, z.ZodMiniLiteral<"">]>>;
356
+ whatsapp: z.ZodMiniOptional<z.ZodMiniString<string>>;
357
+ address: z.ZodMiniOptional<z.ZodMiniObject<{
358
+ street: z.ZodMiniOptional<z.ZodMiniString<string>>;
359
+ postalCode: z.ZodMiniOptional<z.ZodMiniString<string>>;
360
+ city: z.ZodMiniOptional<z.ZodMiniString<string>>;
361
+ country: z.ZodMiniOptional<z.ZodMiniString<string>>;
362
+ }, z.core.$strip>>;
363
+ geo: z.ZodMiniOptional<z.ZodMiniObject<{
364
+ lat: z.ZodMiniNumber<number>;
365
+ lng: z.ZodMiniNumber<number>;
366
+ }, z.core.$strip>>;
367
+ hours: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniObject<{
368
+ day: z.ZodMiniDefault<z.ZodMiniString<string>>;
369
+ hours: z.ZodMiniDefault<z.ZodMiniString<string>>;
370
+ }, z.core.$strip>>>;
371
+ hoursNote: z.ZodMiniOptional<z.ZodMiniString<string>>;
372
+ exceptions: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniObject<{
373
+ date: z.ZodMiniString<string>;
374
+ until: z.ZodMiniOptional<z.ZodMiniString<string>>;
375
+ hours: z.ZodMiniDefault<z.ZodMiniString<string>>;
376
+ label: z.ZodMiniOptional<z.ZodMiniString<string>>;
377
+ }, z.core.$strip>>>;
378
+ priceRange: z.ZodMiniOptional<z.ZodMiniString<string>>;
379
+ kvk: z.ZodMiniOptional<z.ZodMiniString<string>>;
380
+ reviewUrl: z.ZodMiniOptional<z.ZodMiniString<string>>;
381
+ sameAs: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
382
+ }, z.core.$strip>>;
325
383
  }, z.core.$strip>;
326
384
  export type SiteSettings = z.infer<typeof SiteSettingsSchema>;
327
385
  /**
@@ -423,6 +481,16 @@ export declare const PublicSiteSettingsSchema: z.ZodMiniObject<{
423
481
  copyright: z.ZodMiniOptional<z.ZodMiniString<string>>;
424
482
  showAdminLink: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
425
483
  }, z.core.$strip>>;
484
+ header: z.ZodMiniOptional<z.ZodMiniObject<{
485
+ logo: z.ZodMiniOptional<z.ZodMiniString<string>>;
486
+ logoHoogte: z.ZodMiniOptional<z.ZodMiniNumber<number>>;
487
+ cta: z.ZodMiniOptional<z.ZodMiniObject<{
488
+ label: z.ZodMiniString<string>;
489
+ href: z.ZodMiniString<string>;
490
+ }, z.core.$strip>>;
491
+ sticky: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
492
+ mobielBalk: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
493
+ }, z.core.$strip>>;
426
494
  modules: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnion<readonly [z.ZodMiniBoolean<boolean>, z.ZodMiniObject<{
427
495
  enabled: z.ZodMiniOptional<z.ZodMiniBoolean<boolean>>;
428
496
  config: z.ZodMiniOptional<z.ZodMiniRecord<z.ZodMiniString<string>, z.ZodMiniUnknown>>;
@@ -431,6 +499,39 @@ export declare const PublicSiteSettingsSchema: z.ZodMiniObject<{
431
499
  from: z.ZodMiniString<string>;
432
500
  to: z.ZodMiniString<string>;
433
501
  }, z.core.$strip>>>;
502
+ business: z.ZodMiniOptional<z.ZodMiniObject<{
503
+ type: z.ZodMiniOptional<z.ZodMiniString<string>>;
504
+ name: z.ZodMiniOptional<z.ZodMiniString<string>>;
505
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
506
+ phone: z.ZodMiniOptional<z.ZodMiniString<string>>;
507
+ email: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniEmail, z.ZodMiniLiteral<"">]>>;
508
+ whatsapp: z.ZodMiniOptional<z.ZodMiniString<string>>;
509
+ address: z.ZodMiniOptional<z.ZodMiniObject<{
510
+ street: z.ZodMiniOptional<z.ZodMiniString<string>>;
511
+ postalCode: z.ZodMiniOptional<z.ZodMiniString<string>>;
512
+ city: z.ZodMiniOptional<z.ZodMiniString<string>>;
513
+ country: z.ZodMiniOptional<z.ZodMiniString<string>>;
514
+ }, z.core.$strip>>;
515
+ geo: z.ZodMiniOptional<z.ZodMiniObject<{
516
+ lat: z.ZodMiniNumber<number>;
517
+ lng: z.ZodMiniNumber<number>;
518
+ }, z.core.$strip>>;
519
+ hours: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniObject<{
520
+ day: z.ZodMiniDefault<z.ZodMiniString<string>>;
521
+ hours: z.ZodMiniDefault<z.ZodMiniString<string>>;
522
+ }, z.core.$strip>>>;
523
+ hoursNote: z.ZodMiniOptional<z.ZodMiniString<string>>;
524
+ exceptions: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniObject<{
525
+ date: z.ZodMiniString<string>;
526
+ until: z.ZodMiniOptional<z.ZodMiniString<string>>;
527
+ hours: z.ZodMiniDefault<z.ZodMiniString<string>>;
528
+ label: z.ZodMiniOptional<z.ZodMiniString<string>>;
529
+ }, z.core.$strip>>>;
530
+ priceRange: z.ZodMiniOptional<z.ZodMiniString<string>>;
531
+ kvk: z.ZodMiniOptional<z.ZodMiniString<string>>;
532
+ reviewUrl: z.ZodMiniOptional<z.ZodMiniString<string>>;
533
+ sameAs: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
534
+ }, z.core.$strip>>;
434
535
  }, z.core.$strip>;
435
536
  export type PublicSiteSettings = z.infer<typeof PublicSiteSettingsSchema>;
436
537
  /** Haalt de publiek-veilige subset uit de volledige settings (voor het `settings/public`-doc). */
@@ -1,5 +1,6 @@
1
1
  import * as z from "zod/mini";
2
2
  import { SeoSchema } from "./seo.js";
3
+ import { BusinessSchema } from "./business.js";
3
4
  const NavLeafSchema = z.object({
4
5
  label: z.string().check(z.minLength(1)).check(z.maxLength(80)),
5
6
  href: z.string().check(z.minLength(1)).check(z.maxLength(2e3)),
@@ -137,6 +138,18 @@ const FooterSettingsSchema = z.object({
137
138
  /** Toon de "Beheer"-link in de footer (default: aan). */
138
139
  showAdminLink: z.optional(z.boolean())
139
140
  });
141
+ const HeaderSettingsSchema = z.object({
142
+ /** Logo-afbeelding; leeg = de sitenaam als tekst. */
143
+ logo: z.optional(z.string().check(z.maxLength(2e3))),
144
+ /** Hoogte van het logo in px (desktop). */
145
+ logoHoogte: z.optional(z.number().check(z.minimum(20)).check(z.maximum(120))),
146
+ /** De actieknop rechts ("Afspraak maken", "Offerte aanvragen"). */
147
+ cta: z.optional(z.object({ label: z.string().check(z.maxLength(40)), href: z.string().check(z.maxLength(2e3)) })),
148
+ /** Blijft bovenaan staan bij scrollen (standaard aan). */
149
+ sticky: z.optional(z.boolean()),
150
+ /** Op een telefoon een balk onderaan met "Bel" en de actieknop. */
151
+ mobielBalk: z.optional(z.boolean())
152
+ });
140
153
  const ModulesSettingsSchema = z.record(
141
154
  z.string(),
142
155
  z.union([
@@ -154,6 +167,7 @@ const SiteSettingsSchema = z.object({
154
167
  seoDefaults: z.optional(SeoSchema),
155
168
  forms: z.optional(FormsSenderSchema),
156
169
  footer: z.optional(FooterSettingsSchema),
170
+ header: z.optional(HeaderSettingsSchema),
157
171
  modules: z.optional(ModulesSettingsSchema),
158
172
  /**
159
173
  * Snelkoppelingen op de beheer-startpagina (7.16). Beheer-intern: bewust NIET in de publieke
@@ -165,7 +179,9 @@ const SiteSettingsSchema = z.object({
165
179
  href: z.string().check(z.minLength(1)).check(z.maxLength(2e3))
166
180
  })).check(z.maxLength(12))),
167
181
  /** Doorverwijzingen van oude naar nieuwe paden (7.24). Publiek: de catch-all leest ze. */
168
- redirects: z.optional(z.array(RedirectSchema).check(z.maxLength(200)))
182
+ redirects: z.optional(z.array(RedirectSchema).check(z.maxLength(200))),
183
+ /** Bedrijfsprofiel (8.13). Publiek: de site toont het en zet het in de JSON-LD. */
184
+ business: z.optional(BusinessSchema)
169
185
  });
170
186
  const PublicSiteSettingsSchema = z.object({
171
187
  name: z.optional(z.string().check(z.maxLength(160))),
@@ -173,8 +189,10 @@ const PublicSiteSettingsSchema = z.object({
173
189
  theme: z.optional(ThemeSchema),
174
190
  seoDefaults: z.optional(SeoSchema),
175
191
  footer: z.optional(FooterSettingsSchema),
192
+ header: z.optional(HeaderSettingsSchema),
176
193
  modules: z.optional(ModulesSettingsSchema),
177
- redirects: z.optional(z.array(RedirectSchema).check(z.maxLength(200)))
194
+ redirects: z.optional(z.array(RedirectSchema).check(z.maxLength(200))),
195
+ business: z.optional(BusinessSchema)
178
196
  });
179
197
  function toPublicSettings(s) {
180
198
  return {
@@ -183,8 +201,10 @@ function toPublicSettings(s) {
183
201
  theme: s.theme,
184
202
  seoDefaults: s.seoDefaults,
185
203
  footer: s.footer,
204
+ header: s.header,
186
205
  modules: s.modules,
187
- redirects: s.redirects
206
+ redirects: s.redirects,
207
+ business: s.business
188
208
  };
189
209
  }
190
210
  export {
@@ -192,6 +212,7 @@ export {
192
212
  FooterColumnSchema,
193
213
  FooterSettingsSchema,
194
214
  FormsSenderSchema,
215
+ HeaderSettingsSchema,
195
216
  ModulesSettingsSchema,
196
217
  NavItemSchema,
197
218
  PublicSiteSettingsSchema,