@xiwebdesign/xicms-core 7.31.0 → 8.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/XiCMSProvider.js +23 -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 -60
- 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 +248 -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 +159 -0
- package/dist/admin/settings/BedrijfInstellingen.js.map +1 -0
- 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 +56 -17
- 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/auth/AuthProvider.js +1 -0
- package/dist/auth/AuthProvider.js.map +1 -1
- package/dist/bedrijf/bedrijf.d.ts +44 -0
- package/dist/bedrijf/bedrijf.js +125 -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 +37 -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 +3 -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/consentEmbed.js +26 -9
- package/dist/blocks/builtins/consentEmbed.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/onderOffset.d.ts +13 -0
- package/dist/components/onderOffset.js +74 -0
- package/dist/components/onderOffset.js.map +1 -0
- package/dist/components/site/Bedrijfsnummers.d.ts +9 -0
- package/dist/components/site/Bedrijfsnummers.js +12 -0
- package/dist/components/site/Bedrijfsnummers.js.map +1 -0
- package/dist/components/site/SiteFooter.d.ts +6 -1
- package/dist/components/site/SiteFooter.js +62 -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/firebase/functionsClient.js +5 -1
- package/dist/firebase/functionsClient.js.map +1 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +20 -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 +22 -9
- package/dist/modules/builtins.js.map +1 -1
- package/dist/modules/consent/ConsentBanner.d.ts +5 -0
- package/dist/modules/consent/ConsentBanner.js +8 -7
- package/dist/modules/consent/ConsentBanner.js.map +1 -1
- package/dist/modules/consent/standaard.d.ts +12 -0
- package/dist/modules/consent/standaard.js +10 -0
- package/dist/modules/consent/standaard.js.map +1 -0
- package/dist/modules/consent/useConsent.d.ts +4 -0
- package/dist/modules/consent/useConsent.js +30 -1
- package/dist/modules/consent/useConsent.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 +148 -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 +473 -0
- package/dist/schema/blocks.js +105 -5
- package/dist/schema/blocks.js.map +1 -1
- package/dist/schema/business.d.ts +118 -0
- package/dist/schema/business.js +75 -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 +103 -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 +69 -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 +2 -0
- 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 +1181 -212
- 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 +5 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/forms/FormsPanel.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport {\n addDoc,\n collection,\n deleteDoc,\n doc,\n onSnapshot,\n orderBy,\n query,\n serverTimestamp,\n setDoc,\n} from \"firebase/firestore\";\nimport { getDb } from \"../../firebase/client\";\nimport { FormSchema, type FormDefinition, type FormField, type FieldType } from \"../../schema/forms\";\nimport { Button, Card, Field, Input, Badge } from \"../ui/primitives\";\nimport { Select } from \"../ui/select\";\nimport { Switch } from \"../ui/switch\";\nimport { useToast } from \"../ui/toast\";\nimport { useConfirm } from \"../ui/ConfirmDialog\";\nimport { MailTemplates } from \"../settings/MailTemplates\";\nimport { FORM_TEMPLATE_KEYS } from \"../../schema/mail\";\nimport { callable } from \"../../firebase/functionsClient\";\nimport { getFirebaseApp } from \"../../firebase/client\";\nimport { useAuth } from \"../../auth/AuthProvider\";\nimport { canManageSite } from \"../../auth/roles\";\nimport { formulierenGezienSinds, markeerFormulierGezien } from \"./gezien\";\nimport type { Timestamp } from \"firebase/firestore\";\n\ntype StoredForm = FormDefinition & { id: string };\n\nconst FIELD_TYPES: { value: FieldType; label: string }[] = [\n { value: \"text\", label: \"Tekst\" },\n { value: \"email\", label: \"E-mail\" },\n { value: \"tel\", label: \"Telefoon\" },\n { value: \"textarea\", label: \"Tekstvak\" },\n { value: \"select\", label: \"Keuzelijst\" },\n { value: \"radio\", label: \"Keuzerondjes\" },\n { value: \"checkbox\", label: \"Vinkje\" },\n { value: \"date\", label: \"Datum\" },\n { value: \"number\", label: \"Getal\" },\n];\n\nexport function FormsPanel({ siteId }: { siteId: string }) {\n const { toast } = useToast();\n const [forms, setForms] = useState<StoredForm[]>([]);\n const [selected, setSelected] = useState<string | null>(null);\n\n useEffect(() => {\n const db = getDb();\n if (!db) return;\n return onSnapshot(collection(db, \"sites\", siteId, \"forms\"), (snap) =>\n setForms(snap.docs.map((d) => ({ id: d.id, ...(d.data() as Omit<StoredForm, \"id\">) }))),\n );\n }, [siteId]);\n\n const current = forms.find((f) => f.id === selected) ?? null;\n\n async function createForm() {\n const db = getDb();\n if (!db) return;\n const ref = await addDoc(collection(db, \"sites\", siteId, \"forms\"), {\n name: \"Nieuw formulier\",\n fields: [{ name: \"naam\", label: \"Naam\", type: \"text\", required: true }],\n submitLabel: \"Versturen\",\n successMessage: \"Bedankt! We nemen snel contact op.\",\n } satisfies FormDefinition);\n setSelected(ref.id);\n }\n\n return (\n <div className=\"grid gap-6\">\n <div className=\"grid gap-4 md:grid-cols-[260px_1fr]\">\n <Card className=\"h-fit\">\n <div className=\"mb-3 flex items-center justify-between\">\n <h3 className=\"text-sm font-semibold\">Formulieren</h3>\n <Button size=\"sm\" onClick={createForm}>+ Nieuw</Button>\n </div>\n <ul className=\"grid gap-1\">\n {forms.map((f) => (\n <li key={f.id}>\n <button\n onClick={() => setSelected(f.id)}\n className={`w-full truncate rounded-lg px-3 py-2 text-left text-sm ${\n f.id === selected ? \"bg-brand-50 text-brand-700\" : \"hover:bg-slate-100\"\n }`}\n >\n {f.name}\n <span className=\"ml-1 text-xs text-slate-400\">#{f.id.slice(0, 5)}</span>\n </button>\n </li>\n ))}\n {forms.length === 0 && <li className=\"px-3 py-2 text-sm text-slate-500\">Nog geen formulieren.</li>}\n </ul>\n </Card>\n {current ? (\n <FormDetail key={current.id} siteId={siteId} form={current} onDeleted={() => setSelected(null)} onToast={toast} />\n ) : (\n <Card>\n <p className=\"text-sm text-slate-500\">Selecteer of maak een formulier.</p>\n </Card>\n )}\n </div>\n\n <div>\n <h3 className=\"mb-1 text-base font-semibold\">E-mailteksten voor formulieren</h3>\n <p className=\"mb-3 text-sm text-slate-600\">\n Gelden voor álle formulieren: de notificatie naar jou en de bevestiging naar de invuller. De opmaak\n (huisstijl) en verzendprovider stel je site-breed in bij <strong>Instellingen → E-mail</strong>.\n </p>\n <MailTemplates siteId={siteId} keys={FORM_TEMPLATE_KEYS} />\n </div>\n </div>\n );\n}\n\nlet veldTeller = 0;\nconst nieuweVeldId = () => `v${Date.now().toString(36)}${(veldTeller++).toString(36)}`;\n\nfunction FormDetail({\n siteId,\n form,\n onDeleted,\n onToast,\n}: {\n siteId: string;\n form: StoredForm;\n onDeleted: () => void;\n onToast: (t: { title: string; description?: string; tone?: \"default\" | \"success\" | \"error\" }) => void;\n}) {\n const [def, setDef] = useState<FormDefinition>(form);\n const confirm = useConfirm();\n /**\n * Stabiele React-sleutels per veld (7.24). Op index (`key={i}`) erven rijen elkaars state bij\n * verwijderen of verplaatsen — dezelfde stille corruptie die de vorige review in ArrayEditor\n * dichtte. De ids bestaan alleen hier (niet in het schema) en lopen mee met elke mutatie.\n */\n const [veldIds, setVeldIds] = useState<string[]>(() => form.fields.map(() => nieuweVeldId()));\n function zetVelden(fields: FormField[], ids: string[]) {\n setDef((d) => ({ ...d, fields }));\n setVeldIds(ids);\n }\n function verplaatsVeld(i: number, richting: -1 | 1) {\n const j = i + richting;\n if (j < 0 || j >= def.fields.length) return;\n const fields = [...def.fields];\n const ids = [...veldIds];\n [fields[i], fields[j]] = [fields[j], fields[i]];\n [ids[i], ids[j]] = [ids[j], ids[i]];\n zetVelden(fields, ids);\n }\n\n async function save() {\n const db = getDb();\n if (!db) return;\n const parsed = FormSchema.safeParse(def);\n if (!parsed.success) {\n onToast({ title: \"Ongeldig formulier\", description: parsed.error.issues[0]?.message, tone: \"error\" });\n return;\n }\n await setDoc(doc(db, \"sites\", siteId, \"forms\", form.id), parsed.data, { merge: true });\n onToast({ title: \"Opgeslagen\", tone: \"success\" });\n }\n\n async function remove() {\n const db = getDb();\n if (!db) return;\n const ok = await confirm({ title: \"Formulier verwijderen?\", description: \"Het formulier wordt verwijderd. Inzendingen blijven bewaard.\", confirmLabel: \"Verwijderen\", tone: \"danger\" });\n if (!ok) return;\n await deleteDoc(doc(db, \"sites\", siteId, \"forms\", form.id));\n onDeleted();\n }\n\n function setField(i: number, part: Partial<FormField>) {\n const fields = [...def.fields];\n fields[i] = { ...fields[i], ...part };\n setDef({ ...def, fields });\n }\n\n return (\n <div className=\"grid gap-4\">\n <Card>\n <div className=\"mb-3 flex items-center justify-between\">\n <h3 className=\"text-base font-semibold\">Formulier bewerken</h3>\n <div className=\"flex gap-2\">\n <Button variant=\"danger\" size=\"sm\" onClick={remove}>Verwijderen</Button>\n <Button size=\"sm\" onClick={save}>Opslaan</Button>\n </div>\n </div>\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Naam\"><Input value={def.name} onChange={(e) => setDef({ ...def, name: e.target.value })} /></Field>\n <Field label=\"Verstuurknop\"><Input value={def.submitLabel} onChange={(e) => setDef({ ...def, submitLabel: e.target.value })} /></Field>\n <Field label=\"Bedankbericht\"><Input value={def.successMessage} onChange={(e) => setDef({ ...def, successMessage: e.target.value })} /></Field>\n <Field label=\"Bedankt-pagina (optioneel)\" hint=\"Na verzenden doorsturen naar dit pad, bv. /bedankt\">\n <Input value={def.successRedirect ?? \"\"} onChange={(e) => setDef({ ...def, successRedirect: e.target.value || undefined })} />\n </Field>\n </div>\n\n <div className=\"mt-4 rounded-lg border border-slate-200 p-4\">\n <h4 className=\"text-sm font-semibold\">Wat gebeurt er bij een inzending?</h4>\n <p className=\"mb-3 mt-0.5 text-xs text-slate-500\">\n Elke inzending wordt altijd bewaard onder <strong>Inzendingen</strong>. Daarnaast kun je een kopie\n mailen naar jezelf en/of een bevestiging naar de invuller. De opmaak en verzendprovider stel je\n site-breed in bij <strong>Instellingen → E-mail</strong>.\n </p>\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Kopie van inzending naar\" hint=\"Leeg = het notificatie-adres uit Instellingen → E-mail.\">\n <Input\n type=\"email\"\n value={def.notifyTo ?? \"\"}\n onChange={(e) => setDef({ ...def, notifyTo: e.target.value || undefined })}\n placeholder=\"jij@voorbeeld.nl\"\n />\n </Field>\n <label className=\"mt-6 flex h-9 items-center gap-2 text-sm\">\n <input\n type=\"checkbox\"\n checked={Boolean(def.confirmSubmitter)}\n onChange={(e) => setDef({ ...def, confirmSubmitter: e.target.checked })}\n />\n Stuur de invuller ook een bevestiging (naar het eerste e-mailveld)\n </label>\n </div>\n </div>\n <p className=\"mt-3 text-xs text-slate-500\">Formulier-id (voor het Formulier-blok): <code>{form.id}</code></p>\n </Card>\n\n <Card>\n <h4 className=\"mb-3 text-sm font-semibold\">Velden</h4>\n <div className=\"grid gap-3\">\n {def.fields.map((f, i) => (\n <div key={veldIds[i] ?? i} className=\"grid items-end gap-2 rounded-lg border border-slate-200 p-3 md:grid-cols-[1fr_1fr_140px_auto_auto]\">\n <Field label=\"Naam (sleutel)\"><Input value={f.name} onChange={(e) => setField(i, { name: e.target.value })} /></Field>\n <Field label=\"Label\"><Input value={f.label} onChange={(e) => setField(i, { label: e.target.value })} /></Field>\n <Field label=\"Type\">\n <Select value={f.type} onValueChange={(v) => setField(i, { type: v as FieldType })} options={FIELD_TYPES} />\n </Field>\n <Switch checked={f.required} onCheckedChange={(v) => setField(i, { required: v })} label=\"Verplicht\" />\n <div className=\"flex items-center gap-1\">\n <Button variant=\"ghost\" size=\"sm\" aria-label=\"Veld omhoog\" disabled={i === 0} onClick={() => verplaatsVeld(i, -1)}>↑</Button>\n <Button variant=\"ghost\" size=\"sm\" aria-label=\"Veld omlaag\" disabled={i === def.fields.length - 1} onClick={() => verplaatsVeld(i, 1)}>↓</Button>\n <Button variant=\"ghost\" size=\"sm\" aria-label=\"Veld verwijderen\" onClick={() => zetVelden(def.fields.filter((_, idx) => idx !== i), veldIds.filter((_, idx) => idx !== i))}>🗑</Button>\n </div>\n {(f.type === \"select\" || f.type === \"radio\") && (\n <div className=\"md:col-span-5\">\n <Field label=\"Opties (komma-gescheiden)\">\n <Input\n value={(f.options ?? []).join(\", \")}\n onChange={(e) => setField(i, { options: e.target.value.split(\",\").map((s) => s.trim()).filter(Boolean) })}\n />\n </Field>\n </div>\n )}\n </div>\n ))}\n </div>\n <div className=\"mt-3\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => zetVelden([...def.fields, { name: `veld${def.fields.length + 1}`, label: \"Nieuw veld\", type: \"text\", required: false }], [...veldIds, nieuweVeldId()])}\n >\n + Veld toevoegen\n </Button>\n </div>\n </Card>\n\n <Submissions siteId={siteId} formId={form.id} velden={def.fields.map((f) => f.name)} />\n </div>\n );\n}\n\ntype Inzending = { id: string; values: Record<string, unknown>; createdAt?: Timestamp };\n\nfunction datumVan(s: Inzending): string {\n const d = s.createdAt && typeof s.createdAt.toDate === \"function\" ? s.createdAt.toDate() : null;\n return d ? d.toLocaleString(\"nl-NL\", { dateStyle: \"short\", timeStyle: \"short\" }) : \"\";\n}\n\n/** CSV met Excel-vriendelijke opmaak: BOM, puntkomma, alles gequoot. Kolommen = de velden van het formulier. */\nexport function inzendingenCsv(velden: string[], subs: Inzending[]): string {\n const cel = (v: unknown) => `\"${String(v ?? \"\").replace(/\"/g, '\"\"')}\"`;\n const kop = [\"datum\", ...velden].map(cel).join(\";\");\n const rijen = subs.map((s) => [datumVan(s), ...velden.map((k) => s.values?.[k])].map(cel).join(\";\"));\n return \"\\ufeff\" + [kop, ...rijen].join(\"\\r\\n\");\n}\n\nfunction Submissions({ siteId, formId, velden }: { siteId: string; formId: string; velden: string[] }) {\n const [subs, setSubs] = useState<Inzending[]>([]);\n const { toast } = useToast();\n const confirm = useConfirm();\n const { role } = useAuth();\n const magVerwijderen = canManageSite(role);\n // \"Nieuw sinds je laatste bezoek\" — het moment van openen; markeren gebeurt bij het sluiten\n // (unmount), zodat je tijdens het kijken nog ziet wát er nieuw was.\n const [sinds] = useState(() => formulierenGezienSinds(siteId, formId));\n useEffect(() => () => markeerFormulierGezien(siteId, formId), [siteId, formId]);\n\n useEffect(() => {\n const db = getDb();\n if (!db) return;\n const q = query(collection(db, \"sites\", siteId, \"forms\", formId, \"submissions\"), orderBy(\"createdAt\", \"desc\"));\n return onSnapshot(q, (snap) => setSubs(snap.docs.map((d) => ({ id: d.id, ...(d.data() as Omit<Inzending, \"id\">) }))));\n }, [siteId, formId]);\n\n const isNieuw = (s: Inzending) => Boolean(sinds && s.createdAt && s.createdAt.toMillis() > sinds.toMillis());\n const nieuw = subs.filter(isNieuw).length;\n\n function exporteer() {\n const blob = new Blob([inzendingenCsv(velden, subs)], { type: \"text/csv;charset=utf-8\" });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `inzendingen-${formId}-${new Date().toISOString().slice(0, 10)}.csv`;\n a.click();\n URL.revokeObjectURL(url);\n }\n\n async function verwijder(s: Inzending) {\n const ok = await confirm({\n title: \"Inzending verwijderen?\",\n description: \"Bijvoorbeeld op verzoek van de inzender (AVG). Dit kan niet ongedaan worden gemaakt.\",\n confirmLabel: \"Verwijderen\",\n tone: \"danger\",\n });\n if (!ok) return;\n const app = getFirebaseApp();\n if (!app) return;\n try {\n await callable(app, \"deleteSubmission\")({ siteId, formId, submissionId: s.id });\n toast({ title: \"Inzending verwijderd\" });\n } catch (e) {\n toast({ title: \"Verwijderen mislukt\", description: (e as Error).message, tone: \"error\" });\n }\n }\n\n return (\n <Card>\n <div className=\"mb-3 flex flex-wrap items-center justify-between gap-2\">\n <h4 className=\"text-sm font-semibold\">\n Inzendingen <Badge>{subs.length}</Badge>\n {nieuw > 0 && <Badge tone=\"amber\">{nieuw} nieuw</Badge>}\n </h4>\n {subs.length > 0 && (\n <Button variant=\"secondary\" size=\"sm\" onClick={exporteer}>\n Exporteer CSV\n </Button>\n )}\n </div>\n {subs.length === 0 ? (\n <p className=\"text-sm text-slate-500\">Nog geen inzendingen.</p>\n ) : (\n <div className=\"grid gap-2\">\n {subs.map((s) => (\n <div key={s.id} className={`rounded-lg border p-3 text-sm ${isNieuw(s) ? \"border-amber-300 bg-amber-50/40\" : \"border-slate-200\"}`}>\n <div className=\"mb-1 flex items-center justify-between gap-2 text-xs text-slate-400\">\n <span>{datumVan(s)}{isNieuw(s) ? \" · nieuw\" : \"\"}</span>\n {magVerwijderen && (\n <button type=\"button\" className=\"text-red-600 hover:underline\" onClick={() => void verwijder(s)}>\n Verwijderen\n </button>\n )}\n </div>\n {Object.entries(s.values ?? {}).map(([k, v]) => (\n <div key={k}>\n <span className=\"font-medium text-slate-600\">{k}:</span> {String(v)}\n </div>\n ))}\n </div>\n ))}\n </div>\n )}\n </Card>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/forms/FormsPanel.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport {\n addDoc,\n collection,\n deleteDoc,\n doc,\n getDoc,\n onSnapshot,\n orderBy,\n query,\n serverTimestamp,\n setDoc,\n} from \"firebase/firestore\";\nimport { getDb } from \"../../firebase/client\";\nimport { FormMailSchema, FormSchema, type FormDefinition, type FormField, type FieldType } from \"../../schema/forms\";\nimport { Button, Card, Field, Input, Badge, LegeStaat } from \"../ui/primitives\";\nimport { Select } from \"../ui/select\";\nimport { Switch } from \"../ui/switch\";\nimport { useToast } from \"../ui/toast\";\nimport { useConfirm } from \"../ui/ConfirmDialog\";\nimport { LaadStaat } from \"../ui/LaadStaat\";\nimport { isDemoActive } from \"../../demo/demoStore\";\nimport { neemOpenVerzoek } from \"../navContext\";\nimport { useScrollNaarDetail } from \"../lib/scrollNaarDetail\";\nimport { heeftOnopgeslagen, ONOPGESLAGEN_VRAAG, useOnopgeslagen, vergeetOnopgeslagen } from \"../lib/onopgeslagen\";\nimport { MailTemplates } from \"../settings/MailTemplates\";\nimport { FORM_TEMPLATE_KEYS } from \"../../schema/mail\";\nimport { callable } from \"../../firebase/functionsClient\";\nimport { getFirebaseApp } from \"../../firebase/client\";\nimport { useAuth } from \"../../auth/AuthProvider\";\nimport { canManageSite } from \"../../auth/roles\";\nimport { formulierenGezienSinds, markeerFormulierGezien } from \"./gezien\";\nimport type { Timestamp } from \"firebase/firestore\";\nimport { zodFoutTekst } from \"../lib/zodFout\";\nimport { laadFormulierGebruik } from \"../lib/paginaGebruik\";\n\ntype StoredForm = FormDefinition & { id: string };\n\nconst FIELD_TYPES: { value: FieldType; label: string }[] = [\n { value: \"text\", label: \"Tekst\" },\n { value: \"email\", label: \"E-mail\" },\n { value: \"tel\", label: \"Telefoon\" },\n { value: \"textarea\", label: \"Tekstvak\" },\n { value: \"select\", label: \"Keuzelijst\" },\n { value: \"radio\", label: \"Keuzerondjes\" },\n { value: \"checkbox\", label: \"Vinkje\" },\n { value: \"date\", label: \"Datum\" },\n { value: \"number\", label: \"Getal\" },\n { value: \"dateRange\", label: \"Periode (van – tot)\" },\n { value: \"hidden\", label: \"Verborgen (vaste waarde of uit de link)\" },\n];\n\nexport function FormsPanel({ siteId }: { siteId: string }) {\n const { toast } = useToast();\n const [forms, setForms] = useState<StoredForm[]>([]);\n const [selected, setSelected] = useState<string | null>(() => neemOpenVerzoek(\"forms\"));\n const [geladen, setGeladen] = useState(false);\n const [laadFout, setLaadFout] = useState<string | null>(null);\n const [poging, setPoging] = useState(0);\n\n useEffect(() => {\n const db = getDb();\n if (!db) {\n setGeladen(true);\n return;\n }\n return onSnapshot(\n collection(db, \"sites\", siteId, \"forms\"),\n (snap) => {\n setForms(snap.docs.map((d) => ({ id: d.id, ...(d.data() as Omit<StoredForm, \"id\">) })));\n setGeladen(true);\n setLaadFout(null);\n },\n (e) => {\n if (isDemoActive()) {\n setGeladen(true);\n return;\n }\n setLaadFout(e.message);\n },\n );\n }, [siteId, poging]);\n\n const current = forms.find((f) => f.id === selected) ?? null;\n const detailRef = useScrollNaarDetail(selected);\n const confirmLijst = useConfirm();\n\n async function kies(id: string) {\n if (id === selected) return;\n if (heeftOnopgeslagen()) {\n if (!(await confirmLijst(ONOPGESLAGEN_VRAAG))) return;\n vergeetOnopgeslagen();\n }\n setSelected(id);\n }\n\n async function createForm() {\n const db = getDb();\n if (!db) return;\n const ref = await addDoc(collection(db, \"sites\", siteId, \"forms\"), {\n name: \"Nieuw formulier\",\n fields: [{ name: \"naam\", label: \"Naam\", type: \"text\", required: true }],\n submitLabel: \"Versturen\",\n successMessage: \"Bedankt! We nemen snel contact op.\",\n } satisfies FormDefinition);\n setSelected(ref.id);\n }\n\n return (\n <div className=\"grid gap-6\">\n <div className=\"grid gap-4 md:grid-cols-[260px_1fr]\">\n <Card className=\"h-fit\">\n <div className=\"mb-3 flex items-center justify-between\">\n <h3 className=\"text-sm font-semibold\">Formulieren</h3>\n <Button size=\"sm\" onClick={createForm}>+ Nieuw</Button>\n </div>\n <LaadStaat laden={!geladen} fout={laadFout} wat=\"formulieren\" opnieuw={() => { setLaadFout(null); setPoging((n) => n + 1); }}>\n <ul className=\"grid gap-1\">\n {forms.map((f) => (\n <li key={f.id}>\n <button\n onClick={() => void kies(f.id)}\n className={`w-full truncate rounded-lg px-3 py-2 text-left text-sm ${\n f.id === selected ? \"bg-brand-50 text-brand-700\" : \"hover:bg-slate-100\"\n }`}\n >\n {f.name}\n </button>\n </li>\n ))}\n {forms.length === 0 && <li className=\"px-3 py-2 text-sm text-slate-500\">Nog geen formulieren.</li>}\n </ul>\n </LaadStaat>\n </Card>\n <div ref={detailRef} className=\"scroll-mt-24 min-w-0\">\n {current ? (\n <FormDetail key={current.id} siteId={siteId} form={current} onDeleted={() => setSelected(null)} onToast={toast} />\n ) : (\n <Card>\n <p className=\"text-sm text-slate-500\">Selecteer of maak een formulier.</p>\n </Card>\n )}\n </div>\n </div>\n\n <div>\n <h3 className=\"mb-1 text-base font-semibold\">E-mailteksten voor formulieren</h3>\n <p className=\"mb-3 text-sm text-slate-600\">\n Gelden voor álle formulieren: de notificatie naar jou en de bevestiging naar de invuller. De opmaak\n (huisstijl) en verzendprovider stel je site-breed in bij <strong>Instellingen → E-mail</strong>.\n </p>\n <MailTemplates siteId={siteId} keys={FORM_TEMPLATE_KEYS} />\n </div>\n </div>\n );\n}\n\n/** \"E-mailadres\" → \"emailadres\"; uniek gemaakt met een volgnummer. Voldoet aan /^[a-zA-Z][a-zA-Z0-9_]*$/. */\nexport function sleutelUitLabel(label: string, bezet: Set<string>): string {\n const basis = label\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[\\u0300-\\u036f]/g, \"\")\n .replace(/[^a-z0-9]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .slice(0, 40);\n const start = /^[a-z]/.test(basis) ? basis : `veld_${basis}`.replace(/_+$/, \"\") || \"veld\";\n if (!bezet.has(start)) return start;\n for (let n = 2; ; n++) if (!bezet.has(`${start}_${n}`)) return `${start}_${n}`;\n}\n\n/** Keuze-opties als losse regels (8.2) — het komma-veld slikte de komma terwijl je typte. */\nfunction OptiesEditor({ opties, onChange }: { opties: string[]; onChange: (o: string[]) => void }) {\n return (\n <Field label=\"Keuzes\" hint=\"Elke keuze op een eigen regel; volgorde = volgorde op de site.\">\n <div className=\"grid gap-2\">\n {opties.map((o, j) => (\n <div key={j} className=\"flex items-center gap-1\">\n <Input aria-label={`Keuze ${j + 1}`} value={o} onChange={(e) => onChange(opties.map((x, k) => (k === j ? e.target.value : x)))} />\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" aria-label=\"Keuze omhoog\" disabled={j === 0} onClick={() => { const n = [...opties]; [n[j - 1], n[j]] = [n[j], n[j - 1]]; onChange(n); }}>↑</Button>\n <Button type=\"button\" variant=\"dangerGhost\" size=\"sm\" aria-label={`Keuze \"${o}\" verwijderen`} onClick={() => onChange(opties.filter((_, k) => k !== j))}>🗑</Button>\n </div>\n ))}\n <div>\n <Button type=\"button\" variant=\"secondary\" size=\"sm\" onClick={() => onChange([...opties, `Keuze ${opties.length + 1}`])}>+ Keuze</Button>\n </div>\n </div>\n </Field>\n );\n}\n\nlet veldTeller = 0;\nconst nieuweVeldId = () => `v${Date.now().toString(36)}${(veldTeller++).toString(36)}`;\n\nfunction FormDetail({\n siteId,\n form,\n onDeleted,\n onToast,\n}: {\n siteId: string;\n form: StoredForm;\n onDeleted: () => void;\n onToast: (t: { title: string; description?: string; tone?: \"default\" | \"success\" | \"error\" }) => void;\n}) {\n const [def, setDef] = useState<FormDefinition>(form);\n /** Laatst geladen/opgeslagen stand: wijkt `def` daarvan af, dan is er onopgeslagen werk (8.2). */\n const [basis, setBasis] = useState<FormDefinition>(form);\n const [busy, setBusy] = useState(false);\n const vuil = JSON.stringify(def) !== JSON.stringify(basis);\n useOnopgeslagen(vuil);\n const confirm = useConfirm();\n\n // Mailinstellingen staan sinds 8.1 in een niet-publiek subdocument; oude formulieren hebben ze\n // nog op het formulier zelf (die waarden blijven de terugval tot de eerste keer opslaan).\n useEffect(() => {\n const db = getDb();\n if (!db) return;\n let actief = true;\n void getDoc(doc(db, \"sites\", siteId, \"forms\", form.id, \"private\", \"mail\"))\n .then((snap) => {\n if (!actief || !snap.exists()) return;\n const mail = FormMailSchema.safeParse(snap.data());\n if (!mail.success) return;\n const metMail = (d: FormDefinition) => ({ ...d, notifyTo: mail.data.notifyTo, confirmSubmitter: mail.data.confirmSubmitter });\n setDef(metMail);\n setBasis(metMail);\n })\n .catch((e) => console.warn(\"[xicms] mailinstellingen formulier niet geladen:\", e));\n return () => {\n actief = false;\n };\n }, [siteId, form.id]);\n /**\n * Stabiele React-sleutels per veld (7.24). Op index (`key={i}`) erven rijen elkaars state bij\n * verwijderen of verplaatsen — dezelfde stille corruptie die de vorige review in ArrayEditor\n * dichtte. De ids bestaan alleen hier (niet in het schema) en lopen mee met elke mutatie.\n */\n const [veldIds, setVeldIds] = useState<string[]>(() => form.fields.map(() => nieuweVeldId()));\n function zetVelden(fields: FormField[], ids: string[]) {\n setDef((d) => ({ ...d, fields }));\n setVeldIds(ids);\n }\n function verplaatsVeld(i: number, richting: -1 | 1) {\n const j = i + richting;\n if (j < 0 || j >= def.fields.length) return;\n const fields = [...def.fields];\n const ids = [...veldIds];\n [fields[i], fields[j]] = [fields[j], fields[i]];\n [ids[i], ids[j]] = [ids[j], ids[i]];\n zetVelden(fields, ids);\n }\n\n async function save() {\n const db = getDb();\n if (!db) return;\n const parsed = FormSchema.safeParse(def);\n if (!parsed.success) {\n onToast({ title: \"Ongeldig formulier\", description: zodFoutTekst(parsed.error.issues[0]), tone: \"error\" });\n return;\n }\n const { notifyTo, confirmSubmitter, ...publiek } = parsed.data;\n const mail = Object.fromEntries(\n Object.entries({ notifyTo: notifyTo?.trim() || undefined, confirmSubmitter: confirmSubmitter || undefined }).filter(([, v]) => v !== undefined),\n );\n setBusy(true);\n try {\n // Zónder merge: een gewist veld (bedankt-pagina, kopie-adres) moet ook echt weg. Met merge\n // bleef de oude waarde staan, en verdwenen de mailvelden nooit van het publieke document.\n await setDoc(doc(db, \"sites\", siteId, \"forms\", form.id), publiek);\n await setDoc(doc(db, \"sites\", siteId, \"forms\", form.id, \"private\", \"mail\"), mail);\n setBasis(def);\n onToast({ title: \"Opgeslagen\", tone: \"success\" });\n } catch (e) {\n onToast({ title: \"Opslaan mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n async function remove() {\n const db = getDb();\n if (!db) return;\n // 8.10: eerst kijken of een pagina dit formulier toont — dan zegt de bevestiging dat ook.\n const gebruik = await laadFormulierGebruik(siteId, form.id);\n const opPaginas = gebruik && gebruik.length > 0\n ? ` Let op: het staat op ${gebruik.length === 1 ? `de pagina “${gebruik[0]}”` : `${gebruik.length} pagina's (${gebruik.slice(0, 3).map((t) => `“${t}”`).join(\", \")})`}. Daar verschijnt dan “formulier niet beschikbaar” — haal het blok eerst weg of kies er een ander formulier.`\n : \"\";\n const ok = await confirm({\n title: \"Formulier verwijderen?\",\n description: `Het formulier wordt verwijderd. Inzendingen blijven bewaard.${opPaginas}`,\n confirmLabel: gebruik && gebruik.length > 0 ? \"Toch verwijderen\" : \"Verwijderen\",\n tone: \"danger\",\n });\n if (!ok) return;\n setBusy(true);\n try {\n await deleteDoc(doc(db, \"sites\", siteId, \"forms\", form.id));\n // Daarna pas de mailinstellingen (best-effort): mislukt het formulier, dan blijven ze heel.\n await deleteDoc(doc(db, \"sites\", siteId, \"forms\", form.id, \"private\", \"mail\")).catch(() => undefined);\n onToast({ title: \"Formulier verwijderd\", tone: \"success\" });\n onDeleted();\n } catch (e) {\n onToast({ title: \"Verwijderen mislukt\", description: e instanceof Error ? e.message : undefined, tone: \"error\" });\n } finally {\n setBusy(false);\n }\n }\n\n /** Velden die al bestonden bij openen houden hun sleutel (oude inzendingen verwijzen ernaar). */\n const [bestaandeSleutels] = useState(() => new Set(form.fields.map((f) => f.name)));\n\n function zetLabel(i: number, label: string) {\n const veld = def.fields[i];\n if (bestaandeSleutels.has(veld.name)) return setField(i, { label });\n const anderen = new Set(def.fields.filter((_, j) => j !== i).map((f) => f.name));\n setField(i, { label, name: sleutelUitLabel(label, anderen) });\n }\n\n async function verwijderVeld(i: number) {\n const veld = def.fields[i];\n // Een bestaand veld weghalen = die kolom verdwijnt uit de weergave van oude inzendingen.\n if (bestaandeSleutels.has(veld.name)) {\n const ok = await confirm({\n title: `Veld \"${veld.label}\" verwijderen?`,\n description: \"Oude inzendingen behouden hun antwoord, maar nieuwe bezoekers zien dit veld niet meer.\",\n confirmLabel: \"Verwijderen\",\n tone: \"danger\",\n });\n if (!ok) return;\n }\n zetVelden(def.fields.filter((_, idx) => idx !== i), veldIds.filter((_, idx) => idx !== i));\n }\n\n function setField(i: number, part: Partial<FormField>) {\n const fields = [...def.fields];\n fields[i] = { ...fields[i], ...part };\n setDef({ ...def, fields });\n }\n\n return (\n <div className=\"grid gap-4\">\n <Card>\n <div className=\"mb-3 flex items-center justify-between\">\n <h3 className=\"text-base font-semibold\">Formulier bewerken</h3>\n <div className=\"flex gap-2\">\n <Button variant=\"danger\" size=\"sm\" onClick={remove} disabled={busy}>Verwijderen</Button>\n {vuil && <span className=\"self-center text-sm text-amber-700\" role=\"status\">• Niet opgeslagen</span>}\n <Button loading={busy} size=\"sm\" onClick={save} disabled={busy}>{\"Opslaan — direct live\"}</Button>\n </div>\n </div>\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Naam\"><Input value={def.name} onChange={(e) => setDef({ ...def, name: e.target.value })} /></Field>\n <Field label=\"Verstuurknop\"><Input value={def.submitLabel} onChange={(e) => setDef({ ...def, submitLabel: e.target.value })} /></Field>\n <Field label=\"Bedankbericht\"><Input value={def.successMessage} onChange={(e) => setDef({ ...def, successMessage: e.target.value })} /></Field>\n <Field label=\"Bedankt-pagina (optioneel)\" hint=\"Na verzenden doorsturen naar dit pad, bv. /bedankt\">\n <Input value={def.successRedirect ?? \"\"} onChange={(e) => setDef({ ...def, successRedirect: e.target.value || undefined })} />\n </Field>\n </div>\n\n <div className=\"mt-4 rounded-lg border border-slate-200 p-4\">\n <h4 className=\"text-sm font-semibold\">Wat gebeurt er bij een inzending?</h4>\n <p className=\"mb-3 mt-0.5 text-xs text-slate-500\">\n Elke inzending wordt altijd bewaard onder <strong>Inzendingen</strong>. Daarnaast kun je een kopie\n mailen naar jezelf en/of een bevestiging naar de invuller. De opmaak en verzendprovider stel je\n site-breed in bij <strong>Instellingen → E-mail</strong>.\n </p>\n <div className=\"grid gap-3 md:grid-cols-2\">\n <Field label=\"Kopie van inzending naar\" hint=\"Meerdere adressen mag, met een komma ertussen. Leeg = het notificatie-adres uit Instellingen → E-mail.\">\n <Input\n value={def.notifyTo ?? \"\"}\n onChange={(e) => setDef({ ...def, notifyTo: e.target.value || undefined })}\n placeholder=\"jij@voorbeeld.nl\"\n />\n </Field>\n <div className=\"mt-6\">\n <Switch\n checked={Boolean(def.confirmSubmitter)}\n onCheckedChange={(v) => setDef({ ...def, confirmSubmitter: v })}\n label=\"Stuur de invuller een bevestiging (naar het eerste e-mailveld)\"\n />\n </div>\n </div>\n </div>\n <p className=\"mt-3 text-xs text-slate-500\">\n Op een pagina zet je dit formulier met het blok <strong>Formulier</strong>; kies daar "{def.name}".\n </p>\n </Card>\n\n <Card>\n <h4 className=\"mb-3 text-sm font-semibold\">Velden</h4>\n <div className=\"grid gap-3\">\n {def.fields.map((f, i) => (\n <div key={veldIds[i] ?? i} className=\"grid items-end gap-2 rounded-lg border border-slate-200 p-3 md:grid-cols-[1fr_160px_auto_auto]\">\n <Field label=\"Vraag / label\"><Input value={f.label} onChange={(e) => zetLabel(i, e.target.value)} /></Field>\n <Field label=\"Type\">\n <Select value={f.type} onValueChange={(v) => setField(i, { type: v as FieldType })} options={FIELD_TYPES} />\n </Field>\n <Switch checked={f.required} onCheckedChange={(v) => setField(i, { required: v })} label=\"Verplicht\" />\n <div className=\"flex items-center gap-1\">\n <Button variant=\"ghost\" size=\"sm\" aria-label=\"Veld omhoog\" disabled={i === 0} onClick={() => verplaatsVeld(i, -1)}>↑</Button>\n <Button variant=\"ghost\" size=\"sm\" aria-label=\"Veld omlaag\" disabled={i === def.fields.length - 1} onClick={() => verplaatsVeld(i, 1)}>↓</Button>\n <Button variant=\"dangerGhost\" size=\"sm\" aria-label={`Veld \"${f.label}\" verwijderen`} onClick={() => verwijderVeld(i)}>🗑</Button>\n </div>\n {(f.type === \"select\" || f.type === \"radio\") && (\n <div className=\"md:col-span-4\">\n <OptiesEditor opties={f.options ?? []} onChange={(options) => setField(i, { options })} />\n </div>\n )}\n {f.type === \"hidden\" && (\n <div className=\"md:col-span-4\">\n <Field\n label=\"Vaste waarde (optioneel)\"\n hint={`Wordt meegestuurd zonder dat de bezoeker het ziet. Een link als /contact?${f.name}=Huisje%20A vult dit veld met ‘Huisje A’.`}\n >\n <Input value={f.placeholder ?? \"\"} onChange={(e) => setField(i, { placeholder: e.target.value || undefined })} />\n </Field>\n </div>\n )}\n\n {/* De sleutel is techniek: hij volgt vanzelf het label (bij nieuwe velden) en blijft daarna\n vast, zodat oude inzendingen hun kolom houden. Alleen te zien voor wie hem zoekt. */}\n <details className=\"text-xs text-slate-500 md:col-span-4\">\n <summary className=\"cursor-pointer select-none\">Technische naam: {f.name}</summary>\n <div className=\"mt-2 max-w-xs\">\n <Input aria-label=\"Technische naam van het veld\" value={f.name} onChange={(e) => setField(i, { name: e.target.value })} />\n </div>\n </details>\n </div>\n ))}\n </div>\n <div className=\"mt-3\">\n <Button\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => zetVelden([...def.fields, { name: sleutelUitLabel(\"Nieuw veld\", new Set(def.fields.map((f) => f.name))), label: \"Nieuw veld\", type: \"text\", required: false }], [...veldIds, nieuweVeldId()])}\n >\n + Veld toevoegen\n </Button>\n </div>\n </Card>\n\n <Submissions siteId={siteId} formId={form.id} velden={def.fields.map((f) => ({ name: f.name, label: f.label }))} />\n </div>\n );\n}\n\ntype Inzending = { id: string; values: Record<string, unknown>; createdAt?: Timestamp };\n\nfunction datumVan(s: Inzending): string {\n const d = s.createdAt && typeof s.createdAt.toDate === \"function\" ? s.createdAt.toDate() : null;\n return d ? d.toLocaleString(\"nl-NL\", { dateStyle: \"short\", timeStyle: \"short\" }) : \"\";\n}\n\ntype Kolom = string | { name: string; label: string };\nconst kolomNaam = (k: Kolom) => (typeof k === \"string\" ? k : k.name);\nconst kolomLabel = (k: Kolom) => (typeof k === \"string\" ? k : k.label || k.name);\n\n/** Leesbare waarde: vinkjes als ja/nee i.p.v. true/false. */\nfunction waardeTekst(v: unknown): string {\n if (v === true) return \"ja\";\n if (v === false) return \"nee\";\n return String(v ?? \"\");\n}\n\n/**\n * CSV met Excel-vriendelijke opmaak: BOM, puntkomma, alles gequoot. Kolommen = de velden van het\n * formulier, met hun LABEL als kop (8.2; was de technische sleutel, bv. \"naam_1\").\n */\nexport function inzendingenCsv(velden: Kolom[], subs: Inzending[]): string {\n const cel = (v: unknown) => `\"${String(v ?? \"\").replace(/\"/g, '\"\"')}\"`;\n const kop = [\"Datum\", ...velden.map(kolomLabel)].map(cel).join(\";\");\n const rijen = subs.map((s) => [datumVan(s), ...velden.map((k) => waardeTekst(s.values?.[kolomNaam(k)]))].map(cel).join(\";\"));\n return \"\\ufeff\" + [kop, ...rijen].join(\"\\r\\n\");\n}\n\nfunction Submissions({ siteId, formId, velden }: { siteId: string; formId: string; velden: { name: string; label: string }[] }) {\n const [subs, setSubs] = useState<Inzending[]>([]);\n const { toast } = useToast();\n const confirm = useConfirm();\n const { role } = useAuth();\n const magVerwijderen = canManageSite(role);\n // \"Nieuw sinds je laatste bezoek\" — het moment van openen; markeren gebeurt bij het sluiten\n // (unmount), zodat je tijdens het kijken nog ziet wát er nieuw was.\n const [sinds] = useState(() => formulierenGezienSinds(siteId, formId));\n const [subsGeladen, setSubsGeladen] = useState(false);\n const [subsFout, setSubsFout] = useState<string | null>(null);\n const [subsPoging, setSubsPoging] = useState(0);\n useEffect(() => () => markeerFormulierGezien(siteId, formId), [siteId, formId]);\n\n useEffect(() => {\n const db = getDb();\n if (!db) return;\n const q = query(collection(db, \"sites\", siteId, \"forms\", formId, \"submissions\"), orderBy(\"createdAt\", \"desc\"));\n return onSnapshot(\n q,\n (snap) => {\n setSubs(snap.docs.map((d) => ({ id: d.id, ...(d.data() as Omit<Inzending, \"id\">) })));\n setSubsGeladen(true);\n setSubsFout(null);\n },\n (e) => setSubsFout(e.message),\n );\n }, [siteId, formId, subsPoging]);\n\n const isNieuw = (s: Inzending) => Boolean(sinds && s.createdAt && s.createdAt.toMillis() > sinds.toMillis());\n const nieuw = subs.filter(isNieuw).length;\n\n function exporteer() {\n const blob = new Blob([inzendingenCsv(velden, subs)], { type: \"text/csv;charset=utf-8\" });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = `inzendingen-${formId}-${new Date().toISOString().slice(0, 10)}.csv`;\n a.click();\n URL.revokeObjectURL(url);\n }\n\n async function verwijder(s: Inzending) {\n const ok = await confirm({\n title: \"Inzending verwijderen?\",\n description: \"Bijvoorbeeld op verzoek van de inzender (AVG). Dit kan niet ongedaan worden gemaakt.\",\n confirmLabel: \"Verwijderen\",\n tone: \"danger\",\n });\n if (!ok) return;\n const app = getFirebaseApp();\n if (!app) return;\n try {\n await callable(app, \"deleteSubmission\")({ siteId, formId, submissionId: s.id });\n toast({ title: \"Inzending verwijderd\" });\n } catch (e) {\n toast({ title: \"Verwijderen mislukt\", description: (e as Error).message, tone: \"error\" });\n }\n }\n\n return (\n <Card>\n <div className=\"mb-3 flex flex-wrap items-center justify-between gap-2\">\n <h4 className=\"text-sm font-semibold\">\n Inzendingen <Badge>{subs.length}</Badge>\n {nieuw > 0 && <Badge tone=\"amber\">{nieuw} nieuw</Badge>}\n </h4>\n {subs.length > 0 && (\n <Button variant=\"secondary\" size=\"sm\" onClick={exporteer}>\n Exporteer CSV\n </Button>\n )}\n </div>\n {subsFout || !subsGeladen ? (\n <LaadStaat laden={!subsGeladen} fout={subsFout} wat=\"inzendingen\" opnieuw={() => { setSubsFout(null); setSubsPoging((n) => n + 1); }}>{null}</LaadStaat>\n ) : subs.length === 0 ? (\n <LegeStaat titel=\"Nog geen inzendingen\" tekst=\"Zodra iemand dit formulier invult, staat het bericht hier — en krijg je een e-mail.\" />\n ) : (\n <div className=\"grid gap-2\">\n {subs.map((s) => (\n <div key={s.id} className={`rounded-lg border p-3 text-sm ${isNieuw(s) ? \"border-amber-300 bg-amber-50/40\" : \"border-slate-200\"}`}>\n <div className=\"mb-1 flex items-center justify-between gap-2 text-xs text-slate-500\">\n <span>{datumVan(s)}{isNieuw(s) ? \" · nieuw\" : \"\"}</span>\n {magVerwijderen && (\n <Button variant=\"dangerGhost\" size=\"sm\" onClick={() => void verwijder(s)}>\n Verwijderen\n </Button>\n )}\n </div>\n {/* Velden in formuliervolgorde met hun label; oude sleutels (veld inmiddels weg) erachter. */}\n {[...velden.filter((f) => f.name in (s.values ?? {})), ...Object.keys(s.values ?? {}).filter((k) => !velden.some((f) => f.name === k)).map((k) => ({ name: k, label: k }))].map((f) => (\n <div key={f.name}>\n <span className=\"font-medium text-slate-600\">{f.label}:</span>{\" \"}\n <span className=\"whitespace-pre-wrap\">{waardeTekst(s.values?.[f.name])}</span>\n </div>\n ))}\n </div>\n ))}\n </div>\n )}\n </Card>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Groep en uitleg per bloktype, voor de blokkiezer (8.11).
|
|
3
|
+
*
|
|
4
|
+
* Tot nu toe was "blok toevoegen" een platte keuzelijst van zo'n zestig namen met een emoji ervoor
|
|
5
|
+
* en "· widget" erachter. Wie niet wist wat een "Accordeon" of een "Kruimelpad" is, moest gokken.
|
|
6
|
+
* Hier staat in één zin wat elk blok doet, en in welke groep het hoort. Onbekende (maatwerk)blokken
|
|
7
|
+
* vallen in "Overig" met hun eigen naam.
|
|
8
|
+
*/
|
|
9
|
+
export type BlokGroep = "tekst" | "beeld" | "bedrijf" | "contact" | "nieuws" | "winkel" | "indeling" | "compact" | "overig";
|
|
10
|
+
export declare const GROEPEN: {
|
|
11
|
+
id: BlokGroep;
|
|
12
|
+
label: string;
|
|
13
|
+
}[];
|
|
14
|
+
export declare function blokInfo(type: string, categorie?: string): {
|
|
15
|
+
groep: BlokGroep;
|
|
16
|
+
uitleg?: string;
|
|
17
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
const GROEPEN = [
|
|
2
|
+
{ id: "tekst", label: "Tekst en koppen" },
|
|
3
|
+
{ id: "beeld", label: "Foto's en media" },
|
|
4
|
+
{ id: "bedrijf", label: "Over je bedrijf" },
|
|
5
|
+
{ id: "contact", label: "Contact en afspraken" },
|
|
6
|
+
{ id: "nieuws", label: "Nieuws en agenda" },
|
|
7
|
+
{ id: "winkel", label: "Webwinkel" },
|
|
8
|
+
{ id: "indeling", label: "Indeling" },
|
|
9
|
+
{ id: "compact", label: "Compact (voor naast een ander blok)" },
|
|
10
|
+
{ id: "overig", label: "Overig" }
|
|
11
|
+
];
|
|
12
|
+
const INFO = {
|
|
13
|
+
hero: { groep: "tekst", uitleg: "Grote openingsfoto met titel en knoppen \u2014 bovenaan een pagina." },
|
|
14
|
+
richText: { groep: "tekst", uitleg: "Gewone tekst met koppen, lijstjes, links en foto's." },
|
|
15
|
+
sectionHeading: { groep: "tekst", uitleg: "Een kop met een regeltje erboven en een korte inleiding, boven een nieuwe sectie." },
|
|
16
|
+
cta: { groep: "tekst", uitleg: "Een opvallende oproep met een knop, bijvoorbeeld 'Vraag een offerte aan'." },
|
|
17
|
+
banner: { groep: "tekst", uitleg: "Smalle aankondigingsbalk, bijvoorbeeld voor een actie of sluitingsdagen." },
|
|
18
|
+
quote: { groep: "tekst", uitleg: "Een uitgelicht citaat met naam." },
|
|
19
|
+
faq: { groep: "tekst", uitleg: "Vragen en antwoorden die openklappen \u2014 ook zichtbaar in Google." },
|
|
20
|
+
accordion: { groep: "tekst", uitleg: "Onderdelen die openklappen, voor lange informatie." },
|
|
21
|
+
buttons: { groep: "tekst", uitleg: "E\xE9n of meer losse knoppen." },
|
|
22
|
+
image: { groep: "beeld", uitleg: "E\xE9n foto, met een onderschrift als je wilt." },
|
|
23
|
+
gallery: { groep: "beeld", uitleg: "Een raster van foto's die groot openen bij klikken." },
|
|
24
|
+
slider: { groep: "beeld", uitleg: "Foto's of slides die na elkaar in beeld schuiven." },
|
|
25
|
+
video: { groep: "beeld", uitleg: "Een video van YouTube, Vimeo of een eigen bestand." },
|
|
26
|
+
beforeAfter: { groep: "beeld", uitleg: "Twee foto's met een schuifje: v\xF3\xF3r en na." },
|
|
27
|
+
logos: { groep: "beeld", uitleg: "Logo's van klanten, partners of keurmerken." },
|
|
28
|
+
pdf: { groep: "beeld", uitleg: "Een PDF op de pagina tonen, zoals een menukaart of folder." },
|
|
29
|
+
embed: { groep: "beeld", uitleg: "Inhoud van een andere website insluiten." },
|
|
30
|
+
map: { groep: "contact", uitleg: "Een kaartje met je locatie." },
|
|
31
|
+
cards: { groep: "bedrijf", uitleg: "Je diensten of producten als kaarten naast elkaar." },
|
|
32
|
+
feature: { groep: "bedrijf", uitleg: "Een foto naast een stuk tekst \u2014 om iets uit te lichten." },
|
|
33
|
+
pricing: { groep: "bedrijf", uitleg: "Prijzen of pakketten naast elkaar." },
|
|
34
|
+
priceList: { groep: "bedrijf", uitleg: "Prijslijst of menukaart: behandelingen, gerechten of tarieven met prijs en duur." },
|
|
35
|
+
team: { groep: "bedrijf", uitleg: "De mensen achter je bedrijf, met foto en functie." },
|
|
36
|
+
testimonials: { groep: "bedrijf", uitleg: "Wat klanten over je zeggen." },
|
|
37
|
+
counters: { groep: "bedrijf", uitleg: "Een paar indrukwekkende getallen, zoals '25 jaar ervaring'." },
|
|
38
|
+
timeline: { groep: "bedrijf", uitleg: "Stappen of een geschiedenis op een tijdlijn." },
|
|
39
|
+
portfolio: { groep: "bedrijf", uitleg: "Projecten of werk met foto's, te filteren per categorie." },
|
|
40
|
+
jobs: { groep: "bedrijf", uitleg: "Vacatures \u2014 ook zichtbaar in Google voor Banen." },
|
|
41
|
+
downloads: { groep: "bedrijf", uitleg: "Documenten om te downloaden." },
|
|
42
|
+
openingHours: { groep: "contact", uitleg: "Je openingstijden, met 'nu open' erbij." },
|
|
43
|
+
contact: { groep: "contact", uitleg: "Adres, telefoon en e-mail." },
|
|
44
|
+
form: { groep: "contact", uitleg: "Een contact- of aanvraagformulier." },
|
|
45
|
+
booking: { groep: "contact", uitleg: "Online afspraken maken via je boekingssysteem." },
|
|
46
|
+
availability: { groep: "contact", uitleg: "Kalender met vrije en bezette data (uit Airbnb, Booking.com \u2026); bezoekers kiezen een periode en vragen aan." },
|
|
47
|
+
newsletter: { groep: "contact", uitleg: "Aanmelden voor je nieuwsbrief." },
|
|
48
|
+
whatsappChat: { groep: "contact", uitleg: "Een knop waarmee bezoekers je direct appen." },
|
|
49
|
+
social: { groep: "contact", uitleg: "Links naar je social media." },
|
|
50
|
+
search: { groep: "contact", uitleg: "Een zoekveld voor je hele site." },
|
|
51
|
+
newsList: { groep: "nieuws", uitleg: "Je nieuwsberichten als overzicht." },
|
|
52
|
+
agenda: { groep: "nieuws", uitleg: "Activiteiten of evenementen met datum." },
|
|
53
|
+
countdown: { groep: "nieuws", uitleg: "Aftellen naar een datum, zoals een opening of actie." },
|
|
54
|
+
columns: { groep: "indeling", uitleg: "Blokken naast elkaar in kolommen." },
|
|
55
|
+
withSidebar: { groep: "indeling", uitleg: "Een hoofddeel met een smallere zijkolom." },
|
|
56
|
+
tabs: { groep: "indeling", uitleg: "Inhoud verdeeld over tabbladen." },
|
|
57
|
+
spacer: { groep: "indeling", uitleg: "Extra witruimte tussen twee blokken." },
|
|
58
|
+
divider: { groep: "indeling", uitleg: "Een scheidingslijn tussen twee blokken." },
|
|
59
|
+
breadcrumbs: { groep: "indeling", uitleg: "Laat zien waar de bezoeker is: Home \u203A Diensten \u203A \u2026" },
|
|
60
|
+
symbolRef: { groep: "indeling", uitleg: "Een blok dat op meerdere pagina's hetzelfde is; \xE9\xE9n keer aanpassen, overal bijgewerkt." },
|
|
61
|
+
productGrid: { groep: "winkel", uitleg: "Je producten in een raster." },
|
|
62
|
+
productDetail: { groep: "winkel", uitleg: "E\xE9n product met foto's, varianten en bestelknop." },
|
|
63
|
+
shopCategories: { groep: "winkel", uitleg: "De categorie\xEBn van je winkel." },
|
|
64
|
+
cart: { groep: "winkel", uitleg: "De winkelwagen." },
|
|
65
|
+
checkout: { groep: "winkel", uitleg: "Afrekenen." },
|
|
66
|
+
orderStatus: { groep: "winkel", uitleg: "De bedankpagina na een bestelling." },
|
|
67
|
+
donation: { groep: "winkel", uitleg: "Een donatie of gift ontvangen." }
|
|
68
|
+
};
|
|
69
|
+
function blokInfo(type, categorie) {
|
|
70
|
+
const info = INFO[type];
|
|
71
|
+
if (info) return info;
|
|
72
|
+
if (categorie === "widget" || /Widget$/.test(type)) return { groep: "compact" };
|
|
73
|
+
if (categorie === "layout") return { groep: "indeling" };
|
|
74
|
+
return { groep: "overig" };
|
|
75
|
+
}
|
|
76
|
+
export {
|
|
77
|
+
GROEPEN,
|
|
78
|
+
blokInfo
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=blokInfo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/lib/blokInfo.ts"],"sourcesContent":["/**\n * Groep en uitleg per bloktype, voor de blokkiezer (8.11).\n *\n * Tot nu toe was \"blok toevoegen\" een platte keuzelijst van zo'n zestig namen met een emoji ervoor\n * en \"· widget\" erachter. Wie niet wist wat een \"Accordeon\" of een \"Kruimelpad\" is, moest gokken.\n * Hier staat in één zin wat elk blok doet, en in welke groep het hoort. Onbekende (maatwerk)blokken\n * vallen in \"Overig\" met hun eigen naam.\n */\nexport type BlokGroep = \"tekst\" | \"beeld\" | \"bedrijf\" | \"contact\" | \"nieuws\" | \"winkel\" | \"indeling\" | \"compact\" | \"overig\";\n\nexport const GROEPEN: { id: BlokGroep; label: string }[] = [\n { id: \"tekst\", label: \"Tekst en koppen\" },\n { id: \"beeld\", label: \"Foto's en media\" },\n { id: \"bedrijf\", label: \"Over je bedrijf\" },\n { id: \"contact\", label: \"Contact en afspraken\" },\n { id: \"nieuws\", label: \"Nieuws en agenda\" },\n { id: \"winkel\", label: \"Webwinkel\" },\n { id: \"indeling\", label: \"Indeling\" },\n { id: \"compact\", label: \"Compact (voor naast een ander blok)\" },\n { id: \"overig\", label: \"Overig\" },\n];\n\nconst INFO: Record<string, { groep: BlokGroep; uitleg: string }> = {\n hero: { groep: \"tekst\", uitleg: \"Grote openingsfoto met titel en knoppen — bovenaan een pagina.\" },\n richText: { groep: \"tekst\", uitleg: \"Gewone tekst met koppen, lijstjes, links en foto's.\" },\n sectionHeading: { groep: \"tekst\", uitleg: \"Een kop met een regeltje erboven en een korte inleiding, boven een nieuwe sectie.\" },\n cta: { groep: \"tekst\", uitleg: \"Een opvallende oproep met een knop, bijvoorbeeld 'Vraag een offerte aan'.\" },\n banner: { groep: \"tekst\", uitleg: \"Smalle aankondigingsbalk, bijvoorbeeld voor een actie of sluitingsdagen.\" },\n quote: { groep: \"tekst\", uitleg: \"Een uitgelicht citaat met naam.\" },\n faq: { groep: \"tekst\", uitleg: \"Vragen en antwoorden die openklappen — ook zichtbaar in Google.\" },\n accordion: { groep: \"tekst\", uitleg: \"Onderdelen die openklappen, voor lange informatie.\" },\n buttons: { groep: \"tekst\", uitleg: \"Eén of meer losse knoppen.\" },\n image: { groep: \"beeld\", uitleg: \"Eén foto, met een onderschrift als je wilt.\" },\n gallery: { groep: \"beeld\", uitleg: \"Een raster van foto's die groot openen bij klikken.\" },\n slider: { groep: \"beeld\", uitleg: \"Foto's of slides die na elkaar in beeld schuiven.\" },\n video: { groep: \"beeld\", uitleg: \"Een video van YouTube, Vimeo of een eigen bestand.\" },\n beforeAfter: { groep: \"beeld\", uitleg: \"Twee foto's met een schuifje: vóór en na.\" },\n logos: { groep: \"beeld\", uitleg: \"Logo's van klanten, partners of keurmerken.\" },\n pdf: { groep: \"beeld\", uitleg: \"Een PDF op de pagina tonen, zoals een menukaart of folder.\" },\n embed: { groep: \"beeld\", uitleg: \"Inhoud van een andere website insluiten.\" },\n map: { groep: \"contact\", uitleg: \"Een kaartje met je locatie.\" },\n cards: { groep: \"bedrijf\", uitleg: \"Je diensten of producten als kaarten naast elkaar.\" },\n feature: { groep: \"bedrijf\", uitleg: \"Een foto naast een stuk tekst — om iets uit te lichten.\" },\n pricing: { groep: \"bedrijf\", uitleg: \"Prijzen of pakketten naast elkaar.\" },\n priceList: { groep: \"bedrijf\", uitleg: \"Prijslijst of menukaart: behandelingen, gerechten of tarieven met prijs en duur.\" },\n team: { groep: \"bedrijf\", uitleg: \"De mensen achter je bedrijf, met foto en functie.\" },\n testimonials: { groep: \"bedrijf\", uitleg: \"Wat klanten over je zeggen.\" },\n counters: { groep: \"bedrijf\", uitleg: \"Een paar indrukwekkende getallen, zoals '25 jaar ervaring'.\" },\n timeline: { groep: \"bedrijf\", uitleg: \"Stappen of een geschiedenis op een tijdlijn.\" },\n portfolio: { groep: \"bedrijf\", uitleg: \"Projecten of werk met foto's, te filteren per categorie.\" },\n jobs: { groep: \"bedrijf\", uitleg: \"Vacatures — ook zichtbaar in Google voor Banen.\" },\n downloads: { groep: \"bedrijf\", uitleg: \"Documenten om te downloaden.\" },\n openingHours: { groep: \"contact\", uitleg: \"Je openingstijden, met 'nu open' erbij.\" },\n contact: { groep: \"contact\", uitleg: \"Adres, telefoon en e-mail.\" },\n form: { groep: \"contact\", uitleg: \"Een contact- of aanvraagformulier.\" },\n booking: { groep: \"contact\", uitleg: \"Online afspraken maken via je boekingssysteem.\" },\n availability: { groep: \"contact\", uitleg: \"Kalender met vrije en bezette data (uit Airbnb, Booking.com …); bezoekers kiezen een periode en vragen aan.\" },\n newsletter: { groep: \"contact\", uitleg: \"Aanmelden voor je nieuwsbrief.\" },\n whatsappChat: { groep: \"contact\", uitleg: \"Een knop waarmee bezoekers je direct appen.\" },\n social: { groep: \"contact\", uitleg: \"Links naar je social media.\" },\n search: { groep: \"contact\", uitleg: \"Een zoekveld voor je hele site.\" },\n newsList: { groep: \"nieuws\", uitleg: \"Je nieuwsberichten als overzicht.\" },\n agenda: { groep: \"nieuws\", uitleg: \"Activiteiten of evenementen met datum.\" },\n countdown: { groep: \"nieuws\", uitleg: \"Aftellen naar een datum, zoals een opening of actie.\" },\n columns: { groep: \"indeling\", uitleg: \"Blokken naast elkaar in kolommen.\" },\n withSidebar: { groep: \"indeling\", uitleg: \"Een hoofddeel met een smallere zijkolom.\" },\n tabs: { groep: \"indeling\", uitleg: \"Inhoud verdeeld over tabbladen.\" },\n spacer: { groep: \"indeling\", uitleg: \"Extra witruimte tussen twee blokken.\" },\n divider: { groep: \"indeling\", uitleg: \"Een scheidingslijn tussen twee blokken.\" },\n breadcrumbs: { groep: \"indeling\", uitleg: \"Laat zien waar de bezoeker is: Home › Diensten › …\" },\n symbolRef: { groep: \"indeling\", uitleg: \"Een blok dat op meerdere pagina's hetzelfde is; één keer aanpassen, overal bijgewerkt.\" },\n productGrid: { groep: \"winkel\", uitleg: \"Je producten in een raster.\" },\n productDetail: { groep: \"winkel\", uitleg: \"Eén product met foto's, varianten en bestelknop.\" },\n shopCategories: { groep: \"winkel\", uitleg: \"De categorieën van je winkel.\" },\n cart: { groep: \"winkel\", uitleg: \"De winkelwagen.\" },\n checkout: { groep: \"winkel\", uitleg: \"Afrekenen.\" },\n orderStatus: { groep: \"winkel\", uitleg: \"De bedankpagina na een bestelling.\" },\n donation: { groep: \"winkel\", uitleg: \"Een donatie of gift ontvangen.\" },\n};\n\nexport function blokInfo(type: string, categorie?: string): { groep: BlokGroep; uitleg?: string } {\n const info = INFO[type];\n if (info) return info;\n if (categorie === \"widget\" || /Widget$/.test(type)) return { groep: \"compact\" };\n if (categorie === \"layout\") return { groep: \"indeling\" };\n return { groep: \"overig\" };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function foutNaarMens(melding: string | undefined): string | undefined;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const REGELS = [
|
|
2
|
+
[/permission[-_ ]denied|insufficient permissions/i, "Je hebt hier geen rechten voor. Ben je nog ingelogd met het juiste account?"],
|
|
3
|
+
[/unauthenticated|auth\/(user-token-expired|id-token-expired|requires-recent-login)/i, "Je sessie is verlopen. Log opnieuw in en probeer het nog eens."],
|
|
4
|
+
[/client is offline|unavailable|network[- ]request[- ]failed|failed to fetch|networkerror/i, "Geen verbinding met de server. Controleer je internet en probeer het opnieuw."],
|
|
5
|
+
[/deadline[-_ ]exceeded|timed? ?out/i, "Dat duurde te lang. Probeer het over een ogenblik opnieuw."],
|
|
6
|
+
[/resource[-_ ]exhausted|quota|too many requests/i, "Het is even te druk. Wacht een minuut en probeer het opnieuw."],
|
|
7
|
+
[/already[-_ ]exists/i, "Dit bestaat al."],
|
|
8
|
+
[/^not[-_ ]found$|no document to update/i, "Dit item bestaat niet meer \u2014 misschien heeft iemand anders het net verwijderd."],
|
|
9
|
+
[/^internal$/i, "Er ging aan onze kant iets mis. Probeer het opnieuw; blijft het gebeuren, neem dan contact op met Xi Webdesign."],
|
|
10
|
+
[/storage\/unauthorized/i, "Uploaden mag niet met dit account."],
|
|
11
|
+
[/storage\/(quota-exceeded|retry-limit-exceeded)/i, "Uploaden lukte niet (opslag vol of te traag). Probeer een kleinere foto."]
|
|
12
|
+
];
|
|
13
|
+
function foutNaarMens(melding) {
|
|
14
|
+
if (!melding) return melding;
|
|
15
|
+
const kaal = melding.replace(/^(FirebaseError|Error):\s*/i, "").replace(/\s*\((?:[a-z-]+\/)?[a-z-]+\)\.?$/i, "").trim();
|
|
16
|
+
for (const [re, tekst] of REGELS) if (re.test(melding) || re.test(kaal)) return tekst;
|
|
17
|
+
return melding;
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
foutNaarMens
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=foutNaarMens.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/lib/foutNaarMens.ts"],"sourcesContent":["/**\n * Technische foutmeldingen in gewone woorden (8.12).\n *\n * Ruim vijftig plekken in het beheer toonden `e.message` rechtstreeks: \"Missing or insufficient\n * permissions.\", \"Failed to get document because the client is offline\", \"deadline-exceeded\".\n * Engels, en voor een klant niets mee te doen. Dit vangt de bekende Firebase-gevallen op één plek\n * af (de toast doet het automatisch bij elke foutmelding); een melding die al Nederlands is, of die\n * we niet herkennen, blijft zoals hij is.\n */\nconst REGELS: [RegExp, string][] = [\n [/permission[-_ ]denied|insufficient permissions/i, \"Je hebt hier geen rechten voor. Ben je nog ingelogd met het juiste account?\"],\n [/unauthenticated|auth\\/(user-token-expired|id-token-expired|requires-recent-login)/i, \"Je sessie is verlopen. Log opnieuw in en probeer het nog eens.\"],\n [/client is offline|unavailable|network[- ]request[- ]failed|failed to fetch|networkerror/i, \"Geen verbinding met de server. Controleer je internet en probeer het opnieuw.\"],\n [/deadline[-_ ]exceeded|timed? ?out/i, \"Dat duurde te lang. Probeer het over een ogenblik opnieuw.\"],\n [/resource[-_ ]exhausted|quota|too many requests/i, \"Het is even te druk. Wacht een minuut en probeer het opnieuw.\"],\n [/already[-_ ]exists/i, \"Dit bestaat al.\"],\n [/^not[-_ ]found$|no document to update/i, \"Dit item bestaat niet meer — misschien heeft iemand anders het net verwijderd.\"],\n [/^internal$/i, \"Er ging aan onze kant iets mis. Probeer het opnieuw; blijft het gebeuren, neem dan contact op met Xi Webdesign.\"],\n [/storage\\/unauthorized/i, \"Uploaden mag niet met dit account.\"],\n [/storage\\/(quota-exceeded|retry-limit-exceeded)/i, \"Uploaden lukte niet (opslag vol of te traag). Probeer een kleinere foto.\"],\n];\n\nexport function foutNaarMens(melding: string | undefined): string | undefined {\n if (!melding) return melding;\n const kaal = melding.replace(/^(FirebaseError|Error):\\s*/i, \"\").replace(/\\s*\\((?:[a-z-]+\\/)?[a-z-]+\\)\\.?$/i, \"\").trim();\n for (const [re, tekst] of REGELS) if (re.test(melding) || re.test(kaal)) return tekst;\n return melding;\n}\n"],"mappings":"AASA,MAAM,SAA6B;AAAA,EACjC,CAAC,mDAAmD,6EAA6E;AAAA,EACjI,CAAC,sFAAsF,gEAAgE;AAAA,EACvJ,CAAC,4FAA4F,+EAA+E;AAAA,EAC5K,CAAC,sCAAsC,4DAA4D;AAAA,EACnG,CAAC,mDAAmD,+DAA+D;AAAA,EACnH,CAAC,uBAAuB,iBAAiB;AAAA,EACzC,CAAC,0CAA0C,qFAAgF;AAAA,EAC3H,CAAC,eAAe,iHAAiH;AAAA,EACjI,CAAC,0BAA0B,oCAAoC;AAAA,EAC/D,CAAC,mDAAmD,0EAA0E;AAChI;AAEO,SAAS,aAAa,SAAiD;AAC5E,MAAI,CAAC,QAAS,QAAO;AACrB,QAAM,OAAO,QAAQ,QAAQ,+BAA+B,EAAE,EAAE,QAAQ,qCAAqC,EAAE,EAAE,KAAK;AACtH,aAAW,CAAC,IAAI,KAAK,KAAK,OAAQ,KAAI,GAAG,KAAK,OAAO,KAAK,GAAG,KAAK,IAAI,EAAG,QAAO;AAChF,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Wat heeft de gebruiker leeggemaakt?" (8.1). De instellingen gaan via een callable die met
|
|
3
|
+
* `merge` schrijft; een veld dat je in /beheer wist (logo, deelafbeelding, lettertype-URL) kwam
|
|
4
|
+
* als `undefined` aan, werd door JSON weggelaten, en de merge liet de oude waarde staan — hij kwam
|
|
5
|
+
* na herladen gewoon terug. Deze functies zetten zo'n verdwenen veld op `null`; de server maakt
|
|
6
|
+
* daar `FieldValue.delete()` van. Alleen in gewone objecten: een array wordt als geheel vervangen.
|
|
7
|
+
*
|
|
8
|
+
* Bewust vergeleken met de bewerkte state (`nieuw`) en NIET met het door Zod geparste resultaat:
|
|
9
|
+
* Zod laat onbekende sleutels weg, en die zouden anders als "gewist" gelden.
|
|
10
|
+
*/
|
|
11
|
+
export declare function gewisteVelden(oud: unknown, nieuw: unknown): Record<string, unknown> | undefined;
|
|
12
|
+
/** Legt de `null`-markeringen van `gewisteVelden` over de te versturen data. */
|
|
13
|
+
export declare function metGewisteVelden<T extends Record<string, unknown>>(data: T, gewist: Record<string, unknown> | undefined): T;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
function gewisteVelden(oud, nieuw) {
|
|
2
|
+
if (!isObj(oud) || !isObj(nieuw)) return void 0;
|
|
3
|
+
const uit = {};
|
|
4
|
+
for (const [k, v] of Object.entries(oud)) {
|
|
5
|
+
if (v === void 0 || v === null) continue;
|
|
6
|
+
const n = nieuw[k];
|
|
7
|
+
if (n === void 0) uit[k] = null;
|
|
8
|
+
else if (isObj(v) && isObj(n)) {
|
|
9
|
+
const binnen = gewisteVelden(v, n);
|
|
10
|
+
if (binnen) uit[k] = binnen;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return Object.keys(uit).length > 0 ? uit : void 0;
|
|
14
|
+
}
|
|
15
|
+
function metGewisteVelden(data, gewist) {
|
|
16
|
+
if (!gewist) return data;
|
|
17
|
+
const uit = { ...data };
|
|
18
|
+
for (const [k, v] of Object.entries(gewist)) {
|
|
19
|
+
if (v === null) uit[k] = null;
|
|
20
|
+
else if (isObj(v)) uit[k] = metGewisteVelden(isObj(uit[k]) ? uit[k] : {}, v);
|
|
21
|
+
}
|
|
22
|
+
return uit;
|
|
23
|
+
}
|
|
24
|
+
function isObj(v) {
|
|
25
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
26
|
+
}
|
|
27
|
+
export {
|
|
28
|
+
gewisteVelden,
|
|
29
|
+
metGewisteVelden
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=gewisteVelden.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/lib/gewisteVelden.ts"],"sourcesContent":["/**\n * \"Wat heeft de gebruiker leeggemaakt?\" (8.1). De instellingen gaan via een callable die met\n * `merge` schrijft; een veld dat je in /beheer wist (logo, deelafbeelding, lettertype-URL) kwam\n * als `undefined` aan, werd door JSON weggelaten, en de merge liet de oude waarde staan — hij kwam\n * na herladen gewoon terug. Deze functies zetten zo'n verdwenen veld op `null`; de server maakt\n * daar `FieldValue.delete()` van. Alleen in gewone objecten: een array wordt als geheel vervangen.\n *\n * Bewust vergeleken met de bewerkte state (`nieuw`) en NIET met het door Zod geparste resultaat:\n * Zod laat onbekende sleutels weg, en die zouden anders als \"gewist\" gelden.\n */\nexport function gewisteVelden(oud: unknown, nieuw: unknown): Record<string, unknown> | undefined {\n if (!isObj(oud) || !isObj(nieuw)) return undefined;\n const uit: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(oud)) {\n if (v === undefined || v === null) continue;\n const n = nieuw[k];\n if (n === undefined) uit[k] = null;\n else if (isObj(v) && isObj(n)) {\n const binnen = gewisteVelden(v, n);\n if (binnen) uit[k] = binnen;\n }\n }\n return Object.keys(uit).length > 0 ? uit : undefined;\n}\n\n/** Legt de `null`-markeringen van `gewisteVelden` over de te versturen data. */\nexport function metGewisteVelden<T extends Record<string, unknown>>(data: T, gewist: Record<string, unknown> | undefined): T {\n if (!gewist) return data;\n const uit: Record<string, unknown> = { ...data };\n for (const [k, v] of Object.entries(gewist)) {\n if (v === null) uit[k] = null;\n else if (isObj(v)) uit[k] = metGewisteVelden(isObj(uit[k]) ? (uit[k] as Record<string, unknown>) : {}, v);\n }\n return uit as T;\n}\n\nfunction isObj(v: unknown): v is Record<string, unknown> {\n return typeof v === \"object\" && v !== null && !Array.isArray(v);\n}\n"],"mappings":"AAUO,SAAS,cAAc,KAAc,OAAqD;AAC/F,MAAI,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,KAAK,EAAG,QAAO;AACzC,QAAM,MAA+B,CAAC;AACtC,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,GAAG,GAAG;AACxC,QAAI,MAAM,UAAa,MAAM,KAAM;AACnC,UAAM,IAAI,MAAM,CAAC;AACjB,QAAI,MAAM,OAAW,KAAI,CAAC,IAAI;AAAA,aACrB,MAAM,CAAC,KAAK,MAAM,CAAC,GAAG;AAC7B,YAAM,SAAS,cAAc,GAAG,CAAC;AACjC,UAAI,OAAQ,KAAI,CAAC,IAAI;AAAA,IACvB;AAAA,EACF;AACA,SAAO,OAAO,KAAK,GAAG,EAAE,SAAS,IAAI,MAAM;AAC7C;AAGO,SAAS,iBAAoD,MAAS,QAAgD;AAC3H,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,MAA+B,EAAE,GAAG,KAAK;AAC/C,aAAW,CAAC,GAAG,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AAC3C,QAAI,MAAM,KAAM,KAAI,CAAC,IAAI;AAAA,aAChB,MAAM,CAAC,EAAG,KAAI,CAAC,IAAI,iBAAiB,MAAM,IAAI,CAAC,CAAC,IAAK,IAAI,CAAC,IAAgC,CAAC,GAAG,CAAC;AAAA,EAC1G;AACA,SAAO;AACT;AAEA,SAAS,MAAM,GAA0C;AACvD,SAAO,OAAO,MAAM,YAAY,MAAM,QAAQ,CAAC,MAAM,QAAQ,CAAC;AAChE;","names":[]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hero-hulpjes (8.10).
|
|
3
|
+
*
|
|
4
|
+
* Een foto achter witte tekst zonder verloop is op een lichte foto (lucht, witte gevel) onleesbaar —
|
|
5
|
+
* en dat is de belangrijkste kop van de site. Kiest de klant een foto terwijl er nog geen overlay
|
|
6
|
+
* is, dan zetten we het leesbaarheidsverloop aan. Wie bewust "geen overlay" wil, zet het daarna
|
|
7
|
+
* gewoon weer uit; we raken een eenmaal gekozen overlay nooit aan.
|
|
8
|
+
*/
|
|
9
|
+
export declare function heroBeeldPatch(block: Record<string, unknown>, url: string | undefined): Record<string, unknown>;
|
|
10
|
+
/** Een videoadres dat in een `<video>` niet werkt (YouTube/Vimeo-pagina's). Leeg = prima. */
|
|
11
|
+
export declare function videoAdresProbleem(url: string | undefined): string | null;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
function heroBeeldPatch(block, url) {
|
|
2
|
+
const patch = { imageUrl: url };
|
|
3
|
+
const heeftOverlay = Boolean(block.overlayGradient) || Number(block.overlayOpacity ?? 0) > 0;
|
|
4
|
+
if (url && !block.imageUrl && !heeftOverlay) patch.overlayGradient = true;
|
|
5
|
+
return patch;
|
|
6
|
+
}
|
|
7
|
+
function videoAdresProbleem(url) {
|
|
8
|
+
const u = (url ?? "").trim();
|
|
9
|
+
if (!u) return null;
|
|
10
|
+
if (/youtu\.?be|vimeo\.com/i.test(u)) return "Een YouTube- of Vimeo-link werkt hier niet. Gebruik een mp4-bestand uit Media, of het blok Video.";
|
|
11
|
+
if (!/\.(mp4|webm)(\?|#|$)/i.test(u) && !/firebasestorage|storage\.googleapis/i.test(u)) return "Dit lijkt geen videobestand (mp4 of webm).";
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
heroBeeldPatch,
|
|
16
|
+
videoAdresProbleem
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=heroHulp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/lib/heroHulp.ts"],"sourcesContent":["/**\n * Hero-hulpjes (8.10).\n *\n * Een foto achter witte tekst zonder verloop is op een lichte foto (lucht, witte gevel) onleesbaar —\n * en dat is de belangrijkste kop van de site. Kiest de klant een foto terwijl er nog geen overlay\n * is, dan zetten we het leesbaarheidsverloop aan. Wie bewust \"geen overlay\" wil, zet het daarna\n * gewoon weer uit; we raken een eenmaal gekozen overlay nooit aan.\n */\nexport function heroBeeldPatch(block: Record<string, unknown>, url: string | undefined): Record<string, unknown> {\n const patch: Record<string, unknown> = { imageUrl: url };\n const heeftOverlay = Boolean(block.overlayGradient) || Number(block.overlayOpacity ?? 0) > 0;\n if (url && !block.imageUrl && !heeftOverlay) patch.overlayGradient = true;\n return patch;\n}\n\n/** Een videoadres dat in een `<video>` niet werkt (YouTube/Vimeo-pagina's). Leeg = prima. */\nexport function videoAdresProbleem(url: string | undefined): string | null {\n const u = (url ?? \"\").trim();\n if (!u) return null;\n if (/youtu\\.?be|vimeo\\.com/i.test(u)) return \"Een YouTube- of Vimeo-link werkt hier niet. Gebruik een mp4-bestand uit Media, of het blok Video.\";\n if (!/\\.(mp4|webm)(\\?|#|$)/i.test(u) && !/firebasestorage|storage\\.googleapis/i.test(u)) return \"Dit lijkt geen videobestand (mp4 of webm).\";\n return null;\n}\n"],"mappings":"AAQO,SAAS,eAAe,OAAgC,KAAkD;AAC/G,QAAM,QAAiC,EAAE,UAAU,IAAI;AACvD,QAAM,eAAe,QAAQ,MAAM,eAAe,KAAK,OAAO,MAAM,kBAAkB,CAAC,IAAI;AAC3F,MAAI,OAAO,CAAC,MAAM,YAAY,CAAC,aAAc,OAAM,kBAAkB;AACrE,SAAO;AACT;AAGO,SAAS,mBAAmB,KAAwC;AACzE,QAAM,KAAK,OAAO,IAAI,KAAK;AAC3B,MAAI,CAAC,EAAG,QAAO;AACf,MAAI,yBAAyB,KAAK,CAAC,EAAG,QAAO;AAC7C,MAAI,CAAC,wBAAwB,KAAK,CAAC,KAAK,CAAC,uCAAuC,KAAK,CAAC,EAAG,QAAO;AAChG,SAAO;AACT;","names":[]}
|
package/dist/admin/lib/kleur.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { tekstOpKleur } from "../../theme/color.js";
|
|
1
2
|
function hexNaarRgb(hex) {
|
|
2
3
|
if (!hex) return null;
|
|
3
4
|
const m = hex.trim().replace(/^#/, "");
|
|
@@ -27,9 +28,7 @@ function contrast(a, b) {
|
|
|
27
28
|
return (licht + 0.05) / (donker + 0.05);
|
|
28
29
|
}
|
|
29
30
|
function tekstOp(kleur) {
|
|
30
|
-
|
|
31
|
-
if (!rgb) return "#ffffff";
|
|
32
|
-
return luminantie(rgb) > 0.4 ? "#0f172a" : "#ffffff";
|
|
31
|
+
return tekstOpKleur(kleur) ?? "#ffffff";
|
|
33
32
|
}
|
|
34
33
|
function contrastOordeel(ratio) {
|
|
35
34
|
if (ratio === null) return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/lib/kleur.ts"],"sourcesContent":["/**\n * Kleurhulpjes voor het Huisstijl-scherm (7.24): hex ↔ getallen en het WCAG-contrast.\n *\n * Klanten kozen een merkkleur op gevoel en zagen pas op de site dat witte knoptekst op een\n * lichtgele knop onleesbaar is. Het contrastcijfer erbij zetten voorkomt dat gesprek.\n */\n\n/** \"#abc\" / \"#aabbcc\" / \"aabbcc\" → [r, g, b], of null bij iets wat geen hex-kleur is. */\nexport function hexNaarRgb(hex: string | undefined): [number, number, number] | null {\n if (!hex) return null;\n const m = hex.trim().replace(/^#/, \"\");\n const vol = m.length === 3 ? m.split(\"\").map((c) => c + c).join(\"\") : m;\n if (!/^[0-9a-fA-F]{6}$/.test(vol)) return null;\n return [parseInt(vol.slice(0, 2), 16), parseInt(vol.slice(2, 4), 16), parseInt(vol.slice(4, 6), 16)];\n}\n\n/** Naar een 6-cijferige hex voor `<input type=\"color\">` (die accepteert alleen #rrggbb). */\nexport function naarHex6(kleur: string | undefined, fallback = \"#000000\"): string {\n const rgb = hexNaarRgb(kleur);\n if (!rgb) return fallback;\n return `#${rgb.map((n) => n.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\nfunction lineair(c: number): number {\n const v = c / 255;\n return v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;\n}\n\n/** Relatieve luminantie (WCAG 2.x). */\nexport function luminantie(rgb: [number, number, number]): number {\n return 0.2126 * lineair(rgb[0]) + 0.7152 * lineair(rgb[1]) + 0.0722 * lineair(rgb[2]);\n}\n\n/** Contrastverhouding tussen twee kleuren (1 = geen contrast, 21 = zwart op wit). */\nexport function contrast(a: string | undefined, b: string | undefined): number | null {\n const ra = hexNaarRgb(a);\n const rb = hexNaarRgb(b);\n if (!ra || !rb) return null;\n const la = luminantie(ra);\n const lb = luminantie(rb);\n const [licht, donker] = la > lb ? [la, lb] : [lb, la];\n return (licht + 0.05) / (donker + 0.05);\n}\n\n/** Welke tekstkleur komt er op een knop in deze kleur? (Spiegelt de on-accent-afleiding in CSS.) */\nexport function tekstOp(kleur: string | undefined): \"#ffffff\" | \"#0f172a\" {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/lib/kleur.ts"],"sourcesContent":["/**\n * Kleurhulpjes voor het Huisstijl-scherm (7.24): hex ↔ getallen en het WCAG-contrast.\n *\n * Klanten kozen een merkkleur op gevoel en zagen pas op de site dat witte knoptekst op een\n * lichtgele knop onleesbaar is. Het contrastcijfer erbij zetten voorkomt dat gesprek.\n */\n\nimport { tekstOpKleur } from \"../../theme/color\";\n\n/** \"#abc\" / \"#aabbcc\" / \"aabbcc\" → [r, g, b], of null bij iets wat geen hex-kleur is. */\nexport function hexNaarRgb(hex: string | undefined): [number, number, number] | null {\n if (!hex) return null;\n const m = hex.trim().replace(/^#/, \"\");\n const vol = m.length === 3 ? m.split(\"\").map((c) => c + c).join(\"\") : m;\n if (!/^[0-9a-fA-F]{6}$/.test(vol)) return null;\n return [parseInt(vol.slice(0, 2), 16), parseInt(vol.slice(2, 4), 16), parseInt(vol.slice(4, 6), 16)];\n}\n\n/** Naar een 6-cijferige hex voor `<input type=\"color\">` (die accepteert alleen #rrggbb). */\nexport function naarHex6(kleur: string | undefined, fallback = \"#000000\"): string {\n const rgb = hexNaarRgb(kleur);\n if (!rgb) return fallback;\n return `#${rgb.map((n) => n.toString(16).padStart(2, \"0\")).join(\"\")}`;\n}\n\nfunction lineair(c: number): number {\n const v = c / 255;\n return v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;\n}\n\n/** Relatieve luminantie (WCAG 2.x). */\nexport function luminantie(rgb: [number, number, number]): number {\n return 0.2126 * lineair(rgb[0]) + 0.7152 * lineair(rgb[1]) + 0.0722 * lineair(rgb[2]);\n}\n\n/** Contrastverhouding tussen twee kleuren (1 = geen contrast, 21 = zwart op wit). */\nexport function contrast(a: string | undefined, b: string | undefined): number | null {\n const ra = hexNaarRgb(a);\n const rb = hexNaarRgb(b);\n if (!ra || !rb) return null;\n const la = luminantie(ra);\n const lb = luminantie(rb);\n const [licht, donker] = la > lb ? [la, lb] : [lb, la];\n return (licht + 0.05) / (donker + 0.05);\n}\n\n/** Welke tekstkleur komt er op een knop in deze kleur? (Spiegelt de on-accent-afleiding in CSS.) */\nexport function tekstOp(kleur: string | undefined): \"#ffffff\" | \"#0f172a\" {\n // 8.10: dezelfde keuze als de site (theme/color.ts), zodat het voorbeeld niet liegt.\n return tekstOpKleur(kleur) ?? \"#ffffff\";\n}\n\n/**\n * Oordeel in gewone woorden. AA voor normale tekst is 4.5; voor grote tekst en knoppen volstaat 3.\n * We meten tegen 3 (knoppen zijn het hoofdgebruik van de merkkleur) en waarschuwen daaronder.\n */\nexport function contrastOordeel(ratio: number | null): { tekst: string; toon: \"goed\" | \"matig\" | \"slecht\" } | null {\n if (ratio === null) return null;\n const r = Math.round(ratio * 10) / 10;\n if (ratio >= 4.5) return { tekst: `Contrast ${r}:1 — goed leesbaar`, toon: \"goed\" };\n if (ratio >= 3) return { tekst: `Contrast ${r}:1 — voldoende voor knoppen en koppen, krap voor kleine tekst`, toon: \"matig\" };\n return { tekst: `Contrast ${r}:1 — te laag; kies een donkerdere of lichtere tint`, toon: \"slecht\" };\n}\n\n/** Curated lettertype-paren voor het Huisstijl-scherm — één keuze, meteen goed. */\nexport const LETTERTYPE_PAREN: { id: string; label: string; fontFamily: string; headingFont?: string; fontUrl: string }[] = [\n { id: \"inter\", label: \"Inter — helder & neutraal\", fontFamily: \"'Inter', system-ui, sans-serif\", fontUrl: \"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap\" },\n { id: \"inter-sora\", label: \"Inter + Sora — modern met karakter\", fontFamily: \"'Inter', system-ui, sans-serif\", headingFont: \"'Sora', 'Inter', sans-serif\", fontUrl: \"https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=Sora:wght@600;700&display=swap\" },\n { id: \"poppins\", label: \"Poppins — rond & vriendelijk\", fontFamily: \"'Poppins', system-ui, sans-serif\", fontUrl: \"https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap\" },\n { id: \"nunito\", label: \"Nunito — zacht & toegankelijk\", fontFamily: \"'Nunito', system-ui, sans-serif\", fontUrl: \"https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700;800&display=swap\" },\n { id: \"lora-source\", label: \"Source Sans + Lora — klassiek & warm\", fontFamily: \"'Source Sans 3', system-ui, sans-serif\", headingFont: \"'Lora', Georgia, serif\", fontUrl: \"https://fonts.googleapis.com/css2?family=Lora:wght@600;700&family=Source+Sans+3:wght@400;600;700&display=swap\" },\n { id: \"playfair\", label: \"Inter + Playfair Display — elegant\", fontFamily: \"'Inter', system-ui, sans-serif\", headingFont: \"'Playfair Display', Georgia, serif\", fontUrl: \"https://fonts.googleapis.com/css2?family=Inter:wght@400;600&family=Playfair+Display:wght@600;700&display=swap\" },\n { id: \"manrope\", label: \"Manrope — strak & technisch\", fontFamily: \"'Manrope', system-ui, sans-serif\", fontUrl: \"https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700;800&display=swap\" },\n { id: \"systeem\", label: \"Systeemlettertype — snelst, geen download\", fontFamily: \"system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif\", fontUrl: \"\" },\n];\n"],"mappings":"AAOA,SAAS,oBAAoB;AAGtB,SAAS,WAAW,KAA0D;AACnF,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,IAAI,IAAI,KAAK,EAAE,QAAQ,MAAM,EAAE;AACrC,QAAM,MAAM,EAAE,WAAW,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI;AACtE,MAAI,CAAC,mBAAmB,KAAK,GAAG,EAAG,QAAO;AAC1C,SAAO,CAAC,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE,CAAC;AACrG;AAGO,SAAS,SAAS,OAA2B,WAAW,WAAmB;AAChF,QAAM,MAAM,WAAW,KAAK;AAC5B,MAAI,CAAC,IAAK,QAAO;AACjB,SAAO,IAAI,IAAI,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AACrE;AAEA,SAAS,QAAQ,GAAmB;AAClC,QAAM,IAAI,IAAI;AACd,SAAO,KAAK,UAAU,IAAI,UAAU,IAAI,SAAS,UAAU;AAC7D;AAGO,SAAS,WAAW,KAAuC;AAChE,SAAO,SAAS,QAAQ,IAAI,CAAC,CAAC,IAAI,SAAS,QAAQ,IAAI,CAAC,CAAC,IAAI,SAAS,QAAQ,IAAI,CAAC,CAAC;AACtF;AAGO,SAAS,SAAS,GAAuB,GAAsC;AACpF,QAAM,KAAK,WAAW,CAAC;AACvB,QAAM,KAAK,WAAW,CAAC;AACvB,MAAI,CAAC,MAAM,CAAC,GAAI,QAAO;AACvB,QAAM,KAAK,WAAW,EAAE;AACxB,QAAM,KAAK,WAAW,EAAE;AACxB,QAAM,CAAC,OAAO,MAAM,IAAI,KAAK,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE;AACpD,UAAQ,QAAQ,SAAS,SAAS;AACpC;AAGO,SAAS,QAAQ,OAAkD;AAExE,SAAO,aAAa,KAAK,KAAK;AAChC;AAMO,SAAS,gBAAgB,OAAmF;AACjH,MAAI,UAAU,KAAM,QAAO;AAC3B,QAAM,IAAI,KAAK,MAAM,QAAQ,EAAE,IAAI;AACnC,MAAI,SAAS,IAAK,QAAO,EAAE,OAAO,YAAY,CAAC,2BAAsB,MAAM,OAAO;AAClF,MAAI,SAAS,EAAG,QAAO,EAAE,OAAO,YAAY,CAAC,sEAAiE,MAAM,QAAQ;AAC5H,SAAO,EAAE,OAAO,YAAY,CAAC,2DAAsD,MAAM,SAAS;AACpG;AAGO,MAAM,mBAA+G;AAAA,EAC1H,EAAE,IAAI,SAAS,OAAO,kCAA6B,YAAY,kCAAkC,SAAS,mFAAmF;AAAA,EAC7L,EAAE,IAAI,cAAc,OAAO,2CAAsC,YAAY,kCAAkC,aAAa,+BAA+B,SAAS,wGAAwG;AAAA,EAC5Q,EAAE,IAAI,WAAW,OAAO,qCAAgC,YAAY,oCAAoC,SAAS,qFAAqF;AAAA,EACtM,EAAE,IAAI,UAAU,OAAO,sCAAiC,YAAY,mCAAmC,SAAS,oFAAoF;AAAA,EACpM,EAAE,IAAI,eAAe,OAAO,6CAAwC,YAAY,0CAA0C,aAAa,0BAA0B,SAAS,gHAAgH;AAAA,EAC1R,EAAE,IAAI,YAAY,OAAO,2CAAsC,YAAY,kCAAkC,aAAa,sCAAsC,SAAS,gHAAgH;AAAA,EACzR,EAAE,IAAI,WAAW,OAAO,oCAA+B,YAAY,oCAAoC,SAAS,yFAAyF;AAAA,EACzM,EAAE,IAAI,WAAW,OAAO,kDAA6C,YAAY,4DAA4D,SAAS,GAAG;AAC3J;","names":[]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Leesbaarheid van Nederlandse tekst (8.5) — geïnspireerd op de analyse-tab van AstraCMS, maar voor
|
|
3
|
+
* het Nederlands: Flesch-Douma i.p.v. de Engelse Flesch Reading Ease, en niveaus in termen van
|
|
4
|
+
* taalniveau (B1 is de gangbare norm voor teksten voor een breed publiek). Puur, zonder DOM.
|
|
5
|
+
*
|
|
6
|
+
* score = 206,84 − 0,77 × (lettergrepen per 100 woorden) − 0,93 × (woorden per zin)
|
|
7
|
+
*
|
|
8
|
+
* De lettergreeptelling is een heuristiek (klinkergroepen, met trema als grens) — goed genoeg voor
|
|
9
|
+
* een indicatie, niet voor taalkundig onderzoek. Het paneel zegt dat er ook bij.
|
|
10
|
+
*/
|
|
11
|
+
export interface Leesbaarheid {
|
|
12
|
+
woorden: number;
|
|
13
|
+
zinnen: number;
|
|
14
|
+
woordenPerZin: number;
|
|
15
|
+
score: number;
|
|
16
|
+
niveau: {
|
|
17
|
+
naam: string;
|
|
18
|
+
uitleg: string;
|
|
19
|
+
toon: "goed" | "matig" | "slecht";
|
|
20
|
+
};
|
|
21
|
+
/** Minuten, naar boven afgerond (minimaal 1 bij tekst). */
|
|
22
|
+
leestijd: number;
|
|
23
|
+
tips: string[];
|
|
24
|
+
}
|
|
25
|
+
export declare function htmlNaarTekst(html: string): string;
|
|
26
|
+
export declare function lettergrepen(woord: string): number;
|
|
27
|
+
export declare function niveauVoor(score: number): Leesbaarheid["niveau"];
|
|
28
|
+
export declare function meetLeesbaarheid(tekst: string): Leesbaarheid;
|
|
29
|
+
/**
|
|
30
|
+
* De lopende tekst van een pagina uit zijn blokken (koppen, alinea's, kaartteksten), elk stuk als
|
|
31
|
+
* eigen "zin" — zodat een kop niet aan de volgende alinea vastgeplakt wordt. Adressen, sleutels en
|
|
32
|
+
* instellingen tellen niet mee.
|
|
33
|
+
*/
|
|
34
|
+
export declare function paginaTekst(blocks: unknown): string;
|