@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
|
@@ -7,7 +7,11 @@ import { Select } from "../ui/select.js";
|
|
|
7
7
|
import { Switch } from "../ui/switch.js";
|
|
8
8
|
import { ArrayEditor } from "../ui/ArrayEditor.js";
|
|
9
9
|
import { RichTextEditor } from "../editors/RichTextEditor.js";
|
|
10
|
-
import {
|
|
10
|
+
import { ImageField } from "../ui/ImageField.js";
|
|
11
|
+
import { LinkVeld } from "../ui/LinkVeld.js";
|
|
12
|
+
import { lengteAdvies } from "../lib/lengteAdvies.js";
|
|
13
|
+
import { TECHNISCHE_VELDEN, vertaalVelden } from "../lib/veldTaal.js";
|
|
14
|
+
import { useIsSuperadmin } from "../lib/useIsSuperadmin.js";
|
|
11
15
|
import { useRegistry } from "../../blocks/context.js";
|
|
12
16
|
import { subscribePages } from "../lib/pagesClient.js";
|
|
13
17
|
import { introspectToFields, introspectObjectSchema } from "../lib/zodFields.js";
|
|
@@ -19,7 +23,8 @@ function FieldsForm({
|
|
|
19
23
|
siteId,
|
|
20
24
|
jsonSchemas
|
|
21
25
|
}) {
|
|
22
|
-
|
|
26
|
+
const superadmin = useIsSuperadmin();
|
|
27
|
+
return /* @__PURE__ */ jsx("div", { className: "grid gap-3", children: fields.filter((f) => isFieldVisible(f, values) && (superadmin || !TECHNISCHE_VELDEN.has(f.key))).map((f) => /* @__PURE__ */ jsx(FieldWidget, { f, values, onChange, siteId, jsonSchema: jsonSchemas?.[f.key] }, f.key)) });
|
|
23
28
|
}
|
|
24
29
|
function FieldWidget({
|
|
25
30
|
f,
|
|
@@ -39,6 +44,22 @@ function FieldWidget({
|
|
|
39
44
|
case "select":
|
|
40
45
|
return /* @__PURE__ */ jsx(SelectField, { f, v, set });
|
|
41
46
|
case "number":
|
|
47
|
+
if (f.min !== void 0 && f.max !== void 0 && Number.isInteger(f.min) && Number.isInteger(f.max) && f.max - f.min <= 5) {
|
|
48
|
+
const opties = Array.from({ length: f.max - f.min + 1 }, (_, i) => f.min + i);
|
|
49
|
+
const huidig = typeof v === "number" ? v : void 0;
|
|
50
|
+
return /* @__PURE__ */ jsx(FieldRow, { label: f.label, hint: f.hint, children: /* @__PURE__ */ jsx("div", { role: "radiogroup", "aria-label": f.label, className: "inline-flex flex-wrap gap-1", children: opties.map((n) => /* @__PURE__ */ jsx(
|
|
51
|
+
"button",
|
|
52
|
+
{
|
|
53
|
+
type: "button",
|
|
54
|
+
role: "radio",
|
|
55
|
+
"aria-checked": huidig === n,
|
|
56
|
+
onClick: () => set(n),
|
|
57
|
+
className: "xicms-admin-btn h-9 min-w-9 rounded-md border border-slate-200 px-2 text-sm font-medium text-slate-700 hover:bg-slate-100 aria-[checked=true]:border-slate-900 aria-[checked=true]:bg-slate-900 aria-[checked=true]:text-white",
|
|
58
|
+
children: f.key === "rating" ? "\u2605".repeat(n) : n
|
|
59
|
+
},
|
|
60
|
+
n
|
|
61
|
+
)) }) });
|
|
62
|
+
}
|
|
42
63
|
return /* @__PURE__ */ jsx(FieldRow, { label: f.label, hint: f.hint, children: /* @__PURE__ */ jsx(
|
|
43
64
|
Input,
|
|
44
65
|
{
|
|
@@ -70,19 +91,16 @@ function FieldWidget({
|
|
|
70
91
|
case "richtext":
|
|
71
92
|
return /* @__PURE__ */ jsx(FieldRow, { label: f.label, hint: f.hint, children: /* @__PURE__ */ jsx(RichTextEditor, { siteId, value: String(v ?? ""), onChange: set }) });
|
|
72
93
|
case "image":
|
|
73
|
-
return /* @__PURE__ */ jsx(FieldRow, { label: f.label, hint: f.hint, children: /* @__PURE__ */
|
|
74
|
-
/* @__PURE__ */ jsx(Input, { value: String(v ?? ""), onChange: (e) => set(e.target.value), placeholder: "URL of kies \u2192" }),
|
|
75
|
-
/* @__PURE__ */ jsx(MediaPickerButton, { siteId, onSelect: (m) => set(m.url) })
|
|
76
|
-
] }) });
|
|
94
|
+
return /* @__PURE__ */ jsx(FieldRow, { label: f.label, hint: f.hint, children: /* @__PURE__ */ jsx(ImageField, { siteId, value: v ? String(v) : void 0, onChange: (url) => set(url ?? "") }) });
|
|
77
95
|
case "url":
|
|
78
|
-
return /* @__PURE__ */ jsx(FieldRow, { label: f.label, hint: f.hint, children: /* @__PURE__ */ jsx(Input, { value: String(v ?? ""), onChange: (e) => set(e.target.value), placeholder: "https://\u2026
|
|
96
|
+
return /* @__PURE__ */ jsx(FieldRow, { label: f.label, hint: f.hint, children: /href$/i.test(f.key) || f.key === "link" ? /* @__PURE__ */ jsx(LinkVeld, { siteId, value: String(v ?? ""), onChange: set }) : /* @__PURE__ */ jsx(Input, { value: String(v ?? ""), onChange: (e) => set(e.target.value), placeholder: "https://\u2026" }) });
|
|
79
97
|
case "icon":
|
|
80
98
|
return /* @__PURE__ */ jsx(FieldRow, { label: f.label, hint: f.hint ?? "Emoji, bv. \u2702\uFE0F", children: /* @__PURE__ */ jsx(Input, { value: String(v ?? ""), maxLength: 16, onChange: (e) => set(e.target.value), className: "w-24" }) });
|
|
81
99
|
case "link": {
|
|
82
100
|
const link = v ?? {};
|
|
83
|
-
return /* @__PURE__ */ jsx(FieldRow, { label: f.label, hint: f.hint, children: /* @__PURE__ */ jsxs("div", { className: "grid
|
|
84
|
-
/* @__PURE__ */ jsx(Input, { value: link.label ?? "", placeholder: "Tekst", onChange: (e) => set({ ...link, label: e.target.value }) }),
|
|
85
|
-
/* @__PURE__ */ jsx(
|
|
101
|
+
return /* @__PURE__ */ jsx(FieldRow, { label: f.label, hint: f.hint, children: /* @__PURE__ */ jsxs("div", { className: "grid gap-2", children: [
|
|
102
|
+
/* @__PURE__ */ jsx(Input, { value: link.label ?? "", placeholder: "Tekst op de knop", onChange: (e) => set({ ...link, label: e.target.value }) }),
|
|
103
|
+
/* @__PURE__ */ jsx(LinkVeld, { siteId, value: link.href ?? "", onChange: (href) => set({ ...link, href }) })
|
|
86
104
|
] }) });
|
|
87
105
|
}
|
|
88
106
|
case "group": {
|
|
@@ -115,14 +133,17 @@ function FieldWidget({
|
|
|
115
133
|
return /* @__PURE__ */ jsx(JsonField, { label: f.label, value: v, onCommit: set, schema: jsonSchema });
|
|
116
134
|
case "text":
|
|
117
135
|
default:
|
|
118
|
-
return /* @__PURE__ */
|
|
136
|
+
return /* @__PURE__ */ jsxs(FieldRow, { label: f.label, hint: f.hint, children: [
|
|
137
|
+
/* @__PURE__ */ jsx(Input, { value: String(v ?? ""), placeholder: f.type === "text" ? f.placeholder : void 0, onChange: (e) => set(e.target.value) }),
|
|
138
|
+
lengteAdvies(f.key, typeof v === "string" ? v : "") && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-amber-700", children: lengteAdvies(f.key, String(v)) })
|
|
139
|
+
] });
|
|
119
140
|
}
|
|
120
141
|
}
|
|
121
142
|
function PageRefPicker({ siteId, value, onChange }) {
|
|
122
143
|
const [pages, setPages] = useState([]);
|
|
123
144
|
useEffect(() => subscribePages(siteId, setPages), [siteId]);
|
|
124
145
|
const options = useMemo(() => {
|
|
125
|
-
const opts = pages.
|
|
146
|
+
const opts = 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"}` }));
|
|
126
147
|
if (value && !opts.some((o) => o.value === value)) opts.unshift({ value, label: value });
|
|
127
148
|
return [{ value: "", label: "\u2014 geen \u2014" }, ...opts];
|
|
128
149
|
}, [pages, value]);
|
|
@@ -155,7 +176,7 @@ function JsonField({
|
|
|
155
176
|
if (!opts.silent) setError("Geen geldige JSON.");
|
|
156
177
|
}
|
|
157
178
|
};
|
|
158
|
-
return /* @__PURE__ */ jsxs(FieldRow, { label: `${label} (
|
|
179
|
+
return /* @__PURE__ */ jsxs(FieldRow, { label: `${label} (geavanceerd)`, hint: "Technisch veld \u2014 vraag bij twijfel Xi Webdesign. Wordt gecontroleerd v\xF3\xF3r opslaan.", children: [
|
|
159
180
|
/* @__PURE__ */ jsx(
|
|
160
181
|
Textarea,
|
|
161
182
|
{
|
|
@@ -179,7 +200,7 @@ function GenericEditor({ block, siteId, onChange }) {
|
|
|
179
200
|
const fields = useMemo(() => {
|
|
180
201
|
if (!def) return [];
|
|
181
202
|
const custom = def.customFields;
|
|
182
|
-
return custom ?? introspectToFields(def.schema, def.fields);
|
|
203
|
+
return vertaalVelden(custom ?? introspectToFields(def.schema, def.fields), def.type);
|
|
183
204
|
}, [def]);
|
|
184
205
|
const jsonSchemas = useMemo(() => {
|
|
185
206
|
if (!def) return {};
|
|
@@ -206,13 +227,10 @@ function SelectField({
|
|
|
206
227
|
v,
|
|
207
228
|
set
|
|
208
229
|
}) {
|
|
209
|
-
useEffect(() => {
|
|
210
|
-
if (v == null && f.options[0] !== void 0) set(f.options[0].value);
|
|
211
|
-
}, []);
|
|
212
230
|
return /* @__PURE__ */ jsx(FieldRow, { label: f.label, hint: f.hint, children: /* @__PURE__ */ jsx(
|
|
213
231
|
Select,
|
|
214
232
|
{
|
|
215
|
-
value: String(v ?? f.options[0]?.value ?? ""),
|
|
233
|
+
value: String(v ?? f.standaard ?? f.options[0]?.value ?? ""),
|
|
216
234
|
onValueChange: set,
|
|
217
235
|
options: f.options.map((o) => ({ value: o.value, label: o.label || o.value }))
|
|
218
236
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/blockEditors/GenericEditor.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * GenericEditor 2.0 (5.0) — het automatisch gegenereerde formulier voor blokken zonder eigen\n * editor, aangedreven door de Field-IR (schema/fields.ts, primo-port):\n *\n * - **repeaters** en **groepen** zijn echte UI (ArrayEditor met toevoegen/verwijderen/↑↓ en een\n * omkaderde subgroep) i.p.v. een JSON-textarea;\n * - **showIf** verbergt velden conditioneel;\n * - date/slider/link/icoon/pagina-verwijzing hebben eigen widgets;\n * - de JSON-textarea bestaat alleen nog als laatste redmiddel (records/scalar-arrays), met\n * schema-validatie vóór commit.\n *\n * `FieldsForm` is los herbruikbaar: custom blocks (Fase B) renderen er hun opgeslagen Field-IR mee.\n */\nimport { safeParse } from \"zod/v4/core\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { $ZodType as ZodTypeAny } from \"zod/v4/core\";\nimport { Field as FieldRow, Input, Textarea } from \"../ui/primitives\";\nimport { Select } from \"../ui/select\";\nimport { Switch } from \"../ui/switch\";\nimport { ArrayEditor } from \"../ui/ArrayEditor\";\nimport { RichTextEditor } from \"../editors/RichTextEditor\";\nimport { MediaPickerButton } from \"../media/MediaPicker\";\nimport { useRegistry } from \"../../blocks/context\";\nimport { subscribePages, type DraftPage } from \"../lib/pagesClient\";\nimport { introspectToFields, introspectObjectSchema } from \"../lib/zodFields\";\nimport { fieldsDefaults, isFieldVisible, type Field } from \"../../schema/fields\";\n\nexport interface GenericEditorProps {\n block: Record<string, unknown>;\n siteId: string;\n onChange: (next: Record<string, unknown>) => void;\n}\n\n/** Formulier voor een Field-IR over een waarden-object. Recursief (groepen/repeaters). */\nexport function FieldsForm({\n fields,\n values,\n onChange,\n siteId,\n jsonSchemas,\n}: {\n fields: Field[];\n values: Record<string, unknown>;\n onChange: (patch: Record<string, unknown>) => void;\n siteId: string;\n /** Optioneel: sub-schema per json-veldsleutel voor validatie vóór commit. */\n jsonSchemas?: Record<string, ZodTypeAny>;\n}) {\n return (\n <div className=\"grid gap-3\">\n {fields.filter((f) => isFieldVisible(f, values)).map((f) => (\n <FieldWidget key={f.key} f={f} values={values} onChange={onChange} siteId={siteId} jsonSchema={jsonSchemas?.[f.key]} />\n ))}\n </div>\n );\n}\n\nfunction FieldWidget({\n f,\n values,\n onChange,\n siteId,\n jsonSchema,\n}: {\n f: Field;\n values: Record<string, unknown>;\n onChange: (patch: Record<string, unknown>) => void;\n siteId: string;\n jsonSchema?: ZodTypeAny;\n}) {\n const v = values[f.key];\n const set = (val: unknown) => onChange({ [f.key]: val });\n\n switch (f.type) {\n case \"switch\":\n return (\n <label className=\"flex items-center gap-2 text-sm\">\n <Switch checked={Boolean(v)} onCheckedChange={set} />\n {f.label}\n </label>\n );\n case \"select\":\n return <SelectField f={f} v={v} set={set} />;\n case \"number\":\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <Input\n type=\"number\"\n min={f.min}\n max={f.max}\n step={f.step}\n value={v == null ? \"\" : String(v)}\n onChange={(e) => set(e.target.value === \"\" ? undefined : Number(e.target.value))}\n />\n </FieldRow>\n );\n case \"slider\": {\n const val = typeof v === \"number\" ? v : f.min;\n return (\n <FieldRow label={`${f.label} (${val})`} hint={f.hint}>\n <input\n type=\"range\"\n min={f.min}\n max={f.max}\n step={f.step ?? 1}\n value={val}\n onChange={(e) => set(Number(e.target.value))}\n className=\"w-full\"\n />\n </FieldRow>\n );\n }\n case \"date\":\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <Input type=\"date\" value={String(v ?? \"\")} onChange={(e) => set(e.target.value)} />\n </FieldRow>\n );\n case \"richtext\":\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <RichTextEditor siteId={siteId} value={String(v ?? \"\")} onChange={set} />\n </FieldRow>\n );\n case \"image\":\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <div className=\"flex items-center gap-2\">\n <Input value={String(v ?? \"\")} onChange={(e) => set(e.target.value)} placeholder=\"URL of kies →\" />\n <MediaPickerButton siteId={siteId} onSelect={(m) => set(m.url)} />\n </div>\n </FieldRow>\n );\n case \"url\":\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <Input value={String(v ?? \"\")} onChange={(e) => set(e.target.value)} placeholder=\"https://… of /pagina\" />\n </FieldRow>\n );\n case \"icon\":\n return (\n <FieldRow label={f.label} hint={f.hint ?? \"Emoji, bv. ✂️\"}>\n <Input value={String(v ?? \"\")} maxLength={16} onChange={(e) => set(e.target.value)} className=\"w-24\" />\n </FieldRow>\n );\n case \"link\": {\n const link = (v as { label?: string; href?: string } | undefined) ?? {};\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <div className=\"grid grid-cols-2 gap-2\">\n <Input value={link.label ?? \"\"} placeholder=\"Tekst\" onChange={(e) => set({ ...link, label: e.target.value })} />\n <Input value={link.href ?? \"\"} placeholder=\"/pagina of https://…\" onChange={(e) => set({ ...link, href: e.target.value })} />\n </div>\n </FieldRow>\n );\n }\n case \"group\": {\n const group = (v as Record<string, unknown> | undefined) ?? {};\n return (\n <fieldset className=\"grid gap-2 rounded-lg border border-slate-200 p-3\">\n <legend className=\"px-1 text-xs font-semibold text-slate-500\">{f.label}</legend>\n <FieldsForm fields={f.fields} values={group} onChange={(p) => set({ ...group, ...p })} siteId={siteId} />\n </fieldset>\n );\n }\n case \"repeater\": {\n const items = (Array.isArray(v) ? v : []) as Record<string, unknown>[];\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <ArrayEditor<Record<string, unknown>>\n items={items}\n onChange={set}\n newItem={() => fieldsDefaults(f.fields)}\n addLabel={`+ ${f.itemLabel ?? \"Item\"}`}\n renderRow={(item, update) => (\n <FieldsForm fields={f.fields} values={item} onChange={(p) => update(p)} siteId={siteId} />\n )}\n />\n </FieldRow>\n );\n }\n case \"pageRef\":\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <PageRefPicker siteId={siteId} value={String(v ?? \"\")} onChange={set} />\n </FieldRow>\n );\n case \"info\":\n return <p className=\"text-xs text-slate-500\">{f.text}</p>;\n case \"textarea\":\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <Textarea rows={f.rows ?? 4} value={String(v ?? \"\")} onChange={(e) => set(e.target.value)} />\n </FieldRow>\n );\n case \"json\":\n return <JsonField label={f.label} value={v} onCommit={set} schema={jsonSchema} />;\n case \"text\":\n default:\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <Input value={String(v ?? \"\")} placeholder={f.type === \"text\" ? f.placeholder : undefined} onChange={(e) => set(e.target.value)} />\n </FieldRow>\n );\n }\n}\n\n/** Pagina-verwijzing: kies uit de bestaande pagina's van de site (live lijst). */\nfunction PageRefPicker({ siteId, value, onChange }: { siteId: string; value: string; onChange: (v: string) => void }) {\n const [pages, setPages] = useState<DraftPage[]>([]);\n useEffect(() => subscribePages(siteId, setPages), [siteId]);\n const options = useMemo(() => {\n const opts = pages\n .slice()\n .sort((a, b) => (a.path < b.path ? -1 : 1))\n .map((p) => ({ value: p.path, label: `${p.title || p.path} (${p.path})` }));\n // Bewaar een waarde die (nog) niet in de lijst staat, zodat niets stilletjes wegvalt.\n if (value && !opts.some((o) => o.value === value)) opts.unshift({ value, label: value });\n return [{ value: \"\", label: \"— geen —\" }, ...opts];\n }, [pages, value]);\n return <Select value={value} onValueChange={onChange} options={options} />;\n}\n\n/** Laatste redmiddel voor complexe velden: JSON met schema-validatie vóór commit. */\nfunction JsonField({\n label,\n value,\n onCommit,\n schema,\n}: {\n label: string;\n value: unknown;\n onCommit: (v: unknown) => void;\n schema?: ZodTypeAny;\n}) {\n const [text, setText] = useState(() => JSON.stringify(value ?? null, null, 2));\n const [error, setError] = useState<string | null>(null);\n // Committeert de gegeven tekst (niet de state — die is bij een net getypte toets nog niet\n // bijgewerkt). `silent`: tijdens het typen geen foutmelding tonen voor onvolledige JSON (bv.\n // een net geopende `[` of `{`) — pas bij blur laten we die zien. VEILIGHEIDSNET: committeert bij\n // élke wijziging i.p.v. uitsluitend op blur, want blur bleek op mobiel Safari niet altijd te\n // vuren vóór een externe \"Opslaan\"-klik (race), waardoor een bewerking hier stil verloren ging.\n const commit = (raw: string, opts: { silent: boolean }) => {\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (schema) {\n const res = safeParse(schema, parsed);\n if (!res.success) {\n if (!opts.silent) setError(\"Voldoet niet aan het verwachte formaat van dit veld.\");\n return;\n }\n setError(null);\n onCommit(res.data);\n return;\n }\n setError(null);\n onCommit(parsed);\n } catch {\n if (!opts.silent) setError(\"Geen geldige JSON.\");\n }\n };\n return (\n <FieldRow label={`${label} (JSON)`} hint=\"Geavanceerd veld — wordt gecontroleerd vóór opslaan.\">\n <Textarea\n rows={6}\n value={text}\n onChange={(e) => {\n setText(e.target.value);\n commit(e.target.value, { silent: true });\n }}\n onBlur={() => commit(text, { silent: false })}\n spellCheck={false}\n className=\"font-mono text-xs\"\n />\n {error && <p className=\"text-xs text-red-600\">{error}</p>}\n </FieldRow>\n );\n}\n\n/**\n * De blok-editor-fallback: leidt de Field-IR af uit het Zod-schema van het blok (+ optionele\n * `fields`-hints van `defineBlock`) en rendert het formulier. Zo is een blok zonder maatwerk-\n * editor nooit een doodlopend pad voor de klant.\n */\nexport function GenericEditor({ block, siteId, onChange }: GenericEditorProps) {\n const registry = useRegistry();\n const def = registry.get(String(block._type ?? \"\"));\n const fields = useMemo(() => {\n if (!def) return [];\n // Custom blocks (5.0) dragen hun opgeslagen Field-IR mee — rijker dan introspectie\n // (showIf/date/slider-metadata gaat door fieldsToZod heen verloren).\n const custom = (def as { customFields?: Field[] }).customFields;\n return custom ?? introspectToFields(def.schema, def.fields);\n }, [def]);\n // Sub-schema's voor json-velden (validatie vóór commit), uit de platte introspectie.\n const jsonSchemas = useMemo(() => {\n if (!def) return {};\n const out: Record<string, ZodTypeAny> = {};\n for (const f of introspectObjectSchema(def.schema)) if (f.kind === \"json\") out[f.key] = f.schema;\n return out;\n }, [def]);\n if (fields.length === 0) {\n return <p className=\"text-sm text-slate-500\">Voor dit bloktype is geen editor beschikbaar.</p>;\n }\n return (\n <FieldsForm\n fields={fields}\n values={block}\n onChange={(p) => onChange({ ...block, ...p })}\n siteId={siteId}\n jsonSchemas={jsonSchemas}\n />\n );\n}\n\n/**\n * Select als eigen component: commit de default-optie bij mount wanneer er nog geen waarde is.\n * De dropdown TOONDE optie 1 maar sloeg 'm niet op (weergave ≠ opslag) — een verplichte enum kon\n * zo leeg gepubliceerd worden tenzij het Zod-schema toevallig een default had.\n */\nfunction SelectField({\n f,\n v,\n set,\n}: {\n f: Extract<Field, { type: \"select\" }>;\n v: unknown;\n set: (val: unknown) => void;\n}) {\n useEffect(() => {\n if (v == null && f.options[0] !== undefined) set(f.options[0].value);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <Select\n value={String(v ?? f.options[0]?.value ?? \"\")}\n onValueChange={set}\n options={f.options.map((o) => ({ value: o.value, label: o.label || o.value }))}\n />\n </FieldRow>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/blockEditors/GenericEditor.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * GenericEditor 2.0 (5.0) — het automatisch gegenereerde formulier voor blokken zonder eigen\n * editor, aangedreven door de Field-IR (schema/fields.ts, primo-port):\n *\n * - **repeaters** en **groepen** zijn echte UI (ArrayEditor met toevoegen/verwijderen/↑↓ en een\n * omkaderde subgroep) i.p.v. een JSON-textarea;\n * - **showIf** verbergt velden conditioneel;\n * - date/slider/link/icoon/pagina-verwijzing hebben eigen widgets;\n * - de JSON-textarea bestaat alleen nog als laatste redmiddel (records/scalar-arrays), met\n * schema-validatie vóór commit.\n *\n * `FieldsForm` is los herbruikbaar: custom blocks (Fase B) renderen er hun opgeslagen Field-IR mee.\n */\nimport { safeParse } from \"zod/v4/core\";\nimport { useEffect, useMemo, useState } from \"react\";\nimport type { $ZodType as ZodTypeAny } from \"zod/v4/core\";\nimport { Field as FieldRow, Input, Textarea } from \"../ui/primitives\";\nimport { Select } from \"../ui/select\";\nimport { Switch } from \"../ui/switch\";\nimport { ArrayEditor } from \"../ui/ArrayEditor\";\nimport { RichTextEditor } from \"../editors/RichTextEditor\";\nimport { ImageField } from \"../ui/ImageField\";\nimport { LinkVeld } from \"../ui/LinkVeld\";\nimport { lengteAdvies } from \"../lib/lengteAdvies\";\nimport { TECHNISCHE_VELDEN, vertaalVelden } from \"../lib/veldTaal\";\nimport { useIsSuperadmin } from \"../lib/useIsSuperadmin\";\nimport { useRegistry } from \"../../blocks/context\";\nimport { subscribePages, type DraftPage } from \"../lib/pagesClient\";\nimport { introspectToFields, introspectObjectSchema } from \"../lib/zodFields\";\nimport { fieldsDefaults, isFieldVisible, type Field } from \"../../schema/fields\";\n\nexport interface GenericEditorProps {\n block: Record<string, unknown>;\n siteId: string;\n onChange: (next: Record<string, unknown>) => void;\n}\n\n/** Formulier voor een Field-IR over een waarden-object. Recursief (groepen/repeaters). */\nexport function FieldsForm({\n fields,\n values,\n onChange,\n siteId,\n jsonSchemas,\n}: {\n fields: Field[];\n values: Record<string, unknown>;\n onChange: (patch: Record<string, unknown>) => void;\n siteId: string;\n /** Optioneel: sub-schema per json-veldsleutel voor validatie vóór commit. */\n jsonSchemas?: Record<string, ZodTypeAny>;\n}) {\n const superadmin = useIsSuperadmin();\n return (\n <div className=\"grid gap-3\">\n {fields.filter((f) => isFieldVisible(f, values) && (superadmin || !TECHNISCHE_VELDEN.has(f.key))).map((f) => (\n <FieldWidget key={f.key} f={f} values={values} onChange={onChange} siteId={siteId} jsonSchema={jsonSchemas?.[f.key]} />\n ))}\n </div>\n );\n}\n\nfunction FieldWidget({\n f,\n values,\n onChange,\n siteId,\n jsonSchema,\n}: {\n f: Field;\n values: Record<string, unknown>;\n onChange: (patch: Record<string, unknown>) => void;\n siteId: string;\n jsonSchema?: ZodTypeAny;\n}) {\n const v = values[f.key];\n const set = (val: unknown) => onChange({ [f.key]: val });\n\n switch (f.type) {\n case \"switch\":\n return (\n <label className=\"flex items-center gap-2 text-sm\">\n <Switch checked={Boolean(v)} onCheckedChange={set} />\n {f.label}\n </label>\n );\n case \"select\":\n return <SelectField f={f} v={v} set={set} />;\n case \"number\":\n // 8.11: een klein bereik (kolommen 1–4, sterren 1–5) als knoppenrij — een vrij getalveld liet\n // \"17 kolommen\" toe en vroeg de klant te raden wat er mag.\n if (f.min !== undefined && f.max !== undefined && Number.isInteger(f.min) && Number.isInteger(f.max) && f.max - f.min <= 5) {\n const opties = Array.from({ length: f.max - f.min + 1 }, (_, i) => f.min! + i);\n const huidig = typeof v === \"number\" ? v : undefined;\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <div role=\"radiogroup\" aria-label={f.label} className=\"inline-flex flex-wrap gap-1\">\n {opties.map((n) => (\n <button\n key={n}\n type=\"button\"\n role=\"radio\"\n aria-checked={huidig === n}\n onClick={() => set(n)}\n className=\"xicms-admin-btn h-9 min-w-9 rounded-md border border-slate-200 px-2 text-sm font-medium text-slate-700 hover:bg-slate-100 aria-[checked=true]:border-slate-900 aria-[checked=true]:bg-slate-900 aria-[checked=true]:text-white\"\n >\n {f.key === \"rating\" ? \"★\".repeat(n) : n}\n </button>\n ))}\n </div>\n </FieldRow>\n );\n }\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <Input\n type=\"number\"\n min={f.min}\n max={f.max}\n step={f.step}\n value={v == null ? \"\" : String(v)}\n onChange={(e) => set(e.target.value === \"\" ? undefined : Number(e.target.value))}\n />\n </FieldRow>\n );\n case \"slider\": {\n const val = typeof v === \"number\" ? v : f.min;\n return (\n <FieldRow label={`${f.label} (${val})`} hint={f.hint}>\n <input\n type=\"range\"\n min={f.min}\n max={f.max}\n step={f.step ?? 1}\n value={val}\n onChange={(e) => set(Number(e.target.value))}\n className=\"w-full\"\n />\n </FieldRow>\n );\n }\n case \"date\":\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <Input type=\"date\" value={String(v ?? \"\")} onChange={(e) => set(e.target.value)} />\n </FieldRow>\n );\n case \"richtext\":\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <RichTextEditor siteId={siteId} value={String(v ?? \"\")} onChange={set} />\n </FieldRow>\n );\n case \"image\":\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <ImageField siteId={siteId} value={v ? String(v) : undefined} onChange={(url) => set(url ?? \"\")} />\n </FieldRow>\n );\n case \"url\":\n // 8.10: een link (href) via het linkvenster met de pagina's van de site; een technische URL\n // (embed, video, bestand) blijft een tekstveld.\n return (\n <FieldRow label={f.label} hint={f.hint}>\n {/href$/i.test(f.key) || f.key === \"link\" ? (\n <LinkVeld siteId={siteId} value={String(v ?? \"\")} onChange={set} />\n ) : (\n <Input value={String(v ?? \"\")} onChange={(e) => set(e.target.value)} placeholder=\"https://…\" />\n )}\n </FieldRow>\n );\n case \"icon\":\n return (\n <FieldRow label={f.label} hint={f.hint ?? \"Emoji, bv. ✂️\"}>\n <Input value={String(v ?? \"\")} maxLength={16} onChange={(e) => set(e.target.value)} className=\"w-24\" />\n </FieldRow>\n );\n case \"link\": {\n const link = (v as { label?: string; href?: string } | undefined) ?? {};\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <div className=\"grid gap-2\">\n <Input value={link.label ?? \"\"} placeholder=\"Tekst op de knop\" onChange={(e) => set({ ...link, label: e.target.value })} />\n <LinkVeld siteId={siteId} value={link.href ?? \"\"} onChange={(href) => set({ ...link, href })} />\n </div>\n </FieldRow>\n );\n }\n case \"group\": {\n const group = (v as Record<string, unknown> | undefined) ?? {};\n return (\n <fieldset className=\"grid gap-2 rounded-lg border border-slate-200 p-3\">\n <legend className=\"px-1 text-xs font-semibold text-slate-500\">{f.label}</legend>\n <FieldsForm fields={f.fields} values={group} onChange={(p) => set({ ...group, ...p })} siteId={siteId} />\n </fieldset>\n );\n }\n case \"repeater\": {\n const items = (Array.isArray(v) ? v : []) as Record<string, unknown>[];\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <ArrayEditor<Record<string, unknown>>\n items={items}\n onChange={set}\n newItem={() => fieldsDefaults(f.fields)}\n addLabel={`+ ${f.itemLabel ?? \"Item\"}`}\n renderRow={(item, update) => (\n <FieldsForm fields={f.fields} values={item} onChange={(p) => update(p)} siteId={siteId} />\n )}\n />\n </FieldRow>\n );\n }\n case \"pageRef\":\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <PageRefPicker siteId={siteId} value={String(v ?? \"\")} onChange={set} />\n </FieldRow>\n );\n case \"info\":\n return <p className=\"text-xs text-slate-500\">{f.text}</p>;\n case \"textarea\":\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <Textarea rows={f.rows ?? 4} value={String(v ?? \"\")} onChange={(e) => set(e.target.value)} />\n </FieldRow>\n );\n case \"json\":\n return <JsonField label={f.label} value={v} onCommit={set} schema={jsonSchema} />;\n case \"text\":\n default:\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <Input value={String(v ?? \"\")} placeholder={f.type === \"text\" ? f.placeholder : undefined} onChange={(e) => set(e.target.value)} />\n {lengteAdvies(f.key, typeof v === \"string\" ? v : \"\") && <p className=\"mt-1 text-xs text-amber-700\">{lengteAdvies(f.key, String(v))}</p>}\n </FieldRow>\n );\n }\n}\n\n/** Pagina-verwijzing: kies uit de bestaande pagina's van de site (live lijst). */\nfunction PageRefPicker({ siteId, value, onChange }: { siteId: string; value: string; onChange: (v: string) => void }) {\n const [pages, setPages] = useState<DraftPage[]>([]);\n useEffect(() => subscribePages(siteId, setPages), [siteId]);\n const options = useMemo(() => {\n const opts = 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 // Bewaar een waarde die (nog) niet in de lijst staat, zodat niets stilletjes wegvalt.\n if (value && !opts.some((o) => o.value === value)) opts.unshift({ value, label: value });\n return [{ value: \"\", label: \"— geen —\" }, ...opts];\n }, [pages, value]);\n return <Select value={value} onValueChange={onChange} options={options} />;\n}\n\n/** Laatste redmiddel voor complexe velden: JSON met schema-validatie vóór commit. */\nfunction JsonField({\n label,\n value,\n onCommit,\n schema,\n}: {\n label: string;\n value: unknown;\n onCommit: (v: unknown) => void;\n schema?: ZodTypeAny;\n}) {\n const [text, setText] = useState(() => JSON.stringify(value ?? null, null, 2));\n const [error, setError] = useState<string | null>(null);\n // Committeert de gegeven tekst (niet de state — die is bij een net getypte toets nog niet\n // bijgewerkt). `silent`: tijdens het typen geen foutmelding tonen voor onvolledige JSON (bv.\n // een net geopende `[` of `{`) — pas bij blur laten we die zien. VEILIGHEIDSNET: committeert bij\n // élke wijziging i.p.v. uitsluitend op blur, want blur bleek op mobiel Safari niet altijd te\n // vuren vóór een externe \"Opslaan\"-klik (race), waardoor een bewerking hier stil verloren ging.\n const commit = (raw: string, opts: { silent: boolean }) => {\n try {\n const parsed = JSON.parse(raw) as unknown;\n if (schema) {\n const res = safeParse(schema, parsed);\n if (!res.success) {\n if (!opts.silent) setError(\"Voldoet niet aan het verwachte formaat van dit veld.\");\n return;\n }\n setError(null);\n onCommit(res.data);\n return;\n }\n setError(null);\n onCommit(parsed);\n } catch {\n if (!opts.silent) setError(\"Geen geldige JSON.\");\n }\n };\n return (\n <FieldRow label={`${label} (geavanceerd)`} hint=\"Technisch veld — vraag bij twijfel Xi Webdesign. Wordt gecontroleerd vóór opslaan.\">\n <Textarea\n rows={6}\n value={text}\n onChange={(e) => {\n setText(e.target.value);\n commit(e.target.value, { silent: true });\n }}\n onBlur={() => commit(text, { silent: false })}\n spellCheck={false}\n className=\"font-mono text-xs\"\n />\n {error && <p className=\"text-xs text-red-600\">{error}</p>}\n </FieldRow>\n );\n}\n\n/**\n * De blok-editor-fallback: leidt de Field-IR af uit het Zod-schema van het blok (+ optionele\n * `fields`-hints van `defineBlock`) en rendert het formulier. Zo is een blok zonder maatwerk-\n * editor nooit een doodlopend pad voor de klant.\n */\nexport function GenericEditor({ block, siteId, onChange }: GenericEditorProps) {\n const registry = useRegistry();\n const def = registry.get(String(block._type ?? \"\"));\n const fields = useMemo(() => {\n if (!def) return [];\n // Custom blocks (5.0) dragen hun opgeslagen Field-IR mee — rijker dan introspectie\n // (showIf/date/slider-metadata gaat door fieldsToZod heen verloren).\n const custom = (def as { customFields?: Field[] }).customFields;\n // 8.11: Nederlandse labels, keuzes en passende widgets (zie lib/veldTaal).\n return vertaalVelden(custom ?? introspectToFields(def.schema, def.fields), def.type);\n }, [def]);\n // Sub-schema's voor json-velden (validatie vóór commit), uit de platte introspectie.\n const jsonSchemas = useMemo(() => {\n if (!def) return {};\n const out: Record<string, ZodTypeAny> = {};\n for (const f of introspectObjectSchema(def.schema)) if (f.kind === \"json\") out[f.key] = f.schema;\n return out;\n }, [def]);\n if (fields.length === 0) {\n return <p className=\"text-sm text-slate-500\">Voor dit bloktype is geen editor beschikbaar.</p>;\n }\n return (\n <FieldsForm\n fields={fields}\n values={block}\n onChange={(p) => onChange({ ...block, ...p })}\n siteId={siteId}\n jsonSchemas={jsonSchemas}\n />\n );\n}\n\n/**\n * Keuzelijst. Toont de waarde, anders de schema-default, anders optie 1 — dat is wat de site\n * rendert (elk keuzeveld heeft een default: de ingebouwde schema's zelf, maatwerkvelden via\n * `fieldsToZod`). Tot 8.10 schreef dit bij openen optie 1 weg \"zodat weergave = opslag\"; gevolg:\n * alleen het tandwiel aanklikken gaf al \"1 wijziging\" en een publiceerknop die iets te doen had.\n */\nfunction SelectField({\n f,\n v,\n set,\n}: {\n f: Extract<Field, { type: \"select\" }>;\n v: unknown;\n set: (val: unknown) => void;\n}) {\n return (\n <FieldRow label={f.label} hint={f.hint}>\n <Select\n value={String(v ?? f.standaard ?? f.options[0]?.value ?? \"\")}\n onValueChange={set}\n options={f.options.map((o) => ({ value: o.value, label: o.label || o.value }))}\n />\n </FieldRow>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -2,11 +2,23 @@
|
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Field, Input } from "../ui/primitives.js";
|
|
4
4
|
import { Select } from "../ui/select.js";
|
|
5
|
+
import { KleurVeld } from "../ui/KleurVeld.js";
|
|
6
|
+
import { slugify } from "../lib/slugify.js";
|
|
7
|
+
import { useMergedSiteConfig } from "../../settings/useSiteSettings.js";
|
|
5
8
|
function StyleEditor({
|
|
6
9
|
value = {},
|
|
7
10
|
onChange
|
|
8
11
|
}) {
|
|
9
12
|
const update = (part) => onChange({ ...value, ...part });
|
|
13
|
+
const theme = useMergedSiteConfig().theme ?? {};
|
|
14
|
+
const stalen = [
|
|
15
|
+
{ label: "Merkkleur", kleur: theme.primary ?? "" },
|
|
16
|
+
{ label: "Accentkleur", kleur: theme.accent ?? "" },
|
|
17
|
+
{ label: "Achtergrond", kleur: theme.background ?? "" },
|
|
18
|
+
{ label: "Tekstkleur", kleur: theme.foreground ?? "" },
|
|
19
|
+
{ label: "Lichtgrijs", kleur: "#f5f5f4" },
|
|
20
|
+
{ label: "Wit", kleur: "#ffffff" }
|
|
21
|
+
];
|
|
10
22
|
return /* @__PURE__ */ jsxs("details", { className: "rounded-lg border border-slate-200 p-3", children: [
|
|
11
23
|
/* @__PURE__ */ jsx("summary", { className: "cursor-pointer text-sm font-medium text-slate-700", children: "Blokstijl" }),
|
|
12
24
|
/* @__PURE__ */ jsxs("div", { className: "mt-3 grid gap-3", children: [
|
|
@@ -34,7 +46,7 @@ function StyleEditor({
|
|
|
34
46
|
options: [
|
|
35
47
|
{ value: "", label: "Standaard" },
|
|
36
48
|
{ value: "narrow", label: "Smal" },
|
|
37
|
-
{ value: "container", label: "
|
|
49
|
+
{ value: "container", label: "Normale breedte" },
|
|
38
50
|
{ value: "full", label: "Volle breedte" }
|
|
39
51
|
]
|
|
40
52
|
}
|
|
@@ -52,10 +64,32 @@ function StyleEditor({
|
|
|
52
64
|
]
|
|
53
65
|
}
|
|
54
66
|
) }),
|
|
55
|
-
/* @__PURE__ */ jsx(
|
|
67
|
+
/* @__PURE__ */ jsx(
|
|
68
|
+
KleurVeld,
|
|
69
|
+
{
|
|
70
|
+
label: "Achtergrondkleur",
|
|
71
|
+
hint: "De tekstkleur past zich vanzelf aan, zodat het leesbaar blijft.",
|
|
72
|
+
value: value.background ?? "",
|
|
73
|
+
placeholder: "geen",
|
|
74
|
+
onChange: (v) => update({ background: v || void 0 }),
|
|
75
|
+
stalen,
|
|
76
|
+
wisbaar: true
|
|
77
|
+
}
|
|
78
|
+
)
|
|
56
79
|
] }),
|
|
57
80
|
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-3", children: [
|
|
58
|
-
/* @__PURE__ */ jsx(Field, { label: "
|
|
81
|
+
/* @__PURE__ */ jsx(Field, { label: "Sprongnaam (optioneel)", hint: "Hiermee kun je naar dit blok linken, bv. /pagina#contact", children: /* @__PURE__ */ jsx(
|
|
82
|
+
Input,
|
|
83
|
+
{
|
|
84
|
+
value: value.anchorId ?? "",
|
|
85
|
+
onChange: (e) => update({ anchorId: e.target.value || void 0 }),
|
|
86
|
+
onBlur: () => {
|
|
87
|
+
const schoon = slugify(value.anchorId ?? "");
|
|
88
|
+
if ((value.anchorId ?? "") !== schoon) update({ anchorId: schoon || void 0 });
|
|
89
|
+
},
|
|
90
|
+
placeholder: "bv. contact"
|
|
91
|
+
}
|
|
92
|
+
) }),
|
|
59
93
|
/* @__PURE__ */ jsx(Field, { label: "Animatie (bij scrollen)", children: /* @__PURE__ */ jsx(
|
|
60
94
|
Select,
|
|
61
95
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/blockEditors/StyleEditor.tsx"],"sourcesContent":["\"use client\";\n\nimport type { BlockStyle } from \"../../schema/blocks\";\nimport { Field, Input } from \"../ui/primitives\";\nimport { Select } from \"../ui/select\";\n\n/**\n * Inklapbare \"Blokstijl\"-sectie die voor ELK block beschikbaar is (gedeelde `_style`): verticale\n * ruimte, achtergrond, breedte, uitlijning en een anker-id. Wordt generiek aan de block-editors\n * toegevoegd, dus elk block krijgt deze opties zonder zijn editor te wijzigen.\n */\nexport function StyleEditor({\n value = {},\n onChange,\n}: {\n value?: BlockStyle;\n onChange: (style: BlockStyle) => void;\n}) {\n const update = (part: Partial<BlockStyle>) => onChange({ ...value, ...part });\n return (\n <details className=\"rounded-lg border border-slate-200 p-3\">\n <summary className=\"cursor-pointer text-sm font-medium text-slate-700\">Blokstijl</summary>\n <div className=\"mt-3 grid gap-3\">\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Ruimte boven/onder\">\n <Select\n value={value.paddingY ?? \"\"}\n onValueChange={(v) => update({ paddingY: (v || undefined) as BlockStyle[\"paddingY\"] })}\n options={[\n { value: \"\", label: \"Standaard\" },\n { value: \"none\", label: \"Geen\" },\n { value: \"sm\", label: \"Klein\" },\n { value: \"md\", label: \"Normaal\" },\n { value: \"lg\", label: \"Groot\" },\n { value: \"xl\", label: \"Extra groot\" },\n ]}\n />\n </Field>\n <Field label=\"Breedte\">\n <Select\n value={value.width ?? \"\"}\n onValueChange={(v) => update({ width: (v || undefined) as BlockStyle[\"width\"] })}\n options={[\n { value: \"\", label: \"Standaard\" },\n { value: \"narrow\", label: \"Smal\" },\n { value: \"container\", label: \"
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/blockEditors/StyleEditor.tsx"],"sourcesContent":["\"use client\";\n\nimport type { BlockStyle } from \"../../schema/blocks\";\nimport { Field, Input } from \"../ui/primitives\";\nimport { Select } from \"../ui/select\";\nimport { KleurVeld } from \"../ui/KleurVeld\";\nimport { slugify } from \"../lib/slugify\";\nimport { useMergedSiteConfig } from \"../../settings/useSiteSettings\";\n\n/**\n * Inklapbare \"Blokstijl\"-sectie die voor ELK block beschikbaar is (gedeelde `_style`): verticale\n * ruimte, achtergrond, breedte, uitlijning en een anker-id. Wordt generiek aan de block-editors\n * toegevoegd, dus elk block krijgt deze opties zonder zijn editor te wijzigen.\n */\nexport function StyleEditor({\n value = {},\n onChange,\n}: {\n value?: BlockStyle;\n onChange: (style: BlockStyle) => void;\n}) {\n const update = (part: Partial<BlockStyle>) => onChange({ ...value, ...part });\n // Huisstijlkleuren als stalen (8.2): een blokachtergrond in een eigen merkkleur is één klik.\n const theme = useMergedSiteConfig().theme ?? {};\n const stalen = [\n { label: \"Merkkleur\", kleur: theme.primary ?? \"\" },\n { label: \"Accentkleur\", kleur: theme.accent ?? \"\" },\n { label: \"Achtergrond\", kleur: theme.background ?? \"\" },\n { label: \"Tekstkleur\", kleur: theme.foreground ?? \"\" },\n { label: \"Lichtgrijs\", kleur: \"#f5f5f4\" },\n { label: \"Wit\", kleur: \"#ffffff\" },\n ];\n return (\n <details className=\"rounded-lg border border-slate-200 p-3\">\n <summary className=\"cursor-pointer text-sm font-medium text-slate-700\">Blokstijl</summary>\n <div className=\"mt-3 grid gap-3\">\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Ruimte boven/onder\">\n <Select\n value={value.paddingY ?? \"\"}\n onValueChange={(v) => update({ paddingY: (v || undefined) as BlockStyle[\"paddingY\"] })}\n options={[\n { value: \"\", label: \"Standaard\" },\n { value: \"none\", label: \"Geen\" },\n { value: \"sm\", label: \"Klein\" },\n { value: \"md\", label: \"Normaal\" },\n { value: \"lg\", label: \"Groot\" },\n { value: \"xl\", label: \"Extra groot\" },\n ]}\n />\n </Field>\n <Field label=\"Breedte\">\n <Select\n value={value.width ?? \"\"}\n onValueChange={(v) => update({ width: (v || undefined) as BlockStyle[\"width\"] })}\n options={[\n { value: \"\", label: \"Standaard\" },\n { value: \"narrow\", label: \"Smal\" },\n { value: \"container\", label: \"Normale breedte\" },\n { value: \"full\", label: \"Volle breedte\" },\n ]}\n />\n </Field>\n <Field label=\"Uitlijning\">\n <Select\n value={value.align ?? \"\"}\n onValueChange={(v) => update({ align: (v || undefined) as BlockStyle[\"align\"] })}\n options={[\n { value: \"\", label: \"Standaard\" },\n { value: \"left\", label: \"Links\" },\n { value: \"center\", label: \"Midden\" },\n { value: \"right\", label: \"Rechts\" },\n ]}\n />\n </Field>\n <KleurVeld\n label=\"Achtergrondkleur\"\n hint=\"De tekstkleur past zich vanzelf aan, zodat het leesbaar blijft.\"\n value={value.background ?? \"\"}\n placeholder=\"geen\"\n onChange={(v) => update({ background: v || undefined })}\n stalen={stalen}\n wisbaar\n />\n </div>\n <div className=\"grid grid-cols-2 gap-3\">\n <Field label=\"Sprongnaam (optioneel)\" hint=\"Hiermee kun je naar dit blok linken, bv. /pagina#contact\">\n <Input\n value={value.anchorId ?? \"\"}\n onChange={(e) => update({ anchorId: e.target.value || undefined })}\n // 8.10: spaties en hoofdletters maken een sprongnaam onbruikbaar in een link.\n onBlur={() => {\n const schoon = slugify(value.anchorId ?? \"\");\n if ((value.anchorId ?? \"\") !== schoon) update({ anchorId: schoon || undefined });\n }}\n placeholder=\"bv. contact\"\n />\n </Field>\n <Field label=\"Animatie (bij scrollen)\">\n <Select\n value={value.animate ?? \"\"}\n onValueChange={(v) => update({ animate: (v || undefined) as BlockStyle[\"animate\"] })}\n options={[\n { value: \"\", label: \"Geen\" },\n { value: \"fade\", label: \"Vervagen\" },\n { value: \"up\", label: \"Omhoog schuiven\" },\n ]}\n />\n </Field>\n </div>\n </div>\n </details>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -4,16 +4,38 @@ import { useEffect, useMemo, useState } from "react";
|
|
|
4
4
|
import { Button, Field, Input } from "../ui/primitives.js";
|
|
5
5
|
import { Select } from "../ui/select.js";
|
|
6
6
|
import { useToast } from "../ui/toast.js";
|
|
7
|
-
import { subscribeSymbols, saveSymbol } from "../lib/symbolsClient.js";
|
|
7
|
+
import { subscribeSymbols, saveSymbol, subscribeSymbolVersions } from "../lib/symbolsClient.js";
|
|
8
|
+
import { useConfirm } from "../ui/ConfirmDialog.js";
|
|
8
9
|
import { NestedBlocksEditor } from "./index.js";
|
|
9
10
|
function SymbolRefEditor({ block, siteId, onChange }) {
|
|
10
11
|
const { toast } = useToast();
|
|
12
|
+
const confirm = useConfirm();
|
|
13
|
+
const [versies, setVersies] = useState([]);
|
|
11
14
|
const [symbols, setSymbols] = useState([]);
|
|
12
15
|
const [newName, setNewName] = useState("");
|
|
13
16
|
const [draftBlocks, setDraftBlocks] = useState(null);
|
|
14
17
|
const [saving, setSaving] = useState(false);
|
|
15
18
|
const symbolId = String(block.symbolId ?? "");
|
|
16
19
|
useEffect(() => subscribeSymbols(siteId, setSymbols), [siteId]);
|
|
20
|
+
useEffect(() => subscribeSymbolVersions(siteId, symbolId, setVersies), [siteId, symbolId]);
|
|
21
|
+
async function zetVersieTerug(v) {
|
|
22
|
+
const ok = await confirm({
|
|
23
|
+
title: "Deze versie terugzetten?",
|
|
24
|
+
description: "Hij komt meteen op elke pagina die dit symbool gebruikt. Wat er nu staat, blijft als versie bewaard.",
|
|
25
|
+
confirmLabel: "Terugzetten"
|
|
26
|
+
});
|
|
27
|
+
if (!ok || !current) return;
|
|
28
|
+
setSaving(true);
|
|
29
|
+
try {
|
|
30
|
+
await saveSymbol({ siteId, symbolId: current.id, name: v.name || current.name, blocks: v.blocks ?? [], translations: v.translations });
|
|
31
|
+
setDraftBlocks(v.blocks ?? []);
|
|
32
|
+
toast({ title: "Versie teruggezet", description: "Alle pagina's met dit symbool zijn bijgewerkt.", tone: "success" });
|
|
33
|
+
} catch (e) {
|
|
34
|
+
toast({ title: "Terugzetten mislukt", description: e.message, tone: "error" });
|
|
35
|
+
} finally {
|
|
36
|
+
setSaving(false);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
17
39
|
const current = useMemo(() => symbols.find((s) => s.id === symbolId), [symbols, symbolId]);
|
|
18
40
|
useEffect(() => {
|
|
19
41
|
setDraftBlocks(current ? current.blocks : null);
|
|
@@ -45,7 +67,27 @@ function SymbolRefEditor({ block, siteId, onChange }) {
|
|
|
45
67
|
] }) }),
|
|
46
68
|
current && draftBlocks && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
47
69
|
/* @__PURE__ */ jsx(Field, { label: `Inhoud van "${current.name}"`, children: /* @__PURE__ */ jsx(NestedBlocksEditor, { blocks: draftBlocks, siteId, onChange: setDraftBlocks, addLabel: "+ Blok in symbool\u2026" }) }),
|
|
48
|
-
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { type: "button", variant: "primary", size: "sm", disabled: saving, onClick: () => persist(current.name, draftBlocks, current.id), children:
|
|
70
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { loading: saving, type: "button", variant: "primary", size: "sm", disabled: saving, onClick: () => persist(current.name, draftBlocks, current.id), children: "Symbool opslaan (overal bijwerken)" }) }),
|
|
71
|
+
versies.length > 0 && /* @__PURE__ */ jsxs("details", { className: "rounded-lg border border-slate-200 p-3 text-sm", children: [
|
|
72
|
+
/* @__PURE__ */ jsxs("summary", { className: "cursor-pointer font-medium text-slate-700", children: [
|
|
73
|
+
"Eerdere versies (",
|
|
74
|
+
versies.length,
|
|
75
|
+
")"
|
|
76
|
+
] }),
|
|
77
|
+
/* @__PURE__ */ jsx("ul", { className: "mt-2 grid gap-1", children: versies.map((v) => {
|
|
78
|
+
const d = v.savedAt && typeof v.savedAt.toDate === "function" ? v.savedAt.toDate() : null;
|
|
79
|
+
return /* @__PURE__ */ jsxs("li", { className: "flex items-center justify-between gap-2", children: [
|
|
80
|
+
/* @__PURE__ */ jsxs("span", { className: "text-slate-600", children: [
|
|
81
|
+
d ? `Tot ${d.toLocaleString("nl-NL", { day: "numeric", month: "short", hour: "2-digit", minute: "2-digit" })}` : "Eerdere versie",
|
|
82
|
+
" \xB7 ",
|
|
83
|
+
(v.blocks ?? []).length,
|
|
84
|
+
" ",
|
|
85
|
+
(v.blocks ?? []).length === 1 ? "blok" : "blokken"
|
|
86
|
+
] }),
|
|
87
|
+
/* @__PURE__ */ jsx(Button, { type: "button", size: "sm", variant: "ghost", disabled: saving, onClick: () => void zetVersieTerug(v), children: "Terugzetten" })
|
|
88
|
+
] }, v.id);
|
|
89
|
+
}) })
|
|
90
|
+
] })
|
|
49
91
|
] })
|
|
50
92
|
] });
|
|
51
93
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/blockEditors/SymbolRefEditor.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * Editor voor het symbolRef-blok (5.0): kies een gedeeld symbool, of maak er een nieuwe aan,\n * en bewerk de INHOUD van het symbool direct in het zijpaneel (NestedBlocksEditor — dezelfde\n * geneste blok-editor als kolommen/zijbalk). Opslaan gaat via de saveSymbol-callable en\n * propageert naar élke pagina die het symbool gebruikt; de melding maakt dat expliciet.\n * Loskoppelen (kloon i.p.v. referentie) zit als actie op het blok in de VisualEditor.\n */\nimport { useEffect, useMemo, useState } from \"react\";\nimport { Button, Field, Input } from \"../ui/primitives\";\nimport { Select } from \"../ui/select\";\nimport { useToast } from \"../ui/toast\";\nimport { subscribeSymbols, saveSymbol } from \"../lib/symbolsClient\";\nimport type { StoredSymbol } from \"../../schema/symbols\";\nimport type { BlockEditorProps } from \"./index\";\nimport { NestedBlocksEditor } from \"./index\";\n\nexport function SymbolRefEditor({ block, siteId, onChange }: BlockEditorProps) {\n const { toast } = useToast();\n const [symbols, setSymbols] = useState<StoredSymbol[]>([]);\n const [newName, setNewName] = useState(\"\");\n const [draftBlocks, setDraftBlocks] = useState<Record<string, unknown>[] | null>(null);\n const [saving, setSaving] = useState(false);\n const symbolId = String(block.symbolId ?? \"\");\n\n useEffect(() => subscribeSymbols(siteId, setSymbols), [siteId]);\n const current = useMemo(() => symbols.find((s) => s.id === symbolId), [symbols, symbolId]);\n\n // Bewerk-buffer volgt het gekozen symbool (verse kopie bij wissel).\n useEffect(() => {\n setDraftBlocks(current ? (current.blocks as Record<string, unknown>[]) : null);\n }, [current?.id]); // eslint-disable-line react-hooks/exhaustive-deps\n\n async function persist(name: string, blocks: Record<string, unknown>[], id?: string) {\n setSaving(true);\n try {\n const res = await saveSymbol({ siteId, symbolId: id, name, blocks });\n if (!id) onChange({ ...block, symbolId: res.id });\n toast({ title: \"Symbool opgeslagen\", description: \"Alle pagina's met dit symbool zijn bijgewerkt.\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Opslaan mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setSaving(false);\n }\n }\n\n return (\n <div className=\"grid gap-3\">\n <Field label=\"Symbool\" hint=\"Een gedeelde sectie: wijzigingen gelden op élke pagina die dit symbool gebruikt.\">\n <Select\n value={symbolId}\n onValueChange={(v) => onChange({ ...block, symbolId: v })}\n options={[{ value: \"\", label: \"— kies een symbool —\" }, ...symbols.map((s) => ({ value: s.id, label: s.name }))]}\n />\n </Field>\n\n {!symbolId && (\n <Field label=\"Of maak een nieuw symbool\" hint=\"Begint leeg; voeg daarna blokken toe.\">\n <div className=\"flex items-center gap-2\">\n <Input value={newName} placeholder=\"Naam (bv. Afspraak-CTA)\" onChange={(e) => setNewName(e.target.value)} />\n <Button type=\"button\" variant=\"secondary\" size=\"sm\" disabled={!newName.trim() || saving} onClick={() => persist(newName.trim(), [])}>\n Maak\n </Button>\n </div>\n </Field>\n )}\n\n {current && draftBlocks && (\n <>\n <Field label={`Inhoud van \"${current.name}\"`}>\n <NestedBlocksEditor blocks={draftBlocks} siteId={siteId} onChange={setDraftBlocks} addLabel=\"+ Blok in symbool…\" />\n </Field>\n <div>\n <Button type=\"button\" variant=\"primary\" size=\"sm\" disabled={saving} onClick={() => persist(current.name, draftBlocks, current.id)}>\n {
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/blockEditors/SymbolRefEditor.tsx"],"sourcesContent":["\"use client\";\n\n/**\n * Editor voor het symbolRef-blok (5.0): kies een gedeeld symbool, of maak er een nieuwe aan,\n * en bewerk de INHOUD van het symbool direct in het zijpaneel (NestedBlocksEditor — dezelfde\n * geneste blok-editor als kolommen/zijbalk). Opslaan gaat via de saveSymbol-callable en\n * propageert naar élke pagina die het symbool gebruikt; de melding maakt dat expliciet.\n * Loskoppelen (kloon i.p.v. referentie) zit als actie op het blok in de VisualEditor.\n */\nimport { useEffect, useMemo, useState } from \"react\";\nimport { Button, Field, Input } from \"../ui/primitives\";\nimport { Select } from \"../ui/select\";\nimport { useToast } from \"../ui/toast\";\nimport { subscribeSymbols, saveSymbol, subscribeSymbolVersions, type SymboolVersie } from \"../lib/symbolsClient\";\nimport { useConfirm } from \"../ui/ConfirmDialog\";\nimport type { StoredSymbol } from \"../../schema/symbols\";\nimport type { BlockEditorProps } from \"./index\";\nimport { NestedBlocksEditor } from \"./index\";\n\nexport function SymbolRefEditor({ block, siteId, onChange }: BlockEditorProps) {\n const { toast } = useToast();\n const confirm = useConfirm();\n const [versies, setVersies] = useState<SymboolVersie[]>([]);\n const [symbols, setSymbols] = useState<StoredSymbol[]>([]);\n const [newName, setNewName] = useState(\"\");\n const [draftBlocks, setDraftBlocks] = useState<Record<string, unknown>[] | null>(null);\n const [saving, setSaving] = useState(false);\n const symbolId = String(block.symbolId ?? \"\");\n\n useEffect(() => subscribeSymbols(siteId, setSymbols), [siteId]);\n useEffect(() => subscribeSymbolVersions(siteId, symbolId, setVersies), [siteId, symbolId]);\n\n /** Een eerdere versie terugzetten (8.10) = die versie opnieuw opslaan; de huidige wordt zelf een versie. */\n async function zetVersieTerug(v: SymboolVersie) {\n const ok = await confirm({\n title: \"Deze versie terugzetten?\",\n description: \"Hij komt meteen op elke pagina die dit symbool gebruikt. Wat er nu staat, blijft als versie bewaard.\",\n confirmLabel: \"Terugzetten\",\n });\n if (!ok || !current) return;\n setSaving(true);\n try {\n await saveSymbol({ siteId, symbolId: current.id, name: v.name || current.name, blocks: v.blocks ?? [], translations: v.translations });\n setDraftBlocks(v.blocks ?? []);\n toast({ title: \"Versie teruggezet\", description: \"Alle pagina's met dit symbool zijn bijgewerkt.\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Terugzetten mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setSaving(false);\n }\n }\n const current = useMemo(() => symbols.find((s) => s.id === symbolId), [symbols, symbolId]);\n\n // Bewerk-buffer volgt het gekozen symbool (verse kopie bij wissel).\n useEffect(() => {\n setDraftBlocks(current ? (current.blocks as Record<string, unknown>[]) : null);\n }, [current?.id]); // eslint-disable-line react-hooks/exhaustive-deps\n\n async function persist(name: string, blocks: Record<string, unknown>[], id?: string) {\n setSaving(true);\n try {\n const res = await saveSymbol({ siteId, symbolId: id, name, blocks });\n if (!id) onChange({ ...block, symbolId: res.id });\n toast({ title: \"Symbool opgeslagen\", description: \"Alle pagina's met dit symbool zijn bijgewerkt.\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Opslaan mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setSaving(false);\n }\n }\n\n return (\n <div className=\"grid gap-3\">\n <Field label=\"Symbool\" hint=\"Een gedeelde sectie: wijzigingen gelden op élke pagina die dit symbool gebruikt.\">\n <Select\n value={symbolId}\n onValueChange={(v) => onChange({ ...block, symbolId: v })}\n options={[{ value: \"\", label: \"— kies een symbool —\" }, ...symbols.map((s) => ({ value: s.id, label: s.name }))]}\n />\n </Field>\n\n {!symbolId && (\n <Field label=\"Of maak een nieuw symbool\" hint=\"Begint leeg; voeg daarna blokken toe.\">\n <div className=\"flex items-center gap-2\">\n <Input value={newName} placeholder=\"Naam (bv. Afspraak-CTA)\" onChange={(e) => setNewName(e.target.value)} />\n <Button type=\"button\" variant=\"secondary\" size=\"sm\" disabled={!newName.trim() || saving} onClick={() => persist(newName.trim(), [])}>\n Maak\n </Button>\n </div>\n </Field>\n )}\n\n {current && draftBlocks && (\n <>\n <Field label={`Inhoud van \"${current.name}\"`}>\n <NestedBlocksEditor blocks={draftBlocks} siteId={siteId} onChange={setDraftBlocks} addLabel=\"+ Blok in symbool…\" />\n </Field>\n <div>\n <Button loading={saving} type=\"button\" variant=\"primary\" size=\"sm\" disabled={saving} onClick={() => persist(current.name, draftBlocks, current.id)}>\n {\"Symbool opslaan (overal bijwerken)\"}\n </Button>\n </div>\n {versies.length > 0 && (\n <details className=\"rounded-lg border border-slate-200 p-3 text-sm\">\n <summary className=\"cursor-pointer font-medium text-slate-700\">Eerdere versies ({versies.length})</summary>\n <ul className=\"mt-2 grid gap-1\">\n {versies.map((v) => {\n const d = v.savedAt && typeof (v.savedAt as { toDate?: () => Date }).toDate === \"function\" ? (v.savedAt as { toDate: () => Date }).toDate() : null;\n return (\n <li key={v.id} className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-600\">\n {d ? `Tot ${d.toLocaleString(\"nl-NL\", { day: \"numeric\", month: \"short\", hour: \"2-digit\", minute: \"2-digit\" })}` : \"Eerdere versie\"}\n {\" · \"}{(v.blocks ?? []).length} {(v.blocks ?? []).length === 1 ? \"blok\" : \"blokken\"}\n </span>\n <Button type=\"button\" size=\"sm\" variant=\"ghost\" disabled={saving} onClick={() => void zetVersieTerug(v)}>Terugzetten</Button>\n </li>\n );\n })}\n </ul>\n </details>\n )}\n </>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|