@xiwebdesign/xicms-core 7.30.0 → 8.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/XiCMSProvider.js +22 -7
- package/dist/XiCMSProvider.js.map +1 -1
- package/dist/admin/AdminApp.js +175 -93
- package/dist/admin/AdminApp.js.map +1 -1
- package/dist/admin/AdminHelp.d.ts +1 -1
- package/dist/admin/AdminHelp.js +44 -36
- package/dist/admin/AdminHelp.js.map +1 -1
- package/dist/admin/CoreVersion.d.ts +6 -3
- package/dist/admin/CoreVersion.js +60 -24
- package/dist/admin/CoreVersion.js.map +1 -1
- package/dist/admin/NewsEditor.d.ts +7 -0
- package/dist/admin/NewsEditor.js +117 -75
- package/dist/admin/NewsEditor.js.map +1 -1
- package/dist/admin/SuperadminPanel.js +1 -1
- package/dist/admin/SuperadminPanel.js.map +1 -1
- package/dist/admin/ZoekPalet.d.ts +15 -0
- package/dist/admin/ZoekPalet.js +123 -0
- package/dist/admin/ZoekPalet.js.map +1 -0
- package/dist/admin/blockEditors/GenericEditor.js +36 -18
- package/dist/admin/blockEditors/GenericEditor.js.map +1 -1
- package/dist/admin/blockEditors/StyleEditor.js +37 -3
- package/dist/admin/blockEditors/StyleEditor.js.map +1 -1
- package/dist/admin/blockEditors/SymbolRefEditor.js +44 -2
- package/dist/admin/blockEditors/SymbolRefEditor.js.map +1 -1
- package/dist/admin/blockEditors/index.js +154 -73
- package/dist/admin/blockEditors/index.js.map +1 -1
- package/dist/admin/customBlocks/CustomBlocksPanel.js +18 -7
- package/dist/admin/customBlocks/CustomBlocksPanel.js.map +1 -1
- package/dist/admin/dashboard/DashboardPanel.js +26 -16
- package/dist/admin/dashboard/DashboardPanel.js.map +1 -1
- package/dist/admin/editors/RichTextEditor.d.ts +4 -3
- package/dist/admin/editors/RichTextEditor.js +19 -56
- package/dist/admin/editors/RichTextEditor.js.map +1 -1
- package/dist/admin/editors/fontSizeExtension.js +7 -1
- package/dist/admin/editors/fontSizeExtension.js.map +1 -1
- package/dist/admin/editors/slashMenu.d.ts +18 -0
- package/dist/admin/editors/slashMenu.js +34 -0
- package/dist/admin/editors/slashMenu.js.map +1 -0
- package/dist/admin/editors/useRijkeTekst.d.ts +48 -0
- package/dist/admin/editors/useRijkeTekst.js +310 -0
- package/dist/admin/editors/useRijkeTekst.js.map +1 -0
- package/dist/admin/forms/FormsPanel.d.ts +11 -2
- package/dist/admin/forms/FormsPanel.js +218 -65
- package/dist/admin/forms/FormsPanel.js.map +1 -1
- package/dist/admin/lib/blokInfo.d.ts +17 -0
- package/dist/admin/lib/blokInfo.js +80 -0
- package/dist/admin/lib/blokInfo.js.map +1 -0
- package/dist/admin/lib/foutNaarMens.d.ts +1 -0
- package/dist/admin/lib/foutNaarMens.js +22 -0
- package/dist/admin/lib/foutNaarMens.js.map +1 -0
- package/dist/admin/lib/gewisteVelden.d.ts +13 -0
- package/dist/admin/lib/gewisteVelden.js +31 -0
- package/dist/admin/lib/gewisteVelden.js.map +1 -0
- package/dist/admin/lib/heroHulp.d.ts +11 -0
- package/dist/admin/lib/heroHulp.js +18 -0
- package/dist/admin/lib/heroHulp.js.map +1 -0
- package/dist/admin/lib/kleur.js +2 -3
- package/dist/admin/lib/kleur.js.map +1 -1
- package/dist/admin/lib/leesbaarheid.d.ts +34 -0
- package/dist/admin/lib/leesbaarheid.js +82 -0
- package/dist/admin/lib/leesbaarheid.js.map +1 -0
- package/dist/admin/lib/lengteAdvies.d.ts +1 -0
- package/dist/admin/lib/lengteAdvies.js +16 -0
- package/dist/admin/lib/lengteAdvies.js.map +1 -0
- package/dist/admin/lib/mediaLijst.d.ts +26 -0
- package/dist/admin/lib/mediaLijst.js +42 -0
- package/dist/admin/lib/mediaLijst.js.map +1 -0
- package/dist/admin/lib/mediaUsage.d.ts +12 -1
- package/dist/admin/lib/mediaUsage.js +43 -33
- package/dist/admin/lib/mediaUsage.js.map +1 -1
- package/dist/admin/lib/menuHulp.d.ts +16 -0
- package/dist/admin/lib/menuHulp.js +41 -0
- package/dist/admin/lib/menuHulp.js.map +1 -0
- package/dist/admin/lib/onopgeslagen.d.ts +10 -0
- package/dist/admin/lib/onopgeslagen.js +35 -0
- package/dist/admin/lib/onopgeslagen.js.map +1 -0
- package/dist/admin/lib/pagesClient.d.ts +55 -2
- package/dist/admin/lib/pagesClient.js +126 -28
- package/dist/admin/lib/pagesClient.js.map +1 -1
- package/dist/admin/lib/paginaGebruik.d.ts +56 -0
- package/dist/admin/lib/paginaGebruik.js +109 -0
- package/dist/admin/lib/paginaGebruik.js.map +1 -0
- package/dist/admin/lib/publicatieCheck.d.ts +25 -0
- package/dist/admin/lib/publicatieCheck.js +114 -0
- package/dist/admin/lib/publicatieCheck.js.map +1 -0
- package/dist/admin/lib/scrollNaarDetail.d.ts +6 -0
- package/dist/admin/lib/scrollNaarDetail.js +20 -0
- package/dist/admin/lib/scrollNaarDetail.js.map +1 -0
- package/dist/admin/lib/symbolsClient.d.ts +10 -0
- package/dist/admin/lib/symbolsClient.js +14 -1
- package/dist/admin/lib/symbolsClient.js.map +1 -1
- package/dist/admin/lib/tekstVeld.d.ts +8 -0
- package/dist/admin/lib/tekstVeld.js +10 -0
- package/dist/admin/lib/tekstVeld.js.map +1 -0
- package/dist/admin/lib/useIsSuperadmin.d.ts +2 -0
- package/dist/admin/lib/useIsSuperadmin.js +13 -0
- package/dist/admin/lib/useIsSuperadmin.js.map +1 -0
- package/dist/admin/lib/veldTaal.d.ts +14 -0
- package/dist/admin/lib/veldTaal.js +247 -0
- package/dist/admin/lib/veldTaal.js.map +1 -0
- package/dist/admin/lib/versieVergelijk.d.ts +17 -0
- package/dist/admin/lib/versieVergelijk.js +24 -0
- package/dist/admin/lib/versieVergelijk.js.map +1 -0
- package/dist/admin/lib/zodFields.js +22 -4
- package/dist/admin/lib/zodFields.js.map +1 -1
- package/dist/admin/lib/zodFout.d.ts +9 -0
- package/dist/admin/lib/zodFout.js +63 -0
- package/dist/admin/lib/zodFout.js.map +1 -0
- package/dist/admin/media/MediaManager.js +162 -32
- package/dist/admin/media/MediaManager.js.map +1 -1
- package/dist/admin/media/MediaPicker.d.ts +3 -0
- package/dist/admin/media/MediaPicker.js +84 -31
- package/dist/admin/media/MediaPicker.js.map +1 -1
- package/dist/admin/menu/MenuPanel.js +144 -83
- package/dist/admin/menu/MenuPanel.js.map +1 -1
- package/dist/admin/navContext.d.ts +3 -0
- package/dist/admin/navContext.js +13 -1
- package/dist/admin/navContext.js.map +1 -1
- package/dist/admin/pages/PageEditor.js +146 -30
- package/dist/admin/pages/PageEditor.js.map +1 -1
- package/dist/admin/pages/PagesPanel.js +215 -61
- package/dist/admin/pages/PagesPanel.js.map +1 -1
- package/dist/admin/pages/StarterKiezer.d.ts +12 -0
- package/dist/admin/pages/StarterKiezer.js +113 -0
- package/dist/admin/pages/StarterKiezer.js.map +1 -0
- package/dist/admin/panelRegistry.d.ts +1 -1
- package/dist/admin/panelRegistry.js +2 -1
- package/dist/admin/panelRegistry.js.map +1 -1
- package/dist/admin/patterns/PatternInserter.js +1 -1
- package/dist/admin/patterns/PatternInserter.js.map +1 -1
- package/dist/admin/settings/BedrijfInstellingen.d.ts +20 -0
- package/dist/admin/settings/BedrijfInstellingen.js +144 -0
- package/dist/admin/settings/BedrijfInstellingen.js.map +1 -0
- package/dist/admin/settings/MailSettings.js +2 -2
- package/dist/admin/settings/MailSettings.js.map +1 -1
- package/dist/admin/settings/MailTemplates.js +5 -4
- package/dist/admin/settings/MailTemplates.js.map +1 -1
- package/dist/admin/settings/SettingsPanel.js +120 -78
- package/dist/admin/settings/SettingsPanel.js.map +1 -1
- package/dist/admin/settings/SnapshotsCard.js +4 -4
- package/dist/admin/settings/SnapshotsCard.js.map +1 -1
- package/dist/admin/settings/VorigeTerugzetten.d.ts +15 -0
- package/dist/admin/settings/VorigeTerugzetten.js +89 -0
- package/dist/admin/settings/VorigeTerugzetten.js.map +1 -0
- package/dist/admin/shop/CategoriesTab.js +6 -4
- package/dist/admin/shop/CategoriesTab.js.map +1 -1
- package/dist/admin/shop/DiscountsTab.js +4 -2
- package/dist/admin/shop/DiscountsTab.js.map +1 -1
- package/dist/admin/shop/OrdersTab.js +57 -19
- package/dist/admin/shop/OrdersTab.js.map +1 -1
- package/dist/admin/shop/ProductPaneel.js +2 -1
- package/dist/admin/shop/ProductPaneel.js.map +1 -1
- package/dist/admin/shop/ProductsTab.js +40 -19
- package/dist/admin/shop/ProductsTab.js.map +1 -1
- package/dist/admin/shop/ShopPanel.js +13 -1
- package/dist/admin/shop/ShopPanel.js.map +1 -1
- package/dist/admin/shop/ShopSettingsTab.js +27 -1
- package/dist/admin/shop/ShopSettingsTab.js.map +1 -1
- package/dist/admin/shop/productClient.js +7 -3
- package/dist/admin/shop/productClient.js.map +1 -1
- package/dist/admin/stats/NietGevonden.d.ts +10 -0
- package/dist/admin/stats/NietGevonden.js +78 -0
- package/dist/admin/stats/NietGevonden.js.map +1 -0
- package/dist/admin/stats/StatsPanel.js +6 -1
- package/dist/admin/stats/StatsPanel.js.map +1 -1
- package/dist/admin/stats/lib.d.ts +2 -0
- package/dist/admin/stats/lib.js.map +1 -1
- package/dist/admin/ui/ConfirmDialog.js +10 -1
- package/dist/admin/ui/ConfirmDialog.js.map +1 -1
- package/dist/admin/ui/Icon.d.ts +34 -0
- package/dist/admin/ui/Icon.js +44 -0
- package/dist/admin/ui/Icon.js.map +1 -0
- package/dist/admin/ui/ImageField.d.ts +15 -0
- package/dist/admin/ui/ImageField.js +67 -0
- package/dist/admin/ui/ImageField.js.map +1 -0
- package/dist/admin/ui/KleurVeld.d.ts +25 -0
- package/dist/admin/ui/KleurVeld.js +76 -0
- package/dist/admin/ui/KleurVeld.js.map +1 -0
- package/dist/admin/ui/LaadStaat.d.ts +21 -0
- package/dist/admin/ui/LaadStaat.js +43 -0
- package/dist/admin/ui/LaadStaat.js.map +1 -0
- package/dist/admin/ui/LeesbaarheidPaneel.d.ts +10 -0
- package/dist/admin/ui/LeesbaarheidPaneel.js +68 -0
- package/dist/admin/ui/LeesbaarheidPaneel.js.map +1 -0
- package/dist/admin/ui/LinkDialog.d.ts +22 -0
- package/dist/admin/ui/LinkDialog.js +131 -0
- package/dist/admin/ui/LinkDialog.js.map +1 -0
- package/dist/admin/ui/LinkVeld.d.ts +14 -0
- package/dist/admin/ui/LinkVeld.js +49 -0
- package/dist/admin/ui/LinkVeld.js.map +1 -0
- package/dist/admin/ui/PreviewLinkResultaat.d.ts +14 -0
- package/dist/admin/ui/PreviewLinkResultaat.js +52 -0
- package/dist/admin/ui/PreviewLinkResultaat.js.map +1 -0
- package/dist/admin/ui/charts.js +5 -5
- package/dist/admin/ui/charts.js.map +1 -1
- package/dist/admin/ui/primitives.d.ts +16 -6
- package/dist/admin/ui/primitives.js +98 -26
- package/dist/admin/ui/primitives.js.map +1 -1
- package/dist/admin/ui/select.js +5 -2
- package/dist/admin/ui/select.js.map +1 -1
- package/dist/admin/ui/switch.d.ts +3 -1
- package/dist/admin/ui/switch.js +6 -3
- package/dist/admin/ui/switch.js.map +1 -1
- package/dist/admin/ui/toast.d.ts +2 -1
- package/dist/admin/ui/toast.js +17 -11
- package/dist/admin/ui/toast.js.map +1 -1
- package/dist/admin/visual/BlokKiezer.d.ts +34 -0
- package/dist/admin/visual/BlokKiezer.js +225 -0
- package/dist/admin/visual/BlokKiezer.js.map +1 -0
- package/dist/admin/visual/InlineGereedschap.d.ts +52 -0
- package/dist/admin/visual/InlineGereedschap.js +356 -0
- package/dist/admin/visual/InlineGereedschap.js.map +1 -0
- package/dist/admin/visual/InlineRijkeTekst.d.ts +23 -0
- package/dist/admin/visual/InlineRijkeTekst.js +152 -0
- package/dist/admin/visual/InlineRijkeTekst.js.map +1 -0
- package/dist/admin/visual/VisualEditor.js +273 -125
- package/dist/admin/visual/VisualEditor.js.map +1 -1
- package/dist/admin.css +1 -1
- package/dist/bedrijf/bedrijf.d.ts +36 -0
- package/dist/bedrijf/bedrijf.js +110 -0
- package/dist/bedrijf/bedrijf.js.map +1 -0
- package/dist/blocks/BlockRenderer.js +11 -1
- package/dist/blocks/BlockRenderer.js.map +1 -1
- package/dist/blocks/blockStyle.d.ts +7 -0
- package/dist/blocks/blockStyle.js +16 -3
- package/dist/blocks/blockStyle.js.map +1 -1
- package/dist/blocks/builtinSchemas.js +6 -0
- package/dist/blocks/builtinSchemas.js.map +1 -1
- package/dist/blocks/builtins/AgendaRender.d.ts +22 -0
- package/dist/blocks/builtins/AgendaRender.js +69 -9
- package/dist/blocks/builtins/AgendaRender.js.map +1 -1
- package/dist/blocks/builtins/Availability.d.ts +1 -0
- package/dist/blocks/builtins/Availability.js +23 -0
- package/dist/blocks/builtins/Availability.js.map +1 -0
- package/dist/blocks/builtins/AvailabilityRender.d.ts +12 -0
- package/dist/blocks/builtins/AvailabilityRender.js +105 -0
- package/dist/blocks/builtins/AvailabilityRender.js.map +1 -0
- package/dist/blocks/builtins/BeforeAfterRender.js +4 -3
- package/dist/blocks/builtins/BeforeAfterRender.js.map +1 -1
- package/dist/blocks/builtins/Booking.js +1 -1
- package/dist/blocks/builtins/Booking.js.map +1 -1
- package/dist/blocks/builtins/BreadcrumbsRender.d.ts +4 -3
- package/dist/blocks/builtins/BreadcrumbsRender.js +14 -8
- package/dist/blocks/builtins/BreadcrumbsRender.js.map +1 -1
- package/dist/blocks/builtins/ColumnsRender.d.ts +1 -1
- package/dist/blocks/builtins/ColumnsRender.js +3 -1
- package/dist/blocks/builtins/ColumnsRender.js.map +1 -1
- package/dist/blocks/builtins/Contact.js +1 -1
- package/dist/blocks/builtins/Contact.js.map +1 -1
- package/dist/blocks/builtins/ContactRender.d.ts +1 -1
- package/dist/blocks/builtins/ContactRender.js +29 -8
- package/dist/blocks/builtins/ContactRender.js.map +1 -1
- package/dist/blocks/builtins/Cta.js +1 -1
- package/dist/blocks/builtins/Cta.js.map +1 -1
- package/dist/blocks/builtins/CtaRender.d.ts +1 -1
- package/dist/blocks/builtins/CtaRender.js +5 -4
- package/dist/blocks/builtins/CtaRender.js.map +1 -1
- package/dist/blocks/builtins/Embed.js +1 -1
- package/dist/blocks/builtins/Embed.js.map +1 -1
- package/dist/blocks/builtins/FormBlock.js +1 -0
- package/dist/blocks/builtins/FormBlock.js.map +1 -1
- package/dist/blocks/builtins/FormBlockRender.d.ts +6 -0
- package/dist/blocks/builtins/FormBlockRender.js +88 -16
- package/dist/blocks/builtins/FormBlockRender.js.map +1 -1
- package/dist/blocks/builtins/GalleryRender.js +3 -2
- package/dist/blocks/builtins/GalleryRender.js.map +1 -1
- package/dist/blocks/builtins/Hero.js +1 -1
- package/dist/blocks/builtins/Hero.js.map +1 -1
- package/dist/blocks/builtins/HeroRender.js +7 -3
- package/dist/blocks/builtins/HeroRender.js.map +1 -1
- package/dist/blocks/builtins/OpenNowBadge.d.ts +4 -2
- package/dist/blocks/builtins/OpenNowBadge.js +6 -6
- package/dist/blocks/builtins/OpenNowBadge.js.map +1 -1
- package/dist/blocks/builtins/OpeningHoursRender.d.ts +8 -2
- package/dist/blocks/builtins/OpeningHoursRender.js +27 -6
- package/dist/blocks/builtins/OpeningHoursRender.js.map +1 -1
- package/dist/blocks/builtins/PriceList.d.ts +1 -0
- package/dist/blocks/builtins/PriceList.js +25 -0
- package/dist/blocks/builtins/PriceList.js.map +1 -0
- package/dist/blocks/builtins/PriceListRender.d.ts +17 -0
- package/dist/blocks/builtins/PriceListRender.js +87 -0
- package/dist/blocks/builtins/PriceListRender.js.map +1 -0
- package/dist/blocks/builtins/RichTextBlockRender.js +6 -1
- package/dist/blocks/builtins/RichTextBlockRender.js.map +1 -1
- package/dist/blocks/builtins/SectionHeading.d.ts +1 -0
- package/dist/blocks/builtins/SectionHeading.js +14 -0
- package/dist/blocks/builtins/SectionHeading.js.map +1 -0
- package/dist/blocks/builtins/SectionHeadingRender.d.ts +7 -0
- package/dist/blocks/builtins/SectionHeadingRender.js +14 -0
- package/dist/blocks/builtins/SectionHeadingRender.js.map +1 -0
- package/dist/blocks/builtins/SliderRender.js +3 -2
- package/dist/blocks/builtins/SliderRender.js.map +1 -1
- package/dist/blocks/builtins/SymbolRef.js +1 -1
- package/dist/blocks/builtins/SymbolRef.js.map +1 -1
- package/dist/blocks/builtins/TeamRender.js +6 -1
- package/dist/blocks/builtins/TeamRender.js.map +1 -1
- package/dist/blocks/builtins/Testimonials.js +3 -1
- package/dist/blocks/builtins/Testimonials.js.map +1 -1
- package/dist/blocks/builtins/TestimonialsRender.js +4 -0
- package/dist/blocks/builtins/TestimonialsRender.js.map +1 -1
- package/dist/blocks/builtins/WhatsappChatRender.d.ts +1 -1
- package/dist/blocks/builtins/WhatsappChatRender.js +1 -1
- package/dist/blocks/builtins/WhatsappChatRender.js.map +1 -1
- package/dist/blocks/builtins/Widgets.js +2 -2
- package/dist/blocks/builtins/Widgets.js.map +1 -1
- package/dist/blocks/builtins/WidgetsRender.js +3 -1
- package/dist/blocks/builtins/WidgetsRender.js.map +1 -1
- package/dist/blocks/builtins/index.d.ts +3 -0
- package/dist/blocks/builtins/index.js +6 -0
- package/dist/blocks/builtins/index.js.map +1 -1
- package/dist/blocks/builtins/lib/autoComplete.d.ts +7 -0
- package/dist/blocks/builtins/lib/autoComplete.js +20 -0
- package/dist/blocks/builtins/lib/autoComplete.js.map +1 -0
- package/dist/blocks/builtins/lib/bookingUrl.d.ts +2 -2
- package/dist/blocks/builtins/lib/bookingUrl.js +1 -1
- package/dist/blocks/builtins/lib/bookingUrl.js.map +1 -1
- package/dist/blocks/builtins/lib/ical.d.ts +24 -0
- package/dist/blocks/builtins/lib/ical.js +82 -0
- package/dist/blocks/builtins/lib/ical.js.map +1 -0
- package/dist/blocks/builtins/lib/vandaag.d.ts +8 -0
- package/dist/blocks/builtins/lib/vandaag.js +22 -0
- package/dist/blocks/builtins/lib/vandaag.js.map +1 -0
- package/dist/blocks/registry.d.ts +6 -0
- package/dist/blocks/registry.js.map +1 -1
- package/dist/blocks/ui/index.js +1 -0
- package/dist/blocks/ui/index.js.map +1 -1
- package/dist/components/EditBar.js +2 -4
- package/dist/components/EditBar.js.map +1 -1
- package/dist/components/News.js +26 -18
- package/dist/components/News.js.map +1 -1
- package/dist/components/PageView.d.ts +7 -1
- package/dist/components/PageView.js +17 -0
- package/dist/components/PageView.js.map +1 -1
- package/dist/components/ResponsiveImage.js +18 -20
- package/dist/components/ResponsiveImage.js.map +1 -1
- package/dist/components/site/SiteFooter.d.ts +6 -1
- package/dist/components/site/SiteFooter.js +61 -9
- package/dist/components/site/SiteFooter.js.map +1 -1
- package/dist/components/site/SiteHeader.d.ts +15 -0
- package/dist/components/site/SiteHeader.js +70 -0
- package/dist/components/site/SiteHeader.js.map +1 -0
- package/dist/components/site/SiteNav.d.ts +2 -0
- package/dist/components/site/SiteNav.js +29 -5
- package/dist/components/site/SiteNav.js.map +1 -1
- package/dist/demo/DemoStudio.js +2 -2
- package/dist/demo/DemoStudio.js.map +1 -1
- package/dist/demo/demoStore.d.ts +13 -0
- package/dist/demo/demoStore.js +36 -0
- package/dist/demo/demoStore.js.map +1 -1
- package/dist/editor/EditorProvider.js +15 -4
- package/dist/editor/EditorProvider.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/media/ImageContext.d.ts +17 -0
- package/dist/media/ImageContext.js +65 -20
- package/dist/media/ImageContext.js.map +1 -1
- package/dist/media/altInHtml.d.ts +9 -0
- package/dist/media/altInHtml.js +17 -0
- package/dist/media/altInHtml.js.map +1 -0
- package/dist/media/srcset.d.ts +12 -0
- package/dist/media/srcset.js +13 -0
- package/dist/media/srcset.js.map +1 -0
- package/dist/modules/builtins.d.ts +1 -0
- package/dist/modules/builtins.js +16 -3
- package/dist/modules/builtins.js.map +1 -1
- package/dist/modules/shop/blocks/Cart.js +5 -3
- package/dist/modules/shop/blocks/Cart.js.map +1 -1
- package/dist/modules/shop/blocks/Checkout.js +56 -35
- package/dist/modules/shop/blocks/Checkout.js.map +1 -1
- package/dist/modules/shop/blocks/Donation.js +4 -4
- package/dist/modules/shop/blocks/Donation.js.map +1 -1
- package/dist/modules/shop/blocks/ProductDetail.js +19 -3
- package/dist/modules/shop/blocks/ProductDetail.js.map +1 -1
- package/dist/modules/shop/blocks/ProductGrid.d.ts +3 -1
- package/dist/modules/shop/blocks/ProductGrid.js +8 -4
- package/dist/modules/shop/blocks/ProductGrid.js.map +1 -1
- package/dist/modules/shop/blocks/ShopCategories.js +4 -3
- package/dist/modules/shop/blocks/ShopCategories.js.map +1 -1
- package/dist/modules/shop/lib.d.ts +4 -0
- package/dist/modules/shop/lib.js +14 -0
- package/dist/modules/shop/lib.js.map +1 -1
- package/dist/modules/shop/settings.d.ts +3 -0
- package/dist/modules/shop/settings.js +14 -0
- package/dist/modules/shop/settings.js.map +1 -1
- package/dist/modules/shop/strings.d.ts +4 -0
- package/dist/modules/shop/strings.js +8 -0
- package/dist/modules/shop/strings.js.map +1 -1
- package/dist/next/envCheck.d.ts +42 -0
- package/dist/next/envCheck.js +106 -0
- package/dist/next/envCheck.js.map +1 -0
- package/dist/next/index.cjs +185 -2
- package/dist/next/index.d.ts +2 -0
- package/dist/next/index.js +8 -1
- package/dist/next/index.js.map +1 -1
- package/dist/next/securityHeaders.d.ts +36 -0
- package/dist/next/securityHeaders.js +74 -0
- package/dist/next/securityHeaders.js.map +1 -0
- package/dist/patterns/builtins.d.ts +7 -0
- package/dist/patterns/builtins.js +138 -3
- package/dist/patterns/builtins.js.map +1 -1
- package/dist/releaseNotes.js +140 -0
- package/dist/releaseNotes.js.map +1 -1
- package/dist/render/PublishedPage.d.ts +2 -1
- package/dist/render/PublishedPage.js +10 -4
- package/dist/render/PublishedPage.js.map +1 -1
- package/dist/schema/blocks.d.ts +470 -0
- package/dist/schema/blocks.js +102 -4
- package/dist/schema/blocks.js.map +1 -1
- package/dist/schema/business.d.ts +117 -0
- package/dist/schema/business.js +73 -0
- package/dist/schema/business.js.map +1 -0
- package/dist/schema/fields.d.ts +2 -1
- package/dist/schema/fields.js.map +1 -1
- package/dist/schema/forms.d.ts +18 -0
- package/dist/schema/forms.js +18 -3
- package/dist/schema/forms.js.map +1 -1
- package/dist/schema/mail.d.ts +10 -0
- package/dist/schema/mail.js +7 -0
- package/dist/schema/mail.js.map +1 -1
- package/dist/schema/settings.d.ts +101 -0
- package/dist/schema/settings.js +24 -3
- package/dist/schema/settings.js.map +1 -1
- package/dist/schema/shop.d.ts +2 -0
- package/dist/schema/shop.js +4 -0
- package/dist/schema/shop.js.map +1 -1
- package/dist/schema/shopGeld.d.ts +1 -0
- package/dist/schema/shopGeld.js +1 -0
- package/dist/schema/shopGeld.js.map +1 -1
- package/dist/schema/siteConfig.d.ts +68 -1
- package/dist/schema/siteConfig.js +7 -2
- package/dist/schema/siteConfig.js.map +1 -1
- package/dist/server/blockData.d.ts +1 -1
- package/dist/server/blockData.js +74 -18
- package/dist/server/blockData.js.map +1 -1
- package/dist/server/cspRapport.d.ts +20 -0
- package/dist/server/cspRapport.js +56 -0
- package/dist/server/cspRapport.js.map +1 -0
- package/dist/server/fonts.d.ts +3 -0
- package/dist/server/fonts.js +39 -0
- package/dist/server/fonts.js.map +1 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +8 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/sanitize.js +15 -2
- package/dist/server/sanitize.js.map +1 -1
- package/dist/settings/useSiteSettings.js +4 -1
- package/dist/settings/useSiteSettings.js.map +1 -1
- package/dist/starters/starters.d.ts +69 -0
- package/dist/starters/starters.js +171 -0
- package/dist/starters/starters.js.map +1 -0
- package/dist/styles.css +1149 -208
- package/dist/theme/color.d.ts +10 -0
- package/dist/theme/color.js +17 -1
- package/dist/theme/color.js.map +1 -1
- package/dist/theme/fontFallback.d.ts +23 -0
- package/dist/theme/fontFallback.js +58 -0
- package/dist/theme/fontFallback.js.map +1 -0
- package/dist/theme/fonts.d.ts +11 -0
- package/dist/theme/fonts.js +16 -0
- package/dist/theme/fonts.js.map +1 -0
- package/dist/version.js +1 -1
- package/package.json +6 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/blocks/builtins/GalleryRender.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport type { z } from \"zod\";\nimport type { GalleryBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { useModuleSettings } from \"../../modules/context\";\nimport { Grid } from \"../ui\";\nimport { Img } from \"../../media/ImageContext\";\n\ntype Gallery = z.infer<typeof GalleryBlockSchema>;\ntype Item = Gallery[\"items\"][number];\n\n/** Per-site instelbaar via `modules.gallery.config` (door de agent of in /beheer). */\nexport interface GallerySettings {\n columns?: number;\n lightbox?: boolean;\n}\n\n/**\n * Eigen lightbox-overlay: rendert via een portal naar `document.body` (zo raakt geen enkele\n * ancestor-transform — bv. de scroll-reveal — de full-screen positionering). Sluit op klik náást\n * de foto én op Escape; vorige/volgende met teller; herstelt focus zónder de pagina te laten\n * verspringen (`preventScroll`) en zet de body-scroll vast zolang hij open is.\n */\nexport function LightboxOverlay({\n items,\n index,\n onIndex,\n onClose,\n}: {\n items: Item[];\n index: number;\n onIndex: (i: number) => void;\n onClose: () => void;\n}) {\n const it = items[index];\n const total = items.length;\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const prev = useCallback(() => onIndex((index - 1 + total) % total), [index, total, onIndex]);\n const next = useCallback(() => onIndex((index + 1) % total), [index, total, onIndex]);\n // Swipe (pointer events, werkt voor touch én muis-sleep): horizontaal > 40px = vorige/volgende.\n const swipeStart = useRef<number | null>(null);\n const onPointerDown = (e: React.PointerEvent) => {\n swipeStart.current = e.clientX;\n };\n const onPointerUp = (e: React.PointerEvent) => {\n if (swipeStart.current === null || total < 2) return;\n const dx = e.clientX - swipeStart.current;\n swipeStart.current = null;\n if (dx > 40) prev();\n else if (dx < -40) next();\n };\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n else if (e.key === \"ArrowLeft\") prev();\n else if (e.key === \"ArrowRight\") next();\n else if (e.key === \"Tab\") {\n // Focus-trap (aria-modal): Tab cirkelt binnen de dialog i.p.v. naar de pagina eronder.\n const el = overlayRef.current;\n const focusables = el ? [...el.querySelectorAll<HTMLElement>(\"button, a[href]\")] : [];\n if (focusables.length === 0) return;\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const active = document.activeElement;\n if (e.shiftKey && (active === first || !el?.contains(active))) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && (active === last || !el?.contains(active))) {\n e.preventDefault();\n first.focus();\n }\n }\n };\n document.addEventListener(\"keydown\", onKey);\n const prevOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\"; // scroll-lock terwijl open\n // Initiële focus in de dialog (dialog-conventie; toetsenbord/screenreader landt niet \"achter\" de overlay).\n overlayRef.current?.querySelector<HTMLElement>(\".xicms-lightbox__close\")?.focus({ preventScroll: true });\n return () => {\n document.removeEventListener(\"keydown\", onKey);\n document.body.style.overflow = prevOverflow;\n };\n }, [onClose, prev, next]);\n\n if (typeof document === \"undefined\") return null;\n return createPortal(\n <div\n ref={overlayRef}\n className=\"xicms-lightbox\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={it.alt || it.caption || \"Foto\"}\n onClick={onClose}\n >\n <button type=\"button\" className=\"xicms-lightbox__close\" aria-label=\"Sluiten\" onClick={onClose}>✕</button>\n {total > 1 && (\n <>\n <button type=\"button\" className=\"xicms-lightbox__nav xicms-lightbox__nav--prev\" aria-label=\"Vorige\" onClick={(e) => { e.stopPropagation(); prev(); }}>‹</button>\n <button type=\"button\" className=\"xicms-lightbox__nav xicms-lightbox__nav--next\" aria-label=\"Volgende\" onClick={(e) => { e.stopPropagation(); next(); }}>›</button>\n <span className=\"xicms-lightbox__counter\">{index + 1} / {total}</span>\n </>\n )}\n {/* Klik op de foto/onderschrift sluit NIET (stopPropagation); klik op de rand wel.\n touchAction pan-y: verticaal scrollen blijft van de browser, horizontaal is swipen. */}\n <figure\n className=\"xicms-lightbox__figure\"\n onClick={(e) => e.stopPropagation()}\n onPointerDown={onPointerDown}\n onPointerUp={onPointerUp}\n style={{ touchAction: \"pan-y\" }}\n >\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img src={it.url} alt={it.alt ?? \"\"} />\n {it.caption && <figcaption>{it.caption}</figcaption>}\n </figure>\n </div>,\n document.body,\n );\n}\n\n/** Galerij — responsive grid met instelbare beeldverhouding en optionele lightbox. */\nexport function GalleryRender({ block }: BlockRenderProps<Gallery>) {\n const settings = useModuleSettings<GallerySettings>(\"gallery\");\n // `_i` = de index in block.items (vóór url-/tagfilters): het inline-edit-pad\n // (`items.<_i>.caption`) moet naar het ORIGINELE array-item wijzen, niet naar de filterpositie.\n const allItems = (block.items ?? []).map((it, _i) => ({ ...it, _i })).filter((i) => i.url);\n const [open, setOpen] = useState(false);\n const [index, setIndex] = useState(0);\n const [activeTag, setActiveTag] = useState<string | null>(null);\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n\n // Filterbalk op item-tags (opt-in): lightbox-navigatie volgt de gefilterde lijst.\n const tags = block.showFilter ? [...new Set(allItems.map((i) => i.tag).filter((t): t is string => Boolean(t)))] : [];\n const items = activeTag ? allItems.filter((i) => i.tag === activeTag) : allItems;\n\n if (allItems.length === 0) return null;\n\n const cols = block.columns && block.columns > 0 ? block.columns : settings.columns ?? 3;\n const lightbox =\n block.lightbox === \"on\" ? true : block.lightbox === \"off\" ? false : settings.lightbox ?? true;\n const ar = block.aspectRatio ?? \"1/1\";\n\n const imgStyle = {\n width: \"100%\",\n aspectRatio: ar === \"auto\" ? undefined : ar.replace(\"/\", \" / \"),\n objectFit: \"cover\" as const,\n borderRadius: \"var(--radius-element)\",\n display: \"block\",\n };\n\n const close = () => {\n setOpen(false);\n triggerRef.current?.focus({ preventScroll: true }); // geen page-jump bij sluiten\n };\n\n return (\n <div className=\"xicms-gallery\">\n {tags.length > 0 && (\n <div className=\"xicms-gallery__filter\" role=\"group\" aria-label=\"Filter op categorie\">\n <button type=\"button\" className=\"xicms-gallery__filterbtn\" aria-pressed={activeTag === null} data-active={activeTag === null ? \"1\" : \"0\"} onClick={() => { setActiveTag(null); setIndex(0); }}>\n Alles\n </button>\n {tags.map((t) => (\n <button key={t} type=\"button\" className=\"xicms-gallery__filterbtn\" aria-pressed={activeTag === t} data-active={activeTag === t ? \"1\" : \"0\"} onClick={() => { setActiveTag(t); setIndex(0); }}>\n {t}\n </button>\n ))}\n </div>\n )}\n <Grid columns={{ minWidth: 160, max: Math.min(cols, 6) }} gap={2}>\n {items.map((i, idx) => (\n <figure key={idx} style={{ margin: 0 }} className=\"xicms-gallery__item\">\n {lightbox ? (\n <button\n type=\"button\"\n onClick={(e) => { triggerRef.current = e.currentTarget; setIndex(idx); setOpen(true); }}\n aria-label={i.alt || i.caption || `Foto ${idx + 1} vergroten`}\n style={{ display: \"block\", width: \"100%\", padding: 0, border: 0, background: \"none\", cursor: \"zoom-in\" }}\n >\n <Img src={i.url as string} alt={i.alt ?? \"\"} width={600} height={600} sizes=\"(max-width: 640px) 50vw, 280px\" style={imgStyle} />\n </button>\n ) : (\n <Img src={i.url as string} alt={i.alt ?? \"\"} width={600} height={600} sizes=\"(max-width: 640px) 50vw, 280px\" style={imgStyle} />\n )}\n {i.caption && (\n <figcaption className=\"xicms-gallery__caption\" data-xicms-edit={`items.${i._i}.caption`} style={{ marginTop: \"0.4rem\", fontSize: \"0.85rem\", color: \"var(--color-text-secondary)\" }}>\n {i.caption}\n </figcaption>\n )}\n </figure>\n ))}\n </Grid>\n\n {lightbox && open && (\n <LightboxOverlay items={items} index={index} onIndex={setIndex} onClose={close} />\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/GalleryRender.tsx"],"sourcesContent":["\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport type { z } from \"zod\";\nimport type { GalleryBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { useModuleSettings } from \"../../modules/context\";\nimport { Grid } from \"../ui\";\nimport { Img, useGrootsteVariant } from \"../../media/ImageContext\";\n\ntype Gallery = z.infer<typeof GalleryBlockSchema>;\ntype Item = Gallery[\"items\"][number];\n\n/** Per-site instelbaar via `modules.gallery.config` (door de agent of in /beheer). */\nexport interface GallerySettings {\n columns?: number;\n lightbox?: boolean;\n}\n\n/**\n * Eigen lightbox-overlay: rendert via een portal naar `document.body` (zo raakt geen enkele\n * ancestor-transform — bv. de scroll-reveal — de full-screen positionering). Sluit op klik náást\n * de foto én op Escape; vorige/volgende met teller; herstelt focus zónder de pagina te laten\n * verspringen (`preventScroll`) en zet de body-scroll vast zolang hij open is.\n */\nexport function LightboxOverlay({\n items,\n index,\n onIndex,\n onClose,\n}: {\n items: Item[];\n index: number;\n onIndex: (i: number) => void;\n onClose: () => void;\n}) {\n const it = items[index];\n // 8.3: de grootste gegenereerde versie (volle WebP) i.p.v. het origineel van soms 8 MB.\n const groot = useGrootsteVariant(it?.url ?? \"\");\n const total = items.length;\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const prev = useCallback(() => onIndex((index - 1 + total) % total), [index, total, onIndex]);\n const next = useCallback(() => onIndex((index + 1) % total), [index, total, onIndex]);\n // Swipe (pointer events, werkt voor touch én muis-sleep): horizontaal > 40px = vorige/volgende.\n const swipeStart = useRef<number | null>(null);\n const onPointerDown = (e: React.PointerEvent) => {\n swipeStart.current = e.clientX;\n };\n const onPointerUp = (e: React.PointerEvent) => {\n if (swipeStart.current === null || total < 2) return;\n const dx = e.clientX - swipeStart.current;\n swipeStart.current = null;\n if (dx > 40) prev();\n else if (dx < -40) next();\n };\n\n useEffect(() => {\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n else if (e.key === \"ArrowLeft\") prev();\n else if (e.key === \"ArrowRight\") next();\n else if (e.key === \"Tab\") {\n // Focus-trap (aria-modal): Tab cirkelt binnen de dialog i.p.v. naar de pagina eronder.\n const el = overlayRef.current;\n const focusables = el ? [...el.querySelectorAll<HTMLElement>(\"button, a[href]\")] : [];\n if (focusables.length === 0) return;\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const active = document.activeElement;\n if (e.shiftKey && (active === first || !el?.contains(active))) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && (active === last || !el?.contains(active))) {\n e.preventDefault();\n first.focus();\n }\n }\n };\n document.addEventListener(\"keydown\", onKey);\n const prevOverflow = document.body.style.overflow;\n document.body.style.overflow = \"hidden\"; // scroll-lock terwijl open\n // Initiële focus in de dialog (dialog-conventie; toetsenbord/screenreader landt niet \"achter\" de overlay).\n overlayRef.current?.querySelector<HTMLElement>(\".xicms-lightbox__close\")?.focus({ preventScroll: true });\n return () => {\n document.removeEventListener(\"keydown\", onKey);\n document.body.style.overflow = prevOverflow;\n };\n }, [onClose, prev, next]);\n\n if (typeof document === \"undefined\") return null;\n return createPortal(\n <div\n ref={overlayRef}\n className=\"xicms-lightbox\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={it.alt || it.caption || \"Foto\"}\n onClick={onClose}\n >\n <button type=\"button\" className=\"xicms-lightbox__close\" aria-label=\"Sluiten\" onClick={onClose}>✕</button>\n {total > 1 && (\n <>\n <button type=\"button\" className=\"xicms-lightbox__nav xicms-lightbox__nav--prev\" aria-label=\"Vorige\" onClick={(e) => { e.stopPropagation(); prev(); }}>‹</button>\n <button type=\"button\" className=\"xicms-lightbox__nav xicms-lightbox__nav--next\" aria-label=\"Volgende\" onClick={(e) => { e.stopPropagation(); next(); }}>›</button>\n <span className=\"xicms-lightbox__counter\">{index + 1} / {total}</span>\n </>\n )}\n {/* Klik op de foto/onderschrift sluit NIET (stopPropagation); klik op de rand wel.\n touchAction pan-y: verticaal scrollen blijft van de browser, horizontaal is swipen. */}\n <figure\n className=\"xicms-lightbox__figure\"\n onClick={(e) => e.stopPropagation()}\n onPointerDown={onPointerDown}\n onPointerUp={onPointerUp}\n style={{ touchAction: \"pan-y\" }}\n >\n {/* eslint-disable-next-line @next/next/no-img-element */}\n <img src={groot} alt={it.alt ?? \"\"} />\n {it.caption && <figcaption>{it.caption}</figcaption>}\n </figure>\n </div>,\n document.body,\n );\n}\n\n/** Galerij — responsive grid met instelbare beeldverhouding en optionele lightbox. */\nexport function GalleryRender({ block }: BlockRenderProps<Gallery>) {\n const settings = useModuleSettings<GallerySettings>(\"gallery\");\n // `_i` = de index in block.items (vóór url-/tagfilters): het inline-edit-pad\n // (`items.<_i>.caption`) moet naar het ORIGINELE array-item wijzen, niet naar de filterpositie.\n const allItems = (block.items ?? []).map((it, _i) => ({ ...it, _i })).filter((i) => i.url);\n const [open, setOpen] = useState(false);\n const [index, setIndex] = useState(0);\n const [activeTag, setActiveTag] = useState<string | null>(null);\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n\n // Filterbalk op item-tags (opt-in): lightbox-navigatie volgt de gefilterde lijst.\n const tags = block.showFilter ? [...new Set(allItems.map((i) => i.tag).filter((t): t is string => Boolean(t)))] : [];\n const items = activeTag ? allItems.filter((i) => i.tag === activeTag) : allItems;\n\n if (allItems.length === 0) return null;\n\n const cols = block.columns && block.columns > 0 ? block.columns : settings.columns ?? 3;\n const lightbox =\n block.lightbox === \"on\" ? true : block.lightbox === \"off\" ? false : settings.lightbox ?? true;\n const ar = block.aspectRatio ?? \"1/1\";\n\n const imgStyle = {\n width: \"100%\",\n aspectRatio: ar === \"auto\" ? undefined : ar.replace(\"/\", \" / \"),\n objectFit: \"cover\" as const,\n borderRadius: \"var(--radius-element)\",\n display: \"block\",\n };\n\n const close = () => {\n setOpen(false);\n triggerRef.current?.focus({ preventScroll: true }); // geen page-jump bij sluiten\n };\n\n return (\n <div className=\"xicms-gallery\">\n {tags.length > 0 && (\n <div className=\"xicms-gallery__filter\" role=\"group\" aria-label=\"Filter op categorie\">\n <button type=\"button\" className=\"xicms-gallery__filterbtn\" aria-pressed={activeTag === null} data-active={activeTag === null ? \"1\" : \"0\"} onClick={() => { setActiveTag(null); setIndex(0); }}>\n Alles\n </button>\n {tags.map((t) => (\n <button key={t} type=\"button\" className=\"xicms-gallery__filterbtn\" aria-pressed={activeTag === t} data-active={activeTag === t ? \"1\" : \"0\"} onClick={() => { setActiveTag(t); setIndex(0); }}>\n {t}\n </button>\n ))}\n </div>\n )}\n <Grid columns={{ minWidth: 160, max: Math.min(cols, 6) }} gap={2}>\n {items.map((i, idx) => (\n <figure key={idx} style={{ margin: 0 }} className=\"xicms-gallery__item\">\n {lightbox ? (\n <button\n type=\"button\"\n onClick={(e) => { triggerRef.current = e.currentTarget; setIndex(idx); setOpen(true); }}\n aria-label={i.alt || i.caption || `Foto ${idx + 1} vergroten`}\n style={{ display: \"block\", width: \"100%\", padding: 0, border: 0, background: \"none\", cursor: \"zoom-in\" }}\n >\n <Img src={i.url as string} alt={i.alt ?? \"\"} width={600} height={600} sizes=\"(max-width: 640px) 50vw, 280px\" style={imgStyle} />\n </button>\n ) : (\n <Img src={i.url as string} alt={i.alt ?? \"\"} width={600} height={600} sizes=\"(max-width: 640px) 50vw, 280px\" style={imgStyle} />\n )}\n {i.caption && (\n <figcaption className=\"xicms-gallery__caption\" data-xicms-edit={`items.${i._i}.caption`} style={{ marginTop: \"0.4rem\", fontSize: \"0.85rem\", color: \"var(--color-text-secondary)\" }}>\n {i.caption}\n </figcaption>\n )}\n </figure>\n ))}\n </Grid>\n\n {lightbox && open && (\n <LightboxOverlay items={items} index={index} onIndex={setIndex} onClose={close} />\n )}\n </div>\n );\n}\n"],"mappings":";AAoGM,SAEE,UAFF,KAKI,YALJ;AAlGN,SAAS,aAAa,WAAW,QAAQ,gBAAgB;AACzD,SAAS,oBAAoB;AAI7B,SAAS,yBAAyB;AAClC,SAAS,YAAY;AACrB,SAAS,KAAK,0BAA0B;AAiBjC,SAAS,gBAAgB;AAAA,EAC9B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,QAAM,KAAK,MAAM,KAAK;AAEtB,QAAM,QAAQ,mBAAmB,IAAI,OAAO,EAAE;AAC9C,QAAM,QAAQ,MAAM;AACpB,QAAM,aAAa,OAA8B,IAAI;AACrD,QAAM,OAAO,YAAY,MAAM,SAAS,QAAQ,IAAI,SAAS,KAAK,GAAG,CAAC,OAAO,OAAO,OAAO,CAAC;AAC5F,QAAM,OAAO,YAAY,MAAM,SAAS,QAAQ,KAAK,KAAK,GAAG,CAAC,OAAO,OAAO,OAAO,CAAC;AAEpF,QAAM,aAAa,OAAsB,IAAI;AAC7C,QAAM,gBAAgB,CAAC,MAA0B;AAC/C,eAAW,UAAU,EAAE;AAAA,EACzB;AACA,QAAM,cAAc,CAAC,MAA0B;AAC7C,QAAI,WAAW,YAAY,QAAQ,QAAQ,EAAG;AAC9C,UAAM,KAAK,EAAE,UAAU,WAAW;AAClC,eAAW,UAAU;AACrB,QAAI,KAAK,GAAI,MAAK;AAAA,aACT,KAAK,IAAK,MAAK;AAAA,EAC1B;AAEA,YAAU,MAAM;AACd,UAAM,QAAQ,CAAC,MAAqB;AAClC,UAAI,EAAE,QAAQ,SAAU,SAAQ;AAAA,eACvB,EAAE,QAAQ,YAAa,MAAK;AAAA,eAC5B,EAAE,QAAQ,aAAc,MAAK;AAAA,eAC7B,EAAE,QAAQ,OAAO;AAExB,cAAM,KAAK,WAAW;AACtB,cAAM,aAAa,KAAK,CAAC,GAAG,GAAG,iBAA8B,iBAAiB,CAAC,IAAI,CAAC;AACpF,YAAI,WAAW,WAAW,EAAG;AAC7B,cAAM,QAAQ,WAAW,CAAC;AAC1B,cAAM,OAAO,WAAW,WAAW,SAAS,CAAC;AAC7C,cAAM,SAAS,SAAS;AACxB,YAAI,EAAE,aAAa,WAAW,SAAS,CAAC,IAAI,SAAS,MAAM,IAAI;AAC7D,YAAE,eAAe;AACjB,eAAK,MAAM;AAAA,QACb,WAAW,CAAC,EAAE,aAAa,WAAW,QAAQ,CAAC,IAAI,SAAS,MAAM,IAAI;AACpE,YAAE,eAAe;AACjB,gBAAM,MAAM;AAAA,QACd;AAAA,MACF;AAAA,IACF;AACA,aAAS,iBAAiB,WAAW,KAAK;AAC1C,UAAM,eAAe,SAAS,KAAK,MAAM;AACzC,aAAS,KAAK,MAAM,WAAW;AAE/B,eAAW,SAAS,cAA2B,wBAAwB,GAAG,MAAM,EAAE,eAAe,KAAK,CAAC;AACvG,WAAO,MAAM;AACX,eAAS,oBAAoB,WAAW,KAAK;AAC7C,eAAS,KAAK,MAAM,WAAW;AAAA,IACjC;AAAA,EACF,GAAG,CAAC,SAAS,MAAM,IAAI,CAAC;AAExB,MAAI,OAAO,aAAa,YAAa,QAAO;AAC5C,SAAO;AAAA,IACL;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,WAAU;AAAA,QACV,MAAK;AAAA,QACL,cAAW;AAAA,QACX,cAAY,GAAG,OAAO,GAAG,WAAW;AAAA,QACpC,SAAS;AAAA,QAET;AAAA,8BAAC,YAAO,MAAK,UAAS,WAAU,yBAAwB,cAAW,WAAU,SAAS,SAAS,oBAAC;AAAA,UAC/F,QAAQ,KACP,iCACE;AAAA,gCAAC,YAAO,MAAK,UAAS,WAAU,iDAAgD,cAAW,UAAS,SAAS,CAAC,MAAM;AAAE,gBAAE,gBAAgB;AAAG,mBAAK;AAAA,YAAG,GAAG,oBAAC;AAAA,YACvJ,oBAAC,YAAO,MAAK,UAAS,WAAU,iDAAgD,cAAW,YAAW,SAAS,CAAC,MAAM;AAAE,gBAAE,gBAAgB;AAAG,mBAAK;AAAA,YAAG,GAAG,oBAAC;AAAA,YACzJ,qBAAC,UAAK,WAAU,2BAA2B;AAAA,sBAAQ;AAAA,cAAE;AAAA,cAAI;AAAA,eAAM;AAAA,aACjE;AAAA,UAIF;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,SAAS,CAAC,MAAM,EAAE,gBAAgB;AAAA,cAClC;AAAA,cACA;AAAA,cACA,OAAO,EAAE,aAAa,QAAQ;AAAA,cAG9B;AAAA,oCAAC,SAAI,KAAK,OAAO,KAAK,GAAG,OAAO,IAAI;AAAA,gBACnC,GAAG,WAAW,oBAAC,gBAAY,aAAG,SAAQ;AAAA;AAAA;AAAA,UACzC;AAAA;AAAA;AAAA,IACF;AAAA,IACA,SAAS;AAAA,EACX;AACF;AAGO,SAAS,cAAc,EAAE,MAAM,GAA8B;AAClE,QAAM,WAAW,kBAAmC,SAAS;AAG7D,QAAM,YAAY,MAAM,SAAS,CAAC,GAAG,IAAI,CAAC,IAAI,QAAQ,EAAE,GAAG,IAAI,GAAG,EAAE,EAAE,OAAO,CAAC,MAAM,EAAE,GAAG;AACzF,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,CAAC;AACpC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAwB,IAAI;AAC9D,QAAM,aAAa,OAAiC,IAAI;AAGxD,QAAM,OAAO,MAAM,aAAa,CAAC,GAAG,IAAI,IAAI,SAAS,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,OAAO,CAAC,MAAmB,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACnH,QAAM,QAAQ,YAAY,SAAS,OAAO,CAAC,MAAM,EAAE,QAAQ,SAAS,IAAI;AAExE,MAAI,SAAS,WAAW,EAAG,QAAO;AAElC,QAAM,OAAO,MAAM,WAAW,MAAM,UAAU,IAAI,MAAM,UAAU,SAAS,WAAW;AACtF,QAAM,WACJ,MAAM,aAAa,OAAO,OAAO,MAAM,aAAa,QAAQ,QAAQ,SAAS,YAAY;AAC3F,QAAM,KAAK,MAAM,eAAe;AAEhC,QAAM,WAAW;AAAA,IACf,OAAO;AAAA,IACP,aAAa,OAAO,SAAS,SAAY,GAAG,QAAQ,KAAK,KAAK;AAAA,IAC9D,WAAW;AAAA,IACX,cAAc;AAAA,IACd,SAAS;AAAA,EACX;AAEA,QAAM,QAAQ,MAAM;AAClB,YAAQ,KAAK;AACb,eAAW,SAAS,MAAM,EAAE,eAAe,KAAK,CAAC;AAAA,EACnD;AAEA,SACE,qBAAC,SAAI,WAAU,iBACZ;AAAA,SAAK,SAAS,KACb,qBAAC,SAAI,WAAU,yBAAwB,MAAK,SAAQ,cAAW,uBAC7D;AAAA,0BAAC,YAAO,MAAK,UAAS,WAAU,4BAA2B,gBAAc,cAAc,MAAM,eAAa,cAAc,OAAO,MAAM,KAAK,SAAS,MAAM;AAAE,qBAAa,IAAI;AAAG,iBAAS,CAAC;AAAA,MAAG,GAAG,mBAE/L;AAAA,MACC,KAAK,IAAI,CAAC,MACT,oBAAC,YAAe,MAAK,UAAS,WAAU,4BAA2B,gBAAc,cAAc,GAAG,eAAa,cAAc,IAAI,MAAM,KAAK,SAAS,MAAM;AAAE,qBAAa,CAAC;AAAG,iBAAS,CAAC;AAAA,MAAG,GACxL,eADU,CAEb,CACD;AAAA,OACH;AAAA,IAEF,oBAAC,QAAK,SAAS,EAAE,UAAU,KAAK,KAAK,KAAK,IAAI,MAAM,CAAC,EAAE,GAAG,KAAK,GAC5D,gBAAM,IAAI,CAAC,GAAG,QACb,qBAAC,YAAiB,OAAO,EAAE,QAAQ,EAAE,GAAG,WAAU,uBAC/C;AAAA,iBACC;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,CAAC,MAAM;AAAE,uBAAW,UAAU,EAAE;AAAe,qBAAS,GAAG;AAAG,oBAAQ,IAAI;AAAA,UAAG;AAAA,UACtF,cAAY,EAAE,OAAO,EAAE,WAAW,QAAQ,MAAM,CAAC;AAAA,UACjD,OAAO,EAAE,SAAS,SAAS,OAAO,QAAQ,SAAS,GAAG,QAAQ,GAAG,YAAY,QAAQ,QAAQ,UAAU;AAAA,UAEvG,8BAAC,OAAI,KAAK,EAAE,KAAe,KAAK,EAAE,OAAO,IAAI,OAAO,KAAK,QAAQ,KAAK,OAAM,kCAAiC,OAAO,UAAU;AAAA;AAAA,MAChI,IAEA,oBAAC,OAAI,KAAK,EAAE,KAAe,KAAK,EAAE,OAAO,IAAI,OAAO,KAAK,QAAQ,KAAK,OAAM,kCAAiC,OAAO,UAAU;AAAA,MAE/H,EAAE,WACD,oBAAC,gBAAW,WAAU,0BAAyB,mBAAiB,SAAS,EAAE,EAAE,YAAY,OAAO,EAAE,WAAW,UAAU,UAAU,WAAW,OAAO,8BAA8B,GAC9K,YAAE,SACL;AAAA,SAhBS,GAkBb,CACD,GACH;AAAA,IAEC,YAAY,QACX,oBAAC,mBAAgB,OAAc,OAAc,SAAS,UAAU,SAAS,OAAO;AAAA,KAEpF;AAEJ;","names":[]}
|
|
@@ -3,7 +3,7 @@ import { defineBlock } from "../registry.js";
|
|
|
3
3
|
const heroBlock = defineBlock({
|
|
4
4
|
type: "hero",
|
|
5
5
|
Render: dynamic(() => import("./HeroRender.js").then((m) => m.HeroRender)),
|
|
6
|
-
label: "
|
|
6
|
+
label: "Openingsbeeld",
|
|
7
7
|
icon: "\u2728",
|
|
8
8
|
defaults: () => ({ title: "Welkom", subtitle: "", align: "left", vAlign: "center", minHeight: "auto", overlayOpacity: 0, buttons: [] })
|
|
9
9
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/blocks/builtins/Hero.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const heroBlock = defineBlock({\n type: \"hero\",\n Render: dynamic(() => import(\"./HeroRender\").then((m) => m.HeroRender)),\n label: \"
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/Hero.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const heroBlock = defineBlock({\n type: \"hero\",\n Render: dynamic(() => import(\"./HeroRender\").then((m) => m.HeroRender)),\n label: \"Openingsbeeld\",\n icon: \"✨\",\n defaults: () => ({ title: \"Welkom\", subtitle: \"\", align: \"left\", vAlign: \"center\", minHeight: \"auto\", overlayOpacity: 0, buttons: [] }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,YAAY,YAAY;AAAA,EACnC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,cAAc,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,CAAC;AAAA,EACtE,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,OAAO,UAAU,UAAU,IAAI,OAAO,QAAQ,QAAQ,UAAU,WAAW,QAAQ,gBAAgB,GAAG,SAAS,CAAC,EAAE;AACvI,CAAC;","names":[]}
|
|
@@ -22,7 +22,8 @@ function HeroRender({ block }) {
|
|
|
22
22
|
}
|
|
23
23
|
};
|
|
24
24
|
const overlay = block.overlayOpacity > 0 ? { background: block.overlayColor ?? "#000000", opacity: block.overlayOpacity / 100 } : null;
|
|
25
|
-
const
|
|
25
|
+
const naast = block.layout === "naast" && Boolean(block.imageUrl) && !block.videoUrl;
|
|
26
|
+
const coverMedia = !naast && Boolean(block.videoUrl || block.imageUrl) && block.minHeight !== "auto";
|
|
26
27
|
const light = coverMedia ? { color: "#ffffff", textShadow: "0 2px 14px rgba(0,0,0,.45)" } : void 0;
|
|
27
28
|
const buttons = block.buttons ?? [];
|
|
28
29
|
return /* @__PURE__ */ jsxs(
|
|
@@ -33,6 +34,7 @@ function HeroRender({ block }) {
|
|
|
33
34
|
"data-valign": block.vAlign,
|
|
34
35
|
"data-height": block.minHeight,
|
|
35
36
|
"data-media": coverMedia ? "cover" : void 0,
|
|
37
|
+
"data-layout": naast ? "naast" : void 0,
|
|
36
38
|
children: [
|
|
37
39
|
block.videoUrl ? /* @__PURE__ */ jsx(
|
|
38
40
|
"video",
|
|
@@ -47,15 +49,17 @@ function HeroRender({ block }) {
|
|
|
47
49
|
preload: "metadata",
|
|
48
50
|
"aria-hidden": "true"
|
|
49
51
|
}
|
|
50
|
-
) : block.imageUrl ? /* @__PURE__ */ jsx(Img, { src: block.imageUrl, alt: "", className: "xicms-hero__media", width: 1600, height: 900, sizes: "100vw", priority: true, editField: "imageUrl", editFill: true }) : null,
|
|
52
|
+
) : block.imageUrl && !naast ? /* @__PURE__ */ jsx(Img, { src: block.imageUrl, alt: "", className: "xicms-hero__media", width: 1600, height: 900, sizes: "100vw", priority: true, editField: "imageUrl", editFill: true }) : null,
|
|
51
53
|
overlay && /* @__PURE__ */ jsx("div", { className: "xicms-hero__overlay", style: overlay, "aria-hidden": "true" }),
|
|
52
54
|
block.overlayGradient && coverMedia && /* @__PURE__ */ jsx("div", { className: "xicms-hero__gradient", "aria-hidden": "true" }),
|
|
53
55
|
/* @__PURE__ */ jsxs("div", { className: "xicms-hero__inner", children: [
|
|
54
56
|
block.eyebrow && /* @__PURE__ */ jsx(Text, { type: "label", className: "xicms-hero__eyebrow", style: light, "data-xicms-edit": "eyebrow", children: block.eyebrow }),
|
|
55
57
|
block.title && /* @__PURE__ */ jsx(Heading, { level: block.headingLevel === "2" ? 2 : 1, type: "display-1", className: "xicms-hero__title", style: light, "data-xicms-edit": "title", children: block.title }),
|
|
56
58
|
block.subtitle && /* @__PURE__ */ jsx(Text, { type: "large", className: "xicms-hero__sub", style: light, "data-xicms-edit": "subtitle", children: block.subtitle }),
|
|
57
|
-
buttons.length > 0 && /* @__PURE__ */ jsx("div", { className: "xicms-hero__buttons", children: buttons.map((b, i) => ({ ...b, _i: i })).filter((b) => b.label).map((b) => /* @__PURE__ */ jsx(Btn, { label: b.label, href: b.href, variant: b.variant, size: "lg", editField: `buttons.${b._i}.label` }, b._i)) })
|
|
59
|
+
buttons.length > 0 && /* @__PURE__ */ jsx("div", { className: "xicms-hero__buttons", children: buttons.map((b, i) => ({ ...b, _i: i })).filter((b) => b.label).map((b) => /* @__PURE__ */ jsx(Btn, { label: b.label, href: b.href, variant: b.variant, size: "lg", editField: `buttons.${b._i}.label` }, b._i)) }),
|
|
60
|
+
(block.trust ?? []).some((t) => t.trim()) && /* @__PURE__ */ jsx("ul", { className: "xicms-hero__trust", style: light, children: (block.trust ?? []).map((t, i) => t.trim() ? /* @__PURE__ */ jsx("li", { "data-xicms-edit": `trust.${i}`, children: t }, i) : null) })
|
|
58
61
|
] }),
|
|
62
|
+
naast && block.imageUrl && /* @__PURE__ */ jsx("div", { className: "xicms-hero__beeld", children: /* @__PURE__ */ jsx(Img, { src: block.imageUrl, alt: "", width: 1200, height: 1e3, sizes: "(max-width: 900px) 100vw, 50vw", priority: true, editField: "imageUrl", editFill: true }) }),
|
|
59
63
|
block.videoUrl && /* @__PURE__ */ jsx(
|
|
60
64
|
"button",
|
|
61
65
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/blocks/builtins/HeroRender.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState, type CSSProperties } from \"react\";\nimport type { z } from \"zod\";\nimport type { HeroBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { Btn, Heading, Text } from \"../ui\";\nimport { Img } from \"../../media/ImageContext\";\n\ntype Hero = z.infer<typeof HeroBlockSchema>;\n\nexport function HeroRender({ block }: BlockRenderProps<Hero>) {\n // Achtergrondvideo WCAG-proof (2.2.2): geen autoPlay-attribuut (hydration-veilig) — playback\n // start in een effect, en alléén zonder reduced-motion-voorkeur. Altijd een pauzeknop, en\n // imageUrl dient als poster (direct beeld i.p.v. zwart vlak → betere LCP).\n const videoRef = useRef<HTMLVideoElement>(null);\n const [playing, setPlaying] = useState(false);\n useEffect(() => {\n const v = videoRef.current;\n if (!v) return;\n if (window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches) return;\n v.play().then(() => setPlaying(true)).catch(() => undefined);\n }, [block.videoUrl]);\n const toggleVideo = () => {\n const v = videoRef.current;\n if (!v) return;\n if (v.paused) v.play().then(() => setPlaying(true)).catch(() => undefined);\n else {\n v.pause();\n setPlaying(false);\n }\n };\n const overlay =\n block.overlayOpacity > 0\n ? { background: block.overlayColor ?? \"#000000\", opacity: block.overlayOpacity / 100 }\n : null;\n // Beeld/video als dekkende achtergrond (niet bij height \"auto\"): dan moet de tekst licht zijn.\n const coverMedia = Boolean(block.videoUrl || block.imageUrl) && block.minHeight !== \"auto\";\n const light: CSSProperties | undefined = coverMedia\n ? { color: \"#ffffff\", textShadow: \"0 2px 14px rgba(0,0,0,.45)\" }\n : undefined;\n const buttons = block.buttons ?? [];\n\n return (\n <section\n className=\"xicms-hero\"\n data-align={block.align}\n data-valign={block.vAlign}\n data-height={block.minHeight}\n data-media={coverMedia ? \"cover\" : undefined}\n >\n {block.videoUrl ? (\n <video\n ref={videoRef}\n className=\"xicms-hero__media\"\n src={block.videoUrl}\n poster={block.imageUrl || undefined}\n muted\n loop\n playsInline\n preload=\"metadata\"\n aria-hidden=\"true\"\n />\n ) : block.imageUrl ? (\n <Img src={block.imageUrl} alt=\"\" className=\"xicms-hero__media\" width={1600} height={900} sizes=\"100vw\" priority editField=\"imageUrl\" editFill />\n ) : null}\n {overlay && <div className=\"xicms-hero__overlay\" style={overlay} aria-hidden=\"true\" />}\n {/* Gradient (donker onderaan → transparant): leesbare tekst zonder de hele foto te dimmen. */}\n {block.overlayGradient && coverMedia && <div className=\"xicms-hero__gradient\" aria-hidden=\"true\" />}\n <div className=\"xicms-hero__inner\">\n {block.eyebrow && (\n <Text type=\"label\" className=\"xicms-hero__eyebrow\" style={light} data-xicms-edit=\"eyebrow\">\n {block.eyebrow}\n </Text>\n )}\n {block.title && (\n <Heading level={block.headingLevel === \"2\" ? 2 : 1} type=\"display-1\" className=\"xicms-hero__title\" style={light} data-xicms-edit=\"title\">\n {block.title}\n </Heading>\n )}\n {block.subtitle && (\n <Text type=\"large\" className=\"xicms-hero__sub\" style={light} data-xicms-edit=\"subtitle\">\n {block.subtitle}\n </Text>\n )}\n {buttons.length > 0 && (\n <div className=\"xicms-hero__buttons\">\n {/* Via Astryx Btn (zelfde systeem als Cta/Pricing/…): volgt de site-theming en de\n outline→ghost-variantmapping — geen tweede, handmatig te onderhouden knop-CSS. */}\n {buttons.map((b, i) => ({ ...b, _i: i })).filter((b) => b.label).map((b) => (\n <Btn key={b._i} label={b.label} href={b.href} variant={b.variant} size=\"lg\" editField={`buttons.${b._i}.label`} />\n ))}\n </div>\n )}\n </div>\n {block.videoUrl && (\n <button\n type=\"button\"\n className=\"xicms-hero__videotoggle\"\n onClick={toggleVideo}\n aria-label={playing ? \"Achtergrondvideo pauzeren\" : \"Achtergrondvideo afspelen\"}\n >\n {playing ? \"⏸\" : \"▶\"}\n </button>\n )}\n </section>\n );\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/HeroRender.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState, type CSSProperties } from \"react\";\nimport type { z } from \"zod\";\nimport type { HeroBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { Btn, Heading, Text } from \"../ui\";\nimport { Img } from \"../../media/ImageContext\";\n\ntype Hero = z.infer<typeof HeroBlockSchema>;\n\nexport function HeroRender({ block }: BlockRenderProps<Hero>) {\n // Achtergrondvideo WCAG-proof (2.2.2): geen autoPlay-attribuut (hydration-veilig) — playback\n // start in een effect, en alléén zonder reduced-motion-voorkeur. Altijd een pauzeknop, en\n // imageUrl dient als poster (direct beeld i.p.v. zwart vlak → betere LCP).\n const videoRef = useRef<HTMLVideoElement>(null);\n const [playing, setPlaying] = useState(false);\n useEffect(() => {\n const v = videoRef.current;\n if (!v) return;\n if (window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches) return;\n v.play().then(() => setPlaying(true)).catch(() => undefined);\n }, [block.videoUrl]);\n const toggleVideo = () => {\n const v = videoRef.current;\n if (!v) return;\n if (v.paused) v.play().then(() => setPlaying(true)).catch(() => undefined);\n else {\n v.pause();\n setPlaying(false);\n }\n };\n const overlay =\n block.overlayOpacity > 0\n ? { background: block.overlayColor ?? \"#000000\", opacity: block.overlayOpacity / 100 }\n : null;\n // 8.13: \"naast\" = foto rechts naast de tekst, nooit als achtergrond.\n const naast = block.layout === \"naast\" && Boolean(block.imageUrl) && !block.videoUrl;\n // Beeld/video als dekkende achtergrond (niet bij height \"auto\"): dan moet de tekst licht zijn.\n const coverMedia = !naast && Boolean(block.videoUrl || block.imageUrl) && block.minHeight !== \"auto\";\n const light: CSSProperties | undefined = coverMedia\n ? { color: \"#ffffff\", textShadow: \"0 2px 14px rgba(0,0,0,.45)\" }\n : undefined;\n const buttons = block.buttons ?? [];\n\n return (\n <section\n className=\"xicms-hero\"\n data-align={block.align}\n data-valign={block.vAlign}\n data-height={block.minHeight}\n data-media={coverMedia ? \"cover\" : undefined}\n data-layout={naast ? \"naast\" : undefined}\n >\n {block.videoUrl ? (\n <video\n ref={videoRef}\n className=\"xicms-hero__media\"\n src={block.videoUrl}\n poster={block.imageUrl || undefined}\n muted\n loop\n playsInline\n preload=\"metadata\"\n aria-hidden=\"true\"\n />\n ) : block.imageUrl && !naast ? (\n <Img src={block.imageUrl} alt=\"\" className=\"xicms-hero__media\" width={1600} height={900} sizes=\"100vw\" priority editField=\"imageUrl\" editFill />\n ) : null}\n {overlay && <div className=\"xicms-hero__overlay\" style={overlay} aria-hidden=\"true\" />}\n {/* Gradient (donker onderaan → transparant): leesbare tekst zonder de hele foto te dimmen. */}\n {block.overlayGradient && coverMedia && <div className=\"xicms-hero__gradient\" aria-hidden=\"true\" />}\n <div className=\"xicms-hero__inner\">\n {block.eyebrow && (\n <Text type=\"label\" className=\"xicms-hero__eyebrow\" style={light} data-xicms-edit=\"eyebrow\">\n {block.eyebrow}\n </Text>\n )}\n {block.title && (\n <Heading level={block.headingLevel === \"2\" ? 2 : 1} type=\"display-1\" className=\"xicms-hero__title\" style={light} data-xicms-edit=\"title\">\n {block.title}\n </Heading>\n )}\n {block.subtitle && (\n <Text type=\"large\" className=\"xicms-hero__sub\" style={light} data-xicms-edit=\"subtitle\">\n {block.subtitle}\n </Text>\n )}\n {buttons.length > 0 && (\n <div className=\"xicms-hero__buttons\">\n {/* Via Astryx Btn (zelfde systeem als Cta/Pricing/…): volgt de site-theming en de\n outline→ghost-variantmapping — geen tweede, handmatig te onderhouden knop-CSS. */}\n {buttons.map((b, i) => ({ ...b, _i: i })).filter((b) => b.label).map((b) => (\n <Btn key={b._i} label={b.label} href={b.href} variant={b.variant} size=\"lg\" editField={`buttons.${b._i}.label`} />\n ))}\n </div>\n )}\n {(block.trust ?? []).some((t) => t.trim()) && (\n <ul className=\"xicms-hero__trust\" style={light}>\n {(block.trust ?? []).map((t, i) => (t.trim() ? <li key={i} data-xicms-edit={`trust.${i}`}>{t}</li> : null))}\n </ul>\n )}\n </div>\n {naast && block.imageUrl && (\n <div className=\"xicms-hero__beeld\">\n <Img src={block.imageUrl} alt=\"\" width={1200} height={1000} sizes=\"(max-width: 900px) 100vw, 50vw\" priority editField=\"imageUrl\" editFill />\n </div>\n )}\n {block.videoUrl && (\n <button\n type=\"button\"\n className=\"xicms-hero__videotoggle\"\n onClick={toggleVideo}\n aria-label={playing ? \"Achtergrondvideo pauzeren\" : \"Achtergrondvideo afspelen\"}\n >\n {playing ? \"⏸\" : \"▶\"}\n </button>\n )}\n </section>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { type HoursRow } from "./lib/openingHours.js";
|
|
2
|
+
import type { BusinessException } from "../../schema/business.js";
|
|
2
3
|
/**
|
|
3
4
|
* "Nu geopend / Nu gesloten"-badge bij openingstijden. Client-only en pas ná mount berekend
|
|
4
5
|
* (hydration-veilig: de servertijd kan afwijken van de bezoekerstijd). Toont niets wanneer de
|
|
5
6
|
* rijen niet betrouwbaar te parsen zijn — liever geen badge dan een foute.
|
|
6
7
|
*/
|
|
7
|
-
export declare function OpenNowBadge({ rows }: {
|
|
8
|
-
rows: HoursRow[];
|
|
8
|
+
export declare function OpenNowBadge({ rows, afwijkingen }: {
|
|
9
|
+
rows: HoursRow[]; /** 8.13: feestdagen/vakantie tellen mee. */
|
|
10
|
+
afwijkingen?: BusinessException[];
|
|
9
11
|
}): import("react").JSX.Element | null;
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useState } from "react";
|
|
4
4
|
import { StatusDot } from "@astryxdesign/core/StatusDot";
|
|
5
|
-
import {
|
|
6
|
-
function OpenNowBadge({ rows }) {
|
|
5
|
+
import { isOpenNuMetAfwijkingen } from "../../bedrijf/bedrijf.js";
|
|
6
|
+
function OpenNowBadge({ rows, afwijkingen }) {
|
|
7
7
|
const [open, setOpen] = useState(null);
|
|
8
|
-
const rowsKey = JSON.stringify(rows);
|
|
8
|
+
const rowsKey = JSON.stringify([rows, afwijkingen ?? []]);
|
|
9
9
|
useEffect(() => {
|
|
10
|
-
const parsed = JSON.parse(rowsKey);
|
|
11
|
-
setOpen(
|
|
12
|
-
const id = setInterval(() => setOpen(
|
|
10
|
+
const [parsed, uitz] = JSON.parse(rowsKey);
|
|
11
|
+
setOpen(isOpenNuMetAfwijkingen(parsed, uitz));
|
|
12
|
+
const id = setInterval(() => setOpen(isOpenNuMetAfwijkingen(parsed, uitz)), 6e4);
|
|
13
13
|
return () => clearInterval(id);
|
|
14
14
|
}, [rowsKey]);
|
|
15
15
|
if (open === null) return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/blocks/builtins/OpenNowBadge.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { StatusDot } from \"@astryxdesign/core/StatusDot\";\nimport {
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/OpenNowBadge.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { StatusDot } from \"@astryxdesign/core/StatusDot\";\nimport { type HoursRow } from \"./lib/openingHours\";\nimport { isOpenNuMetAfwijkingen } from \"../../bedrijf/bedrijf\";\nimport type { BusinessException } from \"../../schema/business\";\n\n/**\n * \"Nu geopend / Nu gesloten\"-badge bij openingstijden. Client-only en pas ná mount berekend\n * (hydration-veilig: de servertijd kan afwijken van de bezoekerstijd). Toont niets wanneer de\n * rijen niet betrouwbaar te parsen zijn — liever geen badge dan een foute.\n */\nexport function OpenNowBadge({ rows, afwijkingen }: { rows: HoursRow[]; /** 8.13: feestdagen/vakantie tellen mee. */ afwijkingen?: BusinessException[] }) {\n const [open, setOpen] = useState<boolean | null>(null);\n // Op inhoud deppen, niet op referentie: de parent bouwt `rows` elke render opnieuw en zou de\n // minuut-interval anders bij elke render resetten (badge die nooit ververst + effect-churn).\n const rowsKey = JSON.stringify([rows, afwijkingen ?? []]);\n useEffect(() => {\n const [parsed, uitz] = JSON.parse(rowsKey) as [HoursRow[], BusinessException[]];\n setOpen(isOpenNuMetAfwijkingen(parsed, uitz));\n const id = setInterval(() => setOpen(isOpenNuMetAfwijkingen(parsed, uitz)), 60_000);\n return () => clearInterval(id);\n }, [rowsKey]);\n if (open === null) return null;\n const label = open ? \"Nu geopend\" : \"Nu gesloten\";\n return (\n <span className=\"xicms-hours__badge\" data-open={open ? \"1\" : \"0\"}>\n {/* De stip was een `●`-TEKEN in de tekst. Schermlezers lazen dat voor als \"zwarte cirkel\",\n hij volgde de tekstkleur niet los en schaalde mee met de letterhoogte i.p.v. met het\n thema. Astryx' StatusDot is een echt element met een eigen variant; `aria-hidden` omdat\n de status er direct naast al in woorden staat — anders klinkt hij dubbel. */}\n <StatusDot variant={open ? \"success\" : \"error\"} label={label} aria-hidden />\n {label}\n </span>\n );\n}\n"],"mappings":";AA2BI,SAKE,KALF;AAzBJ,SAAS,WAAW,gBAAgB;AACpC,SAAS,iBAAiB;AAE1B,SAAS,8BAA8B;AAQhC,SAAS,aAAa,EAAE,MAAM,YAAY,GAAyG;AACxJ,QAAM,CAAC,MAAM,OAAO,IAAI,SAAyB,IAAI;AAGrD,QAAM,UAAU,KAAK,UAAU,CAAC,MAAM,eAAe,CAAC,CAAC,CAAC;AACxD,YAAU,MAAM;AACd,UAAM,CAAC,QAAQ,IAAI,IAAI,KAAK,MAAM,OAAO;AACzC,YAAQ,uBAAuB,QAAQ,IAAI,CAAC;AAC5C,UAAM,KAAK,YAAY,MAAM,QAAQ,uBAAuB,QAAQ,IAAI,CAAC,GAAG,GAAM;AAClF,WAAO,MAAM,cAAc,EAAE;AAAA,EAC/B,GAAG,CAAC,OAAO,CAAC;AACZ,MAAI,SAAS,KAAM,QAAO;AAC1B,QAAM,QAAQ,OAAO,eAAe;AACpC,SACE,qBAAC,UAAK,WAAU,sBAAqB,aAAW,OAAO,MAAM,KAK3D;AAAA,wBAAC,aAAU,SAAS,OAAO,YAAY,SAAS,OAAc,eAAW,MAAC;AAAA,IACzE;AAAA,KACH;AAEJ;","names":[]}
|
|
@@ -2,6 +2,12 @@ import type { z } from "zod";
|
|
|
2
2
|
import type { OpeningHoursBlockSchema } from "../../schema/blocks.js";
|
|
3
3
|
import type { BlockRenderProps } from "../registry.js";
|
|
4
4
|
type OpeningHours = z.infer<typeof OpeningHoursBlockSchema>;
|
|
5
|
-
/**
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Openingstijden-tabel; de optionele "Nu geopend"-badge is een client-eiland.
|
|
7
|
+
*
|
|
8
|
+
* 8.13: zonder eigen regels toont het blok de tijden uit het bedrijfsprofiel (Instellingen →
|
|
9
|
+
* Bedrijf) — één keer invullen, overal hetzelfde. Afwijkende dagen uit het profiel (feestdagen,
|
|
10
|
+
* vakantie) die binnenkort vallen, staan eronder, en tellen mee voor "nu geopend".
|
|
11
|
+
*/
|
|
12
|
+
export declare function OpeningHoursRender({ block, mode }: BlockRenderProps<OpeningHours>): import("react").JSX.Element | null;
|
|
7
13
|
export {};
|
|
@@ -1,18 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
3
|
import { jsonLdHtml } from "./jsonld.js";
|
|
3
4
|
import { Heading } from "../ui/index.js";
|
|
4
5
|
import { OpenNowBadge } from "./OpenNowBadge.js";
|
|
5
6
|
import { openingHoursSpecJsonLd } from "./lib/openingHours.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
import { useMergedSiteConfig } from "../../settings/useSiteSettings.js";
|
|
8
|
+
import { afwijkingDatumTekst, komendeAfwijkingen } from "../../bedrijf/bedrijf.js";
|
|
9
|
+
function OpeningHoursRender({ block, mode }) {
|
|
10
|
+
const business = useMergedSiteConfig().business;
|
|
11
|
+
const eigen = (block.rows ?? []).filter((r) => r.day.trim() || r.hours.trim());
|
|
12
|
+
const uitProfiel = eigen.length === 0;
|
|
13
|
+
const rows = uitProfiel ? business?.hours ?? [] : block.rows ?? [];
|
|
14
|
+
const afwijkingen = komendeAfwijkingen(business?.exceptions);
|
|
15
|
+
const spec = block.jsonLd && !uitProfiel ? openingHoursSpecJsonLd(rows) : [];
|
|
16
|
+
if (rows.length === 0 && afwijkingen.length === 0) {
|
|
17
|
+
return mode === "preview" ? /* @__PURE__ */ jsx("p", { className: "xicms-ve__hint", children: "Openingstijden: vul ze \xE9\xE9n keer in bij Instellingen \u2192 Bedrijf, of geef dit blok eigen regels." }) : null;
|
|
18
|
+
}
|
|
9
19
|
return /* @__PURE__ */ jsxs("section", { className: "xicms-hours", children: [
|
|
10
20
|
block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
|
|
11
|
-
block.showStatus && /* @__PURE__ */ jsx(OpenNowBadge, { rows }),
|
|
21
|
+
block.showStatus && /* @__PURE__ */ jsx(OpenNowBadge, { rows, afwijkingen: business?.exceptions }),
|
|
12
22
|
/* @__PURE__ */ jsx("table", { className: "xicms-hours-table", children: /* @__PURE__ */ jsx("tbody", { children: rows.map((r, i) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
13
|
-
/* @__PURE__ */ jsx("th", { scope: "row", "data-xicms-edit": `rows.${i}.day`, children: r.day }),
|
|
14
|
-
/* @__PURE__ */ jsx("td", { "data-xicms-edit": `rows.${i}.hours`, children: r.hours })
|
|
23
|
+
/* @__PURE__ */ jsx("th", { scope: "row", "data-xicms-edit": uitProfiel ? void 0 : `rows.${i}.day`, children: r.day }),
|
|
24
|
+
/* @__PURE__ */ jsx("td", { "data-xicms-edit": uitProfiel ? void 0 : `rows.${i}.hours`, children: r.hours })
|
|
15
25
|
] }, i)) }) }),
|
|
26
|
+
uitProfiel && business?.hoursNote && /* @__PURE__ */ jsx("p", { className: "xicms-hours__noot", children: business.hoursNote }),
|
|
27
|
+
afwijkingen.length > 0 && /* @__PURE__ */ jsxs("div", { className: "xicms-hours__afwijkend", role: "note", children: [
|
|
28
|
+
/* @__PURE__ */ jsx("strong", { children: "Aangepaste openingstijden" }),
|
|
29
|
+
/* @__PURE__ */ jsx("ul", { children: afwijkingen.map((a, i) => /* @__PURE__ */ jsxs("li", { children: [
|
|
30
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
31
|
+
afwijkingDatumTekst(a),
|
|
32
|
+
a.label ? ` (${a.label})` : ""
|
|
33
|
+
] }),
|
|
34
|
+
/* @__PURE__ */ jsx("span", { children: a.hours })
|
|
35
|
+
] }, i)) })
|
|
36
|
+
] }),
|
|
16
37
|
spec.length > 0 && /* @__PURE__ */ jsx(
|
|
17
38
|
"script",
|
|
18
39
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/blocks/builtins/OpeningHoursRender.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/OpeningHoursRender.tsx"],"sourcesContent":["\"use client\";\n\nimport type { z } from \"zod\";\nimport { jsonLdHtml } from \"./jsonld\";\nimport type { OpeningHoursBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { Heading } from \"../ui\";\nimport { OpenNowBadge } from \"./OpenNowBadge\";\nimport { openingHoursSpecJsonLd } from \"./lib/openingHours\";\nimport { useMergedSiteConfig } from \"../../settings/useSiteSettings\";\nimport { afwijkingDatumTekst, komendeAfwijkingen } from \"../../bedrijf/bedrijf\";\n\ntype OpeningHours = z.infer<typeof OpeningHoursBlockSchema>;\n\n/**\n * Openingstijden-tabel; de optionele \"Nu geopend\"-badge is een client-eiland.\n *\n * 8.13: zonder eigen regels toont het blok de tijden uit het bedrijfsprofiel (Instellingen →\n * Bedrijf) — één keer invullen, overal hetzelfde. Afwijkende dagen uit het profiel (feestdagen,\n * vakantie) die binnenkort vallen, staan eronder, en tellen mee voor \"nu geopend\".\n */\nexport function OpeningHoursRender({ block, mode }: BlockRenderProps<OpeningHours>) {\n const business = useMergedSiteConfig().business;\n const eigen = (block.rows ?? []).filter((r) => r.day.trim() || r.hours.trim());\n const uitProfiel = eigen.length === 0;\n const rows = uitProfiel ? (business?.hours ?? []) : block.rows ?? [];\n const afwijkingen = komendeAfwijkingen(business?.exceptions);\n // Komt de tijd uit het profiel, dan staat de JSON-LD al in de layout (bedrijfJsonLd).\n const spec = block.jsonLd && !uitProfiel ? openingHoursSpecJsonLd(rows) : [];\n if (rows.length === 0 && afwijkingen.length === 0) {\n return mode === \"preview\" ? (\n <p className=\"xicms-ve__hint\">Openingstijden: vul ze één keer in bij Instellingen → Bedrijf, of geef dit blok eigen regels.</p>\n ) : null;\n }\n return (\n <section className=\"xicms-hours\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n {block.showStatus && <OpenNowBadge rows={rows} afwijkingen={business?.exceptions} />}\n <table className=\"xicms-hours-table\">\n <tbody>\n {rows.map((r, i) => (\n <tr key={i}>\n <th scope=\"row\" data-xicms-edit={uitProfiel ? undefined : `rows.${i}.day`}>{r.day}</th>\n <td data-xicms-edit={uitProfiel ? undefined : `rows.${i}.hours`}>{r.hours}</td>\n </tr>\n ))}\n </tbody>\n </table>\n {uitProfiel && business?.hoursNote && <p className=\"xicms-hours__noot\">{business.hoursNote}</p>}\n {afwijkingen.length > 0 && (\n <div className=\"xicms-hours__afwijkend\" role=\"note\">\n <strong>Aangepaste openingstijden</strong>\n <ul>\n {afwijkingen.map((a, i) => (\n <li key={i}>\n <span>{afwijkingDatumTekst(a)}{a.label ? ` (${a.label})` : \"\"}</span>\n <span>{a.hours}</span>\n </li>\n ))}\n </ul>\n </div>\n )}\n {spec.length > 0 && (\n <script\n type=\"application/ld+json\"\n // eslint-disable-next-line react/no-danger\n dangerouslySetInnerHTML={{\n // Zelfde @id als contact-/layout-JSON-LD → Google voegt de drie samen tot één bedrijf.\n __html: jsonLdHtml({ \"@context\": \"https://schema.org\", \"@type\": \"LocalBusiness\", \"@id\": \"#business\", openingHoursSpecification: spec }),\n }}\n />\n )}\n </section>\n );\n}\n"],"mappings":";AA+BM,cAUM,YAVN;AA5BN,SAAS,kBAAkB;AAG3B,SAAS,eAAe;AACxB,SAAS,oBAAoB;AAC7B,SAAS,8BAA8B;AACvC,SAAS,2BAA2B;AACpC,SAAS,qBAAqB,0BAA0B;AAWjD,SAAS,mBAAmB,EAAE,OAAO,KAAK,GAAmC;AAClF,QAAM,WAAW,oBAAoB,EAAE;AACvC,QAAM,SAAS,MAAM,QAAQ,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,KAAK,KAAK,EAAE,MAAM,KAAK,CAAC;AAC7E,QAAM,aAAa,MAAM,WAAW;AACpC,QAAM,OAAO,aAAc,UAAU,SAAS,CAAC,IAAK,MAAM,QAAQ,CAAC;AACnE,QAAM,cAAc,mBAAmB,UAAU,UAAU;AAE3D,QAAM,OAAO,MAAM,UAAU,CAAC,aAAa,uBAAuB,IAAI,IAAI,CAAC;AAC3E,MAAI,KAAK,WAAW,KAAK,YAAY,WAAW,GAAG;AACjD,WAAO,SAAS,YACd,oBAAC,OAAE,WAAU,kBAAiB,sHAA6F,IACzH;AAAA,EACN;AACA,SACE,qBAAC,aAAQ,WAAU,eAChB;AAAA,UAAM,WAAW,oBAAC,WAAQ,OAAO,GAAG,mBAAgB,WAAW,gBAAM,SAAQ;AAAA,IAC7E,MAAM,cAAc,oBAAC,gBAAa,MAAY,aAAa,UAAU,YAAY;AAAA,IAClF,oBAAC,WAAM,WAAU,qBACf,8BAAC,WACE,eAAK,IAAI,CAAC,GAAG,MACZ,qBAAC,QACC;AAAA,0BAAC,QAAG,OAAM,OAAM,mBAAiB,aAAa,SAAY,QAAQ,CAAC,QAAS,YAAE,KAAI;AAAA,MAClF,oBAAC,QAAG,mBAAiB,aAAa,SAAY,QAAQ,CAAC,UAAW,YAAE,OAAM;AAAA,SAFnE,CAGT,CACD,GACH,GACF;AAAA,IACC,cAAc,UAAU,aAAa,oBAAC,OAAE,WAAU,qBAAqB,mBAAS,WAAU;AAAA,IAC1F,YAAY,SAAS,KACpB,qBAAC,SAAI,WAAU,0BAAyB,MAAK,QAC3C;AAAA,0BAAC,YAAO,uCAAyB;AAAA,MACjC,oBAAC,QACE,sBAAY,IAAI,CAAC,GAAG,MACnB,qBAAC,QACC;AAAA,6BAAC,UAAM;AAAA,8BAAoB,CAAC;AAAA,UAAG,EAAE,QAAQ,KAAK,EAAE,KAAK,MAAM;AAAA,WAAG;AAAA,QAC9D,oBAAC,UAAM,YAAE,OAAM;AAAA,WAFR,CAGT,CACD,GACH;AAAA,OACF;AAAA,IAED,KAAK,SAAS,KACb;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QAEL,yBAAyB;AAAA;AAAA,UAEvB,QAAQ,WAAW,EAAE,YAAY,sBAAsB,SAAS,iBAAiB,OAAO,aAAa,2BAA2B,KAAK,CAAC;AAAA,QACxI;AAAA;AAAA,IACF;AAAA,KAEJ;AAEJ;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const priceListBlock: import("../index.js").BlockDefinition<import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import dynamic from "next/dynamic";
|
|
2
|
+
import { defineBlock } from "../registry.js";
|
|
3
|
+
const priceListBlock = defineBlock({
|
|
4
|
+
type: "priceList",
|
|
5
|
+
Render: dynamic(() => import("./PriceListRender.js").then((m) => m.PriceListRender)),
|
|
6
|
+
label: "Prijslijst / menukaart",
|
|
7
|
+
icon: "\u{1F9FE}",
|
|
8
|
+
defaults: () => ({
|
|
9
|
+
heading: "Prijzen",
|
|
10
|
+
variant: "lijst",
|
|
11
|
+
sections: [
|
|
12
|
+
{
|
|
13
|
+
title: "Behandelingen",
|
|
14
|
+
items: [
|
|
15
|
+
{ name: "Dienst \xE9\xE9n", description: "Korte omschrijving.", price: "\u20AC 25", duration: "30 min" },
|
|
16
|
+
{ name: "Dienst twee", description: "Korte omschrijving.", price: "\u20AC 40", duration: "45 min" }
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
]
|
|
20
|
+
})
|
|
21
|
+
});
|
|
22
|
+
export {
|
|
23
|
+
priceListBlock
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=PriceList.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/PriceList.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const priceListBlock = defineBlock({\n type: \"priceList\",\n Render: dynamic(() => import(\"./PriceListRender\").then((m) => m.PriceListRender)),\n label: \"Prijslijst / menukaart\",\n icon: \"🧾\",\n defaults: () => ({\n heading: \"Prijzen\",\n variant: \"lijst\",\n sections: [\n {\n title: \"Behandelingen\",\n items: [\n { name: \"Dienst één\", description: \"Korte omschrijving.\", price: \"€ 25\", duration: \"30 min\" },\n { name: \"Dienst twee\", description: \"Korte omschrijving.\", price: \"€ 40\", duration: \"45 min\" },\n ],\n },\n ],\n }),\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;AAAA,IACf,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU;AAAA,MACR;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,UACL,EAAE,MAAM,oBAAc,aAAa,uBAAuB,OAAO,aAAQ,UAAU,SAAS;AAAA,UAC5F,EAAE,MAAM,eAAe,aAAa,uBAAuB,OAAO,aAAQ,UAAU,SAAS;AAAA,QAC/F;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF,CAAC;","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { PriceListBlockSchema } from "../../schema/blocks.js";
|
|
3
|
+
import type { BlockRenderProps } from "../registry.js";
|
|
4
|
+
type PriceList = z.infer<typeof PriceListBlockSchema>;
|
|
5
|
+
/** "€ 27,50" / "27.50" / "vanaf € 12" → 27.5 / 12; geen getal → undefined (dan geen prijs in de JSON-LD). */
|
|
6
|
+
export declare function prijsGetal(prijs: string | undefined): number | undefined;
|
|
7
|
+
/** schema.org: een horecamenu wordt Menu → MenuSection → MenuItem; al het andere een OfferCatalog. */
|
|
8
|
+
export declare function prijslijstJsonLd(b: PriceList): Record<string, unknown>;
|
|
9
|
+
/**
|
|
10
|
+
* Prijslijst / menukaart (8.13). Drie weergaven op dezelfde gegevens:
|
|
11
|
+
* - lijst: naam … prijs op één regel, omschrijving en duur eronder (kapper, praktijk);
|
|
12
|
+
* - menu: gecentreerde kaart in de koppenletter (restaurant, café);
|
|
13
|
+
* - kolommen: de secties naast elkaar (uitgebreide kaart of tarieflijst).
|
|
14
|
+
* Elke tekst heeft een veldhaak, dus alles is op de pagina zelf te bewerken (ook regels toevoegen).
|
|
15
|
+
*/
|
|
16
|
+
export declare function PriceListRender({ block, mode }: BlockRenderProps<PriceList>): import("react").JSX.Element | null;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Heading } from "../ui/index.js";
|
|
4
|
+
import { jsonLdHtml } from "./jsonld.js";
|
|
5
|
+
function prijsGetal(prijs) {
|
|
6
|
+
const m = /(\d+(?:[.,]\d{1,2})?)/.exec((prijs ?? "").replace(/\s/g, ""));
|
|
7
|
+
if (!m) return void 0;
|
|
8
|
+
const n = Number(m[1].replace(",", "."));
|
|
9
|
+
return Number.isFinite(n) ? n : void 0;
|
|
10
|
+
}
|
|
11
|
+
function prijslijstJsonLd(b) {
|
|
12
|
+
const aanbod = (prijs) => {
|
|
13
|
+
const n = prijsGetal(prijs);
|
|
14
|
+
return n === void 0 ? void 0 : { "@type": "Offer", price: n.toFixed(2), priceCurrency: "EUR" };
|
|
15
|
+
};
|
|
16
|
+
if (b.variant === "menu") {
|
|
17
|
+
return {
|
|
18
|
+
"@context": "https://schema.org",
|
|
19
|
+
"@type": "Menu",
|
|
20
|
+
...b.heading ? { name: b.heading } : {},
|
|
21
|
+
hasMenuSection: (b.sections ?? []).map((s) => ({
|
|
22
|
+
"@type": "MenuSection",
|
|
23
|
+
name: s.title,
|
|
24
|
+
hasMenuItem: (s.items ?? []).filter((i) => i.name.trim()).map((i) => ({
|
|
25
|
+
"@type": "MenuItem",
|
|
26
|
+
name: i.name,
|
|
27
|
+
...i.description ? { description: i.description } : {},
|
|
28
|
+
...aanbod(i.price) ? { offers: aanbod(i.price) } : {}
|
|
29
|
+
}))
|
|
30
|
+
}))
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
"@context": "https://schema.org",
|
|
35
|
+
"@type": "OfferCatalog",
|
|
36
|
+
...b.heading ? { name: b.heading } : {},
|
|
37
|
+
itemListElement: (b.sections ?? []).map((s) => ({
|
|
38
|
+
"@type": "OfferCatalog",
|
|
39
|
+
name: s.title,
|
|
40
|
+
itemListElement: (s.items ?? []).filter((i) => i.name.trim()).map((i) => ({
|
|
41
|
+
"@type": "Offer",
|
|
42
|
+
itemOffered: { "@type": "Service", name: i.name, ...i.description ? { description: i.description } : {} },
|
|
43
|
+
...prijsGetal(i.price) !== void 0 ? { price: prijsGetal(i.price).toFixed(2), priceCurrency: "EUR" } : {}
|
|
44
|
+
}))
|
|
45
|
+
}))
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function PriceListRender({ block, mode }) {
|
|
49
|
+
const secties = block.sections ?? [];
|
|
50
|
+
if (secties.length === 0 && mode !== "preview") return null;
|
|
51
|
+
const variant = block.variant ?? "lijst";
|
|
52
|
+
return /* @__PURE__ */ jsxs("section", { className: "xicms-prijslijst", "data-variant": variant, children: [
|
|
53
|
+
(block.heading || block.intro) && /* @__PURE__ */ jsxs("header", { className: "xicms-prijslijst__kop", children: [
|
|
54
|
+
block.heading && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "heading", children: block.heading }),
|
|
55
|
+
block.intro && /* @__PURE__ */ jsx("p", { className: "xicms-prijslijst__intro", "data-xicms-edit": "intro", children: block.intro })
|
|
56
|
+
] }),
|
|
57
|
+
/* @__PURE__ */ jsx("div", { className: "xicms-prijslijst__secties", children: secties.map((s, si) => /* @__PURE__ */ jsxs("div", { className: "xicms-prijslijst__sectie", children: [
|
|
58
|
+
s.title && /* @__PURE__ */ jsx("h3", { className: "xicms-prijslijst__sectietitel", "data-xicms-edit": `sections.${si}.title`, children: s.title }),
|
|
59
|
+
s.note && /* @__PURE__ */ jsx("p", { className: "xicms-prijslijst__noot", "data-xicms-edit": `sections.${si}.note`, children: s.note }),
|
|
60
|
+
/* @__PURE__ */ jsx("ul", { className: "xicms-prijslijst__regels", children: (s.items ?? []).map((it, ii) => {
|
|
61
|
+
const pad = `sections.${si}.items.${ii}`;
|
|
62
|
+
const tags = (it.tags ?? "").split(",").map((t) => t.trim()).filter(Boolean);
|
|
63
|
+
return /* @__PURE__ */ jsxs("li", { className: `xicms-prijslijst__regel${it.featured ? " is-uitgelicht" : ""}`, children: [
|
|
64
|
+
/* @__PURE__ */ jsxs("div", { className: "xicms-prijslijst__lijn", children: [
|
|
65
|
+
/* @__PURE__ */ jsx("span", { className: "xicms-prijslijst__naam", "data-xicms-edit": `${pad}.name`, children: it.name }),
|
|
66
|
+
/* @__PURE__ */ jsx("span", { className: "xicms-prijslijst__puntjes", "aria-hidden": true }),
|
|
67
|
+
it.price && /* @__PURE__ */ jsx("span", { className: "xicms-prijslijst__prijs", "data-xicms-edit": `${pad}.price`, children: it.price })
|
|
68
|
+
] }),
|
|
69
|
+
(it.description || it.duration || tags.length > 0) && /* @__PURE__ */ jsxs("div", { className: "xicms-prijslijst__details", children: [
|
|
70
|
+
it.description && /* @__PURE__ */ jsx("span", { "data-xicms-edit": `${pad}.description`, children: it.description }),
|
|
71
|
+
it.duration && /* @__PURE__ */ jsx("span", { className: "xicms-prijslijst__duur", "data-xicms-edit": `${pad}.duration`, children: it.duration }),
|
|
72
|
+
tags.map((t) => /* @__PURE__ */ jsx("span", { className: "xicms-prijslijst__tag", children: t }, t))
|
|
73
|
+
] })
|
|
74
|
+
] }, ii);
|
|
75
|
+
}) })
|
|
76
|
+
] }, si)) }),
|
|
77
|
+
block.footnote && /* @__PURE__ */ jsx("p", { className: "xicms-prijslijst__voetnoot", "data-xicms-edit": "footnote", children: block.footnote }),
|
|
78
|
+
block.jsonLd && // eslint-disable-next-line react/no-danger
|
|
79
|
+
/* @__PURE__ */ jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: { __html: jsonLdHtml(prijslijstJsonLd(block)) } })
|
|
80
|
+
] });
|
|
81
|
+
}
|
|
82
|
+
export {
|
|
83
|
+
PriceListRender,
|
|
84
|
+
prijsGetal,
|
|
85
|
+
prijslijstJsonLd
|
|
86
|
+
};
|
|
87
|
+
//# sourceMappingURL=PriceListRender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/PriceListRender.tsx"],"sourcesContent":["\"use client\";\n\nimport type { z } from \"zod\";\nimport type { PriceListBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { Heading } from \"../ui\";\nimport { jsonLdHtml } from \"./jsonld\";\n\ntype PriceList = z.infer<typeof PriceListBlockSchema>;\n\n/** \"€ 27,50\" / \"27.50\" / \"vanaf € 12\" → 27.5 / 12; geen getal → undefined (dan geen prijs in de JSON-LD). */\nexport function prijsGetal(prijs: string | undefined): number | undefined {\n const m = /(\\d+(?:[.,]\\d{1,2})?)/.exec((prijs ?? \"\").replace(/\\s/g, \"\"));\n if (!m) return undefined;\n const n = Number(m[1].replace(\",\", \".\"));\n return Number.isFinite(n) ? n : undefined;\n}\n\n/** schema.org: een horecamenu wordt Menu → MenuSection → MenuItem; al het andere een OfferCatalog. */\nexport function prijslijstJsonLd(b: PriceList): Record<string, unknown> {\n const aanbod = (prijs: string | undefined) => {\n const n = prijsGetal(prijs);\n return n === undefined ? undefined : { \"@type\": \"Offer\", price: n.toFixed(2), priceCurrency: \"EUR\" };\n };\n if (b.variant === \"menu\") {\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"Menu\",\n ...(b.heading ? { name: b.heading } : {}),\n hasMenuSection: (b.sections ?? []).map((s) => ({\n \"@type\": \"MenuSection\",\n name: s.title,\n hasMenuItem: (s.items ?? []).filter((i) => i.name.trim()).map((i) => ({\n \"@type\": \"MenuItem\",\n name: i.name,\n ...(i.description ? { description: i.description } : {}),\n ...(aanbod(i.price) ? { offers: aanbod(i.price) } : {}),\n })),\n })),\n };\n }\n return {\n \"@context\": \"https://schema.org\",\n \"@type\": \"OfferCatalog\",\n ...(b.heading ? { name: b.heading } : {}),\n itemListElement: (b.sections ?? []).map((s) => ({\n \"@type\": \"OfferCatalog\",\n name: s.title,\n itemListElement: (s.items ?? []).filter((i) => i.name.trim()).map((i) => ({\n \"@type\": \"Offer\",\n itemOffered: { \"@type\": \"Service\", name: i.name, ...(i.description ? { description: i.description } : {}) },\n ...(prijsGetal(i.price) !== undefined ? { price: prijsGetal(i.price)!.toFixed(2), priceCurrency: \"EUR\" } : {}),\n })),\n })),\n };\n}\n\n/**\n * Prijslijst / menukaart (8.13). Drie weergaven op dezelfde gegevens:\n * - lijst: naam … prijs op één regel, omschrijving en duur eronder (kapper, praktijk);\n * - menu: gecentreerde kaart in de koppenletter (restaurant, café);\n * - kolommen: de secties naast elkaar (uitgebreide kaart of tarieflijst).\n * Elke tekst heeft een veldhaak, dus alles is op de pagina zelf te bewerken (ook regels toevoegen).\n */\nexport function PriceListRender({ block, mode }: BlockRenderProps<PriceList>) {\n const secties = block.sections ?? [];\n if (secties.length === 0 && mode !== \"preview\") return null;\n const variant = block.variant ?? \"lijst\";\n return (\n <section className=\"xicms-prijslijst\" data-variant={variant}>\n {(block.heading || block.intro) && (\n <header className=\"xicms-prijslijst__kop\">\n {block.heading && <Heading level={2} data-xicms-edit=\"heading\">{block.heading}</Heading>}\n {block.intro && <p className=\"xicms-prijslijst__intro\" data-xicms-edit=\"intro\">{block.intro}</p>}\n </header>\n )}\n <div className=\"xicms-prijslijst__secties\">\n {secties.map((s, si) => (\n <div key={si} className=\"xicms-prijslijst__sectie\">\n {s.title && <h3 className=\"xicms-prijslijst__sectietitel\" data-xicms-edit={`sections.${si}.title`}>{s.title}</h3>}\n {s.note && <p className=\"xicms-prijslijst__noot\" data-xicms-edit={`sections.${si}.note`}>{s.note}</p>}\n <ul className=\"xicms-prijslijst__regels\">\n {(s.items ?? []).map((it, ii) => {\n const pad = `sections.${si}.items.${ii}`;\n const tags = (it.tags ?? \"\").split(\",\").map((t) => t.trim()).filter(Boolean);\n return (\n <li key={ii} className={`xicms-prijslijst__regel${it.featured ? \" is-uitgelicht\" : \"\"}`}>\n <div className=\"xicms-prijslijst__lijn\">\n <span className=\"xicms-prijslijst__naam\" data-xicms-edit={`${pad}.name`}>{it.name}</span>\n <span className=\"xicms-prijslijst__puntjes\" aria-hidden />\n {it.price && <span className=\"xicms-prijslijst__prijs\" data-xicms-edit={`${pad}.price`}>{it.price}</span>}\n </div>\n {(it.description || it.duration || tags.length > 0) && (\n <div className=\"xicms-prijslijst__details\">\n {it.description && <span data-xicms-edit={`${pad}.description`}>{it.description}</span>}\n {it.duration && <span className=\"xicms-prijslijst__duur\" data-xicms-edit={`${pad}.duration`}>{it.duration}</span>}\n {tags.map((t) => (\n <span key={t} className=\"xicms-prijslijst__tag\">{t}</span>\n ))}\n </div>\n )}\n </li>\n );\n })}\n </ul>\n </div>\n ))}\n </div>\n {block.footnote && <p className=\"xicms-prijslijst__voetnoot\" data-xicms-edit=\"footnote\">{block.footnote}</p>}\n {block.jsonLd && (\n // eslint-disable-next-line react/no-danger\n <script type=\"application/ld+json\" dangerouslySetInnerHTML={{ __html: jsonLdHtml(prijslijstJsonLd(block)) }} />\n )}\n </section>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useBlockData } from "../context.js";
|
|
4
|
+
import { vulAltIn } from "../../media/altInHtml.js";
|
|
2
5
|
function RichTextRender({ block }) {
|
|
3
|
-
|
|
6
|
+
const media = useBlockData("media");
|
|
7
|
+
const html = media ? vulAltIn(block.html, (src) => media[src]?.alt) : block.html;
|
|
8
|
+
return /* @__PURE__ */ jsx("div", { className: "xicms-richtext", "data-xicms-edit": "html", dangerouslySetInnerHTML: { __html: html } });
|
|
4
9
|
}
|
|
5
10
|
export {
|
|
6
11
|
RichTextRender
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/blocks/builtins/RichTextBlockRender.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/RichTextBlockRender.tsx"],"sourcesContent":["\"use client\";\n\nimport type { z } from \"zod\";\nimport type { RichTextBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { useBlockData } from \"../context\";\nimport { vulAltIn } from \"../../media/altInHtml\";\n\ntype RichText = z.infer<typeof RichTextBlockSchema>;\n\nexport function RichTextRender({ block }: BlockRenderProps<RichText>) {\n // Twee bronnen, twee saneringen — allebei vóór dit punt:\n // - GEPUBLICEERD: `publishPage` haalt de blokken door `sanitizeBlocks`, en de Firestore-rules\n // maken `pages` Functions-only. Wat hier binnenkomt is dus al server-side gesaneerd.\n // - WERKVERSIE: die schrijven editors rechtstreeks naar `drafts`, waar rules geen HTML kunnen\n // saneren. Daarom saneert de editor bij het INLEZEN (admin/lib/sanitizeDraft.ts).\n // Ga hier dus niet vanuit \"opslaan heeft het al gedaan\" — dat gold nooit voor werkversies.\n // `data-xicms-edit=\"html\"` geeft dit blok een haakje voor de rode wijzigings-highlight in de\n // visuele editor — zonder dit hook bleef een gewijzigd tekstblok (juist het bloktype dat een\n // klant het vaakst bewerkt) als enige zonder markering, terwijl andere tekstvelden wél rood\n // oplichtten.\n const media = useBlockData<Record<string, { alt?: string }>>(\"media\");\n const html = media ? vulAltIn(block.html, (src) => media[src]?.alt) : block.html;\n return <div className=\"xicms-richtext\" data-xicms-edit=\"html\" dangerouslySetInnerHTML={{ __html: html }} />;\n}\n"],"mappings":";AAuBS;AAlBT,SAAS,oBAAoB;AAC7B,SAAS,gBAAgB;AAIlB,SAAS,eAAe,EAAE,MAAM,GAA+B;AAWpE,QAAM,QAAQ,aAA+C,OAAO;AACpE,QAAM,OAAO,QAAQ,SAAS,MAAM,MAAM,CAAC,QAAQ,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM;AAC5E,SAAO,oBAAC,SAAI,WAAU,kBAAiB,mBAAgB,QAAO,yBAAyB,EAAE,QAAQ,KAAK,GAAG;AAC3G;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const sectionHeadingBlock: import("../index.js").BlockDefinition<import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineBlock } from "../registry.js";
|
|
2
|
+
import { SectionHeadingRender } from "./SectionHeadingRender.js";
|
|
3
|
+
const sectionHeadingBlock = defineBlock({
|
|
4
|
+
type: "sectionHeading",
|
|
5
|
+
// Klein en altijd boven de vouw van een sectie: niet lazy, anders flitst de kop na.
|
|
6
|
+
Render: SectionHeadingRender,
|
|
7
|
+
label: "Sectiekop",
|
|
8
|
+
icon: "\u{1F524}",
|
|
9
|
+
defaults: () => ({ eyebrow: "", title: "Kop van deze sectie", intro: "", align: "center" })
|
|
10
|
+
});
|
|
11
|
+
export {
|
|
12
|
+
sectionHeadingBlock
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=SectionHeading.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/SectionHeading.tsx"],"sourcesContent":["import { defineBlock } from \"../registry\";\nimport { SectionHeadingRender } from \"./SectionHeadingRender\";\n\nexport const sectionHeadingBlock = defineBlock({\n type: \"sectionHeading\",\n // Klein en altijd boven de vouw van een sectie: niet lazy, anders flitst de kop na.\n Render: SectionHeadingRender,\n label: \"Sectiekop\",\n icon: \"🔤\",\n defaults: () => ({ eyebrow: \"\", title: \"Kop van deze sectie\", intro: \"\", align: \"center\" }),\n});\n"],"mappings":"AAAA,SAAS,mBAAmB;AAC5B,SAAS,4BAA4B;AAE9B,MAAM,sBAAsB,YAAY;AAAA,EAC7C,MAAM;AAAA;AAAA,EAEN,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,SAAS,IAAI,OAAO,uBAAuB,OAAO,IAAI,OAAO,SAAS;AAC3F,CAAC;","names":[]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { SectionHeadingBlockSchema } from "../../schema/blocks.js";
|
|
3
|
+
import type { BlockRenderProps } from "../registry.js";
|
|
4
|
+
type SectieKop = z.infer<typeof SectionHeadingBlockSchema>;
|
|
5
|
+
/** Sectiekop (8.13): regeltje, kop en inleiding — overal dezelfde opbouw en uitlijning. */
|
|
6
|
+
export declare function SectionHeadingRender({ block }: BlockRenderProps<SectieKop>): import("react").JSX.Element | null;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Heading } from "../ui/index.js";
|
|
3
|
+
function SectionHeadingRender({ block }) {
|
|
4
|
+
if (!block.title && !block.eyebrow && !block.intro) return null;
|
|
5
|
+
return /* @__PURE__ */ jsxs("header", { className: "xicms-sectiekop", "data-align": block.align ?? "center", children: [
|
|
6
|
+
block.eyebrow && /* @__PURE__ */ jsx("p", { className: "xicms-sectiekop__regel", "data-xicms-edit": "eyebrow", children: block.eyebrow }),
|
|
7
|
+
block.title && /* @__PURE__ */ jsx(Heading, { level: 2, "data-xicms-edit": "title", children: block.title }),
|
|
8
|
+
block.intro && /* @__PURE__ */ jsx("p", { className: "xicms-sectiekop__intro", "data-xicms-edit": "intro", children: block.intro })
|
|
9
|
+
] });
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
SectionHeadingRender
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=SectionHeadingRender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/SectionHeadingRender.tsx"],"sourcesContent":["import type { z } from \"zod\";\nimport type { SectionHeadingBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { Heading } from \"../ui\";\n\ntype SectieKop = z.infer<typeof SectionHeadingBlockSchema>;\n\n/** Sectiekop (8.13): regeltje, kop en inleiding — overal dezelfde opbouw en uitlijning. */\nexport function SectionHeadingRender({ block }: BlockRenderProps<SectieKop>) {\n if (!block.title && !block.eyebrow && !block.intro) return null;\n return (\n <header className=\"xicms-sectiekop\" data-align={block.align ?? \"center\"}>\n {block.eyebrow && <p className=\"xicms-sectiekop__regel\" data-xicms-edit=\"eyebrow\">{block.eyebrow}</p>}\n {block.title && <Heading level={2} data-xicms-edit=\"title\">{block.title}</Heading>}\n {block.intro && <p className=\"xicms-sectiekop__intro\" data-xicms-edit=\"intro\">{block.intro}</p>}\n </header>\n );\n}\n"],"mappings":"AAWI,SACoB,KADpB;AARJ,SAAS,eAAe;AAKjB,SAAS,qBAAqB,EAAE,MAAM,GAAgC;AAC3E,MAAI,CAAC,MAAM,SAAS,CAAC,MAAM,WAAW,CAAC,MAAM,MAAO,QAAO;AAC3D,SACE,qBAAC,YAAO,WAAU,mBAAkB,cAAY,MAAM,SAAS,UAC5D;AAAA,UAAM,WAAW,oBAAC,OAAE,WAAU,0BAAyB,mBAAgB,WAAW,gBAAM,SAAQ;AAAA,IAChG,MAAM,SAAS,oBAAC,WAAQ,OAAO,GAAG,mBAAgB,SAAS,gBAAM,OAAM;AAAA,IACvE,MAAM,SAAS,oBAAC,OAAE,WAAU,0BAAyB,mBAAgB,SAAS,gBAAM,OAAM;AAAA,KAC7F;AAEJ;","names":[]}
|
|
@@ -17,7 +17,8 @@ function SliderRender({ block, mode }) {
|
|
|
17
17
|
}, [count]);
|
|
18
18
|
useEffect(() => {
|
|
19
19
|
if (!block.autoplay || paused || userPaused || count <= 1 || prefersReducedMotion()) return;
|
|
20
|
-
const
|
|
20
|
+
const sec = Number.isFinite(block.interval) && block.interval >= 1 ? block.interval : 5;
|
|
21
|
+
const id = setInterval(() => setIndex((i) => (i + 1) % count), sec * 1e3);
|
|
21
22
|
return () => clearInterval(id);
|
|
22
23
|
}, [block.autoplay, block.interval, paused, userPaused, count]);
|
|
23
24
|
if (count === 0) {
|
|
@@ -50,7 +51,7 @@ function SliderRender({ block, mode }) {
|
|
|
50
51
|
"section",
|
|
51
52
|
{
|
|
52
53
|
className: "xicms-slider",
|
|
53
|
-
style: { ["--xicms-slider-ratio"]: block.aspectRatio.replace("/", " / ") },
|
|
54
|
+
style: { ["--xicms-slider-ratio"]: (block.aspectRatio ?? "16/9").replace("/", " / ") },
|
|
54
55
|
onMouseEnter: () => setPaused(true),
|
|
55
56
|
onMouseLeave: () => setPaused(false),
|
|
56
57
|
onFocus: () => setPaused(true),
|