@xiwebdesign/xicms-core 7.14.0 → 7.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 (263) hide show
  1. package/dist/admin/AdminApp.js +4 -3
  2. package/dist/admin/AdminApp.js.map +1 -1
  3. package/dist/admin/dashboard/DashboardPanel.d.ts +3 -0
  4. package/dist/admin/dashboard/DashboardPanel.js +316 -0
  5. package/dist/admin/dashboard/DashboardPanel.js.map +1 -0
  6. package/dist/admin/navContext.d.ts +14 -0
  7. package/dist/admin/navContext.js +12 -0
  8. package/dist/admin/navContext.js.map +1 -0
  9. package/dist/admin/pages/PagesPanel.js +38 -12
  10. package/dist/admin/pages/PagesPanel.js.map +1 -1
  11. package/dist/admin/panelRegistry.js +4 -0
  12. package/dist/admin/panelRegistry.js.map +1 -1
  13. package/dist/admin/ui/PanelIcon.js +5 -0
  14. package/dist/admin/ui/PanelIcon.js.map +1 -1
  15. package/dist/admin/visual/VisualEditor.js +56 -20
  16. package/dist/admin/visual/VisualEditor.js.map +1 -1
  17. package/dist/admin.css +1 -1
  18. package/dist/auth/AuthProvider.js +8 -1
  19. package/dist/auth/AuthProvider.js.map +1 -1
  20. package/dist/blocks/builtins/Accordion.d.ts +1 -2
  21. package/dist/blocks/builtins/Accordion.js +2 -39
  22. package/dist/blocks/builtins/Accordion.js.map +1 -1
  23. package/dist/blocks/builtins/AccordionRender.d.ts +7 -0
  24. package/dist/blocks/builtins/AccordionRender.js +42 -0
  25. package/dist/blocks/builtins/AccordionRender.js.map +1 -0
  26. package/dist/blocks/builtins/Agenda.d.ts +1 -29
  27. package/dist/blocks/builtins/Agenda.js +3 -94
  28. package/dist/blocks/builtins/Agenda.js.map +1 -1
  29. package/dist/blocks/builtins/AgendaRender.d.ts +34 -0
  30. package/dist/blocks/builtins/AgendaRender.js +96 -0
  31. package/dist/blocks/builtins/AgendaRender.js.map +1 -0
  32. package/dist/blocks/builtins/Banner.d.ts +1 -2
  33. package/dist/blocks/builtins/Banner.js +2 -32
  34. package/dist/blocks/builtins/Banner.js.map +1 -1
  35. package/dist/blocks/builtins/BannerRender.d.ts +11 -0
  36. package/dist/blocks/builtins/BannerRender.js +35 -0
  37. package/dist/blocks/builtins/BannerRender.js.map +1 -0
  38. package/dist/blocks/builtins/BeforeAfter.d.ts +1 -2
  39. package/dist/blocks/builtins/BeforeAfter.js +2 -31
  40. package/dist/blocks/builtins/BeforeAfter.js.map +1 -1
  41. package/dist/blocks/builtins/BeforeAfterRender.d.ts +11 -0
  42. package/dist/blocks/builtins/BeforeAfterRender.js +34 -0
  43. package/dist/blocks/builtins/BeforeAfterRender.js.map +1 -0
  44. package/dist/blocks/builtins/Booking.d.ts +1 -2
  45. package/dist/blocks/builtins/Booking.js +2 -14
  46. package/dist/blocks/builtins/Booking.js.map +1 -1
  47. package/dist/blocks/builtins/BookingRender.d.ts +8 -0
  48. package/dist/blocks/builtins/BookingRender.js +17 -0
  49. package/dist/blocks/builtins/BookingRender.js.map +1 -0
  50. package/dist/blocks/builtins/Breadcrumbs.d.ts +1 -10
  51. package/dist/blocks/builtins/Breadcrumbs.js +3 -69
  52. package/dist/blocks/builtins/Breadcrumbs.js.map +1 -1
  53. package/dist/blocks/builtins/BreadcrumbsRender.d.ts +18 -0
  54. package/dist/blocks/builtins/BreadcrumbsRender.js +71 -0
  55. package/dist/blocks/builtins/BreadcrumbsRender.js.map +1 -0
  56. package/dist/blocks/builtins/Cards.d.ts +1 -2
  57. package/dist/blocks/builtins/Cards.js +2 -74
  58. package/dist/blocks/builtins/Cards.js.map +1 -1
  59. package/dist/blocks/builtins/CardsRender.d.ts +7 -0
  60. package/dist/blocks/builtins/CardsRender.js +77 -0
  61. package/dist/blocks/builtins/CardsRender.js.map +1 -0
  62. package/dist/blocks/builtins/Columns.d.ts +1 -2
  63. package/dist/blocks/builtins/Columns.js +2 -9
  64. package/dist/blocks/builtins/Columns.js.map +1 -1
  65. package/dist/blocks/builtins/ColumnsRender.d.ts +6 -0
  66. package/dist/blocks/builtins/ColumnsRender.js +12 -0
  67. package/dist/blocks/builtins/ColumnsRender.js.map +1 -0
  68. package/dist/blocks/builtins/Contact.d.ts +2 -7
  69. package/dist/blocks/builtins/Contact.js +3 -102
  70. package/dist/blocks/builtins/Contact.js.map +1 -1
  71. package/dist/blocks/builtins/ContactRender.d.ts +9 -0
  72. package/dist/blocks/builtins/ContactRender.js +105 -0
  73. package/dist/blocks/builtins/ContactRender.js.map +1 -0
  74. package/dist/blocks/builtins/Countdown.d.ts +1 -18
  75. package/dist/blocks/builtins/Countdown.js +3 -53
  76. package/dist/blocks/builtins/Countdown.js.map +1 -1
  77. package/dist/blocks/builtins/CountdownRender.d.ts +22 -0
  78. package/dist/blocks/builtins/CountdownRender.js +61 -0
  79. package/dist/blocks/builtins/CountdownRender.js.map +1 -0
  80. package/dist/blocks/builtins/Cta.d.ts +1 -2
  81. package/dist/blocks/builtins/Cta.js +2 -39
  82. package/dist/blocks/builtins/Cta.js.map +1 -1
  83. package/dist/blocks/builtins/CtaRender.d.ts +6 -0
  84. package/dist/blocks/builtins/CtaRender.js +42 -0
  85. package/dist/blocks/builtins/CtaRender.js.map +1 -0
  86. package/dist/blocks/builtins/Downloads.d.ts +1 -2
  87. package/dist/blocks/builtins/Downloads.js +2 -16
  88. package/dist/blocks/builtins/Downloads.js.map +1 -1
  89. package/dist/blocks/builtins/DownloadsRender.d.ts +7 -0
  90. package/dist/blocks/builtins/DownloadsRender.js +19 -0
  91. package/dist/blocks/builtins/DownloadsRender.js.map +1 -0
  92. package/dist/blocks/builtins/Elements.d.ts +3 -4
  93. package/dist/blocks/builtins/Elements.js +4 -38
  94. package/dist/blocks/builtins/Elements.js.map +1 -1
  95. package/dist/blocks/builtins/ElementsRender.d.ts +10 -0
  96. package/dist/blocks/builtins/ElementsRender.js +41 -0
  97. package/dist/blocks/builtins/ElementsRender.js.map +1 -0
  98. package/dist/blocks/builtins/Embed.d.ts +1 -2
  99. package/dist/blocks/builtins/Embed.js +2 -19
  100. package/dist/blocks/builtins/Embed.js.map +1 -1
  101. package/dist/blocks/builtins/EmbedRender.d.ts +7 -0
  102. package/dist/blocks/builtins/EmbedRender.js +22 -0
  103. package/dist/blocks/builtins/EmbedRender.js.map +1 -0
  104. package/dist/blocks/builtins/Faq.d.ts +1 -6
  105. package/dist/blocks/builtins/Faq.js +3 -103
  106. package/dist/blocks/builtins/Faq.js.map +1 -1
  107. package/dist/blocks/builtins/FaqRender.d.ts +10 -0
  108. package/dist/blocks/builtins/FaqRender.js +105 -0
  109. package/dist/blocks/builtins/FaqRender.js.map +1 -0
  110. package/dist/blocks/builtins/FormBlock.d.ts +1 -2
  111. package/dist/blocks/builtins/FormBlock.js +2 -222
  112. package/dist/blocks/builtins/FormBlock.js.map +1 -1
  113. package/dist/blocks/builtins/FormBlockRender.d.ts +6 -0
  114. package/dist/blocks/builtins/FormBlockRender.js +225 -0
  115. package/dist/blocks/builtins/FormBlockRender.js.map +1 -0
  116. package/dist/blocks/builtins/Gallery.d.ts +1 -23
  117. package/dist/blocks/builtins/Gallery.js +2 -164
  118. package/dist/blocks/builtins/Gallery.js.map +1 -1
  119. package/dist/blocks/builtins/GalleryRender.d.ts +25 -0
  120. package/dist/blocks/builtins/GalleryRender.js +167 -0
  121. package/dist/blocks/builtins/GalleryRender.js.map +1 -0
  122. package/dist/blocks/builtins/Hero.d.ts +1 -2
  123. package/dist/blocks/builtins/Hero.js +2 -73
  124. package/dist/blocks/builtins/Hero.js.map +1 -1
  125. package/dist/blocks/builtins/HeroRender.d.ts +6 -0
  126. package/dist/blocks/builtins/HeroRender.js +76 -0
  127. package/dist/blocks/builtins/HeroRender.js.map +1 -0
  128. package/dist/blocks/builtins/ImageBlock.d.ts +1 -2
  129. package/dist/blocks/builtins/ImageBlock.js +2 -22
  130. package/dist/blocks/builtins/ImageBlock.js.map +1 -1
  131. package/dist/blocks/builtins/ImageBlockRender.d.ts +6 -0
  132. package/dist/blocks/builtins/ImageBlockRender.js +25 -0
  133. package/dist/blocks/builtins/ImageBlockRender.js.map +1 -0
  134. package/dist/blocks/builtins/Jobs.d.ts +1 -15
  135. package/dist/blocks/builtins/Jobs.js +3 -69
  136. package/dist/blocks/builtins/Jobs.js.map +1 -1
  137. package/dist/blocks/builtins/JobsRender.d.ts +17 -0
  138. package/dist/blocks/builtins/JobsRender.js +71 -0
  139. package/dist/blocks/builtins/JobsRender.js.map +1 -0
  140. package/dist/blocks/builtins/Layout.d.ts +2 -3
  141. package/dist/blocks/builtins/Layout.js +3 -39
  142. package/dist/blocks/builtins/Layout.js.map +1 -1
  143. package/dist/blocks/builtins/LayoutRender.d.ts +8 -0
  144. package/dist/blocks/builtins/LayoutRender.js +42 -0
  145. package/dist/blocks/builtins/LayoutRender.js.map +1 -0
  146. package/dist/blocks/builtins/MapBlock.d.ts +1 -2
  147. package/dist/blocks/builtins/MapBlock.js +2 -45
  148. package/dist/blocks/builtins/MapBlock.js.map +1 -1
  149. package/dist/blocks/builtins/MapBlockRender.d.ts +6 -0
  150. package/dist/blocks/builtins/MapBlockRender.js +48 -0
  151. package/dist/blocks/builtins/MapBlockRender.js.map +1 -0
  152. package/dist/blocks/builtins/NewsListBlock.d.ts +1 -2
  153. package/dist/blocks/builtins/NewsListBlock.js +2 -11
  154. package/dist/blocks/builtins/NewsListBlock.js.map +1 -1
  155. package/dist/blocks/builtins/NewsListBlockRender.d.ts +6 -0
  156. package/dist/blocks/builtins/NewsListBlockRender.js +14 -0
  157. package/dist/blocks/builtins/NewsListBlockRender.js.map +1 -0
  158. package/dist/blocks/builtins/Newsletter.d.ts +1 -2
  159. package/dist/blocks/builtins/Newsletter.js +2 -89
  160. package/dist/blocks/builtins/Newsletter.js.map +1 -1
  161. package/dist/blocks/builtins/NewsletterRender.d.ts +13 -0
  162. package/dist/blocks/builtins/NewsletterRender.js +92 -0
  163. package/dist/blocks/builtins/NewsletterRender.js.map +1 -0
  164. package/dist/blocks/builtins/OpeningHours.d.ts +1 -2
  165. package/dist/blocks/builtins/OpeningHours.js +2 -28
  166. package/dist/blocks/builtins/OpeningHours.js.map +1 -1
  167. package/dist/blocks/builtins/OpeningHoursRender.d.ts +7 -0
  168. package/dist/blocks/builtins/OpeningHoursRender.js +31 -0
  169. package/dist/blocks/builtins/OpeningHoursRender.js.map +1 -0
  170. package/dist/blocks/builtins/PdfBlock.d.ts +1 -2
  171. package/dist/blocks/builtins/PdfBlock.js +2 -76
  172. package/dist/blocks/builtins/PdfBlock.js.map +1 -1
  173. package/dist/blocks/builtins/PdfBlockRender.d.ts +11 -0
  174. package/dist/blocks/builtins/PdfBlockRender.js +79 -0
  175. package/dist/blocks/builtins/PdfBlockRender.js.map +1 -0
  176. package/dist/blocks/builtins/Portfolio.d.ts +1 -2
  177. package/dist/blocks/builtins/Portfolio.js +2 -75
  178. package/dist/blocks/builtins/Portfolio.js.map +1 -1
  179. package/dist/blocks/builtins/PortfolioRender.d.ts +7 -0
  180. package/dist/blocks/builtins/PortfolioRender.js +78 -0
  181. package/dist/blocks/builtins/PortfolioRender.js.map +1 -0
  182. package/dist/blocks/builtins/Pricing.d.ts +1 -8
  183. package/dist/blocks/builtins/Pricing.js +3 -73
  184. package/dist/blocks/builtins/Pricing.js.map +1 -1
  185. package/dist/blocks/builtins/PricingRender.d.ts +10 -0
  186. package/dist/blocks/builtins/PricingRender.js +75 -0
  187. package/dist/blocks/builtins/PricingRender.js.map +1 -0
  188. package/dist/blocks/builtins/RichTextBlock.d.ts +1 -2
  189. package/dist/blocks/builtins/RichTextBlock.js +2 -5
  190. package/dist/blocks/builtins/RichTextBlock.js.map +1 -1
  191. package/dist/blocks/builtins/RichTextBlockRender.d.ts +6 -0
  192. package/dist/blocks/builtins/RichTextBlockRender.js +8 -0
  193. package/dist/blocks/builtins/RichTextBlockRender.js.map +1 -0
  194. package/dist/blocks/builtins/Search.d.ts +1 -2
  195. package/dist/blocks/builtins/Search.js +2 -80
  196. package/dist/blocks/builtins/Search.js.map +1 -1
  197. package/dist/blocks/builtins/SearchRender.d.ts +7 -0
  198. package/dist/blocks/builtins/SearchRender.js +83 -0
  199. package/dist/blocks/builtins/SearchRender.js.map +1 -0
  200. package/dist/blocks/builtins/Sections.d.ts +4 -5
  201. package/dist/blocks/builtins/Sections.js +5 -142
  202. package/dist/blocks/builtins/Sections.js.map +1 -1
  203. package/dist/blocks/builtins/SectionsRender.d.ts +12 -0
  204. package/dist/blocks/builtins/SectionsRender.js +145 -0
  205. package/dist/blocks/builtins/SectionsRender.js.map +1 -0
  206. package/dist/blocks/builtins/Slider.d.ts +1 -2
  207. package/dist/blocks/builtins/Slider.js +2 -134
  208. package/dist/blocks/builtins/Slider.js.map +1 -1
  209. package/dist/blocks/builtins/SliderRender.d.ts +7 -0
  210. package/dist/blocks/builtins/SliderRender.js +137 -0
  211. package/dist/blocks/builtins/SliderRender.js.map +1 -0
  212. package/dist/blocks/builtins/Spacer.d.ts +1 -2
  213. package/dist/blocks/builtins/Spacer.js +2 -6
  214. package/dist/blocks/builtins/Spacer.js.map +1 -1
  215. package/dist/blocks/builtins/SpacerRender.d.ts +6 -0
  216. package/dist/blocks/builtins/SpacerRender.js +9 -0
  217. package/dist/blocks/builtins/SpacerRender.js.map +1 -0
  218. package/dist/blocks/builtins/SymbolRef.d.ts +1 -2
  219. package/dist/blocks/builtins/SymbolRef.js +2 -76
  220. package/dist/blocks/builtins/SymbolRef.js.map +1 -1
  221. package/dist/blocks/builtins/SymbolRefRender.d.ts +13 -0
  222. package/dist/blocks/builtins/SymbolRefRender.js +79 -0
  223. package/dist/blocks/builtins/SymbolRefRender.js.map +1 -0
  224. package/dist/blocks/builtins/Team.d.ts +1 -2
  225. package/dist/blocks/builtins/Team.js +2 -55
  226. package/dist/blocks/builtins/Team.js.map +1 -1
  227. package/dist/blocks/builtins/TeamRender.d.ts +7 -0
  228. package/dist/blocks/builtins/TeamRender.js +58 -0
  229. package/dist/blocks/builtins/TeamRender.js.map +1 -0
  230. package/dist/blocks/builtins/Testimonials.d.ts +1 -8
  231. package/dist/blocks/builtins/Testimonials.js +2 -69
  232. package/dist/blocks/builtins/Testimonials.js.map +1 -1
  233. package/dist/blocks/builtins/TestimonialsRender.d.ts +10 -0
  234. package/dist/blocks/builtins/TestimonialsRender.js +72 -0
  235. package/dist/blocks/builtins/TestimonialsRender.js.map +1 -0
  236. package/dist/blocks/builtins/Video.d.ts +1 -9
  237. package/dist/blocks/builtins/Video.js +2 -64
  238. package/dist/blocks/builtins/Video.js.map +1 -1
  239. package/dist/blocks/builtins/VideoRender.d.ts +10 -0
  240. package/dist/blocks/builtins/VideoRender.js +67 -0
  241. package/dist/blocks/builtins/VideoRender.js.map +1 -0
  242. package/dist/blocks/builtins/WhatsappChat.d.ts +1 -8
  243. package/dist/blocks/builtins/WhatsappChat.js +2 -37
  244. package/dist/blocks/builtins/WhatsappChat.js.map +1 -1
  245. package/dist/blocks/builtins/WhatsappChatRender.d.ts +17 -0
  246. package/dist/blocks/builtins/WhatsappChatRender.js +40 -0
  247. package/dist/blocks/builtins/WhatsappChatRender.js.map +1 -0
  248. package/dist/blocks/builtins/Widgets.d.ts +12 -13
  249. package/dist/blocks/builtins/Widgets.js +13 -175
  250. package/dist/blocks/builtins/Widgets.js.map +1 -1
  251. package/dist/blocks/builtins/WidgetsRender.d.ts +34 -0
  252. package/dist/blocks/builtins/WidgetsRender.js +178 -0
  253. package/dist/blocks/builtins/WidgetsRender.js.map +1 -0
  254. package/dist/components/barOffset.js +1 -1
  255. package/dist/components/barOffset.js.map +1 -1
  256. package/dist/modules/contract.js +2 -1
  257. package/dist/modules/contract.js.map +1 -1
  258. package/dist/schema/settings.d.ts +4 -0
  259. package/dist/schema/settings.js +10 -1
  260. package/dist/schema/settings.js.map +1 -1
  261. package/dist/styles.css +93 -19
  262. package/dist/version.js +1 -1
  263. package/package.json +1 -1
