@xiwebdesign/xicms-core 7.13.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.
- package/dist/admin/lib/mediaUsage.d.ts +17 -0
- package/dist/admin/lib/mediaUsage.js +32 -1
- package/dist/admin/lib/mediaUsage.js.map +1 -1
- package/dist/admin/media/MediaManager.js +74 -17
- package/dist/admin/media/MediaManager.js.map +1 -1
- package/dist/admin/visual/VisualEditor.js +37 -3
- package/dist/admin/visual/VisualEditor.js.map +1 -1
- package/dist/blocks/BlockErrorBoundary.d.ts +1 -0
- package/dist/blocks/BlockErrorBoundary.js +4 -0
- package/dist/blocks/BlockErrorBoundary.js.map +1 -1
- package/dist/blocks/BlockRenderer.js +1 -1
- package/dist/blocks/BlockRenderer.js.map +1 -1
- package/dist/blocks/builtins/Accordion.d.ts +1 -2
- package/dist/blocks/builtins/Accordion.js +2 -39
- package/dist/blocks/builtins/Accordion.js.map +1 -1
- package/dist/blocks/builtins/AccordionRender.d.ts +7 -0
- package/dist/blocks/builtins/AccordionRender.js +42 -0
- package/dist/blocks/builtins/AccordionRender.js.map +1 -0
- package/dist/blocks/builtins/Agenda.d.ts +1 -29
- package/dist/blocks/builtins/Agenda.js +3 -94
- package/dist/blocks/builtins/Agenda.js.map +1 -1
- package/dist/blocks/builtins/AgendaRender.d.ts +34 -0
- package/dist/blocks/builtins/AgendaRender.js +96 -0
- package/dist/blocks/builtins/AgendaRender.js.map +1 -0
- package/dist/blocks/builtins/Banner.d.ts +1 -2
- package/dist/blocks/builtins/Banner.js +2 -32
- package/dist/blocks/builtins/Banner.js.map +1 -1
- package/dist/blocks/builtins/BannerRender.d.ts +11 -0
- package/dist/blocks/builtins/BannerRender.js +35 -0
- package/dist/blocks/builtins/BannerRender.js.map +1 -0
- package/dist/blocks/builtins/BeforeAfter.d.ts +1 -2
- package/dist/blocks/builtins/BeforeAfter.js +2 -31
- package/dist/blocks/builtins/BeforeAfter.js.map +1 -1
- package/dist/blocks/builtins/BeforeAfterRender.d.ts +11 -0
- package/dist/blocks/builtins/BeforeAfterRender.js +34 -0
- package/dist/blocks/builtins/BeforeAfterRender.js.map +1 -0
- package/dist/blocks/builtins/Booking.d.ts +1 -2
- package/dist/blocks/builtins/Booking.js +2 -14
- package/dist/blocks/builtins/Booking.js.map +1 -1
- package/dist/blocks/builtins/BookingRender.d.ts +8 -0
- package/dist/blocks/builtins/BookingRender.js +17 -0
- package/dist/blocks/builtins/BookingRender.js.map +1 -0
- package/dist/blocks/builtins/Breadcrumbs.d.ts +1 -10
- package/dist/blocks/builtins/Breadcrumbs.js +3 -69
- package/dist/blocks/builtins/Breadcrumbs.js.map +1 -1
- package/dist/blocks/builtins/BreadcrumbsRender.d.ts +18 -0
- package/dist/blocks/builtins/BreadcrumbsRender.js +71 -0
- package/dist/blocks/builtins/BreadcrumbsRender.js.map +1 -0
- package/dist/blocks/builtins/Cards.d.ts +1 -2
- package/dist/blocks/builtins/Cards.js +2 -74
- package/dist/blocks/builtins/Cards.js.map +1 -1
- package/dist/blocks/builtins/CardsRender.d.ts +7 -0
- package/dist/blocks/builtins/CardsRender.js +77 -0
- package/dist/blocks/builtins/CardsRender.js.map +1 -0
- package/dist/blocks/builtins/Columns.d.ts +1 -2
- package/dist/blocks/builtins/Columns.js +2 -9
- package/dist/blocks/builtins/Columns.js.map +1 -1
- package/dist/blocks/builtins/ColumnsRender.d.ts +6 -0
- package/dist/blocks/builtins/ColumnsRender.js +12 -0
- package/dist/blocks/builtins/ColumnsRender.js.map +1 -0
- package/dist/blocks/builtins/Contact.d.ts +2 -7
- package/dist/blocks/builtins/Contact.js +3 -102
- package/dist/blocks/builtins/Contact.js.map +1 -1
- package/dist/blocks/builtins/ContactRender.d.ts +9 -0
- package/dist/blocks/builtins/ContactRender.js +105 -0
- package/dist/blocks/builtins/ContactRender.js.map +1 -0
- package/dist/blocks/builtins/Countdown.d.ts +1 -18
- package/dist/blocks/builtins/Countdown.js +3 -53
- package/dist/blocks/builtins/Countdown.js.map +1 -1
- package/dist/blocks/builtins/CountdownRender.d.ts +22 -0
- package/dist/blocks/builtins/CountdownRender.js +55 -0
- package/dist/blocks/builtins/CountdownRender.js.map +1 -0
- package/dist/blocks/builtins/Cta.d.ts +1 -2
- package/dist/blocks/builtins/Cta.js +2 -39
- package/dist/blocks/builtins/Cta.js.map +1 -1
- package/dist/blocks/builtins/CtaRender.d.ts +6 -0
- package/dist/blocks/builtins/CtaRender.js +42 -0
- package/dist/blocks/builtins/CtaRender.js.map +1 -0
- package/dist/blocks/builtins/Downloads.d.ts +1 -2
- package/dist/blocks/builtins/Downloads.js +2 -16
- package/dist/blocks/builtins/Downloads.js.map +1 -1
- package/dist/blocks/builtins/DownloadsRender.d.ts +7 -0
- package/dist/blocks/builtins/DownloadsRender.js +19 -0
- package/dist/blocks/builtins/DownloadsRender.js.map +1 -0
- package/dist/blocks/builtins/Elements.d.ts +3 -4
- package/dist/blocks/builtins/Elements.js +4 -38
- package/dist/blocks/builtins/Elements.js.map +1 -1
- package/dist/blocks/builtins/ElementsRender.d.ts +10 -0
- package/dist/blocks/builtins/ElementsRender.js +41 -0
- package/dist/blocks/builtins/ElementsRender.js.map +1 -0
- package/dist/blocks/builtins/Embed.d.ts +1 -2
- package/dist/blocks/builtins/Embed.js +2 -19
- package/dist/blocks/builtins/Embed.js.map +1 -1
- package/dist/blocks/builtins/EmbedRender.d.ts +7 -0
- package/dist/blocks/builtins/EmbedRender.js +22 -0
- package/dist/blocks/builtins/EmbedRender.js.map +1 -0
- package/dist/blocks/builtins/Faq.d.ts +1 -6
- package/dist/blocks/builtins/Faq.js +3 -103
- package/dist/blocks/builtins/Faq.js.map +1 -1
- package/dist/blocks/builtins/FaqRender.d.ts +10 -0
- package/dist/blocks/builtins/FaqRender.js +105 -0
- package/dist/blocks/builtins/FaqRender.js.map +1 -0
- package/dist/blocks/builtins/FormBlock.d.ts +1 -2
- package/dist/blocks/builtins/FormBlock.js +2 -222
- package/dist/blocks/builtins/FormBlock.js.map +1 -1
- package/dist/blocks/builtins/FormBlockRender.d.ts +6 -0
- package/dist/blocks/builtins/FormBlockRender.js +225 -0
- package/dist/blocks/builtins/FormBlockRender.js.map +1 -0
- package/dist/blocks/builtins/Gallery.d.ts +1 -23
- package/dist/blocks/builtins/Gallery.js +2 -164
- package/dist/blocks/builtins/Gallery.js.map +1 -1
- package/dist/blocks/builtins/GalleryRender.d.ts +25 -0
- package/dist/blocks/builtins/GalleryRender.js +167 -0
- package/dist/blocks/builtins/GalleryRender.js.map +1 -0
- package/dist/blocks/builtins/Hero.d.ts +1 -2
- package/dist/blocks/builtins/Hero.js +2 -73
- package/dist/blocks/builtins/Hero.js.map +1 -1
- package/dist/blocks/builtins/HeroRender.d.ts +6 -0
- package/dist/blocks/builtins/HeroRender.js +76 -0
- package/dist/blocks/builtins/HeroRender.js.map +1 -0
- package/dist/blocks/builtins/ImageBlock.d.ts +1 -2
- package/dist/blocks/builtins/ImageBlock.js +2 -22
- package/dist/blocks/builtins/ImageBlock.js.map +1 -1
- package/dist/blocks/builtins/ImageBlockRender.d.ts +6 -0
- package/dist/blocks/builtins/ImageBlockRender.js +25 -0
- package/dist/blocks/builtins/ImageBlockRender.js.map +1 -0
- package/dist/blocks/builtins/Jobs.d.ts +1 -15
- package/dist/blocks/builtins/Jobs.js +3 -69
- package/dist/blocks/builtins/Jobs.js.map +1 -1
- package/dist/blocks/builtins/JobsRender.d.ts +17 -0
- package/dist/blocks/builtins/JobsRender.js +71 -0
- package/dist/blocks/builtins/JobsRender.js.map +1 -0
- package/dist/blocks/builtins/Layout.d.ts +2 -3
- package/dist/blocks/builtins/Layout.js +3 -39
- package/dist/blocks/builtins/Layout.js.map +1 -1
- package/dist/blocks/builtins/LayoutRender.d.ts +8 -0
- package/dist/blocks/builtins/LayoutRender.js +42 -0
- package/dist/blocks/builtins/LayoutRender.js.map +1 -0
- package/dist/blocks/builtins/MapBlock.d.ts +1 -2
- package/dist/blocks/builtins/MapBlock.js +2 -45
- package/dist/blocks/builtins/MapBlock.js.map +1 -1
- package/dist/blocks/builtins/MapBlockRender.d.ts +6 -0
- package/dist/blocks/builtins/MapBlockRender.js +48 -0
- package/dist/blocks/builtins/MapBlockRender.js.map +1 -0
- package/dist/blocks/builtins/NewsListBlock.d.ts +1 -2
- package/dist/blocks/builtins/NewsListBlock.js +2 -11
- package/dist/blocks/builtins/NewsListBlock.js.map +1 -1
- package/dist/blocks/builtins/NewsListBlockRender.d.ts +6 -0
- package/dist/blocks/builtins/NewsListBlockRender.js +14 -0
- package/dist/blocks/builtins/NewsListBlockRender.js.map +1 -0
- package/dist/blocks/builtins/Newsletter.d.ts +1 -2
- package/dist/blocks/builtins/Newsletter.js +2 -89
- package/dist/blocks/builtins/Newsletter.js.map +1 -1
- package/dist/blocks/builtins/NewsletterRender.d.ts +13 -0
- package/dist/blocks/builtins/NewsletterRender.js +92 -0
- package/dist/blocks/builtins/NewsletterRender.js.map +1 -0
- package/dist/blocks/builtins/OpeningHours.d.ts +1 -2
- package/dist/blocks/builtins/OpeningHours.js +2 -28
- package/dist/blocks/builtins/OpeningHours.js.map +1 -1
- package/dist/blocks/builtins/OpeningHoursRender.d.ts +7 -0
- package/dist/blocks/builtins/OpeningHoursRender.js +31 -0
- package/dist/blocks/builtins/OpeningHoursRender.js.map +1 -0
- package/dist/blocks/builtins/PdfBlock.d.ts +1 -2
- package/dist/blocks/builtins/PdfBlock.js +2 -76
- package/dist/blocks/builtins/PdfBlock.js.map +1 -1
- package/dist/blocks/builtins/PdfBlockRender.d.ts +11 -0
- package/dist/blocks/builtins/PdfBlockRender.js +79 -0
- package/dist/blocks/builtins/PdfBlockRender.js.map +1 -0
- package/dist/blocks/builtins/Portfolio.d.ts +1 -2
- package/dist/blocks/builtins/Portfolio.js +2 -75
- package/dist/blocks/builtins/Portfolio.js.map +1 -1
- package/dist/blocks/builtins/PortfolioRender.d.ts +7 -0
- package/dist/blocks/builtins/PortfolioRender.js +78 -0
- package/dist/blocks/builtins/PortfolioRender.js.map +1 -0
- package/dist/blocks/builtins/Pricing.d.ts +1 -8
- package/dist/blocks/builtins/Pricing.js +3 -73
- package/dist/blocks/builtins/Pricing.js.map +1 -1
- package/dist/blocks/builtins/PricingRender.d.ts +10 -0
- package/dist/blocks/builtins/PricingRender.js +75 -0
- package/dist/blocks/builtins/PricingRender.js.map +1 -0
- package/dist/blocks/builtins/RichTextBlock.d.ts +1 -2
- package/dist/blocks/builtins/RichTextBlock.js +2 -5
- package/dist/blocks/builtins/RichTextBlock.js.map +1 -1
- package/dist/blocks/builtins/RichTextBlockRender.d.ts +6 -0
- package/dist/blocks/builtins/RichTextBlockRender.js +8 -0
- package/dist/blocks/builtins/RichTextBlockRender.js.map +1 -0
- package/dist/blocks/builtins/Search.d.ts +1 -2
- package/dist/blocks/builtins/Search.js +2 -80
- package/dist/blocks/builtins/Search.js.map +1 -1
- package/dist/blocks/builtins/SearchRender.d.ts +7 -0
- package/dist/blocks/builtins/SearchRender.js +83 -0
- package/dist/blocks/builtins/SearchRender.js.map +1 -0
- package/dist/blocks/builtins/Sections.d.ts +4 -5
- package/dist/blocks/builtins/Sections.js +5 -142
- package/dist/blocks/builtins/Sections.js.map +1 -1
- package/dist/blocks/builtins/SectionsRender.d.ts +12 -0
- package/dist/blocks/builtins/SectionsRender.js +145 -0
- package/dist/blocks/builtins/SectionsRender.js.map +1 -0
- package/dist/blocks/builtins/Slider.d.ts +1 -2
- package/dist/blocks/builtins/Slider.js +2 -134
- package/dist/blocks/builtins/Slider.js.map +1 -1
- package/dist/blocks/builtins/SliderRender.d.ts +7 -0
- package/dist/blocks/builtins/SliderRender.js +137 -0
- package/dist/blocks/builtins/SliderRender.js.map +1 -0
- package/dist/blocks/builtins/Spacer.d.ts +1 -2
- package/dist/blocks/builtins/Spacer.js +2 -6
- package/dist/blocks/builtins/Spacer.js.map +1 -1
- package/dist/blocks/builtins/SpacerRender.d.ts +6 -0
- package/dist/blocks/builtins/SpacerRender.js +9 -0
- package/dist/blocks/builtins/SpacerRender.js.map +1 -0
- package/dist/blocks/builtins/SymbolRef.d.ts +1 -2
- package/dist/blocks/builtins/SymbolRef.js +2 -76
- package/dist/blocks/builtins/SymbolRef.js.map +1 -1
- package/dist/blocks/builtins/SymbolRefRender.d.ts +13 -0
- package/dist/blocks/builtins/SymbolRefRender.js +79 -0
- package/dist/blocks/builtins/SymbolRefRender.js.map +1 -0
- package/dist/blocks/builtins/Team.d.ts +1 -2
- package/dist/blocks/builtins/Team.js +2 -55
- package/dist/blocks/builtins/Team.js.map +1 -1
- package/dist/blocks/builtins/TeamRender.d.ts +7 -0
- package/dist/blocks/builtins/TeamRender.js +58 -0
- package/dist/blocks/builtins/TeamRender.js.map +1 -0
- package/dist/blocks/builtins/Testimonials.d.ts +1 -8
- package/dist/blocks/builtins/Testimonials.js +2 -69
- package/dist/blocks/builtins/Testimonials.js.map +1 -1
- package/dist/blocks/builtins/TestimonialsRender.d.ts +10 -0
- package/dist/blocks/builtins/TestimonialsRender.js +72 -0
- package/dist/blocks/builtins/TestimonialsRender.js.map +1 -0
- package/dist/blocks/builtins/Video.d.ts +1 -9
- package/dist/blocks/builtins/Video.js +2 -64
- package/dist/blocks/builtins/Video.js.map +1 -1
- package/dist/blocks/builtins/VideoRender.d.ts +10 -0
- package/dist/blocks/builtins/VideoRender.js +67 -0
- package/dist/blocks/builtins/VideoRender.js.map +1 -0
- package/dist/blocks/builtins/WhatsappChat.d.ts +1 -8
- package/dist/blocks/builtins/WhatsappChat.js +2 -37
- package/dist/blocks/builtins/WhatsappChat.js.map +1 -1
- package/dist/blocks/builtins/WhatsappChatRender.d.ts +17 -0
- package/dist/blocks/builtins/WhatsappChatRender.js +40 -0
- package/dist/blocks/builtins/WhatsappChatRender.js.map +1 -0
- package/dist/blocks/builtins/Widgets.d.ts +12 -13
- package/dist/blocks/builtins/Widgets.js +13 -175
- package/dist/blocks/builtins/Widgets.js.map +1 -1
- package/dist/blocks/builtins/WidgetsRender.d.ts +34 -0
- package/dist/blocks/builtins/WidgetsRender.js +178 -0
- package/dist/blocks/builtins/WidgetsRender.js.map +1 -0
- package/dist/blocks/reportRenderFout.d.ts +13 -0
- package/dist/blocks/reportRenderFout.js +31 -0
- package/dist/blocks/reportRenderFout.js.map +1 -0
- package/dist/modules/contract.js +2 -1
- package/dist/modules/contract.js.map +1 -1
- package/dist/modules/shop/blocks/Cart.js +1 -2
- package/dist/modules/shop/blocks/Cart.js.map +1 -1
- package/dist/modules/shop/blocks/Checkout.js +1 -2
- package/dist/modules/shop/blocks/Checkout.js.map +1 -1
- package/dist/modules/shop/blocks/Donation.js +1 -2
- package/dist/modules/shop/blocks/Donation.js.map +1 -1
- package/dist/modules/shop/blocks/OrderStatus.js +0 -2
- package/dist/modules/shop/blocks/OrderStatus.js.map +1 -1
- package/dist/modules/shop/blocks/ProductDetail.js +1 -7
- package/dist/modules/shop/blocks/ProductDetail.js.map +1 -1
- package/dist/modules/shop/blocks/ProductGrid.js +1 -2
- package/dist/modules/shop/blocks/ProductGrid.js.map +1 -1
- package/dist/modules/shop/blocks/ShopCategories.js +0 -2
- package/dist/modules/shop/blocks/ShopCategories.js.map +1 -1
- package/dist/modules/shop/module.js +1 -0
- package/dist/modules/shop/module.js.map +1 -1
- package/dist/modules/shop/schemas.d.ts +1 -0
- package/dist/modules/shop/schemas.js +32 -0
- package/dist/modules/shop/schemas.js.map +1 -0
- package/dist/modules/types.d.ts +6 -0
- package/dist/schema/shop.d.ts +1 -11
- package/dist/schema/shop.js +1 -20
- package/dist/schema/shop.js.map +1 -1
- package/dist/schema/shopGeld.d.ts +18 -0
- package/dist/schema/shopGeld.js +27 -0
- package/dist/schema/shopGeld.js.map +1 -0
- package/dist/styles.css +17 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Component } from "react";
|
|
4
|
+
import { reportRenderFout } from "./reportRenderFout.js";
|
|
4
5
|
class BlockErrorBoundary extends Component {
|
|
5
6
|
state = { error: null };
|
|
6
7
|
static getDerivedStateFromError(error) {
|
|
@@ -10,6 +11,9 @@ class BlockErrorBoundary extends Component {
|
|
|
10
11
|
if (typeof console !== "undefined") {
|
|
11
12
|
console.error(`[xicms] block "${this.props.type}" gaf een renderfout:`, error, info);
|
|
12
13
|
}
|
|
14
|
+
if (this.props.mode === "view" && this.props.siteId) {
|
|
15
|
+
reportRenderFout(this.props.siteId, this.props.type, error?.message ?? String(error));
|
|
16
|
+
}
|
|
13
17
|
}
|
|
14
18
|
componentDidUpdate(prev) {
|
|
15
19
|
if (this.state.error && (prev.blockKey !== this.props.blockKey || prev.type !== this.props.type)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/blocks/BlockErrorBoundary.tsx"],"sourcesContent":["\"use client\";\n\nimport { Component, type ErrorInfo, type ReactNode } from \"react\";\n\n/**\n * Vangt een fout in één block-Render op zodat één kapot block nooit de hele pagina sloopt\n * (foolproof: een editor kan geen content maken die de live site breekt).\n *\n * - `mode=\"view\"` (publiek): faalt stil — rendert niets, layout blijft intact.\n * - `mode=\"preview\"` (editor): toont een zichtbare foutkaart zodat de bewerker de breuk ziet.\n *\n * Let op de RSC-grens: een error-boundary is per definitie client (`componentDidCatch`). Daarom is\n * dit een client-leaf die per block om de Render heen wordt gezet; `BlockRenderer` zelf blijft\n * server-importeerbaar. Een fout die al tijdens server-rendering wordt gegooid valt buiten een\n * client-boundary — maar `validateBlocks` haalt schema-ongeldige content er server-side al uit, en\n * de meeste runtime-render-fouten (kapotte URL, client-hook) gebeuren client-side en worden hier\n * dus wél gevangen.\n */\ninterface Props {\n mode: \"view\" | \"preview\";\n type: string;\n blockKey: string;\n children: ReactNode;\n}\ninterface State {\n error: Error | null;\n}\n\nexport class BlockErrorBoundary extends Component<Props, State> {\n state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n componentDidCatch(error: Error, info: ErrorInfo): void {\n if (typeof console !== \"undefined\") {\n console.error(`[xicms] block \"${this.props.type}\" gaf een renderfout:`, error, info);\n }\n }\n\n componentDidUpdate(prev: Props): void {\n // Reset na een fix (ander block of ander type) zodat het block opnieuw probeert te renderen.\n if (this.state.error && (prev.blockKey !== this.props.blockKey || prev.type !== this.props.type)) {\n this.setState({ error: null });\n }\n }\n\n render(): ReactNode {\n if (this.state.error) {\n if (this.props.mode === \"preview\") {\n return (\n <div className=\"xicms-block-error\" role=\"alert\">\n <strong>Blok “{this.props.type}” kon niet worden weergegeven.</strong>\n <span>{this.state.error.message}</span>\n </div>\n );\n }\n // Publiek: stil falen, geen layout-verstoring.\n return null;\n }\n return this.props.children;\n }\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"sources":["../../src/blocks/BlockErrorBoundary.tsx"],"sourcesContent":["\"use client\";\n\nimport { Component, type ErrorInfo, type ReactNode } from \"react\";\nimport { reportRenderFout } from \"./reportRenderFout\";\n\n/**\n * Vangt een fout in één block-Render op zodat één kapot block nooit de hele pagina sloopt\n * (foolproof: een editor kan geen content maken die de live site breekt).\n *\n * - `mode=\"view\"` (publiek): faalt stil — rendert niets, layout blijft intact.\n * - `mode=\"preview\"` (editor): toont een zichtbare foutkaart zodat de bewerker de breuk ziet.\n *\n * Let op de RSC-grens: een error-boundary is per definitie client (`componentDidCatch`). Daarom is\n * dit een client-leaf die per block om de Render heen wordt gezet; `BlockRenderer` zelf blijft\n * server-importeerbaar. Een fout die al tijdens server-rendering wordt gegooid valt buiten een\n * client-boundary — maar `validateBlocks` haalt schema-ongeldige content er server-side al uit, en\n * de meeste runtime-render-fouten (kapotte URL, client-hook) gebeuren client-side en worden hier\n * dus wél gevangen.\n */\ninterface Props {\n mode: \"view\" | \"preview\";\n type: string;\n blockKey: string;\n siteId?: string;\n children: ReactNode;\n}\ninterface State {\n error: Error | null;\n}\n\nexport class BlockErrorBoundary extends Component<Props, State> {\n state: State = { error: null };\n\n static getDerivedStateFromError(error: Error): State {\n return { error };\n }\n\n componentDidCatch(error: Error, info: ErrorInfo): void {\n if (typeof console !== \"undefined\") {\n console.error(`[xicms] block \"${this.props.type}\" gaf een renderfout:`, error, info);\n }\n // Publiek (mode=\"view\"): meld de fout aan de backend — de bezoeker ziet niets (dat is de\n // belofte van deze boundary), maar wij horen het via Cloud Logging/Monitoring. In de editor\n // niet: daar stáát de bewerker naar de foutkaart te kijken.\n if (this.props.mode === \"view\" && this.props.siteId) {\n reportRenderFout(this.props.siteId, this.props.type, error?.message ?? String(error));\n }\n }\n\n componentDidUpdate(prev: Props): void {\n // Reset na een fix (ander block of ander type) zodat het block opnieuw probeert te renderen.\n if (this.state.error && (prev.blockKey !== this.props.blockKey || prev.type !== this.props.type)) {\n this.setState({ error: null });\n }\n }\n\n render(): ReactNode {\n if (this.state.error) {\n if (this.props.mode === \"preview\") {\n return (\n <div className=\"xicms-block-error\" role=\"alert\">\n <strong>Blok “{this.props.type}” kon niet worden weergegeven.</strong>\n <span>{this.state.error.message}</span>\n </div>\n );\n }\n // Publiek: stil falen, geen layout-verstoring.\n return null;\n }\n return this.props.children;\n }\n}\n"],"mappings":";AA6DY,SACA,KADA;AA3DZ,SAAS,iBAAiD;AAC1D,SAAS,wBAAwB;AA2B1B,MAAM,2BAA2B,UAAwB;AAAA,EAC9D,QAAe,EAAE,OAAO,KAAK;AAAA,EAE7B,OAAO,yBAAyB,OAAqB;AACnD,WAAO,EAAE,MAAM;AAAA,EACjB;AAAA,EAEA,kBAAkB,OAAc,MAAuB;AACrD,QAAI,OAAO,YAAY,aAAa;AAClC,cAAQ,MAAM,kBAAkB,KAAK,MAAM,IAAI,yBAAyB,OAAO,IAAI;AAAA,IACrF;AAIA,QAAI,KAAK,MAAM,SAAS,UAAU,KAAK,MAAM,QAAQ;AACnD,uBAAiB,KAAK,MAAM,QAAQ,KAAK,MAAM,MAAM,OAAO,WAAW,OAAO,KAAK,CAAC;AAAA,IACtF;AAAA,EACF;AAAA,EAEA,mBAAmB,MAAmB;AAEpC,QAAI,KAAK,MAAM,UAAU,KAAK,aAAa,KAAK,MAAM,YAAY,KAAK,SAAS,KAAK,MAAM,OAAO;AAChG,WAAK,SAAS,EAAE,OAAO,KAAK,CAAC;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,SAAoB;AAClB,QAAI,KAAK,MAAM,OAAO;AACpB,UAAI,KAAK,MAAM,SAAS,WAAW;AACjC,eACE,qBAAC,SAAI,WAAU,qBAAoB,MAAK,SACtC;AAAA,+BAAC,YAAO;AAAA;AAAA,YAAO,KAAK,MAAM;AAAA,YAAK;AAAA,aAA8B;AAAA,UAC7D,oBAAC,UAAM,eAAK,MAAM,MAAM,SAAQ;AAAA,WAClC;AAAA,MAEJ;AAEA,aAAO;AAAA,IACT;AACA,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;","names":[]}
|
|
@@ -15,7 +15,7 @@ function BlockRenderer({
|
|
|
15
15
|
const Render = def.Render;
|
|
16
16
|
const attrs = blockStyleAttrs(b._style);
|
|
17
17
|
const rendered = /* @__PURE__ */ jsx(Render, { block: b, siteId, mode });
|
|
18
|
-
return /* @__PURE__ */ jsx(BlockErrorBoundary, { mode, type: b._type, blockKey: b._key, children: attrs ? /* @__PURE__ */ jsx(
|
|
18
|
+
return /* @__PURE__ */ jsx(BlockErrorBoundary, { mode, type: b._type, blockKey: b._key, siteId, children: attrs ? /* @__PURE__ */ jsx(
|
|
19
19
|
"div",
|
|
20
20
|
{
|
|
21
21
|
id: attrs.id,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/blocks/BlockRenderer.tsx"],"sourcesContent":["import { validateBlocks, type BlockRegistry } from \"./registry\";\nimport { BlockErrorBoundary } from \"./BlockErrorBoundary\";\nimport { blockStyleAttrs } from \"./blockStyle\";\nimport type { BlockStyle } from \"../schema/blocks\";\n\n/**\n * Rendert een blocks-array via de registry. Server-safe (geen \"use client\"): bruikbaar in\n * React Server Components én client. Geef de registry expliciet mee (zo werkt server-rendering);\n * client-componenten kunnen `useRegistry()` gebruiken om hem te verkrijgen.\n *\n * Elk block wordt in een `BlockErrorBoundary` gewikkeld zodat één kapot block nooit de hele\n * pagina sloopt (foolproof).\n */\nexport function BlockRenderer({\n blocks,\n registry,\n siteId,\n mode = \"view\",\n}: {\n blocks: unknown[] | undefined;\n registry: BlockRegistry;\n siteId: string;\n mode?: \"view\" | \"preview\";\n}) {\n const valid = validateBlocks(blocks, registry);\n return (\n <>\n {valid.map((b) => {\n const def = registry.get(b._type);\n if (!def) return null;\n const Render = def.Render;\n // Gedeelde blokstijl (ruimte/achtergrond/breedte/uitlijning/anker) centraal toepassen.\n const attrs = blockStyleAttrs((b as { _style?: BlockStyle })._style);\n const rendered = <Render block={b} siteId={siteId} mode={mode} />;\n // Altijd een DOM-wrapper met een stabiele block-identifier, zodat het feedback-widget\n // (en andere tooling) een onderdeel op de pagina kan aanwijzen via\n // `closest('[data-xicms-block]')`. Zonder eigen blokstijl gebruiken we `display:contents`\n // zodat de wrapper layout-neutraal is (hij traverseert wél mee in `closest()`).\n return (\n <BlockErrorBoundary key={b._key} mode={mode} type={b._type} blockKey={b._key}>\n {attrs ? (\n <div\n id={attrs.id}\n className={attrs.className}\n style={attrs.style}\n data-xicms-animate={attrs.dataAnimate}\n data-xicms-block={b._key}\n data-xicms-block-type={b._type}\n >\n {rendered}\n </div>\n ) : (\n <div style={{ display: \"contents\" }} data-xicms-block={b._key} data-xicms-block-type={b._type}>\n {rendered}\n </div>\n )}\n </BlockErrorBoundary>\n );\n })}\n </>\n );\n}\n"],"mappings":"AA0BI,mBAOqB,WAPrB;AA1BJ,SAAS,sBAA0C;AACnD,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAWzB,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AACT,GAKG;AACD,QAAM,QAAQ,eAAe,QAAQ,QAAQ;AAC7C,SACE,gCACG,gBAAM,IAAI,CAAC,MAAM;AAChB,UAAM,MAAM,SAAS,IAAI,EAAE,KAAK;AAChC,QAAI,CAAC,IAAK,QAAO;AACjB,UAAM,SAAS,IAAI;AAEnB,UAAM,QAAQ,gBAAiB,EAA8B,MAAM;AACnE,UAAM,WAAW,oBAAC,UAAO,OAAO,GAAG,QAAgB,MAAY;AAK/D,WACE,oBAAC,sBAAgC,MAAY,MAAM,EAAE,OAAO,UAAU,EAAE,
|
|
1
|
+
{"version":3,"sources":["../../src/blocks/BlockRenderer.tsx"],"sourcesContent":["import { validateBlocks, type BlockRegistry } from \"./registry\";\nimport { BlockErrorBoundary } from \"./BlockErrorBoundary\";\nimport { blockStyleAttrs } from \"./blockStyle\";\nimport type { BlockStyle } from \"../schema/blocks\";\n\n/**\n * Rendert een blocks-array via de registry. Server-safe (geen \"use client\"): bruikbaar in\n * React Server Components én client. Geef de registry expliciet mee (zo werkt server-rendering);\n * client-componenten kunnen `useRegistry()` gebruiken om hem te verkrijgen.\n *\n * Elk block wordt in een `BlockErrorBoundary` gewikkeld zodat één kapot block nooit de hele\n * pagina sloopt (foolproof).\n */\nexport function BlockRenderer({\n blocks,\n registry,\n siteId,\n mode = \"view\",\n}: {\n blocks: unknown[] | undefined;\n registry: BlockRegistry;\n siteId: string;\n mode?: \"view\" | \"preview\";\n}) {\n const valid = validateBlocks(blocks, registry);\n return (\n <>\n {valid.map((b) => {\n const def = registry.get(b._type);\n if (!def) return null;\n const Render = def.Render;\n // Gedeelde blokstijl (ruimte/achtergrond/breedte/uitlijning/anker) centraal toepassen.\n const attrs = blockStyleAttrs((b as { _style?: BlockStyle })._style);\n const rendered = <Render block={b} siteId={siteId} mode={mode} />;\n // Altijd een DOM-wrapper met een stabiele block-identifier, zodat het feedback-widget\n // (en andere tooling) een onderdeel op de pagina kan aanwijzen via\n // `closest('[data-xicms-block]')`. Zonder eigen blokstijl gebruiken we `display:contents`\n // zodat de wrapper layout-neutraal is (hij traverseert wél mee in `closest()`).\n return (\n <BlockErrorBoundary key={b._key} mode={mode} type={b._type} blockKey={b._key} siteId={siteId}>\n {attrs ? (\n <div\n id={attrs.id}\n className={attrs.className}\n style={attrs.style}\n data-xicms-animate={attrs.dataAnimate}\n data-xicms-block={b._key}\n data-xicms-block-type={b._type}\n >\n {rendered}\n </div>\n ) : (\n <div style={{ display: \"contents\" }} data-xicms-block={b._key} data-xicms-block-type={b._type}>\n {rendered}\n </div>\n )}\n </BlockErrorBoundary>\n );\n })}\n </>\n );\n}\n"],"mappings":"AA0BI,mBAOqB,WAPrB;AA1BJ,SAAS,sBAA0C;AACnD,SAAS,0BAA0B;AACnC,SAAS,uBAAuB;AAWzB,SAAS,cAAc;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AACT,GAKG;AACD,QAAM,QAAQ,eAAe,QAAQ,QAAQ;AAC7C,SACE,gCACG,gBAAM,IAAI,CAAC,MAAM;AAChB,UAAM,MAAM,SAAS,IAAI,EAAE,KAAK;AAChC,QAAI,CAAC,IAAK,QAAO;AACjB,UAAM,SAAS,IAAI;AAEnB,UAAM,QAAQ,gBAAiB,EAA8B,MAAM;AACnE,UAAM,WAAW,oBAAC,UAAO,OAAO,GAAG,QAAgB,MAAY;AAK/D,WACE,oBAAC,sBAAgC,MAAY,MAAM,EAAE,OAAO,UAAU,EAAE,MAAM,QAC3E,kBACC;AAAA,MAAC;AAAA;AAAA,QACC,IAAI,MAAM;AAAA,QACV,WAAW,MAAM;AAAA,QACjB,OAAO,MAAM;AAAA,QACb,sBAAoB,MAAM;AAAA,QAC1B,oBAAkB,EAAE;AAAA,QACpB,yBAAuB,EAAE;AAAA,QAExB;AAAA;AAAA,IACH,IAEA,oBAAC,SAAI,OAAO,EAAE,SAAS,WAAW,GAAG,oBAAkB,EAAE,MAAM,yBAAuB,EAAE,OACrF,oBACH,KAfqB,EAAE,IAiB3B;AAAA,EAEJ,CAAC,GACH;AAEJ;","names":[]}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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":["
|
|
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
|
-
|
|
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
|
|
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
|
|
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":"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","names":[]}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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":["
|
|
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 {};
|