@xiwebdesign/xicms-core 7.31.0 → 8.16.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 (482) hide show
  1. package/dist/XiCMSProvider.js +23 -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 -60
  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 +248 -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 +159 -0
  133. package/dist/admin/settings/BedrijfInstellingen.js.map +1 -0
  134. package/dist/admin/settings/MailTemplates.js +5 -4
  135. package/dist/admin/settings/MailTemplates.js.map +1 -1
  136. package/dist/admin/settings/SettingsPanel.js +120 -78
  137. package/dist/admin/settings/SettingsPanel.js.map +1 -1
  138. package/dist/admin/settings/SnapshotsCard.js +4 -4
  139. package/dist/admin/settings/SnapshotsCard.js.map +1 -1
  140. package/dist/admin/settings/VorigeTerugzetten.d.ts +15 -0
  141. package/dist/admin/settings/VorigeTerugzetten.js +89 -0
  142. package/dist/admin/settings/VorigeTerugzetten.js.map +1 -0
  143. package/dist/admin/shop/CategoriesTab.js +6 -4
  144. package/dist/admin/shop/CategoriesTab.js.map +1 -1
  145. package/dist/admin/shop/DiscountsTab.js +4 -2
  146. package/dist/admin/shop/DiscountsTab.js.map +1 -1
  147. package/dist/admin/shop/OrdersTab.js +57 -19
  148. package/dist/admin/shop/OrdersTab.js.map +1 -1
  149. package/dist/admin/shop/ProductPaneel.js +2 -1
  150. package/dist/admin/shop/ProductPaneel.js.map +1 -1
  151. package/dist/admin/shop/ProductsTab.js +40 -19
  152. package/dist/admin/shop/ProductsTab.js.map +1 -1
  153. package/dist/admin/shop/ShopPanel.js +13 -1
  154. package/dist/admin/shop/ShopPanel.js.map +1 -1
  155. package/dist/admin/shop/ShopSettingsTab.js +56 -17
  156. package/dist/admin/shop/ShopSettingsTab.js.map +1 -1
  157. package/dist/admin/shop/productClient.js +7 -3
  158. package/dist/admin/shop/productClient.js.map +1 -1
  159. package/dist/admin/stats/NietGevonden.d.ts +10 -0
  160. package/dist/admin/stats/NietGevonden.js +78 -0
  161. package/dist/admin/stats/NietGevonden.js.map +1 -0
  162. package/dist/admin/stats/StatsPanel.js +6 -1
  163. package/dist/admin/stats/StatsPanel.js.map +1 -1
  164. package/dist/admin/stats/lib.d.ts +2 -0
  165. package/dist/admin/stats/lib.js.map +1 -1
  166. package/dist/admin/ui/ConfirmDialog.js +10 -1
  167. package/dist/admin/ui/ConfirmDialog.js.map +1 -1
  168. package/dist/admin/ui/Icon.d.ts +34 -0
  169. package/dist/admin/ui/Icon.js +44 -0
  170. package/dist/admin/ui/Icon.js.map +1 -0
  171. package/dist/admin/ui/ImageField.d.ts +15 -0
  172. package/dist/admin/ui/ImageField.js +67 -0
  173. package/dist/admin/ui/ImageField.js.map +1 -0
  174. package/dist/admin/ui/KleurVeld.d.ts +25 -0
  175. package/dist/admin/ui/KleurVeld.js +76 -0
  176. package/dist/admin/ui/KleurVeld.js.map +1 -0
  177. package/dist/admin/ui/LaadStaat.d.ts +21 -0
  178. package/dist/admin/ui/LaadStaat.js +43 -0
  179. package/dist/admin/ui/LaadStaat.js.map +1 -0
  180. package/dist/admin/ui/LeesbaarheidPaneel.d.ts +10 -0
  181. package/dist/admin/ui/LeesbaarheidPaneel.js +68 -0
  182. package/dist/admin/ui/LeesbaarheidPaneel.js.map +1 -0
  183. package/dist/admin/ui/LinkDialog.d.ts +22 -0
  184. package/dist/admin/ui/LinkDialog.js +131 -0
  185. package/dist/admin/ui/LinkDialog.js.map +1 -0
  186. package/dist/admin/ui/LinkVeld.d.ts +14 -0
  187. package/dist/admin/ui/LinkVeld.js +49 -0
  188. package/dist/admin/ui/LinkVeld.js.map +1 -0
  189. package/dist/admin/ui/PreviewLinkResultaat.d.ts +14 -0
  190. package/dist/admin/ui/PreviewLinkResultaat.js +52 -0
  191. package/dist/admin/ui/PreviewLinkResultaat.js.map +1 -0
  192. package/dist/admin/ui/charts.js +5 -5
  193. package/dist/admin/ui/charts.js.map +1 -1
  194. package/dist/admin/ui/primitives.d.ts +16 -6
  195. package/dist/admin/ui/primitives.js +98 -26
  196. package/dist/admin/ui/primitives.js.map +1 -1
  197. package/dist/admin/ui/select.js +5 -2
  198. package/dist/admin/ui/select.js.map +1 -1
  199. package/dist/admin/ui/switch.d.ts +3 -1
  200. package/dist/admin/ui/switch.js +6 -3
  201. package/dist/admin/ui/switch.js.map +1 -1
  202. package/dist/admin/ui/toast.d.ts +2 -1
  203. package/dist/admin/ui/toast.js +17 -11
  204. package/dist/admin/ui/toast.js.map +1 -1
  205. package/dist/admin/visual/BlokKiezer.d.ts +34 -0
  206. package/dist/admin/visual/BlokKiezer.js +225 -0
  207. package/dist/admin/visual/BlokKiezer.js.map +1 -0
  208. package/dist/admin/visual/InlineGereedschap.d.ts +52 -0
  209. package/dist/admin/visual/InlineGereedschap.js +356 -0
  210. package/dist/admin/visual/InlineGereedschap.js.map +1 -0
  211. package/dist/admin/visual/InlineRijkeTekst.d.ts +23 -0
  212. package/dist/admin/visual/InlineRijkeTekst.js +152 -0
  213. package/dist/admin/visual/InlineRijkeTekst.js.map +1 -0
  214. package/dist/admin/visual/VisualEditor.js +273 -125
  215. package/dist/admin/visual/VisualEditor.js.map +1 -1
  216. package/dist/admin.css +1 -1
  217. package/dist/auth/AuthProvider.js +1 -0
  218. package/dist/auth/AuthProvider.js.map +1 -1
  219. package/dist/bedrijf/bedrijf.d.ts +44 -0
  220. package/dist/bedrijf/bedrijf.js +125 -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 +37 -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 +3 -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/consentEmbed.js +26 -9
  309. package/dist/blocks/builtins/consentEmbed.js.map +1 -1
  310. package/dist/blocks/builtins/index.d.ts +3 -0
  311. package/dist/blocks/builtins/index.js +6 -0
  312. package/dist/blocks/builtins/index.js.map +1 -1
  313. package/dist/blocks/builtins/lib/autoComplete.d.ts +7 -0
  314. package/dist/blocks/builtins/lib/autoComplete.js +20 -0
  315. package/dist/blocks/builtins/lib/autoComplete.js.map +1 -0
  316. package/dist/blocks/builtins/lib/bookingUrl.d.ts +2 -2
  317. package/dist/blocks/builtins/lib/bookingUrl.js +1 -1
  318. package/dist/blocks/builtins/lib/bookingUrl.js.map +1 -1
  319. package/dist/blocks/builtins/lib/ical.d.ts +24 -0
  320. package/dist/blocks/builtins/lib/ical.js +82 -0
  321. package/dist/blocks/builtins/lib/ical.js.map +1 -0
  322. package/dist/blocks/builtins/lib/vandaag.d.ts +8 -0
  323. package/dist/blocks/builtins/lib/vandaag.js +22 -0
  324. package/dist/blocks/builtins/lib/vandaag.js.map +1 -0
  325. package/dist/blocks/registry.d.ts +6 -0
  326. package/dist/blocks/registry.js.map +1 -1
  327. package/dist/blocks/ui/index.js +1 -0
  328. package/dist/blocks/ui/index.js.map +1 -1
  329. package/dist/components/EditBar.js +2 -4
  330. package/dist/components/EditBar.js.map +1 -1
  331. package/dist/components/News.js +26 -18
  332. package/dist/components/News.js.map +1 -1
  333. package/dist/components/PageView.d.ts +7 -1
  334. package/dist/components/PageView.js +17 -0
  335. package/dist/components/PageView.js.map +1 -1
  336. package/dist/components/ResponsiveImage.js +18 -20
  337. package/dist/components/ResponsiveImage.js.map +1 -1
  338. package/dist/components/onderOffset.d.ts +13 -0
  339. package/dist/components/onderOffset.js +74 -0
  340. package/dist/components/onderOffset.js.map +1 -0
  341. package/dist/components/site/Bedrijfsnummers.d.ts +9 -0
  342. package/dist/components/site/Bedrijfsnummers.js +12 -0
  343. package/dist/components/site/Bedrijfsnummers.js.map +1 -0
  344. package/dist/components/site/SiteFooter.d.ts +6 -1
  345. package/dist/components/site/SiteFooter.js +62 -9
  346. package/dist/components/site/SiteFooter.js.map +1 -1
  347. package/dist/components/site/SiteHeader.d.ts +15 -0
  348. package/dist/components/site/SiteHeader.js +70 -0
  349. package/dist/components/site/SiteHeader.js.map +1 -0
  350. package/dist/components/site/SiteNav.d.ts +2 -0
  351. package/dist/components/site/SiteNav.js +29 -5
  352. package/dist/components/site/SiteNav.js.map +1 -1
  353. package/dist/demo/DemoStudio.js +2 -2
  354. package/dist/demo/DemoStudio.js.map +1 -1
  355. package/dist/demo/demoStore.d.ts +13 -0
  356. package/dist/demo/demoStore.js +36 -0
  357. package/dist/demo/demoStore.js.map +1 -1
  358. package/dist/editor/EditorProvider.js +15 -4
  359. package/dist/editor/EditorProvider.js.map +1 -1
  360. package/dist/firebase/functionsClient.js +5 -1
  361. package/dist/firebase/functionsClient.js.map +1 -1
  362. package/dist/index.d.ts +5 -1
  363. package/dist/index.js +20 -1
  364. package/dist/index.js.map +1 -1
  365. package/dist/media/ImageContext.d.ts +17 -0
  366. package/dist/media/ImageContext.js +65 -20
  367. package/dist/media/ImageContext.js.map +1 -1
  368. package/dist/media/altInHtml.d.ts +9 -0
  369. package/dist/media/altInHtml.js +17 -0
  370. package/dist/media/altInHtml.js.map +1 -0
  371. package/dist/media/srcset.d.ts +12 -0
  372. package/dist/media/srcset.js +13 -0
  373. package/dist/media/srcset.js.map +1 -0
  374. package/dist/modules/builtins.d.ts +1 -0
  375. package/dist/modules/builtins.js +22 -9
  376. package/dist/modules/builtins.js.map +1 -1
  377. package/dist/modules/consent/ConsentBanner.d.ts +5 -0
  378. package/dist/modules/consent/ConsentBanner.js +8 -7
  379. package/dist/modules/consent/ConsentBanner.js.map +1 -1
  380. package/dist/modules/consent/standaard.d.ts +12 -0
  381. package/dist/modules/consent/standaard.js +10 -0
  382. package/dist/modules/consent/standaard.js.map +1 -0
  383. package/dist/modules/consent/useConsent.d.ts +4 -0
  384. package/dist/modules/consent/useConsent.js +30 -1
  385. package/dist/modules/consent/useConsent.js.map +1 -1
  386. package/dist/modules/shop/blocks/Cart.js +5 -3
  387. package/dist/modules/shop/blocks/Cart.js.map +1 -1
  388. package/dist/modules/shop/blocks/Checkout.js +56 -35
  389. package/dist/modules/shop/blocks/Checkout.js.map +1 -1
  390. package/dist/modules/shop/blocks/Donation.js +4 -4
  391. package/dist/modules/shop/blocks/Donation.js.map +1 -1
  392. package/dist/modules/shop/blocks/ProductDetail.js +19 -3
  393. package/dist/modules/shop/blocks/ProductDetail.js.map +1 -1
  394. package/dist/modules/shop/blocks/ProductGrid.d.ts +3 -1
  395. package/dist/modules/shop/blocks/ProductGrid.js +8 -4
  396. package/dist/modules/shop/blocks/ProductGrid.js.map +1 -1
  397. package/dist/modules/shop/blocks/ShopCategories.js +4 -3
  398. package/dist/modules/shop/blocks/ShopCategories.js.map +1 -1
  399. package/dist/modules/shop/lib.d.ts +4 -0
  400. package/dist/modules/shop/lib.js +14 -0
  401. package/dist/modules/shop/lib.js.map +1 -1
  402. package/dist/modules/shop/settings.d.ts +3 -0
  403. package/dist/modules/shop/settings.js +14 -0
  404. package/dist/modules/shop/settings.js.map +1 -1
  405. package/dist/modules/shop/strings.d.ts +4 -0
  406. package/dist/modules/shop/strings.js +8 -0
  407. package/dist/modules/shop/strings.js.map +1 -1
  408. package/dist/next/envCheck.d.ts +42 -0
  409. package/dist/next/envCheck.js +106 -0
  410. package/dist/next/envCheck.js.map +1 -0
  411. package/dist/next/index.cjs +185 -2
  412. package/dist/next/index.d.ts +2 -0
  413. package/dist/next/index.js +8 -1
  414. package/dist/next/index.js.map +1 -1
  415. package/dist/next/securityHeaders.d.ts +36 -0
  416. package/dist/next/securityHeaders.js +74 -0
  417. package/dist/next/securityHeaders.js.map +1 -0
  418. package/dist/patterns/builtins.d.ts +7 -0
  419. package/dist/patterns/builtins.js +138 -3
  420. package/dist/patterns/builtins.js.map +1 -1
  421. package/dist/releaseNotes.js +148 -0
  422. package/dist/releaseNotes.js.map +1 -1
  423. package/dist/render/PublishedPage.d.ts +2 -1
  424. package/dist/render/PublishedPage.js +10 -4
  425. package/dist/render/PublishedPage.js.map +1 -1
  426. package/dist/schema/blocks.d.ts +473 -0
  427. package/dist/schema/blocks.js +105 -5
  428. package/dist/schema/blocks.js.map +1 -1
  429. package/dist/schema/business.d.ts +118 -0
  430. package/dist/schema/business.js +75 -0
  431. package/dist/schema/business.js.map +1 -0
  432. package/dist/schema/fields.d.ts +2 -1
  433. package/dist/schema/fields.js.map +1 -1
  434. package/dist/schema/forms.d.ts +18 -0
  435. package/dist/schema/forms.js +18 -3
  436. package/dist/schema/forms.js.map +1 -1
  437. package/dist/schema/mail.d.ts +10 -0
  438. package/dist/schema/mail.js +7 -0
  439. package/dist/schema/mail.js.map +1 -1
  440. package/dist/schema/settings.d.ts +103 -0
  441. package/dist/schema/settings.js +24 -3
  442. package/dist/schema/settings.js.map +1 -1
  443. package/dist/schema/shop.d.ts +2 -0
  444. package/dist/schema/shop.js +4 -0
  445. package/dist/schema/shop.js.map +1 -1
  446. package/dist/schema/shopGeld.d.ts +1 -0
  447. package/dist/schema/shopGeld.js +1 -0
  448. package/dist/schema/shopGeld.js.map +1 -1
  449. package/dist/schema/siteConfig.d.ts +69 -1
  450. package/dist/schema/siteConfig.js +7 -2
  451. package/dist/schema/siteConfig.js.map +1 -1
  452. package/dist/server/blockData.d.ts +1 -1
  453. package/dist/server/blockData.js +74 -18
  454. package/dist/server/blockData.js.map +1 -1
  455. package/dist/server/cspRapport.d.ts +20 -0
  456. package/dist/server/cspRapport.js +56 -0
  457. package/dist/server/cspRapport.js.map +1 -0
  458. package/dist/server/fonts.d.ts +3 -0
  459. package/dist/server/fonts.js +39 -0
  460. package/dist/server/fonts.js.map +1 -0
  461. package/dist/server/index.d.ts +3 -0
  462. package/dist/server/index.js +8 -0
  463. package/dist/server/index.js.map +1 -1
  464. package/dist/server/sanitize.js +2 -0
  465. package/dist/server/sanitize.js.map +1 -1
  466. package/dist/settings/useSiteSettings.js +4 -1
  467. package/dist/settings/useSiteSettings.js.map +1 -1
  468. package/dist/starters/starters.d.ts +69 -0
  469. package/dist/starters/starters.js +171 -0
  470. package/dist/starters/starters.js.map +1 -0
  471. package/dist/styles.css +1181 -212
  472. package/dist/theme/color.d.ts +10 -0
  473. package/dist/theme/color.js +17 -1
  474. package/dist/theme/color.js.map +1 -1
  475. package/dist/theme/fontFallback.d.ts +23 -0
  476. package/dist/theme/fontFallback.js +58 -0
  477. package/dist/theme/fontFallback.js.map +1 -0
  478. package/dist/theme/fonts.d.ts +11 -0
  479. package/dist/theme/fonts.js +16 -0
  480. package/dist/theme/fonts.js.map +1 -0
  481. package/dist/version.js +1 -1
  482. package/package.json +5 -4
