@xiwebdesign/xicms-core 7.31.0 → 8.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (482) hide show
  1. package/dist/XiCMSProvider.js +23 -7
  2. package/dist/XiCMSProvider.js.map +1 -1
  3. package/dist/admin/AdminApp.js +175 -93
  4. package/dist/admin/AdminApp.js.map +1 -1
  5. package/dist/admin/AdminHelp.d.ts +1 -1
  6. package/dist/admin/AdminHelp.js +44 -36
  7. package/dist/admin/AdminHelp.js.map +1 -1
  8. package/dist/admin/CoreVersion.d.ts +6 -3
  9. package/dist/admin/CoreVersion.js +60 -24
  10. package/dist/admin/CoreVersion.js.map +1 -1
  11. package/dist/admin/NewsEditor.d.ts +7 -0
  12. package/dist/admin/NewsEditor.js +117 -75
  13. package/dist/admin/NewsEditor.js.map +1 -1
  14. package/dist/admin/SuperadminPanel.js +1 -1
  15. package/dist/admin/SuperadminPanel.js.map +1 -1
  16. package/dist/admin/ZoekPalet.d.ts +15 -0
  17. package/dist/admin/ZoekPalet.js +123 -0
  18. package/dist/admin/ZoekPalet.js.map +1 -0
  19. package/dist/admin/blockEditors/GenericEditor.js +36 -18
  20. package/dist/admin/blockEditors/GenericEditor.js.map +1 -1
  21. package/dist/admin/blockEditors/StyleEditor.js +37 -3
  22. package/dist/admin/blockEditors/StyleEditor.js.map +1 -1
  23. package/dist/admin/blockEditors/SymbolRefEditor.js +44 -2
  24. package/dist/admin/blockEditors/SymbolRefEditor.js.map +1 -1
  25. package/dist/admin/blockEditors/index.js +154 -73
  26. package/dist/admin/blockEditors/index.js.map +1 -1
  27. package/dist/admin/customBlocks/CustomBlocksPanel.js +18 -7
  28. package/dist/admin/customBlocks/CustomBlocksPanel.js.map +1 -1
  29. package/dist/admin/dashboard/DashboardPanel.js +26 -16
  30. package/dist/admin/dashboard/DashboardPanel.js.map +1 -1
  31. package/dist/admin/editors/RichTextEditor.d.ts +4 -3
  32. package/dist/admin/editors/RichTextEditor.js +19 -60
  33. package/dist/admin/editors/RichTextEditor.js.map +1 -1
  34. package/dist/admin/editors/fontSizeExtension.js +7 -1
  35. package/dist/admin/editors/fontSizeExtension.js.map +1 -1
  36. package/dist/admin/editors/slashMenu.d.ts +18 -0
  37. package/dist/admin/editors/slashMenu.js +34 -0
  38. package/dist/admin/editors/slashMenu.js.map +1 -0
  39. package/dist/admin/editors/useRijkeTekst.d.ts +48 -0
  40. package/dist/admin/editors/useRijkeTekst.js +310 -0
  41. package/dist/admin/editors/useRijkeTekst.js.map +1 -0
  42. package/dist/admin/forms/FormsPanel.d.ts +11 -2
  43. package/dist/admin/forms/FormsPanel.js +218 -65
  44. package/dist/admin/forms/FormsPanel.js.map +1 -1
  45. package/dist/admin/lib/blokInfo.d.ts +17 -0
  46. package/dist/admin/lib/blokInfo.js +80 -0
  47. package/dist/admin/lib/blokInfo.js.map +1 -0
  48. package/dist/admin/lib/foutNaarMens.d.ts +1 -0
  49. package/dist/admin/lib/foutNaarMens.js +22 -0
  50. package/dist/admin/lib/foutNaarMens.js.map +1 -0
  51. package/dist/admin/lib/gewisteVelden.d.ts +13 -0
  52. package/dist/admin/lib/gewisteVelden.js +31 -0
  53. package/dist/admin/lib/gewisteVelden.js.map +1 -0
  54. package/dist/admin/lib/heroHulp.d.ts +11 -0
  55. package/dist/admin/lib/heroHulp.js +18 -0
  56. package/dist/admin/lib/heroHulp.js.map +1 -0
  57. package/dist/admin/lib/kleur.js +2 -3
  58. package/dist/admin/lib/kleur.js.map +1 -1
  59. package/dist/admin/lib/leesbaarheid.d.ts +34 -0
  60. package/dist/admin/lib/leesbaarheid.js +82 -0
  61. package/dist/admin/lib/leesbaarheid.js.map +1 -0
  62. package/dist/admin/lib/lengteAdvies.d.ts +1 -0
  63. package/dist/admin/lib/lengteAdvies.js +16 -0
  64. package/dist/admin/lib/lengteAdvies.js.map +1 -0
  65. package/dist/admin/lib/mediaLijst.d.ts +26 -0
  66. package/dist/admin/lib/mediaLijst.js +42 -0
  67. package/dist/admin/lib/mediaLijst.js.map +1 -0
  68. package/dist/admin/lib/mediaUsage.d.ts +12 -1
  69. package/dist/admin/lib/mediaUsage.js +43 -33
  70. package/dist/admin/lib/mediaUsage.js.map +1 -1
  71. package/dist/admin/lib/menuHulp.d.ts +16 -0
  72. package/dist/admin/lib/menuHulp.js +41 -0
  73. package/dist/admin/lib/menuHulp.js.map +1 -0
  74. package/dist/admin/lib/onopgeslagen.d.ts +10 -0
  75. package/dist/admin/lib/onopgeslagen.js +35 -0
  76. package/dist/admin/lib/onopgeslagen.js.map +1 -0
  77. package/dist/admin/lib/pagesClient.d.ts +55 -2
  78. package/dist/admin/lib/pagesClient.js +126 -28
  79. package/dist/admin/lib/pagesClient.js.map +1 -1
  80. package/dist/admin/lib/paginaGebruik.d.ts +56 -0
  81. package/dist/admin/lib/paginaGebruik.js +109 -0
  82. package/dist/admin/lib/paginaGebruik.js.map +1 -0
  83. package/dist/admin/lib/publicatieCheck.d.ts +25 -0
  84. package/dist/admin/lib/publicatieCheck.js +114 -0
  85. package/dist/admin/lib/publicatieCheck.js.map +1 -0
  86. package/dist/admin/lib/scrollNaarDetail.d.ts +6 -0
  87. package/dist/admin/lib/scrollNaarDetail.js +20 -0
  88. package/dist/admin/lib/scrollNaarDetail.js.map +1 -0
  89. package/dist/admin/lib/symbolsClient.d.ts +10 -0
  90. package/dist/admin/lib/symbolsClient.js +14 -1
  91. package/dist/admin/lib/symbolsClient.js.map +1 -1
  92. package/dist/admin/lib/tekstVeld.d.ts +8 -0
  93. package/dist/admin/lib/tekstVeld.js +10 -0
  94. package/dist/admin/lib/tekstVeld.js.map +1 -0
  95. package/dist/admin/lib/useIsSuperadmin.d.ts +2 -0
  96. package/dist/admin/lib/useIsSuperadmin.js +13 -0
  97. package/dist/admin/lib/useIsSuperadmin.js.map +1 -0
  98. package/dist/admin/lib/veldTaal.d.ts +14 -0
  99. package/dist/admin/lib/veldTaal.js +248 -0
  100. package/dist/admin/lib/veldTaal.js.map +1 -0
  101. package/dist/admin/lib/versieVergelijk.d.ts +17 -0
  102. package/dist/admin/lib/versieVergelijk.js +24 -0
  103. package/dist/admin/lib/versieVergelijk.js.map +1 -0
  104. package/dist/admin/lib/zodFields.js +22 -4
  105. package/dist/admin/lib/zodFields.js.map +1 -1
  106. package/dist/admin/lib/zodFout.d.ts +9 -0
  107. package/dist/admin/lib/zodFout.js +63 -0
  108. package/dist/admin/lib/zodFout.js.map +1 -0
  109. package/dist/admin/media/MediaManager.js +162 -32
  110. package/dist/admin/media/MediaManager.js.map +1 -1
  111. package/dist/admin/media/MediaPicker.d.ts +3 -0
  112. package/dist/admin/media/MediaPicker.js +84 -31
  113. package/dist/admin/media/MediaPicker.js.map +1 -1
  114. package/dist/admin/menu/MenuPanel.js +144 -83
  115. package/dist/admin/menu/MenuPanel.js.map +1 -1
  116. package/dist/admin/navContext.d.ts +3 -0
  117. package/dist/admin/navContext.js +13 -1
  118. package/dist/admin/navContext.js.map +1 -1
  119. package/dist/admin/pages/PageEditor.js +146 -30
  120. package/dist/admin/pages/PageEditor.js.map +1 -1
  121. package/dist/admin/pages/PagesPanel.js +215 -61
  122. package/dist/admin/pages/PagesPanel.js.map +1 -1
  123. package/dist/admin/pages/StarterKiezer.d.ts +12 -0
  124. package/dist/admin/pages/StarterKiezer.js +113 -0
  125. package/dist/admin/pages/StarterKiezer.js.map +1 -0
  126. package/dist/admin/panelRegistry.d.ts +1 -1
  127. package/dist/admin/panelRegistry.js +2 -1
  128. package/dist/admin/panelRegistry.js.map +1 -1
  129. package/dist/admin/patterns/PatternInserter.js +1 -1
  130. package/dist/admin/patterns/PatternInserter.js.map +1 -1
  131. package/dist/admin/settings/BedrijfInstellingen.d.ts +20 -0
  132. package/dist/admin/settings/BedrijfInstellingen.js +159 -0
  133. package/dist/admin/settings/BedrijfInstellingen.js.map +1 -0
  134. package/dist/admin/settings/MailTemplates.js +5 -4
  135. package/dist/admin/settings/MailTemplates.js.map +1 -1
  136. package/dist/admin/settings/SettingsPanel.js +120 -78
  137. package/dist/admin/settings/SettingsPanel.js.map +1 -1
  138. package/dist/admin/settings/SnapshotsCard.js +4 -4
  139. package/dist/admin/settings/SnapshotsCard.js.map +1 -1
  140. package/dist/admin/settings/VorigeTerugzetten.d.ts +15 -0
  141. package/dist/admin/settings/VorigeTerugzetten.js +89 -0
  142. package/dist/admin/settings/VorigeTerugzetten.js.map +1 -0
  143. package/dist/admin/shop/CategoriesTab.js +6 -4
  144. package/dist/admin/shop/CategoriesTab.js.map +1 -1
  145. package/dist/admin/shop/DiscountsTab.js +4 -2
  146. package/dist/admin/shop/DiscountsTab.js.map +1 -1
  147. package/dist/admin/shop/OrdersTab.js +57 -19
  148. package/dist/admin/shop/OrdersTab.js.map +1 -1
  149. package/dist/admin/shop/ProductPaneel.js +2 -1
  150. package/dist/admin/shop/ProductPaneel.js.map +1 -1
  151. package/dist/admin/shop/ProductsTab.js +40 -19
  152. package/dist/admin/shop/ProductsTab.js.map +1 -1
  153. package/dist/admin/shop/ShopPanel.js +13 -1
  154. package/dist/admin/shop/ShopPanel.js.map +1 -1
  155. package/dist/admin/shop/ShopSettingsTab.js +56 -17
  156. package/dist/admin/shop/ShopSettingsTab.js.map +1 -1
  157. package/dist/admin/shop/productClient.js +7 -3
  158. package/dist/admin/shop/productClient.js.map +1 -1
  159. package/dist/admin/stats/NietGevonden.d.ts +10 -0
  160. package/dist/admin/stats/NietGevonden.js +78 -0
  161. package/dist/admin/stats/NietGevonden.js.map +1 -0
  162. package/dist/admin/stats/StatsPanel.js +6 -1
  163. package/dist/admin/stats/StatsPanel.js.map +1 -1
  164. package/dist/admin/stats/lib.d.ts +2 -0
  165. package/dist/admin/stats/lib.js.map +1 -1
  166. package/dist/admin/ui/ConfirmDialog.js +10 -1
  167. package/dist/admin/ui/ConfirmDialog.js.map +1 -1
  168. package/dist/admin/ui/Icon.d.ts +34 -0
  169. package/dist/admin/ui/Icon.js +44 -0
  170. package/dist/admin/ui/Icon.js.map +1 -0
  171. package/dist/admin/ui/ImageField.d.ts +15 -0
  172. package/dist/admin/ui/ImageField.js +67 -0
  173. package/dist/admin/ui/ImageField.js.map +1 -0
  174. package/dist/admin/ui/KleurVeld.d.ts +25 -0
  175. package/dist/admin/ui/KleurVeld.js +76 -0
  176. package/dist/admin/ui/KleurVeld.js.map +1 -0
  177. package/dist/admin/ui/LaadStaat.d.ts +21 -0
  178. package/dist/admin/ui/LaadStaat.js +43 -0
  179. package/dist/admin/ui/LaadStaat.js.map +1 -0
  180. package/dist/admin/ui/LeesbaarheidPaneel.d.ts +10 -0
  181. package/dist/admin/ui/LeesbaarheidPaneel.js +68 -0
  182. package/dist/admin/ui/LeesbaarheidPaneel.js.map +1 -0
  183. package/dist/admin/ui/LinkDialog.d.ts +22 -0
  184. package/dist/admin/ui/LinkDialog.js +131 -0
  185. package/dist/admin/ui/LinkDialog.js.map +1 -0
  186. package/dist/admin/ui/LinkVeld.d.ts +14 -0
  187. package/dist/admin/ui/LinkVeld.js +49 -0
  188. package/dist/admin/ui/LinkVeld.js.map +1 -0
  189. package/dist/admin/ui/PreviewLinkResultaat.d.ts +14 -0
  190. package/dist/admin/ui/PreviewLinkResultaat.js +52 -0
  191. package/dist/admin/ui/PreviewLinkResultaat.js.map +1 -0
  192. package/dist/admin/ui/charts.js +5 -5
  193. package/dist/admin/ui/charts.js.map +1 -1
  194. package/dist/admin/ui/primitives.d.ts +16 -6
  195. package/dist/admin/ui/primitives.js +98 -26
  196. package/dist/admin/ui/primitives.js.map +1 -1
  197. package/dist/admin/ui/select.js +5 -2
  198. package/dist/admin/ui/select.js.map +1 -1
  199. package/dist/admin/ui/switch.d.ts +3 -1
  200. package/dist/admin/ui/switch.js +6 -3
  201. package/dist/admin/ui/switch.js.map +1 -1
  202. package/dist/admin/ui/toast.d.ts +2 -1
  203. package/dist/admin/ui/toast.js +17 -11
  204. package/dist/admin/ui/toast.js.map +1 -1
  205. package/dist/admin/visual/BlokKiezer.d.ts +34 -0
  206. package/dist/admin/visual/BlokKiezer.js +225 -0
  207. package/dist/admin/visual/BlokKiezer.js.map +1 -0
  208. package/dist/admin/visual/InlineGereedschap.d.ts +52 -0
  209. package/dist/admin/visual/InlineGereedschap.js +356 -0
  210. package/dist/admin/visual/InlineGereedschap.js.map +1 -0
  211. package/dist/admin/visual/InlineRijkeTekst.d.ts +23 -0
  212. package/dist/admin/visual/InlineRijkeTekst.js +152 -0
  213. package/dist/admin/visual/InlineRijkeTekst.js.map +1 -0
  214. package/dist/admin/visual/VisualEditor.js +273 -125
  215. package/dist/admin/visual/VisualEditor.js.map +1 -1
  216. package/dist/admin.css +1 -1
  217. package/dist/auth/AuthProvider.js +1 -0
  218. package/dist/auth/AuthProvider.js.map +1 -1
  219. package/dist/bedrijf/bedrijf.d.ts +44 -0
  220. package/dist/bedrijf/bedrijf.js +125 -0
  221. package/dist/bedrijf/bedrijf.js.map +1 -0
  222. package/dist/blocks/BlockRenderer.js +11 -1
  223. package/dist/blocks/BlockRenderer.js.map +1 -1
  224. package/dist/blocks/blockStyle.d.ts +7 -0
  225. package/dist/blocks/blockStyle.js +16 -3
  226. package/dist/blocks/blockStyle.js.map +1 -1
  227. package/dist/blocks/builtinSchemas.js +6 -0
  228. package/dist/blocks/builtinSchemas.js.map +1 -1
  229. package/dist/blocks/builtins/AgendaRender.d.ts +22 -0
  230. package/dist/blocks/builtins/AgendaRender.js +69 -9
  231. package/dist/blocks/builtins/AgendaRender.js.map +1 -1
  232. package/dist/blocks/builtins/Availability.d.ts +1 -0
  233. package/dist/blocks/builtins/Availability.js +23 -0
  234. package/dist/blocks/builtins/Availability.js.map +1 -0
  235. package/dist/blocks/builtins/AvailabilityRender.d.ts +12 -0
  236. package/dist/blocks/builtins/AvailabilityRender.js +105 -0
  237. package/dist/blocks/builtins/AvailabilityRender.js.map +1 -0
  238. package/dist/blocks/builtins/BeforeAfterRender.js +4 -3
  239. package/dist/blocks/builtins/BeforeAfterRender.js.map +1 -1
  240. package/dist/blocks/builtins/Booking.js +1 -1
  241. package/dist/blocks/builtins/Booking.js.map +1 -1
  242. package/dist/blocks/builtins/BreadcrumbsRender.d.ts +4 -3
  243. package/dist/blocks/builtins/BreadcrumbsRender.js +14 -8
  244. package/dist/blocks/builtins/BreadcrumbsRender.js.map +1 -1
  245. package/dist/blocks/builtins/ColumnsRender.d.ts +1 -1
  246. package/dist/blocks/builtins/ColumnsRender.js +3 -1
  247. package/dist/blocks/builtins/ColumnsRender.js.map +1 -1
  248. package/dist/blocks/builtins/Contact.js +1 -1
  249. package/dist/blocks/builtins/Contact.js.map +1 -1
  250. package/dist/blocks/builtins/ContactRender.d.ts +1 -1
  251. package/dist/blocks/builtins/ContactRender.js +37 -8
  252. package/dist/blocks/builtins/ContactRender.js.map +1 -1
  253. package/dist/blocks/builtins/Cta.js +1 -1
  254. package/dist/blocks/builtins/Cta.js.map +1 -1
  255. package/dist/blocks/builtins/CtaRender.d.ts +1 -1
  256. package/dist/blocks/builtins/CtaRender.js +5 -4
  257. package/dist/blocks/builtins/CtaRender.js.map +1 -1
  258. package/dist/blocks/builtins/Embed.js +1 -1
  259. package/dist/blocks/builtins/Embed.js.map +1 -1
  260. package/dist/blocks/builtins/FormBlock.js +1 -0
  261. package/dist/blocks/builtins/FormBlock.js.map +1 -1
  262. package/dist/blocks/builtins/FormBlockRender.d.ts +6 -0
  263. package/dist/blocks/builtins/FormBlockRender.js +88 -16
  264. package/dist/blocks/builtins/FormBlockRender.js.map +1 -1
  265. package/dist/blocks/builtins/GalleryRender.js +3 -2
  266. package/dist/blocks/builtins/GalleryRender.js.map +1 -1
  267. package/dist/blocks/builtins/Hero.js +1 -1
  268. package/dist/blocks/builtins/Hero.js.map +1 -1
  269. package/dist/blocks/builtins/HeroRender.js +7 -3
  270. package/dist/blocks/builtins/HeroRender.js.map +1 -1
  271. package/dist/blocks/builtins/OpenNowBadge.d.ts +4 -2
  272. package/dist/blocks/builtins/OpenNowBadge.js +6 -6
  273. package/dist/blocks/builtins/OpenNowBadge.js.map +1 -1
  274. package/dist/blocks/builtins/OpeningHoursRender.d.ts +8 -2
  275. package/dist/blocks/builtins/OpeningHoursRender.js +27 -6
  276. package/dist/blocks/builtins/OpeningHoursRender.js.map +1 -1
  277. package/dist/blocks/builtins/PriceList.d.ts +1 -0
  278. package/dist/blocks/builtins/PriceList.js +25 -0
  279. package/dist/blocks/builtins/PriceList.js.map +1 -0
  280. package/dist/blocks/builtins/PriceListRender.d.ts +17 -0
  281. package/dist/blocks/builtins/PriceListRender.js +87 -0
  282. package/dist/blocks/builtins/PriceListRender.js.map +1 -0
  283. package/dist/blocks/builtins/RichTextBlockRender.js +6 -1
  284. package/dist/blocks/builtins/RichTextBlockRender.js.map +1 -1
  285. package/dist/blocks/builtins/SectionHeading.d.ts +1 -0
  286. package/dist/blocks/builtins/SectionHeading.js +14 -0
  287. package/dist/blocks/builtins/SectionHeading.js.map +1 -0
  288. package/dist/blocks/builtins/SectionHeadingRender.d.ts +7 -0
  289. package/dist/blocks/builtins/SectionHeadingRender.js +14 -0
  290. package/dist/blocks/builtins/SectionHeadingRender.js.map +1 -0
  291. package/dist/blocks/builtins/SliderRender.js +3 -2
  292. package/dist/blocks/builtins/SliderRender.js.map +1 -1
  293. package/dist/blocks/builtins/SymbolRef.js +1 -1
  294. package/dist/blocks/builtins/SymbolRef.js.map +1 -1
  295. package/dist/blocks/builtins/TeamRender.js +6 -1
  296. package/dist/blocks/builtins/TeamRender.js.map +1 -1
  297. package/dist/blocks/builtins/Testimonials.js +3 -1
  298. package/dist/blocks/builtins/Testimonials.js.map +1 -1
  299. package/dist/blocks/builtins/TestimonialsRender.js +4 -0
  300. package/dist/blocks/builtins/TestimonialsRender.js.map +1 -1
  301. package/dist/blocks/builtins/WhatsappChatRender.d.ts +1 -1
  302. package/dist/blocks/builtins/WhatsappChatRender.js +3 -1
  303. package/dist/blocks/builtins/WhatsappChatRender.js.map +1 -1
  304. package/dist/blocks/builtins/Widgets.js +2 -2
  305. package/dist/blocks/builtins/Widgets.js.map +1 -1
  306. package/dist/blocks/builtins/WidgetsRender.js +3 -1
  307. package/dist/blocks/builtins/WidgetsRender.js.map +1 -1
  308. package/dist/blocks/builtins/consentEmbed.js +26 -9
  309. package/dist/blocks/builtins/consentEmbed.js.map +1 -1
  310. package/dist/blocks/builtins/index.d.ts +3 -0
  311. package/dist/blocks/builtins/index.js +6 -0
  312. package/dist/blocks/builtins/index.js.map +1 -1
  313. package/dist/blocks/builtins/lib/autoComplete.d.ts +7 -0
  314. package/dist/blocks/builtins/lib/autoComplete.js +20 -0
  315. package/dist/blocks/builtins/lib/autoComplete.js.map +1 -0
  316. package/dist/blocks/builtins/lib/bookingUrl.d.ts +2 -2
  317. package/dist/blocks/builtins/lib/bookingUrl.js +1 -1
  318. package/dist/blocks/builtins/lib/bookingUrl.js.map +1 -1
  319. package/dist/blocks/builtins/lib/ical.d.ts +24 -0
  320. package/dist/blocks/builtins/lib/ical.js +82 -0
  321. package/dist/blocks/builtins/lib/ical.js.map +1 -0
  322. package/dist/blocks/builtins/lib/vandaag.d.ts +8 -0
  323. package/dist/blocks/builtins/lib/vandaag.js +22 -0
  324. package/dist/blocks/builtins/lib/vandaag.js.map +1 -0
  325. package/dist/blocks/registry.d.ts +6 -0
  326. package/dist/blocks/registry.js.map +1 -1
  327. package/dist/blocks/ui/index.js +1 -0
  328. package/dist/blocks/ui/index.js.map +1 -1
  329. package/dist/components/EditBar.js +2 -4
  330. package/dist/components/EditBar.js.map +1 -1
  331. package/dist/components/News.js +26 -18
  332. package/dist/components/News.js.map +1 -1
  333. package/dist/components/PageView.d.ts +7 -1
  334. package/dist/components/PageView.js +17 -0
  335. package/dist/components/PageView.js.map +1 -1
  336. package/dist/components/ResponsiveImage.js +18 -20
  337. package/dist/components/ResponsiveImage.js.map +1 -1
  338. package/dist/components/onderOffset.d.ts +13 -0
  339. package/dist/components/onderOffset.js +74 -0
  340. package/dist/components/onderOffset.js.map +1 -0
  341. package/dist/components/site/Bedrijfsnummers.d.ts +9 -0
  342. package/dist/components/site/Bedrijfsnummers.js +12 -0
  343. package/dist/components/site/Bedrijfsnummers.js.map +1 -0
  344. package/dist/components/site/SiteFooter.d.ts +6 -1
  345. package/dist/components/site/SiteFooter.js +62 -9
  346. package/dist/components/site/SiteFooter.js.map +1 -1
  347. package/dist/components/site/SiteHeader.d.ts +15 -0
  348. package/dist/components/site/SiteHeader.js +70 -0
  349. package/dist/components/site/SiteHeader.js.map +1 -0
  350. package/dist/components/site/SiteNav.d.ts +2 -0
  351. package/dist/components/site/SiteNav.js +29 -5
  352. package/dist/components/site/SiteNav.js.map +1 -1
  353. package/dist/demo/DemoStudio.js +2 -2
  354. package/dist/demo/DemoStudio.js.map +1 -1
  355. package/dist/demo/demoStore.d.ts +13 -0
  356. package/dist/demo/demoStore.js +36 -0
  357. package/dist/demo/demoStore.js.map +1 -1
  358. package/dist/editor/EditorProvider.js +15 -4
  359. package/dist/editor/EditorProvider.js.map +1 -1
  360. package/dist/firebase/functionsClient.js +5 -1
  361. package/dist/firebase/functionsClient.js.map +1 -1
  362. package/dist/index.d.ts +5 -1
  363. package/dist/index.js +20 -1
  364. package/dist/index.js.map +1 -1
  365. package/dist/media/ImageContext.d.ts +17 -0
  366. package/dist/media/ImageContext.js +65 -20
  367. package/dist/media/ImageContext.js.map +1 -1
  368. package/dist/media/altInHtml.d.ts +9 -0
  369. package/dist/media/altInHtml.js +17 -0
  370. package/dist/media/altInHtml.js.map +1 -0
  371. package/dist/media/srcset.d.ts +12 -0
  372. package/dist/media/srcset.js +13 -0
  373. package/dist/media/srcset.js.map +1 -0
  374. package/dist/modules/builtins.d.ts +1 -0
  375. package/dist/modules/builtins.js +22 -9
  376. package/dist/modules/builtins.js.map +1 -1
  377. package/dist/modules/consent/ConsentBanner.d.ts +5 -0
  378. package/dist/modules/consent/ConsentBanner.js +8 -7
  379. package/dist/modules/consent/ConsentBanner.js.map +1 -1
  380. package/dist/modules/consent/standaard.d.ts +12 -0
  381. package/dist/modules/consent/standaard.js +10 -0
  382. package/dist/modules/consent/standaard.js.map +1 -0
  383. package/dist/modules/consent/useConsent.d.ts +4 -0
  384. package/dist/modules/consent/useConsent.js +30 -1
  385. package/dist/modules/consent/useConsent.js.map +1 -1
  386. package/dist/modules/shop/blocks/Cart.js +5 -3
  387. package/dist/modules/shop/blocks/Cart.js.map +1 -1
  388. package/dist/modules/shop/blocks/Checkout.js +56 -35
  389. package/dist/modules/shop/blocks/Checkout.js.map +1 -1
  390. package/dist/modules/shop/blocks/Donation.js +4 -4
  391. package/dist/modules/shop/blocks/Donation.js.map +1 -1
  392. package/dist/modules/shop/blocks/ProductDetail.js +19 -3
  393. package/dist/modules/shop/blocks/ProductDetail.js.map +1 -1
  394. package/dist/modules/shop/blocks/ProductGrid.d.ts +3 -1
  395. package/dist/modules/shop/blocks/ProductGrid.js +8 -4
  396. package/dist/modules/shop/blocks/ProductGrid.js.map +1 -1
  397. package/dist/modules/shop/blocks/ShopCategories.js +4 -3
  398. package/dist/modules/shop/blocks/ShopCategories.js.map +1 -1
  399. package/dist/modules/shop/lib.d.ts +4 -0
  400. package/dist/modules/shop/lib.js +14 -0
  401. package/dist/modules/shop/lib.js.map +1 -1
  402. package/dist/modules/shop/settings.d.ts +3 -0
  403. package/dist/modules/shop/settings.js +14 -0
  404. package/dist/modules/shop/settings.js.map +1 -1
  405. package/dist/modules/shop/strings.d.ts +4 -0
  406. package/dist/modules/shop/strings.js +8 -0
  407. package/dist/modules/shop/strings.js.map +1 -1
  408. package/dist/next/envCheck.d.ts +42 -0
  409. package/dist/next/envCheck.js +106 -0
  410. package/dist/next/envCheck.js.map +1 -0
  411. package/dist/next/index.cjs +185 -2
  412. package/dist/next/index.d.ts +2 -0
  413. package/dist/next/index.js +8 -1
  414. package/dist/next/index.js.map +1 -1
  415. package/dist/next/securityHeaders.d.ts +36 -0
  416. package/dist/next/securityHeaders.js +74 -0
  417. package/dist/next/securityHeaders.js.map +1 -0
  418. package/dist/patterns/builtins.d.ts +7 -0
  419. package/dist/patterns/builtins.js +138 -3
  420. package/dist/patterns/builtins.js.map +1 -1
  421. package/dist/releaseNotes.js +148 -0
  422. package/dist/releaseNotes.js.map +1 -1
  423. package/dist/render/PublishedPage.d.ts +2 -1
  424. package/dist/render/PublishedPage.js +10 -4
  425. package/dist/render/PublishedPage.js.map +1 -1
  426. package/dist/schema/blocks.d.ts +473 -0
  427. package/dist/schema/blocks.js +105 -5
  428. package/dist/schema/blocks.js.map +1 -1
  429. package/dist/schema/business.d.ts +118 -0
  430. package/dist/schema/business.js +75 -0
  431. package/dist/schema/business.js.map +1 -0
  432. package/dist/schema/fields.d.ts +2 -1
  433. package/dist/schema/fields.js.map +1 -1
  434. package/dist/schema/forms.d.ts +18 -0
  435. package/dist/schema/forms.js +18 -3
  436. package/dist/schema/forms.js.map +1 -1
  437. package/dist/schema/mail.d.ts +10 -0
  438. package/dist/schema/mail.js +7 -0
  439. package/dist/schema/mail.js.map +1 -1
  440. package/dist/schema/settings.d.ts +103 -0
  441. package/dist/schema/settings.js +24 -3
  442. package/dist/schema/settings.js.map +1 -1
  443. package/dist/schema/shop.d.ts +2 -0
  444. package/dist/schema/shop.js +4 -0
  445. package/dist/schema/shop.js.map +1 -1
  446. package/dist/schema/shopGeld.d.ts +1 -0
  447. package/dist/schema/shopGeld.js +1 -0
  448. package/dist/schema/shopGeld.js.map +1 -1
  449. package/dist/schema/siteConfig.d.ts +69 -1
  450. package/dist/schema/siteConfig.js +7 -2
  451. package/dist/schema/siteConfig.js.map +1 -1
  452. package/dist/server/blockData.d.ts +1 -1
  453. package/dist/server/blockData.js +74 -18
  454. package/dist/server/blockData.js.map +1 -1
  455. package/dist/server/cspRapport.d.ts +20 -0
  456. package/dist/server/cspRapport.js +56 -0
  457. package/dist/server/cspRapport.js.map +1 -0
  458. package/dist/server/fonts.d.ts +3 -0
  459. package/dist/server/fonts.js +39 -0
  460. package/dist/server/fonts.js.map +1 -0
  461. package/dist/server/index.d.ts +3 -0
  462. package/dist/server/index.js +8 -0
  463. package/dist/server/index.js.map +1 -1
  464. package/dist/server/sanitize.js +2 -0
  465. package/dist/server/sanitize.js.map +1 -1
  466. package/dist/settings/useSiteSettings.js +4 -1
  467. package/dist/settings/useSiteSettings.js.map +1 -1
  468. package/dist/starters/starters.d.ts +69 -0
  469. package/dist/starters/starters.js +171 -0
  470. package/dist/starters/starters.js.map +1 -0
  471. package/dist/styles.css +1181 -212
  472. package/dist/theme/color.d.ts +10 -0
  473. package/dist/theme/color.js +17 -1
  474. package/dist/theme/color.js.map +1 -1
  475. package/dist/theme/fontFallback.d.ts +23 -0
  476. package/dist/theme/fontFallback.js +58 -0
  477. package/dist/theme/fontFallback.js.map +1 -0
  478. package/dist/theme/fonts.d.ts +11 -0
  479. package/dist/theme/fonts.js +16 -0
  480. package/dist/theme/fonts.js.map +1 -0
  481. package/dist/version.js +1 -1
  482. package/package.json +5 -4
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/admin/pages/StarterKiezer.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { doc, getDoc } from \"firebase/firestore\";\nimport { getDb, getFirebaseApp } from \"../../firebase/client\";\nimport { callable } from \"../../firebase/functionsClient\";\nimport { isDemoActive } from \"../../demo/demoStore\";\nimport { STARTERS, starterModules, starterPaginas, type Starter } from \"../../starters/starters\";\nimport { builtinModules } from \"../../modules/builtins\";\nimport { builtinThemePresets } from \"../../theme/presets\";\nimport { SiteSettingsSchema, type NavItem, type SiteSettings } from \"../../schema/settings\";\nimport { createPage } from \"../lib/pagesClient\";\nimport { zodFoutTekst } from \"../lib/zodFout\";\nimport { Button, Card } from \"../ui/primitives\";\nimport { Switch } from \"../ui/switch\";\nimport { Dialog, DialogContent, DialogFooter } from \"../ui/dialog\";\nimport { useToast } from \"../ui/toast\";\n\n/**\n * \"Start met een kant-en-klare opzet\" (8.14) — alleen bij een site zonder pagina's.\n *\n * Kies wat voor bedrijf het is, en de site krijgt in één keer de pagina's (als werkversie, niets\n * gaat live), het menu, de modules die die pagina's nodig hebben, het soort bedrijf voor Google, de\n * knop in de kop en — als je wilt — een passende huisstijl. Daarna vul je de teksten in op de\n * pagina zelf. Zie `starters/starters.ts`.\n */\nexport function StarterKiezer({ siteId, onKlaar }: { siteId: string; onKlaar?: () => void }) {\n const { toast } = useToast();\n const [gekozen, setGekozen] = useState<Starter | null>(null);\n const [metStijl, setMetStijl] = useState(true);\n const [bezig, setBezig] = useState(false);\n const preset = gekozen ? builtinThemePresets.find((p) => p.id === gekozen.preset) : undefined;\n\n async function zetKlaar(s: Starter) {\n setBezig(true);\n try {\n const paginas = starterPaginas(s);\n for (const p of paginas) await createPage(siteId, { title: p.title, slug: p.slug, path: p.path, blocks: p.blocks as never });\n\n const db = getDb();\n const app = getFirebaseApp();\n if (!isDemoActive() && db && app) {\n const huidig = ((await getDoc(doc(db, \"sites\", siteId, \"settings\", \"site\"))).data() ?? {}) as SiteSettings;\n const mods = starterModules(s, builtinModules);\n const nav: NavItem[] = huidig.nav?.length ? huidig.nav : paginas.filter((p) => p.inMenu).map((p) => ({ label: p.title, href: p.path }));\n const volgend: SiteSettings = {\n ...huidig,\n nav,\n modules: { ...(huidig.modules ?? {}), ...Object.fromEntries(mods.map((m) => [m, true])) },\n business: { ...(huidig.business ?? {}), type: huidig.business?.type ?? s.bedrijfstype },\n header: { ...(huidig.header ?? {}), cta: huidig.header?.cta ?? s.cta },\n ...(metStijl && preset ? { theme: { ...(huidig.theme ?? {}), ...preset.theme } } : {}),\n };\n const parsed = SiteSettingsSchema.safeParse(volgend);\n if (!parsed.success) throw new Error(zodFoutTekst(parsed.error.issues[0]));\n await callable(app, \"saveSiteSettings\")({ siteId, settings: parsed.data });\n }\n toast({\n title: `${paginas.length} pagina's klaargezet`,\n description: \"Als werkversie — er staat nog niets live. Open een pagina en vul de teksten in met het potlood.\",\n tone: \"success\",\n action: { label: \"Open de homepage\", onClick: () => { try { sessionStorage.setItem(\"xicms-bewerkmodus\", \"bewerken\"); } catch { /* geen opslag */ } window.location.assign(\"/\"); } },\n });\n setGekozen(null);\n onKlaar?.();\n } catch (e) {\n toast({ title: \"Klaarzetten mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setBezig(false);\n }\n }\n\n return (\n <Card>\n <h3 className=\"text-base font-semibold\">Start met een kant-en-klare opzet</h3>\n <p className=\"mb-3 text-sm text-slate-500\">\n Kies wat voor bedrijf je hebt. Je krijgt meteen de pagina&apos;s die daarbij horen, als werkversie om in te vullen.\n </p>\n <div className=\"grid gap-2 sm:grid-cols-2 lg:grid-cols-4\">\n {STARTERS.map((s) => (\n <button\n key={s.id}\n type=\"button\"\n onClick={() => setGekozen(s)}\n className=\"xicms-admin-btn grid gap-1 rounded-lg border border-slate-200 bg-white p-3 text-left hover:border-slate-400 hover:bg-slate-50\"\n >\n <span className=\"text-xl\" aria-hidden>{s.icoon}</span>\n <span className=\"text-sm font-medium text-slate-900\">{s.label}</span>\n <span className=\"text-xs leading-snug text-slate-500\">{s.voor}</span>\n </button>\n ))}\n </div>\n {gekozen && (\n <Dialog open onOpenChange={(v) => !v && !bezig && setGekozen(null)}>\n <DialogContent title={`${gekozen.icoon} ${gekozen.label}`} width=\"min(92vw, 34rem)\">\n <div className=\"grid gap-3 text-sm text-slate-700\">\n <p>Deze pagina&apos;s worden klaargezet (als werkversie):</p>\n <ul className=\"list-disc pl-5\">\n {gekozen.paginas.map((p) => (\n <li key={p.path}>{p.title} <span className=\"text-slate-500\">({p.path})</span></li>\n ))}\n </ul>\n <p className=\"text-slate-500\">\n Ook: het menu, de knop “{gekozen.cta.label}” rechtsboven en de onderdelen die deze pagina&apos;s gebruiken.\n </p>\n {preset && (\n <Switch checked={metStijl} onCheckedChange={setMetStijl} label={`Ook de huisstijl “${preset.label}” gebruiken (later aan te passen)`} />\n )}\n </div>\n <DialogFooter>\n <Button variant=\"ghost\" disabled={bezig} onClick={() => setGekozen(null)}>Annuleren</Button>\n <Button loading={bezig} onClick={() => void zetKlaar(gekozen)}>Klaarzetten</Button>\n </DialogFooter>\n </DialogContent>\n </Dialog>\n )}\n </Card>\n );\n}\n"],"mappings":"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","names":[]}
@@ -4,7 +4,7 @@
4
4
  * nieuwe module met een eigen paneel hoeft `AdminApp` dus niet meer aan te raken.