@@ -0,0 +1,48 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { ConsentEmbed } from "./consentEmbed.js";
4
+ function osmSrc(block) {
5
+ if (block.lat != null && block.lng != null) {
6
+ const degPerTile = 360 / Math.pow(2, block.zoom);
7
+ const lngHalf = degPerTile * 1.25;
8
+ const latHalf = lngHalf * Math.cos(block.lat * Math.PI / 180) * 0.6;
9
+ const bbox = [block.lng - lngHalf, block.lat - latHalf, block.lng + lngHalf, block.lat + latHalf].join(",");
10
+ const marker = `${block.lat},${block.lng}`;
11
+ return `https://www.openstreetmap.org/export/embed.html?bbox=${encodeURIComponent(bbox)}&layer=mapnik&marker=${encodeURIComponent(marker)}`;
12
+ }
13
+ return null;
14
+ }
15
+ function MapRender({ block, mode }) {
16
+ const src = block.provider === "google" ? block.query || null : osmSrc(block);
17
+ if (!src) {
18
+ if (block.provider === "osm" && block.query) {
19
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
20
+ mode === "preview" && /* @__PURE__ */ jsx("p", { className: "xicms-ve__hint", children: "\u{1F5FA}\uFE0F Kaart: vul co\xF6rdinaten (lat/lng) in om de kaart te tonen \u2014 nu staat er een kaartlink." }),
21
+ /* @__PURE__ */ jsxs("p", { className: "xicms-map__fallback", children: [
22
+ "\u{1F4CD}",
23
+ " ",
24
+ /* @__PURE__ */ jsxs("a", { href: `https://www.openstreetmap.org/search?query=${encodeURIComponent(block.query)}`, target: "_blank", rel: "noopener noreferrer", children: [
25
+ "Bekijk ",
26
+ /* @__PURE__ */ jsx("span", { "data-xicms-edit": "query", children: block.query }),
27
+ " op de kaart"
28
+ ] })
29
+ ] })
30
+ ] });
31
+ }
32
+ return null;
33
+ }
34
+ return /* @__PURE__ */ jsx("div", { className: "xicms-map", style: { height: `${block.height}px` }, children: /* @__PURE__ */ jsx(ConsentEmbed, { gated: block.consentGated, preview: mode === "preview", label: "Kaart", children: /* @__PURE__ */ jsx(
35
+ "iframe",
36
+ {
37
+ src,
38
+ title: block.query ? `Kaart: ${block.query}` : "Kaart",
39
+ loading: "lazy",
40
+ style: { border: 0, width: "100%", height: "100%" },
41
+ referrerPolicy: "no-referrer-when-downgrade"
42
+ }
43
+ ) }) });
44
+ }
45
+ export {
46
+ MapRender
47
+ };
48
+ //# sourceMappingURL=MapBlockRender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/blocks/builtins/MapBlockRender.tsx"],"sourcesContent":["\"use client\";\n\nimport type { z } from \"zod\";\nimport type { MapBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { ConsentEmbed } from \"./consentEmbed\";\n\ntype MapBlk = z.infer<typeof MapBlockSchema>;\n\n/**\n * Bouwt de OSM-embed-URL. OSM's `export/embed.html` negeert een tekst-`q` en centreert puur op\n * `bbox`; zonder bbox toont het de HELE WERELD. Daarom: als er `lat`/`lng` zijn, berekenen we\n * deterministisch een echte bbox rond het punt (zoom → graden-span, cos(lat)-correctie zodat de\n * kaart niet vervormt) + een marker. Zonder coördinaten is er geen zinvolle embed — de render\n * toont dan een kaartlink op basis van `query` (beter dan de wereldkaart die het q=-pad gaf).\n */\nfunction osmSrc(block: MapBlk): string | null {\n if (block.lat != null && block.lng != null) {\n const degPerTile = 360 / Math.pow(2, block.zoom);\n const lngHalf = degPerTile * 1.25;\n const latHalf = lngHalf * Math.cos((block.lat * Math.PI) / 180) * 0.6;\n const bbox = [block.lng - lngHalf, block.lat - latHalf, block.lng + lngHalf, block.lat + latHalf].join(\",\");\n const marker = `${block.lat},${block.lng}`;\n return `https://www.openstreetmap.org/export/embed.html?bbox=${encodeURIComponent(bbox)}&layer=mapnik&marker=${encodeURIComponent(marker)}`;\n }\n return null;\n}\n\nexport function MapRender({ block, mode }: BlockRenderProps<MapBlk>) {\n const src = block.provider === \"google\" ? block.query || null : osmSrc(block);\n if (!src) {\n // OSM zonder coördinaten kán niet zinvol embedden (het legacy q=-pad toonde de wereldkaart).\n // Toon een duidelijke kaartlink i.p.v. een nutteloze kaart, en leg het in de editor uit.\n if (block.provider === \"osm\" && block.query) {\n // In de editor stond hier alleen de uitleg. Daardoor was de zoekterm — het enige wat de\n // bezoeker straks ziet — nergens aanklikbaar en dus niet inline te bewerken. Nu tonen we\n // de uitleg én de kaartlink zoals hij live wordt.\n return (\n <>\n {mode === \"preview\" && (\n <p className=\"xicms-ve__hint\">🗺️ Kaart: vul coördinaten (lat/lng) in om de kaart te tonen — nu staat er een kaartlink.</p>\n )}\n <p className=\"xicms-map__fallback\">\n 📍{\" \"}\n <a href={`https://www.openstreetmap.org/search?query=${encodeURIComponent(block.query)}`} target=\"_blank\" rel=\"noopener noreferrer\">\n Bekijk <span data-xicms-edit=\"query\">{block.query}</span> op de kaart\n </a>\n </p>\n </>\n );\n }\n return null;\n }\n return (\n <div className=\"xicms-map\" style={{ height: `${block.height}px` }}>\n <ConsentEmbed gated={block.consentGated} preview={mode === \"preview\"} label=\"Kaart\">\n <iframe\n src={src}\n title={block.query ? `Kaart: ${block.query}` : \"Kaart\"}\n loading=\"lazy\"\n style={{ border: 0, width: \"100%\", height: \"100%\" }}\n referrerPolicy=\"no-referrer-when-downgrade\"\n />\n </ConsentEmbed>\n </div>\n );\n}\n"],"mappings":";AAsCQ,mBAEI,KAIA,YANJ;AAjCR,SAAS,oBAAoB;AAW7B,SAAS,OAAO,OAA8B;AAC5C,MAAI,MAAM,OAAO,QAAQ,MAAM,OAAO,MAAM;AAC1C,UAAM,aAAa,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;AAC/C,UAAM,UAAU,aAAa;AAC7B,UAAM,UAAU,UAAU,KAAK,IAAK,MAAM,MAAM,KAAK,KAAM,GAAG,IAAI;AAClE,UAAM,OAAO,CAAC,MAAM,MAAM,SAAS,MAAM,MAAM,SAAS,MAAM,MAAM,SAAS,MAAM,MAAM,OAAO,EAAE,KAAK,GAAG;AAC1G,UAAM,SAAS,GAAG,MAAM,GAAG,IAAI,MAAM,GAAG;AACxC,WAAO,wDAAwD,mBAAmB,IAAI,CAAC,wBAAwB,mBAAmB,MAAM,CAAC;AAAA,EAC3I;AACA,SAAO;AACT;AAEO,SAAS,UAAU,EAAE,OAAO,KAAK,GAA6B;AACnE,QAAM,MAAM,MAAM,aAAa,WAAW,MAAM,SAAS,OAAO,OAAO,KAAK;AAC5E,MAAI,CAAC,KAAK;AAGR,QAAI,MAAM,aAAa,SAAS,MAAM,OAAO;AAI3C,aACE,iCACG;AAAA,iBAAS,aACR,oBAAC,OAAE,WAAU,kBAAiB,2HAAyF;AAAA,QAEzH,qBAAC,OAAE,WAAU,uBAAsB;AAAA;AAAA,UAC9B;AAAA,UACH,qBAAC,OAAE,MAAM,8CAA8C,mBAAmB,MAAM,KAAK,CAAC,IAAI,QAAO,UAAS,KAAI,uBAAsB;AAAA;AAAA,YAC3H,oBAAC,UAAK,mBAAgB,SAAS,gBAAM,OAAM;AAAA,YAAO;AAAA,aAC3D;AAAA,WACF;AAAA,SACF;AAAA,IAEJ;AACA,WAAO;AAAA,EACT;AACA,SACE,oBAAC,SAAI,WAAU,aAAY,OAAO,EAAE,QAAQ,GAAG,MAAM,MAAM,KAAK,GAC9D,8BAAC,gBAAa,OAAO,MAAM,cAAc,SAAS,SAAS,WAAW,OAAM,SAC1E;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO,MAAM,QAAQ,UAAU,MAAM,KAAK,KAAK;AAAA,MAC/C,SAAQ;AAAA,MACR,OAAO,EAAE,QAAQ,GAAG,OAAO,QAAQ,QAAQ,OAAO;AAAA,MAClD,gBAAe;AAAA;AAAA,EACjB,GACF,GACF;AAEJ;","names":[]}
@@ -1,2 +1 @@
1
- import type { z } from "zod";
2
- export declare const newsListBlock: import("../index.js").BlockDefinition<z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
1
+ export declare const newsListBlock: import("../index.js").BlockDefinition<import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>>;
@@ -1,17 +1,8 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import dynamic from "next/dynamic";
3
2
  import { defineBlock } from "../registry.js";
