@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
@@ -1,5 +1,6 @@
1
1
  import * as z from "zod/mini";
2
2
  import { defineModule } from "./defineModule.js";
3
+ import { DEFAULT_CATEGORIES, DEFAULT_MESSAGE } from "./consent/standaard.js";
3
4
  import { heroBlock } from "../blocks/builtins/Hero.js";
4
5
  import { richTextBlock } from "../blocks/builtins/RichTextBlock.js";
5
6
  import { imageBlock } from "../blocks/builtins/ImageBlock.js";
@@ -10,6 +11,9 @@ import { galleryBlock } from "../blocks/builtins/Gallery.js";
10
11
  import { faqBlock } from "../blocks/builtins/Faq.js";
11
12
  import { openingHoursBlock } from "../blocks/builtins/OpeningHours.js";
12
13
  import { pricingBlock } from "../blocks/builtins/Pricing.js";
14
+ import { priceListBlock } from "../blocks/builtins/PriceList.js";
15
+ import { sectionHeadingBlock } from "../blocks/builtins/SectionHeading.js";
16
+ import { availabilityBlock } from "../blocks/builtins/Availability.js";
13
17
  import { newsListBlock } from "../blocks/builtins/NewsListBlock.js";
14
18
  import { formBlock } from "../blocks/builtins/FormBlock.js";
15
19
  import { testimonialsBlock } from "../blocks/builtins/Testimonials.js";
@@ -59,7 +63,7 @@ const contentModule = defineModule({
59
63
  label: "Basisinhoud",
60
64
  description: "Kern-bouwstenen: hero, tekst, afbeelding, CTA, kolommen, zijbalk, witruimte.",
61
65
  core: true,
62
- blocks: [heroBlock, richTextBlock, imageBlock, ctaBlock, columnsBlock, withSidebarBlock, spacerBlock, buttonsBlock, quoteBlock, dividerBlock, ctaWidget, symbolRefBlock]
66
+ blocks: [heroBlock, sectionHeadingBlock, richTextBlock, imageBlock, ctaBlock, columnsBlock, withSidebarBlock, spacerBlock, buttonsBlock, quoteBlock, dividerBlock, ctaWidget, symbolRefBlock]
63
67
  });
