@xiwebdesign/xicms-core 7.14.0 → 7.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (238) hide show
  1. package/dist/blocks/builtins/Accordion.d.ts +1 -2
  2. package/dist/blocks/builtins/Accordion.js +2 -39
  3. package/dist/blocks/builtins/Accordion.js.map +1 -1
  4. package/dist/blocks/builtins/AccordionRender.d.ts +7 -0
  5. package/dist/blocks/builtins/AccordionRender.js +42 -0
  6. package/dist/blocks/builtins/AccordionRender.js.map +1 -0
  7. package/dist/blocks/builtins/Agenda.d.ts +1 -29
  8. package/dist/blocks/builtins/Agenda.js +3 -94
  9. package/dist/blocks/builtins/Agenda.js.map +1 -1
  10. package/dist/blocks/builtins/AgendaRender.d.ts +34 -0
  11. package/dist/blocks/builtins/AgendaRender.js +96 -0
  12. package/dist/blocks/builtins/AgendaRender.js.map +1 -0
  13. package/dist/blocks/builtins/Banner.d.ts +1 -2
  14. package/dist/blocks/builtins/Banner.js +2 -32
  15. package/dist/blocks/builtins/Banner.js.map +1 -1
  16. package/dist/blocks/builtins/BannerRender.d.ts +11 -0
  17. package/dist/blocks/builtins/BannerRender.js +35 -0
  18. package/dist/blocks/builtins/BannerRender.js.map +1 -0
  19. package/dist/blocks/builtins/BeforeAfter.d.ts +1 -2
  20. package/dist/blocks/builtins/BeforeAfter.js +2 -31
  21. package/dist/blocks/builtins/BeforeAfter.js.map +1 -1
  22. package/dist/blocks/builtins/BeforeAfterRender.d.ts +11 -0
  23. package/dist/blocks/builtins/BeforeAfterRender.js +34 -0
  24. package/dist/blocks/builtins/BeforeAfterRender.js.map +1 -0
  25. package/dist/blocks/builtins/Booking.d.ts +1 -2
  26. package/dist/blocks/builtins/Booking.js +2 -14
  27. package/dist/blocks/builtins/Booking.js.map +1 -1
  28. package/dist/blocks/builtins/BookingRender.d.ts +8 -0
  29. package/dist/blocks/builtins/BookingRender.js +17 -0
  30. package/dist/blocks/builtins/BookingRender.js.map +1 -0
  31. package/dist/blocks/builtins/Breadcrumbs.d.ts +1 -10
  32. package/dist/blocks/builtins/Breadcrumbs.js +3 -69
  33. package/dist/blocks/builtins/Breadcrumbs.js.map +1 -1
  34. package/dist/blocks/builtins/BreadcrumbsRender.d.ts +18 -0
  35. package/dist/blocks/builtins/BreadcrumbsRender.js +71 -0
  36. package/dist/blocks/builtins/BreadcrumbsRender.js.map +1 -0
  37. package/dist/blocks/builtins/Cards.d.ts +1 -2
  38. package/dist/blocks/builtins/Cards.js +2 -74
  39. package/dist/blocks/builtins/Cards.js.map +1 -1
  40. package/dist/blocks/builtins/CardsRender.d.ts +7 -0
  41. package/dist/blocks/builtins/CardsRender.js +77 -0
  42. package/dist/blocks/builtins/CardsRender.js.map +1 -0
  43. package/dist/blocks/builtins/Columns.d.ts +1 -2
  44. package/dist/blocks/builtins/Columns.js +2 -9
  45. package/dist/blocks/builtins/Columns.js.map +1 -1
  46. package/dist/blocks/builtins/ColumnsRender.d.ts +6 -0
  47. package/dist/blocks/builtins/ColumnsRender.js +12 -0
  48. package/dist/blocks/builtins/ColumnsRender.js.map +1 -0
  49. package/dist/blocks/builtins/Contact.d.ts +2 -7
  50. package/dist/blocks/builtins/Contact.js +3 -102
  51. package/dist/blocks/builtins/Contact.js.map +1 -1
  52. package/dist/blocks/builtins/ContactRender.d.ts +9 -0
  53. package/dist/blocks/builtins/ContactRender.js +105 -0
  54. package/dist/blocks/builtins/ContactRender.js.map +1 -0
  55. package/dist/blocks/builtins/Countdown.d.ts +1 -18
  56. package/dist/blocks/builtins/Countdown.js +3 -53
  57. package/dist/blocks/builtins/Countdown.js.map +1 -1
  58. package/dist/blocks/builtins/CountdownRender.d.ts +22 -0
  59. package/dist/blocks/builtins/CountdownRender.js +55 -0
  60. package/dist/blocks/builtins/CountdownRender.js.map +1 -0
  61. package/dist/blocks/builtins/Cta.d.ts +1 -2
  62. package/dist/blocks/builtins/Cta.js +2 -39
  63. package/dist/blocks/builtins/Cta.js.map +1 -1
  64. package/dist/blocks/builtins/CtaRender.d.ts +6 -0
  65. package/dist/blocks/builtins/CtaRender.js +42 -0
  66. package/dist/blocks/builtins/CtaRender.js.map +1 -0
  67. package/dist/blocks/builtins/Downloads.d.ts +1 -2
  68. package/dist/blocks/builtins/Downloads.js +2 -16
  69. package/dist/blocks/builtins/Downloads.js.map +1 -1
  70. package/dist/blocks/builtins/DownloadsRender.d.ts +7 -0
  71. package/dist/blocks/builtins/DownloadsRender.js +19 -0
  72. package/dist/blocks/builtins/DownloadsRender.js.map +1 -0
  73. package/dist/blocks/builtins/Elements.d.ts +3 -4
  74. package/dist/blocks/builtins/Elements.js +4 -38
  75. package/dist/blocks/builtins/Elements.js.map +1 -1
  76. package/dist/blocks/builtins/ElementsRender.d.ts +10 -0
  77. package/dist/blocks/builtins/ElementsRender.js +41 -0
  78. package/dist/blocks/builtins/ElementsRender.js.map +1 -0
  79. package/dist/blocks/builtins/Embed.d.ts +1 -2
  80. package/dist/blocks/builtins/Embed.js +2 -19
  81. package/dist/blocks/builtins/Embed.js.map +1 -1
  82. package/dist/blocks/builtins/EmbedRender.d.ts +7 -0
  83. package/dist/blocks/builtins/EmbedRender.js +22 -0
  84. package/dist/blocks/builtins/EmbedRender.js.map +1 -0
  85. package/dist/blocks/builtins/Faq.d.ts +1 -6
  86. package/dist/blocks/builtins/Faq.js +3 -103
  87. package/dist/blocks/builtins/Faq.js.map +1 -1
  88. package/dist/blocks/builtins/FaqRender.d.ts +10 -0
  89. package/dist/blocks/builtins/FaqRender.js +105 -0
  90. package/dist/blocks/builtins/FaqRender.js.map +1 -0
  91. package/dist/blocks/builtins/FormBlock.d.ts +1 -2
  92. package/dist/blocks/builtins/FormBlock.js +2 -222
  93. package/dist/blocks/builtins/FormBlock.js.map +1 -1
  94. package/dist/blocks/builtins/FormBlockRender.d.ts +6 -0
  95. package/dist/blocks/builtins/FormBlockRender.js +225 -0
  96. package/dist/blocks/builtins/FormBlockRender.js.map +1 -0
  97. package/dist/blocks/builtins/Gallery.d.ts +1 -23
  98. package/dist/blocks/builtins/Gallery.js +2 -164
  99. package/dist/blocks/builtins/Gallery.js.map +1 -1
  100. package/dist/blocks/builtins/GalleryRender.d.ts +25 -0
  101. package/dist/blocks/builtins/GalleryRender.js +167 -0
  102. package/dist/blocks/builtins/GalleryRender.js.map +1 -0
  103. package/dist/blocks/builtins/Hero.d.ts +1 -2
  104. package/dist/blocks/builtins/Hero.js +2 -73
  105. package/dist/blocks/builtins/Hero.js.map +1 -1
  106. package/dist/blocks/builtins/HeroRender.d.ts +6 -0
  107. package/dist/blocks/builtins/HeroRender.js +76 -0
  108. package/dist/blocks/builtins/HeroRender.js.map +1 -0
  109. package/dist/blocks/builtins/ImageBlock.d.ts +1 -2
  110. package/dist/blocks/builtins/ImageBlock.js +2 -22
  111. package/dist/blocks/builtins/ImageBlock.js.map +1 -1
  112. package/dist/blocks/builtins/ImageBlockRender.d.ts +6 -0
  113. package/dist/blocks/builtins/ImageBlockRender.js +25 -0
  114. package/dist/blocks/builtins/ImageBlockRender.js.map +1 -0
  115. package/dist/blocks/builtins/Jobs.d.ts +1 -15
  116. package/dist/blocks/builtins/Jobs.js +3 -69
  117. package/dist/blocks/builtins/Jobs.js.map +1 -1
  118. package/dist/blocks/builtins/JobsRender.d.ts +17 -0
  119. package/dist/blocks/builtins/JobsRender.js +71 -0
  120. package/dist/blocks/builtins/JobsRender.js.map +1 -0
  121. package/dist/blocks/builtins/Layout.d.ts +2 -3
  122. package/dist/blocks/builtins/Layout.js +3 -39
  123. package/dist/blocks/builtins/Layout.js.map +1 -1
  124. package/dist/blocks/builtins/LayoutRender.d.ts +8 -0
  125. package/dist/blocks/builtins/LayoutRender.js +42 -0
  126. package/dist/blocks/builtins/LayoutRender.js.map +1 -0
  127. package/dist/blocks/builtins/MapBlock.d.ts +1 -2
  128. package/dist/blocks/builtins/MapBlock.js +2 -45
  129. package/dist/blocks/builtins/MapBlock.js.map +1 -1
  130. package/dist/blocks/builtins/MapBlockRender.d.ts +6 -0
  131. package/dist/blocks/builtins/MapBlockRender.js +48 -0
  132. package/dist/blocks/builtins/MapBlockRender.js.map +1 -0
  133. package/dist/blocks/builtins/NewsListBlock.d.ts +1 -2
  134. package/dist/blocks/builtins/NewsListBlock.js +2 -11
  135. package/dist/blocks/builtins/NewsListBlock.js.map +1 -1
  136. package/dist/blocks/builtins/NewsListBlockRender.d.ts +6 -0
  137. package/dist/blocks/builtins/NewsListBlockRender.js +14 -0
  138. package/dist/blocks/builtins/NewsListBlockRender.js.map +1 -0
  139. package/dist/blocks/builtins/Newsletter.d.ts +1 -2
  140. package/dist/blocks/builtins/Newsletter.js +2 -89
  141. package/dist/blocks/builtins/Newsletter.js.map +1 -1
  142. package/dist/blocks/builtins/NewsletterRender.d.ts +13 -0
  143. package/dist/blocks/builtins/NewsletterRender.js +92 -0
  144. package/dist/blocks/builtins/NewsletterRender.js.map +1 -0
  145. package/dist/blocks/builtins/OpeningHours.d.ts +1 -2
  146. package/dist/blocks/builtins/OpeningHours.js +2 -28
  147. package/dist/blocks/builtins/OpeningHours.js.map +1 -1
  148. package/dist/blocks/builtins/OpeningHoursRender.d.ts +7 -0
  149. package/dist/blocks/builtins/OpeningHoursRender.js +31 -0
  150. package/dist/blocks/builtins/OpeningHoursRender.js.map +1 -0
  151. package/dist/blocks/builtins/PdfBlock.d.ts +1 -2
  152. package/dist/blocks/builtins/PdfBlock.js +2 -76
  153. package/dist/blocks/builtins/PdfBlock.js.map +1 -1
  154. package/dist/blocks/builtins/PdfBlockRender.d.ts +11 -0
  155. package/dist/blocks/builtins/PdfBlockRender.js +79 -0
  156. package/dist/blocks/builtins/PdfBlockRender.js.map +1 -0
  157. package/dist/blocks/builtins/Portfolio.d.ts +1 -2
  158. package/dist/blocks/builtins/Portfolio.js +2 -75
  159. package/dist/blocks/builtins/Portfolio.js.map +1 -1
  160. package/dist/blocks/builtins/PortfolioRender.d.ts +7 -0
  161. package/dist/blocks/builtins/PortfolioRender.js +78 -0
  162. package/dist/blocks/builtins/PortfolioRender.js.map +1 -0
  163. package/dist/blocks/builtins/Pricing.d.ts +1 -8
  164. package/dist/blocks/builtins/Pricing.js +3 -73
  165. package/dist/blocks/builtins/Pricing.js.map +1 -1
  166. package/dist/blocks/builtins/PricingRender.d.ts +10 -0
  167. package/dist/blocks/builtins/PricingRender.js +75 -0
  168. package/dist/blocks/builtins/PricingRender.js.map +1 -0
  169. package/dist/blocks/builtins/RichTextBlock.d.ts +1 -2
  170. package/dist/blocks/builtins/RichTextBlock.js +2 -5
  171. package/dist/blocks/builtins/RichTextBlock.js.map +1 -1
  172. package/dist/blocks/builtins/RichTextBlockRender.d.ts +6 -0
  173. package/dist/blocks/builtins/RichTextBlockRender.js +8 -0
  174. package/dist/blocks/builtins/RichTextBlockRender.js.map +1 -0
  175. package/dist/blocks/builtins/Search.d.ts +1 -2
  176. package/dist/blocks/builtins/Search.js +2 -80
  177. package/dist/blocks/builtins/Search.js.map +1 -1
  178. package/dist/blocks/builtins/SearchRender.d.ts +7 -0
  179. package/dist/blocks/builtins/SearchRender.js +83 -0
  180. package/dist/blocks/builtins/SearchRender.js.map +1 -0
  181. package/dist/blocks/builtins/Sections.d.ts +4 -5
  182. package/dist/blocks/builtins/Sections.js +5 -142
  183. package/dist/blocks/builtins/Sections.js.map +1 -1
  184. package/dist/blocks/builtins/SectionsRender.d.ts +12 -0
  185. package/dist/blocks/builtins/SectionsRender.js +145 -0
  186. package/dist/blocks/builtins/SectionsRender.js.map +1 -0
  187. package/dist/blocks/builtins/Slider.d.ts +1 -2
  188. package/dist/blocks/builtins/Slider.js +2 -134
  189. package/dist/blocks/builtins/Slider.js.map +1 -1
  190. package/dist/blocks/builtins/SliderRender.d.ts +7 -0
  191. package/dist/blocks/builtins/SliderRender.js +137 -0
  192. package/dist/blocks/builtins/SliderRender.js.map +1 -0
  193. package/dist/blocks/builtins/Spacer.d.ts +1 -2
  194. package/dist/blocks/builtins/Spacer.js +2 -6
  195. package/dist/blocks/builtins/Spacer.js.map +1 -1
  196. package/dist/blocks/builtins/SpacerRender.d.ts +6 -0
  197. package/dist/blocks/builtins/SpacerRender.js +9 -0
  198. package/dist/blocks/builtins/SpacerRender.js.map +1 -0
  199. package/dist/blocks/builtins/SymbolRef.d.ts +1 -2
  200. package/dist/blocks/builtins/SymbolRef.js +2 -76
  201. package/dist/blocks/builtins/SymbolRef.js.map +1 -1
  202. package/dist/blocks/builtins/SymbolRefRender.d.ts +13 -0
  203. package/dist/blocks/builtins/SymbolRefRender.js +79 -0
  204. package/dist/blocks/builtins/SymbolRefRender.js.map +1 -0
  205. package/dist/blocks/builtins/Team.d.ts +1 -2
  206. package/dist/blocks/builtins/Team.js +2 -55
  207. package/dist/blocks/builtins/Team.js.map +1 -1
  208. package/dist/blocks/builtins/TeamRender.d.ts +7 -0
  209. package/dist/blocks/builtins/TeamRender.js +58 -0
  210. package/dist/blocks/builtins/TeamRender.js.map +1 -0
  211. package/dist/blocks/builtins/Testimonials.d.ts +1 -8
  212. package/dist/blocks/builtins/Testimonials.js +2 -69
  213. package/dist/blocks/builtins/Testimonials.js.map +1 -1
  214. package/dist/blocks/builtins/TestimonialsRender.d.ts +10 -0
  215. package/dist/blocks/builtins/TestimonialsRender.js +72 -0
  216. package/dist/blocks/builtins/TestimonialsRender.js.map +1 -0
  217. package/dist/blocks/builtins/Video.d.ts +1 -9
  218. package/dist/blocks/builtins/Video.js +2 -64
  219. package/dist/blocks/builtins/Video.js.map +1 -1
  220. package/dist/blocks/builtins/VideoRender.d.ts +10 -0
  221. package/dist/blocks/builtins/VideoRender.js +67 -0
  222. package/dist/blocks/builtins/VideoRender.js.map +1 -0
  223. package/dist/blocks/builtins/WhatsappChat.d.ts +1 -8
  224. package/dist/blocks/builtins/WhatsappChat.js +2 -37
  225. package/dist/blocks/builtins/WhatsappChat.js.map +1 -1
  226. package/dist/blocks/builtins/WhatsappChatRender.d.ts +17 -0
  227. package/dist/blocks/builtins/WhatsappChatRender.js +40 -0
  228. package/dist/blocks/builtins/WhatsappChatRender.js.map +1 -0
  229. package/dist/blocks/builtins/Widgets.d.ts +12 -13
  230. package/dist/blocks/builtins/Widgets.js +13 -175
  231. package/dist/blocks/builtins/Widgets.js.map +1 -1
  232. package/dist/blocks/builtins/WidgetsRender.d.ts +34 -0
  233. package/dist/blocks/builtins/WidgetsRender.js +178 -0
  234. package/dist/blocks/builtins/WidgetsRender.js.map +1 -0
  235. package/dist/modules/contract.js +2 -1
  236. package/dist/modules/contract.js.map +1 -1
  237. package/dist/version.js +1 -1
  238. package/package.json +1 -1