4
- import { Heading } from "../ui/index.js";
5
- import { NewsList } from "../../components/News.js";
6
- function NewsListRender({ block }) {
7
- return /* @__PURE__ */ jsxs("section", { className: "xicms-newslist", children: [
8
- block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
9
- /* @__PURE__ */ jsx(NewsList, { basePath: block.basePath, limit: block.limit, pageSize: block.pageSize })
10
- ] });
11
- }
12
3
  const newsListBlock = defineBlock({
13
4
  type: "newsList",
14
- Render: NewsListRender,
5
+ Render: dynamic(() => import("./NewsListBlockRender.js").then((m) => m.NewsListRender)),
15
6
  label: "Nieuwsoverzicht",
16
7
  icon: "\u{1F5DE}\uFE0F",
17
8
  defaults: () => ({ heading: "Laatste nieuws", limit: 6, basePath: "/nieuws" })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/builtins/NewsListBlock.tsx"],"sourcesContent":["\"use client\";\n\nimport type { z } from \"zod\";\nimport type { NewsListBlockSchema } from \"../../schema/blocks\";\nimport { defineBlock, type BlockRenderProps } from \"../registry\";\nimport { Heading } from \"../ui\";\nimport { NewsList } from \"../../components/News\";\n\ntype NewsListBlk = z.infer<typeof NewsListBlockSchema>;\n\nfunction NewsListRender({ block }: BlockRenderProps<NewsListBlk>) {\n return (\n <section className=\"xicms-newslist\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n <NewsList basePath={block.basePath} limit={block.limit} pageSize={block.pageSize} />\n </section>\n );\n}\n\nexport const newsListBlock = defineBlock({\n type: \"newsList\",\n Render: NewsListRender,\n label: \"Nieuwsoverzicht\",\n icon: \"🗞️\",\n defaults: () => ({ heading: \"Laatste nieuws\", limit: 6, basePath: \"/nieuws\" }),\n});\n"],"mappings":";AAYI,SACoB,KADpB;AARJ,SAAS,mBAA0C;AACnD,SAAS,eAAe;AACxB,SAAS,gBAAgB;AAIzB,SAAS,eAAe,EAAE,MAAM,GAAkC;AAChE,SACE,qBAAC,aAAQ,WAAU,kBAChB;AAAA,UAAM,WAAW,oBAAC,WAAQ,OAAO,GAAG,mBAAgB,WAAW,gBAAM,SAAQ;AAAA,IAC9E,oBAAC,YAAS,UAAU,MAAM,UAAU,OAAO,MAAM,OAAO,UAAU,MAAM,UAAU;AAAA,KACpF;AAEJ;AAEO,MAAM,gBAAgB,YAAY;AAAA,EACvC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,SAAS,kBAAkB,OAAO,GAAG,UAAU,UAAU;AAC9E,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/builtins/NewsListBlock.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const newsListBlock = defineBlock({\n type: \"newsList\",\n Render: dynamic(() => import(\"./NewsListBlockRender\").then((m) => m.NewsListRender)),\n label: \"Nieuwsoverzicht\",\n icon: \"🗞️\",\n defaults: () => ({ heading: \"Laatste nieuws\", limit: 6, basePath: \"/nieuws\" }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,gBAAgB,YAAY;AAAA,EACvC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,uBAAuB,EAAE,KAAK,CAAC,MAAM,EAAE,cAAc,CAAC;AAAA,EACnF,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,SAAS,kBAAkB,OAAO,GAAG,UAAU,UAAU;AAC9E,CAAC;","names":[]}