5
5
  */
6
6
  import type { ComponentType } from "react";
7
- export type PanelMinRole = "editor" | "siteadmin";
7
+ export type PanelMinRole = "editor" | "siteadmin" | "superadmin";
8
8
  export interface PanelDefinition {
9
9
  /** Moet overeenkomen met de module-`id`; bepaalt of het paneel actief is. */
10
10
  moduleId: string;
@@ -26,7 +26,8 @@ const builtinPanels = [
26
26
  { moduleId: "stats", label: "Statistieken", order: 50, minRole: "editor", Panel: StatsPanel },
27
27
  // Webwinkel (6.0): opt-in via `@xiwebdesign/xicms-core/admin/shop` → `shopPanel` in AdminApp.extraPanels.
28
28
  // Bouwstenen (5.0): custom blocks zonder deploy — hangt aan de altijd-actieve content-module.
29
- { moduleId: "content", id: "bouwstenen", label: "Bouwstenen", order: 60, minRole: "siteadmin", Panel: CustomBlocksPanel },
29
+ // 8.2: superadmin — een scherm met JSON-velden, sjablonen en CSS is bureauwerk, geen klantwerk.
30
+ { moduleId: "content", id: "bouwstenen", label: "Bouwstenen", order: 60, minRole: "superadmin", Panel: CustomBlocksPanel },
30
31
  { moduleId: "settings", label: "Instellingen", order: 100, minRole: "siteadmin", Panel: SettingsPanel }
31
32
  ];
32
33
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/admin/panelRegistry.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * Paneel-registry — koppelt een beheer-paneel aan een module-id. `AdminApp` rendert de tabs\n * hieruit (gesorteerd op `order`, gated op rol én actieve-module-set) i.p.v. hardgecodeerd. Een\n * nieuwe module met een eigen paneel hoeft `AdminApp` dus niet meer aan te raken.\n */\nimport type { ComponentType } from \"react\";\nimport { DashboardPanel } from \"./dashboard/DashboardPanel\";\nimport { PagesPanel } from \"./pages/PagesPanel\";\nimport { MenuPanel } from \"./menu/MenuPanel\";\nimport { MediaManager } from \"./media/MediaManager\";\nimport { FormsPanel } from \"./forms/FormsPanel\";\nimport { StatsPanel } from \"./stats/StatsPanel\";\nimport { SettingsPanel } from \"./settings/SettingsPanel\";\nimport { NewsEditor } from \"./NewsEditor\";\nimport { CustomBlocksPanel } from \"./customBlocks/CustomBlocksPanel\";\n\nexport type PanelMinRole = \"editor\" | \"siteadmin\";\n\nexport interface PanelDefinition {\n /** Moet overeenkomen met de module-`id`; bepaalt of het paneel actief is. */\n moduleId: string;\n /**\n * Unieke sleutel van dit paneel in de tabbladen. Standaard `moduleId`.\n *\n * Die twee liepen door elkaar: `moduleId` bepaalde zowel of een paneel actief is als welk\n * tabblad het is. Zolang elke module één paneel had viel dat niet op, maar het betekende dat\n * twee panelen van dezelfde module elkaars tabblad overschreven — Radix koppelt op de waarde, en\n * React op de key. Menu en Bouwstenen hangen allebei aan de altijd-actieve content-module, en\n * dat maakte het zichtbaar.\n */\n id?: string;\n label: string;\n /** Sorteervolgorde (laag = links). Instellingen staat vast achteraan (100). */\n order: number;\n minRole: PanelMinRole;\n Panel: ComponentType<{ siteId: string }>;\n}\n\n/** Adapter: de NewsEditor leest zelf siteId via context; wrap voor een uniforme prop-signatuur. */\nfunction NewsPanel(_: { siteId: string }) {\n return <NewsEditor />;\n}\n\n/** De panelen van de ingebouwde modules. */\nexport const builtinPanels: PanelDefinition[] = [\n // Start (7.16): uitleg + widgets + snelkoppelingen. Hangt aan de altijd-actieve content-module\n // en staat vooraan — /beheer opent hier, niet meer midden in het pagina-overzicht.\n { moduleId: \"content\", id: \"start\", label: \"Start\", order: 5, minRole: \"editor\", Panel: DashboardPanel },\n { moduleId: \"pages\", label: \"Pagina's\", order: 10, minRole: \"editor\", Panel: PagesPanel },\n // Menu hoort bij de content-module (altijd actief) en staat vlak na Pagina's: een menu-item\n // wijst naar een pagina, dus die volgorde leest zoals je werkt.\n { moduleId: \"content\", id: \"menu\", label: \"Menu\", order: 15, minRole: \"siteadmin\", Panel: MenuPanel },\n { moduleId: \"news\", label: \"Nieuws\", order: 20, minRole: \"editor\", Panel: NewsPanel },\n { moduleId: \"media\", label: \"Media\", order: 30, minRole: \"editor\", Panel: MediaManager },\n { moduleId: \"forms\", label: \"Formulieren\", order: 40, minRole: \"editor\", Panel: FormsPanel },\n { moduleId: \"stats\", label: \"Statistieken\", order: 50, minRole: \"editor\", Panel: StatsPanel },\n // Webwinkel (6.0): opt-in via `@xiwebdesign/xicms-core/admin/shop` → `shopPanel` in AdminApp.extraPanels.\n // Bouwstenen (5.0): custom blocks zonder deploy — hangt aan de altijd-actieve content-module.\n { moduleId: \"content\", id: \"bouwstenen\", label: \"Bouwstenen\", order: 60, minRole: \"siteadmin\", Panel: CustomBlocksPanel },\n { moduleId: \"settings\", label: \"Instellingen\", order: 100, minRole: \"siteadmin\", Panel: SettingsPanel },\n];\n"],"mappings":";AA0CS;AAlCT,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAC3B,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAC3B,SAAS,yBAAyB;AAyBlC,SAAS,UAAU,GAAuB;AACxC,SAAO,oBAAC,cAAW;AACrB;AAGO,MAAM,gBAAmC;AAAA;AAAA;AAAA,EAG9C,EAAE,UAAU,WAAW,IAAI,SAAS,OAAO,SAAS,OAAO,GAAG,SAAS,UAAU,OAAO,eAAe;AAAA,EACvG,EAAE,UAAU,SAAS,OAAO,YAAY,OAAO,IAAI,SAAS,UAAU,OAAO,WAAW;AAAA;AAAA;AAAA,EAGxF,EAAE,UAAU,WAAW,IAAI,QAAQ,OAAO,QAAQ,OAAO,IAAI,SAAS,aAAa,OAAO,UAAU;AAAA,EACpG,EAAE,UAAU,QAAQ,OAAO,UAAU,OAAO,IAAI,SAAS,UAAU,OAAO,UAAU;AAAA,EACpF,EAAE,UAAU,SAAS,OAAO,SAAS,OAAO,IAAI,SAAS,UAAU,OAAO,aAAa;AAAA,EACvF,EAAE,UAAU,SAAS,OAAO,eAAe,OAAO,IAAI,SAAS,UAAU,OAAO,WAAW;AAAA,EAC3F,EAAE,UAAU,SAAS,OAAO,gBAAgB,OAAO,IAAI,SAAS,UAAU,OAAO,WAAW;AAAA;AAAA;AAAA,EAG5F,EAAE,UAAU,WAAW,IAAI,cAAc,OAAO,cAAc,OAAO,IAAI,SAAS,aAAa,OAAO,kBAAkB;AAAA,EACxH,EAAE,UAAU,YAAY,OAAO,gBAAgB,OAAO,KAAK,SAAS,aAAa,OAAO,cAAc;AACxG;","names":[]}
1
+ {"version":3,"sources":["../../src/admin/panelRegistry.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * Paneel-registry — koppelt een beheer-paneel aan een module-id. `AdminApp` rendert de tabs\n * hieruit (gesorteerd op `order`, gated op rol én actieve-module-set) i.p.v. hardgecodeerd. Een\n * nieuwe module met een eigen paneel hoeft `AdminApp` dus niet meer aan te raken.\n */\nimport type { ComponentType } from \"react\";\nimport { DashboardPanel } from \"./dashboard/DashboardPanel\";\nimport { PagesPanel } from \"./pages/PagesPanel\";\nimport { MenuPanel } from \"./menu/MenuPanel\";\nimport { MediaManager } from \"./media/MediaManager\";\nimport { FormsPanel } from \"./forms/FormsPanel\";\nimport { StatsPanel } from \"./stats/StatsPanel\";\nimport { SettingsPanel } from \"./settings/SettingsPanel\";\nimport { NewsEditor } from \"./NewsEditor\";\nimport { CustomBlocksPanel } from \"./customBlocks/CustomBlocksPanel\";\n\nexport type PanelMinRole = \"editor\" | \"siteadmin\" | \"superadmin\";\n\nexport interface PanelDefinition {\n /** Moet overeenkomen met de module-`id`; bepaalt of het paneel actief is. */\n moduleId: string;\n /**\n * Unieke sleutel van dit paneel in de tabbladen. Standaard `moduleId`.\n *\n * Die twee liepen door elkaar: `moduleId` bepaalde zowel of een paneel actief is als welk\n * tabblad het is. Zolang elke module één paneel had viel dat niet op, maar het betekende dat\n * twee panelen van dezelfde module elkaars tabblad overschreven — Radix koppelt op de waarde, en\n * React op de key. Menu en Bouwstenen hangen allebei aan de altijd-actieve content-module, en\n * dat maakte het zichtbaar.\n */\n id?: string;\n label: string;\n /** Sorteervolgorde (laag = links). Instellingen staat vast achteraan (100). */\n order: number;\n minRole: PanelMinRole;\n Panel: ComponentType<{ siteId: string }>;\n}\n\n/** Adapter: de NewsEditor leest zelf siteId via context; wrap voor een uniforme prop-signatuur. */\nfunction NewsPanel(_: { siteId: string }) {\n return <NewsEditor />;\n}\n\n/** De panelen van de ingebouwde modules. */\nexport const builtinPanels: PanelDefinition[] = [\n // Start (7.16): uitleg + widgets + snelkoppelingen. Hangt aan de altijd-actieve content-module\n // en staat vooraan — /beheer opent hier, niet meer midden in het pagina-overzicht.\n { moduleId: \"content\", id: \"start\", label: \"Start\", order: 5, minRole: \"editor\", Panel: DashboardPanel },\n { moduleId: \"pages\", label: \"Pagina's\", order: 10, minRole: \"editor\", Panel: PagesPanel },\n // Menu hoort bij de content-module (altijd actief) en staat vlak na Pagina's: een menu-item\n // wijst naar een pagina, dus die volgorde leest zoals je werkt.\n { moduleId: \"content\", id: \"menu\", label: \"Menu\", order: 15, minRole: \"siteadmin\", Panel: MenuPanel },\n { moduleId: \"news\", label: \"Nieuws\", order: 20, minRole: \"editor\", Panel: NewsPanel },\n { moduleId: \"media\", label: \"Media\", order: 30, minRole: \"editor\", Panel: MediaManager },\n { moduleId: \"forms\", label: \"Formulieren\", order: 40, minRole: \"editor\", Panel: FormsPanel },\n { moduleId: \"stats\", label: \"Statistieken\", order: 50, minRole: \"editor\", Panel: StatsPanel },\n // Webwinkel (6.0): opt-in via `@xiwebdesign/xicms-core/admin/shop` → `shopPanel` in AdminApp.extraPanels.\n // Bouwstenen (5.0): custom blocks zonder deploy — hangt aan de altijd-actieve content-module.\n // 8.2: superadmin — een scherm met JSON-velden, sjablonen en CSS is bureauwerk, geen klantwerk.\n { moduleId: \"content\", id: \"bouwstenen\", label: \"Bouwstenen\", order: 60, minRole: \"superadmin\", Panel: CustomBlocksPanel },\n { moduleId: \"settings\", label: \"Instellingen\", order: 100, minRole: \"siteadmin\", Panel: SettingsPanel },\n];\n"],"mappings":";AA0CS;AAlCT,SAAS,sBAAsB;AAC/B,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAC3B,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB;AAC9B,SAAS,kBAAkB;AAC3B,SAAS,yBAAyB;AAyBlC,SAAS,UAAU,GAAuB;AACxC,SAAO,oBAAC,cAAW;AACrB;AAGO,MAAM,gBAAmC;AAAA;AAAA;AAAA,EAG9C,EAAE,UAAU,WAAW,IAAI,SAAS,OAAO,SAAS,OAAO,GAAG,SAAS,UAAU,OAAO,eAAe;AAAA,EACvG,EAAE,UAAU,SAAS,OAAO,YAAY,OAAO,IAAI,SAAS,UAAU,OAAO,WAAW;AAAA;AAAA;AAAA,EAGxF,EAAE,UAAU,WAAW,IAAI,QAAQ,OAAO,QAAQ,OAAO,IAAI,SAAS,aAAa,OAAO,UAAU;AAAA,EACpG,EAAE,UAAU,QAAQ,OAAO,UAAU,OAAO,IAAI,SAAS,UAAU,OAAO,UAAU;AAAA,EACpF,EAAE,UAAU,SAAS,OAAO,SAAS,OAAO,IAAI,SAAS,UAAU,OAAO,aAAa;AAAA,EACvF,EAAE,UAAU,SAAS,OAAO,eAAe,OAAO,IAAI,SAAS,UAAU,OAAO,WAAW;AAAA,EAC3F,EAAE,UAAU,SAAS,OAAO,gBAAgB,OAAO,IAAI,SAAS,UAAU,OAAO,WAAW;AAAA;AAAA;AAAA;AAAA,EAI5F,EAAE,UAAU,WAAW,IAAI,cAAc,OAAO,cAAc,OAAO,IAAI,SAAS,cAAc,OAAO,kBAAkB;AAAA,EACzH,EAAE,UAAU,YAAY,OAAO,gBAAgB,OAAO,KAAK,SAAS,aAAa,OAAO,cAAc;AACxG;","names":[]}
@@ -27,7 +27,7 @@ function PatternInserter({
27
27
  open && /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(DialogContent, { title: "Sectie toevoegen", width: "min(92vw, 36rem)", children: [
28
28
  /* @__PURE__ */ jsx("p", { className: "mb-3 text-sm text-slate-500", children: "Kies een kant-en-klare sectie; je past de inhoud daarna aan." }),
29
29
  /* @__PURE__ */ jsx("div", { className: "grid max-h-[60vh] gap-4 overflow-auto", children: byCategory.map(([cat, items]) => /* @__PURE__ */ jsxs("div", { children: [
30
- /* @__PURE__ */ jsx("h4", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-slate-400", children: cat }),
30
+ /* @__PURE__ */ jsx("h4", { className: "mb-1 text-xs font-semibold uppercase tracking-wide text-slate-500", children: cat }),
31
31
  /* @__PURE__ */ jsx("div", { className: "grid gap-2", children: items.map((p) => /* @__PURE__ */ jsxs(
32
32
  "button",
33
33
  {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/admin/patterns/PatternInserter.tsx"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useState } from \"react\";\nimport { Dialog, DialogContent, DialogClose } from \"../ui/dialog\";\nimport { Button } from \"../ui/primitives\";\nimport { useRegistry } from \"../../blocks/context\";\nimport { builtinPatterns, instantiatePattern, collectPatternTypes, type Pattern } from \"../../patterns\";\n\n/**\n * \"Sectie toevoegen\" — kiest een kant-en-klaar patroon en voegt de blocks (met verse keys) in.\n * Hergebruikt in de visuele editor én het /beheer-paginapaneel.\n */\nexport function PatternInserter({\n patterns = builtinPatterns,\n onInsert,\n label = \"+ Sectie toevoegen\",\n}: {\n patterns?: Pattern[];\n onInsert: (blocks: Array<Record<string, unknown>>) => void;\n label?: string;\n}) {\n const [open, setOpen] = useState(false);\n const registry = useRegistry();\n const byCategory = useMemo(() => {\n // Verberg patronen waarvan een benodigd blok niet in de registry zit (module uitgeschakeld):\n // invoegen zou anders \"Onbekend blok\"-gaten geven.\n const available = patterns.filter((p) => collectPatternTypes(p).every((t) => registry.get(t)));\n const map = new Map<string, Pattern[]>();\n for (const p of available) {\n const arr = map.get(p.category) ?? [];\n arr.push(p);\n map.set(p.category, arr);\n }\n return [...map.entries()];\n }, [patterns, registry]);\n\n return (\n <>\n <Button type=\"button\" variant=\"secondary\" size=\"sm\" onClick={() => setOpen(true)}>\n {label}\n </Button>\n {/* Dicht = niet gemount; zelfde overweging als bij de mediakiezer (zie MediaPicker). */}\n {open && (\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogContent title=\"Sectie toevoegen\" width=\"min(92vw, 36rem)\">\n <p className=\"mb-3 text-sm text-slate-500\">Kies een kant-en-klare sectie; je past de inhoud daarna aan.</p>\n <div className=\"grid max-h-[60vh] gap-4 overflow-auto\">\n {byCategory.map(([cat, items]) => (\n <div key={cat}>\n <h4 className=\"mb-1 text-xs font-semibold uppercase tracking-wide text-slate-400\">{cat}</h4>\n <div className=\"grid gap-2\">\n {items.map((p) => (\n <button\n key={p.id}\n type=\"button\"\n className=\"rounded-lg border border-slate-200 p-3 text-left text-sm hover:border-brand-500 hover:bg-slate-50\"\n onClick={() => {\n onInsert(instantiatePattern(p));\n setOpen(false);\n }}\n >\n <span className=\"flex items-center justify-between gap-2\">\n <span className=\"font-medium\">{p.label}</span>\n {/* Mini-preview: de iconen van de blokken die dit patroon invoegt. */}\n <span className=\"shrink-0 text-base opacity-70\" aria-hidden>\n {p.blocks.slice(0, 6).map((b, idx) => (\n <span key={idx}>{registry.get(b._type)?.icon ?? \"🧩\"}</span>\n ))}\n </span>\n </span>\n {p.description && <span className=\"block text-xs text-slate-500\">{p.description}</span>}\n </button>\n ))}\n </div>\n </div>\n ))}\n </div>\n <div className=\"mt-4 flex justify-end\">\n <DialogClose asChild>\n <Button variant=\"secondary\" size=\"sm\">Sluiten</Button>\n </DialogClose>\n </div>\n </DialogContent>\n </Dialog>\n )}\n </>\n );\n}\n"],"mappings":";AAqCI,mBACE,KAuBgB,YAxBlB;AAnCJ,SAAS,SAAS,gBAAgB;AAClC,SAAS,QAAQ,eAAe,mBAAmB;AACnD,SAAS,cAAc;AACvB,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB,oBAAoB,2BAAyC;AAMhF,SAAS,gBAAgB;AAAA,EAC9B,WAAW;AAAA,EACX;AAAA,EACA,QAAQ;AACV,GAIG;AACD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,WAAW,YAAY;AAC7B,QAAM,aAAa,QAAQ,MAAM;AAG/B,UAAM,YAAY,SAAS,OAAO,CAAC,MAAM,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,SAAS,IAAI,CAAC,CAAC,CAAC;AAC7F,UAAM,MAAM,oBAAI,IAAuB;AACvC,eAAW,KAAK,WAAW;AACzB,YAAM,MAAM,IAAI,IAAI,EAAE,QAAQ,KAAK,CAAC;AACpC,UAAI,KAAK,CAAC;AACV,UAAI,IAAI,EAAE,UAAU,GAAG;AAAA,IACzB;AACA,WAAO,CAAC,GAAG,IAAI,QAAQ,CAAC;AAAA,EAC1B,GAAG,CAAC,UAAU,QAAQ,CAAC;AAEvB,SACE,iCACE;AAAA,wBAAC,UAAO,MAAK,UAAS,SAAQ,aAAY,MAAK,MAAK,SAAS,MAAM,QAAQ,IAAI,GAC5E,iBACH;AAAA,IAEC,QACD,oBAAC,UAAO,MAAY,cAAc,SAChC,+BAAC,iBAAc,OAAM,oBAAmB,OAAM,oBAC5C;AAAA,0BAAC,OAAE,WAAU,+BAA8B,0EAA4D;AAAA,MACvG,oBAAC,SAAI,WAAU,yCACZ,qBAAW,IAAI,CAAC,CAAC,KAAK,KAAK,MAC1B,qBAAC,SACC;AAAA,4BAAC,QAAG,WAAU,qEAAqE,eAAI;AAAA,QACvF,oBAAC,SAAI,WAAU,cACZ,gBAAM,IAAI,CAAC,MACV;AAAA,UAAC;AAAA;AAAA,YAEC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS,MAAM;AACb,uBAAS,mBAAmB,CAAC,CAAC;AAC9B,sBAAQ,KAAK;AAAA,YACf;AAAA,YAEA;AAAA,mCAAC,UAAK,WAAU,2CACd;AAAA,oCAAC,UAAK,WAAU,eAAe,YAAE,OAAM;AAAA,gBAEvC,oBAAC,UAAK,WAAU,iCAAgC,eAAW,MACxD,YAAE,OAAO,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,QAC5B,oBAAC,UAAgB,mBAAS,IAAI,EAAE,KAAK,GAAG,QAAQ,eAArC,GAA0C,CACtD,GACH;AAAA,iBACF;AAAA,cACC,EAAE,eAAe,oBAAC,UAAK,WAAU,gCAAgC,YAAE,aAAY;AAAA;AAAA;AAAA,UAjB3E,EAAE;AAAA,QAkBT,CACD,GACH;AAAA,WAzBQ,GA0BV,CACD,GACH;AAAA,MACA,oBAAC,SAAI,WAAU,yBACb,8BAAC,eAAY,SAAO,MAClB,8BAAC,UAAO,SAAQ,aAAY,MAAK,MAAK,qBAAO,GAC/C,GACF;AAAA,OACF,GACF;AAAA,KAEF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../src/admin/patterns/PatternInserter.tsx"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useState } from \"react\";\nimport { Dialog, DialogContent, DialogClose } from \"../ui/dialog\";\nimport { Button } from \"../ui/primitives\";\nimport { useRegistry } from \"../../blocks/context\";\nimport { builtinPatterns, instantiatePattern, collectPatternTypes, type Pattern } from \"../../patterns\";\n\n/**\n * \"Sectie toevoegen\" — kiest een kant-en-klaar patroon en voegt de blocks (met verse keys) in.\n * Hergebruikt in de visuele editor én het /beheer-paginapaneel.\n */\nexport function PatternInserter({\n patterns = builtinPatterns,\n onInsert,\n label = \"+ Sectie toevoegen\",\n}: {\n patterns?: Pattern[];\n onInsert: (blocks: Array<Record<string, unknown>>) => void;\n label?: string;\n}) {\n const [open, setOpen] = useState(false);\n const registry = useRegistry();\n const byCategory = useMemo(() => {\n // Verberg patronen waarvan een benodigd blok niet in de registry zit (module uitgeschakeld):\n // invoegen zou anders \"Onbekend blok\"-gaten geven.\n const available = patterns.filter((p) => collectPatternTypes(p).every((t) => registry.get(t)));\n const map = new Map<string, Pattern[]>();\n for (const p of available) {\n const arr = map.get(p.category) ?? [];\n arr.push(p);\n map.set(p.category, arr);\n }\n return [...map.entries()];\n }, [patterns, registry]);\n\n return (\n <>\n <Button type=\"button\" variant=\"secondary\" size=\"sm\" onClick={() => setOpen(true)}>\n {label}\n </Button>\n {/* Dicht = niet gemount; zelfde overweging als bij de mediakiezer (zie MediaPicker). */}\n {open && (\n <Dialog open={open} onOpenChange={setOpen}>\n <DialogContent title=\"Sectie toevoegen\" width=\"min(92vw, 36rem)\">\n <p className=\"mb-3 text-sm text-slate-500\">Kies een kant-en-klare sectie; je past de inhoud daarna aan.</p>\n <div className=\"grid max-h-[60vh] gap-4 overflow-auto\">\n {byCategory.map(([cat, items]) => (\n <div key={cat}>\n <h4 className=\"mb-1 text-xs font-semibold uppercase tracking-wide text-slate-500\">{cat}</h4>\n <div className=\"grid gap-2\">\n {items.map((p) => (\n <button\n key={p.id}\n type=\"button\"\n className=\"rounded-lg border border-slate-200 p-3 text-left text-sm hover:border-brand-500 hover:bg-slate-50\"\n onClick={() => {\n onInsert(instantiatePattern(p));\n setOpen(false);\n }}\n >\n <span className=\"flex items-center justify-between gap-2\">\n <span className=\"font-medium\">{p.label}</span>\n {/* Mini-preview: de iconen van de blokken die dit patroon invoegt. */}\n <span className=\"shrink-0 text-base opacity-70\" aria-hidden>\n {p.blocks.slice(0, 6).map((b, idx) => (\n <span key={idx}>{registry.get(b._type)?.icon ?? \"🧩\"}</span>\n ))}\n </span>\n </span>\n {p.description && <span className=\"block text-xs text-slate-500\">{p.description}</span>}\n </button>\n ))}\n </div>\n </div>\n ))}\n </div>\n <div className=\"mt-4 flex justify-end\">\n <DialogClose asChild>\n <Button variant=\"secondary\" size=\"sm\">Sluiten</Button>\n </DialogClose>\n </div>\n </DialogContent>\n </Dialog>\n )}\n </>\n );\n}\n"],"mappings":";AAqCI,mBACE,KAuBgB,YAxBlB;AAnCJ,SAAS,SAAS,gBAAgB;AAClC,SAAS,QAAQ,eAAe,mBAAmB;AACnD,SAAS,cAAc;AACvB,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB,oBAAoB,2BAAyC;AAMhF,SAAS,gBAAgB;AAAA,EAC9B,WAAW;AAAA,EACX;AAAA,EACA,QAAQ;AACV,GAIG;AACD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,WAAW,YAAY;AAC7B,QAAM,aAAa,QAAQ,MAAM;AAG/B,UAAM,YAAY,SAAS,OAAO,CAAC,MAAM,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,SAAS,IAAI,CAAC,CAAC,CAAC;AAC7F,UAAM,MAAM,oBAAI,IAAuB;AACvC,eAAW,KAAK,WAAW;AACzB,YAAM,MAAM,IAAI,IAAI,EAAE,QAAQ,KAAK,CAAC;AACpC,UAAI,KAAK,CAAC;AACV,UAAI,IAAI,EAAE,UAAU,GAAG;AAAA,IACzB;AACA,WAAO,CAAC,GAAG,IAAI,QAAQ,CAAC;AAAA,EAC1B,GAAG,CAAC,UAAU,QAAQ,CAAC;AAEvB,SACE,iCACE;AAAA,wBAAC,UAAO,MAAK,UAAS,SAAQ,aAAY,MAAK,MAAK,SAAS,MAAM,QAAQ,IAAI,GAC5E,iBACH;AAAA,IAEC,QACD,oBAAC,UAAO,MAAY,cAAc,SAChC,+BAAC,iBAAc,OAAM,oBAAmB,OAAM,oBAC5C;AAAA,0BAAC,OAAE,WAAU,+BAA8B,0EAA4D;AAAA,MACvG,oBAAC,SAAI,WAAU,yCACZ,qBAAW,IAAI,CAAC,CAAC,KAAK,KAAK,MAC1B,qBAAC,SACC;AAAA,4BAAC,QAAG,WAAU,qEAAqE,eAAI;AAAA,QACvF,oBAAC,SAAI,WAAU,cACZ,gBAAM,IAAI,CAAC,MACV;AAAA,UAAC;AAAA;AAAA,YAEC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAS,MAAM;AACb,uBAAS,mBAAmB,CAAC,CAAC;AAC9B,sBAAQ,KAAK;AAAA,YACf;AAAA,YAEA;AAAA,mCAAC,UAAK,WAAU,2CACd;AAAA,oCAAC,UAAK,WAAU,eAAe,YAAE,OAAM;AAAA,gBAEvC,oBAAC,UAAK,WAAU,iCAAgC,eAAW,MACxD,YAAE,OAAO,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,GAAG,QAC5B,oBAAC,UAAgB,mBAAS,IAAI,EAAE,KAAK,GAAG,QAAQ,eAArC,GAA0C,CACtD,GACH;AAAA,iBACF;AAAA,cACC,EAAE,eAAe,oBAAC,UAAK,WAAU,gCAAgC,YAAE,aAAY;AAAA;AAAA;AAAA,UAjB3E,EAAE;AAAA,QAkBT,CACD,GACH;AAAA,WAzBQ,GA0BV,CACD,GACH;AAAA,MACA,oBAAC,SAAI,WAAU,yBACb,8BAAC,eAAY,SAAO,MAClB,8BAAC,UAAO,SAAQ,aAAY,MAAK,MAAK,qBAAO,GAC/C,GACF;AAAA,OACF,GACF;AAAA,KAEF;AAEJ;","names":[]}
@@ -0,0 +1,20 @@
1
+ import type { Business } from "../../schema/business.js";
2
+ import type { HeaderSettings } from "../../schema/settings.js";
3
+ /**
4
+ * Instellingen → Bedrijf (8.13): één plek voor adres, telefoon en openingstijden. De site gebruikt
5
+ * dit voor Google (JSON-LD), het contact- en openingstijdenblok en de footer. Wie hier zijn
6
+ * telefoonnummer wijzigt, wijzigt het overal.
7
+ */
8
+ export declare function BedrijfInstellingen({ siteId, waarde, onChange, dirty, }: {
9
+ siteId: string;
10
+ waarde: Business | undefined;
11
+ onChange: (b: Business) => void;
12
+ dirty: boolean;
13
+ }): import("react").JSX.Element;
14
+ /** Instellingen → Kop (8.13): logo en actieknop van `SiteHeader`. */
15
+ export declare function KopInstellingen({ siteId, waarde, onChange, dirty, }: {
16
+ siteId: string;
17
+ waarde: HeaderSettings | undefined;
18
+ onChange: (h: HeaderSettings) => void;
19
+ dirty: boolean;
20
+ }): import("react").JSX.Element;
@@ -0,0 +1,159 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { BEDRIJFSTYPES } from "../../schema/business.js";
4
+ import { Card, Field, Input, Textarea } from "../ui/primitives.js";
5
+ import { Select } from "../ui/select.js";
6
+ import { Switch } from "../ui/switch.js";
7
+ import { ArrayEditor } from "../ui/ArrayEditor.js";
8
+ import { LinkVeld } from "../ui/LinkVeld.js";
9
+ import { MediaPickerButton } from "../media/MediaPicker.js";
10
+ import { VorigeTerugzetten } from "./VorigeTerugzetten.js";
11
+ import { afwijkingDatumTekst, bedrijfsnummerAdvies } from "../../bedrijf/bedrijf.js";
12
+ function BedrijfInstellingen({
13
+ siteId,
14
+ waarde,
15
+ onChange,
16
+ dirty
17
+ }) {
18
+ const b = waarde ?? {};
19
+ const zet = (patch) => onChange({ ...b, ...patch });
20
+ const adres = b.address ?? {};
21
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-4", children: [
22
+ /* @__PURE__ */ jsxs(Card, { children: [
23
+ /* @__PURE__ */ jsx("h3", { className: "mb-1 text-base font-semibold", children: "Bedrijf" }),
24
+ /* @__PURE__ */ jsx("p", { className: "mb-1 text-xs text-slate-500", children: "E\xE9n keer invullen, overal gebruikt: in Google, in het contact- en openingstijdenblok en onderaan je site." }),
25
+ /* @__PURE__ */ jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsx(VorigeTerugzetten, { siteId, sleutel: "business", dirty }) }),
26
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-3 md:grid-cols-2", children: [
27
+ /* @__PURE__ */ jsx(Field, { label: "Soort bedrijf", hint: "Helpt Google te begrijpen wat je doet.", children: /* @__PURE__ */ jsx(
28
+ Select,
29
+ {
30
+ value: b.type ?? "LocalBusiness",
31
+ onValueChange: (v) => zet({ type: v }),
32
+ options: BEDRIJFSTYPES.map((t) => ({ value: t.value, label: t.label }))
33
+ }
34
+ ) }),
35
+ /* @__PURE__ */ jsx(Field, { label: "Offici\xEBle naam (optioneel)", hint: "Alleen als die afwijkt van de sitenaam, bv. met B.V.", children: /* @__PURE__ */ jsx(Input, { value: b.name ?? "", onChange: (e) => zet({ name: e.target.value || void 0 }) }) }),
36
+ /* @__PURE__ */ jsx(Field, { label: "Telefoonnummer", children: /* @__PURE__ */ jsx(Input, { value: b.phone ?? "", autoComplete: "tel", onChange: (e) => zet({ phone: e.target.value || void 0 }), placeholder: "030 \u2013 123 45 67" }) }),
37
+ /* @__PURE__ */ jsx(Field, { label: "E-mailadres", children: /* @__PURE__ */ jsx(Input, { value: b.email ?? "", autoComplete: "email", onChange: (e) => zet({ email: e.target.value || void 0 }), placeholder: "info@\u2026" }) }),
38
+ /* @__PURE__ */ jsx(Field, { label: "WhatsApp (optioneel)", hint: "Internationaal, bv. +31 6 12345678.", children: /* @__PURE__ */ jsx(Input, { value: b.whatsapp ?? "", onChange: (e) => zet({ whatsapp: e.target.value || void 0 }) }) }),
39
+ /* @__PURE__ */ jsx(
40
+ Field,
41
+ {
42
+ label: "KvK-nummer",
43
+ hint: bedrijfsnummerAdvies("kvk", b.kvk) ?? "Verplicht om op je site te vermelden; het verschijnt onderaan je site en bij contact.",
44
+ children: /* @__PURE__ */ jsx(Input, { value: b.kvk ?? "", onChange: (e) => zet({ kvk: e.target.value || void 0 }), placeholder: "12345678" })
45
+ }
46
+ ),
47
+ /* @__PURE__ */ jsx(
48
+ Field,
49
+ {
50
+ label: "Btw-nummer",
51
+ hint: bedrijfsnummerAdvies("vat", b.vat) ?? "Verplicht als je aan consumenten verkoopt. Komt ook op je facturen.",
52
+ children: /* @__PURE__ */ jsx(Input, { value: b.vat ?? "", onChange: (e) => zet({ vat: e.target.value.toUpperCase() || void 0 }), placeholder: "NL123456789B01" })
53
+ }
54
+ )
55
+ ] }),
56
+ /* @__PURE__ */ jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsx(Field, { label: "Korte omschrijving", hint: "E\xE9n of twee zinnen over wat je doet \u2014 voor Google.", children: /* @__PURE__ */ jsx(Textarea, { rows: 2, value: b.description ?? "", onChange: (e) => zet({ description: e.target.value || void 0 }) }) }) })
57
+ ] }),
58
+ /* @__PURE__ */ jsxs(Card, { children: [
59
+ /* @__PURE__ */ jsx("h3", { className: "mb-3 text-base font-semibold", children: "Adres" }),
60
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-3 md:grid-cols-[2fr_1fr_1.5fr]", children: [
61
+ /* @__PURE__ */ jsx(Field, { label: "Straat en huisnummer", children: /* @__PURE__ */ jsx(Input, { value: adres.street ?? "", autoComplete: "street-address", onChange: (e) => zet({ address: { ...adres, street: e.target.value || void 0 } }) }) }),
62
+ /* @__PURE__ */ jsx(Field, { label: "Postcode", children: /* @__PURE__ */ jsx(Input, { value: adres.postalCode ?? "", autoComplete: "postal-code", onChange: (e) => zet({ address: { ...adres, postalCode: e.target.value || void 0 } }) }) }),
63
+ /* @__PURE__ */ jsx(Field, { label: "Plaats", children: /* @__PURE__ */ jsx(Input, { value: adres.city ?? "", autoComplete: "address-level2", onChange: (e) => zet({ address: { ...adres, city: e.target.value || void 0 } }) }) })
64
+ ] }),
65
+ /* @__PURE__ */ jsx("p", { className: "mt-2 text-xs text-slate-500", children: "Bezoekers krijgen een knop \u201CRoute plannen\u201D naar dit adres." })
66
+ ] }),
67
+ /* @__PURE__ */ jsxs(Card, { children: [
68
+ /* @__PURE__ */ jsx("h3", { className: "mb-1 text-base font-semibold", children: "Openingstijden" }),
69
+ /* @__PURE__ */ jsx("p", { className: "mb-3 text-xs text-slate-500", children: "Gewone taal mag: \u201CMaandag t/m vrijdag\u201D \xB7 \u201C09:00 \u2013 17:00\u201D, of \u201CZondag\u201D \xB7 \u201CGesloten\u201D. Dan klopt ook \u201CNu geopend\u201D op je site." }),
70
+ /* @__PURE__ */ jsx(
71
+ ArrayEditor,
72
+ {
73
+ items: b.hours ?? [],
74
+ onChange: (hours) => zet({ hours }),
75
+ newItem: () => ({ day: "", hours: "" }),
76
+ addLabel: "+ Regel",
77
+ emptyLabel: "Nog geen openingstijden.",
78
+ renderRow: (r, update) => /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-2", children: [
79
+ /* @__PURE__ */ jsx(Input, { value: r.day, placeholder: "Maandag t/m vrijdag", onChange: (e) => update({ day: e.target.value }), "aria-label": "Dag(en)" }),
80
+ /* @__PURE__ */ jsx(Input, { value: r.hours, placeholder: "09:00 \u2013 17:00", onChange: (e) => update({ hours: e.target.value }), "aria-label": "Tijden" })
81
+ ] })
82
+ }
83
+ ),
84
+ /* @__PURE__ */ jsx("div", { className: "mt-3", children: /* @__PURE__ */ jsx(Field, { label: "Toelichting (optioneel)", children: /* @__PURE__ */ jsx(Input, { value: b.hoursNote ?? "", placeholder: "Op afspraak ook 's avonds", onChange: (e) => zet({ hoursNote: e.target.value || void 0 }) }) }) })
85
+ ] }),
86
+ /* @__PURE__ */ jsxs(Card, { children: [
87
+ /* @__PURE__ */ jsx("h3", { className: "mb-1 text-base font-semibold", children: "Afwijkende dagen" }),
88
+ /* @__PURE__ */ jsx("p", { className: "mb-3 text-xs text-slate-500", children: "Feestdagen, vakantie, een koopavond. Ze staan op je site zodra ze binnen drie weken vallen, en Google toont ze als aangepaste tijden." }),
89
+ /* @__PURE__ */ jsx(
90
+ ArrayEditor,
91
+ {
92
+ items: b.exceptions ?? [],
93
+ onChange: (exceptions) => zet({ exceptions }),
94
+ newItem: () => ({ date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10), hours: "Gesloten" }),
95
+ addLabel: "+ Afwijkende dag",
96
+ emptyLabel: "Geen afwijkende dagen.",
97
+ renderRow: (a, update) => /* @__PURE__ */ jsxs("div", { className: "grid gap-2 md:grid-cols-[auto_auto_1fr_1fr]", children: [
98
+ /* @__PURE__ */ jsx(Field, { label: "Van", children: /* @__PURE__ */ jsx(Input, { type: "date", value: a.date, onChange: (e) => update({ date: e.target.value }) }) }),
99
+ /* @__PURE__ */ jsx(Field, { label: "Tot en met (optioneel)", children: /* @__PURE__ */ jsx(Input, { type: "date", value: a.until ?? "", onChange: (e) => update({ until: e.target.value || void 0 }) }) }),
100
+ /* @__PURE__ */ jsx(Field, { label: "Tijden", children: /* @__PURE__ */ jsx(Input, { value: a.hours, placeholder: "Gesloten of 10:00 \u2013 14:00", onChange: (e) => update({ hours: e.target.value }) }) }),
101
+ /* @__PURE__ */ jsx(Field, { label: "Omschrijving", hint: /^\d{4}-\d{2}-\d{2}$/.test(a.date) ? afwijkingDatumTekst(a) : void 0, children: /* @__PURE__ */ jsx(Input, { value: a.label ?? "", placeholder: "Eerste Kerstdag", onChange: (e) => update({ label: e.target.value || void 0 }) }) })
102
+ ] })
103
+ }
104
+ )
105
+ ] }),
106
+ /* @__PURE__ */ jsxs(Card, { children: [
107
+ /* @__PURE__ */ jsx("h3", { className: "mb-3 text-base font-semibold", children: "Reviews en profielen" }),
108
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-3", children: [
109
+ /* @__PURE__ */ jsx(Field, { label: "Link om een review achter te laten", hint: "Je Google-bedrijfsprofiel \u2192 \u2018Vraag om reviews\u2019. Het reviewblok kan er een knop \u2018Beoordeel ons\u2019 van maken.", children: /* @__PURE__ */ jsx(Input, { value: b.reviewUrl ?? "", placeholder: "https://g.page/r/\u2026", onChange: (e) => zet({ reviewUrl: e.target.value || void 0 }) }) }),
110
+ /* @__PURE__ */ jsx(Field, { label: "Prijsklasse (optioneel)", hint: "Bv. \u20AC\u20AC of \u20AC 25 \u2013 \u20AC 45.", children: /* @__PURE__ */ jsx(Input, { value: b.priceRange ?? "", onChange: (e) => zet({ priceRange: e.target.value || void 0 }) }) })
111
+ ] })
112
+ ] })
113
+ ] });
114
+ }
115
+ function KopInstellingen({
116
+ siteId,
117
+ waarde,
118
+ onChange,
119
+ dirty
120
+ }) {
121
+ const h = waarde ?? {};
122
+ const zet = (patch) => onChange({ ...h, ...patch });
123
+ return /* @__PURE__ */ jsxs(Card, { children: [
124
+ /* @__PURE__ */ jsx("h3", { className: "mb-1 text-base font-semibold", children: "Kop van de site" }),
125
+ /* @__PURE__ */ jsx("p", { className: "mb-1 text-xs text-slate-500", children: "Logo en de knop rechtsboven. Het menu zelf beheer je onder Menu." }),
126
+ /* @__PURE__ */ jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsx(VorigeTerugzetten, { siteId, sleutel: "header", dirty }) }),
127
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-4", children: [
128
+ /* @__PURE__ */ jsx(Field, { label: "Logo", hint: "Liefst een PNG of SVG met transparante achtergrond. Leeg = de naam van je site.", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
129
+ h.logo && // eslint-disable-next-line @next/next/no-img-element
130
+ /* @__PURE__ */ jsx("img", { src: h.logo, alt: "", className: "h-10 max-w-48 rounded-md border border-slate-200 bg-white object-contain p-1" }),
131
+ /* @__PURE__ */ jsx(MediaPickerButton, { siteId, label: h.logo ? "Ander logo" : "Kies een logo", onSelect: (m) => zet({ logo: m.url }) }),
132
+ h.logo && /* @__PURE__ */ jsx("button", { type: "button", className: "xicms-admin-btn rounded px-2 py-1 text-sm text-slate-600 hover:bg-slate-100", onClick: () => zet({ logo: void 0 }), children: "Weghalen" })
133
+ ] }) }),
134
+ h.logo && /* @__PURE__ */ jsx(Field, { label: "Hoogte van het logo", children: /* @__PURE__ */ jsx("div", { role: "radiogroup", "aria-label": "Hoogte van het logo", className: "inline-flex gap-1", children: [32, 40, 52, 64].map((px) => /* @__PURE__ */ jsx(
135
+ "button",
136
+ {
137
+ type: "button",
138
+ role: "radio",
139
+ "aria-checked": (h.logoHoogte ?? 40) === px,
140
+ onClick: () => zet({ logoHoogte: px }),
141
+ className: "xicms-admin-btn h-9 rounded-md border border-slate-200 px-3 text-sm aria-[checked=true]:border-slate-900 aria-[checked=true]:bg-slate-900 aria-[checked=true]:text-white",
142
+ children: px === 32 ? "Klein" : px === 40 ? "Normaal" : px === 52 ? "Groot" : "Extra groot"
143
+ },
144
+ px
145
+ )) }) }),
146
+ /* @__PURE__ */ jsxs("div", { className: "grid gap-3 md:grid-cols-2", children: [
147
+ /* @__PURE__ */ jsx(Field, { label: "Knoptekst rechtsboven", hint: "Bv. \u2018Afspraak maken\u2019 of \u2018Offerte aanvragen\u2019. Leeg = geen knop.", children: /* @__PURE__ */ jsx(Input, { value: h.cta?.label ?? "", maxLength: 40, onChange: (e) => zet({ cta: { label: e.target.value, href: h.cta?.href ?? "/contact" } }) }) }),
148
+ /* @__PURE__ */ jsx(Field, { label: "Waar gaat de knop heen?", children: /* @__PURE__ */ jsx(LinkVeld, { siteId, value: h.cta?.href, onChange: (href) => zet({ cta: { label: h.cta?.label ?? "", href } }) }) })
149
+ ] }),
150
+ /* @__PURE__ */ jsx(Switch, { checked: h.sticky !== false, onCheckedChange: (v) => zet({ sticky: v }), label: "Kop blijft bovenaan staan bij scrollen" }),
151
+ /* @__PURE__ */ jsx(Switch, { checked: Boolean(h.mobielBalk), onCheckedChange: (v) => zet({ mobielBalk: v }), label: "Op de telefoon een balk onderaan met \u201CBel ons\u201D en de knop" })
152
+ ] })
153
+ ] });
154
+ }
155
+ export {
156
+ BedrijfInstellingen,
157
+ KopInstellingen
158
+ };
159
+ //# sourceMappingURL=BedrijfInstellingen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/admin/settings/BedrijfInstellingen.tsx"],"sourcesContent":["\"use client\";\n\nimport type { Business, BusinessException } from \"../../schema/business\";\nimport { BEDRIJFSTYPES } from \"../../schema/business\";\nimport type { HeaderSettings } from \"../../schema/settings\";\nimport { Card, Field, Input, Textarea } from \"../ui/primitives\";\nimport { Select } from \"../ui/select\";\nimport { Switch } from \"../ui/switch\";\nimport { ArrayEditor } from \"../ui/ArrayEditor\";\nimport { LinkVeld } from \"../ui/LinkVeld\";\nimport { MediaPickerButton } from \"../media/MediaPicker\";\nimport { VorigeTerugzetten } from \"./VorigeTerugzetten\";\nimport { afwijkingDatumTekst, bedrijfsnummerAdvies } from \"../../bedrijf/bedrijf\";\n\n/**\n * Instellingen → Bedrijf (8.13): één plek voor adres, telefoon en openingstijden. De site gebruikt\n * dit voor Google (JSON-LD), het contact- en openingstijdenblok en de footer. Wie hier zijn\n * telefoonnummer wijzigt, wijzigt het overal.\n */\nexport function BedrijfInstellingen({\n siteId,\n waarde,\n onChange,\n dirty,\n}: {\n siteId: string;\n waarde: Business | undefined;\n onChange: (b: Business) => void;\n dirty: boolean;\n}) {\n const b = waarde ?? {};\n const zet = (patch: Partial<Business>) => onChange({ ...b, ...patch });\n const adres = b.address ?? {};\n return (\n <div className=\"grid gap-4\">\n <Card>\n <h3 className=\"mb-1 text-base font-semibold\">Bedrijf</h3>\n <p className=\"mb-1 text-xs text-slate-500\">\n Eén keer invullen, overal gebruikt: in Google, in het contact- en openingstijdenblok en onderaan je site.\n </p>\n <div className=\"mb-3\"><VorigeTerugzetten siteId={siteId} sleutel=\"business\" dirty={dirty} /></div>\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Soort bedrijf\" hint=\"Helpt Google te begrijpen wat je doet.\">\n <Select\n value={b.type ?? \"LocalBusiness\"}\n onValueChange={(v) => zet({ type: v })}\n options={BEDRIJFSTYPES.map((t) => ({ value: t.value, label: t.label }))}\n />\n </Field>\n <Field label=\"Officiële naam (optioneel)\" hint=\"Alleen als die afwijkt van de sitenaam, bv. met B.V.\">\n <Input value={b.name ?? \"\"} onChange={(e) => zet({ name: e.target.value || undefined })} />\n </Field>\n <Field label=\"Telefoonnummer\"><Input value={b.phone ?? \"\"} autoComplete=\"tel\" onChange={(e) => zet({ phone: e.target.value || undefined })} placeholder=\"030 – 123 45 67\" /></Field>\n <Field label=\"E-mailadres\"><Input value={b.email ?? \"\"} autoComplete=\"email\" onChange={(e) => zet({ email: e.target.value || undefined })} placeholder=\"info@…\" /></Field>\n <Field label=\"WhatsApp (optioneel)\" hint=\"Internationaal, bv. +31 6 12345678.\">\n <Input value={b.whatsapp ?? \"\"} onChange={(e) => zet({ whatsapp: e.target.value || undefined })} />\n </Field>\n <Field\n label=\"KvK-nummer\"\n hint={bedrijfsnummerAdvies(\"kvk\", b.kvk) ?? \"Verplicht om op je site te vermelden; het verschijnt onderaan je site en bij contact.\"}\n >\n <Input value={b.kvk ?? \"\"} onChange={(e) => zet({ kvk: e.target.value || undefined })} placeholder=\"12345678\" />\n </Field>\n <Field\n label=\"Btw-nummer\"\n hint={bedrijfsnummerAdvies(\"vat\", b.vat) ?? \"Verplicht als je aan consumenten verkoopt. Komt ook op je facturen.\"}\n >\n <Input value={b.vat ?? \"\"} onChange={(e) => zet({ vat: e.target.value.toUpperCase() || undefined })} placeholder=\"NL123456789B01\" />\n </Field>\n </div>\n <div className=\"mt-3\">\n <Field label=\"Korte omschrijving\" hint=\"Eén of twee zinnen over wat je doet — voor Google.\">\n <Textarea rows={2} value={b.description ?? \"\"} onChange={(e) => zet({ description: e.target.value || undefined })} />\n </Field>\n </div>\n </Card>\n\n <Card>\n <h3 className=\"mb-3 text-base font-semibold\">Adres</h3>\n <div className=\"grid gap-3 md:grid-cols-[2fr_1fr_1.5fr]\">\n <Field label=\"Straat en huisnummer\"><Input value={adres.street ?? \"\"} autoComplete=\"street-address\" onChange={(e) => zet({ address: { ...adres, street: e.target.value || undefined } })} /></Field>\n <Field label=\"Postcode\"><Input value={adres.postalCode ?? \"\"} autoComplete=\"postal-code\" onChange={(e) => zet({ address: { ...adres, postalCode: e.target.value || undefined } })} /></Field>\n <Field label=\"Plaats\"><Input value={adres.city ?? \"\"} autoComplete=\"address-level2\" onChange={(e) => zet({ address: { ...adres, city: e.target.value || undefined } })} /></Field>\n </div>\n <p className=\"mt-2 text-xs text-slate-500\">Bezoekers krijgen een knop “Route plannen” naar dit adres.</p>\n </Card>\n\n <Card>\n <h3 className=\"mb-1 text-base font-semibold\">Openingstijden</h3>\n <p className=\"mb-3 text-xs text-slate-500\">\n Gewone taal mag: “Maandag t/m vrijdag” · “09:00 – 17:00”, of “Zondag” · “Gesloten”. Dan klopt ook “Nu geopend” op je site.\n </p>\n <ArrayEditor\n items={b.hours ?? []}\n onChange={(hours) => zet({ hours })}\n newItem={() => ({ day: \"\", hours: \"\" })}\n addLabel=\"+ Regel\"\n emptyLabel=\"Nog geen openingstijden.\"\n renderRow={(r, update) => (\n <div className=\"grid grid-cols-2 gap-2\">\n <Input value={r.day} placeholder=\"Maandag t/m vrijdag\" onChange={(e) => update({ day: e.target.value })} aria-label=\"Dag(en)\" />\n <Input value={r.hours} placeholder=\"09:00 – 17:00\" onChange={(e) => update({ hours: e.target.value })} aria-label=\"Tijden\" />\n </div>\n )}\n />\n <div className=\"mt-3\">\n <Field label=\"Toelichting (optioneel)\"><Input value={b.hoursNote ?? \"\"} placeholder=\"Op afspraak ook 's avonds\" onChange={(e) => zet({ hoursNote: e.target.value || undefined })} /></Field>\n </div>\n </Card>\n\n <Card>\n <h3 className=\"mb-1 text-base font-semibold\">Afwijkende dagen</h3>\n <p className=\"mb-3 text-xs text-slate-500\">\n Feestdagen, vakantie, een koopavond. Ze staan op je site zodra ze binnen drie weken vallen, en Google toont ze als aangepaste tijden.\n </p>\n <ArrayEditor<BusinessException>\n items={b.exceptions ?? []}\n onChange={(exceptions) => zet({ exceptions })}\n newItem={() => ({ date: new Date().toISOString().slice(0, 10), hours: \"Gesloten\" })}\n addLabel=\"+ Afwijkende dag\"\n emptyLabel=\"Geen afwijkende dagen.\"\n renderRow={(a, update) => (\n <div className=\"grid gap-2 md:grid-cols-[auto_auto_1fr_1fr]\">\n <Field label=\"Van\"><Input type=\"date\" value={a.date} onChange={(e) => update({ date: e.target.value })} /></Field>\n <Field label=\"Tot en met (optioneel)\"><Input type=\"date\" value={a.until ?? \"\"} onChange={(e) => update({ until: e.target.value || undefined })} /></Field>\n <Field label=\"Tijden\"><Input value={a.hours} placeholder=\"Gesloten of 10:00 – 14:00\" onChange={(e) => update({ hours: e.target.value })} /></Field>\n <Field label=\"Omschrijving\" hint={/^\\d{4}-\\d{2}-\\d{2}$/.test(a.date) ? afwijkingDatumTekst(a) : undefined}>\n <Input value={a.label ?? \"\"} placeholder=\"Eerste Kerstdag\" onChange={(e) => update({ label: e.target.value || undefined })} />\n </Field>\n </div>\n )}\n />\n </Card>\n\n <Card>\n <h3 className=\"mb-3 text-base font-semibold\">Reviews en profielen</h3>\n <div className=\"grid gap-3\">\n <Field label=\"Link om een review achter te laten\" hint=\"Je Google-bedrijfsprofiel → ‘Vraag om reviews’. Het reviewblok kan er een knop ‘Beoordeel ons’ van maken.\">\n <Input value={b.reviewUrl ?? \"\"} placeholder=\"https://g.page/r/…\" onChange={(e) => zet({ reviewUrl: e.target.value || undefined })} />\n </Field>\n <Field label=\"Prijsklasse (optioneel)\" hint=\"Bv. €€ of € 25 – € 45.\">\n <Input value={b.priceRange ?? \"\"} onChange={(e) => zet({ priceRange: e.target.value || undefined })} />\n </Field>\n </div>\n </Card>\n </div>\n );\n}\n\n/** Instellingen → Kop (8.13): logo en actieknop van `SiteHeader`. */\nexport function KopInstellingen({\n siteId,\n waarde,\n onChange,\n dirty,\n}: {\n siteId: string;\n waarde: HeaderSettings | undefined;\n onChange: (h: HeaderSettings) => void;\n dirty: boolean;\n}) {\n const h = waarde ?? {};\n const zet = (patch: Partial<HeaderSettings>) => onChange({ ...h, ...patch });\n return (\n <Card>\n <h3 className=\"mb-1 text-base font-semibold\">Kop van de site</h3>\n <p className=\"mb-1 text-xs text-slate-500\">Logo en de knop rechtsboven. Het menu zelf beheer je onder Menu.</p>\n <div className=\"mb-3\"><VorigeTerugzetten siteId={siteId} sleutel=\"header\" dirty={dirty} /></div>\n <div className=\"grid gap-4\">\n <Field label=\"Logo\" hint=\"Liefst een PNG of SVG met transparante achtergrond. Leeg = de naam van je site.\">\n <div className=\"flex flex-wrap items-center gap-3\">\n {h.logo && (\n // eslint-disable-next-line @next/next/no-img-element\n <img src={h.logo} alt=\"\" className=\"h-10 max-w-48 rounded-md border border-slate-200 bg-white object-contain p-1\" />\n )}\n <MediaPickerButton siteId={siteId} label={h.logo ? \"Ander logo\" : \"Kies een logo\"} onSelect={(m) => zet({ logo: m.url })} />\n {h.logo && (\n <button type=\"button\" className=\"xicms-admin-btn rounded px-2 py-1 text-sm text-slate-600 hover:bg-slate-100\" onClick={() => zet({ logo: undefined })}>\n Weghalen\n </button>\n )}\n </div>\n </Field>\n {h.logo && (\n <Field label=\"Hoogte van het logo\">\n <div role=\"radiogroup\" aria-label=\"Hoogte van het logo\" className=\"inline-flex gap-1\">\n {[32, 40, 52, 64].map((px) => (\n <button\n key={px}\n type=\"button\"\n role=\"radio\"\n aria-checked={(h.logoHoogte ?? 40) === px}\n onClick={() => zet({ logoHoogte: px })}\n className=\"xicms-admin-btn h-9 rounded-md border border-slate-200 px-3 text-sm aria-[checked=true]:border-slate-900 aria-[checked=true]:bg-slate-900 aria-[checked=true]:text-white\"\n >\n {px === 32 ? \"Klein\" : px === 40 ? \"Normaal\" : px === 52 ? \"Groot\" : \"Extra groot\"}\n </button>\n ))}\n </div>\n </Field>\n )}\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Knoptekst rechtsboven\" hint=\"Bv. ‘Afspraak maken’ of ‘Offerte aanvragen’. Leeg = geen knop.\">\n <Input value={h.cta?.label ?? \"\"} maxLength={40} onChange={(e) => zet({ cta: { label: e.target.value, href: h.cta?.href ?? \"/contact\" } })} />\n </Field>\n <Field label=\"Waar gaat de knop heen?\">\n <LinkVeld siteId={siteId} value={h.cta?.href} onChange={(href) => zet({ cta: { label: h.cta?.label ?? \"\", href } })} />\n </Field>\n </div>\n <Switch checked={h.sticky !== false} onCheckedChange={(v) => zet({ sticky: v })} label=\"Kop blijft bovenaan staan bij scrollen\" />\n <Switch checked={Boolean(h.mobielBalk)} onCheckedChange={(v) => zet({ mobielBalk: v })} label=\"Op de telefoon een balk onderaan met “Bel ons” en de knop\" />\n </div>\n </Card>\n );\n}\n"],"mappings":"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","names":[]}
@@ -23,9 +23,10 @@ function MailTemplates({ siteId, keys }) {
23
23
  useEffect(() => {
24
24
  const db = getDb();
25
25
  if (!db) return;
26
- void getDoc(doc(db, "sites", siteId, "settings", "mailTemplates")).then(
27
- (snap) => setTemplates(snap.data() ?? {})
28
- );
26
+ void getDoc(doc(db, "sites", siteId, "settings", "mailTemplates")).then((snap) => setTemplates(snap.data() ?? {})).catch((e) => {
27
+ console.warn("[xicms] mailteksten niet geladen:", e.message);
28
+ setTemplates({});
29
+ });
29
30
  }, [siteId]);
30
31
  async function save() {
31
32
  const db = getDb();
@@ -85,7 +86,7 @@ function MailTemplates({ siteId, keys }) {
85
86
  ] })