64
68
  const galleryModule = defineModule({
65
69
  id: "gallery",
@@ -93,7 +97,7 @@ const pricingModule = defineModule({
93
97
  id: "pricing",
94
98
  version: CORE_VERSION,
95
99
  label: "Prijzen",
96
- blocks: [pricingBlock]
100
+ blocks: [pricingBlock, priceListBlock]
97
101
  });
98
102
  const pagesModule = defineModule({
99
103
  id: "pages",
@@ -241,10 +245,18 @@ const newsletterModule = defineModule({
241
245
  defaultEnabled: false,
242
246
  blocks: [newsletterBlock, newsletterWidget]
243
247
  });
248
+ const verhuurModule = defineModule({
249
+ id: "verhuur",
250
+ version: CORE_VERSION,
251
+ label: "Verhuur & beschikbaarheid",
252
+ description: "Beschikbaarheidskalender uit de iCal-link van je boekingssysteem, met aanvragen voor een gekozen periode.",
253
+ defaultEnabled: false,
254
+ blocks: [availabilityBlock]
255
+ });
244
256
  const bookingModule = defineModule({
245
257
  id: "booking",
246
258
  version: CORE_VERSION,
247
- label: "Afspraak/booking",
259
+ label: "Afspraak maken",
248
260
  description: "Boekings-embed (bv. Calendly), consent-gated.",
249
261
  defaultEnabled: false,
250
262
  blocks: [bookingBlock]
@@ -360,20 +372,19 @@ const consentModule = defineModule({
360
372
  description: "Toestemmingsbanner + consent-opslag; stelt niet-essenti\xEBle scripts uit.",
361
373
  defaultEnabled: false,
362
374
  settingsSchema: z.object({
363
- message: z._default(z.string(), "We gebruiken cookies om de site te verbeteren. Kies hieronder je voorkeuren.").register(z.globalRegistry, { description: "Bannertekst" }),
375
+ message: z._default(z.string(), DEFAULT_MESSAGE).register(z.globalRegistry, { description: "Bannertekst" }),
364
376
  privacyUrl: z.optional(z.string()).register(z.globalRegistry, { description: "Link naar privacyverklaring" }),
365
377
  version: z.optional(z.string()).register(z.globalRegistry, { description: "Beleidsversie (wijzig \u2192 banner opnieuw tonen)" }),
366
378
  showReopen: z._default(z.boolean(), true).register(z.globalRegistry, { description: "Zwevend cookie-knopje om keuze te wijzigen" }),
379
+ toon: z._default(z.enum(["automatisch", "altijd"]), "automatisch").register(z.globalRegistry, {
380
+ description: "Wanneer de banner verschijnt: automatisch = alleen op pagina's met een video, kaart of andere externe inhoud"
381
+ }),
367
382
  categories: z._default(z.array(z.object({
368
383
  id: z.string(),
369
384
  label: z.string(),
370
385
  description: z.optional(z.string()),
371
386
  required: z._default(z.boolean(), false)
372
- })), [
373
- { id: "necessary", label: "Noodzakelijk", description: "Nodig om de site te laten werken.", required: true },
374
- { id: "analytics", label: "Statistieken", description: "Anonieme statistieken om de site te verbeteren.", required: false },
375
- { id: "marketing", label: "Marketing", description: "Externe embeds zoals video's en kaarten.", required: false }
376
- ])
387
+ })), DEFAULT_CATEGORIES.map((c) => ({ ...c, required: Boolean(c.required) })))
377
388
  }),
378
389
  defaultSettings: {}
379
390
  });
@@ -402,6 +413,7 @@ const builtinModules = [
402
413
  contactModule,
403
414
  newsletterModule,
404
415
  bookingModule,
416
+ verhuurModule,
405
417
  accordionModule,
406
418
  embedModule,
407
419
  cardsModule,
@@ -455,6 +467,7 @@ export {
455
467
  teamModule,
456
468
  testimonialsModule,
457
469
  timelineModule,
470
+ verhuurModule,
458
471
  videoModule,
459
472
  whatsappModule
460
473
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/modules/builtins.ts"],"sourcesContent":["/**\n * Ingebouwde modules (XiCMS 3.0). Elke \"feature\" van 2.x is hier een first-class module geworden,\n * zodat hij per site aan/uit kan en los te verbeteren is. De bijbehorende admin-panelen staan in\n * `@xiwebdesign/xicms-core/admin` (paneel-registry), gekoppeld via dezelfde `id`/`featureKey`.\n *\n * Backward compatible: zonder `SiteConfig.modules`/`features` zijn alle modules actief — identiek\n * aan 2.x. De `content`-module is `core: true` en kan niet uitgezet worden (de basis-bouwstenen).\n */\nimport * as z from \"zod/mini\";\nimport { defineModule } from \"./defineModule\";\nimport type { ModuleDefinition } from \"./types\";\n\nimport { heroBlock } from \"../blocks/builtins/Hero\";\nimport { richTextBlock } from \"../blocks/builtins/RichTextBlock\";\nimport { imageBlock } from \"../blocks/builtins/ImageBlock\";\nimport { ctaBlock } from \"../blocks/builtins/Cta\";\nimport { columnsBlock } from \"../blocks/builtins/Columns\";\nimport { spacerBlock } from \"../blocks/builtins/Spacer\";\nimport { galleryBlock } from \"../blocks/builtins/Gallery\";\nimport { faqBlock } from \"../blocks/builtins/Faq\";\nimport { openingHoursBlock } from \"../blocks/builtins/OpeningHours\";\nimport { pricingBlock } from \"../blocks/builtins/Pricing\";\nimport { newsListBlock } from \"../blocks/builtins/NewsListBlock\";\nimport { formBlock } from \"../blocks/builtins/FormBlock\";\nimport { testimonialsBlock } from \"../blocks/builtins/Testimonials\";\nimport { teamBlock } from \"../blocks/builtins/Team\";\nimport { agendaBlock } from \"../blocks/builtins/Agenda\";\nimport { searchBlock } from \"../blocks/builtins/Search\";\nimport { featureBlock, countersBlock, logosBlock, timelineBlock } from \"../blocks/builtins/Sections\";\nimport { symbolRefBlock } from \"../blocks/builtins/SymbolRef\";\nimport { videoBlock } from \"../blocks/builtins/Video\";\nimport { bannerBlock } from \"../blocks/builtins/Banner\";\nimport { contactBlock, socialBlock } from \"../blocks/builtins/Contact\";\nimport { mapBlock } from \"../blocks/builtins/MapBlock\";\nimport { newsletterBlock } from \"../blocks/builtins/Newsletter\";\nimport { bookingBlock } from \"../blocks/builtins/Booking\";\nimport { buttonsBlock, quoteBlock, dividerBlock } from \"../blocks/builtins/Elements\";\nimport { accordionBlock } from \"../blocks/builtins/Accordion\";\nimport { embedBlock } from \"../blocks/builtins/Embed\";\nimport { withSidebarBlock, tabsBlock } from \"../blocks/builtins/Layout\";\nimport { cardsBlock } from \"../blocks/builtins/Cards\";\nimport { downloadsBlock } from \"../blocks/builtins/Downloads\";\nimport { pdfBlock } from \"../blocks/builtins/PdfBlock\";\nimport { countdownBlock } from \"../blocks/builtins/Countdown\";\nimport { sliderBlock } from \"../blocks/builtins/Slider\";\nimport { whatsappChatBlock } from \"../blocks/builtins/WhatsappChat\";\nimport { beforeAfterBlock } from \"../blocks/builtins/BeforeAfter\";\nimport { portfolioBlock } from \"../blocks/builtins/Portfolio\";\nimport { jobsBlock } from \"../blocks/builtins/Jobs\";\nimport { breadcrumbsBlock } from \"../blocks/builtins/Breadcrumbs\";\nimport {\n newsWidget,\n agendaWidget,\n openingHoursWidget,\n contactWidget,\n socialWidget as socialWidgetBlock,\n newsletterWidget,\n ctaWidget,\n galleryWidget,\n testimonialsWidget,\n cardsWidget,\n downloadsWidget,\n countdownWidget,\n} from \"../blocks/builtins/Widgets\";\n\nconst CORE_VERSION = \"5.0.0\";\n\n/**\n * Basis-bouwstenen — altijd aanwezig (niet uit te zetten). Bevat ook de indelingsblokken\n * (kolommen, \"Met zijbalk\") waarmee je widgets naast je hoofdinhoud plaatst, plus de\n * compacte CTA-widget.\n */\nexport const contentModule = defineModule({\n id: \"content\",\n version: CORE_VERSION,\n label: \"Basisinhoud\",\n description: \"Kern-bouwstenen: hero, tekst, afbeelding, CTA, kolommen, zijbalk, witruimte.\",\n core: true,\n blocks: [heroBlock, richTextBlock, imageBlock, ctaBlock, columnsBlock, withSidebarBlock, spacerBlock, buttonsBlock, quoteBlock, dividerBlock, ctaWidget, symbolRefBlock],\n});\n\nexport const galleryModule = defineModule({\n id: \"gallery\",\n version: CORE_VERSION,\n label: \"Fotogalerij\",\n description: \"Galerij-block met grid en (optioneel) lightbox + compacte fotostrip-widget.\",\n blocks: [galleryBlock, galleryWidget],\n // Per-site instelbaar door de agent/klant (modules.gallery.config) zonder core te forken.\n // `.describe()` = het label dat de klant in /beheer ziet.\n settingsSchema: z.object({\n columns: z._default(z.int().check(z.minimum(1)).check(z.maximum(6)), 3).register(z.globalRegistry, { description: \"Kolommen\" }),\n lightbox: z._default(z.boolean(), true).register(z.globalRegistry, { description: \"Lightbox bij klikken\" }),\n }),\n defaultSettings: { columns: 3, lightbox: true },\n});\n\nexport const faqModule = defineModule({\n id: \"faq\",\n version: CORE_VERSION,\n label: \"FAQ\",\n description: \"Veelgestelde vragen (accordeon) met optionele zoek + FAQ-JSON-LD.\",\n blocks: [faqBlock],\n});\n\nexport const openingHoursModule = defineModule({\n id: \"openingHours\",\n version: CORE_VERSION,\n label: \"Openingstijden\",\n description: \"Openingstijden-tabel + compacte widget met 'vandaag' gemarkeerd.\",\n blocks: [openingHoursBlock, openingHoursWidget],\n});\n\nexport const pricingModule = defineModule({\n id: \"pricing\",\n version: CORE_VERSION,\n label: \"Prijzen\",\n blocks: [pricingBlock],\n});\n\nexport const pagesModule = defineModule({\n id: \"pages\",\n version: CORE_VERSION,\n label: \"Pagina's\",\n featureKey: \"pages\",\n description: \"Paginabouwer (draft → publish + versiegeschiedenis).\",\n});\n\nexport const newsModule = defineModule({\n id: \"news\",\n version: CORE_VERSION,\n label: \"Nieuws\",\n featureKey: \"news\",\n description: \"Nieuwsartikelen + nieuwslijst-block + 'laatste nieuws'-widget voor de zijbalk.\",\n blocks: [newsListBlock, newsWidget],\n});\n\nexport const mediaModule = defineModule({\n id: \"media\",\n version: CORE_VERSION,\n label: \"Media\",\n featureKey: \"media\",\n description: \"Mediabeheer met compressie + webp/srcset-varianten.\",\n requires: [{ kind: \"function\", name: \"onMediaUpload\" }, { kind: \"storage\", prefix: \"sites/\" }],\n});\n\nexport const formsModule = defineModule({\n id: \"forms\",\n version: CORE_VERSION,\n label: \"Formulieren\",\n featureKey: \"forms\",\n description: \"Formulierbouwer + inzendingen + e-mailnotificatie.\",\n blocks: [formBlock],\n requires: [\n { kind: \"function\", name: \"submitForm\" },\n { kind: \"firestore\", collection: \"forms\" },\n ],\n});\n\nexport const statsModule = defineModule({\n id: \"stats\",\n version: CORE_VERSION,\n label: \"Statistieken\",\n featureKey: \"stats\",\n description: \"Privacy-vriendelijke bezoekersstatistieken (geen cookies).\",\n requires: [{ kind: \"function\", name: \"trackView\" }],\n});\n\nexport const settingsModule = defineModule({\n id: \"settings\",\n version: CORE_VERSION,\n label: \"Instellingen\",\n core: true,\n description: \"Site-instellingen (nav, thema, SEO, formulier-afzender) — alleen siteadmin.\",\n});\n\n// Opt-in modules (defaultEnabled: false): worden bij installatie of later aangezet via\n// `modules: { <id>: true }`. Geen extra backend nodig — data leeft in de page-blocks.\nexport const testimonialsModule = defineModule({\n id: \"testimonials\",\n version: CORE_VERSION,\n label: \"Reviews\",\n description: \"Klantquotes/reviews met sterren, optionele Review-JSON-LD + compacte review-widget.\",\n defaultEnabled: false,\n blocks: [testimonialsBlock, testimonialsWidget],\n});\n\nexport const teamModule = defineModule({\n id: \"team\",\n version: CORE_VERSION,\n label: \"Team\",\n description: \"Team-/medewerkersoverzicht met foto, functie en bio.\",\n defaultEnabled: false,\n blocks: [teamBlock],\n});\n\nexport const agendaModule = defineModule({\n id: \"agenda\",\n version: CORE_VERSION,\n label: \"Agenda\",\n description: \"Evenementen/agenda (chronologisch) met Event-JSON-LD + 'komende agenda'-widget.\",\n defaultEnabled: false,\n blocks: [agendaBlock, agendaWidget],\n});\n\nexport const searchModule = defineModule({\n id: \"search\",\n version: CORE_VERSION,\n label: \"Zoeken\",\n description: \"Site-zoekblok dat gepubliceerde pagina's (en nieuws) client-side doorzoekt.\",\n defaultEnabled: false,\n blocks: [searchBlock],\n});\n\nexport const featureModule = defineModule({\n id: \"feature\",\n version: CORE_VERSION,\n label: \"Beeld + tekst\",\n description: \"Feature-sectie met afbeelding links/rechts en tekst.\",\n defaultEnabled: false,\n blocks: [featureBlock],\n});\n\nexport const countersModule = defineModule({\n id: \"counters\",\n version: CORE_VERSION,\n label: \"Tellers\",\n description: \"Statistiek-tellers (bv. “100+ klanten”).\",\n defaultEnabled: false,\n blocks: [countersBlock],\n});\n\nexport const logosModule = defineModule({\n id: \"logos\",\n version: CORE_VERSION,\n label: \"Logo's\",\n description: \"Partner-/klantlogo-strip.\",\n defaultEnabled: false,\n blocks: [logosBlock],\n});\n\nexport const timelineModule = defineModule({\n id: \"timeline\",\n version: CORE_VERSION,\n label: \"Tijdlijn\",\n description: \"Stappen/proces als tijdlijn.\",\n defaultEnabled: false,\n blocks: [timelineBlock],\n});\n\nexport const videoModule = defineModule({\n id: \"video\",\n version: CORE_VERSION,\n label: \"Video\",\n description: \"YouTube/Vimeo/MP4-embed (consent-gated).\",\n defaultEnabled: false,\n blocks: [videoBlock],\n});\n\nexport const bannerModule = defineModule({\n id: \"banner\",\n version: CORE_VERSION,\n label: \"Aankondiging\",\n description: \"Aankondigingsbalk, optioneel sluitbaar.\",\n defaultEnabled: false,\n blocks: [bannerBlock],\n});\n\nexport const contactModule = defineModule({\n id: \"contact\",\n version: CORE_VERSION,\n label: \"Contact + kaart + social\",\n description: \"Contactgegevens (JSON-LD), kaart (consent-gated), social-links + compacte widgets.\",\n defaultEnabled: false,\n blocks: [contactBlock, mapBlock, socialBlock, contactWidget, socialWidgetBlock],\n});\n\nexport const newsletterModule = defineModule({\n id: \"newsletter\",\n version: CORE_VERSION,\n label: \"Nieuwsbrief\",\n description: \"Aanmeldformulier via een externe provider-URL + compacte nieuwsbrief-widget.\",\n defaultEnabled: false,\n blocks: [newsletterBlock, newsletterWidget],\n});\n\nexport const bookingModule = defineModule({\n id: \"booking\",\n version: CORE_VERSION,\n label: \"Afspraak/booking\",\n description: \"Boekings-embed (bv. Calendly), consent-gated.\",\n defaultEnabled: false,\n blocks: [bookingBlock],\n});\n\nexport const accordionModule = defineModule({\n id: \"accordion\",\n version: CORE_VERSION,\n label: \"Accordeon\",\n description: \"Generieke in-/uitklapbare panelen.\",\n defaultEnabled: false,\n blocks: [accordionBlock],\n});\n\nexport const embedModule = defineModule({\n id: \"embed\",\n version: CORE_VERSION,\n label: \"Embed\",\n description: \"Generieke responsive iframe-embed (consent-gated).\",\n defaultEnabled: false,\n blocks: [embedBlock],\n});\n\n/* ── Nieuwe modules (3.1) — veelgebruikt op websites, volwaardig + widget waar zinvol ── */\n\nexport const cardsModule = defineModule({\n id: \"cards\",\n version: CORE_VERSION,\n label: \"Diensten / kaarten\",\n description: \"Diensten-/featurekaarten in een grid (icoon of beeld) + compacte 'uitgelicht'-widget.\",\n defaultEnabled: false,\n blocks: [cardsBlock, cardsWidget],\n});\n\nexport const tabsModule = defineModule({\n id: \"tabs\",\n version: CORE_VERSION,\n label: \"Tabbladen\",\n description: \"Tabblad-indeling: per tab een eigen set blokken (bv. beschrijving / specificaties).\",\n defaultEnabled: false,\n blocks: [tabsBlock],\n});\n\nexport const downloadsModule = defineModule({\n id: \"downloads\",\n version: CORE_VERSION,\n label: \"Downloads\",\n description: \"Lijst met downloadbare documenten (brochures, prijslijsten) + compacte widget.\",\n defaultEnabled: false,\n blocks: [downloadsBlock, downloadsWidget],\n});\n\nexport const pdfModule = defineModule({\n id: \"pdf\",\n version: CORE_VERSION,\n label: \"PDF-lezer\",\n description: \"Inline PDF-lezer voor menukaarten/documenten; meerdere PDF's met tabs, zelf te vervangen.\",\n defaultEnabled: false,\n blocks: [pdfBlock],\n});\n\nexport const countdownModule = defineModule({\n id: \"countdown\",\n version: CORE_VERSION,\n label: \"Aftelteller\",\n description: \"Tikkende countdown naar een datum (lancering, evenement, aanbieding) + widget.\",\n defaultEnabled: false,\n blocks: [countdownBlock, countdownWidget],\n});\n\nexport const sliderModule = defineModule({\n id: \"slider\",\n version: CORE_VERSION,\n label: \"Carrousel / slider\",\n description: \"Beeld-/contentcarrousel met dots, pijlen en optioneel autoplay (reduced-motion-veilig).\",\n defaultEnabled: false,\n blocks: [sliderBlock],\n});\n\n/* ── 4.16: nieuwe modules (allemaal opt-in) ──────────────────────────────── */\n\nexport const whatsappModule = defineModule({\n id: \"whatsapp\",\n version: CORE_VERSION,\n label: \"WhatsApp-knop\",\n description: \"Zwevende WhatsApp-/chatknop — laagdrempelig contact (wa.me-link, geen consent nodig).\",\n defaultEnabled: false,\n blocks: [whatsappChatBlock],\n});\n\nexport const beforeAfterModule = defineModule({\n id: \"beforeAfter\",\n version: CORE_VERSION,\n label: \"Voor / na\",\n description: \"Voor/na-vergelijker met sleepbare scheiding — sterk voor hoveniers, schilders, salons.\",\n defaultEnabled: false,\n blocks: [beforeAfterBlock],\n});\n\nexport const portfolioModule = defineModule({\n id: \"portfolio\",\n version: CORE_VERSION,\n label: \"Portfolio / projecten\",\n description: \"Projecten/cases-grid met categorie-filter en lightbox.\",\n defaultEnabled: false,\n blocks: [portfolioBlock],\n});\n\nexport const jobsModule = defineModule({\n id: \"jobs\",\n version: CORE_VERSION,\n label: \"Vacatures\",\n description: \"Vacature-overzicht met JobPosting-JSON-LD (vindbaar via Google Jobs).\",\n defaultEnabled: false,\n blocks: [jobsBlock],\n});\n\nexport const breadcrumbsModule = defineModule({\n id: \"breadcrumbs\",\n version: CORE_VERSION,\n label: \"Kruimelpad\",\n description: \"Kruimelpad afgeleid van de URL, met BreadcrumbList-JSON-LD (SEO).\",\n defaultEnabled: false,\n blocks: [breadcrumbsBlock],\n});\n\n/* ── 5.5: webwinkel + donaties ───────────────────────────────────────────────\n * 6.0: de shop-module zit NIET meer in de default-bundel. Hij is opt-in via de\n * subpath `@xiwebdesign/xicms-core/modules/shop` (+ `/admin/shop`, `/server/shop`),\n * of via de backward-compat-barrel `@xiwebdesign/xicms-core/all`. Zo landt shop-code\n * alleen in de build van sites die 'm daadwerkelijk aanzetten. */\n\nexport const consentModule = defineModule({\n id: \"consent\",\n version: CORE_VERSION,\n label: \"Cookie-consent (AVG)\",\n description: \"Toestemmingsbanner + consent-opslag; stelt niet-essentiële scripts uit.\",\n defaultEnabled: false,\n settingsSchema: z.object({\n message: z._default(z.string(), \"We gebruiken cookies om de site te verbeteren. Kies hieronder je voorkeuren.\").register(z.globalRegistry, { description: \"Bannertekst\" }),\n privacyUrl: z.optional(z.string()).register(z.globalRegistry, { description: \"Link naar privacyverklaring\" }),\n version: z.optional(z.string()).register(z.globalRegistry, { description: \"Beleidsversie (wijzig → banner opnieuw tonen)\" }),\n showReopen: z._default(z.boolean(), true).register(z.globalRegistry, { description: \"Zwevend cookie-knopje om keuze te wijzigen\" }),\n categories: z._default(z.array(z.object({\n id: z.string(),\n label: z.string(),\n description: z.optional(z.string()),\n required: z._default(z.boolean(), false),\n })), [\n { id: \"necessary\", label: \"Noodzakelijk\", description: \"Nodig om de site te laten werken.\", required: true },\n { id: \"analytics\", label: \"Statistieken\", description: \"Anonieme statistieken om de site te verbeteren.\", required: false },\n { id: \"marketing\", label: \"Marketing\", description: \"Externe embeds zoals video's en kaarten.\", required: false },\n ]),\n }),\n defaultSettings: {},\n});\n\n/** Alle ingebouwde modules (volgorde bepaalt block- en tab-volgorde). */\nexport const builtinModules: ModuleDefinition[] = [\n contentModule,\n pagesModule,\n newsModule,\n mediaModule,\n galleryModule,\n faqModule,\n openingHoursModule,\n pricingModule,\n formsModule,\n statsModule,\n settingsModule,\n testimonialsModule,\n teamModule,\n agendaModule,\n searchModule,\n featureModule,\n countersModule,\n logosModule,\n timelineModule,\n videoModule,\n bannerModule,\n contactModule,\n newsletterModule,\n bookingModule,\n accordionModule,\n embedModule,\n cardsModule,\n tabsModule,\n downloadsModule,\n pdfModule,\n countdownModule,\n sliderModule,\n whatsappModule,\n beforeAfterModule,\n portfolioModule,\n jobsModule,\n breadcrumbsModule,\n consentModule,\n];\n"],"mappings":"AAQA,YAAY,OAAO;AACnB,SAAS,oBAAoB;AAG7B,SAAS,iBAAiB;AAC1B,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAC3B,SAAS,gBAAgB;AACzB,SAAS,oBAAoB;AAC7B,SAAS,mBAAmB;AAC5B,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB;AACzB,SAAS,yBAAyB;AAClC,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,iBAAiB;AAC1B,SAAS,yBAAyB;AAClC,SAAS,iBAAiB;AAC1B,SAAS,mBAAmB;AAC5B,SAAS,mBAAmB;AAC5B,SAAS,cAAc,eAAe,YAAY,qBAAqB;AACvE,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,cAAc,mBAAmB;AAC1C,SAAS,gBAAgB;AACzB,SAAS,uBAAuB;AAChC,SAAS,oBAAoB;AAC7B,SAAS,cAAc,YAAY,oBAAoB;AACvD,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB;AAC3B,SAAS,kBAAkB,iBAAiB;AAC5C,SAAS,kBAAkB;AAC3B,SAAS,sBAAsB;AAC/B,SAAS,gBAAgB;AACzB,SAAS,sBAAsB;AAC/B,SAAS,mBAAmB;AAC5B,SAAS,yBAAyB;AAClC,SAAS,wBAAwB;AACjC,SAAS,sBAAsB;AAC/B,SAAS,iBAAiB;AAC1B,SAAS,wBAAwB;AACjC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,gBAAgB;AAAA,EAChB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,MAAM,eAAe;AAOd,MAAM,gBAAgB,aAAa;AAAA,EACxC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,MAAM;AAAA,EACN,QAAQ,CAAC,WAAW,eAAe,YAAY,UAAU,cAAc,kBAAkB,aAAa,cAAc,YAAY,cAAc,WAAW,cAAc;AACzK,CAAC;AAEM,MAAM,gBAAgB,aAAa;AAAA,EACxC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,QAAQ,CAAC,cAAc,aAAa;AAAA;AAAA;AAAA,EAGpC,gBAAgB,EAAE,OAAO;AAAA,IACvB,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,WAAW,CAAC;AAAA,IAC9H,UAAU,EAAE,SAAS,EAAE,QAAQ,GAAG,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,uBAAuB,CAAC;AAAA,EAC5G,CAAC;AAAA,EACD,iBAAiB,EAAE,SAAS,GAAG,UAAU,KAAK;AAChD,CAAC;AAEM,MAAM,YAAY,aAAa;AAAA,EACpC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,QAAQ,CAAC,QAAQ;AACnB,CAAC;AAEM,MAAM,qBAAqB,aAAa;AAAA,EAC7C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,QAAQ,CAAC,mBAAmB,kBAAkB;AAChD,CAAC;AAEM,MAAM,gBAAgB,aAAa;AAAA,EACxC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,QAAQ,CAAC,YAAY;AACvB,CAAC;AAEM,MAAM,cAAc,aAAa;AAAA,EACtC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,aAAa;AACf,CAAC;AAEM,MAAM,aAAa,aAAa;AAAA,EACrC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,QAAQ,CAAC,eAAe,UAAU;AACpC,CAAC;AAEM,MAAM,cAAc,aAAa;AAAA,EACtC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,UAAU,CAAC,EAAE,MAAM,YAAY,MAAM,gBAAgB,GAAG,EAAE,MAAM,WAAW,QAAQ,SAAS,CAAC;AAC/F,CAAC;AAEM,MAAM,cAAc,aAAa;AAAA,EACtC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,QAAQ,CAAC,SAAS;AAAA,EAClB,UAAU;AAAA,IACR,EAAE,MAAM,YAAY,MAAM,aAAa;AAAA,IACvC,EAAE,MAAM,aAAa,YAAY,QAAQ;AAAA,EAC3C;AACF,CAAC;AAEM,MAAM,cAAc,aAAa;AAAA,EACtC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,UAAU,CAAC,EAAE,MAAM,YAAY,MAAM,YAAY,CAAC;AACpD,CAAC;AAEM,MAAM,iBAAiB,aAAa;AAAA,EACzC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,MAAM;AAAA,EACN,aAAa;AACf,CAAC;AAIM,MAAM,qBAAqB,aAAa;AAAA,EAC7C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,mBAAmB,kBAAkB;AAChD,CAAC;AAEM,MAAM,aAAa,aAAa;AAAA,EACrC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,SAAS;AACpB,CAAC;AAEM,MAAM,eAAe,aAAa;AAAA,EACvC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,aAAa,YAAY;AACpC,CAAC;AAEM,MAAM,eAAe,aAAa;AAAA,EACvC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,WAAW;AACtB,CAAC;AAEM,MAAM,gBAAgB,aAAa;AAAA,EACxC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,YAAY;AACvB,CAAC;AAEM,MAAM,iBAAiB,aAAa;AAAA,EACzC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,aAAa;AACxB,CAAC;AAEM,MAAM,cAAc,aAAa;AAAA,EACtC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,UAAU;AACrB,CAAC;AAEM,MAAM,iBAAiB,aAAa;AAAA,EACzC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,aAAa;AACxB,CAAC;AAEM,MAAM,cAAc,aAAa;AAAA,EACtC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,UAAU;AACrB,CAAC;AAEM,MAAM,eAAe,aAAa;AAAA,EACvC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,WAAW;AACtB,CAAC;AAEM,MAAM,gBAAgB,aAAa;AAAA,EACxC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,cAAc,UAAU,aAAa,eAAe,iBAAiB;AAChF,CAAC;AAEM,MAAM,mBAAmB,aAAa;AAAA,EAC3C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,iBAAiB,gBAAgB;AAC5C,CAAC;AAEM,MAAM,gBAAgB,aAAa;AAAA,EACxC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,YAAY;AACvB,CAAC;AAEM,MAAM,kBAAkB,aAAa;AAAA,EAC1C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,cAAc;AACzB,CAAC;AAEM,MAAM,cAAc,aAAa;AAAA,EACtC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,UAAU;AACrB,CAAC;AAIM,MAAM,cAAc,aAAa;AAAA,EACtC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,YAAY,WAAW;AAClC,CAAC;AAEM,MAAM,aAAa,aAAa;AAAA,EACrC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,SAAS;AACpB,CAAC;AAEM,MAAM,kBAAkB,aAAa;AAAA,EAC1C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,gBAAgB,eAAe;AAC1C,CAAC;AAEM,MAAM,YAAY,aAAa;AAAA,EACpC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,QAAQ;AACnB,CAAC;AAEM,MAAM,kBAAkB,aAAa;AAAA,EAC1C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,gBAAgB,eAAe;AAC1C,CAAC;AAEM,MAAM,eAAe,aAAa;AAAA,EACvC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,WAAW;AACtB,CAAC;AAIM,MAAM,iBAAiB,aAAa;AAAA,EACzC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,iBAAiB;AAC5B,CAAC;AAEM,MAAM,oBAAoB,aAAa;AAAA,EAC5C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,gBAAgB;AAC3B,CAAC;AAEM,MAAM,kBAAkB,aAAa;AAAA,EAC1C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,cAAc;AACzB,CAAC;AAEM,MAAM,aAAa,aAAa;AAAA,EACrC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,SAAS;AACpB,CAAC;AAEM,MAAM,oBAAoB,aAAa;AAAA,EAC5C,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,QAAQ,CAAC,gBAAgB;AAC3B,CAAC;AAQM,MAAM,gBAAgB,aAAa;AAAA,EACxC,IAAI;AAAA,EACJ,SAAS;AAAA,EACT,OAAO;AAAA,EACP,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,gBAAgB,EAAE,OAAO;AAAA,IACvB,SAAS,EAAE,SAAS,EAAE,OAAO,GAAG,8EAA8E,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,cAAc,CAAC;AAAA,IACzK,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,8BAA8B,CAAC;AAAA,IAC5G,SAAS,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,qDAAgD,CAAC;AAAA,IAC3H,YAAY,EAAE,SAAS,EAAE,QAAQ,GAAG,IAAI,EAAE,SAAS,EAAE,gBAAgB,EAAE,aAAa,6CAA6C,CAAC;AAAA,IAClI,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO;AAAA,MAClC,IAAI,EAAE,OAAO;AAAA,MACb,OAAO,EAAE,OAAO;AAAA,MAChB,aAAa,EAAE,SAAS,EAAE,OAAO,CAAC;AAAA,MAClC,UAAU,EAAE,SAAS,EAAE,QAAQ,GAAG,KAAK;AAAA,IACzC,CAAC,CAAC,GAAG;AAAA,MACL,EAAE,IAAI,aAAa,OAAO,gBAAgB,aAAa,qCAAqC,UAAU,KAAK;AAAA,MAC3G,EAAE,IAAI,aAAa,OAAO,gBAAgB,aAAa,mDAAmD,UAAU,MAAM;AAAA,MAC1H,EAAE,IAAI,aAAa,OAAO,aAAa,aAAa,4CAA4C,UAAU,MAAM;AAAA,IAClH,CAAC;AAAA,EACL,CAAC;AAAA,EACD,iBAAiB,CAAC;AACpB,CAAC;AAGM,MAAM,iBAAqC;AAAA,EAChD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;","names":[]}
1
+ {"version":3,"sources":["../../src/modules/builtins.ts"],"sourcesContent":["/**\n * Ingebouwde modules (XiCMS 3.0). Elke \"feature\" van 2.x is hier een first-class module geworden,\n * zodat hij per site aan/uit kan en los te verbeteren is. De bijbehorende admin-panelen staan in\n * `@xiwebdesign/xicms-core/admin` (paneel-registry), gekoppeld via dezelfde `id`/`featureKey`.\n *\n * Backward compatible: zonder `SiteConfig.modules`/`features` zijn alle modules actief — identiek\n * aan 2.x. De `content`-module is `core: true` en kan niet uitgezet worden (de basis-bouwstenen).\n */\nimport * as z from \"zod/mini\";\nimport { defineModule } from \"./defineModule\";\nimport { DEFAULT_CATEGORIES, DEFAULT_MESSAGE } from \"./consent/standaard\";\nimport type { ModuleDefinition } from \"./types\";\n\nimport { heroBlock } from \"../blocks/builtins/Hero\";\nimport { richTextBlock } from \"../blocks/builtins/RichTextBlock\";\nimport { imageBlock } from \"../blocks/builtins/ImageBlock\";\nimport { ctaBlock } from \"../blocks/builtins/Cta\";\nimport { columnsBlock } from \"../blocks/builtins/Columns\";\nimport { spacerBlock } from \"../blocks/builtins/Spacer\";\nimport { galleryBlock } from \"../blocks/builtins/Gallery\";\nimport { faqBlock } from \"../blocks/builtins/Faq\";\nimport { openingHoursBlock } from \"../blocks/builtins/OpeningHours\";\nimport { pricingBlock } from \"../blocks/builtins/Pricing\";\nimport { priceListBlock } from \"../blocks/builtins/PriceList\";\nimport { sectionHeadingBlock } from \"../blocks/builtins/SectionHeading\";\nimport { availabilityBlock } from \"../blocks/builtins/Availability\";\nimport { newsListBlock } from \"../blocks/builtins/NewsListBlock\";\nimport { formBlock } from \"../blocks/builtins/FormBlock\";\nimport { testimonialsBlock } from \"../blocks/builtins/Testimonials\";\nimport { teamBlock } from \"../blocks/builtins/Team\";\nimport { agendaBlock } from \"../blocks/builtins/Agenda\";\nimport { searchBlock } from \"../blocks/builtins/Search\";\nimport { featureBlock, countersBlock, logosBlock, timelineBlock } from \"../blocks/builtins/Sections\";\nimport { symbolRefBlock } from \"../blocks/builtins/SymbolRef\";\nimport { videoBlock } from \"../blocks/builtins/Video\";\nimport { bannerBlock } from \"../blocks/builtins/Banner\";\nimport { contactBlock, socialBlock } from \"../blocks/builtins/Contact\";\nimport { mapBlock } from \"../blocks/builtins/MapBlock\";\nimport { newsletterBlock } from \"../blocks/builtins/Newsletter\";\nimport { bookingBlock } from \"../blocks/builtins/Booking\";\nimport { buttonsBlock, quoteBlock, dividerBlock } from \"../blocks/builtins/Elements\";\nimport { accordionBlock } from \"../blocks/builtins/Accordion\";\nimport { embedBlock } from \"../blocks/builtins/Embed\";\nimport { withSidebarBlock, tabsBlock } from \"../blocks/builtins/Layout\";\nimport { cardsBlock } from \"../blocks/builtins/Cards\";\nimport { downloadsBlock } from \"../blocks/builtins/Downloads\";\nimport { pdfBlock } from \"../blocks/builtins/PdfBlock\";\nimport { countdownBlock } from \"../blocks/builtins/Countdown\";\nimport { sliderBlock } from \"../blocks/builtins/Slider\";\nimport { whatsappChatBlock } from \"../blocks/builtins/WhatsappChat\";\nimport { beforeAfterBlock } from \"../blocks/builtins/BeforeAfter\";\nimport { portfolioBlock } from \"../blocks/builtins/Portfolio\";\nimport { jobsBlock } from \"../blocks/builtins/Jobs\";\nimport { breadcrumbsBlock } from \"../blocks/builtins/Breadcrumbs\";\nimport {\n newsWidget,\n agendaWidget,\n openingHoursWidget,\n contactWidget,\n socialWidget as socialWidgetBlock,\n newsletterWidget,\n ctaWidget,\n galleryWidget,\n testimonialsWidget,\n cardsWidget,\n downloadsWidget,\n countdownWidget,\n} from \"../blocks/builtins/Widgets\";\n\nconst CORE_VERSION = \"5.0.0\";\n\n/**\n * Basis-bouwstenen — altijd aanwezig (niet uit te zetten). Bevat ook de indelingsblokken\n * (kolommen, \"Met zijbalk\") waarmee je widgets naast je hoofdinhoud plaatst, plus de\n * compacte CTA-widget.\n */\nexport const contentModule = defineModule({\n id: \"content\",\n version: CORE_VERSION,\n label: \"Basisinhoud\",\n description: \"Kern-bouwstenen: hero, tekst, afbeelding, CTA, kolommen, zijbalk, witruimte.\",\n core: true,\n blocks: [heroBlock, sectionHeadingBlock, richTextBlock, imageBlock, ctaBlock, columnsBlock, withSidebarBlock, spacerBlock, buttonsBlock, quoteBlock, dividerBlock, ctaWidget, symbolRefBlock],\n});\n\nexport const galleryModule = defineModule({\n id: \"gallery\",\n version: CORE_VERSION,\n label: \"Fotogalerij\",\n description: \"Galerij-block met grid en (optioneel) lightbox + compacte fotostrip-widget.\",\n blocks: [galleryBlock, galleryWidget],\n // Per-site instelbaar door de agent/klant (modules.gallery.config) zonder core te forken.\n // `.describe()` = het label dat de klant in /beheer ziet.\n settingsSchema: z.object({\n columns: z._default(z.int().check(z.minimum(1)).check(z.maximum(6)), 3).register(z.globalRegistry, { description: \"Kolommen\" }),\n lightbox: z._default(z.boolean(), true).register(z.globalRegistry, { description: \"Lightbox bij klikken\" }),\n }),\n defaultSettings: { columns: 3, lightbox: true },\n});\n\nexport const faqModule = defineModule({\n id: \"faq\",\n version: CORE_VERSION,\n label: \"FAQ\",\n description: \"Veelgestelde vragen (accordeon) met optionele zoek + FAQ-JSON-LD.\",\n blocks: [faqBlock],\n});\n\nexport const openingHoursModule = defineModule({\n id: \"openingHours\",\n version: CORE_VERSION,\n label: \"Openingstijden\",\n description: \"Openingstijden-tabel + compacte widget met 'vandaag' gemarkeerd.\",\n blocks: [openingHoursBlock, openingHoursWidget],\n});\n\nexport const pricingModule = defineModule({\n id: \"pricing\",\n version: CORE_VERSION,\n label: \"Prijzen\",\n blocks: [pricingBlock, priceListBlock],\n});\n\nexport const pagesModule = defineModule({\n id: \"pages\",\n version: CORE_VERSION,\n label: \"Pagina's\",\n featureKey: \"pages\",\n description: \"Paginabouwer (draft → publish + versiegeschiedenis).\",\n});\n\nexport const newsModule = defineModule({\n id: \"news\",\n version: CORE_VERSION,\n label: \"Nieuws\",\n featureKey: \"news\",\n description: \"Nieuwsartikelen + nieuwslijst-block + 'laatste nieuws'-widget voor de zijbalk.\",\n blocks: [newsListBlock, newsWidget],\n});\n\nexport const mediaModule = defineModule({\n id: \"media\",\n version: CORE_VERSION,\n label: \"Media\",\n featureKey: \"media\",\n description: \"Mediabeheer met compressie + webp/srcset-varianten.\",\n requires: [{ kind: \"function\", name: \"onMediaUpload\" }, { kind: \"storage\", prefix: \"sites/\" }],\n});\n\nexport const formsModule = defineModule({\n id: \"forms\",\n version: CORE_VERSION,\n label: \"Formulieren\",\n featureKey: \"forms\",\n description: \"Formulierbouwer + inzendingen + e-mailnotificatie.\",\n blocks: [formBlock],\n requires: [\n { kind: \"function\", name: \"submitForm\" },\n { kind: \"firestore\", collection: \"forms\" },\n ],\n});\n\nexport const statsModule = defineModule({\n id: \"stats\",\n version: CORE_VERSION,\n label: \"Statistieken\",\n featureKey: \"stats\",\n description: \"Privacy-vriendelijke bezoekersstatistieken (geen cookies).\",\n requires: [{ kind: \"function\", name: \"trackView\" }],\n});\n\nexport const settingsModule = defineModule({\n id: \"settings\",\n version: CORE_VERSION,\n label: \"Instellingen\",\n core: true,\n description: \"Site-instellingen (nav, thema, SEO, formulier-afzender) — alleen siteadmin.\",\n});\n\n// Opt-in modules (defaultEnabled: false): worden bij installatie of later aangezet via\n// `modules: { <id>: true }`. Geen extra backend nodig — data leeft in de page-blocks.\nexport const testimonialsModule = defineModule({\n id: \"testimonials\",\n version: CORE_VERSION,\n label: \"Reviews\",\n description: \"Klantquotes/reviews met sterren, optionele Review-JSON-LD + compacte review-widget.\",\n defaultEnabled: false,\n blocks: [testimonialsBlock, testimonialsWidget],\n});\n\nexport const teamModule = defineModule({\n id: \"team\",\n version: CORE_VERSION,\n label: \"Team\",\n description: \"Team-/medewerkersoverzicht met foto, functie en bio.\",\n defaultEnabled: false,\n blocks: [teamBlock],\n});\n\nexport const agendaModule = defineModule({\n id: \"agenda\",\n version: CORE_VERSION,\n label: \"Agenda\",\n description: \"Evenementen/agenda (chronologisch) met Event-JSON-LD + 'komende agenda'-widget.\",\n defaultEnabled: false,\n blocks: [agendaBlock, agendaWidget],\n});\n\nexport const searchModule = defineModule({\n id: \"search\",\n version: CORE_VERSION,\n label: \"Zoeken\",\n description: \"Site-zoekblok dat gepubliceerde pagina's (en nieuws) client-side doorzoekt.\",\n defaultEnabled: false,\n blocks: [searchBlock],\n});\n\nexport const featureModule = defineModule({\n id: \"feature\",\n version: CORE_VERSION,\n label: \"Beeld + tekst\",\n description: \"Feature-sectie met afbeelding links/rechts en tekst.\",\n defaultEnabled: false,\n blocks: [featureBlock],\n});\n\nexport const countersModule = defineModule({\n id: \"counters\",\n version: CORE_VERSION,\n label: \"Tellers\",\n description: \"Statistiek-tellers (bv. “100+ klanten”).\",\n defaultEnabled: false,\n blocks: [countersBlock],\n});\n\nexport const logosModule = defineModule({\n id: \"logos\",\n version: CORE_VERSION,\n label: \"Logo's\",\n description: \"Partner-/klantlogo-strip.\",\n defaultEnabled: false,\n blocks: [logosBlock],\n});\n\nexport const timelineModule = defineModule({\n id: \"timeline\",\n version: CORE_VERSION,\n label: \"Tijdlijn\",\n description: \"Stappen/proces als tijdlijn.\",\n defaultEnabled: false,\n blocks: [timelineBlock],\n});\n\nexport const videoModule = defineModule({\n id: \"video\",\n version: CORE_VERSION,\n label: \"Video\",\n description: \"YouTube/Vimeo/MP4-embed (consent-gated).\",\n defaultEnabled: false,\n blocks: [videoBlock],\n});\n\nexport const bannerModule = defineModule({\n id: \"banner\",\n version: CORE_VERSION,\n label: \"Aankondiging\",\n description: \"Aankondigingsbalk, optioneel sluitbaar.\",\n defaultEnabled: false,\n blocks: [bannerBlock],\n});\n\nexport const contactModule = defineModule({\n id: \"contact\",\n version: CORE_VERSION,\n label: \"Contact + kaart + social\",\n description: \"Contactgegevens (JSON-LD), kaart (consent-gated), social-links + compacte widgets.\",\n defaultEnabled: false,\n blocks: [contactBlock, mapBlock, socialBlock, contactWidget, socialWidgetBlock],\n});\n\nexport const newsletterModule = defineModule({\n id: \"newsletter\",\n version: CORE_VERSION,\n label: \"Nieuwsbrief\",\n description: \"Aanmeldformulier via een externe provider-URL + compacte nieuwsbrief-widget.\",\n defaultEnabled: false,\n blocks: [newsletterBlock, newsletterWidget],\n});\n\nexport const verhuurModule = defineModule({\n id: \"verhuur\",\n version: CORE_VERSION,\n label: \"Verhuur & beschikbaarheid\",\n description: \"Beschikbaarheidskalender uit de iCal-link van je boekingssysteem, met aanvragen voor een gekozen periode.\",\n defaultEnabled: false,\n blocks: [availabilityBlock],\n});\n\nexport const bookingModule = defineModule({\n id: \"booking\",\n version: CORE_VERSION,\n label: \"Afspraak maken\",\n description: \"Boekings-embed (bv. Calendly), consent-gated.\",\n defaultEnabled: false,\n blocks: [bookingBlock],\n});\n\nexport const accordionModule = defineModule({\n id: \"accordion\",\n version: CORE_VERSION,\n label: \"Accordeon\",\n description: \"Generieke in-/uitklapbare panelen.\",\n defaultEnabled: false,\n blocks: [accordionBlock],\n});\n\nexport const embedModule = defineModule({\n id: \"embed\",\n version: CORE_VERSION,\n label: \"Embed\",\n description: \"Generieke responsive iframe-embed (consent-gated).\",\n defaultEnabled: false,\n blocks: [embedBlock],\n});\n\n/* ── Nieuwe modules (3.1) — veelgebruikt op websites, volwaardig + widget waar zinvol ── */\n\nexport const cardsModule = defineModule({\n id: \"cards\",\n version: CORE_VERSION,\n label: \"Diensten / kaarten\",\n description: \"Diensten-/featurekaarten in een grid (icoon of beeld) + compacte 'uitgelicht'-widget.\",\n defaultEnabled: false,\n blocks: [cardsBlock, cardsWidget],\n});\n\nexport const tabsModule = defineModule({\n id: \"tabs\",\n version: CORE_VERSION,\n label: \"Tabbladen\",\n description: \"Tabblad-indeling: per tab een eigen set blokken (bv. beschrijving / specificaties).\",\n defaultEnabled: false,\n blocks: [tabsBlock],\n});\n\nexport const downloadsModule = defineModule({\n id: \"downloads\",\n version: CORE_VERSION,\n label: \"Downloads\",\n description: \"Lijst met downloadbare documenten (brochures, prijslijsten) + compacte widget.\",\n defaultEnabled: false,\n blocks: [downloadsBlock, downloadsWidget],\n});\n\nexport const pdfModule = defineModule({\n id: \"pdf\",\n version: CORE_VERSION,\n label: \"PDF-lezer\",\n description: \"Inline PDF-lezer voor menukaarten/documenten; meerdere PDF's met tabs, zelf te vervangen.\",\n defaultEnabled: false,\n blocks: [pdfBlock],\n});\n\nexport const countdownModule = defineModule({\n id: \"countdown\",\n version: CORE_VERSION,\n label: \"Aftelteller\",\n description: \"Tikkende countdown naar een datum (lancering, evenement, aanbieding) + widget.\",\n defaultEnabled: false,\n blocks: [countdownBlock, countdownWidget],\n});\n\nexport const sliderModule = defineModule({\n id: \"slider\",\n version: CORE_VERSION,\n label: \"Carrousel / slider\",\n description: \"Beeld-/contentcarrousel met dots, pijlen en optioneel autoplay (reduced-motion-veilig).\",\n defaultEnabled: false,\n blocks: [sliderBlock],\n});\n\n/* ── 4.16: nieuwe modules (allemaal opt-in) ──────────────────────────────── */\n\nexport const whatsappModule = defineModule({\n id: \"whatsapp\",\n version: CORE_VERSION,\n label: \"WhatsApp-knop\",\n description: \"Zwevende WhatsApp-/chatknop — laagdrempelig contact (wa.me-link, geen consent nodig).\",\n defaultEnabled: false,\n blocks: [whatsappChatBlock],\n});\n\nexport const beforeAfterModule = defineModule({\n id: \"beforeAfter\",\n version: CORE_VERSION,\n label: \"Voor / na\",\n description: \"Voor/na-vergelijker met sleepbare scheiding — sterk voor hoveniers, schilders, salons.\",\n defaultEnabled: false,\n blocks: [beforeAfterBlock],\n});\n\nexport const portfolioModule = defineModule({\n id: \"portfolio\",\n version: CORE_VERSION,\n label: \"Portfolio / projecten\",\n description: \"Projecten/cases-grid met categorie-filter en lightbox.\",\n defaultEnabled: false,\n blocks: [portfolioBlock],\n});\n\nexport const jobsModule = defineModule({\n id: \"jobs\",\n version: CORE_VERSION,\n label: \"Vacatures\",\n description: \"Vacature-overzicht met JobPosting-JSON-LD (vindbaar via Google Jobs).\",\n defaultEnabled: false,\n blocks: [jobsBlock],\n});\n\nexport const breadcrumbsModule = defineModule({\n id: \"breadcrumbs\",\n version: CORE_VERSION,\n label: \"Kruimelpad\",\n description: \"Kruimelpad afgeleid van de URL, met BreadcrumbList-JSON-LD (SEO).\",\n defaultEnabled: false,\n blocks: [breadcrumbsBlock],\n});\n\n/* ── 5.5: webwinkel + donaties ───────────────────────────────────────────────\n * 6.0: de shop-module zit NIET meer in de default-bundel. Hij is opt-in via de\n * subpath `@xiwebdesign/xicms-core/modules/shop` (+ `/admin/shop`, `/server/shop`),\n * of via de backward-compat-barrel `@xiwebdesign/xicms-core/all`. Zo landt shop-code\n * alleen in de build van sites die 'm daadwerkelijk aanzetten. */\n\nexport const consentModule = defineModule({\n id: \"consent\",\n version: CORE_VERSION,\n label: \"Cookie-consent (AVG)\",\n description: \"Toestemmingsbanner + consent-opslag; stelt niet-essentiële scripts uit.\",\n defaultEnabled: false,\n settingsSchema: z.object({\n message: z._default(z.string(), DEFAULT_MESSAGE).register(z.globalRegistry, { description: \"Bannertekst\" }),\n privacyUrl: z.optional(z.string()).register(z.globalRegistry, { description: \"Link naar privacyverklaring\" }),\n version: z.optional(z.string()).register(z.globalRegistry, { description: \"Beleidsversie (wijzig → banner opnieuw tonen)\" }),\n showReopen: z._default(z.boolean(), true).register(z.globalRegistry, { description: \"Zwevend cookie-knopje om keuze te wijzigen\" }),\n toon: z._default(z.enum([\"automatisch\", \"altijd\"]), \"automatisch\").register(z.globalRegistry, {\n description: \"Wanneer de banner verschijnt: automatisch = alleen op pagina's met een video, kaart of andere externe inhoud\",\n }),\n categories: z._default(z.array(z.object({\n id: z.string(),\n label: z.string(),\n description: z.optional(z.string()),\n required: z._default(z.boolean(), false),\n })), DEFAULT_CATEGORIES.map((c) => ({ ...c, required: Boolean(c.required) }))),\n }),\n defaultSettings: {},\n});\n\n/** Alle ingebouwde modules (volgorde bepaalt block- en tab-volgorde). */\nexport const builtinModules: ModuleDefinition[] = [\n contentModule,\n pagesModule,\n newsModule,\n mediaModule,\n galleryModule,\n faqModule,\n openingHoursModule,\n pricingModule,\n formsModule,\n statsModule,\n settingsModule,\n testimonialsModule,\n teamModule,\n agendaModule,\n searchModule,\n featureModule,\n countersModule,\n logosModule,\n timelineModule,\n videoModule,\n bannerModule,\n contactModule,\n newsletterModule,\n bookingModule,\n verhuurModule,\n accordionModule,\n embedModule,\n cardsModule,\n tabsModule,\n downloadsModule,\n pdfModule,\n countdownModule,\n sliderModule,\n whatsappModule,\n beforeAfterModule,\n portfolioModule,\n jobsModule,\n breadcrumbsModule,\n consentModule,\n];\n"],"mappings":"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","names":[]}
@@ -14,6 +14,11 @@ export interface ConsentSettings {
14
14
  version?: string;
15
15
  /** Zwevend 🍪-knopje tonen om de keuze later te wijzigen (AVG). Standaard aan. */
16
16
  showReopen?: boolean;
17
+ /**
18
+ * 8.16: "automatisch" (standaard) = de banner verschijnt alleen op een pagina waar iets op
19
+ * toestemming wacht (video, kaart, boekingswidget, ConsentGate). "altijd" = het oude gedrag.
20
+ */
21
+ toon?: "automatisch" | "altijd";
17
22
  }
18
23
  /**
19
24
  * AVG-toestemmingsbanner met twee-staps-UX: compact (accepteren / weigeren / voorkeuren), en een
@@ -1,12 +1,9 @@
1
1
  "use client";
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useRef, useState } from "react";
4
- import { consentDecided, useConsent } from "./useConsent.js";
5
- const DEFAULT_CATEGORIES = [
6
- { id: "necessary", label: "Noodzakelijk", required: true, description: "Nodig om de site te laten werken. Altijd actief." },
7
- { id: "analytics", label: "Statistieken", description: "Anonieme bezoekersstatistieken om de site te verbeteren." },
8
- { id: "marketing", label: "Marketing", description: "Voor gepersonaliseerde content en advertenties." }
9
- ];
4
+ import { consentDecided, useConsent, useConsentNodig, useMeldConsentNodig } from "./useConsent.js";
5
+ import { useOnderOffset } from "../../components/onderOffset.js";
6
+ import { DEFAULT_CATEGORIES, DEFAULT_MESSAGE } from "./standaard.js";
10
7
  function ConsentBanner({ settings }) {
11
8
  const { state, save } = useConsent();
12
9
  const categories = settings?.categories?.length ? settings.categories : DEFAULT_CATEGORIES;
@@ -20,6 +17,8 @@ function ConsentBanner({ settings }) {
20
17
  if (reopened) bannerRef.current?.querySelector(".xicms-consent__btn--primary")?.focus();
21
18
  }, [reopened]);
22
19
  const decided = consentDecided(state, settings?.version);
20
+ const nodig = useConsentNodig();
21
+ useOnderOffset();
23
22
  const openBanner = () => {
24
23
  setChoices((prev) => ({ ...prev, ...state.categories }));
25
24
  setShowPrefs(true);
@@ -30,6 +29,7 @@ function ConsentBanner({ settings }) {
30
29
  window.addEventListener("xicms:consent:open", onOpen);
31
30
  return () => window.removeEventListener("xicms:consent:open", onOpen);
32
31
  }, [state.categories]);
32
+ if (!decided && !reopened && settings?.toon !== "altijd" && !nodig) return null;
33
33
  if (decided && !reopened) {
34
34
  if (settings?.showReopen === false) return null;
35
35
  return /* @__PURE__ */ jsx(
@@ -55,7 +55,7 @@ function ConsentBanner({ settings }) {
55
55
  /* @__PURE__ */ jsxs("div", { className: "xicms-consent__head", children: [
56
56
  /* @__PURE__ */ jsx("p", { className: "xicms-consent__title", children: settings?.title ?? "\u{1F36A} Cookievoorkeuren" }),
57
57
  /* @__PURE__ */ jsxs("p", { className: "xicms-consent__message", children: [
58
- settings?.message ?? "We gebruiken cookies om de site te laten werken en te verbeteren. Kies hieronder wat je toestaat.",
58
+ settings?.message ?? DEFAULT_MESSAGE,
59
59
  settings?.privacyUrl && /* @__PURE__ */ jsxs(Fragment, { children: [
60
60
  " ",
61
61
  /* @__PURE__ */ jsx("a", { className: "xicms-consent__link", href: settings.privacyUrl, children: "Privacyverklaring" })
@@ -98,6 +98,7 @@ function ConsentBanner({ settings }) {
98
98
  }
99
99
  function ConsentGate({ category, children }) {
100
100
  const { has } = useConsent();
101
+ useMeldConsentNodig(category, !has(category));
101
102
  return has(category) ? /* @__PURE__ */ jsx(Fragment, { children }) : null;
102
103
  }
103
104
  function ConsentReopenLink({ children, className }) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/modules/consent/ConsentBanner.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { consentDecided, useConsent } from \"./useConsent\";\n\nexport interface ConsentCategory {\n id: string;\n label: string;\n /** Korte uitleg wat deze categorie doet (getoond in het voorkeuren-paneel). */\n description?: string;\n required?: boolean;\n}\n\nexport interface ConsentSettings {\n title?: string;\n message?: string;\n privacyUrl?: string;\n categories?: ConsentCategory[];\n /** Beleidsversie: verhoog dit als het cookiebeleid wijzigt — bezoekers krijgen de banner dan opnieuw. */\n version?: string;\n /** Zwevend 🍪-knopje tonen om de keuze later te wijzigen (AVG). Standaard aan. */\n showReopen?: boolean;\n}\n\nconst DEFAULT_CATEGORIES: ConsentCategory[] = [\n { id: \"necessary\", label: \"Noodzakelijk\", required: true, description: \"Nodig om de site te laten werken. Altijd actief.\" },\n { id: \"analytics\", label: \"Statistieken\", description: \"Anonieme bezoekersstatistieken om de site te verbeteren.\" },\n { id: \"marketing\", label: \"Marketing\", description: \"Voor gepersonaliseerde content en advertenties.\" },\n];\n\n/**\n * AVG-toestemmingsbanner met twee-staps-UX: compact (accepteren / weigeren / voorkeuren), en een\n * uitklapbaar voorkeuren-paneel met toggle-switches + uitleg per categorie. Strak gestyled op de\n * thema-tokens (`--color-*`), volledig overschrijfbaar via de `xicms-consent*`-classNames. Verschijnt\n * pas als de bezoeker nog niet heeft gekozen; logica/opslag blijven in core.\n */\nexport function ConsentBanner({ settings }: { settings?: ConsentSettings }) {\n const { state, save } = useConsent();\n const categories = settings?.categories?.length ? settings.categories : DEFAULT_CATEGORIES;\n const [choices, setChoices] = useState<Record<string, boolean>>(() =>\n Object.fromEntries(categories.map((c) => [c.id, Boolean(c.required)])),\n );\n const [showPrefs, setShowPrefs] = useState(false);\n // Geforceerd (her)openen: via het 🍪-knopje of het `xicms:consent:open`-event (footerlink).\n const [reopened, setReopened] = useState(false);\n const bannerRef = useRef<HTMLDivElement | null>(null);\n // Bij expliciet heropenen focus de banner in (de bezoeker vroeg erom); bij eerste bezoek\n // stelen we géén focus — de banner is niet-modaal en mag het lezen niet onderbreken.\n useEffect(() => {\n if (reopened) bannerRef.current?.querySelector<HTMLElement>(\".xicms-consent__btn--primary\")?.focus();\n }, [reopened]);\n // Een oude keuze telt niet meer als de beleidsversie is gewijzigd → banner opnieuw tonen.\n const decided = consentDecided(state, settings?.version);\n\n const openBanner = () => {\n // Voorkeuren voor-invullen met de huidige keuze zodat wijzigen intuïtief is.\n setChoices((prev) => ({ ...prev, ...state.categories }));\n setShowPrefs(true);\n setReopened(true);\n };\n\n useEffect(() => {\n const onOpen = () => openBanner();\n window.addEventListener(\"xicms:consent:open\", onOpen);\n return () => window.removeEventListener(\"xicms:consent:open\", onOpen);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.categories]);\n\n if (decided && !reopened) {\n // AVG: de bezoeker moet zijn keuze altijd kunnen wijzigen — zwevend knopje (opt-out via settings).\n if (settings?.showReopen === false) return null;\n return (\n <button\n type=\"button\"\n className=\"xicms-consent__reopen\"\n aria-label=\"Cookie-instellingen wijzigen\"\n title=\"Cookie-instellingen\"\n onClick={openBanner}\n >\n 🍪\n </button>\n );\n }\n\n const commit = (categories: Record<string, boolean>) => {\n save(categories, settings?.version);\n setReopened(false);\n };\n const acceptAll = () => commit(Object.fromEntries(categories.map((c) => [c.id, true])));\n const rejectNonEssential = () =>\n commit(Object.fromEntries(categories.map((c) => [c.id, Boolean(c.required)])));\n const saveChoices = () => commit(choices);\n\n return (\n <div ref={bannerRef} className=\"xicms-consent\" role=\"dialog\" aria-modal=\"false\" aria-label=\"Cookievoorkeuren\">\n <div className=\"xicms-consent__inner\" data-prefs={showPrefs ? \"1\" : \"0\"}>\n <div className=\"xicms-consent__head\">\n <p className=\"xicms-consent__title\">{settings?.title ?? \"🍪 Cookievoorkeuren\"}</p>\n <p className=\"xicms-consent__message\">\n {settings?.message ??\n \"We gebruiken cookies om de site te laten werken en te verbeteren. Kies hieronder wat je toestaat.\"}\n {settings?.privacyUrl && (\n <>\n {\" \"}\n <a className=\"xicms-consent__link\" href={settings.privacyUrl}>\n Privacyverklaring\n </a>\n </>\n )}\n </p>\n </div>\n\n {showPrefs && (\n <fieldset className=\"xicms-consent__categories\">\n <legend className=\"xicms-sr-only\">Cookiecategorieën</legend>\n {categories.map((c) => {\n const on = choices[c.id] ?? Boolean(c.required);\n return (\n <label key={c.id} className=\"xicms-consent__category\" data-on={on ? \"1\" : \"0\"}>\n <span className=\"xicms-consent__cat-text\">\n <span className=\"xicms-consent__cat-label\">\n {c.label}\n {c.required && <span className=\"xicms-consent__required\"> · altijd aan</span>}\n </span>\n {c.description && <span className=\"xicms-consent__cat-desc\">{c.description}</span>}\n </span>\n <span className=\"xicms-consent__switch\">\n <input\n type=\"checkbox\"\n checked={on}\n disabled={c.required}\n onChange={(e) => setChoices((prev) => ({ ...prev, [c.id]: e.target.checked }))}\n />\n <span className=\"xicms-consent__track\" aria-hidden=\"true\" />\n </span>\n </label>\n );\n })}\n </fieldset>\n )}\n\n <div className=\"xicms-consent__actions\">\n {!showPrefs ? (\n <button type=\"button\" className=\"xicms-consent__btn xicms-consent__btn--ghost\" onClick={() => setShowPrefs(true)}>\n Voorkeuren\n </button>\n ) : (\n <button type=\"button\" className=\"xicms-consent__btn xicms-consent__btn--ghost\" onClick={saveChoices}>\n Mijn keuze opslaan\n </button>\n )}\n <button type=\"button\" className=\"xicms-consent__btn xicms-consent__btn--ghost\" onClick={rejectNonEssential}>\n Alleen noodzakelijk\n </button>\n <button type=\"button\" className=\"xicms-consent__btn xicms-consent__btn--primary\" onClick={acceptAll}>\n Alles accepteren\n </button>\n </div>\n </div>\n </div>\n );\n}\n\n/**\n * Toont children alleen als toestemming voor `category` is gegeven. Gebruik dit om niet-essentiële\n * scripts/embeds (analytics, video, maps) pas na consent te laden.\n */\nexport function ConsentGate({ category, children }: { category: string; children: React.ReactNode }) {\n const { has } = useConsent();\n return has(category) ? <>{children}</> : null;\n}\n\n/**\n * Tekstlink/knop die de cookievoorkeuren heropent — voor in een footer (\"Cookie-instellingen\").\n * Werkt via het `xicms:consent:open`-event; de ConsentBanner luistert daarnaar.\n */\nexport function ConsentReopenLink({ children, className }: { children?: React.ReactNode; className?: string }) {\n return (\n <button\n type=\"button\"\n className={className ?? \"xicms-consent__reopen-link\"}\n onClick={() => window.dispatchEvent(new Event(\"xicms:consent:open\"))}\n >\n {children ?? \"Cookie-instellingen\"}\n </button>\n );\n}\n"],"mappings":"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","names":["categories"]}
1
+ {"version":3,"sources":["../../../src/modules/consent/ConsentBanner.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport { consentDecided, useConsent, useConsentNodig, useMeldConsentNodig } from \"./useConsent\";\nimport { useOnderOffset } from \"../../components/onderOffset\";\nimport { DEFAULT_CATEGORIES, DEFAULT_MESSAGE } from \"./standaard\";\n\nexport interface ConsentCategory {\n id: string;\n label: string;\n /** Korte uitleg wat deze categorie doet (getoond in het voorkeuren-paneel). */\n description?: string;\n required?: boolean;\n}\n\nexport interface ConsentSettings {\n title?: string;\n message?: string;\n privacyUrl?: string;\n categories?: ConsentCategory[];\n /** Beleidsversie: verhoog dit als het cookiebeleid wijzigt — bezoekers krijgen de banner dan opnieuw. */\n version?: string;\n /** Zwevend 🍪-knopje tonen om de keuze later te wijzigen (AVG). Standaard aan. */\n showReopen?: boolean;\n /**\n * 8.16: \"automatisch\" (standaard) = de banner verschijnt alleen op een pagina waar iets op\n * toestemming wacht (video, kaart, boekingswidget, ConsentGate). \"altijd\" = het oude gedrag.\n */\n toon?: \"automatisch\" | \"altijd\";\n}\n\n/**\n * AVG-toestemmingsbanner met twee-staps-UX: compact (accepteren / weigeren / voorkeuren), en een\n * uitklapbaar voorkeuren-paneel met toggle-switches + uitleg per categorie. Strak gestyled op de\n * thema-tokens (`--color-*`), volledig overschrijfbaar via de `xicms-consent*`-classNames. Verschijnt\n * pas als de bezoeker nog niet heeft gekozen; logica/opslag blijven in core.\n */\nexport function ConsentBanner({ settings }: { settings?: ConsentSettings }) {\n const { state, save } = useConsent();\n const categories = settings?.categories?.length ? settings.categories : DEFAULT_CATEGORIES;\n const [choices, setChoices] = useState<Record<string, boolean>>(() =>\n Object.fromEntries(categories.map((c) => [c.id, Boolean(c.required)])),\n );\n const [showPrefs, setShowPrefs] = useState(false);\n // Geforceerd (her)openen: via het 🍪-knopje of het `xicms:consent:open`-event (footerlink).\n const [reopened, setReopened] = useState(false);\n const bannerRef = useRef<HTMLDivElement | null>(null);\n // Bij expliciet heropenen focus de banner in (de bezoeker vroeg erom); bij eerste bezoek\n // stelen we géén focus — de banner is niet-modaal en mag het lezen niet onderbreken.\n useEffect(() => {\n if (reopened) bannerRef.current?.querySelector<HTMLElement>(\".xicms-consent__btn--primary\")?.focus();\n }, [reopened]);\n // Een oude keuze telt niet meer als de beleidsversie is gewijzigd → banner opnieuw tonen.\n const decided = consentDecided(state, settings?.version);\n const nodig = useConsentNodig();\n // De banner en het 🍪-knopje boven vaste balken onderaan (demobalk, belbalk, eigen CTA-balk).\n useOnderOffset();\n\n const openBanner = () => {\n // Voorkeuren voor-invullen met de huidige keuze zodat wijzigen intuïtief is.\n setChoices((prev) => ({ ...prev, ...state.categories }));\n setShowPrefs(true);\n setReopened(true);\n };\n\n useEffect(() => {\n const onOpen = () => openBanner();\n window.addEventListener(\"xicms:consent:open\", onOpen);\n return () => window.removeEventListener(\"xicms:consent:open\", onOpen);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state.categories]);\n\n // 8.16: niets te vragen op deze pagina → geen banner. De footerlink \"Cookie-instellingen\" werkt wel.\n if (!decided && !reopened && settings?.toon !== \"altijd\" && !nodig) return null;\n\n if (decided && !reopened) {\n // AVG: de bezoeker moet zijn keuze altijd kunnen wijzigen — zwevend knopje (opt-out via settings).\n if (settings?.showReopen === false) return null;\n return (\n <button\n type=\"button\"\n className=\"xicms-consent__reopen\"\n aria-label=\"Cookie-instellingen wijzigen\"\n title=\"Cookie-instellingen\"\n onClick={openBanner}\n >\n 🍪\n </button>\n );\n }\n\n const commit = (categories: Record<string, boolean>) => {\n save(categories, settings?.version);\n setReopened(false);\n };\n const acceptAll = () => commit(Object.fromEntries(categories.map((c) => [c.id, true])));\n const rejectNonEssential = () =>\n commit(Object.fromEntries(categories.map((c) => [c.id, Boolean(c.required)])));\n const saveChoices = () => commit(choices);\n\n return (\n <div ref={bannerRef} className=\"xicms-consent\" role=\"dialog\" aria-modal=\"false\" aria-label=\"Cookievoorkeuren\">\n <div className=\"xicms-consent__inner\" data-prefs={showPrefs ? \"1\" : \"0\"}>\n <div className=\"xicms-consent__head\">\n <p className=\"xicms-consent__title\">{settings?.title ?? \"🍪 Cookievoorkeuren\"}</p>\n <p className=\"xicms-consent__message\">\n {settings?.message ??\n DEFAULT_MESSAGE}\n {settings?.privacyUrl && (\n <>\n {\" \"}\n <a className=\"xicms-consent__link\" href={settings.privacyUrl}>\n Privacyverklaring\n </a>\n </>\n )}\n </p>\n </div>\n\n {showPrefs && (\n <fieldset className=\"xicms-consent__categories\">\n <legend className=\"xicms-sr-only\">Cookiecategorieën</legend>\n {categories.map((c) => {\n const on = choices[c.id] ?? Boolean(c.required);\n return (\n <label key={c.id} className=\"xicms-consent__category\" data-on={on ? \"1\" : \"0\"}>\n <span className=\"xicms-consent__cat-text\">\n <span className=\"xicms-consent__cat-label\">\n {c.label}\n {c.required && <span className=\"xicms-consent__required\"> · altijd aan</span>}\n </span>\n {c.description && <span className=\"xicms-consent__cat-desc\">{c.description}</span>}\n </span>\n <span className=\"xicms-consent__switch\">\n <input\n type=\"checkbox\"\n checked={on}\n disabled={c.required}\n onChange={(e) => setChoices((prev) => ({ ...prev, [c.id]: e.target.checked }))}\n />\n <span className=\"xicms-consent__track\" aria-hidden=\"true\" />\n </span>\n </label>\n );\n })}\n </fieldset>\n )}\n\n <div className=\"xicms-consent__actions\">\n {!showPrefs ? (\n <button type=\"button\" className=\"xicms-consent__btn xicms-consent__btn--ghost\" onClick={() => setShowPrefs(true)}>\n Voorkeuren\n </button>\n ) : (\n <button type=\"button\" className=\"xicms-consent__btn xicms-consent__btn--ghost\" onClick={saveChoices}>\n Mijn keuze opslaan\n </button>\n )}\n <button type=\"button\" className=\"xicms-consent__btn xicms-consent__btn--ghost\" onClick={rejectNonEssential}>\n Alleen noodzakelijk\n </button>\n <button type=\"button\" className=\"xicms-consent__btn xicms-consent__btn--primary\" onClick={acceptAll}>\n Alles accepteren\n </button>\n </div>\n </div>\n </div>\n );\n}\n\n/**\n * Toont children alleen als toestemming voor `category` is gegeven. Gebruik dit om niet-essentiële\n * scripts/embeds (analytics, video, maps) pas na consent te laden.\n */\nexport function ConsentGate({ category, children }: { category: string; children: React.ReactNode }) {\n const { has } = useConsent();\n // 8.16: zolang dit wacht, mag de banner (in \"automatisch\") verschijnen.\n useMeldConsentNodig(category, !has(category));\n return has(category) ? <>{children}</> : null;\n}\n\n/**\n * Tekstlink/knop die de cookievoorkeuren heropent — voor in een footer (\"Cookie-instellingen\").\n * Werkt via het `xicms:consent:open`-event; de ConsentBanner luistert daarnaar.\n */\nexport function ConsentReopenLink({ children, className }: { children?: React.ReactNode; className?: string }) {\n return (\n <button\n type=\"button\"\n className={className ?? \"xicms-consent__reopen-link\"}\n onClick={() => window.dispatchEvent(new Event(\"xicms:consent:open\"))}\n >\n {children ?? \"Cookie-instellingen\"}\n </button>\n );\n}\n"],"mappings":"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","names":["categories"]}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * 8.16: alleen wat er echt is. De bezoekersteller van XiCMS is cookieloos en hoeft geen toestemming
3
+ * (er stond een schakelaar "Statistieken" die nergens iets deed); "marketing" is de categorie
4
+ * waaronder video's, kaarten en boekingswidgets al jaren wachten — de id blijft, het label klopt nu.
5
+ */
6
+ export declare const DEFAULT_CATEGORIES: {
7
+ id: string;
8
+ label: string;
9
+ description?: string;
10
+ required?: boolean;
11
+ }[];
12
+ export declare const DEFAULT_MESSAGE = "Deze site gebruikt zelf geen tracking-cookies. Inhoud van andere partijen, zoals video's en kaarten, laden we pas als je dat toestaat.";
@@ -0,0 +1,10 @@
1
+ const DEFAULT_CATEGORIES = [
2
+ { id: "necessary", label: "Noodzakelijk", required: true, description: "Nodig om de site te laten werken, zoals je winkelwagen en deze keuze. Geen tracking." },
3
+ { id: "marketing", label: "Inhoud van andere partijen", description: "Video's, kaarten en boekingsmodules (zoals YouTube en Google Maps). Die partijen kunnen cookies plaatsen." }
4
+ ];
5
+ const DEFAULT_MESSAGE = "Deze site gebruikt zelf geen tracking-cookies. Inhoud van andere partijen, zoals video's en kaarten, laden we pas als je dat toestaat.";
6
+ export {
7
+ DEFAULT_CATEGORIES,
8
+ DEFAULT_MESSAGE
9
+ };
10
+ //# sourceMappingURL=standaard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/modules/consent/standaard.ts"],"sourcesContent":["// Gedeeld door de banner (client) en het module-schema (server): daarom geen \"use client\" hier.\n\n/**\n * 8.16: alleen wat er echt is. De bezoekersteller van XiCMS is cookieloos en hoeft geen toestemming\n * (er stond een schakelaar \"Statistieken\" die nergens iets deed); \"marketing\" is de categorie\n * waaronder video's, kaarten en boekingswidgets al jaren wachten — de id blijft, het label klopt nu.\n */\nexport const DEFAULT_CATEGORIES: { id: string; label: string; description?: string; required?: boolean }[] = [\n { id: \"necessary\", label: \"Noodzakelijk\", required: true, description: \"Nodig om de site te laten werken, zoals je winkelwagen en deze keuze. Geen tracking.\" },\n { id: \"marketing\", label: \"Inhoud van andere partijen\", description: \"Video's, kaarten en boekingsmodules (zoals YouTube en Google Maps). Die partijen kunnen cookies plaatsen.\" },\n];\n\nexport const DEFAULT_MESSAGE =\n \"Deze site gebruikt zelf geen tracking-cookies. Inhoud van andere partijen, zoals video's en kaarten, laden we pas als je dat toestaat.\";\n"],"mappings":"AAOO,MAAM,qBAAgG;AAAA,EAC3G,EAAE,IAAI,aAAa,OAAO,gBAAgB,UAAU,MAAM,aAAa,uFAAuF;AAAA,EAC9J,EAAE,IAAI,aAAa,OAAO,8BAA8B,aAAa,4GAA4G;AACnL;AAEO,MAAM,kBACX;","names":[]}
@@ -26,3 +26,7 @@ export declare function useConsent(): {
26
26
  has: (category: string) => boolean;
27
27
  save: (categories: Record<string, boolean>, version?: string) => void;
28
28
  };
29
+ /** Meld dat dit onderdeel op toestemming voor `category` wacht (zolang `actief`). */
30
+ export declare function useMeldConsentNodig(category: string, actief: boolean): void;
31
+ /** Wacht er op deze pagina iets op toestemming? */
32
+ export declare function useConsentNodig(): boolean;
@@ -56,9 +56,38 @@ function useConsent() {
56
56
  );
57
57
  return { state, decided, has, save };
58
58
  }
59
+ const nodig = /* @__PURE__ */ new Map();
60
+ function meldNodig(category) {
61
+ nodig.set(category, (nodig.get(category) ?? 0) + 1);
62
+ window.dispatchEvent(new Event("xicms:consent:nodig"));
63
+ return () => {
64
+ const n = (nodig.get(category) ?? 1) - 1;
65
+ if (n <= 0) nodig.delete(category);
66
+ else nodig.set(category, n);
67
+ window.dispatchEvent(new Event("xicms:consent:nodig"));
68
+ };
69
+ }
70
+ function useMeldConsentNodig(category, actief) {
71
+ useEffect(() => {
72
+ if (!actief || typeof window === "undefined") return;
73
+ return meldNodig(category);
74
+ }, [category, actief]);
75
+ }
76
+ function useConsentNodig() {
77
+ const [ja, setJa] = useState(false);
78
+ useEffect(() => {
79
+ const lees = () => setJa(nodig.size > 0);
80
+ lees();
81
+ window.addEventListener("xicms:consent:nodig", lees);
82
+ return () => window.removeEventListener("xicms:consent:nodig", lees);
83
+ }, []);
84
+ return ja;
85
+ }
59
86
  export {
60
87
  consentDecided,
61
88
  normalizeConsentState,
62
- useConsent
89
+ useConsent,
90
+ useConsentNodig,
91
+ useMeldConsentNodig
63
92
  };
64
93
  //# sourceMappingURL=useConsent.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/modules/consent/useConsent.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useModuleSettings } from \"../context\";\n\nconst STORAGE_KEY = \"xicms-consent\";\n\nexport interface ConsentState {\n /** Per categorie-id of de bezoeker toestemming gaf. */\n categories: Record<string, boolean>;\n /** Tijdstip (ms) waarop de keuze is gemaakt; null = nog niet gekozen. */\n decidedAt: number | null;\n /** Versie van het cookiebeleid waarvoor de keuze gold — wijzigt de site zijn beleid\n * (nieuwe `version` in de instellingen), dan telt een oude keuze niet meer. */\n version?: string;\n}\n\nconst EMPTY: ConsentState = { categories: {}, decidedAt: null };\n\n/** Normaliseer willekeurige opgeslagen JSON naar een geldige ConsentState (defensief tegen\n * corrupte/oude vormen — `has()` mag nooit crashen op een afwijkende localStorage-waarde). */\nexport function normalizeConsentState(value: unknown): ConsentState {\n if (!value || typeof value !== \"object\") return EMPTY;\n const v = value as Record<string, unknown>;\n const categories =\n v.categories && typeof v.categories === \"object\" ? (v.categories as Record<string, boolean>) : {};\n const decidedAt = typeof v.decidedAt === \"number\" ? v.decidedAt : null;\n const version = typeof v.version === \"string\" ? v.version : undefined;\n return version === undefined ? { categories, decidedAt } : { categories, decidedAt, version };\n}\n\n/**\n * Geldt de opgeslagen keuze nog? Alleen als er beslist is én de keuze bij de huidige\n * beleidsversie hoort (geen `requiredVersion` = elke keuze telt — het pre-versie-gedrag).\n */\nexport function consentDecided(state: ConsentState, requiredVersion?: string): boolean {\n if (state.decidedAt === null) return false;\n if (!requiredVersion) return true;\n return state.version === requiredVersion;\n}\n\n// Vangnet als localStorage weigert (privémodus/vol): de keuze geldt dan alleen voor deze\n// paginasessie, maar wél consistent voor álle componenten (read() geeft hetzelfde terug).\nlet memoryFallback: ConsentState | null = null;\n\nfunction read(): ConsentState {\n if (typeof window === \"undefined\") return EMPTY;\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (raw) return normalizeConsentState(JSON.parse(raw));\n } catch {\n /* corrupt/onbeschikbaar: behandel als nog-niet-gekozen */\n }\n return memoryFallback ?? EMPTY;\n}\n\n/**\n * Leest/zet cookie-consent (client-side, geen backend). Andere code gebruikt `has(\"analytics\")`\n * om niet-essentiële scripts pas te laden na toestemming. De `xicms:consent`-event laat losse\n * luisteraars reageren zonder re-render.\n */\nexport function useConsent() {\n const [state, setState] = useState<ConsentState>({ categories: {}, decidedAt: null });\n // Beleidsversie + categorie-configuratie van de site: een keuze van een oude versie telt niet\n // meer (AVG), en dat moet ook voor `has()` gelden — niet alleen voor het hertonen van de banner.\n const settings = useModuleSettings<{ version?: string; categories?: Array<{ id: string }> }>(\"consent\");\n\n useEffect(() => {\n setState(read());\n const onChange = () => setState(read());\n window.addEventListener(\"xicms:consent\", onChange);\n return () => window.removeEventListener(\"xicms:consent\", onChange);\n }, []);\n\n const save = useCallback((categories: Record<string, boolean>, version?: string) => {\n const next: ConsentState = { categories, decidedAt: Date.now(), ...(version ? { version } : {}) };\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next));\n } catch {\n memoryFallback = next; // opslag geweigerd: keuze geldt alleen voor deze paginasessie\n }\n setState(next);\n window.dispatchEvent(new Event(\"xicms:consent\"));\n }, []);\n\n const decided = consentDecided(state, settings.version);\n const has = useCallback(\n (category: string) => {\n if (!decided) return false;\n if (state.categories[category] === true) return true;\n // Een categorie die niet in de banner voorkomt kan een bezoeker nooit aanvinken; na een\n // geldige keuze vallen we dan open i.p.v. de inhoud eeuwig achter een onbereikbare gate\n // te zetten (maatwerk-categorieën vs. de standaard-gates van video/kaart/embed).\n return settings.categories !== undefined && !settings.categories.some((c) => c.id === category);\n },\n [decided, state, settings.categories],\n );\n\n return { state, decided, has, save };\n}\n"],"mappings":";AAEA,SAAS,aAAa,WAAW,gBAAgB;AACjD,SAAS,yBAAyB;AAElC,MAAM,cAAc;AAYpB,MAAM,QAAsB,EAAE,YAAY,CAAC,GAAG,WAAW,KAAK;AAIvD,SAAS,sBAAsB,OAA8B;AAClE,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAM,IAAI;AACV,QAAM,aACJ,EAAE,cAAc,OAAO,EAAE,eAAe,WAAY,EAAE,aAAyC,CAAC;AAClG,QAAM,YAAY,OAAO,EAAE,cAAc,WAAW,EAAE,YAAY;AAClE,QAAM,UAAU,OAAO,EAAE,YAAY,WAAW,EAAE,UAAU;AAC5D,SAAO,YAAY,SAAY,EAAE,YAAY,UAAU,IAAI,EAAE,YAAY,WAAW,QAAQ;AAC9F;AAMO,SAAS,eAAe,OAAqB,iBAAmC;AACrF,MAAI,MAAM,cAAc,KAAM,QAAO;AACrC,MAAI,CAAC,gBAAiB,QAAO;AAC7B,SAAO,MAAM,YAAY;AAC3B;AAIA,IAAI,iBAAsC;AAE1C,SAAS,OAAqB;AAC5B,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,MAAI;AACF,UAAM,MAAM,OAAO,aAAa,QAAQ,WAAW;AACnD,QAAI,IAAK,QAAO,sBAAsB,KAAK,MAAM,GAAG,CAAC;AAAA,EACvD,QAAQ;AAAA,EAER;AACA,SAAO,kBAAkB;AAC3B;AAOO,SAAS,aAAa;AAC3B,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAuB,EAAE,YAAY,CAAC,GAAG,WAAW,KAAK,CAAC;AAGpF,QAAM,WAAW,kBAA4E,SAAS;AAEtG,YAAU,MAAM;AACd,aAAS,KAAK,CAAC;AACf,UAAM,WAAW,MAAM,SAAS,KAAK,CAAC;AACtC,WAAO,iBAAiB,iBAAiB,QAAQ;AACjD,WAAO,MAAM,OAAO,oBAAoB,iBAAiB,QAAQ;AAAA,EACnE,GAAG,CAAC,CAAC;AAEL,QAAM,OAAO,YAAY,CAAC,YAAqC,YAAqB;AAClF,UAAM,OAAqB,EAAE,YAAY,WAAW,KAAK,IAAI,GAAG,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC,EAAG;AAChG,QAAI;AACF,aAAO,aAAa,QAAQ,aAAa,KAAK,UAAU,IAAI,CAAC;AAAA,IAC/D,QAAQ;AACN,uBAAiB;AAAA,IACnB;AACA,aAAS,IAAI;AACb,WAAO,cAAc,IAAI,MAAM,eAAe,CAAC;AAAA,EACjD,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,eAAe,OAAO,SAAS,OAAO;AACtD,QAAM,MAAM;AAAA,IACV,CAAC,aAAqB;AACpB,UAAI,CAAC,QAAS,QAAO;AACrB,UAAI,MAAM,WAAW,QAAQ,MAAM,KAAM,QAAO;AAIhD,aAAO,SAAS,eAAe,UAAa,CAAC,SAAS,WAAW,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AAAA,IAChG;AAAA,IACA,CAAC,SAAS,OAAO,SAAS,UAAU;AAAA,EACtC;AAEA,SAAO,EAAE,OAAO,SAAS,KAAK,KAAK;AACrC;","names":[]}
1
+ {"version":3,"sources":["../../../src/modules/consent/useConsent.ts"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\nimport { useModuleSettings } from \"../context\";\n\nconst STORAGE_KEY = \"xicms-consent\";\n\nexport interface ConsentState {\n /** Per categorie-id of de bezoeker toestemming gaf. */\n categories: Record<string, boolean>;\n /** Tijdstip (ms) waarop de keuze is gemaakt; null = nog niet gekozen. */\n decidedAt: number | null;\n /** Versie van het cookiebeleid waarvoor de keuze gold — wijzigt de site zijn beleid\n * (nieuwe `version` in de instellingen), dan telt een oude keuze niet meer. */\n version?: string;\n}\n\nconst EMPTY: ConsentState = { categories: {}, decidedAt: null };\n\n/** Normaliseer willekeurige opgeslagen JSON naar een geldige ConsentState (defensief tegen\n * corrupte/oude vormen — `has()` mag nooit crashen op een afwijkende localStorage-waarde). */\nexport function normalizeConsentState(value: unknown): ConsentState {\n if (!value || typeof value !== \"object\") return EMPTY;\n const v = value as Record<string, unknown>;\n const categories =\n v.categories && typeof v.categories === \"object\" ? (v.categories as Record<string, boolean>) : {};\n const decidedAt = typeof v.decidedAt === \"number\" ? v.decidedAt : null;\n const version = typeof v.version === \"string\" ? v.version : undefined;\n return version === undefined ? { categories, decidedAt } : { categories, decidedAt, version };\n}\n\n/**\n * Geldt de opgeslagen keuze nog? Alleen als er beslist is én de keuze bij de huidige\n * beleidsversie hoort (geen `requiredVersion` = elke keuze telt — het pre-versie-gedrag).\n */\nexport function consentDecided(state: ConsentState, requiredVersion?: string): boolean {\n if (state.decidedAt === null) return false;\n if (!requiredVersion) return true;\n return state.version === requiredVersion;\n}\n\n// Vangnet als localStorage weigert (privémodus/vol): de keuze geldt dan alleen voor deze\n// paginasessie, maar wél consistent voor álle componenten (read() geeft hetzelfde terug).\nlet memoryFallback: ConsentState | null = null;\n\nfunction read(): ConsentState {\n if (typeof window === \"undefined\") return EMPTY;\n try {\n const raw = window.localStorage.getItem(STORAGE_KEY);\n if (raw) return normalizeConsentState(JSON.parse(raw));\n } catch {\n /* corrupt/onbeschikbaar: behandel als nog-niet-gekozen */\n }\n return memoryFallback ?? EMPTY;\n}\n\n/**\n * Leest/zet cookie-consent (client-side, geen backend). Andere code gebruikt `has(\"analytics\")`\n * om niet-essentiële scripts pas te laden na toestemming. De `xicms:consent`-event laat losse\n * luisteraars reageren zonder re-render.\n */\nexport function useConsent() {\n const [state, setState] = useState<ConsentState>({ categories: {}, decidedAt: null });\n // Beleidsversie + categorie-configuratie van de site: een keuze van een oude versie telt niet\n // meer (AVG), en dat moet ook voor `has()` gelden — niet alleen voor het hertonen van de banner.\n const settings = useModuleSettings<{ version?: string; categories?: Array<{ id: string }> }>(\"consent\");\n\n useEffect(() => {\n setState(read());\n const onChange = () => setState(read());\n window.addEventListener(\"xicms:consent\", onChange);\n return () => window.removeEventListener(\"xicms:consent\", onChange);\n }, []);\n\n const save = useCallback((categories: Record<string, boolean>, version?: string) => {\n const next: ConsentState = { categories, decidedAt: Date.now(), ...(version ? { version } : {}) };\n try {\n window.localStorage.setItem(STORAGE_KEY, JSON.stringify(next));\n } catch {\n memoryFallback = next; // opslag geweigerd: keuze geldt alleen voor deze paginasessie\n }\n setState(next);\n window.dispatchEvent(new Event(\"xicms:consent\"));\n }, []);\n\n const decided = consentDecided(state, settings.version);\n const has = useCallback(\n (category: string) => {\n if (!decided) return false;\n if (state.categories[category] === true) return true;\n // Een categorie die niet in de banner voorkomt kan een bezoeker nooit aanvinken; na een\n // geldige keuze vallen we dan open i.p.v. de inhoud eeuwig achter een onbereikbare gate\n // te zetten (maatwerk-categorieën vs. de standaard-gates van video/kaart/embed).\n return settings.categories !== undefined && !settings.categories.some((c) => c.id === category);\n },\n [decided, state, settings.categories],\n );\n\n return { state, decided, has, save };\n}\n\n/*\n * ── 8.16: welke toestemming is er OP DEZE PAGINA nodig? ───────────────────────────────────\n *\n * XiCMS zelf plaatst geen tracking-cookies: de bezoekersteller is cookieloos (één sessionStorage-\n * vlag per pad, geen persoonsgegevens) en de winkelwagen is functioneel. Daarvoor hoeft niemand\n * toestemming te geven (Telecommunicatiewet 11.7a: functioneel en analytisch zonder privacy-\n * gevolgen). Toestemming is pas nodig voor inhoud van ANDERE partijen: een YouTube-video, een\n * Google-kaart, een boekingswidget. Een banner op elke pagina van elke site was dus vooral ruis.\n *\n * Nu melden zulke onderdelen zich hier aan zolang ze op toestemming wachten (`useMeldConsentNodig`),\n * en toont de banner zich alleen als er iets is aangemeld (instelling `toon: \"automatisch\"`).\n */\nconst nodig = new Map<string, number>();\n\nfunction meldNodig(category: string): () => void {\n nodig.set(category, (nodig.get(category) ?? 0) + 1);\n window.dispatchEvent(new Event(\"xicms:consent:nodig\"));\n return () => {\n const n = (nodig.get(category) ?? 1) - 1;\n if (n <= 0) nodig.delete(category);\n else nodig.set(category, n);\n window.dispatchEvent(new Event(\"xicms:consent:nodig\"));\n };\n}\n\n/** Meld dat dit onderdeel op toestemming voor `category` wacht (zolang `actief`). */\nexport function useMeldConsentNodig(category: string, actief: boolean): void {\n useEffect(() => {\n if (!actief || typeof window === \"undefined\") return;\n return meldNodig(category);\n }, [category, actief]);\n}\n\n/** Wacht er op deze pagina iets op toestemming? */\nexport function useConsentNodig(): boolean {\n const [ja, setJa] = useState(false);\n useEffect(() => {\n const lees = () => setJa(nodig.size > 0);\n lees();\n window.addEventListener(\"xicms:consent:nodig\", lees);\n return () => window.removeEventListener(\"xicms:consent:nodig\", lees);\n }, []);\n return ja;\n}\n"],"mappings":"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","names":[]}
@@ -6,7 +6,8 @@ import { Card, Heading, Text } from "../../../blocks/ui/index.js";
6
6
  import { cartLineKey, cartRemove, cartSetQty, useCart } from "../cartStore.js";
7
7
  import { AantalInvoer } from "./AantalInvoer.js";
8
8
  import { useShopStrings } from "../strings.js";
9
- import { useShopSettings } from "../lib.js";
9
+ import { useShopSettings, productHref } from "../lib.js";
10
+ import { SeedImg } from "../../../media/ImageContext.js";
10
11
  function CartRender({ block, siteId }) {
11
12
  const settings = useShopSettings();
12
13
  const t = useShopStrings();
@@ -29,9 +30,9 @@ function CartRender({ block, siteId }) {
29
30
  /* @__PURE__ */ jsx("a", { href: settings.shopPath, children: t("toShop") })
30
31
  ] }) }) : /* @__PURE__ */ jsxs("div", { style: { display: "grid", gap: "1rem", marginTop: "1rem" }, children: [
31
32
  lines.map((l) => /* @__PURE__ */ jsx(Card, { padding: 3, children: /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "1rem", alignItems: "center", flexWrap: "wrap" }, children: [
32
- l.imageUrl && /* @__PURE__ */ jsx("img", { src: l.imageUrl, alt: "", style: { width: 72, height: 72, objectFit: "cover", borderRadius: 8 } }),
33
+ l.imageUrl && /* @__PURE__ */ jsx(SeedImg, { src: l.imageUrl, alt: "", sizes: "72px", style: { width: 72, height: 72, objectFit: "cover", borderRadius: 8 } }),
33
34
  /* @__PURE__ */ jsxs("div", { style: { flex: "1 1 200px" }, children: [
34
- /* @__PURE__ */ jsx("a", { href: `${settings.detailPath}?p=${encodeURIComponent(l.slug)}`, style: { textDecoration: "none", color: "inherit" }, children: /* @__PURE__ */ jsx(Text, { weight: "bold", display: "block", children: l.name }) }),
35
+ /* @__PURE__ */ jsx("a", { href: productHref(settings.detailPath, l.slug, settings.mooieUrls), style: { textDecoration: "none", color: "inherit" }, children: /* @__PURE__ */ jsx(Text, { weight: "bold", display: "block", children: l.name }) }),
35
36
  l.variantLabel && /* @__PURE__ */ jsx(Text, { size: "sm", display: "block", style: { opacity: 0.75 }, children: l.variantLabel }),
36
37
  l.personalizationLabel && /* @__PURE__ */ jsx(Text, { size: "sm", display: "block", style: { opacity: 0.75 }, children: l.personalizationLabel }),
37
38
  /* @__PURE__ */ jsxs(Text, { size: "sm", display: "block", style: { marginTop: 2 }, children: [
@@ -95,6 +96,7 @@ const cartBlock = defineBlock({
95
96
  Render: CartRender,
96
97
  label: "Winkelwagen",
97
98
  icon: "\u{1F6D2}",
99
+ essentieel: "Zonder dit blok kunnen klanten hun winkelwagen niet zien en niet afrekenen.",
98
100
  defaults: () => ({ heading: "Winkelwagen" })
99
101
  });
100
102
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/modules/shop/blocks/Cart.tsx"],"sourcesContent":["\"use client\";\n\nimport type { z } from \"zod\";\nimport { formatCents, shippingCentsFor } from \"../../../schema/shopGeld\";\nimport type { CartBlockSchema } from \"../../../schema/shop\";\nimport { defineBlock, type BlockRenderProps } from \"../../../blocks/registry\";\nimport { Card, Heading, Text } from \"../../../blocks/ui\";\nimport { cartLineKey, cartRemove, cartSetQty, useCart } from \"../cartStore\";\nimport { AantalInvoer } from \"./AantalInvoer\";\nimport { useShopStrings } from \"../strings\";\nimport { useShopSettings } from \"../lib\";\n\ntype Blk = z.infer<typeof CartBlockSchema>;\n\nfunction CartRender({ block, siteId }: BlockRenderProps<Blk>) {\n const settings = useShopSettings();\n const t = useShopStrings();\n const { lines, itemsCents } = useCart(siteId);\n /**\n * Verzendkosten in de winkelwagen zijn een RICHTBEDRAG voor het standaardland: de klant kiest\n * zijn land (en een eventuele kortingscode) pas bij het afrekenen. Met zones staat dat er nu\n * ook bij, zodat \"€ 7,25\" niet als een belofte leest voor een Belgische bezoeker.\n */\n const shippingCents = shippingCentsFor(\n itemsCents,\n {\n shippingFlatCents: settings.shippingFlatCents,\n shippingFreeFromCents: settings.shippingFreeFromCents || undefined,\n shippingZones: settings.shippingZones,\n },\n lines.length > 0,\n );\n const meerdereZones = (settings.shippingZones ?? []).length > 1;\n\n return (\n <div className=\"xicms-shop-cart\">\n {block.heading && <Heading level={1} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n\n {lines.length === 0 ? (\n <Card padding={4} variant=\"muted\" style={{ marginTop: \"1rem\" }}>\n <Text>\n {t(\"cartEmpty\")} <a href={settings.shopPath}>{t(\"toShop\")}</a>\n </Text>\n </Card>\n ) : (\n <div style={{ display: \"grid\", gap: \"1rem\", marginTop: \"1rem\" }}>\n {lines.map((l) => (\n <Card key={cartLineKey(l)} padding={3}>\n <div style={{ display: \"flex\", gap: \"1rem\", alignItems: \"center\", flexWrap: \"wrap\" }}>\n {l.imageUrl && (\n <img src={l.imageUrl} alt=\"\" style={{ width: 72, height: 72, objectFit: \"cover\", borderRadius: 8 }} />\n )}\n <div style={{ flex: \"1 1 200px\" }}>\n <a href={`${settings.detailPath}?p=${encodeURIComponent(l.slug)}`} style={{ textDecoration: \"none\", color: \"inherit\" }}>\n <Text weight=\"bold\" display=\"block\">{l.name}</Text>\n </a>\n {l.variantLabel && <Text size=\"sm\" display=\"block\" style={{ opacity: 0.75 }}>{l.variantLabel}</Text>}\n {l.personalizationLabel && (\n <Text size=\"sm\" display=\"block\" style={{ opacity: 0.75 }}>{l.personalizationLabel}</Text>\n )}\n <Text size=\"sm\" display=\"block\" style={{ marginTop: 2 }}>\n {formatCents(l.unitPriceCents, settings.currency)} {t(\"perPiece\")}\n </Text>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n {/* min 1: een leeg veld mag nooit de regel uit de wagen gooien — weghalen doe\n je met het kruisje hiernaast. */}\n <AantalInvoer\n value={l.qty}\n onChange={(n) => cartSetQty(siteId, l, n)}\n min={1}\n max={999}\n ariaLabel={`${t(\"qty\")} ${l.name}`}\n style={{ width: 72 }}\n />\n <Text weight=\"bold\" style={{ minWidth: 80, textAlign: \"right\" }}>\n {formatCents(l.unitPriceCents * l.qty, settings.currency)}\n </Text>\n <button\n type=\"button\"\n aria-label={`Verwijder ${l.name}`}\n onClick={() => cartRemove(siteId, l)}\n style={{ background: \"none\", border: \"none\", cursor: \"pointer\", fontSize: \"1.1rem\", opacity: 0.6 }}\n >\n ✕\n </button>\n </div>\n </div>\n </Card>\n ))}\n\n <Card padding={3} variant=\"muted\">\n <div style={{ display: \"grid\", gap: 4, justifyContent: \"end\", textAlign: \"right\" }}>\n <Text size=\"sm\">{t(\"subtotal\")}: {formatCents(itemsCents, settings.currency)}</Text>\n <Text size=\"sm\">\n {t(\"shippingCosts\")}: {shippingCents === 0 ? t(\"free\") : formatCents(shippingCents, settings.currency)}\n {meerdereZones ? ` ${t(\"shippingFromCountry\")}` : \"\"}\n </Text>\n <Text weight=\"bold\">{t(\"total\")}: {formatCents(itemsCents + shippingCents, settings.currency)}</Text>\n </div>\n </Card>\n\n <div style={{ display: \"flex\", gap: 12, flexWrap: \"wrap\" }}>\n <a className=\"xicms-btn xicms-btn--primary\" href={settings.checkoutPath}>{t(\"checkout\")}</a>\n <a className=\"xicms-btn xicms-btn--secondary\" href={settings.shopPath}>{t(\"continueShopping\")}</a>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const cartBlock = defineBlock({\n type: \"cart\",\n Render: CartRender,\n label: \"Winkelwagen\",\n icon: \"🛒\",\n defaults: () => ({ heading: \"Winkelwagen\" }),\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/modules/shop/blocks/Cart.tsx"],"sourcesContent":["\"use client\";\n\nimport type { z } from \"zod\";\nimport { formatCents, shippingCentsFor } from \"../../../schema/shopGeld\";\nimport type { CartBlockSchema } from \"../../../schema/shop\";\nimport { defineBlock, type BlockRenderProps } from \"../../../blocks/registry\";\nimport { Card, Heading, Text } from \"../../../blocks/ui\";\nimport { cartLineKey, cartRemove, cartSetQty, useCart } from \"../cartStore\";\nimport { AantalInvoer } from \"./AantalInvoer\";\nimport { useShopStrings } from \"../strings\";\nimport { useShopSettings, productHref } from \"../lib\";\nimport { SeedImg } from \"../../../media/ImageContext\";\n\ntype Blk = z.infer<typeof CartBlockSchema>;\n\nfunction CartRender({ block, siteId }: BlockRenderProps<Blk>) {\n const settings = useShopSettings();\n const t = useShopStrings();\n const { lines, itemsCents } = useCart(siteId);\n /**\n * Verzendkosten in de winkelwagen zijn een RICHTBEDRAG voor het standaardland: de klant kiest\n * zijn land (en een eventuele kortingscode) pas bij het afrekenen. Met zones staat dat er nu\n * ook bij, zodat \"€ 7,25\" niet als een belofte leest voor een Belgische bezoeker.\n */\n const shippingCents = shippingCentsFor(\n itemsCents,\n {\n shippingFlatCents: settings.shippingFlatCents,\n shippingFreeFromCents: settings.shippingFreeFromCents || undefined,\n shippingZones: settings.shippingZones,\n },\n lines.length > 0,\n );\n const meerdereZones = (settings.shippingZones ?? []).length > 1;\n\n return (\n <div className=\"xicms-shop-cart\">\n {block.heading && <Heading level={1} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n\n {lines.length === 0 ? (\n <Card padding={4} variant=\"muted\" style={{ marginTop: \"1rem\" }}>\n <Text>\n {t(\"cartEmpty\")} <a href={settings.shopPath}>{t(\"toShop\")}</a>\n </Text>\n </Card>\n ) : (\n <div style={{ display: \"grid\", gap: \"1rem\", marginTop: \"1rem\" }}>\n {lines.map((l) => (\n <Card key={cartLineKey(l)} padding={3}>\n <div style={{ display: \"flex\", gap: \"1rem\", alignItems: \"center\", flexWrap: \"wrap\" }}>\n {l.imageUrl && (\n <SeedImg src={l.imageUrl} alt=\"\" sizes=\"72px\" style={{ width: 72, height: 72, objectFit: \"cover\", borderRadius: 8 }} />\n )}\n <div style={{ flex: \"1 1 200px\" }}>\n <a href={productHref(settings.detailPath, l.slug, settings.mooieUrls)} style={{ textDecoration: \"none\", color: \"inherit\" }}>\n <Text weight=\"bold\" display=\"block\">{l.name}</Text>\n </a>\n {l.variantLabel && <Text size=\"sm\" display=\"block\" style={{ opacity: 0.75 }}>{l.variantLabel}</Text>}\n {l.personalizationLabel && (\n <Text size=\"sm\" display=\"block\" style={{ opacity: 0.75 }}>{l.personalizationLabel}</Text>\n )}\n <Text size=\"sm\" display=\"block\" style={{ marginTop: 2 }}>\n {formatCents(l.unitPriceCents, settings.currency)} {t(\"perPiece\")}\n </Text>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n {/* min 1: een leeg veld mag nooit de regel uit de wagen gooien — weghalen doe\n je met het kruisje hiernaast. */}\n <AantalInvoer\n value={l.qty}\n onChange={(n) => cartSetQty(siteId, l, n)}\n min={1}\n max={999}\n ariaLabel={`${t(\"qty\")} ${l.name}`}\n style={{ width: 72 }}\n />\n <Text weight=\"bold\" style={{ minWidth: 80, textAlign: \"right\" }}>\n {formatCents(l.unitPriceCents * l.qty, settings.currency)}\n </Text>\n <button\n type=\"button\"\n aria-label={`Verwijder ${l.name}`}\n onClick={() => cartRemove(siteId, l)}\n style={{ background: \"none\", border: \"none\", cursor: \"pointer\", fontSize: \"1.1rem\", opacity: 0.6 }}\n >\n ✕\n </button>\n </div>\n </div>\n </Card>\n ))}\n\n <Card padding={3} variant=\"muted\">\n <div style={{ display: \"grid\", gap: 4, justifyContent: \"end\", textAlign: \"right\" }}>\n <Text size=\"sm\">{t(\"subtotal\")}: {formatCents(itemsCents, settings.currency)}</Text>\n <Text size=\"sm\">\n {t(\"shippingCosts\")}: {shippingCents === 0 ? t(\"free\") : formatCents(shippingCents, settings.currency)}\n {meerdereZones ? ` ${t(\"shippingFromCountry\")}` : \"\"}\n </Text>\n <Text weight=\"bold\">{t(\"total\")}: {formatCents(itemsCents + shippingCents, settings.currency)}</Text>\n </div>\n </Card>\n\n <div style={{ display: \"flex\", gap: 12, flexWrap: \"wrap\" }}>\n <a className=\"xicms-btn xicms-btn--primary\" href={settings.checkoutPath}>{t(\"checkout\")}</a>\n <a className=\"xicms-btn xicms-btn--secondary\" href={settings.shopPath}>{t(\"continueShopping\")}</a>\n </div>\n </div>\n )}\n </div>\n );\n}\n\nexport const cartBlock = defineBlock({\n type: \"cart\",\n Render: CartRender,\n label: \"Winkelwagen\",\n icon: \"🛒\",\n essentieel: \"Zonder dit blok kunnen klanten hun winkelwagen niet zien en niet afrekenen.\",\n defaults: () => ({ heading: \"Winkelwagen\" }),\n});\n"],"mappings":"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","names":[]}