@@ -0,0 +1,118 @@
1
+ import * as z from "zod/mini";
2
+ /**
3
+ * Het bedrijfsprofiel (8.13): naam, adres, telefoon, openingstijden — één keer ingevuld in
4
+ * /beheer → Instellingen → Bedrijf, en daarna overal gebruikt.
5
+ *
6
+ * Tot nu toe stonden deze gegevens op vier plekken tegelijk: hardcoded in de footer van de site,
7
+ * hardcoded als LocalBusiness-JSON-LD in `app/layout.tsx`, en nog eens in een contact- en een
8
+ * openingstijdenblok. Een klant die van telefoonnummer wisselde, kon er maar één van aanpassen. Nu:
9
+ * - de JSON-LD voor Google komt automatisch uit dit profiel (`bedrijfJsonLd`);
10
+ * - het contact- en openingstijdenblok vallen erop terug als ze zelf leeg zijn;
11
+ * - de footer kan een contactkolom uit het profiel tonen.
12
+ *
13
+ * Openingstijden gebruiken hetzelfde rijmodel als het openingstijdenblok ({ day, hours } in gewone
14
+ * taal: "Maandag t/m vrijdag" · "09:00 – 17:00"), dus dezelfde parser voor "nu open" en Google.
15
+ */
16
+ /** schema.org-types die een klant kan kiezen, met een Nederlandse naam. */
17
+ export declare const BEDRIJFSTYPES: readonly [{
18
+ readonly value: "LocalBusiness";
19
+ readonly label: "Lokaal bedrijf (algemeen)";
20
+ }, {
21
+ readonly value: "HomeAndConstructionBusiness";
22
+ readonly label: "Bouw, klussen en tuin";
23
+ }, {
24
+ readonly value: "ProfessionalService";
25
+ readonly label: "Zakelijke dienstverlening";
26
+ }, {
27
+ readonly value: "HairSalon";
28
+ readonly label: "Kapper of barbier";
29
+ }, {
30
+ readonly value: "BeautySalon";
31
+ readonly label: "Schoonheidssalon";
32
+ }, {
33
+ readonly value: "Restaurant";
34
+ readonly label: "Restaurant";
35
+ }, {
36
+ readonly value: "CafeOrCoffeeShop";
37
+ readonly label: "Café of koffiebar";
38
+ }, {
39
+ readonly value: "Bakery";
40
+ readonly label: "Bakkerij";
41
+ }, {
42
+ readonly value: "Store";
43
+ readonly label: "Winkel";
44
+ }, {
45
+ readonly value: "LodgingBusiness";
46
+ readonly label: "Verhuur of overnachting";
47
+ }, {
48
+ readonly value: "BedAndBreakfast";
49
+ readonly label: "Bed & breakfast";
50
+ }, {
51
+ readonly value: "MedicalBusiness";
52
+ readonly label: "Zorg of praktijk";
53
+ }, {
54
+ readonly value: "Physiotherapy";
55
+ readonly label: "Fysiotherapie";
56
+ }, {
57
+ readonly value: "Dentist";
58
+ readonly label: "Tandarts";
59
+ }, {
60
+ readonly value: "SportsActivityLocation";
61
+ readonly label: "Sport of fitness";
62
+ }, {
63
+ readonly value: "EducationalOrganization";
64
+ readonly label: "Onderwijs of cursus";
65
+ }, {
66
+ readonly value: "Church";
67
+ readonly label: "Kerk";
68
+ }, {
69
+ readonly value: "NGO";
70
+ readonly label: "Stichting of vereniging";
71
+ }];
72
+ export declare const BusinessHoursRowSchema: z.ZodMiniObject<{
73
+ day: z.ZodMiniDefault<z.ZodMiniString<string>>;
74
+ hours: z.ZodMiniDefault<z.ZodMiniString<string>>;
75
+ }, z.core.$strip>;
76
+ /** Een afwijkende dag of periode: feestdag, vakantie, koopavond. */
77
+ export declare const BusinessExceptionSchema: z.ZodMiniObject<{
78
+ date: z.ZodMiniString<string>;
79
+ until: z.ZodMiniOptional<z.ZodMiniString<string>>;
80
+ hours: z.ZodMiniDefault<z.ZodMiniString<string>>;
81
+ label: z.ZodMiniOptional<z.ZodMiniString<string>>;
82
+ }, z.core.$strip>;
83
+ export declare const BusinessSchema: z.ZodMiniObject<{
84
+ type: z.ZodMiniOptional<z.ZodMiniString<string>>;
85
+ name: z.ZodMiniOptional<z.ZodMiniString<string>>;
86
+ description: z.ZodMiniOptional<z.ZodMiniString<string>>;
87
+ phone: z.ZodMiniOptional<z.ZodMiniString<string>>;
88
+ email: z.ZodMiniOptional<z.ZodMiniUnion<readonly [z.ZodMiniEmail, z.ZodMiniLiteral<"">]>>;
89
+ whatsapp: z.ZodMiniOptional<z.ZodMiniString<string>>;
90
+ address: z.ZodMiniOptional<z.ZodMiniObject<{
91
+ street: z.ZodMiniOptional<z.ZodMiniString<string>>;
92
+ postalCode: z.ZodMiniOptional<z.ZodMiniString<string>>;
93
+ city: z.ZodMiniOptional<z.ZodMiniString<string>>;
94
+ country: z.ZodMiniOptional<z.ZodMiniString<string>>;
95
+ }, z.core.$strip>>;
96
+ geo: z.ZodMiniOptional<z.ZodMiniObject<{
97
+ lat: z.ZodMiniNumber<number>;
98
+ lng: z.ZodMiniNumber<number>;
99
+ }, z.core.$strip>>;
100
+ hours: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniObject<{
101
+ day: z.ZodMiniDefault<z.ZodMiniString<string>>;
102
+ hours: z.ZodMiniDefault<z.ZodMiniString<string>>;
103
+ }, z.core.$strip>>>;
104
+ hoursNote: z.ZodMiniOptional<z.ZodMiniString<string>>;
105
+ exceptions: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniObject<{
106
+ date: z.ZodMiniString<string>;
107
+ until: z.ZodMiniOptional<z.ZodMiniString<string>>;
108
+ hours: z.ZodMiniDefault<z.ZodMiniString<string>>;
109
+ label: z.ZodMiniOptional<z.ZodMiniString<string>>;
110
+ }, z.core.$strip>>>;
111
+ priceRange: z.ZodMiniOptional<z.ZodMiniString<string>>;
112
+ kvk: z.ZodMiniOptional<z.ZodMiniString<string>>;
113
+ vat: z.ZodMiniOptional<z.ZodMiniString<string>>;
114
+ reviewUrl: z.ZodMiniOptional<z.ZodMiniString<string>>;
115
+ sameAs: z.ZodMiniOptional<z.ZodMiniArray<z.ZodMiniString<string>>>;
116
+ }, z.core.$strip>;
117
+ export type Business = z.infer<typeof BusinessSchema>;
118
+ export type BusinessException = z.infer<typeof BusinessExceptionSchema>;
@@ -0,0 +1,75 @@
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
+ /** Btw-identificatienummer (NL123456789B01). Verplicht op de site bij verkoop aan consumenten. */
63
+ vat: tekst(20),
64
+ /** Link waar klanten een review achterlaten (Google-bedrijfsprofiel). */
65
+ reviewUrl: z.optional(z.string().check(z.maxLength(2e3))),
66
+ /** Profielen elders: Instagram, Facebook, LinkedIn … */
67
+ sameAs: z.optional(z.array(z.string().check(z.maxLength(2e3))).check(z.maxLength(12)))
68
+ });
69
+ export {
70
+ BEDRIJFSTYPES,
71
+ BusinessExceptionSchema,
72
+ BusinessHoursRowSchema,
73
+ BusinessSchema
74
+ };
75
+ //# 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 /** Btw-identificatienummer (NL123456789B01). Verplicht op de site bij verkoop aan consumenten. */\n vat: 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":[]}