86
87
  ] }, key);
87
88
  }),
88
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { onClick: save, disabled: busy !== null, children: busy === "save" ? "Opslaan\u2026" : "E-mailteksten opslaan" }) })
89
+ /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { loading: busy === "save", onClick: save, disabled: busy !== null, children: "E-mailteksten opslaan" }) })
89
90
  ] });
90
91
  }
91
92
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/admin/settings/MailTemplates.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { doc, getDoc, setDoc } from \"firebase/firestore\";\nimport { callable } from \"../../firebase/functionsClient\";\nimport { getDb, getFirebaseApp } from \"../../firebase/client\";\nimport { MAIL_TEMPLATE_DEFS, type MailTemplateKey, type MailTemplates as MailTemplatesData } from \"../../schema/mail\";\nimport { Button, Card, Field, Input, Textarea } from \"../ui/primitives\";\nimport { useToast } from \"../ui/toast\";\n\ntype MailTemplatesProps = {\n siteId: string;\n /** Welke templates tonen — bv. FORM_TEMPLATE_KEYS in Formulieren, SHOP_TEMPLATE_KEYS in de shop. */\n keys?: readonly MailTemplateKey[];\n};\n\n/** Generieke callable-helper (niet shop-gebonden) — mail is een site-brede instelling. */\nfunction callFunction<TIn, TOut>(name: string) {\n return async (data: TIn): Promise<TOut> => {\n const app = getFirebaseApp();\n if (!app) throw new Error(\"Firebase niet beschikbaar.\");\n const fn = callable(app, name);\n const res = await fn(data as Record<string, unknown>);\n return res.data as TOut;\n };\n}\n\n/**\n * E-mailteksten — bewerkbare templates in `settings/mailTemplates` (site-breed, siteadmin). Een\n * leeg veld gebruikt de ingebouwde standaardtekst, dus er gaat altijd een correcte mail uit. Je\n * bewerkt platte tekst met {{invulvelden}}; de engine verpakt die in je huisstijl (kleur, logo,\n * footer) en stuurt een nette HTML-mail. Shop-templates verschijnen alleen op sites met webwinkel.\n */\nexport function MailTemplates({ siteId, keys }: MailTemplatesProps) {\n const { toast } = useToast();\n const [templates, setTemplates] = useState<MailTemplatesData | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n\n useEffect(() => {\n const db = getDb();\n if (!db) return;\n void getDoc(doc(db, \"sites\", siteId, \"settings\", \"mailTemplates\")).then((snap) =>\n setTemplates((snap.data() as MailTemplatesData | undefined) ?? {}),\n );\n }, [siteId]);\n\n async function save() {\n const db = getDb();\n if (!db || !templates) return;\n setBusy(\"save\");\n try {\n await setDoc(doc(db, \"sites\", siteId, \"settings\", \"mailTemplates\"), templates);\n toast({ title: \"E-mailteksten opgeslagen\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Opslaan mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n async function preview(key: MailTemplateKey) {\n setBusy(key);\n try {\n const res = await callFunction<{ siteId: string; template: MailTemplateKey }, { to: string }>(\"sendTemplatePreview\")({\n siteId,\n template: key,\n });\n toast({ title: \"Voorbeeld verstuurd\", description: `Naar ${res.to} (met voorbeeldgegevens en je huisstijl).`, tone: \"success\" });\n } catch (e) {\n toast({ title: \"Voorbeeld mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n if (!templates) return <p className=\"text-sm text-slate-500\">E-mailteksten laden…</p>;\n\n const defs = keys ? MAIL_TEMPLATE_DEFS.filter((d) => keys.includes(d.key as MailTemplateKey)) : MAIL_TEMPLATE_DEFS;\n\n return (\n <div className=\"grid gap-4\">\n <p className=\"text-sm text-slate-600\">\n Laat een veld leeg voor de standaardtekst. De opmaak (huisstijlkleur, logo, footer) zet de engine er\n automatisch omheen — je bewerkt alleen de tekst. Gebruik de {\"{{invulvelden}}\"} die per e-mail staan vermeld.\n </p>\n\n {defs.map((def) => {\n const key = def.key as MailTemplateKey;\n const tpl = templates[key] ?? {};\n const set = (patch: { subject?: string; bodyText?: string }) =>\n setTemplates((p) => ({ ...p, [key]: { ...p?.[key], ...patch } }));\n return (\n <Card key={key}>\n <div className=\"mb-2 flex items-start justify-between gap-3\">\n <div>\n <h4 className=\"text-sm font-semibold\">{def.label}</h4>\n <p className=\"text-xs text-slate-500\">{def.hint}</p>\n </div>\n <Button size=\"sm\" variant=\"secondary\" disabled={busy !== null} onClick={() => preview(key)}>\n {busy === key ? \"Versturen…\" : \"Stuur voorbeeld naar mij\"}\n </Button>\n </div>\n <div className=\"grid gap-3\">\n <Field label=\"Onderwerp\" hint=\"Leeg = standaard\">\n <Input value={tpl.subject ?? \"\"} onChange={(e) => set({ subject: e.target.value })} />\n </Field>\n <Field label=\"Tekst\" hint=\"Leeg = standaard\">\n <Textarea rows={6} value={tpl.bodyText ?? \"\"} onChange={(e) => set({ bodyText: e.target.value })} />\n </Field>\n <p className=\"text-xs text-slate-500\">\n Invulvelden:{\" \"}\n <code className=\"rounded bg-slate-100 px-1 py-0.5 text-[11px]\">{def.placeholders}</code>\n </p>\n </div>\n </Card>\n );\n })}\n\n <div>\n <Button onClick={save} disabled={busy !== null}>\n {busy === \"save\" ? \"Opslaan…\" : \"E-mailteksten opslaan\"}\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/admin/settings/MailTemplates.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { doc, getDoc, setDoc } from \"firebase/firestore\";\nimport { callable } from \"../../firebase/functionsClient\";\nimport { getDb, getFirebaseApp } from \"../../firebase/client\";\nimport { MAIL_TEMPLATE_DEFS, type MailTemplateKey, type MailTemplates as MailTemplatesData } from \"../../schema/mail\";\nimport { Button, Card, Field, Input, Textarea } from \"../ui/primitives\";\nimport { useToast } from \"../ui/toast\";\n\ntype MailTemplatesProps = {\n siteId: string;\n /** Welke templates tonen — bv. FORM_TEMPLATE_KEYS in Formulieren, SHOP_TEMPLATE_KEYS in de shop. */\n keys?: readonly MailTemplateKey[];\n};\n\n/** Generieke callable-helper (niet shop-gebonden) — mail is een site-brede instelling. */\nfunction callFunction<TIn, TOut>(name: string) {\n return async (data: TIn): Promise<TOut> => {\n const app = getFirebaseApp();\n if (!app) throw new Error(\"Firebase niet beschikbaar.\");\n const fn = callable(app, name);\n const res = await fn(data as Record<string, unknown>);\n return res.data as TOut;\n };\n}\n\n/**\n * E-mailteksten — bewerkbare templates in `settings/mailTemplates` (site-breed, siteadmin). Een\n * leeg veld gebruikt de ingebouwde standaardtekst, dus er gaat altijd een correcte mail uit. Je\n * bewerkt platte tekst met {{invulvelden}}; de engine verpakt die in je huisstijl (kleur, logo,\n * footer) en stuurt een nette HTML-mail. Shop-templates verschijnen alleen op sites met webwinkel.\n */\nexport function MailTemplates({ siteId, keys }: MailTemplatesProps) {\n const { toast } = useToast();\n const [templates, setTemplates] = useState<MailTemplatesData | null>(null);\n const [busy, setBusy] = useState<string | null>(null);\n\n useEffect(() => {\n const db = getDb();\n if (!db) return;\n void getDoc(doc(db, \"sites\", siteId, \"settings\", \"mailTemplates\"))\n .then((snap) => setTemplates((snap.data() as MailTemplatesData | undefined) ?? {}))\n // 8.2: zonder catch een ongevangen fout (o.a. in de demo, zonder database). De standaard-\n // teksten blijven dan staan, en die werken.\n .catch((e) => {\n console.warn(\"[xicms] mailteksten niet geladen:\", (e as Error).message);\n setTemplates({});\n });\n }, [siteId]);\n\n async function save() {\n const db = getDb();\n if (!db || !templates) return;\n setBusy(\"save\");\n try {\n await setDoc(doc(db, \"sites\", siteId, \"settings\", \"mailTemplates\"), templates);\n toast({ title: \"E-mailteksten opgeslagen\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Opslaan mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n async function preview(key: MailTemplateKey) {\n setBusy(key);\n try {\n const res = await callFunction<{ siteId: string; template: MailTemplateKey }, { to: string }>(\"sendTemplatePreview\")({\n siteId,\n template: key,\n });\n toast({ title: \"Voorbeeld verstuurd\", description: `Naar ${res.to} (met voorbeeldgegevens en je huisstijl).`, tone: \"success\" });\n } catch (e) {\n toast({ title: \"Voorbeeld mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(null);\n }\n }\n\n if (!templates) return <p className=\"text-sm text-slate-500\">E-mailteksten laden…</p>;\n\n const defs = keys ? MAIL_TEMPLATE_DEFS.filter((d) => keys.includes(d.key as MailTemplateKey)) : MAIL_TEMPLATE_DEFS;\n\n return (\n <div className=\"grid gap-4\">\n <p className=\"text-sm text-slate-600\">\n Laat een veld leeg voor de standaardtekst. De opmaak (huisstijlkleur, logo, footer) zet de engine er\n automatisch omheen — je bewerkt alleen de tekst. Gebruik de {\"{{invulvelden}}\"} die per e-mail staan vermeld.\n </p>\n\n {defs.map((def) => {\n const key = def.key as MailTemplateKey;\n const tpl = templates[key] ?? {};\n const set = (patch: { subject?: string; bodyText?: string }) =>\n setTemplates((p) => ({ ...p, [key]: { ...p?.[key], ...patch } }));\n return (\n <Card key={key}>\n <div className=\"mb-2 flex items-start justify-between gap-3\">\n <div>\n <h4 className=\"text-sm font-semibold\">{def.label}</h4>\n <p className=\"text-xs text-slate-500\">{def.hint}</p>\n </div>\n <Button size=\"sm\" variant=\"secondary\" disabled={busy !== null} onClick={() => preview(key)}>\n {busy === key ? \"Versturen…\" : \"Stuur voorbeeld naar mij\"}\n </Button>\n </div>\n <div className=\"grid gap-3\">\n <Field label=\"Onderwerp\" hint=\"Leeg = standaard\">\n <Input value={tpl.subject ?? \"\"} onChange={(e) => set({ subject: e.target.value })} />\n </Field>\n <Field label=\"Tekst\" hint=\"Leeg = standaard\">\n <Textarea rows={6} value={tpl.bodyText ?? \"\"} onChange={(e) => set({ bodyText: e.target.value })} />\n </Field>\n <p className=\"text-xs text-slate-500\">\n Invulvelden:{\" \"}\n <code className=\"rounded bg-slate-100 px-1 py-0.5 text-[11px]\">{def.placeholders}</code>\n </p>\n </div>\n </Card>\n );\n })}\n\n <div>\n <Button loading={busy === \"save\"} onClick={save} disabled={busy !== null}>\n {\"E-mailteksten opslaan\"}\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}