@xiwebdesign/xicms-core 7.13.0 → 7.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/admin/lib/mediaUsage.d.ts +17 -0
- package/dist/admin/lib/mediaUsage.js +32 -1
- package/dist/admin/lib/mediaUsage.js.map +1 -1
- package/dist/admin/media/MediaManager.js +74 -17
- package/dist/admin/media/MediaManager.js.map +1 -1
- package/dist/admin/visual/VisualEditor.js +37 -3
- package/dist/admin/visual/VisualEditor.js.map +1 -1
- package/dist/blocks/BlockErrorBoundary.d.ts +1 -0
- package/dist/blocks/BlockErrorBoundary.js +4 -0
- package/dist/blocks/BlockErrorBoundary.js.map +1 -1
- package/dist/blocks/BlockRenderer.js +1 -1
- package/dist/blocks/BlockRenderer.js.map +1 -1
- package/dist/blocks/builtins/Accordion.d.ts +1 -2
- package/dist/blocks/builtins/Accordion.js +2 -39
- package/dist/blocks/builtins/Accordion.js.map +1 -1
- package/dist/blocks/builtins/AccordionRender.d.ts +7 -0
- package/dist/blocks/builtins/AccordionRender.js +42 -0
- package/dist/blocks/builtins/AccordionRender.js.map +1 -0
- package/dist/blocks/builtins/Agenda.d.ts +1 -29
- package/dist/blocks/builtins/Agenda.js +3 -94
- package/dist/blocks/builtins/Agenda.js.map +1 -1
- package/dist/blocks/builtins/AgendaRender.d.ts +34 -0
- package/dist/blocks/builtins/AgendaRender.js +96 -0
- package/dist/blocks/builtins/AgendaRender.js.map +1 -0
- package/dist/blocks/builtins/Banner.d.ts +1 -2
- package/dist/blocks/builtins/Banner.js +2 -32
- package/dist/blocks/builtins/Banner.js.map +1 -1
- package/dist/blocks/builtins/BannerRender.d.ts +11 -0
- package/dist/blocks/builtins/BannerRender.js +35 -0
- package/dist/blocks/builtins/BannerRender.js.map +1 -0
- package/dist/blocks/builtins/BeforeAfter.d.ts +1 -2
- package/dist/blocks/builtins/BeforeAfter.js +2 -31
- package/dist/blocks/builtins/BeforeAfter.js.map +1 -1
- package/dist/blocks/builtins/BeforeAfterRender.d.ts +11 -0
- package/dist/blocks/builtins/BeforeAfterRender.js +34 -0
- package/dist/blocks/builtins/BeforeAfterRender.js.map +1 -0
- package/dist/blocks/builtins/Booking.d.ts +1 -2
- package/dist/blocks/builtins/Booking.js +2 -14
- package/dist/blocks/builtins/Booking.js.map +1 -1
- package/dist/blocks/builtins/BookingRender.d.ts +8 -0
- package/dist/blocks/builtins/BookingRender.js +17 -0
- package/dist/blocks/builtins/BookingRender.js.map +1 -0
- package/dist/blocks/builtins/Breadcrumbs.d.ts +1 -10
- package/dist/blocks/builtins/Breadcrumbs.js +3 -69
- package/dist/blocks/builtins/Breadcrumbs.js.map +1 -1
- package/dist/blocks/builtins/BreadcrumbsRender.d.ts +18 -0
- package/dist/blocks/builtins/BreadcrumbsRender.js +71 -0
- package/dist/blocks/builtins/BreadcrumbsRender.js.map +1 -0
- package/dist/blocks/builtins/Cards.d.ts +1 -2
- package/dist/blocks/builtins/Cards.js +2 -74
- package/dist/blocks/builtins/Cards.js.map +1 -1
- package/dist/blocks/builtins/CardsRender.d.ts +7 -0
- package/dist/blocks/builtins/CardsRender.js +77 -0
- package/dist/blocks/builtins/CardsRender.js.map +1 -0
- package/dist/blocks/builtins/Columns.d.ts +1 -2
- package/dist/blocks/builtins/Columns.js +2 -9
- package/dist/blocks/builtins/Columns.js.map +1 -1
- package/dist/blocks/builtins/ColumnsRender.d.ts +6 -0
- package/dist/blocks/builtins/ColumnsRender.js +12 -0
- package/dist/blocks/builtins/ColumnsRender.js.map +1 -0
- package/dist/blocks/builtins/Contact.d.ts +2 -7
- package/dist/blocks/builtins/Contact.js +3 -102
- package/dist/blocks/builtins/Contact.js.map +1 -1
- package/dist/blocks/builtins/ContactRender.d.ts +9 -0
- package/dist/blocks/builtins/ContactRender.js +105 -0
- package/dist/blocks/builtins/ContactRender.js.map +1 -0
- package/dist/blocks/builtins/Countdown.d.ts +1 -18
- package/dist/blocks/builtins/Countdown.js +3 -53
- package/dist/blocks/builtins/Countdown.js.map +1 -1
- package/dist/blocks/builtins/CountdownRender.d.ts +22 -0
- package/dist/blocks/builtins/CountdownRender.js +55 -0
- package/dist/blocks/builtins/CountdownRender.js.map +1 -0
- package/dist/blocks/builtins/Cta.d.ts +1 -2
- package/dist/blocks/builtins/Cta.js +2 -39
- package/dist/blocks/builtins/Cta.js.map +1 -1
- package/dist/blocks/builtins/CtaRender.d.ts +6 -0
- package/dist/blocks/builtins/CtaRender.js +42 -0
- package/dist/blocks/builtins/CtaRender.js.map +1 -0
- package/dist/blocks/builtins/Downloads.d.ts +1 -2
- package/dist/blocks/builtins/Downloads.js +2 -16
- package/dist/blocks/builtins/Downloads.js.map +1 -1
- package/dist/blocks/builtins/DownloadsRender.d.ts +7 -0
- package/dist/blocks/builtins/DownloadsRender.js +19 -0
- package/dist/blocks/builtins/DownloadsRender.js.map +1 -0
- package/dist/blocks/builtins/Elements.d.ts +3 -4
- package/dist/blocks/builtins/Elements.js +4 -38
- package/dist/blocks/builtins/Elements.js.map +1 -1
- package/dist/blocks/builtins/ElementsRender.d.ts +10 -0
- package/dist/blocks/builtins/ElementsRender.js +41 -0
- package/dist/blocks/builtins/ElementsRender.js.map +1 -0
- package/dist/blocks/builtins/Embed.d.ts +1 -2
- package/dist/blocks/builtins/Embed.js +2 -19
- package/dist/blocks/builtins/Embed.js.map +1 -1
- package/dist/blocks/builtins/EmbedRender.d.ts +7 -0
- package/dist/blocks/builtins/EmbedRender.js +22 -0
- package/dist/blocks/builtins/EmbedRender.js.map +1 -0
- package/dist/blocks/builtins/Faq.d.ts +1 -6
- package/dist/blocks/builtins/Faq.js +3 -103
- package/dist/blocks/builtins/Faq.js.map +1 -1
- package/dist/blocks/builtins/FaqRender.d.ts +10 -0
- package/dist/blocks/builtins/FaqRender.js +105 -0
- package/dist/blocks/builtins/FaqRender.js.map +1 -0
- package/dist/blocks/builtins/FormBlock.d.ts +1 -2
- package/dist/blocks/builtins/FormBlock.js +2 -222
- package/dist/blocks/builtins/FormBlock.js.map +1 -1
- package/dist/blocks/builtins/FormBlockRender.d.ts +6 -0
- package/dist/blocks/builtins/FormBlockRender.js +225 -0
- package/dist/blocks/builtins/FormBlockRender.js.map +1 -0
- package/dist/blocks/builtins/Gallery.d.ts +1 -23
- package/dist/blocks/builtins/Gallery.js +2 -164
- package/dist/blocks/builtins/Gallery.js.map +1 -1
- package/dist/blocks/builtins/GalleryRender.d.ts +25 -0
- package/dist/blocks/builtins/GalleryRender.js +167 -0
- package/dist/blocks/builtins/GalleryRender.js.map +1 -0
- package/dist/blocks/builtins/Hero.d.ts +1 -2
- package/dist/blocks/builtins/Hero.js +2 -73
- package/dist/blocks/builtins/Hero.js.map +1 -1
- package/dist/blocks/builtins/HeroRender.d.ts +6 -0
- package/dist/blocks/builtins/HeroRender.js +76 -0
- package/dist/blocks/builtins/HeroRender.js.map +1 -0
- package/dist/blocks/builtins/ImageBlock.d.ts +1 -2
- package/dist/blocks/builtins/ImageBlock.js +2 -22
- package/dist/blocks/builtins/ImageBlock.js.map +1 -1
- package/dist/blocks/builtins/ImageBlockRender.d.ts +6 -0
- package/dist/blocks/builtins/ImageBlockRender.js +25 -0
- package/dist/blocks/builtins/ImageBlockRender.js.map +1 -0
- package/dist/blocks/builtins/Jobs.d.ts +1 -15
- package/dist/blocks/builtins/Jobs.js +3 -69
- package/dist/blocks/builtins/Jobs.js.map +1 -1
- package/dist/blocks/builtins/JobsRender.d.ts +17 -0
- package/dist/blocks/builtins/JobsRender.js +71 -0
- package/dist/blocks/builtins/JobsRender.js.map +1 -0
- package/dist/blocks/builtins/Layout.d.ts +2 -3
- package/dist/blocks/builtins/Layout.js +3 -39
- package/dist/blocks/builtins/Layout.js.map +1 -1
- package/dist/blocks/builtins/LayoutRender.d.ts +8 -0
- package/dist/blocks/builtins/LayoutRender.js +42 -0
- package/dist/blocks/builtins/LayoutRender.js.map +1 -0
- package/dist/blocks/builtins/MapBlock.d.ts +1 -2
- package/dist/blocks/builtins/MapBlock.js +2 -45
- package/dist/blocks/builtins/MapBlock.js.map +1 -1
- package/dist/blocks/builtins/MapBlockRender.d.ts +6 -0
- package/dist/blocks/builtins/MapBlockRender.js +48 -0
- package/dist/blocks/builtins/MapBlockRender.js.map +1 -0
- package/dist/blocks/builtins/NewsListBlock.d.ts +1 -2
- package/dist/blocks/builtins/NewsListBlock.js +2 -11
- package/dist/blocks/builtins/NewsListBlock.js.map +1 -1
- package/dist/blocks/builtins/NewsListBlockRender.d.ts +6 -0
- package/dist/blocks/builtins/NewsListBlockRender.js +14 -0
- package/dist/blocks/builtins/NewsListBlockRender.js.map +1 -0
- package/dist/blocks/builtins/Newsletter.d.ts +1 -2
- package/dist/blocks/builtins/Newsletter.js +2 -89
- package/dist/blocks/builtins/Newsletter.js.map +1 -1
- package/dist/blocks/builtins/NewsletterRender.d.ts +13 -0
- package/dist/blocks/builtins/NewsletterRender.js +92 -0
- package/dist/blocks/builtins/NewsletterRender.js.map +1 -0
- package/dist/blocks/builtins/OpeningHours.d.ts +1 -2
- package/dist/blocks/builtins/OpeningHours.js +2 -28
- package/dist/blocks/builtins/OpeningHours.js.map +1 -1
- package/dist/blocks/builtins/OpeningHoursRender.d.ts +7 -0
- package/dist/blocks/builtins/OpeningHoursRender.js +31 -0
- package/dist/blocks/builtins/OpeningHoursRender.js.map +1 -0
- package/dist/blocks/builtins/PdfBlock.d.ts +1 -2
- package/dist/blocks/builtins/PdfBlock.js +2 -76
- package/dist/blocks/builtins/PdfBlock.js.map +1 -1
- package/dist/blocks/builtins/PdfBlockRender.d.ts +11 -0
- package/dist/blocks/builtins/PdfBlockRender.js +79 -0
- package/dist/blocks/builtins/PdfBlockRender.js.map +1 -0
- package/dist/blocks/builtins/Portfolio.d.ts +1 -2
- package/dist/blocks/builtins/Portfolio.js +2 -75
- package/dist/blocks/builtins/Portfolio.js.map +1 -1
- package/dist/blocks/builtins/PortfolioRender.d.ts +7 -0
- package/dist/blocks/builtins/PortfolioRender.js +78 -0
- package/dist/blocks/builtins/PortfolioRender.js.map +1 -0
- package/dist/blocks/builtins/Pricing.d.ts +1 -8
- package/dist/blocks/builtins/Pricing.js +3 -73
- package/dist/blocks/builtins/Pricing.js.map +1 -1
- package/dist/blocks/builtins/PricingRender.d.ts +10 -0
- package/dist/blocks/builtins/PricingRender.js +75 -0
- package/dist/blocks/builtins/PricingRender.js.map +1 -0
- package/dist/blocks/builtins/RichTextBlock.d.ts +1 -2
- package/dist/blocks/builtins/RichTextBlock.js +2 -5
- package/dist/blocks/builtins/RichTextBlock.js.map +1 -1
- package/dist/blocks/builtins/RichTextBlockRender.d.ts +6 -0
- package/dist/blocks/builtins/RichTextBlockRender.js +8 -0
- package/dist/blocks/builtins/RichTextBlockRender.js.map +1 -0
- package/dist/blocks/builtins/Search.d.ts +1 -2
- package/dist/blocks/builtins/Search.js +2 -80
- package/dist/blocks/builtins/Search.js.map +1 -1
- package/dist/blocks/builtins/SearchRender.d.ts +7 -0
- package/dist/blocks/builtins/SearchRender.js +83 -0
- package/dist/blocks/builtins/SearchRender.js.map +1 -0
- package/dist/blocks/builtins/Sections.d.ts +4 -5
- package/dist/blocks/builtins/Sections.js +5 -142
- package/dist/blocks/builtins/Sections.js.map +1 -1
- package/dist/blocks/builtins/SectionsRender.d.ts +12 -0
- package/dist/blocks/builtins/SectionsRender.js +145 -0
- package/dist/blocks/builtins/SectionsRender.js.map +1 -0
- package/dist/blocks/builtins/Slider.d.ts +1 -2
- package/dist/blocks/builtins/Slider.js +2 -134
- package/dist/blocks/builtins/Slider.js.map +1 -1
- package/dist/blocks/builtins/SliderRender.d.ts +7 -0
- package/dist/blocks/builtins/SliderRender.js +137 -0
- package/dist/blocks/builtins/SliderRender.js.map +1 -0
- package/dist/blocks/builtins/Spacer.d.ts +1 -2
- package/dist/blocks/builtins/Spacer.js +2 -6
- package/dist/blocks/builtins/Spacer.js.map +1 -1
- package/dist/blocks/builtins/SpacerRender.d.ts +6 -0
- package/dist/blocks/builtins/SpacerRender.js +9 -0
- package/dist/blocks/builtins/SpacerRender.js.map +1 -0
- package/dist/blocks/builtins/SymbolRef.d.ts +1 -2
- package/dist/blocks/builtins/SymbolRef.js +2 -76
- package/dist/blocks/builtins/SymbolRef.js.map +1 -1
- package/dist/blocks/builtins/SymbolRefRender.d.ts +13 -0
- package/dist/blocks/builtins/SymbolRefRender.js +79 -0
- package/dist/blocks/builtins/SymbolRefRender.js.map +1 -0
- package/dist/blocks/builtins/Team.d.ts +1 -2
- package/dist/blocks/builtins/Team.js +2 -55
- package/dist/blocks/builtins/Team.js.map +1 -1
- package/dist/blocks/builtins/TeamRender.d.ts +7 -0
- package/dist/blocks/builtins/TeamRender.js +58 -0
- package/dist/blocks/builtins/TeamRender.js.map +1 -0
- package/dist/blocks/builtins/Testimonials.d.ts +1 -8
- package/dist/blocks/builtins/Testimonials.js +2 -69
- package/dist/blocks/builtins/Testimonials.js.map +1 -1
- package/dist/blocks/builtins/TestimonialsRender.d.ts +10 -0
- package/dist/blocks/builtins/TestimonialsRender.js +72 -0
- package/dist/blocks/builtins/TestimonialsRender.js.map +1 -0
- package/dist/blocks/builtins/Video.d.ts +1 -9
- package/dist/blocks/builtins/Video.js +2 -64
- package/dist/blocks/builtins/Video.js.map +1 -1
- package/dist/blocks/builtins/VideoRender.d.ts +10 -0
- package/dist/blocks/builtins/VideoRender.js +67 -0
- package/dist/blocks/builtins/VideoRender.js.map +1 -0
- package/dist/blocks/builtins/WhatsappChat.d.ts +1 -8
- package/dist/blocks/builtins/WhatsappChat.js +2 -37
- package/dist/blocks/builtins/WhatsappChat.js.map +1 -1
- package/dist/blocks/builtins/WhatsappChatRender.d.ts +17 -0
- package/dist/blocks/builtins/WhatsappChatRender.js +40 -0
- package/dist/blocks/builtins/WhatsappChatRender.js.map +1 -0
- package/dist/blocks/builtins/Widgets.d.ts +12 -13
- package/dist/blocks/builtins/Widgets.js +13 -175
- package/dist/blocks/builtins/Widgets.js.map +1 -1
- package/dist/blocks/builtins/WidgetsRender.d.ts +34 -0
- package/dist/blocks/builtins/WidgetsRender.js +178 -0
- package/dist/blocks/builtins/WidgetsRender.js.map +1 -0
- package/dist/blocks/reportRenderFout.d.ts +13 -0
- package/dist/blocks/reportRenderFout.js +31 -0
- package/dist/blocks/reportRenderFout.js.map +1 -0
- package/dist/modules/contract.js +2 -1
- package/dist/modules/contract.js.map +1 -1
- package/dist/modules/shop/blocks/Cart.js +1 -2
- package/dist/modules/shop/blocks/Cart.js.map +1 -1
- package/dist/modules/shop/blocks/Checkout.js +1 -2
- package/dist/modules/shop/blocks/Checkout.js.map +1 -1
- package/dist/modules/shop/blocks/Donation.js +1 -2
- package/dist/modules/shop/blocks/Donation.js.map +1 -1
- package/dist/modules/shop/blocks/OrderStatus.js +0 -2
- package/dist/modules/shop/blocks/OrderStatus.js.map +1 -1
- package/dist/modules/shop/blocks/ProductDetail.js +1 -7
- package/dist/modules/shop/blocks/ProductDetail.js.map +1 -1
- package/dist/modules/shop/blocks/ProductGrid.js +1 -2
- package/dist/modules/shop/blocks/ProductGrid.js.map +1 -1
- package/dist/modules/shop/blocks/ShopCategories.js +0 -2
- package/dist/modules/shop/blocks/ShopCategories.js.map +1 -1
- package/dist/modules/shop/module.js +1 -0
- package/dist/modules/shop/module.js.map +1 -1
- package/dist/modules/shop/schemas.d.ts +1 -0
- package/dist/modules/shop/schemas.js +32 -0
- package/dist/modules/shop/schemas.js.map +1 -0
- package/dist/modules/types.d.ts +6 -0
- package/dist/schema/shop.d.ts +1 -11
- package/dist/schema/shop.js +1 -20
- package/dist/schema/shop.js.map +1 -1
- package/dist/schema/shopGeld.d.ts +18 -0
- package/dist/schema/shopGeld.js +27 -0
- package/dist/schema/shopGeld.js.map +1 -0
- package/dist/styles.css +17 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -1,140 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect, useRef, useState } from "react";
|
|
1
|
+
import dynamic from "next/dynamic";
|
|
4
2
|
import { defineBlock } from "../registry.js";
|
|
5
|
-
import { Img } from "../../media/ImageContext.js";
|
|
6
|
-
function prefersReducedMotion() {
|
|
7
|
-
return typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
8
|
-
}
|
|
9
|
-
function SliderRender({ block, mode }) {
|
|
10
|
-
const slides = (block.slides ?? []).map((s, i) => ({ ...s, _i: i })).filter((s) => s.imageUrl || s.caption);
|
|
11
|
-
const [index, setIndex] = useState(0);
|
|
12
|
-
const [paused, setPaused] = useState(false);
|
|
13
|
-
const [userPaused, setUserPaused] = useState(false);
|
|
14
|
-
const swipeStart = useRef(null);
|
|
15
|
-
const count = slides.length;
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
setIndex((i) => count === 0 ? 0 : Math.min(i, count - 1));
|
|
18
|
-
}, [count]);
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
if (!block.autoplay || paused || userPaused || count <= 1 || prefersReducedMotion()) return;
|
|
21
|
-
const id = setInterval(() => setIndex((i) => (i + 1) % count), block.interval * 1e3);
|
|
22
|
-
return () => clearInterval(id);
|
|
23
|
-
}, [block.autoplay, block.interval, paused, userPaused, count]);
|
|
24
|
-
if (count === 0) {
|
|
25
|
-
if (mode === "preview") {
|
|
26
|
-
return /* @__PURE__ */ jsx("div", { className: "xicms-slider xicms-slider--empty", children: "\u{1F3A0} Carrousel \u2014 voeg in het zijpaneel slides met een afbeelding of tekst toe." });
|
|
27
|
-
}
|
|
28
|
-
return null;
|
|
29
|
-
}
|
|
30
|
-
const go = (i) => setIndex((i % count + count) % count);
|
|
31
|
-
const onPointerDown = (e) => {
|
|
32
|
-
swipeStart.current = e.clientX;
|
|
33
|
-
};
|
|
34
|
-
const onPointerUp = (e) => {
|
|
35
|
-
if (swipeStart.current === null || count < 2) return;
|
|
36
|
-
const dx = e.clientX - swipeStart.current;
|
|
37
|
-
swipeStart.current = null;
|
|
38
|
-
if (dx > 40) go(index - 1);
|
|
39
|
-
else if (dx < -40) go(index + 1);
|
|
40
|
-
};
|
|
41
|
-
const onKeyDown = (e) => {
|
|
42
|
-
if (e.key === "ArrowLeft") {
|
|
43
|
-
e.preventDefault();
|
|
44
|
-
go(index - 1);
|
|
45
|
-
} else if (e.key === "ArrowRight") {
|
|
46
|
-
e.preventDefault();
|
|
47
|
-
go(index + 1);
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
return /* @__PURE__ */ jsxs(
|
|
51
|
-
"section",
|
|
52
|
-
{
|
|
53
|
-
className: "xicms-slider",
|
|
54
|
-
style: { ["--xicms-slider-ratio"]: block.aspectRatio.replace("/", " / ") },
|
|
55
|
-
onMouseEnter: () => setPaused(true),
|
|
56
|
-
onMouseLeave: () => setPaused(false),
|
|
57
|
-
onFocus: () => setPaused(true),
|
|
58
|
-
onBlur: () => setPaused(false),
|
|
59
|
-
onKeyDown,
|
|
60
|
-
tabIndex: 0,
|
|
61
|
-
role: "region",
|
|
62
|
-
"aria-roledescription": "carousel",
|
|
63
|
-
"aria-label": "Carrousel",
|
|
64
|
-
children: [
|
|
65
|
-
/* @__PURE__ */ jsxs(
|
|
66
|
-
"div",
|
|
67
|
-
{
|
|
68
|
-
className: "xicms-slider__viewport",
|
|
69
|
-
onPointerDown,
|
|
70
|
-
onPointerUp,
|
|
71
|
-
onPointerCancel: () => {
|
|
72
|
-
swipeStart.current = null;
|
|
73
|
-
},
|
|
74
|
-
onPointerLeave: () => {
|
|
75
|
-
swipeStart.current = null;
|
|
76
|
-
},
|
|
77
|
-
style: { touchAction: "pan-y" },
|
|
78
|
-
children: [
|
|
79
|
-
/* @__PURE__ */ jsx("div", { className: "xicms-slider__track", style: { transform: `translateX(-${index * 100}%)` }, children: slides.map((s, i) => {
|
|
80
|
-
const img = s.imageUrl ? /* @__PURE__ */ jsx(Img, { className: "xicms-slider__image", src: s.imageUrl, alt: s.alt ?? "", width: 1800, height: 800, sizes: "100vw", priority: i === 0 }) : null;
|
|
81
|
-
return (
|
|
82
|
-
/* inert haalt links in verborgen slides ook uit de tabvolgorde — aria-hidden
|
|
83
|
-
mét bereikbare focusables is een WCAG-schending (4.1.2). */
|
|
84
|
-
/* @__PURE__ */ jsxs(
|
|
85
|
-
"div",
|
|
86
|
-
{
|
|
87
|
-
className: "xicms-slider__slide",
|
|
88
|
-
role: "group",
|
|
89
|
-
"aria-roledescription": "slide",
|
|
90
|
-
"aria-label": `${i + 1} / ${count}`,
|
|
91
|
-
"aria-hidden": i !== index,
|
|
92
|
-
inert: i !== index || void 0,
|
|
93
|
-
children: [
|
|
94
|
-
s.href ? /* @__PURE__ */ jsx("a", { href: s.href, children: img }) : img,
|
|
95
|
-
s.caption && /* @__PURE__ */ jsx("div", { className: "xicms-slider__caption", "data-xicms-edit": `slides.${s._i}.caption`, children: s.caption })
|
|
96
|
-
]
|
|
97
|
-
},
|
|
98
|
-
i
|
|
99
|
-
)
|
|
100
|
-
);
|
|
101
|
-
}) }),
|
|
102
|
-
block.showArrows && count > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
103
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "xicms-slider__arrow xicms-slider__arrow--prev", "aria-label": "Vorige", onClick: () => go(index - 1), children: "\u2039" }),
|
|
104
|
-
/* @__PURE__ */ jsx("button", { type: "button", className: "xicms-slider__arrow xicms-slider__arrow--next", "aria-label": "Volgende", onClick: () => go(index + 1), children: "\u203A" })
|
|
105
|
-
] }),
|
|
106
|
-
block.autoplay && count > 1 && /* @__PURE__ */ jsx(
|
|
107
|
-
"button",
|
|
108
|
-
{
|
|
109
|
-
type: "button",
|
|
110
|
-
className: "xicms-slider__pause",
|
|
111
|
-
"aria-pressed": userPaused,
|
|
112
|
-
"aria-label": userPaused ? "Diavoorstelling afspelen" : "Diavoorstelling pauzeren",
|
|
113
|
-
onClick: () => setUserPaused((v) => !v),
|
|
114
|
-
children: userPaused ? "\u25B6" : "\u23F8"
|
|
115
|
-
}
|
|
116
|
-
)
|
|
117
|
-
]
|
|
118
|
-
}
|
|
119
|
-
),
|
|
120
|
-
block.showDots && count > 1 && /* @__PURE__ */ jsx("div", { className: "xicms-slider__dots", role: "group", "aria-label": "Kies slide", children: slides.map((_, i) => /* @__PURE__ */ jsx(
|
|
121
|
-
"button",
|
|
122
|
-
{
|
|
123
|
-
type: "button",
|
|
124
|
-
"aria-current": i === index || void 0,
|
|
125
|
-
"aria-label": `Naar slide ${i + 1}`,
|
|
126
|
-
className: `xicms-slider__dot${i === index ? " xicms-slider__dot--active" : ""}`,
|
|
127
|
-
onClick: () => go(i)
|
|
128
|
-
},
|
|
129
|
-
i
|
|
130
|
-
)) })
|
|
131
|
-
]
|
|
132
|
-
}
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
3
|
const sliderBlock = defineBlock({
|
|
136
4
|
type: "slider",
|
|
137
|
-
Render: SliderRender,
|
|
5
|
+
Render: dynamic(() => import("./SliderRender.js").then((m) => m.SliderRender)),
|
|
138
6
|
label: "Carrousel / slider",
|
|
139
7
|
icon: "\u{1F3A0}",
|
|
140
8
|
defaults: () => ({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/blocks/builtins/Slider.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport type { z } from \"zod\";\nimport type { SliderBlockSchema } from \"../../schema/blocks\";\nimport { defineBlock, type BlockRenderProps } from \"../registry\";\nimport { Img } from \"../../media/ImageContext\";\n\ntype Slider = z.infer<typeof SliderBlockSchema>;\n\nfunction prefersReducedMotion(): boolean {\n return typeof window !== \"undefined\" && window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\n/** Beeld-/contentcarrousel. Client-side; autoplay respecteert reduced-motion en pauzeert bij hover. */\nfunction SliderRender({ block, mode }: BlockRenderProps<Slider>) {\n // `_i` = ORIGINELE index (slides gefilterd): inline caption-edits schrijven naar het juiste item.\n const slides = (block.slides ?? []).map((s, i) => ({ ...s, _i: i })).filter((s) => s.imageUrl || s.caption);\n const [index, setIndex] = useState(0);\n const [paused, setPaused] = useState(false);\n // Expliciete stopknop voor autoplay: hover-/focus-pauze helpt touch- en screenreadergebruikers\n // niet, dus WCAG (2.2.2, bewegende content) vraagt een echte pauzeknop.\n const [userPaused, setUserPaused] = useState(false);\n const swipeStart = useRef<number | null>(null);\n const count = slides.length;\n\n // Clamp de index als het aantal slides krimpt (bv. tijdens bewerken in preview), anders blijft\n // de carrousel op een lege positie hangen tot de bezoeker interacteert.\n useEffect(() => {\n setIndex((i) => (count === 0 ? 0 : Math.min(i, count - 1)));\n }, [count]);\n\n useEffect(() => {\n if (!block.autoplay || paused || userPaused || count <= 1 || prefersReducedMotion()) return;\n const id = setInterval(() => setIndex((i) => (i + 1) % count), block.interval * 1000);\n return () => clearInterval(id);\n }, [block.autoplay, block.interval, paused, userPaused, count]);\n\n if (count === 0) {\n // In de editor was een verse slider ONZICHTBAAR (default-slide is leeg → weggefilterd → null):\n // de klant zag \"er gebeurt niets\" na toevoegen. Toon in preview een duidelijke lege staat;\n // publiek blijft het blok gewoon verborgen.\n if (mode === \"preview\") {\n return (\n <div className=\"xicms-slider xicms-slider--empty\">\n 🎠 Carrousel — voeg in het zijpaneel slides met een afbeelding of tekst toe.\n </div>\n );\n }\n return null;\n }\n const go = (i: number) => setIndex(((i % count) + count) % count);\n\n // Swipe (pointer events: touch én muis-sleep) + pijltjestoetsen wanneer de carrousel focus heeft.\n const onPointerDown = (e: React.PointerEvent) => {\n swipeStart.current = e.clientX;\n };\n const onPointerUp = (e: React.PointerEvent) => {\n if (swipeStart.current === null || count < 2) return;\n const dx = e.clientX - swipeStart.current;\n swipeStart.current = null;\n if (dx > 40) go(index - 1);\n else if (dx < -40) go(index + 1);\n };\n const onKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"ArrowLeft\") {\n e.preventDefault();\n go(index - 1);\n } else if (e.key === \"ArrowRight\") {\n e.preventDefault();\n go(index + 1);\n }\n };\n\n return (\n <section\n className=\"xicms-slider\"\n style={{ [\"--xicms-slider-ratio\" as string]: block.aspectRatio.replace(\"/\", \" / \") }}\n onMouseEnter={() => setPaused(true)}\n onMouseLeave={() => setPaused(false)}\n onFocus={() => setPaused(true)}\n onBlur={() => setPaused(false)}\n onKeyDown={onKeyDown}\n tabIndex={0}\n role=\"region\"\n aria-roledescription=\"carousel\"\n aria-label=\"Carrousel\"\n >\n <div\n className=\"xicms-slider__viewport\"\n onPointerDown={onPointerDown}\n onPointerUp={onPointerUp}\n onPointerCancel={() => { swipeStart.current = null; }}\n onPointerLeave={() => { swipeStart.current = null; }}\n style={{ touchAction: \"pan-y\" }}\n >\n <div className=\"xicms-slider__track\" style={{ transform: `translateX(-${index * 100}%)` }}>\n {slides.map((s, i) => {\n const img = s.imageUrl ? (\n <Img className=\"xicms-slider__image\" src={s.imageUrl} alt={s.alt ?? \"\"} width={1800} height={800} sizes=\"100vw\" priority={i === 0} />\n ) : null;\n return (\n /* inert haalt links in verborgen slides ook uit de tabvolgorde — aria-hidden\n mét bereikbare focusables is een WCAG-schending (4.1.2). */\n <div\n key={i}\n className=\"xicms-slider__slide\"\n role=\"group\"\n aria-roledescription=\"slide\"\n aria-label={`${i + 1} / ${count}`}\n aria-hidden={i !== index}\n inert={i !== index || undefined}\n >\n {s.href ? <a href={s.href}>{img}</a> : img}\n {s.caption && <div className=\"xicms-slider__caption\" data-xicms-edit={`slides.${s._i}.caption`}>{s.caption}</div>}\n </div>\n );\n })}\n </div>\n\n {block.showArrows && count > 1 && (\n <>\n <button type=\"button\" className=\"xicms-slider__arrow xicms-slider__arrow--prev\" aria-label=\"Vorige\" onClick={() => go(index - 1)}>‹</button>\n <button type=\"button\" className=\"xicms-slider__arrow xicms-slider__arrow--next\" aria-label=\"Volgende\" onClick={() => go(index + 1)}>›</button>\n </>\n )}\n {/* Geen reduced-motion-check hier: die zou server en client verschillend laten renderen. */}\n {block.autoplay && count > 1 && (\n <button\n type=\"button\"\n className=\"xicms-slider__pause\"\n aria-pressed={userPaused}\n aria-label={userPaused ? \"Diavoorstelling afspelen\" : \"Diavoorstelling pauzeren\"}\n onClick={() => setUserPaused((v) => !v)}\n >\n {userPaused ? \"▶\" : \"⏸\"}\n </button>\n )}\n </div>\n\n {/* Dots als gewone knoppen (geen tablist: er zijn geen tabpanels om aan te koppelen). */}\n {block.showDots && count > 1 && (\n <div className=\"xicms-slider__dots\" role=\"group\" aria-label=\"Kies slide\">\n {slides.map((_, i) => (\n <button\n key={i}\n type=\"button\"\n aria-current={i === index || undefined}\n aria-label={`Naar slide ${i + 1}`}\n className={`xicms-slider__dot${i === index ? \" xicms-slider__dot--active\" : \"\"}`}\n onClick={() => go(i)}\n />\n ))}\n </div>\n )}\n </section>\n );\n}\n\nexport const sliderBlock = defineBlock({\n type: \"slider\",\n Render: SliderRender,\n label: \"Carrousel / slider\",\n icon: \"🎠\",\n defaults: () => ({\n slides: [{ imageUrl: \"\", alt: \"\", caption: \"\" }],\n autoplay: false,\n interval: 5,\n showDots: true,\n showArrows: true,\n aspectRatio: \"16/9\",\n }),\n});\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/Slider.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const sliderBlock = defineBlock({\n type: \"slider\",\n Render: dynamic(() => import(\"./SliderRender\").then((m) => m.SliderRender)),\n label: \"Carrousel / slider\",\n icon: \"🎠\",\n defaults: () => ({\n slides: [{ imageUrl: \"\", alt: \"\", caption: \"\" }],\n autoplay: false,\n interval: 5,\n showDots: true,\n showArrows: true,\n aspectRatio: \"16/9\",\n }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,cAAc,YAAY;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,gBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC;AAAA,EAC1E,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO;AAAA,IACf,QAAQ,CAAC,EAAE,UAAU,IAAI,KAAK,IAAI,SAAS,GAAG,CAAC;AAAA,IAC/C,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,aAAa;AAAA,EACf;AACF,CAAC;","names":[]}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { SliderBlockSchema } from "../../schema/blocks.js";
|
|
3
|
+
import type { BlockRenderProps } from "../registry.js";
|
|
4
|
+
type Slider = z.infer<typeof SliderBlockSchema>;
|
|
5
|
+
/** Beeld-/contentcarrousel. Client-side; autoplay respecteert reduced-motion en pauzeert bij hover. */
|
|
6
|
+
export declare function SliderRender({ block, mode }: BlockRenderProps<Slider>): import("react").JSX.Element | null;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useRef, useState } from "react";
|
|
4
|
+
import { Img } from "../../media/ImageContext.js";
|
|
5
|
+
function prefersReducedMotion() {
|
|
6
|
+
return typeof window !== "undefined" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
7
|
+
}
|
|
8
|
+
function SliderRender({ block, mode }) {
|
|
9
|
+
const slides = (block.slides ?? []).map((s, i) => ({ ...s, _i: i })).filter((s) => s.imageUrl || s.caption);
|
|
10
|
+
const [index, setIndex] = useState(0);
|
|
11
|
+
const [paused, setPaused] = useState(false);
|
|
12
|
+
const [userPaused, setUserPaused] = useState(false);
|
|
13
|
+
const swipeStart = useRef(null);
|
|
14
|
+
const count = slides.length;
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
setIndex((i) => count === 0 ? 0 : Math.min(i, count - 1));
|
|
17
|
+
}, [count]);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (!block.autoplay || paused || userPaused || count <= 1 || prefersReducedMotion()) return;
|
|
20
|
+
const id = setInterval(() => setIndex((i) => (i + 1) % count), block.interval * 1e3);
|
|
21
|
+
return () => clearInterval(id);
|
|
22
|
+
}, [block.autoplay, block.interval, paused, userPaused, count]);
|
|
23
|
+
if (count === 0) {
|
|
24
|
+
if (mode === "preview") {
|
|
25
|
+
return /* @__PURE__ */ jsx("div", { className: "xicms-slider xicms-slider--empty", children: "\u{1F3A0} Carrousel \u2014 voeg in het zijpaneel slides met een afbeelding of tekst toe." });
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const go = (i) => setIndex((i % count + count) % count);
|
|
30
|
+
const onPointerDown = (e) => {
|
|
31
|
+
swipeStart.current = e.clientX;
|
|
32
|
+
};
|
|
33
|
+
const onPointerUp = (e) => {
|
|
34
|
+
if (swipeStart.current === null || count < 2) return;
|
|
35
|
+
const dx = e.clientX - swipeStart.current;
|
|
36
|
+
swipeStart.current = null;
|
|
37
|
+
if (dx > 40) go(index - 1);
|
|
38
|
+
else if (dx < -40) go(index + 1);
|
|
39
|
+
};
|
|
40
|
+
const onKeyDown = (e) => {
|
|
41
|
+
if (e.key === "ArrowLeft") {
|
|
42
|
+
e.preventDefault();
|
|
43
|
+
go(index - 1);
|
|
44
|
+
} else if (e.key === "ArrowRight") {
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
go(index + 1);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
return /* @__PURE__ */ jsxs(
|
|
50
|
+
"section",
|
|
51
|
+
{
|
|
52
|
+
className: "xicms-slider",
|
|
53
|
+
style: { ["--xicms-slider-ratio"]: block.aspectRatio.replace("/", " / ") },
|
|
54
|
+
onMouseEnter: () => setPaused(true),
|
|
55
|
+
onMouseLeave: () => setPaused(false),
|
|
56
|
+
onFocus: () => setPaused(true),
|
|
57
|
+
onBlur: () => setPaused(false),
|
|
58
|
+
onKeyDown,
|
|
59
|
+
tabIndex: 0,
|
|
60
|
+
role: "region",
|
|
61
|
+
"aria-roledescription": "carousel",
|
|
62
|
+
"aria-label": "Carrousel",
|
|
63
|
+
children: [
|
|
64
|
+
/* @__PURE__ */ jsxs(
|
|
65
|
+
"div",
|
|
66
|
+
{
|
|
67
|
+
className: "xicms-slider__viewport",
|
|
68
|
+
onPointerDown,
|
|
69
|
+
onPointerUp,
|
|
70
|
+
onPointerCancel: () => {
|
|
71
|
+
swipeStart.current = null;
|
|
72
|
+
},
|
|
73
|
+
onPointerLeave: () => {
|
|
74
|
+
swipeStart.current = null;
|
|
75
|
+
},
|
|
76
|
+
style: { touchAction: "pan-y" },
|
|
77
|
+
children: [
|
|
78
|
+
/* @__PURE__ */ jsx("div", { className: "xicms-slider__track", style: { transform: `translateX(-${index * 100}%)` }, children: slides.map((s, i) => {
|
|
79
|
+
const img = s.imageUrl ? /* @__PURE__ */ jsx(Img, { className: "xicms-slider__image", src: s.imageUrl, alt: s.alt ?? "", width: 1800, height: 800, sizes: "100vw", priority: i === 0 }) : null;
|
|
80
|
+
return (
|
|
81
|
+
/* inert haalt links in verborgen slides ook uit de tabvolgorde — aria-hidden
|
|
82
|
+
mét bereikbare focusables is een WCAG-schending (4.1.2). */
|
|
83
|
+
/* @__PURE__ */ jsxs(
|
|
84
|
+
"div",
|
|
85
|
+
{
|
|
86
|
+
className: "xicms-slider__slide",
|
|
87
|
+
role: "group",
|
|
88
|
+
"aria-roledescription": "slide",
|
|
89
|
+
"aria-label": `${i + 1} / ${count}`,
|
|
90
|
+
"aria-hidden": i !== index,
|
|
91
|
+
inert: i !== index || void 0,
|
|
92
|
+
children: [
|
|
93
|
+
s.href ? /* @__PURE__ */ jsx("a", { href: s.href, children: img }) : img,
|
|
94
|
+
s.caption && /* @__PURE__ */ jsx("div", { className: "xicms-slider__caption", "data-xicms-edit": `slides.${s._i}.caption`, children: s.caption })
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
i
|
|
98
|
+
)
|
|
99
|
+
);
|
|
100
|
+
}) }),
|
|
101
|
+
block.showArrows && count > 1 && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
102
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "xicms-slider__arrow xicms-slider__arrow--prev", "aria-label": "Vorige", onClick: () => go(index - 1), children: "\u2039" }),
|
|
103
|
+
/* @__PURE__ */ jsx("button", { type: "button", className: "xicms-slider__arrow xicms-slider__arrow--next", "aria-label": "Volgende", onClick: () => go(index + 1), children: "\u203A" })
|
|
104
|
+
] }),
|
|
105
|
+
block.autoplay && count > 1 && /* @__PURE__ */ jsx(
|
|
106
|
+
"button",
|
|
107
|
+
{
|
|
108
|
+
type: "button",
|
|
109
|
+
className: "xicms-slider__pause",
|
|
110
|
+
"aria-pressed": userPaused,
|
|
111
|
+
"aria-label": userPaused ? "Diavoorstelling afspelen" : "Diavoorstelling pauzeren",
|
|
112
|
+
onClick: () => setUserPaused((v) => !v),
|
|
113
|
+
children: userPaused ? "\u25B6" : "\u23F8"
|
|
114
|
+
}
|
|
115
|
+
)
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
),
|
|
119
|
+
block.showDots && count > 1 && /* @__PURE__ */ jsx("div", { className: "xicms-slider__dots", role: "group", "aria-label": "Kies slide", children: slides.map((_, i) => /* @__PURE__ */ jsx(
|
|
120
|
+
"button",
|
|
121
|
+
{
|
|
122
|
+
type: "button",
|
|
123
|
+
"aria-current": i === index || void 0,
|
|
124
|
+
"aria-label": `Naar slide ${i + 1}`,
|
|
125
|
+
className: `xicms-slider__dot${i === index ? " xicms-slider__dot--active" : ""}`,
|
|
126
|
+
onClick: () => go(i)
|
|
127
|
+
},
|
|
128
|
+
i
|
|
129
|
+
)) })
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
export {
|
|
135
|
+
SliderRender
|
|
136
|
+
};
|
|
137
|
+
//# sourceMappingURL=SliderRender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/SliderRender.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport type { z } from \"zod\";\nimport type { SliderBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { Img } from \"../../media/ImageContext\";\n\ntype Slider = z.infer<typeof SliderBlockSchema>;\n\nfunction prefersReducedMotion(): boolean {\n return typeof window !== \"undefined\" && window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\n/** Beeld-/contentcarrousel. Client-side; autoplay respecteert reduced-motion en pauzeert bij hover. */\nexport function SliderRender({ block, mode }: BlockRenderProps<Slider>) {\n // `_i` = ORIGINELE index (slides gefilterd): inline caption-edits schrijven naar het juiste item.\n const slides = (block.slides ?? []).map((s, i) => ({ ...s, _i: i })).filter((s) => s.imageUrl || s.caption);\n const [index, setIndex] = useState(0);\n const [paused, setPaused] = useState(false);\n // Expliciete stopknop voor autoplay: hover-/focus-pauze helpt touch- en screenreadergebruikers\n // niet, dus WCAG (2.2.2, bewegende content) vraagt een echte pauzeknop.\n const [userPaused, setUserPaused] = useState(false);\n const swipeStart = useRef<number | null>(null);\n const count = slides.length;\n\n // Clamp de index als het aantal slides krimpt (bv. tijdens bewerken in preview), anders blijft\n // de carrousel op een lege positie hangen tot de bezoeker interacteert.\n useEffect(() => {\n setIndex((i) => (count === 0 ? 0 : Math.min(i, count - 1)));\n }, [count]);\n\n useEffect(() => {\n if (!block.autoplay || paused || userPaused || count <= 1 || prefersReducedMotion()) return;\n const id = setInterval(() => setIndex((i) => (i + 1) % count), block.interval * 1000);\n return () => clearInterval(id);\n }, [block.autoplay, block.interval, paused, userPaused, count]);\n\n if (count === 0) {\n // In de editor was een verse slider ONZICHTBAAR (default-slide is leeg → weggefilterd → null):\n // de klant zag \"er gebeurt niets\" na toevoegen. Toon in preview een duidelijke lege staat;\n // publiek blijft het blok gewoon verborgen.\n if (mode === \"preview\") {\n return (\n <div className=\"xicms-slider xicms-slider--empty\">\n 🎠 Carrousel — voeg in het zijpaneel slides met een afbeelding of tekst toe.\n </div>\n );\n }\n return null;\n }\n const go = (i: number) => setIndex(((i % count) + count) % count);\n\n // Swipe (pointer events: touch én muis-sleep) + pijltjestoetsen wanneer de carrousel focus heeft.\n const onPointerDown = (e: React.PointerEvent) => {\n swipeStart.current = e.clientX;\n };\n const onPointerUp = (e: React.PointerEvent) => {\n if (swipeStart.current === null || count < 2) return;\n const dx = e.clientX - swipeStart.current;\n swipeStart.current = null;\n if (dx > 40) go(index - 1);\n else if (dx < -40) go(index + 1);\n };\n const onKeyDown = (e: React.KeyboardEvent) => {\n if (e.key === \"ArrowLeft\") {\n e.preventDefault();\n go(index - 1);\n } else if (e.key === \"ArrowRight\") {\n e.preventDefault();\n go(index + 1);\n }\n };\n\n return (\n <section\n className=\"xicms-slider\"\n style={{ [\"--xicms-slider-ratio\" as string]: block.aspectRatio.replace(\"/\", \" / \") }}\n onMouseEnter={() => setPaused(true)}\n onMouseLeave={() => setPaused(false)}\n onFocus={() => setPaused(true)}\n onBlur={() => setPaused(false)}\n onKeyDown={onKeyDown}\n tabIndex={0}\n role=\"region\"\n aria-roledescription=\"carousel\"\n aria-label=\"Carrousel\"\n >\n <div\n className=\"xicms-slider__viewport\"\n onPointerDown={onPointerDown}\n onPointerUp={onPointerUp}\n onPointerCancel={() => { swipeStart.current = null; }}\n onPointerLeave={() => { swipeStart.current = null; }}\n style={{ touchAction: \"pan-y\" }}\n >\n <div className=\"xicms-slider__track\" style={{ transform: `translateX(-${index * 100}%)` }}>\n {slides.map((s, i) => {\n const img = s.imageUrl ? (\n <Img className=\"xicms-slider__image\" src={s.imageUrl} alt={s.alt ?? \"\"} width={1800} height={800} sizes=\"100vw\" priority={i === 0} />\n ) : null;\n return (\n /* inert haalt links in verborgen slides ook uit de tabvolgorde — aria-hidden\n mét bereikbare focusables is een WCAG-schending (4.1.2). */\n <div\n key={i}\n className=\"xicms-slider__slide\"\n role=\"group\"\n aria-roledescription=\"slide\"\n aria-label={`${i + 1} / ${count}`}\n aria-hidden={i !== index}\n inert={i !== index || undefined}\n >\n {s.href ? <a href={s.href}>{img}</a> : img}\n {s.caption && <div className=\"xicms-slider__caption\" data-xicms-edit={`slides.${s._i}.caption`}>{s.caption}</div>}\n </div>\n );\n })}\n </div>\n\n {block.showArrows && count > 1 && (\n <>\n <button type=\"button\" className=\"xicms-slider__arrow xicms-slider__arrow--prev\" aria-label=\"Vorige\" onClick={() => go(index - 1)}>‹</button>\n <button type=\"button\" className=\"xicms-slider__arrow xicms-slider__arrow--next\" aria-label=\"Volgende\" onClick={() => go(index + 1)}>›</button>\n </>\n )}\n {/* Geen reduced-motion-check hier: die zou server en client verschillend laten renderen. */}\n {block.autoplay && count > 1 && (\n <button\n type=\"button\"\n className=\"xicms-slider__pause\"\n aria-pressed={userPaused}\n aria-label={userPaused ? \"Diavoorstelling afspelen\" : \"Diavoorstelling pauzeren\"}\n onClick={() => setUserPaused((v) => !v)}\n >\n {userPaused ? \"▶\" : \"⏸\"}\n </button>\n )}\n </div>\n\n {/* Dots als gewone knoppen (geen tablist: er zijn geen tabpanels om aan te koppelen). */}\n {block.showDots && count > 1 && (\n <div className=\"xicms-slider__dots\" role=\"group\" aria-label=\"Kies slide\">\n {slides.map((_, i) => (\n <button\n key={i}\n type=\"button\"\n aria-current={i === index || undefined}\n aria-label={`Naar slide ${i + 1}`}\n className={`xicms-slider__dot${i === index ? \" xicms-slider__dot--active\" : \"\"}`}\n onClick={() => go(i)}\n />\n ))}\n </div>\n )}\n </section>\n );\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const spacerBlock: import("../index.js").BlockDefinition<z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
1
|
+
export declare const spacerBlock: import("../index.js").BlockDefinition<import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>>;
|
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import dynamic from "next/dynamic";
|
|
2
2
|
import { defineBlock } from "../registry.js";
|
|
3
|
-
const HEIGHTS = { sm: 16, md: 32, lg: 64, xl: 120 };
|
|
4
|
-
function SpacerRender({ block }) {
|
|
5
|
-
return /* @__PURE__ */ jsx("div", { "aria-hidden": true, style: { height: HEIGHTS[block.size] } });
|
|
6
|
-
}
|
|
7
3
|
const spacerBlock = defineBlock({
|
|
8
4
|
type: "spacer",
|
|
9
|
-
Render: SpacerRender,
|
|
5
|
+
Render: dynamic(() => import("./SpacerRender.js").then((m) => m.SpacerRender)),
|
|
10
6
|
label: "Witruimte",
|
|
11
7
|
icon: "\u2195",
|
|
12
8
|
defaults: () => ({ size: "md" })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/blocks/builtins/Spacer.tsx"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/Spacer.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const spacerBlock = defineBlock({\n type: \"spacer\",\n Render: dynamic(() => import(\"./SpacerRender\").then((m) => m.SpacerRender)),\n label: \"Witruimte\",\n icon: \"↕\",\n defaults: () => ({ size: \"md\" }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,cAAc,YAAY;AAAA,EACrC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,gBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE,YAAY,CAAC;AAAA,EAC1E,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,MAAM,KAAK;AAChC,CAAC;","names":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { SpacerBlockSchema } from "../../schema/blocks.js";
|
|
3
|
+
import type { BlockRenderProps } from "../registry.js";
|
|
4
|
+
type Spacer = z.infer<typeof SpacerBlockSchema>;
|
|
5
|
+
export declare function SpacerRender({ block }: BlockRenderProps<Spacer>): import("react").JSX.Element;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
const HEIGHTS = { sm: 16, md: 32, lg: 64, xl: 120 };
|
|
3
|
+
function SpacerRender({ block }) {
|
|
4
|
+
return /* @__PURE__ */ jsx("div", { "aria-hidden": true, style: { height: HEIGHTS[block.size] } });
|
|
5
|
+
}
|
|
6
|
+
export {
|
|
7
|
+
SpacerRender
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=SpacerRender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/SpacerRender.tsx"],"sourcesContent":["import type { z } from \"zod\";\nimport type { SpacerBlockSchema } from \"../../schema/blocks\";\nimport type { BlockRenderProps } from \"../registry\";\n\ntype Spacer = z.infer<typeof SpacerBlockSchema>;\n\nconst HEIGHTS: Record<Spacer[\"size\"], number> = { sm: 16, md: 32, lg: 64, xl: 120 };\n\nexport function SpacerRender({ block }: BlockRenderProps<Spacer>) {\n return <div aria-hidden style={{ height: HEIGHTS[block.size] }} />;\n}\n"],"mappings":"AASS;AAHT,MAAM,UAA0C,EAAE,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI;AAE3E,SAAS,aAAa,EAAE,MAAM,GAA6B;AAChE,SAAO,oBAAC,SAAI,eAAW,MAAC,OAAO,EAAE,QAAQ,QAAQ,MAAM,IAAI,EAAE,GAAG;AAClE;","names":[]}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const symbolRefBlock: import("../index.js").BlockDefinition<z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
1
|
+
export declare const symbolRefBlock: import("../index.js").BlockDefinition<import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>>;
|
|
@@ -1,82 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect, useState } from "react";
|
|
1
|
+
import dynamic from "next/dynamic";
|
|
4
2
|
import { defineBlock } from "../registry.js";
|
|
5
|
-
import { BlockRenderer } from "../BlockRenderer.js";
|
|
6
|
-
import { useRegistry } from "../context.js";
|
|
7
|
-
import { useEditor } from "../../editor/EditorProvider.js";
|
|
8
|
-
function SymbolRefRender({ block, siteId, mode }) {
|
|
9
|
-
const registry = useRegistry();
|
|
10
|
-
const bewerken = useEditor().open || mode === "preview";
|
|
11
|
-
const [symbol, setSymbol] = useState(void 0);
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
if (!block.symbolId) {
|
|
14
|
-
setSymbol(null);
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
let unsub;
|
|
18
|
-
let afgebroken = false;
|
|
19
|
-
void (async () => {
|
|
20
|
-
const [{ getDb }, { doc, onSnapshot }] = await Promise.all([
|
|
21
|
-
import("../../firebase/client.js"),
|
|
22
|
-
import("firebase/firestore")
|
|
23
|
-
]);
|
|
24
|
-
const db = getDb();
|
|
25
|
-
if (!db || afgebroken) {
|
|
26
|
-
setSymbol(null);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
const ref = doc(db, "sites", siteId, "symbols", block.symbolId);
|
|
30
|
-
const zet = (data, bestaat) => {
|
|
31
|
-
const d = bestaat && data && typeof data === "object" ? data : null;
|
|
32
|
-
const geldig = d && typeof d.name === "string" && Array.isArray(d.blocks);
|
|
33
|
-
setSymbol(geldig ? d : null);
|
|
34
|
-
};
|
|
35
|
-
if (bewerken) {
|
|
36
|
-
unsub = onSnapshot(
|
|
37
|
-
ref,
|
|
38
|
-
(snap) => zet(snap.data(), snap.exists()),
|
|
39
|
-
() => setSymbol(null)
|
|
40
|
-
);
|
|
41
|
-
} else {
|
|
42
|
-
const { getDoc } = await import("firebase/firestore");
|
|
43
|
-
try {
|
|
44
|
-
const snap = await getDoc(ref);
|
|
45
|
-
if (!afgebroken) zet(snap.data(), snap.exists());
|
|
46
|
-
} catch {
|
|
47
|
-
if (!afgebroken) setSymbol(null);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
})();
|
|
51
|
-
return () => {
|
|
52
|
-
afgebroken = true;
|
|
53
|
-
unsub?.();
|
|
54
|
-
};
|
|
55
|
-
}, [siteId, block.symbolId, bewerken]);
|
|
56
|
-
if (symbol === void 0) return null;
|
|
57
|
-
if (symbol === null) {
|
|
58
|
-
return mode === "preview" ? /* @__PURE__ */ jsxs("p", { className: "xicms-ve__hint", children: [
|
|
59
|
-
"\u{1F9E9} Symbool niet gevonden (",
|
|
60
|
-
block.symbolId,
|
|
61
|
-
") \u2014 kies een ander symbool of verwijder dit blok."
|
|
62
|
-
] }) : null;
|
|
63
|
-
}
|
|
64
|
-
const inner = /* @__PURE__ */ jsx(BlockRenderer, { blocks: symbol.blocks, registry, siteId, mode });
|
|
65
|
-
if (mode === "preview") {
|
|
66
|
-
return /* @__PURE__ */ jsxs("div", { className: "xicms-symbol", "data-symbol": block.symbolId, children: [
|
|
67
|
-
/* @__PURE__ */ jsxs("div", { className: "xicms-symbol__badge", children: [
|
|
68
|
-
"\u{1F9E9} ",
|
|
69
|
-
symbol.name,
|
|
70
|
-
" \u2014 gedeeld symbool (wijzigingen gelden op \xE9lke pagina)"
|
|
71
|
-
] }),
|
|
72
|
-
inner
|
|
73
|
-
] });
|
|
74
|
-
}
|
|
75
|
-
return inner;
|
|
76
|
-
}
|
|
77
3
|
const symbolRefBlock = defineBlock({
|
|
78
4
|
type: "symbolRef",
|
|
79
|
-
Render: SymbolRefRender,
|
|
5
|
+
Render: dynamic(() => import("./SymbolRefRender.js").then((m) => m.SymbolRefRender)),
|
|
80
6
|
label: "Symbool (gedeelde sectie)",
|
|
81
7
|
icon: "\u{1F9E9}",
|
|
82
8
|
defaults: () => ({ symbolId: "" })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/blocks/builtins/SymbolRef.tsx"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/SymbolRef.tsx"],"sourcesContent":["import dynamic from \"next/dynamic\";\nimport { defineBlock } from \"../registry\";\n\nexport const symbolRefBlock = defineBlock({\n type: \"symbolRef\",\n Render: dynamic(() => import(\"./SymbolRefRender\").then((m) => m.SymbolRefRender)),\n label: \"Symbool (gedeelde sectie)\",\n icon: \"🧩\",\n defaults: () => ({ symbolId: \"\" }),\n});\n"],"mappings":"AAAA,OAAO,aAAa;AACpB,SAAS,mBAAmB;AAErB,MAAM,iBAAiB,YAAY;AAAA,EACxC,MAAM;AAAA,EACN,QAAQ,QAAQ,MAAM,OAAO,mBAAmB,EAAE,KAAK,CAAC,MAAM,EAAE,eAAe,CAAC;AAAA,EAChF,OAAO;AAAA,EACP,MAAM;AAAA,EACN,UAAU,OAAO,EAAE,UAAU,GAAG;AAClC,CAAC;","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { z } from "zod";
|
|
2
|
+
import type { SymbolRefBlockSchema } from "../../schema/blocks.js";
|
|
3
|
+
import type { BlockRenderProps } from "../registry.js";
|
|
4
|
+
type SymbolRef = z.infer<typeof SymbolRefBlockSchema>;
|
|
5
|
+
/**
|
|
6
|
+
* Verwijzing naar een gedeeld symbool. Op de LIVE site wordt een symbolRef normaliter al
|
|
7
|
+
* server-side vervangen door de symbool-blokken (server/pages.ts `expandSymbols`) — dan komt
|
|
8
|
+
* deze Render niet eens aan bod. In de editor/preview (en als client-fallback) rendert hij het
|
|
9
|
+
* symbool live vanuit Firestore, met een subtiel kader zodat de editor ziet dat dit gedeelde
|
|
10
|
+
* inhoud is die op meerdere pagina's meebeweegt.
|
|
11
|
+
*/
|
|
12
|
+
export declare function SymbolRefRender({ block, siteId, mode }: BlockRenderProps<SymbolRef>): import("react").JSX.Element | null;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
import { BlockRenderer } from "../BlockRenderer.js";
|
|
5
|
+
import { useRegistry } from "../context.js";
|
|
6
|
+
import { useEditor } from "../../editor/EditorProvider.js";
|
|
7
|
+
function SymbolRefRender({ block, siteId, mode }) {
|
|
8
|
+
const registry = useRegistry();
|
|
9
|
+
const bewerken = useEditor().open || mode === "preview";
|
|
10
|
+
const [symbol, setSymbol] = useState(void 0);
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
if (!block.symbolId) {
|
|
13
|
+
setSymbol(null);
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
let unsub;
|
|
17
|
+
let afgebroken = false;
|
|
18
|
+
void (async () => {
|
|
19
|
+
const [{ getDb }, { doc, onSnapshot }] = await Promise.all([
|
|
20
|
+
import("../../firebase/client.js"),
|
|
21
|
+
import("firebase/firestore")
|
|
22
|
+
]);
|
|
23
|
+
const db = getDb();
|
|
24
|
+
if (!db || afgebroken) {
|
|
25
|
+
setSymbol(null);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
const ref = doc(db, "sites", siteId, "symbols", block.symbolId);
|
|
29
|
+
const zet = (data, bestaat) => {
|
|
30
|
+
const d = bestaat && data && typeof data === "object" ? data : null;
|
|
31
|
+
const geldig = d && typeof d.name === "string" && Array.isArray(d.blocks);
|
|
32
|
+
setSymbol(geldig ? d : null);
|
|
33
|
+
};
|
|
34
|
+
if (bewerken) {
|
|
35
|
+
unsub = onSnapshot(
|
|
36
|
+
ref,
|
|
37
|
+
(snap) => zet(snap.data(), snap.exists()),
|
|
38
|
+
() => setSymbol(null)
|
|
39
|
+
);
|
|
40
|
+
} else {
|
|
41
|
+
const { getDoc } = await import("firebase/firestore");
|
|
42
|
+
try {
|
|
43
|
+
const snap = await getDoc(ref);
|
|
44
|
+
if (!afgebroken) zet(snap.data(), snap.exists());
|
|
45
|
+
} catch {
|
|
46
|
+
if (!afgebroken) setSymbol(null);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
})();
|
|
50
|
+
return () => {
|
|
51
|
+
afgebroken = true;
|
|
52
|
+
unsub?.();
|
|
53
|
+
};
|
|
54
|
+
}, [siteId, block.symbolId, bewerken]);
|
|
55
|
+
if (symbol === void 0) return null;
|
|
56
|
+
if (symbol === null) {
|
|
57
|
+
return mode === "preview" ? /* @__PURE__ */ jsxs("p", { className: "xicms-ve__hint", children: [
|
|
58
|
+
"\u{1F9E9} Symbool niet gevonden (",
|
|
59
|
+
block.symbolId,
|
|
60
|
+
") \u2014 kies een ander symbool of verwijder dit blok."
|
|
61
|
+
] }) : null;
|
|
62
|
+
}
|
|
63
|
+
const inner = /* @__PURE__ */ jsx(BlockRenderer, { blocks: symbol.blocks, registry, siteId, mode });
|
|
64
|
+
if (mode === "preview") {
|
|
65
|
+
return /* @__PURE__ */ jsxs("div", { className: "xicms-symbol", "data-symbol": block.symbolId, children: [
|
|
66
|
+
/* @__PURE__ */ jsxs("div", { className: "xicms-symbol__badge", children: [
|
|
67
|
+
"\u{1F9E9} ",
|
|
68
|
+
symbol.name,
|
|
69
|
+
" \u2014 gedeeld symbool (wijzigingen gelden op \xE9lke pagina)"
|
|
70
|
+
] }),
|
|
71
|
+
inner
|
|
72
|
+
] });
|
|
73
|
+
}
|
|
74
|
+
return inner;
|
|
75
|
+
}
|
|
76
|
+
export {
|
|
77
|
+
SymbolRefRender
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=SymbolRefRender.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/blocks/builtins/SymbolRefRender.tsx"],"sourcesContent":["\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { z } from \"zod\";\nimport type { SymbolRefBlockSchema } from \"../../schema/blocks\";\nimport type { SymbolDefinition } from \"../../schema/symbols\";\nimport type { BlockRenderProps } from \"../registry\";\nimport { BlockRenderer } from \"../BlockRenderer\";\nimport { useRegistry } from \"../context\";\nimport { useEditor } from \"../../editor/EditorProvider\";\n\ntype SymbolRef = z.infer<typeof SymbolRefBlockSchema>;\n\n/**\n * Verwijzing naar een gedeeld symbool. Op de LIVE site wordt een symbolRef normaliter al\n * server-side vervangen door de symbool-blokken (server/pages.ts `expandSymbols`) — dan komt\n * deze Render niet eens aan bod. In de editor/preview (en als client-fallback) rendert hij het\n * symbool live vanuit Firestore, met een subtiel kader zodat de editor ziet dat dit gedeelde\n * inhoud is die op meerdere pagina's meebeweegt.\n */\nexport function SymbolRefRender({ block, siteId, mode }: BlockRenderProps<SymbolRef>) {\n const registry = useRegistry();\n // Live meebewegen is alleen nuttig terwijl er BEWERKT wordt. Voor een gewone bezoeker was de\n // onSnapshot hieronder het duurste patroon van het systeem: een read plus een blijvend open\n // verbinding, per bezoeker — voor content die toch pas verandert als iemand publiceert.\n const bewerken = useEditor().open || mode === \"preview\";\n const [symbol, setSymbol] = useState<SymbolDefinition | null | undefined>(undefined);\n useEffect(() => {\n if (!block.symbolId) {\n setSymbol(null);\n return;\n }\n // Firestore dynamisch laden: een pagina zonder symbolen haalt de SDK zo nooit binnen, en een\n // pagina mét symbolen pas op het moment dat er echt iets op te halen valt.\n let unsub: (() => void) | undefined;\n let afgebroken = false;\n void (async () => {\n const [{ getDb }, { doc, onSnapshot }] = await Promise.all([\n import(\"../../firebase/client\"),\n import(\"firebase/firestore\"),\n ]);\n const db = getDb();\n if (!db || afgebroken) {\n setSymbol(null);\n return;\n }\n const ref = doc(db, \"sites\", siteId, \"symbols\", block.symbolId!);\n const zet = (data: unknown, bestaat: boolean) => {\n // Lichte vormcheck i.p.v. zod (7.13): dit is een publiek renderpad en de enige plek die\n // anders het hele symbols-schema (en daarmee de zod-runtime) in de bezoekersbundel trok.\n // De BlockRenderer eronder valideert de blokken zelf al per type.\n const d = bestaat && data && typeof data === \"object\" ? (data as { name?: unknown; blocks?: unknown }) : null;\n const geldig = d && typeof d.name === \"string\" && Array.isArray(d.blocks);\n setSymbol(geldig ? (d as unknown as SymbolDefinition) : null);\n };\n if (bewerken) {\n unsub = onSnapshot(\n ref,\n (snap) => zet(snap.data(), snap.exists()),\n () => setSymbol(null),\n );\n } else {\n // Publieke fallback (zeldzaam: normaal is de ref al server-side geëxpandeerd): één read,\n // geen listener.\n const { getDoc } = await import(\"firebase/firestore\");\n try {\n const snap = await getDoc(ref);\n if (!afgebroken) zet(snap.data(), snap.exists());\n } catch {\n if (!afgebroken) setSymbol(null);\n }\n }\n })();\n return () => {\n afgebroken = true;\n unsub?.();\n };\n }, [siteId, block.symbolId, bewerken]);\n\n if (symbol === undefined) return null; // laden — geen flits\n if (symbol === null) {\n // Verweesde referentie: nooit de pagina breken; in preview uitleggen, live niets tonen.\n return mode === \"preview\" ? (\n <p className=\"xicms-ve__hint\">🧩 Symbool niet gevonden ({block.symbolId}) — kies een ander symbool of verwijder dit blok.</p>\n ) : null;\n }\n const inner = <BlockRenderer blocks={symbol.blocks} registry={registry} siteId={siteId} mode={mode} />;\n if (mode === \"preview\") {\n return (\n <div className=\"xicms-symbol\" data-symbol={block.symbolId}>\n <div className=\"xicms-symbol__badge\">🧩 {symbol.name} — gedeeld symbool (wijzigingen gelden op élke pagina)</div>\n {inner}\n </div>\n );\n }\n return inner;\n}\n"],"mappings":";AAmFM,SAGU,KAHV;AAjFN,SAAS,WAAW,gBAAgB;AAKpC,SAAS,qBAAqB;AAC9B,SAAS,mBAAmB;AAC5B,SAAS,iBAAiB;AAWnB,SAAS,gBAAgB,EAAE,OAAO,QAAQ,KAAK,GAAgC;AACpF,QAAM,WAAW,YAAY;AAI7B,QAAM,WAAW,UAAU,EAAE,QAAQ,SAAS;AAC9C,QAAM,CAAC,QAAQ,SAAS,IAAI,SAA8C,MAAS;AACnF,YAAU,MAAM;AACd,QAAI,CAAC,MAAM,UAAU;AACnB,gBAAU,IAAI;AACd;AAAA,IACF;AAGA,QAAI;AACJ,QAAI,aAAa;AACjB,UAAM,YAAY;AAChB,YAAM,CAAC,EAAE,MAAM,GAAG,EAAE,KAAK,WAAW,CAAC,IAAI,MAAM,QAAQ,IAAI;AAAA,QACzD,OAAO,uBAAuB;AAAA,QAC9B,OAAO,oBAAoB;AAAA,MAC7B,CAAC;AACD,YAAM,KAAK,MAAM;AACjB,UAAI,CAAC,MAAM,YAAY;AACrB,kBAAU,IAAI;AACd;AAAA,MACF;AACA,YAAM,MAAM,IAAI,IAAI,SAAS,QAAQ,WAAW,MAAM,QAAS;AAC/D,YAAM,MAAM,CAAC,MAAe,YAAqB;AAI/C,cAAM,IAAI,WAAW,QAAQ,OAAO,SAAS,WAAY,OAAgD;AACzG,cAAM,SAAS,KAAK,OAAO,EAAE,SAAS,YAAY,MAAM,QAAQ,EAAE,MAAM;AACxE,kBAAU,SAAU,IAAoC,IAAI;AAAA,MAC9D;AACA,UAAI,UAAU;AACZ,gBAAQ;AAAA,UACN;AAAA,UACA,CAAC,SAAS,IAAI,KAAK,KAAK,GAAG,KAAK,OAAO,CAAC;AAAA,UACxC,MAAM,UAAU,IAAI;AAAA,QACtB;AAAA,MACF,OAAO;AAGL,cAAM,EAAE,OAAO,IAAI,MAAM,OAAO,oBAAoB;AACpD,YAAI;AACF,gBAAM,OAAO,MAAM,OAAO,GAAG;AAC7B,cAAI,CAAC,WAAY,KAAI,KAAK,KAAK,GAAG,KAAK,OAAO,CAAC;AAAA,QACjD,QAAQ;AACN,cAAI,CAAC,WAAY,WAAU,IAAI;AAAA,QACjC;AAAA,MACF;AAAA,IACF,GAAG;AACH,WAAO,MAAM;AACX,mBAAa;AACb,cAAQ;AAAA,IACV;AAAA,EACF,GAAG,CAAC,QAAQ,MAAM,UAAU,QAAQ,CAAC;AAErC,MAAI,WAAW,OAAW,QAAO;AACjC,MAAI,WAAW,MAAM;AAEnB,WAAO,SAAS,YACd,qBAAC,OAAE,WAAU,kBAAiB;AAAA;AAAA,MAA2B,MAAM;AAAA,MAAS;AAAA,OAAiD,IACvH;AAAA,EACN;AACA,QAAM,QAAQ,oBAAC,iBAAc,QAAQ,OAAO,QAAQ,UAAoB,QAAgB,MAAY;AACpG,MAAI,SAAS,WAAW;AACtB,WACE,qBAAC,SAAI,WAAU,gBAAe,eAAa,MAAM,UAC/C;AAAA,2BAAC,SAAI,WAAU,uBAAsB;AAAA;AAAA,QAAI,OAAO;AAAA,QAAK;AAAA,SAAsD;AAAA,MAC1G;AAAA,OACH;AAAA,EAEJ;AACA,SAAO;AACT;","names":[]}
|
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const teamBlock: import("../index.js").BlockDefinition<z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>>;
|
|
1
|
+
export declare const teamBlock: import("../index.js").BlockDefinition<import("zod/v4/core").$ZodType<unknown, unknown, import("zod/v4/core").$ZodTypeInternals<unknown, unknown>>>;
|