@@ -0,0 +1,6 @@
1
+ import type { z } from "zod";
2
+ import type { NewsListBlockSchema } from "../../schema/blocks.js";
3
+ import type { BlockRenderProps } from "../registry.js";
4
+ type NewsListBlk = z.infer<typeof NewsListBlockSchema>;
5
+ export declare function NewsListRender({ block }: BlockRenderProps<NewsListBlk>): import("react").JSX.Element;
6
+ export {};
@@ -0,0 +1,14 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { Heading } from "../ui/index.js";
4
+ import { NewsList } from "../../components/News.js";
5
+ function NewsListRender({ block }) {
6
+ return /* @__PURE__ */ jsxs("section", { className: "xicms-newslist", children: [
7
+ block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
8
+ /* @__PURE__ */ jsx(NewsList, { basePath: block.basePath, limit: block.limit, pageSize: block.pageSize })
9
+ ] });
10
+ }
11
+ export {
12
+ NewsListRender
13
+ };
14
+ //# sourceMappingURL=NewsListBlockRender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/blocks/builtins/NewsListBlockRender.tsx"],"sourcesContent":["\"use client\";\n\nimport type { z } from \"zod\";\nimport type { NewsListBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { Heading } from \"../ui\";\nimport { NewsList } from \"../../components/News\";\n\ntype NewsListBlk = z.infer<typeof NewsListBlockSchema>;\n\nexport function NewsListRender({ block }: BlockRenderProps<NewsListBlk>) {\n return (\n <section className=\"xicms-newslist\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n <NewsList basePath={block.basePath} limit={block.limit} pageSize={block.pageSize} />\n </section>\n );\n}\n"],"mappings":";AAYI,SACoB,KADpB;AAPJ,SAAS,eAAe;AACxB,SAAS,gBAAgB;AAIlB,SAAS,eAAe,EAAE,MAAM,GAAkC;AACvE,SACE,qBAAC,aAAQ,WAAU,kBAChB;AAAA,UAAM,WAAW,oBAAC,WAAQ,OAAO,GAAG,mBAAgB,WAAW,gBAAM,SAAQ;AAAA,IAC9E,oBAAC,YAAS,UAAU,MAAM,UAAU,OAAO,MAAM,OAAO,UAAU,MAAM,UAAU;AAAA,KACpF;AAEJ;","names":[]}
@@ -1,2 +1 @@
1
- import type { z } from "zod";
2
- export declare const newsletterBlock: import("../index.js").BlockDefinition<z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
1
+ export declare const newsletterBlock: import("../index.js").BlockDefinition<import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>>;
@@ -1,95 +1,8 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useEffect, useState } from "react";
1
+ import dynamic from "next/dynamic";
4
2
  import { defineBlock } from "../registry.js";