@@ -1,2 +1 @@
1
- import type { z } from "zod";
2
- export declare const accordionBlock: import("../index.js").BlockDefinition<z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
1
+ export declare const accordionBlock: import("../index.js").BlockDefinition<import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>>;
@@ -1,45 +1,8 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useState } from "react";
1
+ import dynamic from "next/dynamic";
4
2
  import { defineBlock } from "../registry.js";
5
- import { Collapsible } from "@astryxdesign/core/Collapsible";
6
- import { VStack, Heading, Text } from "../ui/index.js";
7
- function AccordionRender({ block }) {
8
- const items = (block.items ?? []).filter((i) => i.title);
9
- const [openIdx, setOpenIdx] = useState(null);
10
- if (items.length === 0) return null;
11
- return /* @__PURE__ */ jsxs(VStack, { gap: 3, as: "section", className: "xicms-accordion", children: [
12
- block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
13
- /* @__PURE__ */ jsx(VStack, { gap: 1.5, children: items.map((it, i) => {
14
- const body = it.bodyHtml ? (
15
- // Server-side gesanitized bij publiceren (*Html-velden) — zie functions/lib/sanitize.
16
- // eslint-disable-next-line react/no-danger
17
- /* @__PURE__ */ jsx(
18
- "div",
19
- {
20
- className: "xicms-richtext",
21
- "data-xicms-edit": `items.${i}.bodyHtml`,
22
- dangerouslySetInnerHTML: { __html: it.bodyHtml }
23
- }
24
- )
25
- ) : /* @__PURE__ */ jsx(Text, { color: "secondary", "data-xicms-edit": `items.${i}.body`, children: it.body });
26
- const trigger = /* @__PURE__ */ jsx(Text, { weight: "bold", "data-xicms-edit": `items.${i}.title`, children: it.title });
27
- return block.multiple ? /* @__PURE__ */ jsx(Collapsible, { trigger, defaultIsOpen: false, children: body }, i) : /* @__PURE__ */ jsx(
28
- Collapsible,
29
- {
30
- trigger,
31
- isOpen: openIdx === i,
32
- onOpenChange: (o) => setOpenIdx(o ? i : null),
33
- children: body
34
- },
35
- i
36
- );
37
- }) })
38
- ] });
39
- }
40
3
  const accordionBlock = defineBlock({
41
4
  type: "accordion",
42
- Render: AccordionRender,
5
+ Render: dynamic(() => import("./AccordionRender.js").then((m) => m.AccordionRender)),
43
6
  label: "Accordeon",
44
7
  icon: "\u{1FA97}",
45
8
  defaults: () => ({ items: [{ title: "Titel", body: "Inhoud\u2026" }], multiple: false })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/builtins/Accordion.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport type { z } from \"zod\";\nimport type { AccordionBlockSchema } from \"../../schema/blocks\";\nimport { defineBlock, type BlockRenderProps } from \"../registry\";\nimport { Collapsible } from \"@astryxdesign/core/Collapsible\";\nimport { VStack, Heading, Text } from \"../ui\";\n\ntype Accordion = z.infer<typeof AccordionBlockSchema>;\n\n/** Accordeon op Astryx Collapsible. Bij `multiple: false` is er max. één paneel tegelijk open. */\nfunction AccordionRender({ block }: BlockRenderProps<Accordion>) {\n const items = (block.items ?? []).filter((i) => i.title);\n const [openIdx, setOpenIdx] = useState<number | null>(null);\n if (items.length === 0) return null;\n return (\n <VStack gap={3} as=\"section\" className=\"xicms-accordion\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n <VStack gap={1.5}>\n {items.map((it, i) => {\n const body = it.bodyHtml ? (\n // Server-side gesanitized bij publiceren (*Html-velden) — zie functions/lib/sanitize.\n // eslint-disable-next-line react/no-danger\n <div\n className=\"xicms-richtext\"\n data-xicms-edit={`items.${i}.bodyHtml`}\n dangerouslySetInnerHTML={{ __html: it.bodyHtml }}\n />\n ) : (\n <Text color=\"secondary\" data-xicms-edit={`items.${i}.body`}>{it.body}</Text>\n );\n const trigger = <Text weight=\"bold\" data-xicms-edit={`items.${i}.title`}>{it.title}</Text>;\n return block.multiple ? (\n <Collapsible key={i} trigger={trigger} defaultIsOpen={false}>{body}</Collapsible>\n ) : (\n <Collapsible\n key={i}\n trigger={trigger}\n isOpen={openIdx === i}\n onOpenChange={(o) => setOpenIdx(o ? i : null)}\n >\n {body}\n </Collapsible>\n );\n })}\n </VStack>\n </VStack>\n );\n}\n\nexport const accordionBlock = defineBlock({\n type: \"accordion\",\n Render: AccordionRender,\n label: \"Accordeon\",\n icon: \"🪗\",\n defaults: () => ({ items: [{ title: \"Titel\", body: \"Inhoud…\" }], multiple: false }),\n});\n"],"mappings":";AAiBI,SACoB,KADpB;AAfJ,SAAS,gBAAgB;AAGzB,SAAS,mBAA0C;AACnD,SAAS,mBAAmB;AAC5B,SAAS,QAAQ,SAAS,YAAY;AAKtC,SAAS,gBAAgB,EAAE,MAAM,GAAgC;AAC/D,QAAM,SAAS,MAAM,SAAS,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK;AACvD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAwB,IAAI;AAC1D,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SACE,qBAAC,UAAO,KAAK,GAAG,IAAG,WAAU,WAAU,mBACpC;AAAA,UAAM,WAAW,oBAAC,WAAQ,OAAO,GAAG,mBAAgB,WAAW,gBAAM,SAAQ;AAAA,IAC9E,oBAAC,UAAO,KAAK,KACV,gBAAM,IAAI,CAAC,IAAI,MAAM;AACpB,YAAM,OAAO,GAAG;AAAA;AAAA;AAAA,QAGd;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,mBAAiB,SAAS,CAAC;AAAA,YAC3B,yBAAyB,EAAE,QAAQ,GAAG,SAAS;AAAA;AAAA,QACjD;AAAA,UAEA,oBAAC,QAAK,OAAM,aAAY,mBAAiB,SAAS,CAAC,SAAU,aAAG,MAAK;AAEvE,YAAM,UAAU,oBAAC,QAAK,QAAO,QAAO,mBAAiB,SAAS,CAAC,UAAW,aAAG,OAAM;AACnF,aAAO,MAAM,WACX,oBAAC,eAAoB,SAAkB,eAAe,OAAQ,kBAA5C,CAAiD,IAEnE;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,QAAQ,YAAY;AAAA,UACpB,cAAc,CAAC,MAAM,WAAW,IAAI,IAAI,IAAI;AAAA,UAE3C;AAAA;AAAA,QALI;AAAA,MAMP;AAAA,IAEJ,CAAC,GACH;AAAA,KACF;AAEJ;AAEO,MAAM,iBAAiB,YAAY;AAAA,EACxC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,SAAS,MAAM,eAAU,CAAC,GAAG,UAAU,MAAM;AACnF,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/builtins/Accordion.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const accordionBlock = defineBlock({\n type: \"accordion\",\n Render: dynamic(() => import(\"./AccordionRender\").then((m) => m.AccordionRender)),\n label: \"Accordeon\",\n icon: \"🪗\",\n defaults: () => ({ items: [{ title: \"Titel\", body: \"Inhoud…\" }], multiple: false }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,iBAAiB,YAAY;AAAA,EACxC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,mBAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe,CAAC;AAAA,EAChF,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,SAAS,MAAM,eAAU,CAAC,GAAG,UAAU,MAAM;AACnF,CAAC;","names":[]}
