@xiwebdesign/xicms-core 7.30.0 → 8.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/XiCMSProvider.js +22 -7
- package/dist/XiCMSProvider.js.map +1 -1
- package/dist/admin/AdminApp.js +175 -93
- package/dist/admin/AdminApp.js.map +1 -1
- package/dist/admin/AdminHelp.d.ts +1 -1
- package/dist/admin/AdminHelp.js +44 -36
- package/dist/admin/AdminHelp.js.map +1 -1
- package/dist/admin/CoreVersion.d.ts +6 -3
- package/dist/admin/CoreVersion.js +60 -24
- package/dist/admin/CoreVersion.js.map +1 -1
- package/dist/admin/NewsEditor.d.ts +7 -0
- package/dist/admin/NewsEditor.js +117 -75
- package/dist/admin/NewsEditor.js.map +1 -1
- package/dist/admin/SuperadminPanel.js +1 -1
- package/dist/admin/SuperadminPanel.js.map +1 -1
- package/dist/admin/ZoekPalet.d.ts +15 -0
- package/dist/admin/ZoekPalet.js +123 -0
- package/dist/admin/ZoekPalet.js.map +1 -0
- package/dist/admin/blockEditors/GenericEditor.js +36 -18
- package/dist/admin/blockEditors/GenericEditor.js.map +1 -1
- package/dist/admin/blockEditors/StyleEditor.js +37 -3
- package/dist/admin/blockEditors/StyleEditor.js.map +1 -1
- package/dist/admin/blockEditors/SymbolRefEditor.js +44 -2
- package/dist/admin/blockEditors/SymbolRefEditor.js.map +1 -1
- package/dist/admin/blockEditors/index.js +154 -73
- package/dist/admin/blockEditors/index.js.map +1 -1
- package/dist/admin/customBlocks/CustomBlocksPanel.js +18 -7
- package/dist/admin/customBlocks/CustomBlocksPanel.js.map +1 -1
- package/dist/admin/dashboard/DashboardPanel.js +26 -16
- package/dist/admin/dashboard/DashboardPanel.js.map +1 -1
- package/dist/admin/editors/RichTextEditor.d.ts +4 -3
- package/dist/admin/editors/RichTextEditor.js +19 -56
- package/dist/admin/editors/RichTextEditor.js.map +1 -1
- package/dist/admin/editors/fontSizeExtension.js +7 -1
- package/dist/admin/editors/fontSizeExtension.js.map +1 -1
- package/dist/admin/editors/slashMenu.d.ts +18 -0
- package/dist/admin/editors/slashMenu.js +34 -0
- package/dist/admin/editors/slashMenu.js.map +1 -0
- package/dist/admin/editors/useRijkeTekst.d.ts +48 -0
- package/dist/admin/editors/useRijkeTekst.js +310 -0
- package/dist/admin/editors/useRijkeTekst.js.map +1 -0
- package/dist/admin/forms/FormsPanel.d.ts +11 -2
- package/dist/admin/forms/FormsPanel.js +218 -65
- package/dist/admin/forms/FormsPanel.js.map +1 -1
- package/dist/admin/lib/blokInfo.d.ts +17 -0
- package/dist/admin/lib/blokInfo.js +80 -0
- package/dist/admin/lib/blokInfo.js.map +1 -0
- package/dist/admin/lib/foutNaarMens.d.ts +1 -0
- package/dist/admin/lib/foutNaarMens.js +22 -0
- package/dist/admin/lib/foutNaarMens.js.map +1 -0
- package/dist/admin/lib/gewisteVelden.d.ts +13 -0
- package/dist/admin/lib/gewisteVelden.js +31 -0
- package/dist/admin/lib/gewisteVelden.js.map +1 -0
- package/dist/admin/lib/heroHulp.d.ts +11 -0
- package/dist/admin/lib/heroHulp.js +18 -0
- package/dist/admin/lib/heroHulp.js.map +1 -0
- package/dist/admin/lib/kleur.js +2 -3
- package/dist/admin/lib/kleur.js.map +1 -1
- package/dist/admin/lib/leesbaarheid.d.ts +34 -0
- package/dist/admin/lib/leesbaarheid.js +82 -0
- package/dist/admin/lib/leesbaarheid.js.map +1 -0
- package/dist/admin/lib/lengteAdvies.d.ts +1 -0
- package/dist/admin/lib/lengteAdvies.js +16 -0
- package/dist/admin/lib/lengteAdvies.js.map +1 -0
- package/dist/admin/lib/mediaLijst.d.ts +26 -0
- package/dist/admin/lib/mediaLijst.js +42 -0
- package/dist/admin/lib/mediaLijst.js.map +1 -0
- package/dist/admin/lib/mediaUsage.d.ts +12 -1
- package/dist/admin/lib/mediaUsage.js +43 -33
- package/dist/admin/lib/mediaUsage.js.map +1 -1
- package/dist/admin/lib/menuHulp.d.ts +16 -0
- package/dist/admin/lib/menuHulp.js +41 -0
- package/dist/admin/lib/menuHulp.js.map +1 -0
- package/dist/admin/lib/onopgeslagen.d.ts +10 -0
- package/dist/admin/lib/onopgeslagen.js +35 -0
- package/dist/admin/lib/onopgeslagen.js.map +1 -0
- package/dist/admin/lib/pagesClient.d.ts +55 -2
- package/dist/admin/lib/pagesClient.js +126 -28
- package/dist/admin/lib/pagesClient.js.map +1 -1
- package/dist/admin/lib/paginaGebruik.d.ts +56 -0
- package/dist/admin/lib/paginaGebruik.js +109 -0
- package/dist/admin/lib/paginaGebruik.js.map +1 -0
- package/dist/admin/lib/publicatieCheck.d.ts +25 -0
- package/dist/admin/lib/publicatieCheck.js +114 -0
- package/dist/admin/lib/publicatieCheck.js.map +1 -0
- package/dist/admin/lib/scrollNaarDetail.d.ts +6 -0
- package/dist/admin/lib/scrollNaarDetail.js +20 -0
- package/dist/admin/lib/scrollNaarDetail.js.map +1 -0
- package/dist/admin/lib/symbolsClient.d.ts +10 -0
- package/dist/admin/lib/symbolsClient.js +14 -1
- package/dist/admin/lib/symbolsClient.js.map +1 -1
- package/dist/admin/lib/tekstVeld.d.ts +8 -0
- package/dist/admin/lib/tekstVeld.js +10 -0
- package/dist/admin/lib/tekstVeld.js.map +1 -0
- package/dist/admin/lib/useIsSuperadmin.d.ts +2 -0
- package/dist/admin/lib/useIsSuperadmin.js +13 -0
- package/dist/admin/lib/useIsSuperadmin.js.map +1 -0
- package/dist/admin/lib/veldTaal.d.ts +14 -0
- package/dist/admin/lib/veldTaal.js +247 -0
- package/dist/admin/lib/veldTaal.js.map +1 -0
- package/dist/admin/lib/versieVergelijk.d.ts +17 -0
- package/dist/admin/lib/versieVergelijk.js +24 -0
- package/dist/admin/lib/versieVergelijk.js.map +1 -0
- package/dist/admin/lib/zodFields.js +22 -4
- package/dist/admin/lib/zodFields.js.map +1 -1
- package/dist/admin/lib/zodFout.d.ts +9 -0
- package/dist/admin/lib/zodFout.js +63 -0
- package/dist/admin/lib/zodFout.js.map +1 -0
- package/dist/admin/media/MediaManager.js +162 -32
- package/dist/admin/media/MediaManager.js.map +1 -1
- package/dist/admin/media/MediaPicker.d.ts +3 -0
- package/dist/admin/media/MediaPicker.js +84 -31
- package/dist/admin/media/MediaPicker.js.map +1 -1
- package/dist/admin/menu/MenuPanel.js +144 -83
- package/dist/admin/menu/MenuPanel.js.map +1 -1
- package/dist/admin/navContext.d.ts +3 -0
- package/dist/admin/navContext.js +13 -1
- package/dist/admin/navContext.js.map +1 -1
- package/dist/admin/pages/PageEditor.js +146 -30
- package/dist/admin/pages/PageEditor.js.map +1 -1
- package/dist/admin/pages/PagesPanel.js +215 -61
- package/dist/admin/pages/PagesPanel.js.map +1 -1
- package/dist/admin/pages/StarterKiezer.d.ts +12 -0
- package/dist/admin/pages/StarterKiezer.js +113 -0
- package/dist/admin/pages/StarterKiezer.js.map +1 -0
- package/dist/admin/panelRegistry.d.ts +1 -1
- package/dist/admin/panelRegistry.js +2 -1
- package/dist/admin/panelRegistry.js.map +1 -1
- package/dist/admin/patterns/PatternInserter.js +1 -1
- package/dist/admin/patterns/PatternInserter.js.map +1 -1
- package/dist/admin/settings/BedrijfInstellingen.d.ts +20 -0
- package/dist/admin/settings/BedrijfInstellingen.js +144 -0
- package/dist/admin/settings/BedrijfInstellingen.js.map +1 -0
- package/dist/admin/settings/MailSettings.js +2 -2
- package/dist/admin/settings/MailSettings.js.map +1 -1
- package/dist/admin/settings/MailTemplates.js +5 -4
- package/dist/admin/settings/MailTemplates.js.map +1 -1
- package/dist/admin/settings/SettingsPanel.js +120 -78
- package/dist/admin/settings/SettingsPanel.js.map +1 -1
- package/dist/admin/settings/SnapshotsCard.js +4 -4
- package/dist/admin/settings/SnapshotsCard.js.map +1 -1
- package/dist/admin/settings/VorigeTerugzetten.d.ts +15 -0
- package/dist/admin/settings/VorigeTerugzetten.js +89 -0
- package/dist/admin/settings/VorigeTerugzetten.js.map +1 -0
- package/dist/admin/shop/CategoriesTab.js +6 -4
- package/dist/admin/shop/CategoriesTab.js.map +1 -1
- package/dist/admin/shop/DiscountsTab.js +4 -2
- package/dist/admin/shop/DiscountsTab.js.map +1 -1
- package/dist/admin/shop/OrdersTab.js +57 -19
- package/dist/admin/shop/OrdersTab.js.map +1 -1
- package/dist/admin/shop/ProductPaneel.js +2 -1
- package/dist/admin/shop/ProductPaneel.js.map +1 -1
- package/dist/admin/shop/ProductsTab.js +40 -19
- package/dist/admin/shop/ProductsTab.js.map +1 -1
- package/dist/admin/shop/ShopPanel.js +13 -1
- package/dist/admin/shop/ShopPanel.js.map +1 -1
- package/dist/admin/shop/ShopSettingsTab.js +27 -1
- package/dist/admin/shop/ShopSettingsTab.js.map +1 -1
- package/dist/admin/shop/productClient.js +7 -3
- package/dist/admin/shop/productClient.js.map +1 -1
- package/dist/admin/stats/NietGevonden.d.ts +10 -0
- package/dist/admin/stats/NietGevonden.js +78 -0
- package/dist/admin/stats/NietGevonden.js.map +1 -0
- package/dist/admin/stats/StatsPanel.js +6 -1
- package/dist/admin/stats/StatsPanel.js.map +1 -1
- package/dist/admin/stats/lib.d.ts +2 -0
- package/dist/admin/stats/lib.js.map +1 -1
- package/dist/admin/ui/ConfirmDialog.js +10 -1
- package/dist/admin/ui/ConfirmDialog.js.map +1 -1
- package/dist/admin/ui/Icon.d.ts +34 -0
- package/dist/admin/ui/Icon.js +44 -0
- package/dist/admin/ui/Icon.js.map +1 -0
- package/dist/admin/ui/ImageField.d.ts +15 -0
- package/dist/admin/ui/ImageField.js +67 -0
- package/dist/admin/ui/ImageField.js.map +1 -0
- package/dist/admin/ui/KleurVeld.d.ts +25 -0
- package/dist/admin/ui/KleurVeld.js +76 -0
- package/dist/admin/ui/KleurVeld.js.map +1 -0
- package/dist/admin/ui/LaadStaat.d.ts +21 -0
- package/dist/admin/ui/LaadStaat.js +43 -0
- package/dist/admin/ui/LaadStaat.js.map +1 -0
- package/dist/admin/ui/LeesbaarheidPaneel.d.ts +10 -0
- package/dist/admin/ui/LeesbaarheidPaneel.js +68 -0
- package/dist/admin/ui/LeesbaarheidPaneel.js.map +1 -0
- package/dist/admin/ui/LinkDialog.d.ts +22 -0
- package/dist/admin/ui/LinkDialog.js +131 -0
- package/dist/admin/ui/LinkDialog.js.map +1 -0
- package/dist/admin/ui/LinkVeld.d.ts +14 -0
- package/dist/admin/ui/LinkVeld.js +49 -0
- package/dist/admin/ui/LinkVeld.js.map +1 -0
- package/dist/admin/ui/PreviewLinkResultaat.d.ts +14 -0
- package/dist/admin/ui/PreviewLinkResultaat.js +52 -0
- package/dist/admin/ui/PreviewLinkResultaat.js.map +1 -0
- package/dist/admin/ui/charts.js +5 -5
- package/dist/admin/ui/charts.js.map +1 -1
- package/dist/admin/ui/primitives.d.ts +16 -6
- package/dist/admin/ui/primitives.js +98 -26
- package/dist/admin/ui/primitives.js.map +1 -1
- package/dist/admin/ui/select.js +5 -2
- package/dist/admin/ui/select.js.map +1 -1
- package/dist/admin/ui/switch.d.ts +3 -1
- package/dist/admin/ui/switch.js +6 -3
- package/dist/admin/ui/switch.js.map +1 -1
- package/dist/admin/ui/toast.d.ts +2 -1
- package/dist/admin/ui/toast.js +17 -11
- package/dist/admin/ui/toast.js.map +1 -1
- package/dist/admin/visual/BlokKiezer.d.ts +34 -0
- package/dist/admin/visual/BlokKiezer.js +225 -0
- package/dist/admin/visual/BlokKiezer.js.map +1 -0
- package/dist/admin/visual/InlineGereedschap.d.ts +52 -0
- package/dist/admin/visual/InlineGereedschap.js +356 -0
- package/dist/admin/visual/InlineGereedschap.js.map +1 -0
- package/dist/admin/visual/InlineRijkeTekst.d.ts +23 -0
- package/dist/admin/visual/InlineRijkeTekst.js +152 -0
- package/dist/admin/visual/InlineRijkeTekst.js.map +1 -0
- package/dist/admin/visual/VisualEditor.js +273 -125
- package/dist/admin/visual/VisualEditor.js.map +1 -1
- package/dist/admin.css +1 -1
- package/dist/bedrijf/bedrijf.d.ts +36 -0
- package/dist/bedrijf/bedrijf.js +110 -0
- package/dist/bedrijf/bedrijf.js.map +1 -0
- package/dist/blocks/BlockRenderer.js +11 -1
- package/dist/blocks/BlockRenderer.js.map +1 -1
- package/dist/blocks/blockStyle.d.ts +7 -0
- package/dist/blocks/blockStyle.js +16 -3
- package/dist/blocks/blockStyle.js.map +1 -1
- package/dist/blocks/builtinSchemas.js +6 -0
- package/dist/blocks/builtinSchemas.js.map +1 -1
- package/dist/blocks/builtins/AgendaRender.d.ts +22 -0
- package/dist/blocks/builtins/AgendaRender.js +69 -9
- package/dist/blocks/builtins/AgendaRender.js.map +1 -1
- package/dist/blocks/builtins/Availability.d.ts +1 -0
- package/dist/blocks/builtins/Availability.js +23 -0
- package/dist/blocks/builtins/Availability.js.map +1 -0
- package/dist/blocks/builtins/AvailabilityRender.d.ts +12 -0
- package/dist/blocks/builtins/AvailabilityRender.js +105 -0
- package/dist/blocks/builtins/AvailabilityRender.js.map +1 -0
- package/dist/blocks/builtins/BeforeAfterRender.js +4 -3
- package/dist/blocks/builtins/BeforeAfterRender.js.map +1 -1
- package/dist/blocks/builtins/Booking.js +1 -1
- package/dist/blocks/builtins/Booking.js.map +1 -1
- package/dist/blocks/builtins/BreadcrumbsRender.d.ts +4 -3
- package/dist/blocks/builtins/BreadcrumbsRender.js +14 -8
- package/dist/blocks/builtins/BreadcrumbsRender.js.map +1 -1
- package/dist/blocks/builtins/ColumnsRender.d.ts +1 -1
- package/dist/blocks/builtins/ColumnsRender.js +3 -1
- package/dist/blocks/builtins/ColumnsRender.js.map +1 -1
- package/dist/blocks/builtins/Contact.js +1 -1
- package/dist/blocks/builtins/Contact.js.map +1 -1
- package/dist/blocks/builtins/ContactRender.d.ts +1 -1
- package/dist/blocks/builtins/ContactRender.js +29 -8
- package/dist/blocks/builtins/ContactRender.js.map +1 -1
- package/dist/blocks/builtins/Cta.js +1 -1
- package/dist/blocks/builtins/Cta.js.map +1 -1
- package/dist/blocks/builtins/CtaRender.d.ts +1 -1
- package/dist/blocks/builtins/CtaRender.js +5 -4
- package/dist/blocks/builtins/CtaRender.js.map +1 -1
- package/dist/blocks/builtins/Embed.js +1 -1
- package/dist/blocks/builtins/Embed.js.map +1 -1
- package/dist/blocks/builtins/FormBlock.js +1 -0
- package/dist/blocks/builtins/FormBlock.js.map +1 -1
- package/dist/blocks/builtins/FormBlockRender.d.ts +6 -0
- package/dist/blocks/builtins/FormBlockRender.js +88 -16
- package/dist/blocks/builtins/FormBlockRender.js.map +1 -1
- package/dist/blocks/builtins/GalleryRender.js +3 -2
- package/dist/blocks/builtins/GalleryRender.js.map +1 -1
- package/dist/blocks/builtins/Hero.js +1 -1
- package/dist/blocks/builtins/Hero.js.map +1 -1
- package/dist/blocks/builtins/HeroRender.js +7 -3
- package/dist/blocks/builtins/HeroRender.js.map +1 -1
- package/dist/blocks/builtins/OpenNowBadge.d.ts +4 -2
- package/dist/blocks/builtins/OpenNowBadge.js +6 -6
- package/dist/blocks/builtins/OpenNowBadge.js.map +1 -1
- package/dist/blocks/builtins/OpeningHoursRender.d.ts +8 -2
- package/dist/blocks/builtins/OpeningHoursRender.js +27 -6
- package/dist/blocks/builtins/OpeningHoursRender.js.map +1 -1
- package/dist/blocks/builtins/PriceList.d.ts +1 -0
- package/dist/blocks/builtins/PriceList.js +25 -0
- package/dist/blocks/builtins/PriceList.js.map +1 -0
- package/dist/blocks/builtins/PriceListRender.d.ts +17 -0
- package/dist/blocks/builtins/PriceListRender.js +87 -0
- package/dist/blocks/builtins/PriceListRender.js.map +1 -0
- package/dist/blocks/builtins/RichTextBlockRender.js +6 -1
- package/dist/blocks/builtins/RichTextBlockRender.js.map +1 -1
- package/dist/blocks/builtins/SectionHeading.d.ts +1 -0
- package/dist/blocks/builtins/SectionHeading.js +14 -0
- package/dist/blocks/builtins/SectionHeading.js.map +1 -0
- package/dist/blocks/builtins/SectionHeadingRender.d.ts +7 -0
- package/dist/blocks/builtins/SectionHeadingRender.js +14 -0
- package/dist/blocks/builtins/SectionHeadingRender.js.map +1 -0
- package/dist/blocks/builtins/SliderRender.js +3 -2
- package/dist/blocks/builtins/SliderRender.js.map +1 -1
- package/dist/blocks/builtins/SymbolRef.js +1 -1
- package/dist/blocks/builtins/SymbolRef.js.map +1 -1
- package/dist/blocks/builtins/TeamRender.js +6 -1
- package/dist/blocks/builtins/TeamRender.js.map +1 -1
- package/dist/blocks/builtins/Testimonials.js +3 -1
- package/dist/blocks/builtins/Testimonials.js.map +1 -1
- package/dist/blocks/builtins/TestimonialsRender.js +4 -0
- package/dist/blocks/builtins/TestimonialsRender.js.map +1 -1
- package/dist/blocks/builtins/WhatsappChatRender.d.ts +1 -1
- package/dist/blocks/builtins/WhatsappChatRender.js +1 -1
- package/dist/blocks/builtins/WhatsappChatRender.js.map +1 -1
- package/dist/blocks/builtins/Widgets.js +2 -2
- package/dist/blocks/builtins/Widgets.js.map +1 -1
- package/dist/blocks/builtins/WidgetsRender.js +3 -1
- package/dist/blocks/builtins/WidgetsRender.js.map +1 -1
- package/dist/blocks/builtins/index.d.ts +3 -0
- package/dist/blocks/builtins/index.js +6 -0
- package/dist/blocks/builtins/index.js.map +1 -1
- package/dist/blocks/builtins/lib/autoComplete.d.ts +7 -0
- package/dist/blocks/builtins/lib/autoComplete.js +20 -0
- package/dist/blocks/builtins/lib/autoComplete.js.map +1 -0
- package/dist/blocks/builtins/lib/bookingUrl.d.ts +2 -2
- package/dist/blocks/builtins/lib/bookingUrl.js +1 -1
- package/dist/blocks/builtins/lib/bookingUrl.js.map +1 -1
- package/dist/blocks/builtins/lib/ical.d.ts +24 -0
- package/dist/blocks/builtins/lib/ical.js +82 -0
- package/dist/blocks/builtins/lib/ical.js.map +1 -0
- package/dist/blocks/builtins/lib/vandaag.d.ts +8 -0
- package/dist/blocks/builtins/lib/vandaag.js +22 -0
- package/dist/blocks/builtins/lib/vandaag.js.map +1 -0
- package/dist/blocks/registry.d.ts +6 -0
- package/dist/blocks/registry.js.map +1 -1
- package/dist/blocks/ui/index.js +1 -0
- package/dist/blocks/ui/index.js.map +1 -1
- package/dist/components/EditBar.js +2 -4
- package/dist/components/EditBar.js.map +1 -1
- package/dist/components/News.js +26 -18
- package/dist/components/News.js.map +1 -1
- package/dist/components/PageView.d.ts +7 -1
- package/dist/components/PageView.js +17 -0
- package/dist/components/PageView.js.map +1 -1
- package/dist/components/ResponsiveImage.js +18 -20
- package/dist/components/ResponsiveImage.js.map +1 -1
- package/dist/components/site/SiteFooter.d.ts +6 -1
- package/dist/components/site/SiteFooter.js +61 -9
- package/dist/components/site/SiteFooter.js.map +1 -1
- package/dist/components/site/SiteHeader.d.ts +15 -0
- package/dist/components/site/SiteHeader.js +70 -0
- package/dist/components/site/SiteHeader.js.map +1 -0
- package/dist/components/site/SiteNav.d.ts +2 -0
- package/dist/components/site/SiteNav.js +29 -5
- package/dist/components/site/SiteNav.js.map +1 -1
- package/dist/demo/DemoStudio.js +2 -2
- package/dist/demo/DemoStudio.js.map +1 -1
- package/dist/demo/demoStore.d.ts +13 -0
- package/dist/demo/demoStore.js +36 -0
- package/dist/demo/demoStore.js.map +1 -1
- package/dist/editor/EditorProvider.js +15 -4
- package/dist/editor/EditorProvider.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/media/ImageContext.d.ts +17 -0
- package/dist/media/ImageContext.js +65 -20
- package/dist/media/ImageContext.js.map +1 -1
- package/dist/media/altInHtml.d.ts +9 -0
- package/dist/media/altInHtml.js +17 -0
- package/dist/media/altInHtml.js.map +1 -0
- package/dist/media/srcset.d.ts +12 -0
- package/dist/media/srcset.js +13 -0
- package/dist/media/srcset.js.map +1 -0
- package/dist/modules/builtins.d.ts +1 -0
- package/dist/modules/builtins.js +16 -3
- package/dist/modules/builtins.js.map +1 -1
- package/dist/modules/shop/blocks/Cart.js +5 -3
- package/dist/modules/shop/blocks/Cart.js.map +1 -1
- package/dist/modules/shop/blocks/Checkout.js +56 -35
- package/dist/modules/shop/blocks/Checkout.js.map +1 -1
- package/dist/modules/shop/blocks/Donation.js +4 -4
- package/dist/modules/shop/blocks/Donation.js.map +1 -1
- package/dist/modules/shop/blocks/ProductDetail.js +19 -3
- package/dist/modules/shop/blocks/ProductDetail.js.map +1 -1
- package/dist/modules/shop/blocks/ProductGrid.d.ts +3 -1
- package/dist/modules/shop/blocks/ProductGrid.js +8 -4
- package/dist/modules/shop/blocks/ProductGrid.js.map +1 -1
- package/dist/modules/shop/blocks/ShopCategories.js +4 -3
- package/dist/modules/shop/blocks/ShopCategories.js.map +1 -1
- package/dist/modules/shop/lib.d.ts +4 -0
- package/dist/modules/shop/lib.js +14 -0
- package/dist/modules/shop/lib.js.map +1 -1
- package/dist/modules/shop/settings.d.ts +3 -0
- package/dist/modules/shop/settings.js +14 -0
- package/dist/modules/shop/settings.js.map +1 -1
- package/dist/modules/shop/strings.d.ts +4 -0
- package/dist/modules/shop/strings.js +8 -0
- package/dist/modules/shop/strings.js.map +1 -1
- package/dist/next/envCheck.d.ts +42 -0
- package/dist/next/envCheck.js +106 -0
- package/dist/next/envCheck.js.map +1 -0
- package/dist/next/index.cjs +185 -2
- package/dist/next/index.d.ts +2 -0
- package/dist/next/index.js +8 -1
- package/dist/next/index.js.map +1 -1
- package/dist/next/securityHeaders.d.ts +36 -0
- package/dist/next/securityHeaders.js +74 -0
- package/dist/next/securityHeaders.js.map +1 -0
- package/dist/patterns/builtins.d.ts +7 -0
- package/dist/patterns/builtins.js +138 -3
- package/dist/patterns/builtins.js.map +1 -1
- package/dist/releaseNotes.js +140 -0
- package/dist/releaseNotes.js.map +1 -1
- package/dist/render/PublishedPage.d.ts +2 -1
- package/dist/render/PublishedPage.js +10 -4
- package/dist/render/PublishedPage.js.map +1 -1
- package/dist/schema/blocks.d.ts +470 -0
- package/dist/schema/blocks.js +102 -4
- package/dist/schema/blocks.js.map +1 -1
- package/dist/schema/business.d.ts +117 -0
- package/dist/schema/business.js +73 -0
- package/dist/schema/business.js.map +1 -0
- package/dist/schema/fields.d.ts +2 -1
- package/dist/schema/fields.js.map +1 -1
- package/dist/schema/forms.d.ts +18 -0
- package/dist/schema/forms.js +18 -3
- package/dist/schema/forms.js.map +1 -1
- package/dist/schema/mail.d.ts +10 -0
- package/dist/schema/mail.js +7 -0
- package/dist/schema/mail.js.map +1 -1
- package/dist/schema/settings.d.ts +101 -0
- package/dist/schema/settings.js +24 -3
- package/dist/schema/settings.js.map +1 -1
- package/dist/schema/shop.d.ts +2 -0
- package/dist/schema/shop.js +4 -0
- package/dist/schema/shop.js.map +1 -1
- package/dist/schema/shopGeld.d.ts +1 -0
- package/dist/schema/shopGeld.js +1 -0
- package/dist/schema/shopGeld.js.map +1 -1
- package/dist/schema/siteConfig.d.ts +68 -1
- package/dist/schema/siteConfig.js +7 -2
- package/dist/schema/siteConfig.js.map +1 -1
- package/dist/server/blockData.d.ts +1 -1
- package/dist/server/blockData.js +74 -18
- package/dist/server/blockData.js.map +1 -1
- package/dist/server/cspRapport.d.ts +20 -0
- package/dist/server/cspRapport.js +56 -0
- package/dist/server/cspRapport.js.map +1 -0
- package/dist/server/fonts.d.ts +3 -0
- package/dist/server/fonts.js +39 -0
- package/dist/server/fonts.js.map +1 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.js +8 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/sanitize.js +15 -2
- package/dist/server/sanitize.js.map +1 -1
- package/dist/settings/useSiteSettings.js +4 -1
- package/dist/settings/useSiteSettings.js.map +1 -1
- package/dist/starters/starters.d.ts +69 -0
- package/dist/starters/starters.js +171 -0
- package/dist/starters/starters.js.map +1 -0
- package/dist/styles.css +1149 -208
- package/dist/theme/color.d.ts +10 -0
- package/dist/theme/color.js +17 -1
- package/dist/theme/color.js.map +1 -1
- package/dist/theme/fontFallback.d.ts +23 -0
- package/dist/theme/fontFallback.js +58 -0
- package/dist/theme/fontFallback.js.map +1 -0
- package/dist/theme/fonts.d.ts +11 -0
- package/dist/theme/fonts.js +16 -0
- package/dist/theme/fonts.js.map +1 -0
- package/dist/version.js +1 -1
- package/package.json +6 -4
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useMemo, useState } from "react";
|
|
4
4
|
import { Button, Card, Field, Input } from "../ui/primitives.js";
|
|
5
5
|
import { Select } from "../ui/select.js";
|
|
6
|
-
import { Dialog,
|
|
6
|
+
import { Dialog, DialogContent } from "../ui/dialog.js";
|
|
7
7
|
import { useToast } from "../ui/toast.js";
|
|
8
8
|
import { useConfirm } from "../ui/ConfirmDialog.js";
|
|
9
|
-
import {
|
|
9
|
+
import { LaadStaat } from "../ui/LaadStaat.js";
|
|
10
|
+
import { isDemoActive } from "../../demo/demoStore.js";
|
|
11
|
+
import { neemOpenVerzoek } from "../navContext.js";
|
|
12
|
+
import { useScrollNaarDetail } from "../lib/scrollNaarDetail.js";
|
|
13
|
+
import { subscribePages, createPage, deletePage, restorePage, paginaToestand, publishPage, publicatieContext } from "../lib/pagesClient.js";
|
|
14
|
+
import { controleerPagina } from "../lib/publicatieCheck.js";
|
|
10
15
|
import { seoSignaal } from "../lib/seoHulp.js";
|
|
11
|
-
import { builtinPatterns, instantiatePattern } from "../../patterns/index.js";
|
|
16
|
+
import { builtinPatterns, collectPatternTypes, instantiatePattern } from "../../patterns/index.js";
|
|
17
|
+
import { useRegistry } from "../../blocks/context.js";
|
|
12
18
|
import { PageEditor, ToestandBadge } from "./PageEditor.js";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
19
|
+
import { slugify } from "../lib/slugify.js";
|
|
20
|
+
import { voegToeAanMenu, vrijPad } from "../lib/menuHulp.js";
|
|
21
|
+
import { Switch } from "../ui/switch.js";
|
|
22
|
+
import { useAuth } from "../../auth/AuthProvider.js";
|
|
23
|
+
import { canManageSite } from "../../auth/roles.js";
|
|
24
|
+
import { StarterKiezer } from "./StarterKiezer.js";
|
|
25
|
+
import { useSiteConfig } from "../../config.js";
|
|
16
26
|
const FUNCTIONELE_TYPES = /* @__PURE__ */ new Set([
|
|
17
27
|
"shopCategories",
|
|
18
28
|
"productGrid",
|
|
@@ -37,12 +47,14 @@ function PaginaKnop({ p, selected, onClick }) {
|
|
|
37
47
|
children: [
|
|
38
48
|
/* @__PURE__ */ jsxs("span", { className: "min-w-0", children: [
|
|
39
49
|
/* @__PURE__ */ jsx("span", { className: "block truncate", children: p.title }),
|
|
40
|
-
/* @__PURE__ */ jsxs("span", { className: `block truncate text-xs ${selected ? "text-brand-700/70" : "text-slate-
|
|
50
|
+
/* @__PURE__ */ jsxs("span", { className: `block truncate text-xs ${selected ? "text-brand-700/70" : "text-slate-500"}`, children: [
|
|
41
51
|
p.path,
|
|
42
52
|
signaal && !p.trashed && /* @__PURE__ */ jsxs("span", { className: "text-amber-600", children: [
|
|
43
53
|
" \xB7 ",
|
|
44
54
|
signaal
|
|
45
|
-
] })
|
|
55
|
+
] }),
|
|
56
|
+
Boolean(p.publishAt || p.unpublishAt) && !p.trashed && /* @__PURE__ */ jsx("span", { className: "text-slate-600", children: " \xB7 ingepland" }),
|
|
57
|
+
p.planningFout && !p.trashed && /* @__PURE__ */ jsx("span", { className: "text-red-700", children: " \xB7 planning mislukt" })
|
|
46
58
|
] })
|
|
47
59
|
] }),
|
|
48
60
|
/* @__PURE__ */ jsx(ToestandBadge, { p })
|
|
@@ -52,13 +64,41 @@ function PaginaKnop({ p, selected, onClick }) {
|
|
|
52
64
|
}
|
|
53
65
|
const SJABLONEN = builtinPatterns.filter((p) => p.id.startsWith("page-"));
|
|
54
66
|
function PagesPanel({ siteId }) {
|
|
67
|
+
const registry = useRegistry();
|
|
55
68
|
const { toast } = useToast();
|
|
56
69
|
const confirm = useConfirm();
|
|
57
70
|
const [pages, setPages] = useState([]);
|
|
58
|
-
const [selected, setSelected] = useState(
|
|
71
|
+
const [selected, setSelected] = useState(() => neemOpenVerzoek("pages"));
|
|
59
72
|
const [newTitle, setNewTitle] = useState("");
|
|
60
73
|
const [sjabloon, setSjabloon] = useState("leeg");
|
|
61
|
-
|
|
74
|
+
const [nieuwOpen, setNieuwOpen] = useState(false);
|
|
75
|
+
const [inMenu, setInMenu] = useState(true);
|
|
76
|
+
const [titelFout, setTitelFout] = useState(null);
|
|
77
|
+
const [maakt, setMaakt] = useState(false);
|
|
78
|
+
const { role } = useAuth();
|
|
79
|
+
const magMenu = canManageSite(role);
|
|
80
|
+
const cfg = useSiteConfig();
|
|
81
|
+
const [geladen, setGeladen] = useState(false);
|
|
82
|
+
const [laadFout, setLaadFout] = useState(null);
|
|
83
|
+
const [poging, setPoging] = useState(0);
|
|
84
|
+
useEffect(
|
|
85
|
+
() => subscribePages(
|
|
86
|
+
siteId,
|
|
87
|
+
(p) => {
|
|
88
|
+
setPages(p);
|
|
89
|
+
setGeladen(true);
|
|
90
|
+
setLaadFout(null);
|
|
91
|
+
},
|
|
92
|
+
(e) => {
|
|
93
|
+
if (isDemoActive()) {
|
|
94
|
+
setGeladen(true);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
setLaadFout(e.message);
|
|
98
|
+
}
|
|
99
|
+
),
|
|
100
|
+
[siteId, poging]
|
|
101
|
+
);
|
|
62
102
|
const actief = useMemo(() => pages.filter((p) => !p.trashed), [pages]);
|
|
63
103
|
const prullenbak = useMemo(() => pages.filter((p) => p.trashed), [pages]);
|
|
64
104
|
const gewoon = actief.filter((p) => !isFunctioneel(p));
|
|
@@ -68,12 +108,68 @@ function PagesPanel({ siteId }) {
|
|
|
68
108
|
if (!selected && actief.length) setSelected((gewoon[0] ?? actief[0]).id);
|
|
69
109
|
}, [pages, selected]);
|
|
70
110
|
const current = pages.find((p) => p.id === selected) ?? null;
|
|
111
|
+
const detailRef = useScrollNaarDetail(selected);
|
|
112
|
+
const [zoek, setZoek] = useState("");
|
|
113
|
+
const past = (p) => {
|
|
114
|
+
const q = zoek.trim().toLowerCase();
|
|
115
|
+
return !q || `${p.title} ${p.path}`.toLowerCase().includes(q);
|
|
116
|
+
};
|
|
117
|
+
const [publiceertAlles, setPubliceertAlles] = useState(false);
|
|
118
|
+
async function allesPubliceren() {
|
|
119
|
+
const lijst = actief.filter((p) => paginaToestand(p) === "gewijzigd");
|
|
120
|
+
const ctx = await publicatieContext(siteId);
|
|
121
|
+
const straksLive = /* @__PURE__ */ new Set([...actief.filter((p) => p.published).map((p) => p.path), ...lijst.map((p) => p.path)]);
|
|
122
|
+
const perPagina = lijst.map((p) => ({
|
|
123
|
+
p,
|
|
124
|
+
w: controleerPagina(p, {
|
|
125
|
+
bekendePaden: actief.map((x) => x.path),
|
|
126
|
+
livePaden: [...straksLive],
|
|
127
|
+
redirects: ctx.redirects
|
|
128
|
+
}).filter((w) => w.soort !== "seo" && w.soort !== "leesbaarheid")
|
|
129
|
+
}));
|
|
130
|
+
const ok = await confirm({
|
|
131
|
+
title: `${lijst.length} pagina's publiceren?`,
|
|
132
|
+
description: /* @__PURE__ */ jsx("ul", { className: "list-disc pl-5", children: perPagina.map(({ p, w }) => /* @__PURE__ */ jsxs("li", { children: [
|
|
133
|
+
p.title || p.path,
|
|
134
|
+
" ",
|
|
135
|
+
/* @__PURE__ */ jsxs("span", { className: "text-slate-500", children: [
|
|
136
|
+
"(",
|
|
137
|
+
p.path,
|
|
138
|
+
")"
|
|
139
|
+
] }),
|
|
140
|
+
w.length > 0 && /* @__PURE__ */ jsx("ul", { className: "mt-0.5 list-[circle] pl-4 text-amber-800", children: w.map((x, i) => /* @__PURE__ */ jsx("li", { children: x.tekst }, i)) })
|
|
141
|
+
] }, p.id)) }),
|
|
142
|
+
confirmLabel: "Alles publiceren"
|
|
143
|
+
});
|
|
144
|
+
if (!ok) return;
|
|
145
|
+
setPubliceertAlles(true);
|
|
146
|
+
const mislukt = [];
|
|
147
|
+
for (const p of lijst) {
|
|
148
|
+
try {
|
|
149
|
+
await publishPage(siteId, p.id);
|
|
150
|
+
} catch (e) {
|
|
151
|
+
mislukt.push(`${p.title || p.path}: ${e.message}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
setPubliceertAlles(false);
|
|
155
|
+
toast(
|
|
156
|
+
mislukt.length === 0 ? { title: "Alles staat live", tone: "success" } : { title: `${mislukt.length} van ${lijst.length} niet gepubliceerd`, description: mislukt.join(" \xB7 "), tone: "error" }
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
const nieuwPad = (() => {
|
|
160
|
+
const slug = slugify(newTitle.trim()) || "pagina";
|
|
161
|
+
return vrijPad(slug === "home" ? "/" : `/${slug}`, pages.filter((p) => !p.trashed).map((p) => p.path));
|
|
162
|
+
})();
|
|
71
163
|
async function create() {
|
|
72
164
|
const title = newTitle.trim();
|
|
73
|
-
if (!title)
|
|
74
|
-
|
|
75
|
-
|
|
165
|
+
if (!title) {
|
|
166
|
+
setTitelFout("Geef de pagina een naam.");
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const path = nieuwPad;
|
|
170
|
+
const slug = path.split("/").pop() || "home";
|
|
76
171
|
const patroon = SJABLONEN.find((p) => p.id === sjabloon);
|
|
172
|
+
setMaakt(true);
|
|
77
173
|
try {
|
|
78
174
|
const id = await createPage(siteId, {
|
|
79
175
|
title,
|
|
@@ -81,15 +177,35 @@ function PagesPanel({ siteId }) {
|
|
|
81
177
|
path,
|
|
82
178
|
...patroon ? { blocks: instantiatePattern(patroon) } : {}
|
|
83
179
|
});
|
|
180
|
+
let menuMislukt = false;
|
|
181
|
+
if (magMenu && inMenu && path !== "/") {
|
|
182
|
+
await voegToeAanMenu(siteId, { label: title, href: path }, cfg.nav ?? []).catch(() => {
|
|
183
|
+
menuMislukt = true;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
84
186
|
setNewTitle("");
|
|
85
187
|
setSjabloon("leeg");
|
|
86
188
|
setSelected(id);
|
|
189
|
+
setNieuwOpen(false);
|
|
87
190
|
toast({
|
|
88
191
|
title: "Pagina aangemaakt",
|
|
89
|
-
description:
|
|
192
|
+
description: menuMislukt ? `${path} \u2014 staat nog niet in het menu (dat lukte niet); voeg hem toe onder Menu.` : `${path} \u2014 nog een concept. Vul hem op de site en publiceer als het goed is.`,
|
|
193
|
+
tone: "success",
|
|
194
|
+
action: {
|
|
195
|
+
label: "Nu bewerken op de site \u2192",
|
|
196
|
+
onClick: () => {
|
|
197
|
+
try {
|
|
198
|
+
sessionStorage.setItem("xicms-bewerkmodus", "bewerken");
|
|
199
|
+
} catch {
|
|
200
|
+
}
|
|
201
|
+
window.location.assign(path);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
90
204
|
});
|
|
91
205
|
} catch (e) {
|
|
92
206
|
toast({ title: "Pagina aanmaken mislukt", description: e.message, tone: "error" });
|
|
207
|
+
} finally {
|
|
208
|
+
setMaakt(false);
|
|
93
209
|
}
|
|
94
210
|
}
|
|
95
211
|
async function herstel(p) {
|
|
@@ -117,55 +233,93 @@ function PagesPanel({ siteId }) {
|
|
|
117
233
|
toast({ title: "Verwijderen mislukt", description: e.message, tone: "error" });
|
|
118
234
|
}
|
|
119
235
|
}
|
|
120
|
-
|
|
121
|
-
/* @__PURE__ */
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
236
|
+
if (laadFout || !geladen) {
|
|
237
|
+
return /* @__PURE__ */ jsx(LaadStaat, { laden: !geladen, fout: laadFout, wat: "pagina's", opnieuw: () => {
|
|
238
|
+
setLaadFout(null);
|
|
239
|
+
setPoging((n) => n + 1);
|
|
240
|
+
}, children: null });
|
|
241
|
+
}
|
|
242
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
243
|
+
actief.length === 0 && magMenu && /* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx(StarterKiezer, { siteId }) }),
|
|
244
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-4 md:grid-cols-[260px_1fr]", children: [
|
|
245
|
+
/* @__PURE__ */ jsxs(Card, { className: "h-fit", children: [
|
|
246
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-3 flex items-center justify-between gap-2", children: [
|
|
247
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium tracking-wide text-slate-500 uppercase", children: "Overzicht" }),
|
|
248
|
+
/* @__PURE__ */ jsx(Button, { size: "sm", onClick: () => {
|
|
249
|
+
setTitelFout(null);
|
|
250
|
+
setNieuwOpen(true);
|
|
251
|
+
}, children: "+ Nieuw" }),
|
|
252
|
+
/* @__PURE__ */ jsx(Dialog, { open: nieuwOpen, onOpenChange: setNieuwOpen, children: /* @__PURE__ */ jsx(DialogContent, { title: "Nieuwe pagina", children: /* @__PURE__ */ jsxs(
|
|
253
|
+
"form",
|
|
254
|
+
{
|
|
255
|
+
className: "grid gap-3",
|
|
256
|
+
onSubmit: (e) => {
|
|
257
|
+
e.preventDefault();
|
|
258
|
+
void create();
|
|
259
|
+
},
|
|
260
|
+
children: [
|
|
261
|
+
/* @__PURE__ */ jsx(Field, { label: "Naam van de pagina", hint: newTitle.trim() ? `Komt op ${nieuwPad}` : "bv. Over ons", children: /* @__PURE__ */ jsx(
|
|
262
|
+
Input,
|
|
263
|
+
{
|
|
264
|
+
value: newTitle,
|
|
265
|
+
onChange: (e) => {
|
|
266
|
+
setNewTitle(e.target.value);
|
|
267
|
+
setTitelFout(null);
|
|
268
|
+
},
|
|
269
|
+
placeholder: "bv. Over ons",
|
|
270
|
+
autoFocus: true,
|
|
271
|
+
"aria-invalid": titelFout ? true : void 0
|
|
272
|
+
}
|
|
273
|
+
) }),
|
|
274
|
+
titelFout && /* @__PURE__ */ jsx("p", { role: "alert", className: "-mt-1 text-sm text-red-700", children: titelFout }),
|
|
275
|
+
/* @__PURE__ */ jsx(Field, { label: "Beginnen met", hint: "Een sjabloon zet alvast passende blokken met voorbeeldtekst neer \u2014 alles is daarna aan te passen.", children: /* @__PURE__ */ jsx(
|
|
276
|
+
Select,
|
|
277
|
+
{
|
|
278
|
+
value: sjabloon,
|
|
279
|
+
onValueChange: setSjabloon,
|
|
280
|
+
options: [{ value: "leeg", label: "Lege pagina" }, ...SJABLONEN.filter((p) => collectPatternTypes(p).every((t) => registry.get(t))).map((p) => ({ value: p.id, label: p.label }))]
|
|
281
|
+
}
|
|
282
|
+
) }),
|
|
283
|
+
magMenu && nieuwPad !== "/" && /* @__PURE__ */ jsx(Switch, { checked: inMenu, onCheckedChange: setInMenu, label: "Ook in het hoofdmenu zetten" }),
|
|
284
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
|
|
285
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", onClick: () => setNieuwOpen(false), children: "Annuleren" }),
|
|
286
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", disabled: maakt, children: maakt ? "Aanmaken\u2026" : "Aanmaken" })
|
|
287
|
+
] })
|
|
288
|
+
]
|
|
289
|
+
}
|
|
290
|
+
) }) })
|
|
291
|
+
] }),
|
|
292
|
+
nietLive > 0 && /* @__PURE__ */ jsxs("div", { className: "mb-2 grid gap-2 rounded-lg bg-amber-50 px-3 py-2 text-xs text-amber-900", children: [
|
|
293
|
+
/* @__PURE__ */ jsxs("p", { children: [
|
|
294
|
+
nietLive === 1 ? "1 pagina heeft" : `${nietLive} pagina's hebben`,
|
|
295
|
+
" wijzigingen die nog niet live staan."
|
|
296
|
+
] }),
|
|
297
|
+
nietLive > 1 && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { size: "sm", variant: "secondary", disabled: publiceertAlles, onClick: () => void allesPubliceren(), children: publiceertAlles ? "Publiceren\u2026" : `Alles publiceren (${nietLive})` }) })
|
|
298
|
+
] }),
|
|
299
|
+
actief.length > 10 && /* @__PURE__ */ jsx(Input, { "aria-label": "Pagina's zoeken", placeholder: "Zoeken\u2026", value: zoek, onChange: (e) => setZoek(e.target.value), className: "mb-2" }),
|
|
300
|
+
/* @__PURE__ */ jsx("ul", { className: "grid gap-1", children: gewoon.filter(past).map((p) => /* @__PURE__ */ jsx("li", { className: "min-w-0", children: /* @__PURE__ */ jsx(PaginaKnop, { p, selected: p.id === selected, onClick: () => setSelected(p.id) }) }, p.id)) }),
|
|
301
|
+
functioneel.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-4 border-t border-slate-200 pt-3", children: [
|
|
302
|
+
/* @__PURE__ */ jsx("p", { className: "mb-1 px-3 text-xs font-medium tracking-wide text-slate-500 uppercase", children: "Winkel & functioneel" }),
|
|
303
|
+
/* @__PURE__ */ jsx("p", { className: "mb-2 px-3 text-xs text-slate-500", children: "Deze pagina's zijn het omhulsel van een functie. Producten en bestellingen beheer je onder Webwinkel; hier pas je alleen de tekst eromheen aan." }),
|
|
304
|
+
/* @__PURE__ */ jsx("ul", { className: "grid gap-1", children: functioneel.filter(past).map((p) => /* @__PURE__ */ jsx("li", { className: "min-w-0", children: /* @__PURE__ */ jsx(PaginaKnop, { p, selected: p.id === selected, onClick: () => setSelected(p.id) }) }, p.id)) })
|
|
305
|
+
] }),
|
|
306
|
+
prullenbak.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-4 border-t border-slate-200 pt-3", children: [
|
|
307
|
+
/* @__PURE__ */ jsx("p", { className: "mb-1 px-3 text-xs font-medium tracking-wide text-slate-500 uppercase", children: "Prullenbak" }),
|
|
308
|
+
/* @__PURE__ */ jsx("p", { className: "mb-2 px-3 text-xs text-slate-500", children: "Wordt na 30 dagen automatisch geleegd." }),
|
|
309
|
+
/* @__PURE__ */ jsx("ul", { className: "grid gap-1", children: prullenbak.map((p) => /* @__PURE__ */ jsxs("li", { className: "min-w-0", children: [
|
|
310
|
+
/* @__PURE__ */ jsx(PaginaKnop, { p, selected: p.id === selected, onClick: () => setSelected(p.id) }),
|
|
311
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-1 px-3 pb-1", children: [
|
|
312
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: () => void herstel(p), children: "Herstellen" }),
|
|
313
|
+
/* @__PURE__ */ jsx(Button, { variant: "dangerGhost", size: "sm", onClick: () => void definitiefWeg(p), children: "Definitief verwijderen" })
|
|
139
314
|
] })
|
|
140
|
-
] }) })
|
|
315
|
+
] }, p.id)) })
|
|
141
316
|
] })
|
|
142
317
|
] }),
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
"
|
|
146
|
-
] })
|
|
147
|
-
|
|
148
|
-
functioneel.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-4 border-t border-slate-200 pt-3", children: [
|
|
149
|
-
/* @__PURE__ */ jsx("p", { className: "mb-1 px-3 text-xs font-medium tracking-wide text-slate-500 uppercase", children: "Winkel & functioneel" }),
|
|
150
|
-
/* @__PURE__ */ jsx("p", { className: "mb-2 px-3 text-xs text-slate-400", children: "Deze pagina's zijn het omhulsel van een functie. Producten en bestellingen beheer je onder Webwinkel; hier pas je alleen de tekst eromheen aan." }),
|
|
151
|
-
/* @__PURE__ */ jsx("ul", { className: "grid gap-1", children: functioneel.map((p) => /* @__PURE__ */ jsx("li", { className: "min-w-0", children: /* @__PURE__ */ jsx(PaginaKnop, { p, selected: p.id === selected, onClick: () => setSelected(p.id) }) }, p.id)) })
|
|
152
|
-
] }),
|
|
153
|
-
prullenbak.length > 0 && /* @__PURE__ */ jsxs("div", { className: "mt-4 border-t border-slate-200 pt-3", children: [
|
|
154
|
-
/* @__PURE__ */ jsx("p", { className: "mb-1 px-3 text-xs font-medium tracking-wide text-slate-500 uppercase", children: "Prullenbak" }),
|
|
155
|
-
/* @__PURE__ */ jsx("p", { className: "mb-2 px-3 text-xs text-slate-400", children: "Wordt na 30 dagen automatisch geleegd." }),
|
|
156
|
-
/* @__PURE__ */ jsx("ul", { className: "grid gap-1", children: prullenbak.map((p) => /* @__PURE__ */ jsxs("li", { className: "min-w-0", children: [
|
|
157
|
-
/* @__PURE__ */ jsx(PaginaKnop, { p, selected: p.id === selected, onClick: () => setSelected(p.id) }),
|
|
158
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-1 px-3 pb-1", children: [
|
|
159
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", onClick: () => void herstel(p), children: "Herstellen" }),
|
|
160
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "rounded px-2 py-1 text-xs text-red-600 hover:underline", onClick: () => void definitiefWeg(p), children: "Definitief verwijderen" })
|
|
161
|
-
] })
|
|
162
|
-
] }, p.id)) })
|
|
163
|
-
] })
|
|
164
|
-
] }),
|
|
165
|
-
/* @__PURE__ */ jsx("div", { children: current ? /* @__PURE__ */ jsx(PageEditor, { siteId, page: current, allPages: pages }) : /* @__PURE__ */ jsx(Card, { className: "grid place-items-center py-16 text-center", children: /* @__PURE__ */ jsxs("div", { className: "max-w-sm", children: [
|
|
166
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-slate-700", children: actief.length === 0 ? "Nog geen pagina's" : "Geen pagina geselecteerd" }),
|
|
167
|
-
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-slate-500", children: actief.length === 0 ? "Maak je eerste pagina met + Nieuw. Wat je maakt blijft een concept tot je publiceert." : "Kies links een pagina om de instellingen aan te passen, of open hem op de site om de tekst te bewerken." })
|
|
168
|
-
] }) }) })
|
|
318
|
+
/* @__PURE__ */ jsx("div", { ref: detailRef, className: "scroll-mt-24", children: current ? /* @__PURE__ */ jsx(PageEditor, { siteId, page: current, allPages: pages }) : /* @__PURE__ */ jsx(Card, { className: "grid place-items-center py-16 text-center", children: /* @__PURE__ */ jsxs("div", { className: "max-w-sm", children: [
|
|
319
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-slate-700", children: actief.length === 0 ? "Nog geen pagina's" : "Geen pagina geselecteerd" }),
|
|
320
|
+
/* @__PURE__ */ jsx("p", { className: "mt-1 text-sm text-slate-500", children: actief.length === 0 ? isDemoActive() ? "In de demo zie je hier de pagina's die je op de site hebt geopend of bewerkt. Maak er een met + Nieuw, of bewerk een pagina op de site zelf." : "Maak je eerste pagina met + Nieuw. Wat je maakt blijft een concept tot je publiceert." : "Kies links een pagina om de instellingen aan te passen, of open hem op de site om de tekst te bewerken." })
|
|
321
|
+
] }) }) })
|
|
322
|
+
] })
|
|
169
323
|
] });
|
|
170
324
|
}
|
|
171
325
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/admin/pages/PagesPanel.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { Button, Card, Field, Input } from \"../ui/primitives\";\nimport { Select } from \"../ui/select\";\nimport { Dialog, DialogTrigger, DialogContent, DialogClose } from \"../ui/dialog\";\nimport { useToast } from \"../ui/toast\";\nimport { useConfirm } from \"../ui/ConfirmDialog\";\nimport { subscribePages, createPage, deletePage, restorePage, paginaToestand, type DraftPage } from \"../lib/pagesClient\";\nimport { seoSignaal } from \"../lib/seoHulp\";\nimport { builtinPatterns, instantiatePattern } from \"../../patterns\";\nimport { PageEditor, ToestandBadge } from \"./PageEditor\";\n\nfunction slugify(s: string): string {\n return s\n .toLowerCase()\n .normalize(\"NFD\")\n .replace(/[̀-ͯ]/g, \"\")\n .replace(/[^a-z0-9]+/g, \"-\")\n .replace(/(^-|-$)/g, \"\");\n}\n\n/**\n * Bloktypes die een pagina FUNCTIONEEL maken (7.16): een afrekenpagina is \"een pagina met een\n * checkout-blok\", en die hoort in de lijst niet tussen \"Over ons\" te staan — de inhoud (producten,\n * bestellingen) beheer je onder Webwinkel, hier staat alleen het omhulsel. Er is bewust géén\n * pagina-type-veld in het schema (dat zou een tweede waarheid zijn naast de blokken zelf); we lezen\n * het af aan wat er op de pagina staat.\n */\nconst FUNCTIONELE_TYPES = new Set([\n \"shopCategories\",\n \"productGrid\",\n \"productDetail\",\n \"cart\",\n \"checkout\",\n \"donation\",\n \"orderStatus\",\n]);\nfunction isFunctioneel(p: DraftPage): boolean {\n // De homepage hoort ALTIJD bij de gewone pagina's: op een winkel-site staat er vaak een\n // productGrid op de home, maar de home is nooit alleen \"het omhulsel van een functie\" —\n // het is de voordeur van de site, en die moet bovenaan staan waar de klant hem zoekt.\n if (p.path === \"/\") return false;\n return (p.blocks ?? []).some((b) => FUNCTIONELE_TYPES.has(String((b as { _type?: unknown })._type)));\n}\n\n/**\n * Eén rij in de paginalijst. Titel + pad onder elkaar: de kolom is 260px en een SEO-titel als\n * \"Christelijk Kraamcadeau — christelijke geschenken en kraamcadeaus\" is dan onleesbaar afgekapt\n * zónder dat je kunt zien wélke pagina het is. Het pad is kort, uniek en herkenbaar (\"/\", \"/over-\n * ons\") — precies het houvast dat de afgekapte titel mist. `title` levert de volle titel bij hover.\n *\n * 7.24: de badge zegt nu ook \"gewijzigd, nog niet live\" — de toestand waar klanten het vaakst\n * over belden (\"ik heb het aangepast maar het staat er niet\"), en die tot nu toe nergens zichtbaar\n * was buiten de editor. Plus een stil SEO-signaal (\"mist omschrijving\").\n */\nfunction PaginaKnop({ p, selected, onClick }: { p: DraftPage; selected: boolean; onClick: () => void }) {\n const signaal = seoSignaal(p);\n return (\n <button\n onClick={onClick}\n title={`${p.title} — ${p.path}`}\n className={`flex w-full items-center justify-between gap-2 rounded-lg px-3 py-2 text-left text-sm ${\n selected ? \"bg-brand-50 text-brand-700\" : \"hover:bg-slate-100\"\n }`}\n >\n <span className=\"min-w-0\">\n <span className=\"block truncate\">{p.title}</span>\n <span className={`block truncate text-xs ${selected ? \"text-brand-700/70\" : \"text-slate-400\"}`}>\n {p.path}\n {signaal && !p.trashed && <span className=\"text-amber-600\"> · {signaal}</span>}\n </span>\n </span>\n <ToestandBadge p={p} />\n </button>\n );\n}\n\n/** Paginasjablonen voor \"+ Nieuw\": de `page-*`-patronen, plus \"leeg\". */\nconst SJABLONEN = builtinPatterns.filter((p) => p.id.startsWith(\"page-\"));\n\nexport function PagesPanel({ siteId }: { siteId: string }) {\n const { toast } = useToast();\n const confirm = useConfirm();\n const [pages, setPages] = useState<DraftPage[]>([]);\n const [selected, setSelected] = useState<string | null>(null);\n const [newTitle, setNewTitle] = useState(\"\");\n const [sjabloon, setSjabloon] = useState(\"leeg\");\n\n useEffect(() => subscribePages(siteId, setPages), [siteId]);\n\n const actief = useMemo(() => pages.filter((p) => !p.trashed), [pages]);\n const prullenbak = useMemo(() => pages.filter((p) => p.trashed), [pages]);\n const gewoon = actief.filter((p) => !isFunctioneel(p));\n const functioneel = actief.filter(isFunctioneel);\n const nietLive = actief.filter((p) => paginaToestand(p) === \"gewijzigd\").length;\n\n useEffect(() => {\n // Standaard de eerste GEWONE pagina: /beheer → Pagina's gaat over teksten, niet over de winkel.\n if (!selected && actief.length) setSelected((gewoon[0] ?? actief[0]).id);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pages, selected]);\n\n const current = pages.find((p) => p.id === selected) ?? null;\n\n async function create() {\n const title = newTitle.trim();\n if (!title) return;\n const slug = slugify(title) || \"pagina\";\n const path = slug === \"home\" ? \"/\" : `/${slug}`;\n const patroon = SJABLONEN.find((p) => p.id === sjabloon);\n try {\n const id = await createPage(siteId, {\n title,\n slug,\n path,\n ...(patroon ? { blocks: instantiatePattern(patroon) as DraftPage[\"blocks\"] } : {}),\n });\n setNewTitle(\"\");\n setSjabloon(\"leeg\");\n setSelected(id);\n toast({\n title: \"Pagina aangemaakt\",\n description: patroon ? `${path} — met voorbeeldtekst; bewerk op de site en publiceer als het goed is.` : path,\n });\n } catch (e) {\n // De dialoog sluit sowieso (DialogClose) — zonder deze toast dacht de klant dat de pagina\n // bestond terwijl de write (rules/offline) faalde.\n toast({ title: \"Pagina aanmaken mislukt\", description: (e as Error).message, tone: \"error\" });\n }\n }\n\n async function herstel(p: DraftPage) {\n try {\n await restorePage(siteId, p.id);\n setSelected(p.id);\n toast({ title: \"Hersteld als concept\", description: \"Publiceer om hem weer live te zetten.\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Herstellen mislukt\", description: (e as Error).message, tone: \"error\" });\n }\n }\n\n async function definitiefWeg(p: DraftPage) {\n const ok = await confirm({\n title: `\"${p.title}\" definitief verwijderen?`,\n description: \"Dit kan niet ongedaan worden gemaakt — ook de versiegeschiedenis verdwijnt.\",\n confirmLabel: \"Definitief verwijderen\",\n tone: \"danger\",\n });\n if (!ok) return;\n try {\n await deletePage(siteId, p.id);\n if (selected === p.id) setSelected(null);\n toast({ title: \"Pagina verwijderd\" });\n } catch (e) {\n toast({ title: \"Verwijderen mislukt\", description: (e as Error).message, tone: \"error\" });\n }\n }\n\n return (\n <div className=\"grid gap-4 md:grid-cols-[260px_1fr]\">\n <Card className=\"h-fit\">\n <div className=\"mb-3 flex items-center justify-between gap-2\">\n <span className=\"text-xs font-medium tracking-wide text-slate-500 uppercase\">Overzicht</span>\n <Dialog>\n <DialogTrigger asChild>\n <Button size=\"sm\">+ Nieuw</Button>\n </DialogTrigger>\n <DialogContent title=\"Nieuwe pagina\">\n <div className=\"grid gap-3\">\n <Field label=\"Titel\">\n <Input value={newTitle} onChange={(e) => setNewTitle(e.target.value)} placeholder=\"bv. Over ons\" />\n </Field>\n <Field label=\"Beginnen met\" hint=\"Een sjabloon zet alvast passende blokken met voorbeeldtekst neer — alles is daarna aan te passen.\">\n <Select\n value={sjabloon}\n onValueChange={setSjabloon}\n options={[{ value: \"leeg\", label: \"Lege pagina\" }, ...SJABLONEN.map((p) => ({ value: p.id, label: p.label }))]}\n />\n </Field>\n <div className=\"flex justify-end gap-2\">\n <DialogClose asChild>\n <Button variant=\"secondary\">Annuleren</Button>\n </DialogClose>\n <DialogClose asChild>\n <Button onClick={create}>Aanmaken</Button>\n </DialogClose>\n </div>\n </div>\n </DialogContent>\n </Dialog>\n </div>\n {nietLive > 0 && (\n <p className=\"mb-2 rounded-lg bg-amber-50 px-3 py-2 text-xs text-amber-900\">\n {nietLive === 1 ? \"1 pagina heeft\" : `${nietLive} pagina's hebben`} wijzigingen die nog niet live staan.\n </p>\n )}\n <ul className=\"grid gap-1\">\n {gewoon.map((p) => (\n <li key={p.id} className=\"min-w-0\">\n <PaginaKnop p={p} selected={p.id === selected} onClick={() => setSelected(p.id)} />\n </li>\n ))}\n {/* Geen lege-lijst-tekst hier: de lege staat rechts zegt hetzelfde én noemt de volgende\n stap. Twee keer \"Nog geen pagina's\" naast elkaar leest als een fout. */}\n </ul>\n {functioneel.length > 0 && (\n <div className=\"mt-4 border-t border-slate-200 pt-3\">\n <p className=\"mb-1 px-3 text-xs font-medium tracking-wide text-slate-500 uppercase\">Winkel & functioneel</p>\n <p className=\"mb-2 px-3 text-xs text-slate-400\">\n Deze pagina's zijn het omhulsel van een functie. Producten en bestellingen beheer je\n onder Webwinkel; hier pas je alleen de tekst eromheen aan.\n </p>\n <ul className=\"grid gap-1\">\n {functioneel.map((p) => (\n <li key={p.id} className=\"min-w-0\">\n <PaginaKnop p={p} selected={p.id === selected} onClick={() => setSelected(p.id)} />\n </li>\n ))}\n </ul>\n </div>\n )}\n {prullenbak.length > 0 && (\n <div className=\"mt-4 border-t border-slate-200 pt-3\">\n <p className=\"mb-1 px-3 text-xs font-medium tracking-wide text-slate-500 uppercase\">Prullenbak</p>\n <p className=\"mb-2 px-3 text-xs text-slate-400\">Wordt na 30 dagen automatisch geleegd.</p>\n <ul className=\"grid gap-1\">\n {prullenbak.map((p) => (\n <li key={p.id} className=\"min-w-0\">\n <PaginaKnop p={p} selected={p.id === selected} onClick={() => setSelected(p.id)} />\n <div className=\"flex gap-1 px-3 pb-1\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void herstel(p)}>Herstellen</Button>\n <button type=\"button\" className=\"rounded px-2 py-1 text-xs text-red-600 hover:underline\" onClick={() => void definitiefWeg(p)}>\n Definitief verwijderen\n </button>\n </div>\n </li>\n ))}\n </ul>\n </div>\n )}\n </Card>\n\n <div>\n {current ? (\n <PageEditor siteId={siteId} page={current} allPages={pages} />\n ) : (\n <Card className=\"grid place-items-center py-16 text-center\">\n <div className=\"max-w-sm\">\n {/* Een lege lijst is een uitnodiging, geen mededeling: zeg wat de volgende stap is. */}\n <p className=\"text-sm font-medium text-slate-700\">\n {actief.length === 0 ? \"Nog geen pagina's\" : \"Geen pagina geselecteerd\"}\n </p>\n <p className=\"mt-1 text-sm text-slate-500\">\n {actief.length === 0\n ? \"Maak je eerste pagina met + Nieuw. Wat je maakt blijft een concept tot je publiceert.\"\n : \"Kies links een pagina om de instellingen aan te passen, of open hem op de site om de tekst te bewerken.\"}\n </p>\n </div>\n </Card>\n )}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/admin/pages/PagesPanel.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { Button, Card, Field, Input } from \"../ui/primitives\";\nimport { Select } from \"../ui/select\";\nimport { Dialog, DialogContent } from \"../ui/dialog\";\nimport { useToast } from \"../ui/toast\";\nimport { useConfirm } from \"../ui/ConfirmDialog\";\nimport { LaadStaat } from \"../ui/LaadStaat\";\nimport { isDemoActive } from \"../../demo/demoStore\";\nimport { neemOpenVerzoek } from \"../navContext\";\nimport { useScrollNaarDetail } from \"../lib/scrollNaarDetail\";\nimport { subscribePages, createPage, deletePage, restorePage, paginaToestand, publishPage, publicatieContext, type DraftPage } from \"../lib/pagesClient\";\nimport { controleerPagina } from \"../lib/publicatieCheck\";\nimport { seoSignaal } from \"../lib/seoHulp\";\nimport { builtinPatterns, collectPatternTypes, instantiatePattern } from \"../../patterns\";\nimport { useRegistry } from \"../../blocks/context\";\nimport { PageEditor, ToestandBadge } from \"./PageEditor\";\n\nimport { slugify } from \"../lib/slugify\";\nimport { voegToeAanMenu, vrijPad } from \"../lib/menuHulp\";\nimport { Switch } from \"../ui/switch\";\nimport { useAuth } from \"../../auth/AuthProvider\";\nimport { canManageSite } from \"../../auth/roles\";\nimport { StarterKiezer } from \"./StarterKiezer\";\nimport { useSiteConfig } from \"../../config\";\n\n/**\n * Bloktypes die een pagina FUNCTIONEEL maken (7.16): een afrekenpagina is \"een pagina met een\n * checkout-blok\", en die hoort in de lijst niet tussen \"Over ons\" te staan — de inhoud (producten,\n * bestellingen) beheer je onder Webwinkel, hier staat alleen het omhulsel. Er is bewust géén\n * pagina-type-veld in het schema (dat zou een tweede waarheid zijn naast de blokken zelf); we lezen\n * het af aan wat er op de pagina staat.\n */\nconst FUNCTIONELE_TYPES = new Set([\n \"shopCategories\",\n \"productGrid\",\n \"productDetail\",\n \"cart\",\n \"checkout\",\n \"donation\",\n \"orderStatus\",\n]);\nfunction isFunctioneel(p: DraftPage): boolean {\n // De homepage hoort ALTIJD bij de gewone pagina's: op een winkel-site staat er vaak een\n // productGrid op de home, maar de home is nooit alleen \"het omhulsel van een functie\" —\n // het is de voordeur van de site, en die moet bovenaan staan waar de klant hem zoekt.\n if (p.path === \"/\") return false;\n return (p.blocks ?? []).some((b) => FUNCTIONELE_TYPES.has(String((b as { _type?: unknown })._type)));\n}\n\n/**\n * Eén rij in de paginalijst. Titel + pad onder elkaar: de kolom is 260px en een SEO-titel als\n * \"Christelijk Kraamcadeau — christelijke geschenken en kraamcadeaus\" is dan onleesbaar afgekapt\n * zónder dat je kunt zien wélke pagina het is. Het pad is kort, uniek en herkenbaar (\"/\", \"/over-\n * ons\") — precies het houvast dat de afgekapte titel mist. `title` levert de volle titel bij hover.\n *\n * 7.24: de badge zegt nu ook \"gewijzigd, nog niet live\" — de toestand waar klanten het vaakst\n * over belden (\"ik heb het aangepast maar het staat er niet\"), en die tot nu toe nergens zichtbaar\n * was buiten de editor. Plus een stil SEO-signaal (\"mist omschrijving\").\n */\nfunction PaginaKnop({ p, selected, onClick }: { p: DraftPage; selected: boolean; onClick: () => void }) {\n const signaal = seoSignaal(p);\n return (\n <button\n onClick={onClick}\n title={`${p.title} — ${p.path}`}\n className={`flex w-full items-center justify-between gap-2 rounded-lg px-3 py-2 text-left text-sm ${\n selected ? \"bg-brand-50 text-brand-700\" : \"hover:bg-slate-100\"\n }`}\n >\n <span className=\"min-w-0\">\n <span className=\"block truncate\">{p.title}</span>\n <span className={`block truncate text-xs ${selected ? \"text-brand-700/70\" : \"text-slate-500\"}`}>\n {p.path}\n {signaal && !p.trashed && <span className=\"text-amber-600\"> · {signaal}</span>}\n {Boolean(p.publishAt || p.unpublishAt) && !p.trashed && <span className=\"text-slate-600\"> · ingepland</span>}\n {p.planningFout && !p.trashed && <span className=\"text-red-700\"> · planning mislukt</span>}\n </span>\n </span>\n <ToestandBadge p={p} />\n </button>\n );\n}\n\n/** Paginasjablonen voor \"+ Nieuw\": de `page-*`-patronen, plus \"leeg\". */\nconst SJABLONEN = builtinPatterns.filter((p) => p.id.startsWith(\"page-\"));\n\nexport function PagesPanel({ siteId }: { siteId: string }) {\n const registry = useRegistry();\n const { toast } = useToast();\n const confirm = useConfirm();\n const [pages, setPages] = useState<DraftPage[]>([]);\n const [selected, setSelected] = useState<string | null>(() => neemOpenVerzoek(\"pages\"));\n const [newTitle, setNewTitle] = useState(\"\");\n const [sjabloon, setSjabloon] = useState(\"leeg\");\n const [nieuwOpen, setNieuwOpen] = useState(false);\n const [inMenu, setInMenu] = useState(true);\n const [titelFout, setTitelFout] = useState<string | null>(null);\n const [maakt, setMaakt] = useState(false);\n const { role } = useAuth();\n const magMenu = canManageSite(role);\n const cfg = useSiteConfig();\n\n const [geladen, setGeladen] = useState(false);\n const [laadFout, setLaadFout] = useState<string | null>(null);\n const [poging, setPoging] = useState(0);\n useEffect(\n () =>\n subscribePages(\n siteId,\n (p) => {\n setPages(p);\n setGeladen(true);\n setLaadFout(null);\n },\n (e) => {\n // Demo: geen database — gewoon een lege lijst (pagina's aanmaken werkt lokaal wél).\n if (isDemoActive()) {\n setGeladen(true);\n return;\n }\n setLaadFout(e.message);\n },\n ),\n [siteId, poging],\n );\n\n const actief = useMemo(() => pages.filter((p) => !p.trashed), [pages]);\n const prullenbak = useMemo(() => pages.filter((p) => p.trashed), [pages]);\n const gewoon = actief.filter((p) => !isFunctioneel(p));\n const functioneel = actief.filter(isFunctioneel);\n const nietLive = actief.filter((p) => paginaToestand(p) === \"gewijzigd\").length;\n\n useEffect(() => {\n // Standaard de eerste GEWONE pagina: /beheer → Pagina's gaat over teksten, niet over de winkel.\n if (!selected && actief.length) setSelected((gewoon[0] ?? actief[0]).id);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [pages, selected]);\n\n const current = pages.find((p) => p.id === selected) ?? null;\n const detailRef = useScrollNaarDetail(selected);\n\n // Zoeken (8.2) zodra de lijst lang wordt — producten en bestellingen hadden het al.\n const [zoek, setZoek] = useState(\"\");\n const past = (p: DraftPage) => {\n const q = zoek.trim().toLowerCase();\n return !q || `${p.title} ${p.path}`.toLowerCase().includes(q);\n };\n\n /** Alle pagina's met ongepubliceerde wijzigingen in één keer live (8.2), na een overzicht. */\n const [publiceertAlles, setPubliceertAlles] = useState(false);\n async function allesPubliceren() {\n const lijst = actief.filter((p) => paginaToestand(p) === \"gewijzigd\");\n // 8.10: dezelfde controle als bij één pagina — tien pagina's met dode links gingen anders in\n // één klik ongezien live. Wat er straks live staat telt als \"live\" voor de linkcontrole.\n const ctx = await publicatieContext(siteId);\n const straksLive = new Set([...actief.filter((p) => p.published).map((p) => p.path), ...lijst.map((p) => p.path)]);\n const perPagina = lijst.map((p) => ({\n p,\n w: controleerPagina(p, {\n bekendePaden: actief.map((x) => x.path),\n livePaden: [...straksLive],\n redirects: ctx.redirects,\n }).filter((w) => w.soort !== \"seo\" && w.soort !== \"leesbaarheid\"),\n }));\n const ok = await confirm({\n title: `${lijst.length} pagina's publiceren?`,\n description: (\n <ul className=\"list-disc pl-5\">\n {perPagina.map(({ p, w }) => (\n <li key={p.id}>\n {p.title || p.path} <span className=\"text-slate-500\">({p.path})</span>\n {w.length > 0 && (\n <ul className=\"mt-0.5 list-[circle] pl-4 text-amber-800\">\n {w.map((x, i) => <li key={i}>{x.tekst}</li>)}\n </ul>\n )}\n </li>\n ))}\n </ul>\n ),\n confirmLabel: \"Alles publiceren\",\n });\n if (!ok) return;\n setPubliceertAlles(true);\n const mislukt: string[] = [];\n for (const p of lijst) {\n try {\n await publishPage(siteId, p.id);\n } catch (e) {\n mislukt.push(`${p.title || p.path}: ${(e as Error).message}`);\n }\n }\n setPubliceertAlles(false);\n toast(\n mislukt.length === 0\n ? { title: \"Alles staat live\", tone: \"success\" }\n : { title: `${mislukt.length} van ${lijst.length} niet gepubliceerd`, description: mislukt.join(\" · \"), tone: \"error\" },\n );\n }\n\n /** Het adres dat de nieuwe pagina krijgt — ook getoond in de dialoog, vóór je op Aanmaken drukt. */\n const nieuwPad = (() => {\n const slug = slugify(newTitle.trim()) || \"pagina\";\n return vrijPad(slug === \"home\" ? \"/\" : `/${slug}`, pages.filter((p) => !p.trashed).map((p) => p.path));\n })();\n\n async function create() {\n const title = newTitle.trim();\n // 8.2: de dialoog sloot ook bij een lege titel en deed dan stil niets.\n if (!title) {\n setTitelFout(\"Geef de pagina een naam.\");\n return;\n }\n const path = nieuwPad;\n const slug = path.split(\"/\").pop() || \"home\";\n const patroon = SJABLONEN.find((p) => p.id === sjabloon);\n setMaakt(true);\n try {\n const id = await createPage(siteId, {\n title,\n slug,\n path,\n ...(patroon ? { blocks: instantiatePattern(patroon) as DraftPage[\"blocks\"] } : {}),\n });\n let menuMislukt = false;\n if (magMenu && inMenu && path !== \"/\") {\n await voegToeAanMenu(siteId, { label: title, href: path }, cfg.nav ?? []).catch(() => {\n menuMislukt = true;\n });\n }\n setNewTitle(\"\");\n setSjabloon(\"leeg\");\n setSelected(id);\n setNieuwOpen(false);\n toast({\n title: \"Pagina aangemaakt\",\n description: menuMislukt\n ? `${path} — staat nog niet in het menu (dat lukte niet); voeg hem toe onder Menu.`\n : `${path} — nog een concept. Vul hem op de site en publiceer als het goed is.`,\n tone: \"success\",\n action: {\n label: \"Nu bewerken op de site →\",\n onClick: () => {\n try {\n sessionStorage.setItem(\"xicms-bewerkmodus\", \"bewerken\");\n } catch {\n /* geblokkeerde opslag: dan opent de pagina in kijkmodus */\n }\n window.location.assign(path);\n },\n },\n });\n } catch (e) {\n toast({ title: \"Pagina aanmaken mislukt\", description: (e as Error).message, tone: \"error\" });\n } finally {\n setMaakt(false);\n }\n }\n\n async function herstel(p: DraftPage) {\n try {\n await restorePage(siteId, p.id);\n setSelected(p.id);\n toast({ title: \"Hersteld als concept\", description: \"Publiceer om hem weer live te zetten.\", tone: \"success\" });\n } catch (e) {\n toast({ title: \"Herstellen mislukt\", description: (e as Error).message, tone: \"error\" });\n }\n }\n\n async function definitiefWeg(p: DraftPage) {\n const ok = await confirm({\n title: `\"${p.title}\" definitief verwijderen?`,\n description: \"Dit kan niet ongedaan worden gemaakt — ook de versiegeschiedenis verdwijnt.\",\n confirmLabel: \"Definitief verwijderen\",\n tone: \"danger\",\n });\n if (!ok) return;\n try {\n await deletePage(siteId, p.id);\n if (selected === p.id) setSelected(null);\n toast({ title: \"Pagina verwijderd\" });\n } catch (e) {\n toast({ title: \"Verwijderen mislukt\", description: (e as Error).message, tone: \"error\" });\n }\n }\n\n if (laadFout || !geladen) {\n return (\n <LaadStaat laden={!geladen} fout={laadFout} wat=\"pagina's\" opnieuw={() => { setLaadFout(null); setPoging((n) => n + 1); }}>\n {null}\n </LaadStaat>\n );\n }\n\n return (\n <>\n {/* 8.14: een lege site begint niet met een leeg vel maar met een opzet per soort bedrijf.\n Alleen voor wie ook het menu en de modules mag zetten (siteadmin). */}\n {actief.length === 0 && magMenu && <div className=\"mb-4\"><StarterKiezer siteId={siteId} /></div>}\n <div className=\"grid gap-4 md:grid-cols-[260px_1fr]\">\n <Card className=\"h-fit\">\n <div className=\"mb-3 flex items-center justify-between gap-2\">\n <span className=\"text-xs font-medium tracking-wide text-slate-500 uppercase\">Overzicht</span>\n <Button size=\"sm\" onClick={() => { setTitelFout(null); setNieuwOpen(true); }}>+ Nieuw</Button>\n <Dialog open={nieuwOpen} onOpenChange={setNieuwOpen}>\n <DialogContent title=\"Nieuwe pagina\">\n <form\n className=\"grid gap-3\"\n onSubmit={(e) => {\n e.preventDefault();\n void create();\n }}\n >\n <Field label=\"Naam van de pagina\" hint={newTitle.trim() ? `Komt op ${nieuwPad}` : \"bv. Over ons\"}>\n <Input\n value={newTitle}\n onChange={(e) => {\n setNewTitle(e.target.value);\n setTitelFout(null);\n }}\n placeholder=\"bv. Over ons\"\n autoFocus\n aria-invalid={titelFout ? true : undefined}\n />\n </Field>\n {titelFout && <p role=\"alert\" className=\"-mt-1 text-sm text-red-700\">{titelFout}</p>}\n <Field label=\"Beginnen met\" hint=\"Een sjabloon zet alvast passende blokken met voorbeeldtekst neer — alles is daarna aan te passen.\">\n <Select\n value={sjabloon}\n onValueChange={setSjabloon}\n // 8.14: alleen sjablonen waarvan alle blokken op deze site bestaan (modules aan).\n options={[{ value: \"leeg\", label: \"Lege pagina\" }, ...SJABLONEN.filter((p) => collectPatternTypes(p).every((t) => registry.get(t))).map((p) => ({ value: p.id, label: p.label }))]}\n />\n </Field>\n {magMenu && nieuwPad !== \"/\" && (\n <Switch checked={inMenu} onCheckedChange={setInMenu} label=\"Ook in het hoofdmenu zetten\" />\n )}\n <div className=\"flex justify-end gap-2\">\n <Button type=\"button\" variant=\"secondary\" onClick={() => setNieuwOpen(false)}>Annuleren</Button>\n <Button type=\"submit\" disabled={maakt}>{maakt ? \"Aanmaken…\" : \"Aanmaken\"}</Button>\n </div>\n </form>\n </DialogContent>\n </Dialog>\n </div>\n {nietLive > 0 && (\n <div className=\"mb-2 grid gap-2 rounded-lg bg-amber-50 px-3 py-2 text-xs text-amber-900\">\n <p>{nietLive === 1 ? \"1 pagina heeft\" : `${nietLive} pagina's hebben`} wijzigingen die nog niet live staan.</p>\n {nietLive > 1 && (\n <div>\n <Button size=\"sm\" variant=\"secondary\" disabled={publiceertAlles} onClick={() => void allesPubliceren()}>\n {publiceertAlles ? \"Publiceren…\" : `Alles publiceren (${nietLive})`}\n </Button>\n </div>\n )}\n </div>\n )}\n {actief.length > 10 && (\n <Input aria-label=\"Pagina's zoeken\" placeholder=\"Zoeken…\" value={zoek} onChange={(e) => setZoek(e.target.value)} className=\"mb-2\" />\n )}\n <ul className=\"grid gap-1\">\n {gewoon.filter(past).map((p) => (\n <li key={p.id} className=\"min-w-0\">\n <PaginaKnop p={p} selected={p.id === selected} onClick={() => setSelected(p.id)} />\n </li>\n ))}\n {/* Geen lege-lijst-tekst hier: de lege staat rechts zegt hetzelfde én noemt de volgende\n stap. Twee keer \"Nog geen pagina's\" naast elkaar leest als een fout. */}\n </ul>\n {functioneel.length > 0 && (\n <div className=\"mt-4 border-t border-slate-200 pt-3\">\n <p className=\"mb-1 px-3 text-xs font-medium tracking-wide text-slate-500 uppercase\">Winkel & functioneel</p>\n <p className=\"mb-2 px-3 text-xs text-slate-500\">\n Deze pagina's zijn het omhulsel van een functie. Producten en bestellingen beheer je\n onder Webwinkel; hier pas je alleen de tekst eromheen aan.\n </p>\n <ul className=\"grid gap-1\">\n {functioneel.filter(past).map((p) => (\n <li key={p.id} className=\"min-w-0\">\n <PaginaKnop p={p} selected={p.id === selected} onClick={() => setSelected(p.id)} />\n </li>\n ))}\n </ul>\n </div>\n )}\n {prullenbak.length > 0 && (\n <div className=\"mt-4 border-t border-slate-200 pt-3\">\n <p className=\"mb-1 px-3 text-xs font-medium tracking-wide text-slate-500 uppercase\">Prullenbak</p>\n <p className=\"mb-2 px-3 text-xs text-slate-500\">Wordt na 30 dagen automatisch geleegd.</p>\n <ul className=\"grid gap-1\">\n {prullenbak.map((p) => (\n <li key={p.id} className=\"min-w-0\">\n <PaginaKnop p={p} selected={p.id === selected} onClick={() => setSelected(p.id)} />\n <div className=\"flex gap-1 px-3 pb-1\">\n <Button variant=\"ghost\" size=\"sm\" onClick={() => void herstel(p)}>Herstellen</Button>\n <Button variant=\"dangerGhost\" size=\"sm\" onClick={() => void definitiefWeg(p)}>\n Definitief verwijderen\n </Button>\n </div>\n </li>\n ))}\n </ul>\n </div>\n )}\n </Card>\n\n <div ref={detailRef} className=\"scroll-mt-24\">\n {current ? (\n <PageEditor siteId={siteId} page={current} allPages={pages} />\n ) : (\n <Card className=\"grid place-items-center py-16 text-center\">\n <div className=\"max-w-sm\">\n {/* Een lege lijst is een uitnodiging, geen mededeling: zeg wat de volgende stap is. */}\n <p className=\"text-sm font-medium text-slate-700\">\n {actief.length === 0 ? \"Nog geen pagina's\" : \"Geen pagina geselecteerd\"}\n </p>\n <p className=\"mt-1 text-sm text-slate-500\">\n {actief.length === 0\n ? isDemoActive()\n ? \"In de demo zie je hier de pagina's die je op de site hebt geopend of bewerkt. Maak er een met + Nieuw, of bewerk een pagina op de site zelf.\"\n : \"Maak je eerste pagina met + Nieuw. Wat je maakt blijft een concept tot je publiceert.\"\n : \"Kies links een pagina om de instellingen aan te passen, of open hem op de site om de tekst te bewerken.\"}\n </p>\n </div>\n </Card>\n )}\n </div>\n </div>\n </>\n );\n}\n"],"mappings":";AAwEQ,SAiOJ,UAjOI,KAG4B,YAH5B;AAtER,SAAS,WAAW,SAAS,gBAAgB;AAC7C,SAAS,QAAQ,MAAM,OAAO,aAAa;AAC3C,SAAS,cAAc;AACvB,SAAS,QAAQ,qBAAqB;AACtC,SAAS,gBAAgB;AACzB,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAC1B,SAAS,oBAAoB;AAC7B,SAAS,uBAAuB;AAChC,SAAS,2BAA2B;AACpC,SAAS,gBAAgB,YAAY,YAAY,aAAa,gBAAgB,aAAa,yBAAyC;AACpI,SAAS,wBAAwB;AACjC,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB,qBAAqB,0BAA0B;AACzE,SAAS,mBAAmB;AAC5B,SAAS,YAAY,qBAAqB;AAE1C,SAAS,eAAe;AACxB,SAAS,gBAAgB,eAAe;AACxC,SAAS,cAAc;AACvB,SAAS,eAAe;AACxB,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAS9B,MAAM,oBAAoB,oBAAI,IAAI;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AACD,SAAS,cAAc,GAAuB;AAI5C,MAAI,EAAE,SAAS,IAAK,QAAO;AAC3B,UAAQ,EAAE,UAAU,CAAC,GAAG,KAAK,CAAC,MAAM,kBAAkB,IAAI,OAAQ,EAA0B,KAAK,CAAC,CAAC;AACrG;AAYA,SAAS,WAAW,EAAE,GAAG,UAAU,QAAQ,GAA6D;AACtG,QAAM,UAAU,WAAW,CAAC;AAC5B,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO,GAAG,EAAE,KAAK,WAAM,EAAE,IAAI;AAAA,MAC7B,WAAW,yFACT,WAAW,+BAA+B,oBAC5C;AAAA,MAEA;AAAA,6BAAC,UAAK,WAAU,WACd;AAAA,8BAAC,UAAK,WAAU,kBAAkB,YAAE,OAAM;AAAA,UAC1C,qBAAC,UAAK,WAAW,0BAA0B,WAAW,sBAAsB,gBAAgB,IACzF;AAAA,cAAE;AAAA,YACF,WAAW,CAAC,EAAE,WAAW,qBAAC,UAAK,WAAU,kBAAiB;AAAA;AAAA,cAAI;AAAA,eAAQ;AAAA,YACtE,QAAQ,EAAE,aAAa,EAAE,WAAW,KAAK,CAAC,EAAE,WAAW,oBAAC,UAAK,WAAU,kBAAiB,6BAAY;AAAA,YACpG,EAAE,gBAAgB,CAAC,EAAE,WAAW,oBAAC,UAAK,WAAU,gBAAe,oCAAmB;AAAA,aACrF;AAAA,WACF;AAAA,QACA,oBAAC,iBAAc,GAAM;AAAA;AAAA;AAAA,EACvB;AAEJ;AAGA,MAAM,YAAY,gBAAgB,OAAO,CAAC,MAAM,EAAE,GAAG,WAAW,OAAO,CAAC;AAEjE,SAAS,WAAW,EAAE,OAAO,GAAuB;AACzD,QAAM,WAAW,YAAY;AAC7B,QAAM,EAAE,MAAM,IAAI,SAAS;AAC3B,QAAM,UAAU,WAAW;AAC3B,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAsB,CAAC,CAAC;AAClD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAwB,MAAM,gBAAgB,OAAO,CAAC;AACtF,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,EAAE;AAC3C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAS,MAAM;AAC/C,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,KAAK;AAChD,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,IAAI;AACzC,QAAM,CAAC,WAAW,YAAY,IAAI,SAAwB,IAAI;AAC9D,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,KAAK;AACxC,QAAM,EAAE,KAAK,IAAI,QAAQ;AACzB,QAAM,UAAU,cAAc,IAAI;AAClC,QAAM,MAAM,cAAc;AAE1B,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAC5C,QAAM,CAAC,UAAU,WAAW,IAAI,SAAwB,IAAI;AAC5D,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,CAAC;AACtC;AAAA,IACE,MACE;AAAA,MACE;AAAA,MACA,CAAC,MAAM;AACL,iBAAS,CAAC;AACV,mBAAW,IAAI;AACf,oBAAY,IAAI;AAAA,MAClB;AAAA,MACA,CAAC,MAAM;AAEL,YAAI,aAAa,GAAG;AAClB,qBAAW,IAAI;AACf;AAAA,QACF;AACA,oBAAY,EAAE,OAAO;AAAA,MACvB;AAAA,IACF;AAAA,IACF,CAAC,QAAQ,MAAM;AAAA,EACjB;AAEA,QAAM,SAAS,QAAQ,MAAM,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,CAAC,KAAK,CAAC;AACrE,QAAM,aAAa,QAAQ,MAAM,MAAM,OAAO,CAAC,MAAM,EAAE,OAAO,GAAG,CAAC,KAAK,CAAC;AACxE,QAAM,SAAS,OAAO,OAAO,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;AACrD,QAAM,cAAc,OAAO,OAAO,aAAa;AAC/C,QAAM,WAAW,OAAO,OAAO,CAAC,MAAM,eAAe,CAAC,MAAM,WAAW,EAAE;AAEzE,YAAU,MAAM;AAEd,QAAI,CAAC,YAAY,OAAO,OAAQ,cAAa,OAAO,CAAC,KAAK,OAAO,CAAC,GAAG,EAAE;AAAA,EAEzE,GAAG,CAAC,OAAO,QAAQ,CAAC;AAEpB,QAAM,UAAU,MAAM,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ,KAAK;AACxD,QAAM,YAAY,oBAAoB,QAAQ;AAG9C,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE;AACnC,QAAM,OAAO,CAAC,MAAiB;AAC7B,UAAM,IAAI,KAAK,KAAK,EAAE,YAAY;AAClC,WAAO,CAAC,KAAK,GAAG,EAAE,KAAK,IAAI,EAAE,IAAI,GAAG,YAAY,EAAE,SAAS,CAAC;AAAA,EAC9D;AAGA,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAS,KAAK;AAC5D,iBAAe,kBAAkB;AAC/B,UAAM,QAAQ,OAAO,OAAO,CAAC,MAAM,eAAe,CAAC,MAAM,WAAW;AAGpE,UAAM,MAAM,MAAM,kBAAkB,MAAM;AAC1C,UAAM,aAAa,oBAAI,IAAI,CAAC,GAAG,OAAO,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AACjH,UAAM,YAAY,MAAM,IAAI,CAAC,OAAO;AAAA,MAClC;AAAA,MACA,GAAG,iBAAiB,GAAG;AAAA,QACrB,cAAc,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,QACtC,WAAW,CAAC,GAAG,UAAU;AAAA,QACzB,WAAW,IAAI;AAAA,MACjB,CAAC,EAAE,OAAO,CAAC,MAAM,EAAE,UAAU,SAAS,EAAE,UAAU,cAAc;AAAA,IAClE,EAAE;AACF,UAAM,KAAK,MAAM,QAAQ;AAAA,MACvB,OAAO,GAAG,MAAM,MAAM;AAAA,MACtB,aACE,oBAAC,QAAG,WAAU,kBACX,oBAAU,IAAI,CAAC,EAAE,GAAG,EAAE,MACrB,qBAAC,QACE;AAAA,UAAE,SAAS,EAAE;AAAA,QAAK;AAAA,QAAC,qBAAC,UAAK,WAAU,kBAAiB;AAAA;AAAA,UAAE,EAAE;AAAA,UAAK;AAAA,WAAC;AAAA,QAC9D,EAAE,SAAS,KACV,oBAAC,QAAG,WAAU,4CACX,YAAE,IAAI,CAAC,GAAG,MAAM,oBAAC,QAAY,YAAE,SAAN,CAAY,CAAK,GAC7C;AAAA,WALK,EAAE,EAOX,CACD,GACH;AAAA,MAEF,cAAc;AAAA,IAChB,CAAC;AACD,QAAI,CAAC,GAAI;AACT,uBAAmB,IAAI;AACvB,UAAM,UAAoB,CAAC;AAC3B,eAAW,KAAK,OAAO;AACrB,UAAI;AACF,cAAM,YAAY,QAAQ,EAAE,EAAE;AAAA,MAChC,SAAS,GAAG;AACV,gBAAQ,KAAK,GAAG,EAAE,SAAS,EAAE,IAAI,KAAM,EAAY,OAAO,EAAE;AAAA,MAC9D;AAAA,IACF;AACA,uBAAmB,KAAK;AACxB;AAAA,MACE,QAAQ,WAAW,IACf,EAAE,OAAO,oBAAoB,MAAM,UAAU,IAC7C,EAAE,OAAO,GAAG,QAAQ,MAAM,QAAQ,MAAM,MAAM,sBAAsB,aAAa,QAAQ,KAAK,QAAK,GAAG,MAAM,QAAQ;AAAA,IAC1H;AAAA,EACF;AAGA,QAAM,YAAY,MAAM;AACtB,UAAM,OAAO,QAAQ,SAAS,KAAK,CAAC,KAAK;AACzC,WAAO,QAAQ,SAAS,SAAS,MAAM,IAAI,IAAI,IAAI,MAAM,OAAO,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC;AAAA,EACvG,GAAG;AAEH,iBAAe,SAAS;AACtB,UAAM,QAAQ,SAAS,KAAK;AAE5B,QAAI,CAAC,OAAO;AACV,mBAAa,0BAA0B;AACvC;AAAA,IACF;AACA,UAAM,OAAO;AACb,UAAM,OAAO,KAAK,MAAM,GAAG,EAAE,IAAI,KAAK;AACtC,UAAM,UAAU,UAAU,KAAK,CAAC,MAAM,EAAE,OAAO,QAAQ;AACvD,aAAS,IAAI;AACb,QAAI;AACF,YAAM,KAAK,MAAM,WAAW,QAAQ;AAAA,QAClC;AAAA,QACA;AAAA,QACA;AAAA,QACA,GAAI,UAAU,EAAE,QAAQ,mBAAmB,OAAO,EAAyB,IAAI,CAAC;AAAA,MAClF,CAAC;AACD,UAAI,cAAc;AAClB,UAAI,WAAW,UAAU,SAAS,KAAK;AACrC,cAAM,eAAe,QAAQ,EAAE,OAAO,OAAO,MAAM,KAAK,GAAG,IAAI,OAAO,CAAC,CAAC,EAAE,MAAM,MAAM;AACpF,wBAAc;AAAA,QAChB,CAAC;AAAA,MACH;AACA,kBAAY,EAAE;AACd,kBAAY,MAAM;AAClB,kBAAY,EAAE;AACd,mBAAa,KAAK;AAClB,YAAM;AAAA,QACJ,OAAO;AAAA,QACP,aAAa,cACT,GAAG,IAAI,kFACP,GAAG,IAAI;AAAA,QACX,MAAM;AAAA,QACN,QAAQ;AAAA,UACN,OAAO;AAAA,UACP,SAAS,MAAM;AACb,gBAAI;AACF,6BAAe,QAAQ,qBAAqB,UAAU;AAAA,YACxD,QAAQ;AAAA,YAER;AACA,mBAAO,SAAS,OAAO,IAAI;AAAA,UAC7B;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,SAAS,GAAG;AACV,YAAM,EAAE,OAAO,2BAA2B,aAAc,EAAY,SAAS,MAAM,QAAQ,CAAC;AAAA,IAC9F,UAAE;AACA,eAAS,KAAK;AAAA,IAChB;AAAA,EACF;AAEA,iBAAe,QAAQ,GAAc;AACnC,QAAI;AACF,YAAM,YAAY,QAAQ,EAAE,EAAE;AAC9B,kBAAY,EAAE,EAAE;AAChB,YAAM,EAAE,OAAO,wBAAwB,aAAa,yCAAyC,MAAM,UAAU,CAAC;AAAA,IAChH,SAAS,GAAG;AACV,YAAM,EAAE,OAAO,sBAAsB,aAAc,EAAY,SAAS,MAAM,QAAQ,CAAC;AAAA,IACzF;AAAA,EACF;AAEA,iBAAe,cAAc,GAAc;AACzC,UAAM,KAAK,MAAM,QAAQ;AAAA,MACvB,OAAO,IAAI,EAAE,KAAK;AAAA,MAClB,aAAa;AAAA,MACb,cAAc;AAAA,MACd,MAAM;AAAA,IACR,CAAC;AACD,QAAI,CAAC,GAAI;AACT,QAAI;AACF,YAAM,WAAW,QAAQ,EAAE,EAAE;AAC7B,UAAI,aAAa,EAAE,GAAI,aAAY,IAAI;AACvC,YAAM,EAAE,OAAO,oBAAoB,CAAC;AAAA,IACtC,SAAS,GAAG;AACV,YAAM,EAAE,OAAO,uBAAuB,aAAc,EAAY,SAAS,MAAM,QAAQ,CAAC;AAAA,IAC1F;AAAA,EACF;AAEA,MAAI,YAAY,CAAC,SAAS;AACxB,WACE,oBAAC,aAAU,OAAO,CAAC,SAAS,MAAM,UAAU,KAAI,YAAW,SAAS,MAAM;AAAE,kBAAY,IAAI;AAAG,gBAAU,CAAC,MAAM,IAAI,CAAC;AAAA,IAAG,GACrH,gBACH;AAAA,EAEJ;AAEA,SACE,iCAGC;AAAA,WAAO,WAAW,KAAK,WAAW,oBAAC,SAAI,WAAU,QAAO,8BAAC,iBAAc,QAAgB,GAAE;AAAA,IAC1F,qBAAC,SAAI,WAAU,uCACb;AAAA,2BAAC,QAAK,WAAU,SACd;AAAA,6BAAC,SAAI,WAAU,gDACb;AAAA,8BAAC,UAAK,WAAU,8DAA6D,uBAAS;AAAA,UACtF,oBAAC,UAAO,MAAK,MAAK,SAAS,MAAM;AAAE,yBAAa,IAAI;AAAG,yBAAa,IAAI;AAAA,UAAG,GAAG,qBAAO;AAAA,UACrF,oBAAC,UAAO,MAAM,WAAW,cAAc,cACrC,8BAAC,iBAAc,OAAM,iBACnB;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,UAAU,CAAC,MAAM;AACf,kBAAE,eAAe;AACjB,qBAAK,OAAO;AAAA,cACd;AAAA,cAEA;AAAA,oCAAC,SAAM,OAAM,sBAAqB,MAAM,SAAS,KAAK,IAAI,WAAW,QAAQ,KAAK,gBAChF;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,oBACP,UAAU,CAAC,MAAM;AACf,kCAAY,EAAE,OAAO,KAAK;AAC1B,mCAAa,IAAI;AAAA,oBACnB;AAAA,oBACA,aAAY;AAAA,oBACZ,WAAS;AAAA,oBACT,gBAAc,YAAY,OAAO;AAAA;AAAA,gBACnC,GACF;AAAA,gBACC,aAAa,oBAAC,OAAE,MAAK,SAAQ,WAAU,8BAA8B,qBAAU;AAAA,gBAChF,oBAAC,SAAM,OAAM,gBAAe,MAAK,0GAC/B;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,oBACP,eAAe;AAAA,oBAEf,SAAS,CAAC,EAAE,OAAO,QAAQ,OAAO,cAAc,GAAG,GAAG,UAAU,OAAO,CAAC,MAAM,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,SAAS,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,OAAO,EAAE,MAAM,EAAE,CAAC;AAAA;AAAA,gBACnL,GACF;AAAA,gBACC,WAAW,aAAa,OACvB,oBAAC,UAAO,SAAS,QAAQ,iBAAiB,WAAW,OAAM,+BAA8B;AAAA,gBAE3F,qBAAC,SAAI,WAAU,0BACb;AAAA,sCAAC,UAAO,MAAK,UAAS,SAAQ,aAAY,SAAS,MAAM,aAAa,KAAK,GAAG,uBAAS;AAAA,kBACvF,oBAAC,UAAO,MAAK,UAAS,UAAU,OAAQ,kBAAQ,mBAAc,YAAW;AAAA,mBAC3E;AAAA;AAAA;AAAA,UACF,GACF,GACF;AAAA,WACF;AAAA,QACC,WAAW,KACV,qBAAC,SAAI,WAAU,2EACb;AAAA,+BAAC,OAAG;AAAA,yBAAa,IAAI,mBAAmB,GAAG,QAAQ;AAAA,YAAmB;AAAA,aAAqC;AAAA,UAC1G,WAAW,KACV,oBAAC,SACC,8BAAC,UAAO,MAAK,MAAK,SAAQ,aAAY,UAAU,iBAAiB,SAAS,MAAM,KAAK,gBAAgB,GAClG,4BAAkB,qBAAgB,qBAAqB,QAAQ,KAClE,GACF;AAAA,WAEJ;AAAA,QAED,OAAO,SAAS,MACf,oBAAC,SAAM,cAAW,mBAAkB,aAAY,gBAAU,OAAO,MAAM,UAAU,CAAC,MAAM,QAAQ,EAAE,OAAO,KAAK,GAAG,WAAU,QAAO;AAAA,QAEpI,oBAAC,QAAG,WAAU,cACX,iBAAO,OAAO,IAAI,EAAE,IAAI,CAAC,MACxB,oBAAC,QAAc,WAAU,WACvB,8BAAC,cAAW,GAAM,UAAU,EAAE,OAAO,UAAU,SAAS,MAAM,YAAY,EAAE,EAAE,GAAG,KAD1E,EAAE,EAEX,CACD,GAGH;AAAA,QACC,YAAY,SAAS,KACpB,qBAAC,SAAI,WAAU,uCACb;AAAA,8BAAC,OAAE,WAAU,wEAAuE,kCAAwB;AAAA,UAC5G,oBAAC,OAAE,WAAU,oCAAmC,6JAGhD;AAAA,UACA,oBAAC,QAAG,WAAU,cACX,sBAAY,OAAO,IAAI,EAAE,IAAI,CAAC,MAC7B,oBAAC,QAAc,WAAU,WACvB,8BAAC,cAAW,GAAM,UAAU,EAAE,OAAO,UAAU,SAAS,MAAM,YAAY,EAAE,EAAE,GAAG,KAD1E,EAAE,EAEX,CACD,GACH;AAAA,WACF;AAAA,QAED,WAAW,SAAS,KACnB,qBAAC,SAAI,WAAU,uCACb;AAAA,8BAAC,OAAE,WAAU,wEAAuE,wBAAU;AAAA,UAC9F,oBAAC,OAAE,WAAU,oCAAmC,oDAAsC;AAAA,UACtF,oBAAC,QAAG,WAAU,cACX,qBAAW,IAAI,CAAC,MACf,qBAAC,QAAc,WAAU,WACvB;AAAA,gCAAC,cAAW,GAAM,UAAU,EAAE,OAAO,UAAU,SAAS,MAAM,YAAY,EAAE,EAAE,GAAG;AAAA,YACjF,qBAAC,SAAI,WAAU,wBACb;AAAA,kCAAC,UAAO,SAAQ,SAAQ,MAAK,MAAK,SAAS,MAAM,KAAK,QAAQ,CAAC,GAAG,wBAAU;AAAA,cAC5E,oBAAC,UAAO,SAAQ,eAAc,MAAK,MAAK,SAAS,MAAM,KAAK,cAAc,CAAC,GAAG,oCAE9E;AAAA,eACF;AAAA,eAPO,EAAE,EAQX,CACD,GACH;AAAA,WACF;AAAA,SAEJ;AAAA,MAEA,oBAAC,SAAI,KAAK,WAAW,WAAU,gBAC5B,oBACC,oBAAC,cAAW,QAAgB,MAAM,SAAS,UAAU,OAAO,IAE5D,oBAAC,QAAK,WAAU,6CACd,+BAAC,SAAI,WAAU,YAEb;AAAA,4BAAC,OAAE,WAAU,sCACV,iBAAO,WAAW,IAAI,sBAAsB,4BAC/C;AAAA,QACA,oBAAC,OAAE,WAAU,+BACV,iBAAO,WAAW,IACf,aAAa,IACX,iJACA,0FACF,2GACN;AAAA,SACF,GACF,GAEJ;AAAA,OACF;AAAA,KACA;AAEJ;","names":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Start met een kant-en-klare opzet" (8.14) — alleen bij een site zonder pagina's.
|
|
3
|
+
*
|
|
4
|
+
* Kies wat voor bedrijf het is, en de site krijgt in één keer de pagina's (als werkversie, niets
|
|
5
|
+
* gaat live), het menu, de modules die die pagina's nodig hebben, het soort bedrijf voor Google, de
|
|
6
|
+
* knop in de kop en — als je wilt — een passende huisstijl. Daarna vul je de teksten in op de
|
|
7
|
+
* pagina zelf. Zie `starters/starters.ts`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function StarterKiezer({ siteId, onKlaar }: {
|
|
10
|
+
siteId: string;
|
|
11
|
+
onKlaar?: () => void;
|
|
12
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
import { doc, getDoc } from "firebase/firestore";
|
|
5
|
+
import { getDb, getFirebaseApp } from "../../firebase/client.js";
|
|
6
|
+
import { callable } from "../../firebase/functionsClient.js";
|
|
7
|
+
import { isDemoActive } from "../../demo/demoStore.js";
|
|
8
|
+
import { STARTERS, starterModules, starterPaginas } from "../../starters/starters.js";
|
|
9
|
+
import { builtinModules } from "../../modules/builtins.js";
|
|
10
|
+
import { builtinThemePresets } from "../../theme/presets.js";
|
|
11
|
+
import { SiteSettingsSchema } from "../../schema/settings.js";
|
|
12
|
+
import { createPage } from "../lib/pagesClient.js";
|
|
13
|
+
import { zodFoutTekst } from "../lib/zodFout.js";
|
|
14
|
+
import { Button, Card } from "../ui/primitives.js";
|
|
15
|
+
import { Switch } from "../ui/switch.js";
|
|
16
|
+
import { Dialog, DialogContent, DialogFooter } from "../ui/dialog.js";
|
|
17
|
+
import { useToast } from "../ui/toast.js";
|
|
18
|
+
function StarterKiezer({ siteId, onKlaar }) {
|
|
19
|
+
const { toast } = useToast();
|
|
20
|
+
const [gekozen, setGekozen] = useState(null);
|
|
21
|
+
const [metStijl, setMetStijl] = useState(true);
|
|
22
|
+
const [bezig, setBezig] = useState(false);
|
|
23
|
+
const preset = gekozen ? builtinThemePresets.find((p) => p.id === gekozen.preset) : void 0;
|
|
24
|
+
async function zetKlaar(s) {
|
|
25
|
+
setBezig(true);
|
|
26
|
+
try {
|
|
27
|
+
const paginas = starterPaginas(s);
|
|
28
|
+
for (const p of paginas) await createPage(siteId, { title: p.title, slug: p.slug, path: p.path, blocks: p.blocks });
|
|
29
|
+
const db = getDb();
|
|
30
|
+
const app = getFirebaseApp();
|
|
31
|
+
if (!isDemoActive() && db && app) {
|
|
32
|
+
const huidig = (await getDoc(doc(db, "sites", siteId, "settings", "site"))).data() ?? {};
|
|
33
|
+
const mods = starterModules(s, builtinModules);
|
|
34
|
+
const nav = huidig.nav?.length ? huidig.nav : paginas.filter((p) => p.inMenu).map((p) => ({ label: p.title, href: p.path }));
|
|
35
|
+
const volgend = {
|
|
36
|
+
...huidig,
|
|
37
|
+
nav,
|
|
38
|
+
modules: { ...huidig.modules ?? {}, ...Object.fromEntries(mods.map((m) => [m, true])) },
|
|
39
|
+
business: { ...huidig.business ?? {}, type: huidig.business?.type ?? s.bedrijfstype },
|
|
40
|
+
header: { ...huidig.header ?? {}, cta: huidig.header?.cta ?? s.cta },
|
|
41
|
+
...metStijl && preset ? { theme: { ...huidig.theme ?? {}, ...preset.theme } } : {}
|
|
42
|
+
};
|
|
43
|
+
const parsed = SiteSettingsSchema.safeParse(volgend);
|
|
44
|
+
if (!parsed.success) throw new Error(zodFoutTekst(parsed.error.issues[0]));
|
|
45
|
+
await callable(app, "saveSiteSettings")({ siteId, settings: parsed.data });
|
|
46
|
+
}
|
|
47
|
+
toast({
|
|
48
|
+
title: `${paginas.length} pagina's klaargezet`,
|
|
49
|
+
description: "Als werkversie \u2014 er staat nog niets live. Open een pagina en vul de teksten in met het potlood.",
|
|
50
|
+
tone: "success",
|
|
51
|
+
action: { label: "Open de homepage", onClick: () => {
|
|
52
|
+
try {
|
|
53
|
+
sessionStorage.setItem("xicms-bewerkmodus", "bewerken");
|
|
54
|
+
} catch {
|
|
55
|
+
}
|
|
56
|
+
window.location.assign("/");
|
|
57
|
+
} }
|
|
58
|
+
});
|
|
59
|
+
setGekozen(null);
|
|
60
|
+
onKlaar?.();
|
|
61
|
+
} catch (e) {
|
|
62
|
+
toast({ title: "Klaarzetten mislukt", description: e.message, tone: "error" });
|
|
63
|
+
} finally {
|
|
64
|
+
setBezig(false);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
68
|
+
/* @__PURE__ */ jsx("h3", { className: "text-base font-semibold", children: "Start met een kant-en-klare opzet" }),
|
|
69
|
+
/* @__PURE__ */ jsx("p", { className: "mb-3 text-sm text-slate-500", children: "Kies wat voor bedrijf je hebt. Je krijgt meteen de pagina's die daarbij horen, als werkversie om in te vullen." }),
|
|
70
|
+
/* @__PURE__ */ jsx("div", { className: "grid gap-2 sm:grid-cols-2 lg:grid-cols-4", children: STARTERS.map((s) => /* @__PURE__ */ jsxs(
|
|
71
|
+
"button",
|
|
72
|
+
{
|
|
73
|
+
type: "button",
|
|
74
|
+
onClick: () => setGekozen(s),
|
|
75
|
+
className: "xicms-admin-btn grid gap-1 rounded-lg border border-slate-200 bg-white p-3 text-left hover:border-slate-400 hover:bg-slate-50",
|
|
76
|
+
children: [
|
|
77
|
+
/* @__PURE__ */ jsx("span", { className: "text-xl", "aria-hidden": true, children: s.icoon }),
|
|
78
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-slate-900", children: s.label }),
|
|
79
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs leading-snug text-slate-500", children: s.voor })
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
s.id
|
|
83
|
+
)) }),
|
|
84
|
+
gekozen && /* @__PURE__ */ jsx(Dialog, { open: true, onOpenChange: (v) => !v && !bezig && setGekozen(null), children: /* @__PURE__ */ jsxs(DialogContent, { title: `${gekozen.icoon} ${gekozen.label}`, width: "min(92vw, 34rem)", children: [
|
|
85
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-3 text-sm text-slate-700", children: [
|
|
86
|
+
/* @__PURE__ */ jsx("p", { children: "Deze pagina's worden klaargezet (als werkversie):" }),
|
|
87
|
+
/* @__PURE__ */ jsx("ul", { className: "list-disc pl-5", children: gekozen.paginas.map((p) => /* @__PURE__ */ jsxs("li", { children: [
|
|
88
|
+
p.title,
|
|
89
|
+
" ",
|
|
90
|
+
/* @__PURE__ */ jsxs("span", { className: "text-slate-500", children: [
|
|
91
|
+
"(",
|
|
92
|
+
p.path,
|
|
93
|
+
")"
|
|
94
|
+
] })
|
|
95
|
+
] }, p.path)) }),
|
|
96
|
+
/* @__PURE__ */ jsxs("p", { className: "text-slate-500", children: [
|
|
97
|
+
"Ook: het menu, de knop \u201C",
|
|
98
|
+
gekozen.cta.label,
|
|
99
|
+
"\u201D rechtsboven en de onderdelen die deze pagina's gebruiken."
|
|
100
|
+
] }),
|
|
101
|
+
preset && /* @__PURE__ */ jsx(Switch, { checked: metStijl, onCheckedChange: setMetStijl, label: `Ook de huisstijl \u201C${preset.label}\u201D gebruiken (later aan te passen)` })
|
|
102
|
+
] }),
|
|
103
|
+
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
104
|
+
/* @__PURE__ */ jsx(Button, { variant: "ghost", disabled: bezig, onClick: () => setGekozen(null), children: "Annuleren" }),
|
|
105
|
+
/* @__PURE__ */ jsx(Button, { loading: bezig, onClick: () => void zetKlaar(gekozen), children: "Klaarzetten" })
|
|
106
|
+
] })
|
|
107
|
+
] }) })
|
|
108
|
+
] });
|
|
109
|
+
}
|
|
110
|
+
export {
|
|
111
|
+
StarterKiezer
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=StarterKiezer.js.map
|