5
- import { Button } from "@astryxdesign/core/Button";
6
- import { TextInput } from "@astryxdesign/core/TextInput";
7
- import { CheckboxInput } from "@astryxdesign/core/CheckboxInput";
8
- import { VStack, Card, Heading, Text } from "../ui/index.js";
9
- import { isDemoActive } from "../../demo/demoStore.js";
10
- import { Onvoltooid } from "./lib/Onvoltooid.js";
11
- import { isFirebaseConfigured } from "../../firebase/config.js";
12
- import { submitFormValues } from "./lib/submitForm.js";
13
- function NewsletterRender({ block, siteId, mode }) {
14
- const [email, setEmail] = useState("");
15
- const [agreed, setAgreed] = useState(false);
16
- const [status, setStatus] = useState("idle");
17
- const [demo, setDemo] = useState(false);
18
- useEffect(() => setDemo(isDemoActive()), []);
19
- const useXicmsForm = !block.actionUrl && (Boolean(block.formId) || demo);
20
- async function submitViaXicms(e) {
21
- e.preventDefault();
22
- if (mode === "preview") return;
23
- if (!block.formId && !demo) return;
24
- if (isDemoActive() || !isFirebaseConfigured()) {
25
- setStatus("ok");
26
- return;
27
- }
28
- setStatus("busy");
29
- try {
30
- await submitFormValues(siteId, block.formId, { email });
31
- setStatus("ok");
32
- setEmail("");
33
- } catch {
34
- setStatus("error");
35
- }
36
- }
37
- const consentBox = block.consentText ? /* @__PURE__ */ jsx("div", { style: { textAlign: "left", maxWidth: 440, width: "100%" }, children: /* @__PURE__ */ jsx(CheckboxInput, { label: block.consentText, isRequired: true, value: agreed, onChange: setAgreed }) }) : null;
38
- const emailInput = /* @__PURE__ */ jsx("div", { style: { flex: 1, minWidth: 200, textAlign: "left" }, children: /* @__PURE__ */ jsx(
39
- TextInput,
40
- {
41
- label: "E-mailadres",
42
- isLabelHidden: true,
43
- type: "email",
44
- htmlName: "EMAIL",
45
- isRequired: true,
46
- placeholder: "je@email.nl",
47
- value: email,
48
- onChange: setEmail
49
- }
50
- ) });
51
- const rowStyle = { display: "flex", gap: "0.75rem", flexWrap: "wrap", alignItems: "end", justifyContent: "center", maxWidth: 440, width: "100%" };
52
- return /* @__PURE__ */ jsx(Card, { padding: 5, variant: "muted", children: /* @__PURE__ */ jsxs(VStack, { gap: 2, hAlign: "center", style: { textAlign: "center" }, children: [
53
- block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
54
- block.text && /* @__PURE__ */ jsx(Text, { color: "secondary", "data-xicms-edit": "text", children: block.text }),
55
- status === "ok" ? /* @__PURE__ */ jsx(Text, { role: "status", children: "Bedankt voor je aanmelding!" }) : block.actionUrl ? /* @__PURE__ */ jsxs(
56
- "form",
57
- {
58
- action: block.actionUrl,
59
- method: "post",
60
- target: "_blank",
61
- style: rowStyle,
62
- onSubmit: (e) => {
63
- if (block.consentText && !agreed) e.preventDefault();
64
- },
65
- children: [
66
- emailInput,
67
- consentBox,
68
- block.consentText && /* @__PURE__ */ jsx("input", { type: "hidden", name: "CONSENT", value: agreed ? "yes" : "" }),
69
- /* @__PURE__ */ jsx(Button, { label: block.buttonLabel, variant: "primary", size: "lg", type: "submit", children: /* @__PURE__ */ jsx("span", { "data-xicms-edit": "buttonLabel", children: block.buttonLabel }) })
70
- ]
71
- }
72
- ) : useXicmsForm ? /* @__PURE__ */ jsxs("form", { onSubmit: submitViaXicms, style: rowStyle, children: [
73
- emailInput,
74
- consentBox,
75
- /* @__PURE__ */ jsx(
76
- Button,
77
- {
78
- label: status === "busy" ? "Aanmelden\u2026" : block.buttonLabel,
79
- variant: "primary",
80
- size: "lg",
81
- type: "submit",
82
- isLoading: status === "busy",
83
- children: status === "busy" ? void 0 : /* @__PURE__ */ jsx("span", { "data-xicms-edit": "buttonLabel", children: block.buttonLabel })
84
- }
85
- ),
86
- status === "error" && /* @__PURE__ */ jsx(Text, { role: "alert", type: "supporting", style: { color: "var(--color-error, #c0392b)" }, children: "Aanmelden mislukt. Probeer het later opnieuw." })
87
- ] }) : /* @__PURE__ */ jsx(Onvoltooid, { children: "Dit nieuwsbrief-blok is nog leeg: kies een aanmeld-URL of een formulier via het tandwiel. Bezoekers zien dit blok niet." })
88
- ] }) });
89
- }
90
3
  const newsletterBlock = defineBlock({
91
4
  type: "newsletter",
92
- Render: NewsletterRender,
5
+ Render: dynamic(() => import("./NewsletterRender.js").then((m) => m.NewsletterRender)),
93
6
  label: "Nieuwsbrief",
94
7
  icon: "\u2709\uFE0F",
95
8
  defaults: () => ({ heading: "Blijf op de hoogte", buttonLabel: "Aanmelden" })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/builtins/Newsletter.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState, type FormEvent } from \"react\";\nimport type { z } from \"zod\";\nimport type { NewsletterBlockSchema } from \"../../schema/blocks\";\nimport { defineBlock, type BlockRenderProps } from \"../registry\";\nimport { Button } from \"@astryxdesign/core/Button\";\nimport { TextInput } from \"@astryxdesign/core/TextInput\";\nimport { CheckboxInput } from \"@astryxdesign/core/CheckboxInput\";\nimport { VStack, Card, Heading, Text } from \"../ui\";\nimport { isDemoActive } from \"../../demo/demoStore\";\nimport { Onvoltooid } from \"./lib/Onvoltooid\";\nimport { isFirebaseConfigured } from \"../../firebase/config\";\nimport { submitFormValues } from \"./lib/submitForm\";\n\ntype Newsletter = z.infer<typeof NewsletterBlockSchema>;\n\n/**\n * Nieuwsbrief-aanmelding. Twee modi:\n * - `actionUrl` (bv. de embed-action van Mailchimp/Brevo): native form-POST naar de provider.\n * - `formId` (zonder actionUrl): opslag via het XiCMS-formulier (submitForm-callable) — inzendingen\n * verschijnen in /beheer → Formulieren, met dezelfde rate-limiting/validatie als het formulier-blok.\n * Optionele AVG-checkbox via `consentText`.\n */\nfunction NewsletterRender({ block, siteId, mode }: BlockRenderProps<Newsletter>) {\n const [email, setEmail] = useState(\"\");\n const [agreed, setAgreed] = useState(false);\n const [status, setStatus] = useState<\"idle\" | \"busy\" | \"ok\" | \"error\">(\"idle\");\n /**\n * In een demo is er altijd een werkend formulier: het slaat lokaal \"op\" (zie submitViaXicms),\n * precies zoals het formulier-blok. Een demo die om configuratie vraagt verkoopt niets.\n *\n * Via state + effect en niet rechtstreeks in de render: `setDemoActive` draait in een effect van\n * de provider, dus tijdens de eerste render is `isDemoActive()` nog false en zou dit blok zich\n * één keer verkeerd aankleden — en zonder eigen re-render zo blijven staan. FormBlock leert\n * dezelfde les op dezelfde manier.\n */\n const [demo, setDemo] = useState(false);\n useEffect(() => setDemo(isDemoActive()), []);\n const useXicmsForm = !block.actionUrl && (Boolean(block.formId) || demo);\n\n async function submitViaXicms(e: FormEvent) {\n e.preventDefault();\n if (mode === \"preview\") return;\n // Zonder formId kan er alleen in demo iets \"verzonden\" worden — de guard hieronder vangt dat af\n // met een lokaal succes vóór submitFormValues ooit wordt bereikt.\n if (!block.formId && !demo) return;\n // Zelfde vangnet als het formulier-blok: in demo of zonder Firebase-backend lokaal \"slagen\"\n // i.p.v. een foutmelding tonen op een statische (referentie)site.\n if (isDemoActive() || !isFirebaseConfigured()) {\n setStatus(\"ok\");\n return;\n }\n setStatus(\"busy\");\n try {\n // Niet-demo-pad; hierboven afgevangen als formId ontbreekt, dus hier bestaat hij.\n await submitFormValues(siteId, block.formId as string, { email });\n setStatus(\"ok\");\n setEmail(\"\");\n } catch {\n setStatus(\"error\");\n }\n }\n\n const consentBox = block.consentText ? (\n <div style={{ textAlign: \"left\", maxWidth: 440, width: \"100%\" }}>\n <CheckboxInput label={block.consentText} isRequired value={agreed} onChange={setAgreed} />\n </div>\n ) : null;\n\n const emailInput = (\n <div style={{ flex: 1, minWidth: 200, textAlign: \"left\" }}>\n <TextInput\n label=\"E-mailadres\"\n isLabelHidden\n type=\"email\"\n htmlName=\"EMAIL\"\n isRequired\n placeholder=\"je@email.nl\"\n value={email}\n onChange={setEmail}\n />\n </div>\n );\n const rowStyle = { display: \"flex\", gap: \"0.75rem\", flexWrap: \"wrap\", alignItems: \"end\", justifyContent: \"center\", maxWidth: 440, width: \"100%\" } as const;\n\n return (\n <Card padding={5} variant=\"muted\">\n <VStack gap={2} hAlign=\"center\" style={{ textAlign: \"center\" }}>\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n {block.text && <Text color=\"secondary\" data-xicms-edit=\"text\">{block.text}</Text>}\n {status === \"ok\" ? (\n <Text role=\"status\">Bedankt voor je aanmelding!</Text>\n ) : block.actionUrl ? (\n <form\n action={block.actionUrl}\n method=\"post\"\n target=\"_blank\"\n style={rowStyle}\n // AVG: zonder deze guard kon de native POST doorgaan zonder aangevinkte toestemming\n // (Astryx CheckboxInput heeft geen htmlName, dus de browser hield 'm niet tegen).\n onSubmit={(e) => {\n if (block.consentText && !agreed) e.preventDefault();\n }}\n >\n {emailInput}\n {consentBox}\n {/* De toestemmingswaarde ook daadwerkelijk meesturen naar de provider. */}\n {block.consentText && <input type=\"hidden\" name=\"CONSENT\" value={agreed ? \"yes\" : \"\"} />}\n <Button label={block.buttonLabel} variant=\"primary\" size=\"lg\" type=\"submit\">\n <span data-xicms-edit=\"buttonLabel\">{block.buttonLabel}</span>\n </Button>\n </form>\n ) : useXicmsForm ? (\n <form onSubmit={submitViaXicms} style={rowStyle}>\n {emailInput}\n {consentBox}\n <Button\n label={status === \"busy\" ? \"Aanmelden…\" : block.buttonLabel}\n variant=\"primary\"\n size=\"lg\"\n type=\"submit\"\n isLoading={status === \"busy\"}\n >\n {/* Tijdens versturen wint het wachtlabel: `undefined` laat Astryx op `label` terugvallen. */}\n {status === \"busy\" ? undefined : <span data-xicms-edit=\"buttonLabel\">{block.buttonLabel}</span>}\n </Button>\n {status === \"error\" && (\n <Text role=\"alert\" type=\"supporting\" style={{ color: \"var(--color-error, #c0392b)\" }}>\n Aanmelden mislukt. Probeer het later opnieuw.\n </Text>\n )}\n </form>\n ) : (\n <Onvoltooid>Dit nieuwsbrief-blok is nog leeg: kies een aanmeld-URL of een formulier via het tandwiel. Bezoekers zien dit blok niet.</Onvoltooid>\n )}\n </VStack>\n </Card>\n );\n}\n\nexport const newsletterBlock = defineBlock({\n type: \"newsletter\",\n Render: NewsletterRender,\n label: \"Nieuwsbrief\",\n icon: \"✉️\",\n defaults: () => ({ heading: \"Blijf op de hoogte\", buttonLabel: \"Aanmelden\" }),\n});\n"],"mappings":";AAkEM,cA4BI,YA5BJ;AAhEN,SAAS,WAAW,gBAAgC;AAGpD,SAAS,mBAA0C;AACnD,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAC1B,SAAS,qBAAqB;AAC9B,SAAS,QAAQ,MAAM,SAAS,YAAY;AAC5C,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAC3B,SAAS,4BAA4B;AACrC,SAAS,wBAAwB;AAWjC,SAAS,iBAAiB,EAAE,OAAO,QAAQ,KAAK,GAAiC;AAC/E,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,CAAC,QAAQ,SAAS,IAAI,SAA2C,MAAM;AAU7E,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,YAAU,MAAM,QAAQ,aAAa,CAAC,GAAG,CAAC,CAAC;AAC3C,QAAM,eAAe,CAAC,MAAM,cAAc,QAAQ,MAAM,MAAM,KAAK;AAEnE,iBAAe,eAAe,GAAc;AAC1C,MAAE,eAAe;AACjB,QAAI,SAAS,UAAW;AAGxB,QAAI,CAAC,MAAM,UAAU,CAAC,KAAM;AAG5B,QAAI,aAAa,KAAK,CAAC,qBAAqB,GAAG;AAC7C,gBAAU,IAAI;AACd;AAAA,IACF;AACA,cAAU,MAAM;AAChB,QAAI;AAEF,YAAM,iBAAiB,QAAQ,MAAM,QAAkB,EAAE,MAAM,CAAC;AAChE,gBAAU,IAAI;AACd,eAAS,EAAE;AAAA,IACb,QAAQ;AACN,gBAAU,OAAO;AAAA,IACnB;AAAA,EACF;AAEA,QAAM,aAAa,MAAM,cACvB,oBAAC,SAAI,OAAO,EAAE,WAAW,QAAQ,UAAU,KAAK,OAAO,OAAO,GAC5D,8BAAC,iBAAc,OAAO,MAAM,aAAa,YAAU,MAAC,OAAO,QAAQ,UAAU,WAAW,GAC1F,IACE;AAEJ,QAAM,aACJ,oBAAC,SAAI,OAAO,EAAE,MAAM,GAAG,UAAU,KAAK,WAAW,OAAO,GACtD;AAAA,IAAC;AAAA;AAAA,MACC,OAAM;AAAA,MACN,eAAa;AAAA,MACb,MAAK;AAAA,MACL,UAAS;AAAA,MACT,YAAU;AAAA,MACV,aAAY;AAAA,MACZ,OAAO;AAAA,MACP,UAAU;AAAA;AAAA,EACZ,GACF;AAEF,QAAM,WAAW,EAAE,SAAS,QAAQ,KAAK,WAAW,UAAU,QAAQ,YAAY,OAAO,gBAAgB,UAAU,UAAU,KAAK,OAAO,OAAO;AAEhJ,SACE,oBAAC,QAAK,SAAS,GAAG,SAAQ,SACxB,+BAAC,UAAO,KAAK,GAAG,QAAO,UAAS,OAAO,EAAE,WAAW,SAAS,GAC1D;AAAA,UAAM,WAAW,oBAAC,WAAQ,OAAO,GAAG,mBAAgB,WAAW,gBAAM,SAAQ;AAAA,IAC7E,MAAM,QAAQ,oBAAC,QAAK,OAAM,aAAY,mBAAgB,QAAQ,gBAAM,MAAK;AAAA,IACzE,WAAW,OACV,oBAAC,QAAK,MAAK,UAAS,yCAA2B,IAC7C,MAAM,YACR;AAAA,MAAC;AAAA;AAAA,QACC,QAAQ,MAAM;AAAA,QACd,QAAO;AAAA,QACP,QAAO;AAAA,QACP,OAAO;AAAA,QAGP,UAAU,CAAC,MAAM;AACf,cAAI,MAAM,eAAe,CAAC,OAAQ,GAAE,eAAe;AAAA,QACrD;AAAA,QAEC;AAAA;AAAA,UACA;AAAA,UAEA,MAAM,eAAe,oBAAC,WAAM,MAAK,UAAS,MAAK,WAAU,OAAO,SAAS,QAAQ,IAAI;AAAA,UACtF,oBAAC,UAAO,OAAO,MAAM,aAAa,SAAQ,WAAU,MAAK,MAAK,MAAK,UACjE,8BAAC,UAAK,mBAAgB,eAAe,gBAAM,aAAY,GACzD;AAAA;AAAA;AAAA,IACF,IACE,eACF,qBAAC,UAAK,UAAU,gBAAgB,OAAO,UACpC;AAAA;AAAA,MACA;AAAA,MACD;AAAA,QAAC;AAAA;AAAA,UACC,OAAO,WAAW,SAAS,oBAAe,MAAM;AAAA,UAChD,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,MAAK;AAAA,UACL,WAAW,WAAW;AAAA,UAGrB,qBAAW,SAAS,SAAY,oBAAC,UAAK,mBAAgB,eAAe,gBAAM,aAAY;AAAA;AAAA,MAC1F;AAAA,MACC,WAAW,WACV,oBAAC,QAAK,MAAK,SAAQ,MAAK,cAAa,OAAO,EAAE,OAAO,8BAA8B,GAAG,2DAEtF;AAAA,OAEJ,IAEA,oBAAC,cAAW,qIAAuH;AAAA,KAEvI,GACF;AAEJ;AAEO,MAAM,kBAAkB,YAAY;AAAA,EACzC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,SAAS,sBAAsB,aAAa,YAAY;AAC7E,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/builtins/Newsletter.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const newsletterBlock = defineBlock({\n type: \"newsletter\",\n Render: dynamic(() => import(\"./NewsletterRender\").then((m) => m.NewsletterRender)),\n label: \"Nieuwsbrief\",\n icon: \"✉️\",\n defaults: () => ({ heading: \"Blijf op de hoogte\", buttonLabel: \"Aanmelden\" }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,kBAAkB,YAAY;AAAA,EACzC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,oBAAoB,EAAE,KAAK,CAAC,MAAM,EAAE,gBAAgB,CAAC;AAAA,EAClF,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,SAAS,sBAAsB,aAAa,YAAY;AAC7E,CAAC;","names":[]}