@@ -0,0 +1,7 @@
1
+ import type { z } from "zod";
2
+ import type { AccordionBlockSchema } from "../../schema/blocks.js";
3
+ import type { BlockRenderProps } from "../registry.js";
4
+ type Accordion = z.infer<typeof AccordionBlockSchema>;
5
+ /** Accordeon op Astryx Collapsible. Bij `multiple: false` is er max. één paneel tegelijk open. */
6
+ export declare function AccordionRender({ block }: BlockRenderProps<Accordion>): import("react").JSX.Element | null;
7
+ export {};
@@ -0,0 +1,42 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState } from "react";
4
+ import { Collapsible } from "@astryxdesign/core/Collapsible";
5
+ import { VStack, Heading, Text } from "../ui/index.js";
6
+ function AccordionRender({ block }) {
7
+ const items = (block.items ?? []).filter((i) => i.title);
8
+ const [openIdx, setOpenIdx] = useState(null);
9
+ if (items.length === 0) return null;
10
+ return /* @__PURE__ */ jsxs(VStack, { gap: 3, as: "section", className: "xicms-accordion", children: [
11
+ block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
12
+ /* @__PURE__ */ jsx(VStack, { gap: 1.5, children: items.map((it, i) => {
13
+ const body = it.bodyHtml ? (
14
+ // Server-side gesanitized bij publiceren (*Html-velden) — zie functions/lib/sanitize.
15
+ // eslint-disable-next-line react/no-danger
16
+ /* @__PURE__ */ jsx(
17
+ "div",
18
+ {
19
+ className: "xicms-richtext",
20
+ "data-xicms-edit": `items.${i}.bodyHtml`,
21
+ dangerouslySetInnerHTML: { __html: it.bodyHtml }
22
+ }
23
+ )
24
+ ) : /* @__PURE__ */ jsx(Text, { color: "secondary", "data-xicms-edit": `items.${i}.body`, children: it.body });
25
+ const trigger = /* @__PURE__ */ jsx(Text, { weight: "bold", "data-xicms-edit": `items.${i}.title`, children: it.title });
26
+ return block.multiple ? /* @__PURE__ */ jsx(Collapsible, { trigger, defaultIsOpen: false, children: body }, i) : /* @__PURE__ */ jsx(
27
+ Collapsible,
28
+ {
29
+ trigger,
30
+ isOpen: openIdx === i,
31
+ onOpenChange: (o) => setOpenIdx(o ? i : null),
32
+ children: body
33
+ },
34
+ i
35
+ );
36
+ }) })
37
+ ] });
38
+ }
39
+ export {
40
+ AccordionRender
41
+ };
42
+ //# sourceMappingURL=AccordionRender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/blocks/builtins/AccordionRender.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport type { z } from \"zod\";\nimport type { AccordionBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { Collapsible } from \"@astryxdesign/core/Collapsible\";\nimport { VStack, Heading, Text } from \"../ui\";\n\ntype Accordion = z.infer<typeof AccordionBlockSchema>;\n\n/** Accordeon op Astryx Collapsible. Bij `multiple: false` is er max. één paneel tegelijk open. */\nexport function AccordionRender({ block }: BlockRenderProps<Accordion>) {\n const items = (block.items ?? []).filter((i) => i.title);\n const [openIdx, setOpenIdx] = useState<number | null>(null);\n if (items.length === 0) return null;\n return (\n <VStack gap={3} as=\"section\" className=\"xicms-accordion\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n <VStack gap={1.5}>\n {items.map((it, i) => {\n const body = it.bodyHtml ? (\n // Server-side gesanitized bij publiceren (*Html-velden) — zie functions/lib/sanitize.\n // eslint-disable-next-line react/no-danger\n <div\n className=\"xicms-richtext\"\n data-xicms-edit={`items.${i}.bodyHtml`}\n dangerouslySetInnerHTML={{ __html: it.bodyHtml }}\n />\n ) : (\n <Text color=\"secondary\" data-xicms-edit={`items.${i}.body`}>{it.body}</Text>\n );\n const trigger = <Text weight=\"bold\" data-xicms-edit={`items.${i}.title`}>{it.title}</Text>;\n return block.multiple ? (\n <Collapsible key={i} trigger={trigger} defaultIsOpen={false}>{body}</Collapsible>\n ) : (\n <Collapsible\n key={i}\n trigger={trigger}\n isOpen={openIdx === i}\n onOpenChange={(o) => setOpenIdx(o ? i : null)}\n >\n {body}\n </Collapsible>\n );\n })}\n </VStack>\n </VStack>\n );\n}\n"],"mappings":";AAiBI,SACoB,KADpB;AAfJ,SAAS,gBAAgB;AAIzB,SAAS,mBAAmB;AAC5B,SAAS,QAAQ,SAAS,YAAY;AAK/B,SAAS,gBAAgB,EAAE,MAAM,GAAgC;AACtE,QAAM,SAAS,MAAM,SAAS,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK;AACvD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAwB,IAAI;AAC1D,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SACE,qBAAC,UAAO,KAAK,GAAG,IAAG,WAAU,WAAU,mBACpC;AAAA,UAAM,WAAW,oBAAC,WAAQ,OAAO,GAAG,mBAAgB,WAAW,gBAAM,SAAQ;AAAA,IAC9E,oBAAC,UAAO,KAAK,KACV,gBAAM,IAAI,CAAC,IAAI,MAAM;AACpB,YAAM,OAAO,GAAG;AAAA;AAAA;AAAA,QAGd;AAAA,UAAC;AAAA;AAAA,YACC,WAAU;AAAA,YACV,mBAAiB,SAAS,CAAC;AAAA,YAC3B,yBAAyB,EAAE,QAAQ,GAAG,SAAS;AAAA;AAAA,QACjD;AAAA,UAEA,oBAAC,QAAK,OAAM,aAAY,mBAAiB,SAAS,CAAC,SAAU,aAAG,MAAK;AAEvE,YAAM,UAAU,oBAAC,QAAK,QAAO,QAAO,mBAAiB,SAAS,CAAC,UAAW,aAAG,OAAM;AACnF,aAAO,MAAM,WACX,oBAAC,eAAoB,SAAkB,eAAe,OAAQ,kBAA5C,CAAiD,IAEnE;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA,QAAQ,YAAY;AAAA,UACpB,cAAc,CAAC,MAAM,WAAW,IAAI,IAAI,IAAI;AAAA,UAE3C;AAAA;AAAA,QALI;AAAA,MAMP;AAAA,IAEJ,CAAC,GACH;AAAA,KACF;AAEJ;","names":[]}
@@ -1,29 +1 @@
1
- import type { z } from "zod";
2
- /** Eén event zoals zowel het Agenda-blok als de Agenda-widget het kennen. */
3
- export interface AgendaEvent {
4
- title: string;
5
- start: string;
6
- end?: string;
7
- location?: string;
8
- description?: string;
9
- url?: string;
10
- }
11
- /**
12
- * Parseert een event-datum als LOKALE tijd. Cruciaal voor datum-zonder-tijd: `new Date("2026-08-01")`
13
- * is per spec UTC-middernacht, waardoor west-van-UTC-bezoekers "31 juli" te zien kregen (en de
14
- * server/client bij hydration konden verschillen). "2026-08-01" is hier gewoon 1 augustus, overal.
15
- */
16
- export declare function parseEventDate(value: string): Date;
17
- /** Toont een datum leesbaar (nl-NL). Valt terug op de ruwe string bij ongeldige invoer. */
18
- export declare function formatEventDate(value: string): string;
19
- /**
20
- * Selecteert de te tonen events: filtert lege titels, optioneel verlopen events, sorteert
21
- * chronologisch (events zonder geldige datum achteraan, in invoervolgorde) en limiteert. Gedeeld
22
- * door het volwaardige Agenda-blok en de compacte Agenda-widget — zo "haalt" de widget alles
23
- * uit dezelfde logica als de volledige versie.
24
- */
25
- export declare function selectAgendaEvents<T extends AgendaEvent>(events: T[] | undefined, opts?: {
26
- hidePast?: boolean;
27
- limit?: number;
28
- }): T[];
29
- export declare const agendaBlock: import("../index.js").BlockDefinition<z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
1
+ export declare const agendaBlock: import("../index.js").BlockDefinition<import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>>;
@@ -1,96 +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 { icsDataUrl } from "./lib/ics.js";
6
- function parseEventDate(value) {
7
- const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value.trim());
8
- if (m) return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
9
- return new Date(value);
10
- }
11
- function formatEventDate(value) {
12
- if (!value) return "";
13
- const d = parseEventDate(value);
14
- if (Number.isNaN(d.getTime())) return value;
15
- const hasTime = value.includes("T");
16
- return d.toLocaleDateString("nl-NL", {
17
- weekday: "short",
18
- day: "numeric",
19
- month: "long",
20
- year: "numeric",
21
- ...hasTime ? { hour: "2-digit", minute: "2-digit" } : {}
22
- });
23
- }
24
- function selectAgendaEvents(events, opts = {}) {
25
- let list = (events ?? []).filter((e) => e.title);
26
- if (opts.hidePast) {
27
- const today = /* @__PURE__ */ new Date();
28
- today.setHours(0, 0, 0, 0);
29
- list = list.filter((e) => {
30
- const d = parseEventDate(e.end || e.start);
31
- return Number.isNaN(d.getTime()) || d >= today;
32
- });
33
- }
34
- list = [...list].sort((a, b) => {
35
- const ta = parseEventDate(a.start).getTime();
36
- const tb = parseEventDate(b.start).getTime();
37
- if (Number.isNaN(ta) && Number.isNaN(tb)) return 0;
38
- if (Number.isNaN(ta)) return 1;
39
- if (Number.isNaN(tb)) return -1;
40
- return ta - tb;
41
- });
42
- return typeof opts.limit === "number" ? list.slice(0, opts.limit) : list;
43
- }
44
- function eventJsonLd(events) {
45
- return {
46
- "@context": "https://schema.org",
47
- "@type": "ItemList",
48
- // Google vereist `location` voor Event-rich-results: events zonder locatie renderen wel op
49
- // de pagina, maar blijven uit de JSON-LD (voorkomt gegarandeerde Search-Console-errors).
50
- itemListElement: events.filter((e) => e.title && e.start && e.location).map((e, i) => ({
51
- "@type": "ListItem",
52
- position: i + 1,
53
- item: {
54
- "@type": "Event",
55
- name: e.title,
56
- startDate: e.start,
57
- ...e.end ? { endDate: e.end } : {},
58
- location: { "@type": "Place", name: e.location },
59
- ...e.description ? { description: e.description } : {},
60
- ...e.url ? { url: e.url } : {}
61
- }
62
- }))
63
- };
64
- }
65
- function AgendaRender({ block }) {
66
- const events = selectAgendaEvents((block.events ?? []).map((e, i) => ({ ...e, _i: i })), { hidePast: block.hidePast });
67
- if (events.length === 0) return null;
68
- return /* @__PURE__ */ jsxs("section", { className: "xicms-agenda", children: [
69
- block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
70
- /* @__PURE__ */ jsx("ul", { className: "xicms-agenda__list", children: events.map((e) => /* @__PURE__ */ jsxs("li", { className: "xicms-agenda__item", children: [
71
- /* @__PURE__ */ jsx("time", { className: "xicms-agenda__date", dateTime: e.start, children: formatEventDate(e.start) }),
72
- /* @__PURE__ */ jsxs("div", { className: "xicms-agenda__body", children: [
73
- /* @__PURE__ */ jsx("strong", { className: "xicms-agenda__title", children: e.url ? /* @__PURE__ */ jsx("a", { href: e.url, "data-xicms-edit": `events.${e._i}.title`, children: e.title }) : /* @__PURE__ */ jsx("span", { "data-xicms-edit": `events.${e._i}.title`, children: e.title }) }),
74
- e.location && /* @__PURE__ */ jsx("span", { className: "xicms-agenda__location", "data-xicms-edit": `events.${e._i}.location`, children: e.location }),
75
- e.description && /* @__PURE__ */ jsx("p", { className: "xicms-agenda__desc", "data-xicms-edit": `events.${e._i}.description`, children: e.description }),
76
- (() => {
77
- const ics = icsDataUrl(e);
78
- return ics ? /* @__PURE__ */ jsx("a", { className: "xicms-agenda__ics", href: ics, download: `${(e.title || "evenement").toLowerCase().replace(/\s+/g, "-").slice(0, 40)}.ics`, children: "\u{1F4C5} Zet in agenda" }) : null;
79
- })()
80
- ] })
81
- ] }, e._i)) }),
82
- block.jsonLd && /* @__PURE__ */ jsx(
83
- "script",
84
- {
85
- type: "application/ld+json",
86
- dangerouslySetInnerHTML: { __html: jsonLdHtml(eventJsonLd(events)) }
87
- }
88
- )
89
- ] });
90
- }
91
3
  const agendaBlock = defineBlock({
92
4
  type: "agenda",
93
- Render: AgendaRender,
5
+ Render: dynamic(() => import("./AgendaRender.js").then((m) => m.AgendaRender)),
94
6
  label: "Agenda",
95
7
  icon: "\u{1F4C5}",
96
8
  defaults: () => ({
@@ -101,9 +13,6 @@ const agendaBlock = defineBlock({
101
13
  })
102
14
  });
103
15
  export {
104
- agendaBlock,
105
- formatEventDate,
106
- parseEventDate,
107
- selectAgendaEvents
16
+ agendaBlock
108
17
  };
109
18
  //# sourceMappingURL=Agenda.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/builtins/Agenda.tsx"],"sourcesContent":["import type { z } from \"zod\";\nimport { jsonLdHtml } from \"./jsonld\";\nimport type { AgendaBlockSchema } from \"../../schema/blocks\";\nimport { defineBlock, type BlockRenderProps } from \"../registry\";\nimport { Heading } from \"../ui\";\nimport { icsDataUrl } from \"./lib/ics\";\n\ntype Agenda = z.infer<typeof AgendaBlockSchema>;\n\n/** Eén event zoals zowel het Agenda-blok als de Agenda-widget het kennen. */\nexport interface AgendaEvent {\n title: string;\n start: string;\n end?: string;\n location?: string;\n description?: string;\n url?: string;\n}\n\n/**\n * Parseert een event-datum als LOKALE tijd. Cruciaal voor datum-zonder-tijd: `new Date(\"2026-08-01\")`\n * is per spec UTC-middernacht, waardoor west-van-UTC-bezoekers \"31 juli\" te zien kregen (en de\n * server/client bij hydration konden verschillen). \"2026-08-01\" is hier gewoon 1 augustus, overal.\n */\nexport function parseEventDate(value: string): Date {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(value.trim());\n if (m) return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));\n return new Date(value);\n}\n\n/** Toont een datum leesbaar (nl-NL). Valt terug op de ruwe string bij ongeldige invoer. */\nexport function formatEventDate(value: string): string {\n if (!value) return \"\";\n const d = parseEventDate(value);\n if (Number.isNaN(d.getTime())) return value;\n const hasTime = value.includes(\"T\");\n return d.toLocaleDateString(\"nl-NL\", {\n weekday: \"short\",\n day: \"numeric\",\n month: \"long\",\n year: \"numeric\",\n ...(hasTime ? { hour: \"2-digit\", minute: \"2-digit\" } : {}),\n });\n}\n\n/**\n * Selecteert de te tonen events: filtert lege titels, optioneel verlopen events, sorteert\n * chronologisch (events zonder geldige datum achteraan, in invoervolgorde) en limiteert. Gedeeld\n * door het volwaardige Agenda-blok en de compacte Agenda-widget — zo \"haalt\" de widget alles\n * uit dezelfde logica als de volledige versie.\n */\nexport function selectAgendaEvents<T extends AgendaEvent>(\n events: T[] | undefined,\n opts: { hidePast?: boolean; limit?: number } = {},\n): T[] {\n let list = (events ?? []).filter((e) => e.title);\n if (opts.hidePast) {\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n list = list.filter((e) => {\n const d = parseEventDate(e.end || e.start);\n return Number.isNaN(d.getTime()) || d >= today;\n });\n }\n list = [...list].sort((a, b) => {\n const ta = parseEventDate(a.start).getTime();\n const tb = parseEventDate(b.start).getTime();\n if (Number.isNaN(ta) && Number.isNaN(tb)) return 0;\n if (Number.isNaN(ta)) return 1;\n if (Number.isNaN(tb)) return -1;\n return ta - tb;\n });\n return typeof opts.limit === \"number\" ? list.slice(0, opts.limit) : list;\n}\n\nfunction eventJsonLd(events: Agenda[\"events\"]): Record<string, unknown> {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"ItemList\",\n // Google vereist `location` voor Event-rich-results: events zonder locatie renderen wel op\n // de pagina, maar blijven uit de JSON-LD (voorkomt gegarandeerde Search-Console-errors).\n itemListElement: events\n .filter((e) => e.title && e.start && e.location)\n .map((e, i) => ({\n \"@type\": \"ListItem\",\n position: i + 1,\n item: {\n \"@type\": \"Event\",\n name: e.title,\n startDate: e.start,\n ...(e.end ? { endDate: e.end } : {}),\n location: { \"@type\": \"Place\", name: e.location },\n ...(e.description ? { description: e.description } : {}),\n ...(e.url ? { url: e.url } : {}),\n },\n })),\n };\n}\n\n/** Agenda/evenementen. Server-safe (geen client-state); `hidePast` filtert verlopen events. */\nfunction AgendaRender({ block }: BlockRenderProps<Agenda>) {\n const events = selectAgendaEvents((block.events ?? []).map((e, i) => ({ ...e, _i: i })), { hidePast: block.hidePast });\n if (events.length === 0) return null;\n\n return (\n <section className=\"xicms-agenda\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n <ul className=\"xicms-agenda__list\">\n {events.map((e) => (\n <li key={e._i} className=\"xicms-agenda__item\">\n <time className=\"xicms-agenda__date\" dateTime={e.start}>\n {formatEventDate(e.start)}\n </time>\n <div className=\"xicms-agenda__body\">\n <strong className=\"xicms-agenda__title\">\n {e.url\n ? <a href={e.url} data-xicms-edit={`events.${e._i}.title`}>{e.title}</a>\n : <span data-xicms-edit={`events.${e._i}.title`}>{e.title}</span>}\n </strong>\n {e.location && <span className=\"xicms-agenda__location\" data-xicms-edit={`events.${e._i}.location`}>{e.location}</span>}\n {e.description && <p className=\"xicms-agenda__desc\" data-xicms-edit={`events.${e._i}.description`}>{e.description}</p>}\n {(() => {\n const ics = icsDataUrl(e);\n return ics ? (\n <a className=\"xicms-agenda__ics\" href={ics} download={`${(e.title || \"evenement\").toLowerCase().replace(/\\s+/g, \"-\").slice(0, 40)}.ics`}>\n 📅 Zet in agenda\n </a>\n ) : null;\n })()}\n </div>\n </li>\n ))}\n </ul>\n {block.jsonLd && (\n <script\n type=\"application/ld+json\"\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: jsonLdHtml(eventJsonLd(events)) }}\n />\n )}\n </section>\n );\n}\n\nexport const agendaBlock = defineBlock({\n type: \"agenda\",\n Render: AgendaRender,\n label: \"Agenda\",\n icon: \"📅\",\n defaults: () => ({\n heading: \"Agenda\",\n events: [{ title: \"Evenement\", start: \"\" }],\n hidePast: true,\n jsonLd: true,\n }),\n});\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/builtins/Agenda.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const agendaBlock = defineBlock({\n type: \"agenda\",\n Render: dynamic(() => import(\"./AgendaRender\").then((m) => m.AgendaRender)),\n label: \"Agenda\",\n icon: \"📅\",\n defaults: () => ({\n heading: \"Agenda\",\n events: [{ title: \"Evenement\", start: \"\" }],\n hidePast: true,\n jsonLd: true,\n }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,cAAc,YAAY;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,gBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC;AAAA,EAC1E,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO;AAAA,IACf,SAAS;AAAA,IACT,QAAQ,CAAC,EAAE,OAAO,aAAa,OAAO,GAAG,CAAC;AAAA,IAC1C,UAAU;AAAA,IACV,QAAQ;AAAA,EACV;AACF,CAAC;","names":[]}
@@ -0,0 +1,34 @@
1
+ import type { z } from "zod";
2
+ import type { AgendaBlockSchema } from "../../schema/blocks.js";
3
+ import type { BlockRenderProps } from "../registry.js";
4
+ type Agenda = z.infer<typeof AgendaBlockSchema>;
5
+ /** Eén event zoals zowel het Agenda-blok als de Agenda-widget het kennen. */
6
+ export interface AgendaEvent {
7
+ title: string;
8
+ start: string;
9
+ end?: string;
10
+ location?: string;
11
+ description?: string;
12
+ url?: string;
13
+ }
14
+ /**
15
+ * Parseert een event-datum als LOKALE tijd. Cruciaal voor datum-zonder-tijd: `new Date("2026-08-01")`
16
+ * is per spec UTC-middernacht, waardoor west-van-UTC-bezoekers "31 juli" te zien kregen (en de
17
+ * server/client bij hydration konden verschillen). "2026-08-01" is hier gewoon 1 augustus, overal.
18
+ */
19
+ export declare function parseEventDate(value: string): Date;
20
+ /** Toont een datum leesbaar (nl-NL). Valt terug op de ruwe string bij ongeldige invoer. */
21
+ export declare function formatEventDate(value: string): string;
22
+ /**
23
+ * Selecteert de te tonen events: filtert lege titels, optioneel verlopen events, sorteert
24
+ * chronologisch (events zonder geldige datum achteraan, in invoervolgorde) en limiteert. Gedeeld
25
+ * door het volwaardige Agenda-blok en de compacte Agenda-widget — zo "haalt" de widget alles
26
+ * uit dezelfde logica als de volledige versie.
27
+ */
28
+ export declare function selectAgendaEvents<T extends AgendaEvent>(events: T[] | undefined, opts?: {
29
+ hidePast?: boolean;
30
+ limit?: number;
31
+ }): T[];
32
+ /** Agenda/evenementen. Server-safe (geen client-state); `hidePast` filtert verlopen events. */
33
+ export declare function AgendaRender({ block }: BlockRenderProps<Agenda>): import("react").JSX.Element | null;
34
+ export {};
@@ -0,0 +1,96 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { jsonLdHtml } from "./jsonld.js";
3
+ import { Heading } from "../ui/index.js";
4
+ import { icsDataUrl } from "./lib/ics.js";
5
+ function parseEventDate(value) {
6
+ const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value.trim());
7
+ if (m) return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
8
+ return new Date(value);
9
+ }
10
+ function formatEventDate(value) {
11
+ if (!value) return "";
12
+ const d = parseEventDate(value);
13
+ if (Number.isNaN(d.getTime())) return value;
14
+ const hasTime = value.includes("T");
15
+ return d.toLocaleDateString("nl-NL", {
16
+ weekday: "short",
17
+ day: "numeric",
18
+ month: "long",
19
+ year: "numeric",
20
+ ...hasTime ? { hour: "2-digit", minute: "2-digit" } : {}
21
+ });
22
+ }
23
+ function selectAgendaEvents(events, opts = {}) {
24
+ let list = (events ?? []).filter((e) => e.title);
25
+ if (opts.hidePast) {
26
+ const today = /* @__PURE__ */ new Date();
27
+ today.setHours(0, 0, 0, 0);
28
+ list = list.filter((e) => {
29
+ const d = parseEventDate(e.end || e.start);
30
+ return Number.isNaN(d.getTime()) || d >= today;
31
+ });
32
+ }
33
+ list = [...list].sort((a, b) => {
34
+ const ta = parseEventDate(a.start).getTime();
35
+ const tb = parseEventDate(b.start).getTime();
36
+ if (Number.isNaN(ta) && Number.isNaN(tb)) return 0;
37
+ if (Number.isNaN(ta)) return 1;
38
+ if (Number.isNaN(tb)) return -1;
39
+ return ta - tb;
40
+ });
41
+ return typeof opts.limit === "number" ? list.slice(0, opts.limit) : list;
42
+ }
43
+ function eventJsonLd(events) {
44
+ return {
45
+ "@context": "https://schema.org",
46
+ "@type": "ItemList",
47
+ // Google vereist `location` voor Event-rich-results: events zonder locatie renderen wel op
48
+ // de pagina, maar blijven uit de JSON-LD (voorkomt gegarandeerde Search-Console-errors).
49
+ itemListElement: events.filter((e) => e.title && e.start && e.location).map((e, i) => ({
50
+ "@type": "ListItem",
51
+ position: i + 1,
52
+ item: {
53
+ "@type": "Event",
54
+ name: e.title,
55
+ startDate: e.start,
56
+ ...e.end ? { endDate: e.end } : {},
57
+ location: { "@type": "Place", name: e.location },
58
+ ...e.description ? { description: e.description } : {},
59
+ ...e.url ? { url: e.url } : {}
60
+ }
61
+ }))
62
+ };
63
+ }
64
+ function AgendaRender({ block }) {
65
+ const events = selectAgendaEvents((block.events ?? []).map((e, i) => ({ ...e, _i: i })), { hidePast: block.hidePast });
66
+ if (events.length === 0) return null;
67
+ return /* @__PURE__ */ jsxs("section", { className: "xicms-agenda", children: [
68
+ block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
69
+ /* @__PURE__ */ jsx("ul", { className: "xicms-agenda__list", children: events.map((e) => /* @__PURE__ */ jsxs("li", { className: "xicms-agenda__item", children: [
70
+ /* @__PURE__ */ jsx("time", { className: "xicms-agenda__date", dateTime: e.start, children: formatEventDate(e.start) }),
71
+ /* @__PURE__ */ jsxs("div", { className: "xicms-agenda__body", children: [
72
+ /* @__PURE__ */ jsx("strong", { className: "xicms-agenda__title", children: e.url ? /* @__PURE__ */ jsx("a", { href: e.url, "data-xicms-edit": `events.${e._i}.title`, children: e.title }) : /* @__PURE__ */ jsx("span", { "data-xicms-edit": `events.${e._i}.title`, children: e.title }) }),
73
+ e.location && /* @__PURE__ */ jsx("span", { className: "xicms-agenda__location", "data-xicms-edit": `events.${e._i}.location`, children: e.location }),
74
+ e.description && /* @__PURE__ */ jsx("p", { className: "xicms-agenda__desc", "data-xicms-edit": `events.${e._i}.description`, children: e.description }),
75
+ (() => {
76
+ const ics = icsDataUrl(e);
77
+ return ics ? /* @__PURE__ */ jsx("a", { className: "xicms-agenda__ics", href: ics, download: `${(e.title || "evenement").toLowerCase().replace(/\s+/g, "-").slice(0, 40)}.ics`, children: "\u{1F4C5} Zet in agenda" }) : null;
78
+ })()
79
+ ] })
80
+ ] }, e._i)) }),
81
+ block.jsonLd && /* @__PURE__ */ jsx(
82
+ "script",
83
+ {
84
+ type: "application/ld+json",
85
+ dangerouslySetInnerHTML: { __html: jsonLdHtml(eventJsonLd(events)) }
86
+ }
87
+ )
88
+ ] });
89
+ }
90
+ export {
91
+ AgendaRender,
92
+ formatEventDate,
93
+ parseEventDate,
94
+ selectAgendaEvents
95
+ };
96
+ //# sourceMappingURL=AgendaRender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/blocks/builtins/AgendaRender.tsx"],"sourcesContent":["import type { z } from \"zod\";\nimport { jsonLdHtml } from \"./jsonld\";\nimport type { AgendaBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { Heading } from \"../ui\";\nimport { icsDataUrl } from \"./lib/ics\";\n\ntype Agenda = z.infer<typeof AgendaBlockSchema>;\n\n/** Eén event zoals zowel het Agenda-blok als de Agenda-widget het kennen. */\nexport interface AgendaEvent {\n title: string;\n start: string;\n end?: string;\n location?: string;\n description?: string;\n url?: string;\n}\n\n/**\n * Parseert een event-datum als LOKALE tijd. Cruciaal voor datum-zonder-tijd: `new Date(\"2026-08-01\")`\n * is per spec UTC-middernacht, waardoor west-van-UTC-bezoekers \"31 juli\" te zien kregen (en de\n * server/client bij hydration konden verschillen). \"2026-08-01\" is hier gewoon 1 augustus, overal.\n */\nexport function parseEventDate(value: string): Date {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(value.trim());\n if (m) return new Date(Number(m[1]), Number(m[2]) - 1, Number(m[3]));\n return new Date(value);\n}\n\n/** Toont een datum leesbaar (nl-NL). Valt terug op de ruwe string bij ongeldige invoer. */\nexport function formatEventDate(value: string): string {\n if (!value) return \"\";\n const d = parseEventDate(value);\n if (Number.isNaN(d.getTime())) return value;\n const hasTime = value.includes(\"T\");\n return d.toLocaleDateString(\"nl-NL\", {\n weekday: \"short\",\n day: \"numeric\",\n month: \"long\",\n year: \"numeric\",\n ...(hasTime ? { hour: \"2-digit\", minute: \"2-digit\" } : {}),\n });\n}\n\n/**\n * Selecteert de te tonen events: filtert lege titels, optioneel verlopen events, sorteert\n * chronologisch (events zonder geldige datum achteraan, in invoervolgorde) en limiteert. Gedeeld\n * door het volwaardige Agenda-blok en de compacte Agenda-widget — zo \"haalt\" de widget alles\n * uit dezelfde logica als de volledige versie.\n */\nexport function selectAgendaEvents<T extends AgendaEvent>(\n events: T[] | undefined,\n opts: { hidePast?: boolean; limit?: number } = {},\n): T[] {\n let list = (events ?? []).filter((e) => e.title);\n if (opts.hidePast) {\n const today = new Date();\n today.setHours(0, 0, 0, 0);\n list = list.filter((e) => {\n const d = parseEventDate(e.end || e.start);\n return Number.isNaN(d.getTime()) || d >= today;\n });\n }\n list = [...list].sort((a, b) => {\n const ta = parseEventDate(a.start).getTime();\n const tb = parseEventDate(b.start).getTime();\n if (Number.isNaN(ta) && Number.isNaN(tb)) return 0;\n if (Number.isNaN(ta)) return 1;\n if (Number.isNaN(tb)) return -1;\n return ta - tb;\n });\n return typeof opts.limit === \"number\" ? list.slice(0, opts.limit) : list;\n}\n\nfunction eventJsonLd(events: Agenda[\"events\"]): Record<string, unknown> {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"ItemList\",\n // Google vereist `location` voor Event-rich-results: events zonder locatie renderen wel op\n // de pagina, maar blijven uit de JSON-LD (voorkomt gegarandeerde Search-Console-errors).\n itemListElement: events\n .filter((e) => e.title && e.start && e.location)\n .map((e, i) => ({\n \"@type\": \"ListItem\",\n position: i + 1,\n item: {\n \"@type\": \"Event\",\n name: e.title,\n startDate: e.start,\n ...(e.end ? { endDate: e.end } : {}),\n location: { \"@type\": \"Place\", name: e.location },\n ...(e.description ? { description: e.description } : {}),\n ...(e.url ? { url: e.url } : {}),\n },\n })),\n };\n}\n\n/** Agenda/evenementen. Server-safe (geen client-state); `hidePast` filtert verlopen events. */\nexport function AgendaRender({ block }: BlockRenderProps<Agenda>) {\n const events = selectAgendaEvents((block.events ?? []).map((e, i) => ({ ...e, _i: i })), { hidePast: block.hidePast });\n if (events.length === 0) return null;\n\n return (\n <section className=\"xicms-agenda\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n <ul className=\"xicms-agenda__list\">\n {events.map((e) => (\n <li key={e._i} className=\"xicms-agenda__item\">\n <time className=\"xicms-agenda__date\" dateTime={e.start}>\n {formatEventDate(e.start)}\n </time>\n <div className=\"xicms-agenda__body\">\n <strong className=\"xicms-agenda__title\">\n {e.url\n ? <a href={e.url} data-xicms-edit={`events.${e._i}.title`}>{e.title}</a>\n : <span data-xicms-edit={`events.${e._i}.title`}>{e.title}</span>}\n </strong>\n {e.location && <span className=\"xicms-agenda__location\" data-xicms-edit={`events.${e._i}.location`}>{e.location}</span>}\n {e.description && <p className=\"xicms-agenda__desc\" data-xicms-edit={`events.${e._i}.description`}>{e.description}</p>}\n {(() => {\n const ics = icsDataUrl(e);\n return ics ? (\n <a className=\"xicms-agenda__ics\" href={ics} download={`${(e.title || \"evenement\").toLowerCase().replace(/\\s+/g, \"-\").slice(0, 40)}.ics`}>\n 📅 Zet in agenda\n </a>\n ) : null;\n })()}\n </div>\n </li>\n ))}\n </ul>\n {block.jsonLd && (\n <script\n type=\"application/ld+json\"\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{ __html: jsonLdHtml(eventJsonLd(events)) }}\n />\n )}\n </section>\n );\n}\n"],"mappings":"AA0GwB,cAOZ,YAPY;AAzGxB,SAAS,kBAAkB;AAG3B,SAAS,eAAe;AACxB,SAAS,kBAAkB;AAmBpB,SAAS,eAAe,OAAqB;AAClD,QAAM,IAAI,4BAA4B,KAAK,MAAM,KAAK,CAAC;AACvD,MAAI,EAAG,QAAO,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,CAAC,IAAI,GAAG,OAAO,EAAE,CAAC,CAAC,CAAC;AACnE,SAAO,IAAI,KAAK,KAAK;AACvB;AAGO,SAAS,gBAAgB,OAAuB;AACrD,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,IAAI,eAAe,KAAK;AAC9B,MAAI,OAAO,MAAM,EAAE,QAAQ,CAAC,EAAG,QAAO;AACtC,QAAM,UAAU,MAAM,SAAS,GAAG;AAClC,SAAO,EAAE,mBAAmB,SAAS;AAAA,IACnC,SAAS;AAAA,IACT,KAAK;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,GAAI,UAAU,EAAE,MAAM,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,EAC1D,CAAC;AACH;AAQO,SAAS,mBACd,QACA,OAA+C,CAAC,GAC3C;AACL,MAAI,QAAQ,UAAU,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK;AAC/C,MAAI,KAAK,UAAU;AACjB,UAAM,QAAQ,oBAAI,KAAK;AACvB,UAAM,SAAS,GAAG,GAAG,GAAG,CAAC;AACzB,WAAO,KAAK,OAAO,CAAC,MAAM;AACxB,YAAM,IAAI,eAAe,EAAE,OAAO,EAAE,KAAK;AACzC,aAAO,OAAO,MAAM,EAAE,QAAQ,CAAC,KAAK,KAAK;AAAA,IAC3C,CAAC;AAAA,EACH;AACA,SAAO,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,MAAM;AAC9B,UAAM,KAAK,eAAe,EAAE,KAAK,EAAE,QAAQ;AAC3C,UAAM,KAAK,eAAe,EAAE,KAAK,EAAE,QAAQ;AAC3C,QAAI,OAAO,MAAM,EAAE,KAAK,OAAO,MAAM,EAAE,EAAG,QAAO;AACjD,QAAI,OAAO,MAAM,EAAE,EAAG,QAAO;AAC7B,QAAI,OAAO,MAAM,EAAE,EAAG,QAAO;AAC7B,WAAO,KAAK;AAAA,EACd,CAAC;AACD,SAAO,OAAO,KAAK,UAAU,WAAW,KAAK,MAAM,GAAG,KAAK,KAAK,IAAI;AACtE;AAEA,SAAS,YAAY,QAAmD;AACtE,SAAO;AAAA,IACL,YAAY;AAAA,IACZ,SAAS;AAAA;AAAA;AAAA,IAGT,iBAAiB,OACd,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAC9C,IAAI,CAAC,GAAG,OAAO;AAAA,MACd,SAAS;AAAA,MACT,UAAU,IAAI;AAAA,MACd,MAAM;AAAA,QACJ,SAAS;AAAA,QACT,MAAM,EAAE;AAAA,QACR,WAAW,EAAE;AAAA,QACb,GAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,IAAI,CAAC;AAAA,QAClC,UAAU,EAAE,SAAS,SAAS,MAAM,EAAE,SAAS;AAAA,QAC/C,GAAI,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,IAAI,CAAC;AAAA,QACtD,GAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC;AAAA,MAChC;AAAA,IACF,EAAE;AAAA,EACN;AACF;AAGO,SAAS,aAAa,EAAE,MAAM,GAA6B;AAChE,QAAM,SAAS,oBAAoB,MAAM,UAAU,CAAC,GAAG,IAAI,CAAC,GAAG,OAAO,EAAE,GAAG,GAAG,IAAI,EAAE,EAAE,GAAG,EAAE,UAAU,MAAM,SAAS,CAAC;AACrH,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,SACE,qBAAC,aAAQ,WAAU,gBAChB;AAAA,UAAM,WAAW,oBAAC,WAAQ,OAAO,GAAG,mBAAgB,WAAW,gBAAM,SAAQ;AAAA,IAC9E,oBAAC,QAAG,WAAU,sBACX,iBAAO,IAAI,CAAC,MACX,qBAAC,QAAc,WAAU,sBACvB;AAAA,0BAAC,UAAK,WAAU,sBAAqB,UAAU,EAAE,OAC9C,0BAAgB,EAAE,KAAK,GAC1B;AAAA,MACA,qBAAC,SAAI,WAAU,sBACb;AAAA,4BAAC,YAAO,WAAU,uBACf,YAAE,MACC,oBAAC,OAAE,MAAM,EAAE,KAAK,mBAAiB,UAAU,EAAE,EAAE,UAAW,YAAE,OAAM,IAClE,oBAAC,UAAK,mBAAiB,UAAU,EAAE,EAAE,UAAW,YAAE,OAAM,GAC9D;AAAA,QACC,EAAE,YAAY,oBAAC,UAAK,WAAU,0BAAyB,mBAAiB,UAAU,EAAE,EAAE,aAAc,YAAE,UAAS;AAAA,QAC/G,EAAE,eAAe,oBAAC,OAAE,WAAU,sBAAqB,mBAAiB,UAAU,EAAE,EAAE,gBAAiB,YAAE,aAAY;AAAA,SAChH,MAAM;AACN,gBAAM,MAAM,WAAW,CAAC;AACxB,iBAAO,MACL,oBAAC,OAAE,WAAU,qBAAoB,MAAM,KAAK,UAAU,IAAI,EAAE,SAAS,aAAa,YAAY,EAAE,QAAQ,QAAQ,GAAG,EAAE,MAAM,GAAG,EAAE,CAAC,QAAQ,qCAEzI,IACE;AAAA,QACN,GAAG;AAAA,SACL;AAAA,SApBO,EAAE,EAqBX,CACD,GACH;AAAA,IACC,MAAM,UACL;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QAEL,yBAAyB,EAAE,QAAQ,WAAW,YAAY,MAAM,CAAC,EAAE;AAAA;AAAA,IACrE;AAAA,KAEJ;AAEJ;","names":[]}
@@ -1,2 +1 @@
1
- import type { z } from "zod";
2
- export declare const bannerBlock: import("../index.js").BlockDefinition<z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
1
+ export declare const bannerBlock: import("../index.js").BlockDefinition<import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>>;
@@ -1,38 +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
- function storageKey(block) {
6
- return `xicms-banner:${block._key}${block.dismissVersion ? `:${block.dismissVersion}` : ""}`;
7
- }
8
- function BannerRender({ block, mode }) {
9
- const [closed, setClosed] = useState(false);
10
- useEffect(() => {
11
- if (mode === "preview" || !block.dismissible) return;
12
- try {
13
- if (window.localStorage.getItem(storageKey(block)) === "1") setClosed(true);
14
- } catch {
15
- }
16
- }, [block, mode]);
17
- const dismiss = () => {
18
- setClosed(true);
19
- try {
20
- window.localStorage.setItem(storageKey(block), "1");
21
- } catch {
22
- }
23
- };
24
- if (!block.text || closed && mode !== "preview") return null;
25
- return /* @__PURE__ */ jsxs("div", { className: "xicms-banner", "data-tone": block.tone, role: "region", "aria-label": "Aankondiging", children: [
26
- /* @__PURE__ */ jsxs("span", { children: [
27
- /* @__PURE__ */ jsx("span", { "data-xicms-edit": "text", children: block.text }),
28
- block.href && /* @__PURE__ */ jsx("a", { className: "xicms-banner__link", href: block.href, "data-xicms-edit": "linkLabel", children: block.linkLabel ?? "Meer" })
29
- ] }),
30
- block.dismissible && /* @__PURE__ */ jsx("button", { type: "button", className: "xicms-banner__close", "aria-label": "Sluiten", onClick: dismiss, children: "\u2715" })
31
- ] });
32
- }
33
3
  const bannerBlock = defineBlock({
34
4
  type: "banner",
35
- Render: BannerRender,
5
+ Render: dynamic(() => import("./BannerRender.js").then((m) => m.BannerRender)),
36
6
  label: "Aankondiging",
37
7
  icon: "\u{1F4E2}",
38
8
  defaults: () => ({ text: "Nieuw: \u2026", tone: "info", dismissible: true })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/blocks/builtins/Banner.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { z } from \"zod\";\nimport type { BannerBlockSchema } from \"../../schema/blocks\";\nimport { defineBlock, type BlockRenderProps } from \"../registry\";\n\ntype Banner = z.infer<typeof BannerBlockSchema>;\n\n/** Sleutel per blok (+ optionele versie): wegklikken onthouden we per banner-inhoud. */\nfunction storageKey(block: Banner): string {\n return `xicms-banner:${block._key}${block.dismissVersion ? `:${block.dismissVersion}` : \"\"}`;\n}\n\n/**\n * Aankondigingsbalk, optioneel sluitbaar. Wegklikken wordt in localStorage onthouden (per blok +\n * `dismissVersion`), zodat de balk niet bij elke paginaweergave terugkomt. In de editor-preview\n * tonen we hem altijd (anders kan een editor zijn eigen weggeklikte banner niet meer bewerken).\n */\nfunction BannerRender({ block, mode }: BlockRenderProps<Banner>) {\n const [closed, setClosed] = useState(false);\n\n // localStorage pas na mount lezen (SSR-veilig; voorkomt hydration-mismatch).\n useEffect(() => {\n if (mode === \"preview\" || !block.dismissible) return;\n try {\n if (window.localStorage.getItem(storageKey(block)) === \"1\") setClosed(true);\n } catch {\n /* opslag onbeschikbaar: banner gewoon tonen */\n }\n }, [block, mode]);\n\n const dismiss = () => {\n setClosed(true);\n try {\n window.localStorage.setItem(storageKey(block), \"1\");\n } catch {\n /* opslag geweigerd: sluiten geldt dan alleen voor deze weergave */\n }\n };\n\n if (!block.text || (closed && mode !== \"preview\")) return null;\n return (\n <div className=\"xicms-banner\" data-tone={block.tone} role=\"region\" aria-label=\"Aankondiging\">\n <span>\n <span data-xicms-edit=\"text\">{block.text}</span>\n {block.href && (\n <a className=\"xicms-banner__link\" href={block.href} data-xicms-edit=\"linkLabel\">\n {block.linkLabel ?? \"Meer\"}\n </a>\n )}\n </span>\n {block.dismissible && (\n <button type=\"button\" className=\"xicms-banner__close\" aria-label=\"Sluiten\" onClick={dismiss}>\n ✕\n </button>\n )}\n </div>\n );\n}\n\nexport const bannerBlock = defineBlock({\n type: \"banner\",\n Render: BannerRender,\n label: \"Aankondiging\",\n icon: \"📢\",\n defaults: () => ({ text: \"Nieuw: …\", tone: \"info\", dismissible: true }),\n});\n"],"mappings":";AA4CM,SACE,KADF;AA1CN,SAAS,WAAW,gBAAgB;AAGpC,SAAS,mBAA0C;AAKnD,SAAS,WAAW,OAAuB;AACzC,SAAO,gBAAgB,MAAM,IAAI,GAAG,MAAM,iBAAiB,IAAI,MAAM,cAAc,KAAK,EAAE;AAC5F;AAOA,SAAS,aAAa,EAAE,OAAO,KAAK,GAA6B;AAC/D,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAG1C,YAAU,MAAM;AACd,QAAI,SAAS,aAAa,CAAC,MAAM,YAAa;AAC9C,QAAI;AACF,UAAI,OAAO,aAAa,QAAQ,WAAW,KAAK,CAAC,MAAM,IAAK,WAAU,IAAI;AAAA,IAC5E,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,OAAO,IAAI,CAAC;AAEhB,QAAM,UAAU,MAAM;AACpB,cAAU,IAAI;AACd,QAAI;AACF,aAAO,aAAa,QAAQ,WAAW,KAAK,GAAG,GAAG;AAAA,IACpD,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,MAAI,CAAC,MAAM,QAAS,UAAU,SAAS,UAAY,QAAO;AAC1D,SACE,qBAAC,SAAI,WAAU,gBAAe,aAAW,MAAM,MAAM,MAAK,UAAS,cAAW,gBAC5E;AAAA,yBAAC,UACC;AAAA,0BAAC,UAAK,mBAAgB,QAAQ,gBAAM,MAAK;AAAA,MACxC,MAAM,QACL,oBAAC,OAAE,WAAU,sBAAqB,MAAM,MAAM,MAAM,mBAAgB,aACjE,gBAAM,aAAa,QACtB;AAAA,OAEJ;AAAA,IACC,MAAM,eACL,oBAAC,YAAO,MAAK,UAAS,WAAU,uBAAsB,cAAW,WAAU,SAAS,SAAS,oBAE7F;AAAA,KAEJ;AAEJ;AAEO,MAAM,cAAc,YAAY;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,MAAM,iBAAY,MAAM,QAAQ,aAAa,KAAK;AACvE,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/blocks/builtins/Banner.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const bannerBlock = defineBlock({\n type: \"banner\",\n Render: dynamic(() => import(\"./BannerRender\").then((m) => m.BannerRender)),\n label: \"Aankondiging\",\n icon: \"📢\",\n defaults: () => ({ text: \"Nieuw: …\", tone: \"info\", dismissible: true }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,cAAc,YAAY;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,gBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC;AAAA,EAC1E,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,MAAM,iBAAY,MAAM,QAAQ,aAAa,KAAK;AACvE,CAAC;","names":[]}
@@ -0,0 +1,11 @@
1
+ import type { z } from "zod";
2
+ import type { BannerBlockSchema } from "../../schema/blocks.js";
3
+ import type { BlockRenderProps } from "../registry.js";
4
+ type Banner = z.infer<typeof BannerBlockSchema>;
5
+ /**
6
+ * Aankondigingsbalk, optioneel sluitbaar. Wegklikken wordt in localStorage onthouden (per blok +
7
+ * `dismissVersion`), zodat de balk niet bij elke paginaweergave terugkomt. In de editor-preview
8
+ * tonen we hem altijd (anders kan een editor zijn eigen weggeklikte banner niet meer bewerken).
9
+ */
10
+ export declare function BannerRender({ block, mode }: BlockRenderProps<Banner>): import("react").JSX.Element | null;
11
+ export {};
@@ -0,0 +1,35 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useEffect, useState } from "react";
4
+ function storageKey(block) {
5
+ return `xicms-banner:${block._key}${block.dismissVersion ? `:${block.dismissVersion}` : ""}`;
6
+ }
7
+ function BannerRender({ block, mode }) {
8
+ const [closed, setClosed] = useState(false);
9
+ useEffect(() => {
10
+ if (mode === "preview" || !block.dismissible) return;
11
+ try {
12
+ if (window.localStorage.getItem(storageKey(block)) === "1") setClosed(true);
13
+ } catch {
14
+ }
15
+ }, [block, mode]);
16
+ const dismiss = () => {
17
+ setClosed(true);
18
+ try {
19
+ window.localStorage.setItem(storageKey(block), "1");
20
+ } catch {
21
+ }
22
+ };
23
+ if (!block.text || closed && mode !== "preview") return null;
24
+ return /* @__PURE__ */ jsxs("div", { className: "xicms-banner", "data-tone": block.tone, role: "region", "aria-label": "Aankondiging", children: [
25
+ /* @__PURE__ */ jsxs("span", { children: [
26
+ /* @__PURE__ */ jsx("span", { "data-xicms-edit": "text", children: block.text }),
27
+ block.href && /* @__PURE__ */ jsx("a", { className: "xicms-banner__link", href: block.href, "data-xicms-edit": "linkLabel", children: block.linkLabel ?? "Meer" })
28
+ ] }),
29
+ block.dismissible && /* @__PURE__ */ jsx("button", { type: "button", className: "xicms-banner__close", "aria-label": "Sluiten", onClick: dismiss, children: "\u2715" })
30
+ ] });
31
+ }
32
+ export {
33
+ BannerRender
34
+ };
35
+ //# sourceMappingURL=BannerRender.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/blocks/builtins/BannerRender.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { z } from \"zod\";\nimport type { BannerBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\n\ntype Banner = z.infer<typeof BannerBlockSchema>;\n\n/** Sleutel per blok (+ optionele versie): wegklikken onthouden we per banner-inhoud. */\nfunction storageKey(block: Banner): string {\n return `xicms-banner:${block._key}${block.dismissVersion ? `:${block.dismissVersion}` : \"\"}`;\n}\n\n/**\n * Aankondigingsbalk, optioneel sluitbaar. Wegklikken wordt in localStorage onthouden (per blok +\n * `dismissVersion`), zodat de balk niet bij elke paginaweergave terugkomt. In de editor-preview\n * tonen we hem altijd (anders kan een editor zijn eigen weggeklikte banner niet meer bewerken).\n */\nexport function BannerRender({ block, mode }: BlockRenderProps<Banner>) {\n const [closed, setClosed] = useState(false);\n\n // localStorage pas na mount lezen (SSR-veilig; voorkomt hydration-mismatch).\n useEffect(() => {\n if (mode === \"preview\" || !block.dismissible) return;\n try {\n if (window.localStorage.getItem(storageKey(block)) === \"1\") setClosed(true);\n } catch {\n /* opslag onbeschikbaar: banner gewoon tonen */\n }\n }, [block, mode]);\n\n const dismiss = () => {\n setClosed(true);\n try {\n window.localStorage.setItem(storageKey(block), \"1\");\n } catch {\n /* opslag geweigerd: sluiten geldt dan alleen voor deze weergave */\n }\n };\n\n if (!block.text || (closed && mode !== \"preview\")) return null;\n return (\n <div className=\"xicms-banner\" data-tone={block.tone} role=\"region\" aria-label=\"Aankondiging\">\n <span>\n <span data-xicms-edit=\"text\">{block.text}</span>\n {block.href && (\n <a className=\"xicms-banner__link\" href={block.href} data-xicms-edit=\"linkLabel\">\n {block.linkLabel ?? \"Meer\"}\n </a>\n )}\n </span>\n {block.dismissible && (\n <button type=\"button\" className=\"xicms-banner__close\" aria-label=\"Sluiten\" onClick={dismiss}>\n ✕\n </button>\n )}\n </div>\n );\n}\n"],"mappings":";AA4CM,SACE,KADF;AA1CN,SAAS,WAAW,gBAAgB;AAQpC,SAAS,WAAW,OAAuB;AACzC,SAAO,gBAAgB,MAAM,IAAI,GAAG,MAAM,iBAAiB,IAAI,MAAM,cAAc,KAAK,EAAE;AAC5F;AAOO,SAAS,aAAa,EAAE,OAAO,KAAK,GAA6B;AACtE,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAG1C,YAAU,MAAM;AACd,QAAI,SAAS,aAAa,CAAC,MAAM,YAAa;AAC9C,QAAI;AACF,UAAI,OAAO,aAAa,QAAQ,WAAW,KAAK,CAAC,MAAM,IAAK,WAAU,IAAI;AAAA,IAC5E,QAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,OAAO,IAAI,CAAC;AAEhB,QAAM,UAAU,MAAM;AACpB,cAAU,IAAI;AACd,QAAI;AACF,aAAO,aAAa,QAAQ,WAAW,KAAK,GAAG,GAAG;AAAA,IACpD,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,MAAI,CAAC,MAAM,QAAS,UAAU,SAAS,UAAY,QAAO;AAC1D,SACE,qBAAC,SAAI,WAAU,gBAAe,aAAW,MAAM,MAAM,MAAK,UAAS,cAAW,gBAC5E;AAAA,yBAAC,UACC;AAAA,0BAAC,UAAK,mBAAgB,QAAQ,gBAAM,MAAK;AAAA,MACxC,MAAM,QACL,oBAAC,OAAE,WAAU,sBAAqB,MAAM,MAAM,MAAM,mBAAgB,aACjE,gBAAM,aAAa,QACtB;AAAA,OAEJ;AAAA,IACC,MAAM,eACL,oBAAC,YAAO,MAAK,UAAS,WAAU,uBAAsB,cAAW,WAAU,SAAS,SAAS,oBAE7F;AAAA,KAEJ;AAEJ;","names":[]}
@@ -1,2 +1 @@
1
- import type { z } from "zod";
2
- export declare const beforeAfterBlock: import("../index.js").BlockDefinition<z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
1
+ export declare const beforeAfterBlock: import("../index.js").BlockDefinition<import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>>;
@@ -1,38 +1,9 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { useState } from "react";
1
+ import dynamic from "next/dynamic";
4
2
  import { defineBlock } from "../registry.js";
