@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
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useMemo, useState } from "react";
|
|
4
|
+
import { subscribePages } from "../lib/pagesClient.js";
|
|
5
|
+
import { Dialog, DialogContent, DialogFooter } from "./dialog.js";
|
|
6
|
+
import { Button, Field, Input } from "./primitives.js";
|
|
7
|
+
import { Select } from "./select.js";
|
|
8
|
+
import { Switch } from "./switch.js";
|
|
9
|
+
function LinkDialog({
|
|
10
|
+
open,
|
|
11
|
+
onOpenChange,
|
|
12
|
+
siteId,
|
|
13
|
+
huidig,
|
|
14
|
+
huidigNieuwTabblad,
|
|
15
|
+
onKlaar
|
|
16
|
+
}) {
|
|
17
|
+
const [pages, setPages] = useState([]);
|
|
18
|
+
useEffect(() => open && siteId ? subscribePages(siteId, setPages) : void 0, [open, siteId]);
|
|
19
|
+
const [soort, setSoort] = useState("pagina");
|
|
20
|
+
const [pad, setPad] = useState("");
|
|
21
|
+
const [adres, setAdres] = useState("");
|
|
22
|
+
const [fout, setFout] = useState(null);
|
|
23
|
+
const [nieuwTabblad, setNieuwTabblad] = useState(false);
|
|
24
|
+
const [tabbladAangeraakt, setTabbladAangeraakt] = useState(false);
|
|
25
|
+
useEffect(() => {
|
|
26
|
+
if (!open) return;
|
|
27
|
+
setFout(null);
|
|
28
|
+
setTabbladAangeraakt(huidigNieuwTabblad !== void 0 && Boolean(huidig));
|
|
29
|
+
setNieuwTabblad(Boolean(huidigNieuwTabblad));
|
|
30
|
+
const h = huidig?.trim() ?? "";
|
|
31
|
+
if (siteId && (h === "" || h.startsWith("/") && !h.startsWith("//"))) {
|
|
32
|
+
setSoort("pagina");
|
|
33
|
+
setPad(h);
|
|
34
|
+
setAdres("");
|
|
35
|
+
} else {
|
|
36
|
+
setSoort("adres");
|
|
37
|
+
setPad("");
|
|
38
|
+
setAdres(h);
|
|
39
|
+
}
|
|
40
|
+
}, [open, huidig, siteId, huidigNieuwTabblad]);
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
if (!tabbladAangeraakt) setNieuwTabblad(soort === "adres" && !/^(mailto|tel):/i.test(adres.trim()));
|
|
43
|
+
}, [soort, adres, tabbladAangeraakt]);
|
|
44
|
+
const opties = useMemo(() => {
|
|
45
|
+
const o = pages.filter((p) => !p.trashed).sort((a, b) => a.path < b.path ? -1 : 1).map((p) => ({ value: p.path, label: `${p.title || p.path} (${p.path})${p.published ? "" : " \u2014 nog niet live"}` }));
|
|
46
|
+
if (pad && !o.some((x) => x.value === pad)) o.unshift({ value: pad, label: pad });
|
|
47
|
+
return o;
|
|
48
|
+
}, [pages, pad]);
|
|
49
|
+
function plaats() {
|
|
50
|
+
const href = soort === "pagina" ? pad : normaliseerAdres(adres);
|
|
51
|
+
if (!href) {
|
|
52
|
+
setFout(soort === "pagina" ? "Kies een pagina." : "Vul een webadres of e-mailadres in.");
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
onKlaar(href, { nieuwTabblad: nieuwTabblad && !/^(mailto|tel):/i.test(href) });
|
|
56
|
+
onOpenChange(false);
|
|
57
|
+
}
|
|
58
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx(DialogContent, { title: huidig ? "Link wijzigen" : "Link plaatsen", children: /* @__PURE__ */ jsxs(
|
|
59
|
+
"form",
|
|
60
|
+
{
|
|
61
|
+
className: "grid gap-3",
|
|
62
|
+
onSubmit: (e) => {
|
|
63
|
+
e.preventDefault();
|
|
64
|
+
plaats();
|
|
65
|
+
},
|
|
66
|
+
children: [
|
|
67
|
+
siteId && /* @__PURE__ */ jsx("div", { role: "radiogroup", "aria-label": "Soort link", className: "flex flex-wrap gap-2", children: [
|
|
68
|
+
["pagina", "Pagina op deze site"],
|
|
69
|
+
["adres", "Webadres of e-mail"]
|
|
70
|
+
].map(([k, label]) => /* @__PURE__ */ jsx(
|
|
71
|
+
"button",
|
|
72
|
+
{
|
|
73
|
+
type: "button",
|
|
74
|
+
role: "radio",
|
|
75
|
+
"aria-checked": soort === k,
|
|
76
|
+
onClick: () => setSoort(k),
|
|
77
|
+
className: "xicms-admin-btn rounded-lg border px-3 py-1.5 text-sm aria-[checked=true]:border-transparent aria-[checked=true]:bg-slate-900 aria-[checked=true]:text-white",
|
|
78
|
+
style: { borderColor: "var(--color-border)" },
|
|
79
|
+
children: label
|
|
80
|
+
},
|
|
81
|
+
k
|
|
82
|
+
)) }),
|
|
83
|
+
soort === "pagina" ? /* @__PURE__ */ jsx(Field, { label: "Pagina", children: /* @__PURE__ */ jsx(Select, { value: pad, onValueChange: setPad, options: opties, placeholder: "Kies een pagina\u2026" }) }) : /* @__PURE__ */ jsx(Field, { label: "Adres", hint: "bv. www.voorbeeld.nl of naam@voorbeeld.nl", children: /* @__PURE__ */ jsx(Input, { value: adres, onChange: (e) => setAdres(e.target.value), placeholder: "www.voorbeeld.nl", autoFocus: true }) }),
|
|
84
|
+
/* @__PURE__ */ jsx(
|
|
85
|
+
Switch,
|
|
86
|
+
{
|
|
87
|
+
checked: nieuwTabblad,
|
|
88
|
+
onCheckedChange: (v) => {
|
|
89
|
+
setTabbladAangeraakt(true);
|
|
90
|
+
setNieuwTabblad(v);
|
|
91
|
+
},
|
|
92
|
+
label: "Openen in een nieuw tabblad"
|
|
93
|
+
}
|
|
94
|
+
),
|
|
95
|
+
fout && /* @__PURE__ */ jsx("p", { role: "alert", className: "text-sm text-red-700", children: fout }),
|
|
96
|
+
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
97
|
+
huidig && /* @__PURE__ */ jsx(
|
|
98
|
+
Button,
|
|
99
|
+
{
|
|
100
|
+
type: "button",
|
|
101
|
+
variant: "dangerGhost",
|
|
102
|
+
className: "mr-auto",
|
|
103
|
+
onClick: () => {
|
|
104
|
+
onKlaar(null);
|
|
105
|
+
onOpenChange(false);
|
|
106
|
+
},
|
|
107
|
+
children: "Link weghalen"
|
|
108
|
+
}
|
|
109
|
+
),
|
|
110
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", onClick: () => onOpenChange(false), children: "Annuleren" }),
|
|
111
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", children: huidig ? "Wijzigen" : "Link plaatsen" })
|
|
112
|
+
] })
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
) }) });
|
|
116
|
+
}
|
|
117
|
+
function normaliseerAdres(ruw) {
|
|
118
|
+
const a = ruw.trim();
|
|
119
|
+
if (!a) return "";
|
|
120
|
+
if (/^(javascript|data|vbscript):/i.test(a)) return "";
|
|
121
|
+
if (/^(https?:|mailto:|tel:)/i.test(a)) return a;
|
|
122
|
+
if (a.startsWith("/") || a.startsWith("#")) return a;
|
|
123
|
+
if (/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(a)) return `mailto:${a}`;
|
|
124
|
+
if (/^\+?[\d\s()-]{6,}$/.test(a)) return `tel:${a.replace(/[^\d+]/g, "")}`;
|
|
125
|
+
return `https://${a}`;
|
|
126
|
+
}
|
|
127
|
+
export {
|
|
128
|
+
LinkDialog,
|
|
129
|
+
normaliseerAdres
|
|
130
|
+
};
|
|
131
|
+
//# sourceMappingURL=LinkDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/ui/LinkDialog.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { subscribePages, type DraftPage } from \"../lib/pagesClient\";\nimport { Dialog, DialogContent, DialogFooter } from \"./dialog\";\nimport { Button, Field, Input } from \"./primitives\";\nimport { Select } from \"./select\";\nimport { Switch } from \"./switch\";\n\n/**\n * Link plaatsen of wijzigen (8.2). Verving `window.prompt(\"Link-URL\")` in de inline editor en de\n * rich-text-editor: geen keuze uit eigen pagina's (dus typefouten → 404), niet te stijlen, en op\n * een telefoon nauwelijks bruikbaar. Hier kies je een pagina van de site, of typ je een webadres\n * of e-mailadres; \"www.voorbeeld.nl\" wordt vanzelf \"https://www.voorbeeld.nl\".\n */\nexport function LinkDialog({\n open,\n onOpenChange,\n siteId,\n huidig,\n huidigNieuwTabblad,\n onKlaar,\n}: {\n open: boolean;\n onOpenChange: (v: boolean) => void;\n /** Zonder siteId (bv. een editor buiten een site) alleen het webadres-tabblad. */\n siteId?: string;\n /** De link die er nu staat (leeg = nieuwe link). */\n huidig?: string;\n /** Opende de bestaande link in een nieuw tabblad? */\n huidigNieuwTabblad?: boolean;\n /** `null` = link weghalen. */\n onKlaar: (href: string | null, opties?: { nieuwTabblad: boolean }) => void;\n}) {\n const [pages, setPages] = useState<DraftPage[]>([]);\n useEffect(() => (open && siteId ? subscribePages(siteId, setPages) : undefined), [open, siteId]);\n\n const [soort, setSoort] = useState<\"pagina\" | \"adres\">(\"pagina\");\n const [pad, setPad] = useState(\"\");\n const [adres, setAdres] = useState(\"\");\n const [fout, setFout] = useState<string | null>(null);\n /**\n * In een nieuw tabblad openen (8.5, naar het voorbeeld van AstraCMS' linkvenster). Standaard: aan\n * voor een link naar een andere site, uit voor een eigen pagina — zelf om te zetten.\n */\n const [nieuwTabblad, setNieuwTabblad] = useState(false);\n const [tabbladAangeraakt, setTabbladAangeraakt] = useState(false);\n\n // Bij openen: de bestaande link in het juiste tabblad zetten.\n useEffect(() => {\n if (!open) return;\n setFout(null);\n setTabbladAangeraakt(huidigNieuwTabblad !== undefined && Boolean(huidig));\n setNieuwTabblad(Boolean(huidigNieuwTabblad));\n const h = huidig?.trim() ?? \"\";\n if (siteId && (h === \"\" || (h.startsWith(\"/\") && !h.startsWith(\"//\")))) {\n setSoort(\"pagina\");\n setPad(h);\n setAdres(\"\");\n } else {\n setSoort(\"adres\");\n setPad(\"\");\n setAdres(h);\n }\n }, [open, huidig, siteId, huidigNieuwTabblad]);\n\n // Volgt de soort, tot de gebruiker de schakelaar zelf omzet.\n useEffect(() => {\n if (!tabbladAangeraakt) setNieuwTabblad(soort === \"adres\" && !/^(mailto|tel):/i.test(adres.trim()));\n }, [soort, adres, tabbladAangeraakt]);\n\n const opties = useMemo(() => {\n const o = pages\n .filter((p) => !p.trashed)\n .sort((a, b) => (a.path < b.path ? -1 : 1))\n .map((p) => ({ value: p.path, label: `${p.title || p.path} (${p.path})${p.published ? \"\" : \" — nog niet live\"}` }));\n if (pad && !o.some((x) => x.value === pad)) o.unshift({ value: pad, label: pad });\n return o;\n }, [pages, pad]);\n\n function plaats() {\n const href = soort === \"pagina\" ? pad : normaliseerAdres(adres);\n if (!href) {\n setFout(soort === \"pagina\" ? \"Kies een pagina.\" : \"Vul een webadres of e-mailadres in.\");\n return;\n }\n onKlaar(href, { nieuwTabblad: nieuwTabblad && !/^(mailto|tel):/i.test(href) });\n onOpenChange(false);\n }\n\n return (\n <Dialog open={open} onOpenChange={onOpenChange}>\n <DialogContent title={huidig ? \"Link wijzigen\" : \"Link plaatsen\"}>\n <form\n className=\"grid gap-3\"\n onSubmit={(e) => {\n e.preventDefault();\n plaats();\n }}\n >\n {siteId && (\n <div role=\"radiogroup\" aria-label=\"Soort link\" className=\"flex flex-wrap gap-2\">\n {(\n [\n [\"pagina\", \"Pagina op deze site\"],\n [\"adres\", \"Webadres of e-mail\"],\n ] as const\n ).map(([k, label]) => (\n <button\n key={k}\n type=\"button\"\n role=\"radio\"\n aria-checked={soort === k}\n onClick={() => setSoort(k)}\n className=\"xicms-admin-btn rounded-lg border px-3 py-1.5 text-sm aria-[checked=true]:border-transparent aria-[checked=true]:bg-slate-900 aria-[checked=true]:text-white\"\n style={{ borderColor: \"var(--color-border)\" }}\n >\n {label}\n </button>\n ))}\n </div>\n )}\n {soort === \"pagina\" ? (\n <Field label=\"Pagina\">\n <Select value={pad} onValueChange={setPad} options={opties} placeholder=\"Kies een pagina…\" />\n </Field>\n ) : (\n <Field label=\"Adres\" hint=\"bv. www.voorbeeld.nl of naam@voorbeeld.nl\">\n <Input value={adres} onChange={(e) => setAdres(e.target.value)} placeholder=\"www.voorbeeld.nl\" autoFocus />\n </Field>\n )}\n <Switch\n checked={nieuwTabblad}\n onCheckedChange={(v) => {\n setTabbladAangeraakt(true);\n setNieuwTabblad(v);\n }}\n label=\"Openen in een nieuw tabblad\"\n />\n {fout && (\n <p role=\"alert\" className=\"text-sm text-red-700\">\n {fout}\n </p>\n )}\n <DialogFooter>\n {huidig && (\n <Button\n type=\"button\"\n variant=\"dangerGhost\"\n className=\"mr-auto\"\n onClick={() => {\n onKlaar(null);\n onOpenChange(false);\n }}\n >\n Link weghalen\n </Button>\n )}\n <Button type=\"button\" variant=\"secondary\" onClick={() => onOpenChange(false)}>\n Annuleren\n </Button>\n <Button type=\"submit\">{huidig ? \"Wijzigen\" : \"Link plaatsen\"}</Button>\n </DialogFooter>\n </form>\n </DialogContent>\n </Dialog>\n );\n}\n\n/** \"www.x.nl\" → \"https://www.x.nl\", \"a@b.nl\" → \"mailto:a@b.nl\"; gevaarlijke schema's weigeren. */\nexport function normaliseerAdres(ruw: string): string {\n const a = ruw.trim();\n if (!a) return \"\";\n if (/^(javascript|data|vbscript):/i.test(a)) return \"\";\n if (/^(https?:|mailto:|tel:)/i.test(a)) return a;\n if (a.startsWith(\"/\") || a.startsWith(\"#\")) return a;\n if (/^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(a)) return `mailto:${a}`;\n if (/^\\+?[\\d\\s()-]{6,}$/.test(a)) return `tel:${a.replace(/[^\\d+]/g, \"\")}`;\n return `https://${a}`;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Een linkveld zoals een klant het leest (8.10): "Contact (/contact)" of "www.voorbeeld.nl", met
|
|
3
|
+
* "Kies…" ernaast dat het linkvenster opent — pagina uit de lijst, of een webadres/e-mail/telefoon.
|
|
4
|
+
*
|
|
5
|
+
* Vervangt de kale tekstvakken bij knoppen in de hero, de oproepbalk, de footer en de automatisch
|
|
6
|
+
* gegenereerde formulieren. Daar typte je "/contakt" of liet je "#" staan, en de knop deed niets of
|
|
7
|
+
* gaf een 404; de controle vóór publiceren ving dat pas achteraf.
|
|
8
|
+
*/
|
|
9
|
+
export declare function LinkVeld({ siteId, value, onChange, leegTekst, }: {
|
|
10
|
+
siteId?: string;
|
|
11
|
+
value: string | undefined;
|
|
12
|
+
onChange: (href: string) => void;
|
|
13
|
+
leegTekst?: string;
|
|
14
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { subscribePages } from "../lib/pagesClient.js";
|
|
5
|
+
import { LinkDialog } from "./LinkDialog.js";
|
|
6
|
+
import { Button } from "./primitives.js";
|
|
7
|
+
function LinkVeld({
|
|
8
|
+
siteId,
|
|
9
|
+
value,
|
|
10
|
+
onChange,
|
|
11
|
+
leegTekst = "Nog geen link"
|
|
12
|
+
}) {
|
|
13
|
+
const [open, setOpen] = useState(false);
|
|
14
|
+
const [pages, setPages] = useState([]);
|
|
15
|
+
useEffect(() => siteId ? subscribePages(siteId, setPages) : void 0, [siteId]);
|
|
16
|
+
const href = (value ?? "").trim();
|
|
17
|
+
const pagina = href.startsWith("/") ? pages.find((p) => !p.trashed && p.path === href.split(/[?#]/)[0]) : void 0;
|
|
18
|
+
const leeg = !href || href === "#";
|
|
19
|
+
const tekst = leeg ? leegTekst : pagina ? `${pagina.title || pagina.path} (${href})` : href.replace(/^https?:\/\//, "").replace(/^mailto:/, "e-mail: ").replace(/^tel:/, "bel: ");
|
|
20
|
+
const waarschuwing = pagina && !pagina.published ? "Deze pagina staat nog niet live." : null;
|
|
21
|
+
return /* @__PURE__ */ jsxs("div", { className: "grid gap-1", children: [
|
|
22
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-2", children: [
|
|
23
|
+
/* @__PURE__ */ jsx(
|
|
24
|
+
"span",
|
|
25
|
+
{
|
|
26
|
+
className: `min-w-0 flex-1 truncate rounded-md border border-slate-200 bg-white px-2.5 py-1.5 text-sm ${leeg ? "text-slate-500 italic" : "text-slate-800"}`,
|
|
27
|
+
title: href || void 0,
|
|
28
|
+
children: tekst
|
|
29
|
+
}
|
|
30
|
+
),
|
|
31
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", variant: "secondary", onClick: () => setOpen(true), children: leeg ? "Kies\u2026" : "Wijzig\u2026" })
|
|
32
|
+
] }),
|
|
33
|
+
waarschuwing && /* @__PURE__ */ jsx("p", { className: "text-xs text-amber-700", children: waarschuwing }),
|
|
34
|
+
/* @__PURE__ */ jsx(
|
|
35
|
+
LinkDialog,
|
|
36
|
+
{
|
|
37
|
+
open,
|
|
38
|
+
onOpenChange: setOpen,
|
|
39
|
+
siteId,
|
|
40
|
+
huidig: leeg ? "" : href,
|
|
41
|
+
onKlaar: (nieuw) => onChange(nieuw ?? "")
|
|
42
|
+
}
|
|
43
|
+
)
|
|
44
|
+
] });
|
|
45
|
+
}
|
|
46
|
+
export {
|
|
47
|
+
LinkVeld
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=LinkVeld.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/ui/LinkVeld.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { subscribePages, type DraftPage } from \"../lib/pagesClient\";\nimport { LinkDialog } from \"./LinkDialog\";\nimport { Button } from \"./primitives\";\n\n/**\n * Een linkveld zoals een klant het leest (8.10): \"Contact (/contact)\" of \"www.voorbeeld.nl\", met\n * \"Kies…\" ernaast dat het linkvenster opent — pagina uit de lijst, of een webadres/e-mail/telefoon.\n *\n * Vervangt de kale tekstvakken bij knoppen in de hero, de oproepbalk, de footer en de automatisch\n * gegenereerde formulieren. Daar typte je \"/contakt\" of liet je \"#\" staan, en de knop deed niets of\n * gaf een 404; de controle vóór publiceren ving dat pas achteraf.\n */\nexport function LinkVeld({\n siteId,\n value,\n onChange,\n leegTekst = \"Nog geen link\",\n}: {\n siteId?: string;\n value: string | undefined;\n onChange: (href: string) => void;\n leegTekst?: string;\n}) {\n const [open, setOpen] = useState(false);\n const [pages, setPages] = useState<DraftPage[]>([]);\n useEffect(() => (siteId ? subscribePages(siteId, setPages) : undefined), [siteId]);\n\n const href = (value ?? \"\").trim();\n const pagina = href.startsWith(\"/\") ? pages.find((p) => !p.trashed && p.path === href.split(/[?#]/)[0]) : undefined;\n const leeg = !href || href === \"#\";\n const tekst = leeg\n ? leegTekst\n : pagina\n ? `${pagina.title || pagina.path} (${href})`\n : href.replace(/^https?:\\/\\//, \"\").replace(/^mailto:/, \"e-mail: \").replace(/^tel:/, \"bel: \");\n // Alleen \"nog niet live\": een pad zonder werkversie kan best bestaan (een pagina uit de sitecode,\n // de webwinkel, de demo) — \"bestaat niet\" zou dan een valse schrik zijn.\n const waarschuwing = pagina && !pagina.published ? \"Deze pagina staat nog niet live.\" : null;\n\n return (\n <div className=\"grid gap-1\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span\n className={`min-w-0 flex-1 truncate rounded-md border border-slate-200 bg-white px-2.5 py-1.5 text-sm ${leeg ? \"text-slate-500 italic\" : \"text-slate-800\"}`}\n title={href || undefined}\n >\n {tekst}\n </span>\n <Button size=\"sm\" variant=\"secondary\" onClick={() => setOpen(true)}>\n {leeg ? \"Kies…\" : \"Wijzig…\"}\n </Button>\n </div>\n {waarschuwing && <p className=\"text-xs text-amber-700\">{waarschuwing}</p>}\n <LinkDialog\n open={open}\n onOpenChange={setOpen}\n siteId={siteId}\n huidig={leeg ? \"\" : href}\n onKlaar={(nieuw) => onChange(nieuw ?? \"\")}\n />\n </div>\n );\n}\n"],"mappings":";AA4CM,SACE,KADF;AA1CN,SAAS,WAAW,gBAAgB;AACpC,SAAS,sBAAsC;AAC/C,SAAS,kBAAkB;AAC3B,SAAS,cAAc;AAUhB,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AACd,GAKG;AACD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,KAAK;AACtC,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAsB,CAAC,CAAC;AAClD,YAAU,MAAO,SAAS,eAAe,QAAQ,QAAQ,IAAI,QAAY,CAAC,MAAM,CAAC;AAEjF,QAAM,QAAQ,SAAS,IAAI,KAAK;AAChC,QAAM,SAAS,KAAK,WAAW,GAAG,IAAI,MAAM,KAAK,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,SAAS,KAAK,MAAM,MAAM,EAAE,CAAC,CAAC,IAAI;AAC1G,QAAM,OAAO,CAAC,QAAQ,SAAS;AAC/B,QAAM,QAAQ,OACV,YACA,SACE,GAAG,OAAO,SAAS,OAAO,IAAI,KAAK,IAAI,MACvC,KAAK,QAAQ,gBAAgB,EAAE,EAAE,QAAQ,YAAY,UAAU,EAAE,QAAQ,SAAS,OAAO;AAG/F,QAAM,eAAe,UAAU,CAAC,OAAO,YAAY,qCAAqC;AAExF,SACE,qBAAC,SAAI,WAAU,cACb;AAAA,yBAAC,SAAI,WAAU,mCACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,6FAA6F,OAAO,0BAA0B,gBAAgB;AAAA,UACzJ,OAAO,QAAQ;AAAA,UAEd;AAAA;AAAA,MACH;AAAA,MACA,oBAAC,UAAO,MAAK,MAAK,SAAQ,aAAY,SAAS,MAAM,QAAQ,IAAI,GAC9D,iBAAO,eAAU,gBACpB;AAAA,OACF;AAAA,IACC,gBAAgB,oBAAC,OAAE,WAAU,0BAA0B,wBAAa;AAAA,IACrE;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA,cAAc;AAAA,QACd;AAAA,QACA,QAAQ,OAAO,KAAK;AAAA,QACpB,SAAS,CAAC,UAAU,SAAS,SAAS,EAAE;AAAA;AAAA,IAC1C;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface PreviewLink {
|
|
2
|
+
url: string;
|
|
3
|
+
/** Epoch-ms; ontbreekt bij een oude functions-versie. */
|
|
4
|
+
expiresAt?: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Gedeelde weergave van een gemaakte preview-link (8.5): adres, kopiëren, openen, delen
|
|
8
|
+
* (telefoon: WhatsApp/mail via het deelmenu) en tot wanneer hij werkt. Eerst stond er alleen
|
|
9
|
+
* een los invoerveld en moest de klant zelf selecteren en kopiëren.
|
|
10
|
+
*/
|
|
11
|
+
export declare function PreviewLinkResultaat({ link, titel }: {
|
|
12
|
+
link: PreviewLink;
|
|
13
|
+
titel?: string;
|
|
14
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { Button, Input } from "./primitives.js";
|
|
5
|
+
import { useToast } from "./toast.js";
|
|
6
|
+
function PreviewLinkResultaat({ link, titel }) {
|
|
7
|
+
const { toast } = useToast();
|
|
8
|
+
const [gekopieerd, setGekopieerd] = useState(false);
|
|
9
|
+
const kanDelen = typeof navigator !== "undefined" && typeof navigator.share === "function";
|
|
10
|
+
const tot = link.expiresAt ? new Date(link.expiresAt).toLocaleString("nl-NL", { weekday: "long", day: "numeric", month: "long", hour: "2-digit", minute: "2-digit" }) : null;
|
|
11
|
+
async function kopieer() {
|
|
12
|
+
try {
|
|
13
|
+
await navigator.clipboard.writeText(link.url);
|
|
14
|
+
setGekopieerd(true);
|
|
15
|
+
setTimeout(() => setGekopieerd(false), 2e3);
|
|
16
|
+
} catch {
|
|
17
|
+
toast({ title: "Kopi\xEBren lukte niet", description: "Selecteer het adres en kopieer het zelf.", tone: "error" });
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
async function deel() {
|
|
21
|
+
try {
|
|
22
|
+
await navigator.share({ title: titel ? `Voorbeeld: ${titel}` : "Voorbeeld van de website", url: link.url });
|
|
23
|
+
} catch {
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
27
|
+
/* @__PURE__ */ jsx(
|
|
28
|
+
Input,
|
|
29
|
+
{
|
|
30
|
+
readOnly: true,
|
|
31
|
+
value: link.url,
|
|
32
|
+
"aria-label": "Voorbeeldlink",
|
|
33
|
+
className: "min-w-0 text-xs",
|
|
34
|
+
onFocus: (e) => e.currentTarget.select()
|
|
35
|
+
}
|
|
36
|
+
),
|
|
37
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-1", children: [
|
|
38
|
+
/* @__PURE__ */ jsx(Button, { variant: "secondary", size: "sm", onClick: () => void kopieer(), children: gekopieerd ? "\u2713 Gekopieerd" : "Kopi\xEBren" }),
|
|
39
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: () => window.open(link.url, "_blank", "noopener"), children: "Openen \u2197" }),
|
|
40
|
+
kanDelen && /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: () => void deel(), children: "Delen\u2026" })
|
|
41
|
+
] }),
|
|
42
|
+
tot && /* @__PURE__ */ jsxs("p", { className: "text-xs text-slate-500", children: [
|
|
43
|
+
"Werkt tot ",
|
|
44
|
+
tot,
|
|
45
|
+
". Daarna maak je eenvoudig een nieuwe."
|
|
46
|
+
] })
|
|
47
|
+
] });
|
|
48
|
+
}
|
|
49
|
+
export {
|
|
50
|
+
PreviewLinkResultaat
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=PreviewLinkResultaat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/ui/PreviewLinkResultaat.tsx"],"sourcesContent":["\"use client\";\n\nimport { useState } from \"react\";\nimport { Button, Input } from \"./primitives\";\nimport { useToast } from \"./toast\";\n\nexport interface PreviewLink {\n url: string;\n /** Epoch-ms; ontbreekt bij een oude functions-versie. */\n expiresAt?: number;\n}\n\n/**\n * Gedeelde weergave van een gemaakte preview-link (8.5): adres, kopiëren, openen, delen\n * (telefoon: WhatsApp/mail via het deelmenu) en tot wanneer hij werkt. Eerst stond er alleen\n * een los invoerveld en moest de klant zelf selecteren en kopiëren.\n */\nexport function PreviewLinkResultaat({ link, titel }: { link: PreviewLink; titel?: string }) {\n const { toast } = useToast();\n const [gekopieerd, setGekopieerd] = useState(false);\n const kanDelen = typeof navigator !== \"undefined\" && typeof navigator.share === \"function\";\n const tot = link.expiresAt\n ? new Date(link.expiresAt).toLocaleString(\"nl-NL\", { weekday: \"long\", day: \"numeric\", month: \"long\", hour: \"2-digit\", minute: \"2-digit\" })\n : null;\n\n async function kopieer() {\n try {\n await navigator.clipboard.writeText(link.url);\n setGekopieerd(true);\n setTimeout(() => setGekopieerd(false), 2000);\n } catch {\n toast({ title: \"Kopiëren lukte niet\", description: \"Selecteer het adres en kopieer het zelf.\", tone: \"error\" });\n }\n }\n\n async function deel() {\n try {\n await navigator.share({ title: titel ? `Voorbeeld: ${titel}` : \"Voorbeeld van de website\", url: link.url });\n } catch {\n /* geannuleerd */\n }\n }\n\n return (\n <div className=\"grid gap-2\">\n <Input\n readOnly\n value={link.url}\n aria-label=\"Voorbeeldlink\"\n className=\"min-w-0 text-xs\"\n onFocus={(e) => e.currentTarget.select()}\n />\n <div className=\"flex flex-wrap gap-1\">\n <Button variant=\"secondary\" size=\"sm\" onClick={() => void kopieer()}>\n {gekopieerd ? \"✓ Gekopieerd\" : \"Kopiëren\"}\n </Button>\n <Button variant=\"ghost\" size=\"sm\" onClick={() => window.open(link.url, \"_blank\", \"noopener\")}>\n Openen ↗\n </Button>\n {kanDelen && (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void deel()}>\n Delen…\n </Button>\n )}\n </div>\n {tot && <p className=\"text-xs text-slate-500\">Werkt tot {tot}. Daarna maak je eenvoudig een nieuwe.</p>}\n </div>\n );\n}\n"],"mappings":";AA6CM,cAOA,YAPA;AA3CN,SAAS,gBAAgB;AACzB,SAAS,QAAQ,aAAa;AAC9B,SAAS,gBAAgB;AAalB,SAAS,qBAAqB,EAAE,MAAM,MAAM,GAA0C;AAC3F,QAAM,EAAE,MAAM,IAAI,SAAS;AAC3B,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,WAAW,OAAO,cAAc,eAAe,OAAO,UAAU,UAAU;AAChF,QAAM,MAAM,KAAK,YACb,IAAI,KAAK,KAAK,SAAS,EAAE,eAAe,SAAS,EAAE,SAAS,QAAQ,KAAK,WAAW,OAAO,QAAQ,MAAM,WAAW,QAAQ,UAAU,CAAC,IACvI;AAEJ,iBAAe,UAAU;AACvB,QAAI;AACF,YAAM,UAAU,UAAU,UAAU,KAAK,GAAG;AAC5C,oBAAc,IAAI;AAClB,iBAAW,MAAM,cAAc,KAAK,GAAG,GAAI;AAAA,IAC7C,QAAQ;AACN,YAAM,EAAE,OAAO,0BAAuB,aAAa,4CAA4C,MAAM,QAAQ,CAAC;AAAA,IAChH;AAAA,EACF;AAEA,iBAAe,OAAO;AACpB,QAAI;AACF,YAAM,UAAU,MAAM,EAAE,OAAO,QAAQ,cAAc,KAAK,KAAK,4BAA4B,KAAK,KAAK,IAAI,CAAC;AAAA,IAC5G,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SACE,qBAAC,SAAI,WAAU,cACb;AAAA;AAAA,MAAC;AAAA;AAAA,QACC,UAAQ;AAAA,QACR,OAAO,KAAK;AAAA,QACZ,cAAW;AAAA,QACX,WAAU;AAAA,QACV,SAAS,CAAC,MAAM,EAAE,cAAc,OAAO;AAAA;AAAA,IACzC;AAAA,IACA,qBAAC,SAAI,WAAU,wBACb;AAAA,0BAAC,UAAO,SAAQ,aAAY,MAAK,MAAK,SAAS,MAAM,KAAK,QAAQ,GAC/D,uBAAa,sBAAiB,eACjC;AAAA,MACA,oBAAC,UAAO,SAAQ,SAAQ,MAAK,MAAK,SAAS,MAAM,OAAO,KAAK,KAAK,KAAK,UAAU,UAAU,GAAG,2BAE9F;AAAA,MACC,YACC,oBAAC,UAAO,SAAQ,SAAQ,MAAK,MAAK,SAAS,MAAM,KAAK,KAAK,GAAG,yBAE9D;AAAA,OAEJ;AAAA,IACC,OAAO,qBAAC,OAAE,WAAU,0BAAyB;AAAA;AAAA,MAAW;AAAA,MAAI;AAAA,OAAsC;AAAA,KACrG;AAEJ;","names":[]}
|
package/dist/admin/ui/charts.js
CHANGED
|
@@ -99,7 +99,7 @@ function DagStaven({
|
|
|
99
99
|
},
|
|
100
100
|
i
|
|
101
101
|
)) }),
|
|
102
|
-
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-x-0", style: { top: plotH + 3 }, children: [0, 9, 19, n - 1].filter((v, i, a) => v >= 0 && v < n && a.indexOf(v) === i).map((i) => /* @__PURE__ */ jsx("span", { className: "absolute -translate-x-1/2 text-[10px] text-slate-
|
|
102
|
+
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-x-0", style: { top: plotH + 3 }, children: [0, 9, 19, n - 1].filter((v, i, a) => v >= 0 && v < n && a.indexOf(v) === i).map((i) => /* @__PURE__ */ jsx("span", { className: "absolute -translate-x-1/2 text-[10px] text-slate-500", style: { left: `${(i + 0.5) / n * 100}%` }, children: i + 1 }, i)) }),
|
|
103
103
|
maxWaarde > 0 && hover === null && /* @__PURE__ */ jsx(
|
|
104
104
|
"span",
|
|
105
105
|
{
|
|
@@ -109,7 +109,7 @@ function DagStaven({
|
|
|
109
109
|
children: nf.format(maxWaarde)
|
|
110
110
|
}
|
|
111
111
|
),
|
|
112
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute -top-0.5 right-0 bg-white pl-1 text-[10px] text-slate-
|
|
112
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute -top-0.5 right-0 bg-white pl-1 text-[10px] text-slate-500", style: { fontVariantNumeric: "tabular-nums" }, children: nf.format(max) })
|
|
113
113
|
] });
|
|
114
114
|
}
|
|
115
115
|
function MaandLijn({
|
|
@@ -167,7 +167,7 @@ function MaandLijn({
|
|
|
167
167
|
/* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "pointer-events-none absolute inset-x-0", style: { top: plotH + 3 }, children: [0, Math.floor((n - 1) / 2), n - 1].filter((v, i, a) => a.indexOf(v) === i).map((i) => /* @__PURE__ */ jsx(
|
|
168
168
|
"span",
|
|
169
169
|
{
|
|
170
|
-
className: "absolute text-[10px] text-slate-
|
|
170
|
+
className: "absolute text-[10px] text-slate-500",
|
|
171
171
|
style: { left: `${px(i)}%`, transform: i === 0 ? "none" : i === n - 1 ? "translateX(-100%)" : "translateX(-50%)" },
|
|
172
172
|
children: punten[i].label
|
|
173
173
|
},
|
|
@@ -182,7 +182,7 @@ function MaandLijn({
|
|
|
182
182
|
children: nf.format(punten[n - 1].waarde)
|
|
183
183
|
}
|
|
184
184
|
),
|
|
185
|
-
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute -top-0.5 right-0 bg-white pl-1 text-[10px] text-slate-
|
|
185
|
+
/* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "pointer-events-none absolute -top-0.5 right-0 bg-white pl-1 text-[10px] text-slate-500", style: { fontVariantNumeric: "tabular-nums" }, children: nf.format(max) })
|
|
186
186
|
] });
|
|
187
187
|
}
|
|
188
188
|
function BalkjesLijst({ items }) {
|
|
@@ -216,7 +216,7 @@ function StatTegel({
|
|
|
216
216
|
}
|
|
217
217
|
function AlsTabel({ kop, rijen }) {
|
|
218
218
|
return /* @__PURE__ */ jsxs("details", { className: "mt-2", children: [
|
|
219
|
-
/* @__PURE__ */ jsx("summary", { className: "cursor-pointer text-xs text-slate-
|
|
219
|
+
/* @__PURE__ */ jsx("summary", { className: "cursor-pointer text-xs text-slate-500 hover:text-slate-600", children: "Bekijk als tabel" }),
|
|
220
220
|
/* @__PURE__ */ jsxs("table", { className: "mt-2 w-full text-sm", children: [
|
|
221
221
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "text-left text-xs text-slate-500", children: [
|
|
222
222
|
/* @__PURE__ */ jsx("th", { className: "py-1 font-medium", children: kop[0] }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/ui/charts.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * Lichte grafieken voor het beheer (7.17) — geen chart-library: dit is een editor-chunk en\n * drie vormen (kolommen, lijn, balkjeslijst) rechtvaardigen geen dependency in elke klantsite.\n *\n * Vaste GEREEDSCHAPSKLEUREN, bewust niet de merkkleur: `--color-brand` volgt `--xicms-primary`\n * van de klant en kan licht zijn (goud, lime) — dan verdwijnen de staven op een witte kaart.\n * Dit blauwpaar is met de dataviz-validator doorgerekend op wit (lichtheid, chroma, CVD-ΔE 18.9,\n * normaal-zicht-ΔE 19.2, contrast ≥ 3:1 — alles groen). Zelfde filosofie als de editor-balk:\n * gereedschap ziet er op elke site hetzelfde uit.\n *\n * Vormregels die hier vastliggen (dataviz-methode):\n * - kolommen: ronde datakant (4px), vlakke voet op de basislijn, ≤ 24px dik, 2px lucht ertussen;\n * - lijn: 2px met ronde joins, vulling als wash (10%), punten ≥ 8px met witte ring;\n * - raster: haarlijnen één stap van het oppervlak af, nooit gestreept, recessief;\n * - tekst draagt tekstkleuren, nooit de seriekleur — identiteit zit in de mark ernaast;\n * - hover hoort erbij: ruime hit-zones met tooltip, en alles wat de tooltip toont is óók\n * zonder muis bereikbaar (as-ticks, selectieve labels, de tabel-uitklapper).\n *\n * Bewust HTML-marks (divs) waar het kan: een SVG met `preserveAspectRatio=\"none\"` schaalt\n * niet-uniform, waardoor rondingen en cirkels vervormen — divs met border-radius blijven\n * pixel-zuiver op elke kaartbreedte. Alleen het lijnpad zelf is SVG (met non-scaling-stroke).\n */\nimport { useId, useRef, useState } from \"react\";\n\nexport const CHART = {\n serie: \"#3987e5\",\n accent: \"#184f95\",\n wash: \"rgba(57, 135, 229, 0.10)\",\n track: \"#e9f1fc\",\n grid: \"#e2e8f0\",\n as: \"#cbd5e1\",\n} as const;\n\nconst nf = new Intl.NumberFormat(\"nl-NL\");\n\n/** Nette bovengrens voor de y-as (1/2/5 × macht van 10), zodat de schaal-tick rond is. */\nfunction netteMax(max: number): number {\n if (max <= 4) return 4;\n const macht = 10 ** Math.floor(Math.log10(max));\n for (const f of [1, 2, 5, 10]) if (max <= f * macht) return f * macht;\n return 10 * macht;\n}\n\ninterface TooltipStand {\n x: number;\n y: number;\n titel: string;\n waarde: number;\n}\n\n/** Zwevende uitlezing. Waarde voorop en zwaar, label secundair — de lezer wil het getal. */\nfunction Tooltip({ t }: { t: TooltipStand | null }) {\n if (!t) return null;\n return (\n <div\n className=\"pointer-events-none absolute z-10 rounded-lg border border-slate-200 bg-white px-2.5 py-1.5 whitespace-nowrap shadow-md\"\n style={{ left: t.x, top: Math.max(26, t.y), transform: \"translate(-50%, calc(-100% - 8px))\" }}\n role=\"status\"\n >\n <span className=\"text-sm font-semibold text-slate-900\">{nf.format(t.waarde)}</span>\n <span className=\"ml-1.5 text-xs text-slate-500\">{t.titel}</span>\n </div>\n );\n}\n\n/** Recessief raster: haarlijnen op 50% en 100% van de schaal + de basislijn. */\nfunction Raster({ plotH }: { plotH: number }) {\n return (\n <div aria-hidden=\"true\" className=\"pointer-events-none absolute inset-x-0 top-0\" style={{ height: plotH }}>\n <div className=\"absolute inset-x-0\" style={{ top: 0, borderTop: `1px solid ${CHART.grid}` }} />\n <div className=\"absolute inset-x-0\" style={{ top: plotH / 2, borderTop: `1px solid ${CHART.grid}` }} />\n <div className=\"absolute inset-x-0\" style={{ top: plotH, borderTop: `1px solid ${CHART.as}` }} />\n </div>\n );\n}\n\n/**\n * Kolomgrafiek voor één maand: dag 1..N. `accentIndex` (bv. vandaag) kleurt één kolom in de\n * donkere stap van dezelfde ramp — zelfde reeks, gemarkeerd, geen tweede kleur.\n */\nexport function DagStaven({\n waarden,\n accentIndex,\n hoogte = 150,\n titel,\n labelVan,\n}: {\n /** Waarde per dag, index 0 = dag 1. */\n waarden: number[];\n accentIndex?: number;\n hoogte?: number;\n titel: string;\n /** Tooltiplabel per index (standaard \"dag N\"). */\n labelVan?: (i: number) => string;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const [tip, setTip] = useState<TooltipStand | null>(null);\n const [hover, setHover] = useState<number | null>(null);\n const uid = useId();\n\n const n = Math.max(1, waarden.length);\n const max = netteMax(Math.max(1, ...waarden));\n const plotH = hoogte - 18;\n const maxWaarde = Math.max(...waarden);\n const maxIdx = waarden.indexOf(maxWaarde);\n const label = labelVan ?? ((i: number) => `dag ${i + 1}`);\n\n const move = (i: number) => {\n const host = ref.current;\n if (!host) return;\n const r = host.getBoundingClientRect();\n setHover(i);\n setTip({ x: ((i + 0.5) / n) * r.width, y: plotH * (1 - waarden[i] / max), titel: label(i), waarde: waarden[i] });\n };\n const leave = () => {\n setHover(null);\n setTip(null);\n };\n\n return (\n <div ref={ref} className=\"relative\" role=\"img\" aria-labelledby={`${uid}-t`} style={{ height: hoogte }}>\n <span id={`${uid}-t`} className=\"sr-only\">{titel}</span>\n <Tooltip t={tip} />\n <Raster plotH={plotH} />\n {/* De kolommen zelf: flex-sloten met 2px lucht; de balk groeit vanaf de basislijn en is\n nooit dikker dan 24px — de rest van het slot blijft lucht. */}\n <div className=\"absolute inset-x-0 top-0 flex items-end\" style={{ height: plotH, gap: 2 }}>\n {waarden.map((v, i) => (\n <button\n key={i}\n type=\"button\"\n tabIndex={v > 0 ? 0 : -1}\n aria-label={`${label(i)}: ${nf.format(v)} weergaven`}\n className=\"flex h-full min-w-0 flex-1 cursor-default items-end justify-center focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600\"\n onPointerMove={() => move(i)}\n onFocus={() => move(i)}\n onPointerLeave={leave}\n onBlur={leave}\n >\n {v > 0 && (\n <span\n aria-hidden=\"true\"\n className=\"block w-full\"\n style={{\n maxWidth: 24,\n height: Math.max(3, (v / max) * (plotH - 6)),\n borderRadius: \"4px 4px 0 0\",\n background: i === accentIndex ? CHART.accent : CHART.serie,\n opacity: hover === null || hover === i ? 1 : 0.45,\n transition: \"opacity 0.1s\",\n }}\n />\n )}\n </button>\n ))}\n </div>\n {/* Daglabels: spaarzaam (1 · 10 · 20 · einde). */}\n <div aria-hidden=\"true\" className=\"pointer-events-none absolute inset-x-0\" style={{ top: plotH + 3 }}>\n {[0, 9, 19, n - 1]\n .filter((v, i, a) => v >= 0 && v < n && a.indexOf(v) === i)\n .map((i) => (\n <span key={i} className=\"absolute -translate-x-1/2 text-[10px] text-slate-400\" style={{ left: `${((i + 0.5) / n) * 100}%` }}>\n {i + 1}\n </span>\n ))}\n </div>\n {/* Selectief direct label: alleen de piek — de rest draagt de tooltip en de schaal-tick. */}\n {maxWaarde > 0 && hover === null && (\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute -translate-x-1/2 text-[10px] font-medium text-slate-500\"\n style={{ left: `${((maxIdx + 0.5) / n) * 100}%`, top: Math.max(0, plotH * (1 - maxWaarde / max) - 16) }}\n >\n {nf.format(maxWaarde)}\n </span>\n )}\n <span aria-hidden=\"true\" className=\"pointer-events-none absolute -top-0.5 right-0 bg-white pl-1 text-[10px] text-slate-400\" style={{ fontVariantNumeric: \"tabular-nums\" }}>\n {nf.format(max)}\n </span>\n </div>\n );\n}\n\n/** Lijngrafiek over maanden: 2px lijn, wash-vulling, crosshair-tooltip, eindpunt gemarkeerd. */\nexport function MaandLijn({\n punten,\n hoogte = 150,\n titel,\n}: {\n punten: { label: string; waarde: number }[];\n hoogte?: number;\n titel: string;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const [tip, setTip] = useState<TooltipStand | null>(null);\n const [kruis, setKruis] = useState<number | null>(null);\n const uid = useId();\n\n const n = punten.length;\n const max = netteMax(Math.max(1, ...punten.map((p) => p.waarde)));\n const plotH = hoogte - 18;\n // x in procenten (2% marge), y in pixels — de SVG rekt alleen horizontaal.\n const px = (i: number) => (n === 1 ? 50 : 2 + (i / (n - 1)) * 96);\n const py = (v: number) => 6 + (plotH - 12) * (1 - v / max);\n const pad = punten.map((p, i) => `${i === 0 ? \"M\" : \"L\"} ${px(i)} ${py(p.waarde)}`).join(\" \");\n\n const move = (e: React.PointerEvent) => {\n const host = ref.current;\n if (!host || n === 0) return;\n const r = host.getBoundingClientRect();\n const fx = ((e.clientX - r.left) / r.width) * 100;\n const i = Math.max(0, Math.min(n - 1, Math.round(((fx - 2) / 96) * (n - 1))));\n setKruis(i);\n setTip({ x: (px(i) / 100) * r.width, y: py(punten[i].waarde), titel: punten[i].label, waarde: punten[i].waarde });\n };\n const leave = () => {\n setKruis(null);\n setTip(null);\n };\n\n if (n === 0) return null;\n const focus = kruis ?? n - 1;\n\n return (\n <div ref={ref} className=\"relative\" role=\"img\" aria-labelledby={`${uid}-t`} style={{ height: hoogte }} onPointerMove={move} onPointerLeave={leave}>\n <span id={`${uid}-t`} className=\"sr-only\">{titel}</span>\n <Tooltip t={tip} />\n <Raster plotH={plotH} />\n <svg viewBox={`0 0 100 ${plotH}`} preserveAspectRatio=\"none\" className=\"absolute inset-x-0 top-0 block w-full\" style={{ height: plotH }} aria-hidden=\"true\">\n {/* Wash onder de lijn: de seriekleur op 10% — een waas, nooit een vlak. */}\n <path d={`${pad} L ${px(n - 1)} ${plotH} L ${px(0)} ${plotH} Z`} fill={CHART.wash} />\n <path d={pad} fill=\"none\" stroke={CHART.serie} strokeWidth=\"2\" strokeLinejoin=\"round\" strokeLinecap=\"round\" vectorEffect=\"non-scaling-stroke\" />\n {kruis !== null && (\n <line x1={px(kruis)} x2={px(kruis)} y1=\"0\" y2={plotH} stroke={CHART.as} strokeWidth=\"1\" vectorEffect=\"non-scaling-stroke\" />\n )}\n </svg>\n {/* Punt als HTML-dot (8px + 2px witte ring): een SVG-cirkel vervormt onder de niet-uniforme\n schaal. Alleen het focuspunt draagt een dot — een dot op elk punt is ruis. */}\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute h-2 w-2 -translate-x-1/2 -translate-y-1/2 rounded-full\"\n style={{\n left: `${px(focus)}%`,\n top: py(punten[focus].waarde),\n background: focus === n - 1 ? CHART.accent : CHART.serie,\n boxShadow: \"0 0 0 2px #ffffff\",\n }}\n />\n <div aria-hidden=\"true\" className=\"pointer-events-none absolute inset-x-0\" style={{ top: plotH + 3 }}>\n {[0, Math.floor((n - 1) / 2), n - 1]\n .filter((v, i, a) => a.indexOf(v) === i)\n .map((i) => (\n <span\n key={i}\n className=\"absolute text-[10px] text-slate-400\"\n style={{ left: `${px(i)}%`, transform: i === 0 ? \"none\" : i === n - 1 ? \"translateX(-100%)\" : \"translateX(-50%)\" }}\n >\n {punten[i].label}\n </span>\n ))}\n </div>\n {/* Direct label op het eindpunt — de waarde waar het verhaal om draait. */}\n {kruis === null && (\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute text-[11px] font-semibold text-slate-700\"\n style={{ left: `${px(n - 1)}%`, top: Math.max(0, py(punten[n - 1].waarde) - 20), transform: \"translateX(-100%)\" }}\n >\n {nf.format(punten[n - 1].waarde)}\n </span>\n )}\n <span aria-hidden=\"true\" className=\"pointer-events-none absolute -top-0.5 right-0 bg-white pl-1 text-[10px] text-slate-400\" style={{ fontVariantNumeric: \"tabular-nums\" }}>\n {nf.format(max)}\n </span>\n </div>\n );\n}\n\n/** Horizontale balkjeslijst (toppagina's): label · waarde · balk. De track is een lichtere stap\n * van dezelfde ramp, zodat einden vergelijkbaar zijn zonder raster. */\nexport function BalkjesLijst({ items }: { items: { label: string; waarde: number }[] }) {\n const max = Math.max(1, ...items.map((i) => i.waarde));\n return (\n <ul className=\"grid gap-2.5\">\n {items.map((it) => (\n <li key={it.label} className=\"grid grid-cols-[minmax(0,1fr)_auto] items-center gap-x-3 gap-y-1\">\n <span className=\"truncate text-sm text-slate-700\" title={it.label}>{it.label}</span>\n <span className=\"text-sm font-medium text-slate-900\" style={{ fontVariantNumeric: \"tabular-nums\" }}>\n {nf.format(it.waarde)}\n </span>\n <span aria-hidden=\"true\" className=\"col-span-2 block h-1.5 w-full overflow-hidden rounded-full\" style={{ background: CHART.track }}>\n <span className=\"block h-full rounded-full\" style={{ width: `${(it.waarde / max) * 100}%`, background: CHART.serie }} />\n </span>\n </li>\n ))}\n </ul>\n );\n}\n\n/** Stat-tegel: label · grote waarde (proportionele cijfers) · optionele delta t.o.v. een genoemde periode. */\nexport function StatTegel({\n label,\n waarde,\n delta,\n deltaLabel,\n}: {\n label: string;\n waarde: number | string;\n /** Relatief verschil in procenten (bv. +12) — kleur volgt de richting (meer bezoek = goed). */\n delta?: number | null;\n deltaLabel?: string;\n}) {\n return (\n <div className=\"rounded-xl border border-slate-200 bg-white p-4\">\n <p className=\"text-sm text-slate-500\">{label}</p>\n <p className=\"mt-1 text-3xl font-semibold text-slate-900\">\n {typeof waarde === \"number\" ? nf.format(waarde) : waarde}\n </p>\n {delta != null && Number.isFinite(delta) && (\n <p className={`mt-1 text-xs font-medium ${delta >= 0 ? \"text-emerald-700\" : \"text-red-700\"}`}>\n <span aria-hidden=\"true\">{delta >= 0 ? \"▲\" : \"▼\"}</span> {Math.abs(Math.round(delta))}%\n {deltaLabel ? <span className=\"font-normal text-slate-500\"> {deltaLabel}</span> : null}\n </p>\n )}\n </div>\n );\n}\n\n/** Toegankelijke tabelweergave achter een uitklapper — alles wat een grafiek toont, zonder muis. */\nexport function AlsTabel({ kop, rijen }: { kop: [string, string]; rijen: [string, number][] }) {\n return (\n <details className=\"mt-2\">\n <summary className=\"cursor-pointer text-xs text-slate-400 hover:text-slate-600\">Bekijk als tabel</summary>\n <table className=\"mt-2 w-full text-sm\">\n <thead>\n <tr className=\"text-left text-xs text-slate-500\">\n <th className=\"py-1 font-medium\">{kop[0]}</th>\n <th className=\"py-1 text-right font-medium\">{kop[1]}</th>\n </tr>\n </thead>\n <tbody>\n {rijen.map(([l, w]) => (\n <tr key={l} className=\"border-t border-slate-100\">\n <td className=\"py-1 text-slate-700\">{l}</td>\n <td className=\"py-1 text-right text-slate-900\" style={{ fontVariantNumeric: \"tabular-nums\" }}>{nf.format(w)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </details>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/ui/charts.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * Lichte grafieken voor het beheer (7.17) — geen chart-library: dit is een editor-chunk en\n * drie vormen (kolommen, lijn, balkjeslijst) rechtvaardigen geen dependency in elke klantsite.\n *\n * Vaste GEREEDSCHAPSKLEUREN, bewust niet de merkkleur: `--color-brand` volgt `--xicms-primary`\n * van de klant en kan licht zijn (goud, lime) — dan verdwijnen de staven op een witte kaart.\n * Dit blauwpaar is met de dataviz-validator doorgerekend op wit (lichtheid, chroma, CVD-ΔE 18.9,\n * normaal-zicht-ΔE 19.2, contrast ≥ 3:1 — alles groen). Zelfde filosofie als de editor-balk:\n * gereedschap ziet er op elke site hetzelfde uit.\n *\n * Vormregels die hier vastliggen (dataviz-methode):\n * - kolommen: ronde datakant (4px), vlakke voet op de basislijn, ≤ 24px dik, 2px lucht ertussen;\n * - lijn: 2px met ronde joins, vulling als wash (10%), punten ≥ 8px met witte ring;\n * - raster: haarlijnen één stap van het oppervlak af, nooit gestreept, recessief;\n * - tekst draagt tekstkleuren, nooit de seriekleur — identiteit zit in de mark ernaast;\n * - hover hoort erbij: ruime hit-zones met tooltip, en alles wat de tooltip toont is óók\n * zonder muis bereikbaar (as-ticks, selectieve labels, de tabel-uitklapper).\n *\n * Bewust HTML-marks (divs) waar het kan: een SVG met `preserveAspectRatio=\"none\"` schaalt\n * niet-uniform, waardoor rondingen en cirkels vervormen — divs met border-radius blijven\n * pixel-zuiver op elke kaartbreedte. Alleen het lijnpad zelf is SVG (met non-scaling-stroke).\n */\nimport { useId, useRef, useState } from \"react\";\n\nexport const CHART = {\n serie: \"#3987e5\",\n accent: \"#184f95\",\n wash: \"rgba(57, 135, 229, 0.10)\",\n track: \"#e9f1fc\",\n grid: \"#e2e8f0\",\n as: \"#cbd5e1\",\n} as const;\n\nconst nf = new Intl.NumberFormat(\"nl-NL\");\n\n/** Nette bovengrens voor de y-as (1/2/5 × macht van 10), zodat de schaal-tick rond is. */\nfunction netteMax(max: number): number {\n if (max <= 4) return 4;\n const macht = 10 ** Math.floor(Math.log10(max));\n for (const f of [1, 2, 5, 10]) if (max <= f * macht) return f * macht;\n return 10 * macht;\n}\n\ninterface TooltipStand {\n x: number;\n y: number;\n titel: string;\n waarde: number;\n}\n\n/** Zwevende uitlezing. Waarde voorop en zwaar, label secundair — de lezer wil het getal. */\nfunction Tooltip({ t }: { t: TooltipStand | null }) {\n if (!t) return null;\n return (\n <div\n className=\"pointer-events-none absolute z-10 rounded-lg border border-slate-200 bg-white px-2.5 py-1.5 whitespace-nowrap shadow-md\"\n style={{ left: t.x, top: Math.max(26, t.y), transform: \"translate(-50%, calc(-100% - 8px))\" }}\n role=\"status\"\n >\n <span className=\"text-sm font-semibold text-slate-900\">{nf.format(t.waarde)}</span>\n <span className=\"ml-1.5 text-xs text-slate-500\">{t.titel}</span>\n </div>\n );\n}\n\n/** Recessief raster: haarlijnen op 50% en 100% van de schaal + de basislijn. */\nfunction Raster({ plotH }: { plotH: number }) {\n return (\n <div aria-hidden=\"true\" className=\"pointer-events-none absolute inset-x-0 top-0\" style={{ height: plotH }}>\n <div className=\"absolute inset-x-0\" style={{ top: 0, borderTop: `1px solid ${CHART.grid}` }} />\n <div className=\"absolute inset-x-0\" style={{ top: plotH / 2, borderTop: `1px solid ${CHART.grid}` }} />\n <div className=\"absolute inset-x-0\" style={{ top: plotH, borderTop: `1px solid ${CHART.as}` }} />\n </div>\n );\n}\n\n/**\n * Kolomgrafiek voor één maand: dag 1..N. `accentIndex` (bv. vandaag) kleurt één kolom in de\n * donkere stap van dezelfde ramp — zelfde reeks, gemarkeerd, geen tweede kleur.\n */\nexport function DagStaven({\n waarden,\n accentIndex,\n hoogte = 150,\n titel,\n labelVan,\n}: {\n /** Waarde per dag, index 0 = dag 1. */\n waarden: number[];\n accentIndex?: number;\n hoogte?: number;\n titel: string;\n /** Tooltiplabel per index (standaard \"dag N\"). */\n labelVan?: (i: number) => string;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const [tip, setTip] = useState<TooltipStand | null>(null);\n const [hover, setHover] = useState<number | null>(null);\n const uid = useId();\n\n const n = Math.max(1, waarden.length);\n const max = netteMax(Math.max(1, ...waarden));\n const plotH = hoogte - 18;\n const maxWaarde = Math.max(...waarden);\n const maxIdx = waarden.indexOf(maxWaarde);\n const label = labelVan ?? ((i: number) => `dag ${i + 1}`);\n\n const move = (i: number) => {\n const host = ref.current;\n if (!host) return;\n const r = host.getBoundingClientRect();\n setHover(i);\n setTip({ x: ((i + 0.5) / n) * r.width, y: plotH * (1 - waarden[i] / max), titel: label(i), waarde: waarden[i] });\n };\n const leave = () => {\n setHover(null);\n setTip(null);\n };\n\n return (\n <div ref={ref} className=\"relative\" role=\"img\" aria-labelledby={`${uid}-t`} style={{ height: hoogte }}>\n <span id={`${uid}-t`} className=\"sr-only\">{titel}</span>\n <Tooltip t={tip} />\n <Raster plotH={plotH} />\n {/* De kolommen zelf: flex-sloten met 2px lucht; de balk groeit vanaf de basislijn en is\n nooit dikker dan 24px — de rest van het slot blijft lucht. */}\n <div className=\"absolute inset-x-0 top-0 flex items-end\" style={{ height: plotH, gap: 2 }}>\n {waarden.map((v, i) => (\n <button\n key={i}\n type=\"button\"\n tabIndex={v > 0 ? 0 : -1}\n aria-label={`${label(i)}: ${nf.format(v)} weergaven`}\n className=\"flex h-full min-w-0 flex-1 cursor-default items-end justify-center focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600\"\n onPointerMove={() => move(i)}\n onFocus={() => move(i)}\n onPointerLeave={leave}\n onBlur={leave}\n >\n {v > 0 && (\n <span\n aria-hidden=\"true\"\n className=\"block w-full\"\n style={{\n maxWidth: 24,\n height: Math.max(3, (v / max) * (plotH - 6)),\n borderRadius: \"4px 4px 0 0\",\n background: i === accentIndex ? CHART.accent : CHART.serie,\n opacity: hover === null || hover === i ? 1 : 0.45,\n transition: \"opacity 0.1s\",\n }}\n />\n )}\n </button>\n ))}\n </div>\n {/* Daglabels: spaarzaam (1 · 10 · 20 · einde). */}\n <div aria-hidden=\"true\" className=\"pointer-events-none absolute inset-x-0\" style={{ top: plotH + 3 }}>\n {[0, 9, 19, n - 1]\n .filter((v, i, a) => v >= 0 && v < n && a.indexOf(v) === i)\n .map((i) => (\n <span key={i} className=\"absolute -translate-x-1/2 text-[10px] text-slate-500\" style={{ left: `${((i + 0.5) / n) * 100}%` }}>\n {i + 1}\n </span>\n ))}\n </div>\n {/* Selectief direct label: alleen de piek — de rest draagt de tooltip en de schaal-tick. */}\n {maxWaarde > 0 && hover === null && (\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute -translate-x-1/2 text-[10px] font-medium text-slate-500\"\n style={{ left: `${((maxIdx + 0.5) / n) * 100}%`, top: Math.max(0, plotH * (1 - maxWaarde / max) - 16) }}\n >\n {nf.format(maxWaarde)}\n </span>\n )}\n <span aria-hidden=\"true\" className=\"pointer-events-none absolute -top-0.5 right-0 bg-white pl-1 text-[10px] text-slate-500\" style={{ fontVariantNumeric: \"tabular-nums\" }}>\n {nf.format(max)}\n </span>\n </div>\n );\n}\n\n/** Lijngrafiek over maanden: 2px lijn, wash-vulling, crosshair-tooltip, eindpunt gemarkeerd. */\nexport function MaandLijn({\n punten,\n hoogte = 150,\n titel,\n}: {\n punten: { label: string; waarde: number }[];\n hoogte?: number;\n titel: string;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const [tip, setTip] = useState<TooltipStand | null>(null);\n const [kruis, setKruis] = useState<number | null>(null);\n const uid = useId();\n\n const n = punten.length;\n const max = netteMax(Math.max(1, ...punten.map((p) => p.waarde)));\n const plotH = hoogte - 18;\n // x in procenten (2% marge), y in pixels — de SVG rekt alleen horizontaal.\n const px = (i: number) => (n === 1 ? 50 : 2 + (i / (n - 1)) * 96);\n const py = (v: number) => 6 + (plotH - 12) * (1 - v / max);\n const pad = punten.map((p, i) => `${i === 0 ? \"M\" : \"L\"} ${px(i)} ${py(p.waarde)}`).join(\" \");\n\n const move = (e: React.PointerEvent) => {\n const host = ref.current;\n if (!host || n === 0) return;\n const r = host.getBoundingClientRect();\n const fx = ((e.clientX - r.left) / r.width) * 100;\n const i = Math.max(0, Math.min(n - 1, Math.round(((fx - 2) / 96) * (n - 1))));\n setKruis(i);\n setTip({ x: (px(i) / 100) * r.width, y: py(punten[i].waarde), titel: punten[i].label, waarde: punten[i].waarde });\n };\n const leave = () => {\n setKruis(null);\n setTip(null);\n };\n\n if (n === 0) return null;\n const focus = kruis ?? n - 1;\n\n return (\n <div ref={ref} className=\"relative\" role=\"img\" aria-labelledby={`${uid}-t`} style={{ height: hoogte }} onPointerMove={move} onPointerLeave={leave}>\n <span id={`${uid}-t`} className=\"sr-only\">{titel}</span>\n <Tooltip t={tip} />\n <Raster plotH={plotH} />\n <svg viewBox={`0 0 100 ${plotH}`} preserveAspectRatio=\"none\" className=\"absolute inset-x-0 top-0 block w-full\" style={{ height: plotH }} aria-hidden=\"true\">\n {/* Wash onder de lijn: de seriekleur op 10% — een waas, nooit een vlak. */}\n <path d={`${pad} L ${px(n - 1)} ${plotH} L ${px(0)} ${plotH} Z`} fill={CHART.wash} />\n <path d={pad} fill=\"none\" stroke={CHART.serie} strokeWidth=\"2\" strokeLinejoin=\"round\" strokeLinecap=\"round\" vectorEffect=\"non-scaling-stroke\" />\n {kruis !== null && (\n <line x1={px(kruis)} x2={px(kruis)} y1=\"0\" y2={plotH} stroke={CHART.as} strokeWidth=\"1\" vectorEffect=\"non-scaling-stroke\" />\n )}\n </svg>\n {/* Punt als HTML-dot (8px + 2px witte ring): een SVG-cirkel vervormt onder de niet-uniforme\n schaal. Alleen het focuspunt draagt een dot — een dot op elk punt is ruis. */}\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute h-2 w-2 -translate-x-1/2 -translate-y-1/2 rounded-full\"\n style={{\n left: `${px(focus)}%`,\n top: py(punten[focus].waarde),\n background: focus === n - 1 ? CHART.accent : CHART.serie,\n boxShadow: \"0 0 0 2px #ffffff\",\n }}\n />\n <div aria-hidden=\"true\" className=\"pointer-events-none absolute inset-x-0\" style={{ top: plotH + 3 }}>\n {[0, Math.floor((n - 1) / 2), n - 1]\n .filter((v, i, a) => a.indexOf(v) === i)\n .map((i) => (\n <span\n key={i}\n className=\"absolute text-[10px] text-slate-500\"\n style={{ left: `${px(i)}%`, transform: i === 0 ? \"none\" : i === n - 1 ? \"translateX(-100%)\" : \"translateX(-50%)\" }}\n >\n {punten[i].label}\n </span>\n ))}\n </div>\n {/* Direct label op het eindpunt — de waarde waar het verhaal om draait. */}\n {kruis === null && (\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute text-[11px] font-semibold text-slate-700\"\n style={{ left: `${px(n - 1)}%`, top: Math.max(0, py(punten[n - 1].waarde) - 20), transform: \"translateX(-100%)\" }}\n >\n {nf.format(punten[n - 1].waarde)}\n </span>\n )}\n <span aria-hidden=\"true\" className=\"pointer-events-none absolute -top-0.5 right-0 bg-white pl-1 text-[10px] text-slate-500\" style={{ fontVariantNumeric: \"tabular-nums\" }}>\n {nf.format(max)}\n </span>\n </div>\n );\n}\n\n/** Horizontale balkjeslijst (toppagina's): label · waarde · balk. De track is een lichtere stap\n * van dezelfde ramp, zodat einden vergelijkbaar zijn zonder raster. */\nexport function BalkjesLijst({ items }: { items: { label: string; waarde: number }[] }) {\n const max = Math.max(1, ...items.map((i) => i.waarde));\n return (\n <ul className=\"grid gap-2.5\">\n {items.map((it) => (\n <li key={it.label} className=\"grid grid-cols-[minmax(0,1fr)_auto] items-center gap-x-3 gap-y-1\">\n <span className=\"truncate text-sm text-slate-700\" title={it.label}>{it.label}</span>\n <span className=\"text-sm font-medium text-slate-900\" style={{ fontVariantNumeric: \"tabular-nums\" }}>\n {nf.format(it.waarde)}\n </span>\n <span aria-hidden=\"true\" className=\"col-span-2 block h-1.5 w-full overflow-hidden rounded-full\" style={{ background: CHART.track }}>\n <span className=\"block h-full rounded-full\" style={{ width: `${(it.waarde / max) * 100}%`, background: CHART.serie }} />\n </span>\n </li>\n ))}\n </ul>\n );\n}\n\n/** Stat-tegel: label · grote waarde (proportionele cijfers) · optionele delta t.o.v. een genoemde periode. */\nexport function StatTegel({\n label,\n waarde,\n delta,\n deltaLabel,\n}: {\n label: string;\n waarde: number | string;\n /** Relatief verschil in procenten (bv. +12) — kleur volgt de richting (meer bezoek = goed). */\n delta?: number | null;\n deltaLabel?: string;\n}) {\n return (\n <div className=\"rounded-xl border border-slate-200 bg-white p-4\">\n <p className=\"text-sm text-slate-500\">{label}</p>\n <p className=\"mt-1 text-3xl font-semibold text-slate-900\">\n {typeof waarde === \"number\" ? nf.format(waarde) : waarde}\n </p>\n {delta != null && Number.isFinite(delta) && (\n <p className={`mt-1 text-xs font-medium ${delta >= 0 ? \"text-emerald-700\" : \"text-red-700\"}`}>\n <span aria-hidden=\"true\">{delta >= 0 ? \"▲\" : \"▼\"}</span> {Math.abs(Math.round(delta))}%\n {deltaLabel ? <span className=\"font-normal text-slate-500\"> {deltaLabel}</span> : null}\n </p>\n )}\n </div>\n );\n}\n\n/** Toegankelijke tabelweergave achter een uitklapper — alles wat een grafiek toont, zonder muis. */\nexport function AlsTabel({ kop, rijen }: { kop: [string, string]; rijen: [string, number][] }) {\n return (\n <details className=\"mt-2\">\n <summary className=\"cursor-pointer text-xs text-slate-500 hover:text-slate-600\">Bekijk als tabel</summary>\n <table className=\"mt-2 w-full text-sm\">\n <thead>\n <tr className=\"text-left text-xs text-slate-500\">\n <th className=\"py-1 font-medium\">{kop[0]}</th>\n <th className=\"py-1 text-right font-medium\">{kop[1]}</th>\n </tr>\n </thead>\n <tbody>\n {rijen.map(([l, w]) => (\n <tr key={l} className=\"border-t border-slate-100\">\n <td className=\"py-1 text-slate-700\">{l}</td>\n <td className=\"py-1 text-right text-slate-900\" style={{ fontVariantNumeric: \"tabular-nums\" }}>{nf.format(w)}</td>\n </tr>\n ))}\n </tbody>\n </table>\n </details>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ButtonHTMLAttributes, type InputHTMLAttributes, type TextareaHTMLAttributes } from "react";
|
|
1
|
+
import { type ButtonHTMLAttributes, type InputHTMLAttributes, type ReactNode, type TextareaHTMLAttributes } from "react";
|
|
2
2
|
/**
|
|
3
3
|
* Admin-primitieven op het **Astryx design system**. Form-controls (Input/Textarea) renderen echte
|
|
4
4
|
* Astryx-componenten; bijzondere input-types (datetime-local, file…) die Astryx niet kent vallen
|
|
@@ -6,21 +6,31 @@ import { type ButtonHTMLAttributes, type InputHTMLAttributes, type TextareaHTMLA
|
|
|
6
6
|
* Astryx-huisstijl) — bewust geen Astryx Button (die werkt op `label`/`clickAction` i.p.v. children/
|
|
7
7
|
* onClick, wat de ~honderd editor-call-sites zou breken). De API blijft gelijk → robuust.
|
|
8
8
|
*/
|
|
9
|
-
type Variant = "primary" | "secondary" | "ghost" | "danger";
|
|
9
|
+
type Variant = "primary" | "secondary" | "ghost" | "danger" | "dangerGhost";
|
|
10
10
|
type Size = "sm" | "md";
|
|
11
11
|
export declare const Button: import("react").ForwardRefExoticComponent<ButtonHTMLAttributes<HTMLButtonElement> & {
|
|
12
12
|
variant?: Variant;
|
|
13
13
|
size?: Size;
|
|
14
|
+
/**
|
|
15
|
+
* 8.12: bezig. Toont een draaiertje vóór het label en zet de knop uit — het label blijft staan.
|
|
16
|
+
* Tot nu toe werd de tekst "Bezig…": de knop sprong van breedte en je zag niet meer wát er bezig was.
|
|
17
|
+
*/
|
|
18
|
+
loading?: boolean;
|
|
14
19
|
} & import("react").RefAttributes<HTMLButtonElement>>;
|
|
15
20
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* `Field`; hier dus `isLabelHidden`.
|
|
21
|
+
* Een lege lijst als uitnodiging (8.12): icoon, één zin en de eerste stap — in plaats van een kale
|
|
22
|
+
* grijze regel "Nog geen media." waar de klant niets mee kon.
|
|
19
23
|
*/
|
|
24
|
+
export declare function LegeStaat({ titel, tekst, actie }: {
|
|
25
|
+
titel: string;
|
|
26
|
+
tekst?: ReactNode;
|
|
27
|
+
actie?: ReactNode;
|
|
28
|
+
}): import("react").JSX.Element;
|
|
29
|
+
export declare function useFieldLabel(fallback: string): string;
|
|
20
30
|
export declare const Input: import("react").ForwardRefExoticComponent<InputHTMLAttributes<HTMLInputElement> & import("react").RefAttributes<HTMLInputElement>>;
|
|
21
31
|
export declare const Textarea: import("react").ForwardRefExoticComponent<TextareaHTMLAttributes<HTMLTextAreaElement> & import("react").RefAttributes<HTMLTextAreaElement>>;
|
|
22
32
|
/** Label-wrapper. Een `<div>` (geen `<label>`) zodat het geen geneste label vormt met de
|
|
23
|
-
* Astryx-controls
|
|
33
|
+
* Astryx-controls; het label gaat via context naar de control zelf (toegankelijke naam). */
|
|
24
34
|
export declare function Field({ label, children, hint }: {
|
|
25
35
|
label: string;
|
|
26
36
|
children: React.ReactNode;
|