@@ -0,0 +1,13 @@
1
+ import type { z } from "zod";
2
+ import type { NewsletterBlockSchema } from "../../schema/blocks.js";
3
+ import type { BlockRenderProps } from "../registry.js";
4
+ type Newsletter = z.infer<typeof NewsletterBlockSchema>;
5
+ /**
6
+ * Nieuwsbrief-aanmelding. Twee modi:
7
+ * - `actionUrl` (bv. de embed-action van Mailchimp/Brevo): native form-POST naar de provider.
8
+ * - `formId` (zonder actionUrl): opslag via het XiCMS-formulier (submitForm-callable) — inzendingen
9
+ * verschijnen in /beheer → Formulieren, met dezelfde rate-limiting/validatie als het formulier-blok.
10
+ * Optionele AVG-checkbox via `consentText`.
11
+ */
12
+ export declare function NewsletterRender({ block, siteId, mode }: BlockRenderProps<Newsletter>): import("react").JSX.Element;
13
+ export {};
@@ -0,0 +1,92 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ import { Button } from "@astryxdesign/core/Button";
5
+ import { TextInput } from "@astryxdesign/core/TextInput";
6
+ import { CheckboxInput } from "@astryxdesign/core/CheckboxInput";
7
+ import { VStack, Card, Heading, Text } from "../ui/index.js";
8
+ import { isDemoActive } from "../../demo/demoStore.js";
9
+ import { Onvoltooid } from "./lib/Onvoltooid.js";
10
+ import { isFirebaseConfigured } from "../../firebase/config.js";
11
+ import { submitFormValues } from "./lib/submitForm.js";
12
+ function NewsletterRender({ block, siteId, mode }) {
13
+ const [email, setEmail] = useState("");
14
+ const [agreed, setAgreed] = useState(false);
15
+ const [status, setStatus] = useState("idle");
16
+ const [demo, setDemo] = useState(false);
17
+ useEffect(() => setDemo(isDemoActive()), []);
18
+ const useXicmsForm = !block.actionUrl && (Boolean(block.formId) || demo);
19
+ async function submitViaXicms(e) {
20
+ e.preventDefault();
21
+ if (mode === "preview") return;
22
+ if (!block.formId && !demo) return;
23
+ if (isDemoActive() || !isFirebaseConfigured()) {
24
+ setStatus("ok");
25
+ return;
26
+ }
27
+ setStatus("busy");
28
+ try {
29
+ await submitFormValues(siteId, block.formId, { email });
30
+ setStatus("ok");
31
+ setEmail("");
32
+ } catch {
33
+ setStatus("error");
34
+ }
35
+ }
36
+ const consentBox = block.consentText ? /* @__PURE__ */ jsx("div", { style: { textAlign: "left", maxWidth: 440, width: "100%" }, children: /* @__PURE__ */ jsx(CheckboxInput, { label: block.consentText, isRequired: true, value: agreed, onChange: setAgreed }) }) : null;
37
+ const emailInput = /* @__PURE__ */ jsx("div", { style: { flex: 1, minWidth: 200, textAlign: "left" }, children: /* @__PURE__ */ jsx(
38
+ TextInput,
39
+ {
40
+ label: "E-mailadres",
41
+ isLabelHidden: true,
42
+ type: "email",
43
+ htmlName: "EMAIL",
44
+ isRequired: true,
45
+ placeholder: "je@email.nl",
46
+ value: email,
47
+ onChange: setEmail
48
+ }
49
+ ) });
50
+ const rowStyle = { display: "flex", gap: "0.75rem", flexWrap: "wrap", alignItems: "end", justifyContent: "center", maxWidth: 440, width: "100%" };
51
+ return /* @__PURE__ */ jsx(Card, { padding: 5, variant: "muted", children: /* @__PURE__ */ jsxs(VStack, { gap: 2, hAlign: "center", style: { textAlign: "center" }, children: [
52
+ block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
53
+ block.text && /* @__PURE__ */ jsx(Text, { color: "secondary", "data-xicms-edit": "text", children: block.text }),
54
+ status === "ok" ? /* @__PURE__ */ jsx(Text, { role: "status", children: "Bedankt voor je aanmelding!" }) : block.actionUrl ? /* @__PURE__ */ jsxs(
55
+ "form",
56
+ {
57
+ action: block.actionUrl,
58
+ method: "post",
59
+ target: "_blank",
60
+ style: rowStyle,
61
+ onSubmit: (e) => {
62
+ if (block.consentText && !agreed) e.preventDefault();
63
+ },
64
+ children: [
65
+ emailInput,
66
+ consentBox,
67
+ block.consentText && /* @__PURE__ */ jsx("input", { type: "hidden", name: "CONSENT", value: agreed ? "yes" : "" }),
68
+ /* @__PURE__ */ jsx(Button, { label: block.buttonLabel, variant: "primary", size: "lg", type: "submit", children: /* @__PURE__ */ jsx("span", { "data-xicms-edit": "buttonLabel", children: block.buttonLabel }) })
69
+ ]
70
+ }
71
+ ) : useXicmsForm ? /* @__PURE__ */ jsxs("form", { onSubmit: submitViaXicms, style: rowStyle, children: [
72
+ emailInput,
73
+ consentBox,
74
+ /* @__PURE__ */ jsx(
75
+ Button,
76
+ {
77
+ label: status === "busy" ? "Aanmelden\u2026" : block.buttonLabel,
78
+ variant: "primary",
79
+ size: "lg",
80
+ type: "submit",
81
+ isLoading: status === "busy",
82
+ children: status === "busy" ? void 0 : /* @__PURE__ */ jsx("span", { "data-xicms-edit": "buttonLabel", children: block.buttonLabel })
83
+ }
84
+ ),
85
+ status === "error" && /* @__PURE__ */ jsx(Text, { role: "alert", type: "supporting", style: { color: "var(--color-error, #c0392b)" }, children: "Aanmelden mislukt. Probeer het later opnieuw." })
86
+ ] }) : /* @__PURE__ */ jsx(Onvoltooid, { children: "Dit nieuwsbrief-blok is nog leeg: kies een aanmeld-URL of een formulier via het tandwiel. Bezoekers zien dit blok niet." })
87
+ ] }) });
88
+ }
89
+ export {
90
+ NewsletterRender
91
+ };
92
+ //# sourceMappingURL=NewsletterRender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/blocks/builtins/NewsletterRender.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState, type FormEvent } from \"react\";\nimport type { z } from \"zod\";\nimport type { NewsletterBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { Button } from \"@astryxdesign/core/Button\";\nimport { TextInput } from \"@astryxdesign/core/TextInput\";\nimport { CheckboxInput } from \"@astryxdesign/core/CheckboxInput\";\nimport { VStack, Card, Heading, Text } from \"../ui\";\nimport { isDemoActive } from \"../../demo/demoStore\";\nimport { Onvoltooid } from \"./lib/Onvoltooid\";\nimport { isFirebaseConfigured } from \"../../firebase/config\";\nimport { submitFormValues } from \"./lib/submitForm\";\n\ntype Newsletter = z.infer<typeof NewsletterBlockSchema>;\n\n/**\n * Nieuwsbrief-aanmelding. Twee modi:\n * - `actionUrl` (bv. de embed-action van Mailchimp/Brevo): native form-POST naar de provider.\n * - `formId` (zonder actionUrl): opslag via het XiCMS-formulier (submitForm-callable) — inzendingen\n * verschijnen in /beheer → Formulieren, met dezelfde rate-limiting/validatie als het formulier-blok.\n * Optionele AVG-checkbox via `consentText`.\n */\nexport function NewsletterRender({ block, siteId, mode }: BlockRenderProps<Newsletter>) {\n const [email, setEmail] = useState(\"\");\n const [agreed, setAgreed] = useState(false);\n const [status, setStatus] = useState<\"idle\" | \"busy\" | \"ok\" | \"error\">(\"idle\");\n /**\n * In een demo is er altijd een werkend formulier: het slaat lokaal \"op\" (zie submitViaXicms),\n * precies zoals het formulier-blok. Een demo die om configuratie vraagt verkoopt niets.\n *\n * Via state + effect en niet rechtstreeks in de render: `setDemoActive` draait in een effect van\n * de provider, dus tijdens de eerste render is `isDemoActive()` nog false en zou dit blok zich\n * één keer verkeerd aankleden — en zonder eigen re-render zo blijven staan. FormBlock leert\n * dezelfde les op dezelfde manier.\n */\n const [demo, setDemo] = useState(false);\n useEffect(() => setDemo(isDemoActive()), []);\n const useXicmsForm = !block.actionUrl && (Boolean(block.formId) || demo);\n\n async function submitViaXicms(e: FormEvent) {\n e.preventDefault();\n if (mode === \"preview\") return;\n // Zonder formId kan er alleen in demo iets \"verzonden\" worden — de guard hieronder vangt dat af\n // met een lokaal succes vóór submitFormValues ooit wordt bereikt.\n if (!block.formId && !demo) return;\n // Zelfde vangnet als het formulier-blok: in demo of zonder Firebase-backend lokaal \"slagen\"\n // i.p.v. een foutmelding tonen op een statische (referentie)site.\n if (isDemoActive() || !isFirebaseConfigured()) {\n setStatus(\"ok\");\n return;\n }\n setStatus(\"busy\");\n try {\n // Niet-demo-pad; hierboven afgevangen als formId ontbreekt, dus hier bestaat hij.\n await submitFormValues(siteId, block.formId as string, { email });\n setStatus(\"ok\");\n setEmail(\"\");\n } catch {\n setStatus(\"error\");\n }\n }\n\n const consentBox = block.consentText ? (\n <div style={{ textAlign: \"left\", maxWidth: 440, width: \"100%\" }}>\n <CheckboxInput label={block.consentText} isRequired value={agreed} onChange={setAgreed} />\n </div>\n ) : null;\n\n const emailInput = (\n <div style={{ flex: 1, minWidth: 200, textAlign: \"left\" }}>\n <TextInput\n label=\"E-mailadres\"\n isLabelHidden\n type=\"email\"\n htmlName=\"EMAIL\"\n isRequired\n placeholder=\"je@email.nl\"\n value={email}\n onChange={setEmail}\n />\n </div>\n );\n const rowStyle = { display: \"flex\", gap: \"0.75rem\", flexWrap: \"wrap\", alignItems: \"end\", justifyContent: \"center\", maxWidth: 440, width: \"100%\" } as const;\n\n return (\n <Card padding={5} variant=\"muted\">\n <VStack gap={2} hAlign=\"center\" style={{ textAlign: \"center\" }}>\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n {block.text && <Text color=\"secondary\" data-xicms-edit=\"text\">{block.text}</Text>}\n {status === \"ok\" ? (\n <Text role=\"status\">Bedankt voor je aanmelding!</Text>\n ) : block.actionUrl ? (\n <form\n action={block.actionUrl}\n method=\"post\"\n target=\"_blank\"\n style={rowStyle}\n // AVG: zonder deze guard kon de native POST doorgaan zonder aangevinkte toestemming\n // (Astryx CheckboxInput heeft geen htmlName, dus de browser hield 'm niet tegen).\n onSubmit={(e) => {\n if (block.consentText && !agreed) e.preventDefault();\n }}\n >\n {emailInput}\n {consentBox}\n {/* De toestemmingswaarde ook daadwerkelijk meesturen naar de provider. */}\n {block.consentText && <input type=\"hidden\" name=\"CONSENT\" value={agreed ? \"yes\" : \"\"} />}\n <Button label={block.buttonLabel} variant=\"primary\" size=\"lg\" type=\"submit\">\n <span data-xicms-edit=\"buttonLabel\">{block.buttonLabel}</span>\n </Button>\n </form>\n ) : useXicmsForm ? (\n <form onSubmit={submitViaXicms} style={rowStyle}>\n {emailInput}\n {consentBox}\n <Button\n label={status === \"busy\" ? \"Aanmelden…\" : block.buttonLabel}\n variant=\"primary\"\n size=\"lg\"\n type=\"submit\"\n isLoading={status === \"busy\"}\n >\n {/* Tijdens versturen wint het wachtlabel: `undefined` laat Astryx op `label` terugvallen. */}\n {status === \"busy\" ? undefined : <span data-xicms-edit=\"buttonLabel\">{block.buttonLabel}</span>}\n </Button>\n {status === \"error\" && (\n <Text role=\"alert\" type=\"supporting\" style={{ color: \"var(--color-error, #c0392b)\" }}>\n Aanmelden mislukt. Probeer het later opnieuw.\n </Text>\n )}\n </form>\n ) : (\n <Onvoltooid>Dit nieuwsbrief-blok is nog leeg: kies een aanmeld-URL of een formulier via het tandwiel. Bezoekers zien dit blok niet.</Onvoltooid>\n )}\n </VStack>\n </Card>\n );\n}\n"],"mappings":"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","names":[]}
@@ -1,2 +1 @@
1
- import type { z } from "zod";
2
- export declare const openingHoursBlock: import("../index.js").BlockDefinition<z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
1
+ export declare const openingHoursBlock: import("../index.js").BlockDefinition<import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>>;
@@ -1,34 +1,8 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
2
- import { jsonLdHtml } from "./jsonld.js";
1
+ import dynamic from "next/dynamic";
3
2
  import { defineBlock } from "../registry.js";