5
- function BeforeAfterRender({ block }) {
6
- const [pos, setPos] = useState(50);
7
- if (!block.beforeUrl || !block.afterUrl) return null;
8
- return /* @__PURE__ */ jsxs("figure", { className: "xicms-beforeafter", style: { aspectRatio: block.aspectRatio.replace("/", " / ") }, children: [
9
- block.heading && /* @__PURE__ */ jsx("figcaption", { className: "xicms-beforeafter__heading", "data-xicms-edit": "heading", children: block.heading }),
10
- /* @__PURE__ */ jsxs("div", { className: "xicms-beforeafter__stage", children: [
11
- /* @__PURE__ */ jsx("img", { className: "xicms-beforeafter__img", src: block.beforeUrl, alt: block.alt || block.beforeLabel, loading: "lazy" }),
12
- /* @__PURE__ */ jsx("div", { className: "xicms-beforeafter__clip", style: { clipPath: `inset(0 0 0 ${pos}%)` }, "aria-hidden": true, children: /* @__PURE__ */ jsx("img", { className: "xicms-beforeafter__img", src: block.afterUrl, alt: "", loading: "lazy" }) }),
13
- /* @__PURE__ */ jsx("div", { className: "xicms-beforeafter__divider", style: { left: `${pos}%` }, "aria-hidden": true, children: /* @__PURE__ */ jsx("span", { className: "xicms-beforeafter__handle", children: "\u27E8\u27E9" }) }),
14
- /* @__PURE__ */ jsx("span", { className: "xicms-beforeafter__badge xicms-beforeafter__badge--before", "data-xicms-edit": "beforeLabel", children: block.beforeLabel }),
15
- /* @__PURE__ */ jsx("span", { className: "xicms-beforeafter__badge xicms-beforeafter__badge--after", "data-xicms-edit": "afterLabel", children: block.afterLabel }),
16
- /* @__PURE__ */ jsx(
17
- "input",
18
- {
19
- className: "xicms-beforeafter__range",
20
- type: "range",
21
- min: 0,
22
- max: 100,
23
- value: pos,
24
- onChange: (e) => setPos(Number(e.target.value)),
25
- "aria-label": `Vergelijk ${block.beforeLabel} en ${block.afterLabel}`,
26
- "aria-valuetext": `${pos}% ${block.afterLabel}`
27
- }
28
- )
29
- ] })
30
- ] });
31
- }
32
3
  const beforeAfterBlock = defineBlock({
33
4
  type: "beforeAfter",
34
5
  fields: { beforeUrl: { type: "image" }, afterUrl: { type: "image" } },
35
- Render: BeforeAfterRender,
6
+ Render: dynamic(() => import("./BeforeAfterRender.js").then((m) => m.BeforeAfterRender)),
36
7
  label: "Voor / na",
37
8
  icon: "\u{1F500}",
38
9
  defaults: () => ({ beforeUrl: "", afterUrl: "", beforeLabel: "Voor", afterLabel: "Na", aspectRatio: "4/3" })