4
- import { Heading } from "../ui/index.js";
5
- import { OpenNowBadge } from "./OpenNowBadge.js";
6
- import { openingHoursSpecJsonLd } from "./lib/openingHours.js";
7
- function OpeningHoursRender({ block }) {
8
- const rows = block.rows ?? [];
9
- const spec = block.jsonLd ? openingHoursSpecJsonLd(rows) : [];
10
- return /* @__PURE__ */ jsxs("section", { className: "xicms-hours", children: [
11
- block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
12
- block.showStatus && /* @__PURE__ */ jsx(OpenNowBadge, { rows }),
13
- /* @__PURE__ */ jsx("table", { className: "xicms-hours-table", children: /* @__PURE__ */ jsx("tbody", { children: rows.map((r, i) => /* @__PURE__ */ jsxs("tr", { children: [
14
- /* @__PURE__ */ jsx("th", { scope: "row", "data-xicms-edit": `rows.${i}.day`, children: r.day }),
15
- /* @__PURE__ */ jsx("td", { "data-xicms-edit": `rows.${i}.hours`, children: r.hours })
16
- ] }, i)) }) }),
17
- spec.length > 0 && /* @__PURE__ */ jsx(
18
- "script",
19
- {
20
- type: "application/ld+json",
21
- dangerouslySetInnerHTML: {
22
- // Zelfde @id als contact-/layout-JSON-LD → Google voegt de drie samen tot één bedrijf.
23
- __html: jsonLdHtml({ "@context": "https://schema.org", "@type": "LocalBusiness", "@id": "#business", openingHoursSpecification: spec })
24
- }
25
- }
26
- )
27
- ] });
28
- }
29
3
  const openingHoursBlock = defineBlock({
30
4
  type: "openingHours",
31
- Render: OpeningHoursRender,
5
+ Render: dynamic(() => import("./OpeningHoursRender.js").then((m) => m.OpeningHoursRender)),
32
6
  label: "Openingstijden",
33
7
  icon: "\u{1F552}",
34
8
  defaults: () => ({
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/builtins/OpeningHours.tsx"],"sourcesContent":["import type { z } from \"zod\";\nimport { jsonLdHtml } from \"./jsonld\";\nimport type { OpeningHoursBlockSchema } from \"../../schema/blocks\";\nimport { defineBlock, type BlockRenderProps } from \"../registry\";\nimport { Heading } from \"../ui\";\nimport { OpenNowBadge } from \"./OpenNowBadge\";\nimport { openingHoursSpecJsonLd } from \"./lib/openingHours\";\n\ntype OpeningHours = z.infer<typeof OpeningHoursBlockSchema>;\n\n/** Openingstijden-tabel. Server-safe; de optionele \"Nu geopend\"-badge is een client-eiland. */\nfunction OpeningHoursRender({ block }: BlockRenderProps<OpeningHours>) {\n const rows = block.rows ?? [];\n const spec = block.jsonLd ? openingHoursSpecJsonLd(rows) : [];\n return (\n <section className=\"xicms-hours\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n {block.showStatus && <OpenNowBadge rows={rows} />}\n <table className=\"xicms-hours-table\">\n <tbody>\n {rows.map((r, i) => (\n <tr key={i}>\n <th scope=\"row\" data-xicms-edit={`rows.${i}.day`}>{r.day}</th>\n <td data-xicms-edit={`rows.${i}.hours`}>{r.hours}</td>\n </tr>\n ))}\n </tbody>\n </table>\n {spec.length > 0 && (\n <script\n type=\"application/ld+json\"\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n // Zelfde @id als contact-/layout-JSON-LD → Google voegt de drie samen tot één bedrijf.\n __html: jsonLdHtml({ \"@context\": \"https://schema.org\", \"@type\": \"LocalBusiness\", \"@id\": \"#business\", openingHoursSpecification: spec }),\n }}\n />\n )}\n </section>\n );\n}\n\nexport const openingHoursBlock = defineBlock({\n type: \"openingHours\",\n Render: OpeningHoursRender,\n label: \"Openingstijden\",\n icon: \"🕒\",\n defaults: () => ({\n heading: \"Openingstijden\",\n rows: [\n { day: \"Maandag t/m vrijdag\", hours: \"09:00 – 17:00\" },\n { day: \"Zaterdag\", hours: \"10:00 – 16:00\" },\n { day: \"Zondag\", hours: \"Gesloten\" },\n ],\n }),\n});\n"],"mappings":"AAgBwB,cAKZ,YALY;AAfxB,SAAS,kBAAkB;AAE3B,SAAS,mBAA0C;AACnD,SAAS,eAAe;AACxB,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AAKvC,SAAS,mBAAmB,EAAE,MAAM,GAAmC;AACrE,QAAM,OAAO,MAAM,QAAQ,CAAC;AAC5B,QAAM,OAAO,MAAM,SAAS,uBAAuB,IAAI,IAAI,CAAC;AAC5D,SACE,qBAAC,aAAQ,WAAU,eAChB;AAAA,UAAM,WAAW,oBAAC,WAAQ,OAAO,GAAG,mBAAgB,WAAW,gBAAM,SAAQ;AAAA,IAC7E,MAAM,cAAc,oBAAC,gBAAa,MAAY;AAAA,IAC/C,oBAAC,WAAM,WAAU,qBACf,8BAAC,WACE,eAAK,IAAI,CAAC,GAAG,MACZ,qBAAC,QACC;AAAA,0BAAC,QAAG,OAAM,OAAM,mBAAiB,QAAQ,CAAC,QAAS,YAAE,KAAI;AAAA,MACzD,oBAAC,QAAG,mBAAiB,QAAQ,CAAC,UAAW,YAAE,OAAM;AAAA,SAF1C,CAGT,CACD,GACH,GACF;AAAA,IACC,KAAK,SAAS,KACb;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QAEL,yBAAyB;AAAA;AAAA,UAEvB,QAAQ,WAAW,EAAE,YAAY,sBAAsB,SAAS,iBAAiB,OAAO,aAAa,2BAA2B,KAAK,CAAC;AAAA,QACxI;AAAA;AAAA,IACF;AAAA,KAEJ;AAEJ;AAEO,MAAM,oBAAoB,YAAY;AAAA,EAC3C,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,MACJ,EAAE,KAAK,uBAAuB,OAAO,qBAAgB;AAAA,MACrD,EAAE,KAAK,YAAY,OAAO,qBAAgB;AAAA,MAC1C,EAAE,KAAK,UAAU,OAAO,WAAW;AAAA,IACrC;AAAA,EACF;AACF,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/builtins/OpeningHours.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const openingHoursBlock = defineBlock({\n type: \"openingHours\",\n Render: dynamic(() => import(\"./OpeningHoursRender\").then((m) => m.OpeningHoursRender)),\n label: \"Openingstijden\",\n icon: \"🕒\",\n defaults: () => ({\n heading: \"Openingstijden\",\n rows: [\n { day: \"Maandag t/m vrijdag\", hours: \"09:00 – 17:00\" },\n { day: \"Zaterdag\", hours: \"10:00 – 16:00\" },\n { day: \"Zondag\", hours: \"Gesloten\" },\n ],\n }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,oBAAoB,YAAY;AAAA,EAC3C,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,sBAAsB,EAAE,KAAK,CAAC,MAAM,EAAE,kBAAkB,CAAC;AAAA,EACtF,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO;AAAA,IACf,SAAS;AAAA,IACT,MAAM;AAAA,MACJ,EAAE,KAAK,uBAAuB,OAAO,qBAAgB;AAAA,MACrD,EAAE,KAAK,YAAY,OAAO,qBAAgB;AAAA,MAC1C,EAAE,KAAK,UAAU,OAAO,WAAW;AAAA,IACrC;AAAA,EACF;AACF,CAAC;","names":[]}
@@ -0,0 +1,7 @@
1
+ import type { z } from "zod";
2
+ import type { OpeningHoursBlockSchema } from "../../schema/blocks.js";
3
+ import type { BlockRenderProps } from "../registry.js";
4
+ type OpeningHours = z.infer<typeof OpeningHoursBlockSchema>;
5
+ /** Openingstijden-tabel. Server-safe; de optionele "Nu geopend"-badge is een client-eiland. */
6
+ export declare function OpeningHoursRender({ block }: BlockRenderProps<OpeningHours>): import("react").JSX.Element;
7
+ export {};
@@ -0,0 +1,31 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { jsonLdHtml } from "./jsonld.js";
3
+ import { Heading } from "../ui/index.js";
4
+ import { OpenNowBadge } from "./OpenNowBadge.js";
5
+ import { openingHoursSpecJsonLd } from "./lib/openingHours.js";
6
+ function OpeningHoursRender({ block }) {
7
+ const rows = block.rows ?? [];
8
+ const spec = block.jsonLd ? openingHoursSpecJsonLd(rows) : [];
9
+ return /* @__PURE__ */ jsxs("section", { className: "xicms-hours", children: [
10
+ block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
11
+ block.showStatus && /* @__PURE__ */ jsx(OpenNowBadge, { rows }),
12
+ /* @__PURE__ */ jsx("table", { className: "xicms-hours-table", children: /* @__PURE__ */ jsx("tbody", { children: rows.map((r, i) => /* @__PURE__ */ jsxs("tr", { children: [
13
+ /* @__PURE__ */ jsx("th", { scope: "row", "data-xicms-edit": `rows.${i}.day`, children: r.day }),
14
+ /* @__PURE__ */ jsx("td", { "data-xicms-edit": `rows.${i}.hours`, children: r.hours })
15
+ ] }, i)) }) }),
16
+ spec.length > 0 && /* @__PURE__ */ jsx(
17
+ "script",
18
+ {
19
+ type: "application/ld+json",
20
+ dangerouslySetInnerHTML: {
21
+ // Zelfde @id als contact-/layout-JSON-LD → Google voegt de drie samen tot één bedrijf.
22
+ __html: jsonLdHtml({ "@context": "https://schema.org", "@type": "LocalBusiness", "@id": "#business", openingHoursSpecification: spec })
23
+ }
24
+ }
25
+ )
26
+ ] });
27
+ }
28
+ export {
29
+ OpeningHoursRender
30
+ };
31
+ //# sourceMappingURL=OpeningHoursRender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/blocks/builtins/OpeningHoursRender.tsx"],"sourcesContent":["import type { z } from \"zod\";\nimport { jsonLdHtml } from \"./jsonld\";\nimport type { OpeningHoursBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { Heading } from \"../ui\";\nimport { OpenNowBadge } from \"./OpenNowBadge\";\nimport { openingHoursSpecJsonLd } from \"./lib/openingHours\";\n\ntype OpeningHours = z.infer<typeof OpeningHoursBlockSchema>;\n\n/** Openingstijden-tabel. Server-safe; de optionele \"Nu geopend\"-badge is een client-eiland. */\nexport function OpeningHoursRender({ block }: BlockRenderProps<OpeningHours>) {\n const rows = block.rows ?? [];\n const spec = block.jsonLd ? openingHoursSpecJsonLd(rows) : [];\n return (\n <section className=\"xicms-hours\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n {block.showStatus && <OpenNowBadge rows={rows} />}\n <table className=\"xicms-hours-table\">\n <tbody>\n {rows.map((r, i) => (\n <tr key={i}>\n <th scope=\"row\" data-xicms-edit={`rows.${i}.day`}>{r.day}</th>\n <td data-xicms-edit={`rows.${i}.hours`}>{r.hours}</td>\n </tr>\n ))}\n </tbody>\n </table>\n {spec.length > 0 && (\n <script\n type=\"application/ld+json\"\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n // Zelfde @id als contact-/layout-JSON-LD → Google voegt de drie samen tot één bedrijf.\n __html: jsonLdHtml({ \"@context\": \"https://schema.org\", \"@type\": \"LocalBusiness\", \"@id\": \"#business\", openingHoursSpecification: spec }),\n }}\n />\n )}\n </section>\n );\n}\n"],"mappings":"AAgBwB,cAKZ,YALY;AAfxB,SAAS,kBAAkB;AAG3B,SAAS,eAAe;AACxB,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AAKhC,SAAS,mBAAmB,EAAE,MAAM,GAAmC;AAC5E,QAAM,OAAO,MAAM,QAAQ,CAAC;AAC5B,QAAM,OAAO,MAAM,SAAS,uBAAuB,IAAI,IAAI,CAAC;AAC5D,SACE,qBAAC,aAAQ,WAAU,eAChB;AAAA,UAAM,WAAW,oBAAC,WAAQ,OAAO,GAAG,mBAAgB,WAAW,gBAAM,SAAQ;AAAA,IAC7E,MAAM,cAAc,oBAAC,gBAAa,MAAY;AAAA,IAC/C,oBAAC,WAAM,WAAU,qBACf,8BAAC,WACE,eAAK,IAAI,CAAC,GAAG,MACZ,qBAAC,QACC;AAAA,0BAAC,QAAG,OAAM,OAAM,mBAAiB,QAAQ,CAAC,QAAS,YAAE,KAAI;AAAA,MACzD,oBAAC,QAAG,mBAAiB,QAAQ,CAAC,UAAW,YAAE,OAAM;AAAA,SAF1C,CAGT,CACD,GACH,GACF;AAAA,IACC,KAAK,SAAS,KACb;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QAEL,yBAAyB;AAAA;AAAA,UAEvB,QAAQ,WAAW,EAAE,YAAY,sBAAsB,SAAS,iBAAiB,OAAO,aAAa,2BAA2B,KAAK,CAAC;AAAA,QACxI;AAAA;AAAA,IACF;AAAA,KAEJ;AAEJ;","names":[]}
@@ -1,2 +1 @@
1
- import type { z } from "zod";
2
- export declare const pdfBlock: import("../index.js").BlockDefinition<z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
1
+ export declare const pdfBlock: import("../index.js").BlockDefinition<import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>>;
@@ -1,82 +1,8 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useState } from "react";
4
- import { Onvoltooid } from "./lib/Onvoltooid.js";
1
+ import dynamic from "next/dynamic";
5
2
  import { defineBlock } from "../registry.js";
6
- import { VStack, HStack, Heading, Text } from "../ui/index.js";
7
- function PdfRender({ block, mode }) {
8
- const docs = (block.documents ?? []).map((d, i) => ({ ...d, _i: i })).filter((d) => d.url);
9
- const [active, setActive] = useState(0);
10
- if (docs.length === 0 && !block.heading) return null;
11
- const current = docs[Math.min(active, docs.length - 1)];
12
- return /* @__PURE__ */ jsxs(VStack, { gap: 3, as: "section", children: [
13
- block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
14
- docs.length > 1 && /* @__PURE__ */ jsx(HStack, { gap: 1, style: { flexWrap: "wrap" }, role: "group", "aria-label": "Kies document", children: docs.map((d, i) => /* @__PURE__ */ jsx(
15
- "button",
16
- {
17
- type: "button",
18
- "aria-pressed": i === active,
19
- onClick: () => setActive(i),
20
- style: {
21
- padding: "0.4rem 0.9rem",
22
- borderRadius: "var(--radius-full, 999px)",
23
- border: "1px solid var(--color-border)",
24
- cursor: "pointer",
25
- fontWeight: 600,
26
- fontSize: "0.9rem",
27
- background: i === active ? "var(--color-accent)" : "transparent",
28
- color: i === active ? "var(--color-on-accent)" : "var(--color-text-primary)"
29
- },
30
- children: /* @__PURE__ */ jsx("span", { "data-xicms-edit": `documents.${d._i}.label`, children: d.label || `Document ${i + 1}` })
31
- },
32
- i
33
- )) }),
34
- current ? /* @__PURE__ */ jsx(
35
- "div",
36
- {
37
- style: {
38
- borderRadius: "var(--radius-container)",
39
- overflow: "hidden",
40
- border: "1px solid var(--color-border)",
41
- background: "var(--color-background-muted, rgba(0,0,0,0.03))"
42
- },
43
- children: mode === "preview" ? /* @__PURE__ */ jsx("div", { className: "xicms-embed-consent xicms-embed-preview", role: "note", style: { height: Math.min(block.height, 360) }, children: /* @__PURE__ */ jsxs("p", { children: [
44
- "\u{1F4C4} PDF \u201C",
45
- current.label || "document",
46
- "\u201D \u2014 wordt op de live site geladen (niet in de editor)."
47
- ] }) }) : (
48
- // <object> i.p.v. <iframe>: browsers zonder inline PDF-viewer (veel mobiel) tonen
49
- // dan de fallback-inhoud met een open/download-knop i.p.v. een leeg vlak.
50
- /* @__PURE__ */ jsx(
51
- "object",
52
- {
53
- data: `${current.url}#view=FitH`,
54
- type: "application/pdf",
55
- "aria-label": current.label || block.heading || "PDF",
56
- style: { border: 0, width: "100%", height: block.height, display: "block" },
57
- children: /* @__PURE__ */ jsxs("div", { style: { display: "grid", placeItems: "center", gap: "0.6rem", padding: "2.5rem 1rem", textAlign: "center" }, children: [
58
- /* @__PURE__ */ jsx(Text, { color: "secondary", children: "Je browser kan deze PDF niet inline tonen." }),
59
- /* @__PURE__ */ jsxs("a", { className: "xicms-btn", href: current.url, target: "_blank", rel: "noopener noreferrer", children: [
60
- "\u{1F4C4} Open \u201C",
61
- current.label || "PDF",
62
- "\u201D"
63
- ] })
64
- ] })
65
- }
66
- )
67
- )
68
- }
69
- ) : /* @__PURE__ */ jsx(Onvoltooid, { children: "Dit PDF-blok is nog leeg: kies een document via het tandwiel. Bezoekers zien dit blok niet." }),
70
- block.showDownload && current && /* @__PURE__ */ jsx("a", { href: current.url, target: "_blank", rel: "noopener noreferrer", style: { color: "var(--color-accent)" }, children: /* @__PURE__ */ jsxs(Text, { type: "label", children: [
71
- "\u2197 Open \u201C",
72
- current.label || "PDF",
73
- "\u201D in een nieuw tabblad"
74
- ] }) })
75
- ] });
76
- }
77
3
  const pdfBlock = defineBlock({
78
4
  type: "pdf",
79
- Render: PdfRender,
5
+ Render: dynamic(() => import("./PdfBlockRender.js").then((m) => m.PdfRender)),
80
6
  label: "PDF-lezer (menu/document)",
81
7
  icon: "\u{1F4C4}",
82
8
  defaults: () => ({