@riverbankcms/sdk 0.74.0 → 0.75.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.
Files changed (113) hide show
  1. package/dist/{PreviewEditorSidebar-5XL7M3OM.mjs → PreviewEditorSidebar-U2IHCBYN.mjs} +3 -3
  2. package/dist/{PreviewEditorUI-ZDFRDJID.mjs → PreviewEditorUI-ZGH2RQNP.mjs} +3 -3
  3. package/dist/SdkPreviewModeRuntime-MTUGBTLQ.mjs +8 -0
  4. package/dist/_dts/api/src/cache-tags.d.ts +22 -0
  5. package/dist/_dts/api/src/contentRuntime.d.ts +1 -0
  6. package/dist/_dts/api/src/endpoints.d.ts +24 -24
  7. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +2 -1
  8. package/dist/_dts/block-form/src/blockDraftSaveability.d.ts +4 -1
  9. package/dist/_dts/blocks/src/client/booking-form.d.ts +2 -0
  10. package/dist/_dts/blocks/src/client/carousel.d.ts +1 -0
  11. package/dist/_dts/blocks/src/client/course-registration.d.ts +2 -0
  12. package/dist/_dts/blocks/src/client/events.d.ts +4 -0
  13. package/dist/_dts/blocks/src/client/form.d.ts +2 -0
  14. package/dist/_dts/blocks/src/client/header.d.ts +1 -0
  15. package/dist/_dts/blocks/src/client/location-map.d.ts +1 -0
  16. package/dist/_dts/blocks/src/client/newsletter-form.d.ts +2 -0
  17. package/dist/_dts/blocks/src/client/shop.d.ts +6 -0
  18. package/dist/_dts/blocks/src/lib/video.d.ts +2 -0
  19. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +21 -1
  20. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +1 -0
  21. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +3 -2
  22. package/dist/_dts/blocks/src/system/runtime/nodes/events/index.d.ts +3 -0
  23. package/dist/_dts/blocks/src/system/runtime/nodes/header-section.client.d.ts +1 -0
  24. package/dist/_dts/blocks/src/system/runtime/nodes/header-section.server.d.ts +1 -0
  25. package/dist/_dts/content-editor/src/hooks/validateBlocksForPublish.d.ts +5 -0
  26. package/dist/_dts/preview-next/src/client/preview/SiteChromeEditableSurface.d.ts +12 -2
  27. package/dist/_dts/sdk/src/public-api/contracts.d.ts +1 -0
  28. package/dist/_dts/sdk/src/rendering/islands/deferredVideoEmbeds.d.ts +2 -0
  29. package/dist/_dts/sdk/src/rendering/server.d.ts +3 -0
  30. package/dist/_dts/sdk/src/version.d.ts +1 -1
  31. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  32. package/dist/{chunk-YY7K3QD2.mjs → chunk-BGMNDF6T.mjs} +7 -7
  33. package/dist/{chunk-2MIWNFJM.mjs → chunk-GFE74WRD.mjs} +309 -84
  34. package/dist/{chunk-CEQBBLMJ.mjs → chunk-RWXQBRQZ.mjs} +1 -1
  35. package/dist/{chunk-7RX72SK2.mjs → chunk-VX7B5VAC.mjs} +36 -25
  36. package/dist/{chunk-YRJKZEQ3.mjs → chunk-Z7JLNTJR.mjs} +1 -1
  37. package/dist/{chunk-CBD47MTM.mjs → chunk-ZSHFGFUG.mjs} +2 -2
  38. package/dist/cli/index.mjs +3395 -3753
  39. package/dist/client/{accordion-ZZVXWV3N.mjs → accordion-T2UD2ZTH.mjs} +1 -1
  40. package/dist/client/bookingForm-GUP75FKN.mjs +3022 -0
  41. package/dist/client/bookings.mjs +19 -10
  42. package/dist/client/{carousel-25WK2H7G.mjs → carousel-2NQA6V57.mjs} +3 -2
  43. package/dist/client/cart-5TFIAFDS.mjs +18 -0
  44. package/dist/client/checkout-TP4WAHZE.mjs +18 -0
  45. package/dist/client/chunk-2PHQZ666.mjs +383 -0
  46. package/dist/client/chunk-3DCJ45Z2.mjs +36 -0
  47. package/dist/client/chunk-3PEDD5KJ.mjs +146 -0
  48. package/dist/client/chunk-CY2ZTSE5.mjs +204 -0
  49. package/dist/client/chunk-F7LHOKEH.mjs +146 -0
  50. package/dist/client/{chunk-6VGXRE34.mjs → chunk-FU2QRZMX.mjs} +6 -6
  51. package/dist/client/chunk-I2MMZO53.mjs +6 -0
  52. package/dist/client/chunk-II7O4XN3.mjs +2206 -0
  53. package/dist/client/chunk-M3L3KYYR.mjs +1181 -0
  54. package/dist/client/chunk-NWOUL6JY.mjs +1378 -0
  55. package/dist/client/chunk-OJPZEZU2.mjs +31 -0
  56. package/dist/client/chunk-RTZ3JKKX.mjs +178 -0
  57. package/dist/client/chunk-TQ5MSPDX.mjs +74 -0
  58. package/dist/client/chunk-VUAOE3AG.mjs +5592 -0
  59. package/dist/client/chunk-WJXXNDSE.mjs +245 -0
  60. package/dist/client/chunk-YLMKMCSJ.mjs +86 -0
  61. package/dist/client/chunk-ZLMS67RR.mjs +106 -0
  62. package/dist/client/client.mjs +51626 -52074
  63. package/dist/client/courseRegistration-5DPU6PDY.mjs +1737 -0
  64. package/dist/client/{eventCalendar-X6GIPYFM.mjs → eventCalendar-F3GZGTEF.mjs} +13 -2
  65. package/dist/client/{eventCombined-EZUOPM3G.mjs → eventCombined-BQOB6QMY.mjs} +13 -2
  66. package/dist/client/eventDetails-PEM2EJWE.mjs +25 -0
  67. package/dist/client/{eventListing-HEFGAETC.mjs → eventListing-YMIQPVME.mjs} +13 -2
  68. package/dist/client/{eventRegistration-3LCP2V3P.mjs → eventRegistration-4I6ZNDUF.mjs} +13 -2
  69. package/dist/client/form-ZJVAYZ6G.mjs +300 -0
  70. package/dist/client/headerSection-TOT5MGTF.mjs +729 -0
  71. package/dist/client/hooks.mjs +49 -33
  72. package/dist/client/locationMap-J66NZREU.mjs +227 -0
  73. package/dist/client/newsletterForm-ET2XUMRO.mjs +208 -0
  74. package/dist/client/productDetail-C2XIH7C5.mjs +18 -0
  75. package/dist/client/productList-T2AZLFTP.mjs +18 -0
  76. package/dist/client/rendering/client.mjs +11763 -12445
  77. package/dist/client/rendering/islands.mjs +98 -21
  78. package/dist/client/rendering.mjs +46778 -47229
  79. package/dist/client/shop-UZ6IUZXD.mjs +20 -0
  80. package/dist/preview-next/before-render.mjs +37 -25
  81. package/dist/preview-next/client/runtime.mjs +5 -5
  82. package/dist/preview-next/middleware.mjs +37 -25
  83. package/dist/{sdk-runtime-OHNONZ5U.mjs → sdk-runtime-JCUQM63Y.mjs} +6 -6
  84. package/dist/server/components.mjs +409 -266
  85. package/dist/server/config-validation.mjs +49 -33
  86. package/dist/server/config.mjs +49 -33
  87. package/dist/server/data.mjs +49 -33
  88. package/dist/server/index.mjs +45 -33
  89. package/dist/server/next.mjs +405 -262
  90. package/dist/server/page-converter.mjs +12 -8
  91. package/dist/server/prebuild.mjs +1 -1
  92. package/dist/server/rendering/server.mjs +493 -265
  93. package/dist/server/rendering.mjs +411 -268
  94. package/dist/server/routing.mjs +49 -33
  95. package/dist/server/server.mjs +50 -34
  96. package/dist/server/theme-bridge.mjs +5 -0
  97. package/dist/styles/index.css +5 -0
  98. package/package.json +2 -1
  99. package/dist/SdkPreviewModeRuntime-CRYNDSPL.mjs +0 -8
  100. package/dist/client/bookingForm-4X77HKDS.mjs +0 -34
  101. package/dist/client/cart-JWD2VRFU.mjs +0 -11
  102. package/dist/client/checkout-V7KYGWL7.mjs +0 -11
  103. package/dist/client/chunk-5IYGMTUE.mjs +0 -18614
  104. package/dist/client/chunk-RKCFVIMS.mjs +0 -26
  105. package/dist/client/courseRegistration-O6ZPK4YT.mjs +0 -29
  106. package/dist/client/eventDetails-3WODIXET.mjs +0 -14
  107. package/dist/client/form-AKXQMY6Z.mjs +0 -85
  108. package/dist/client/headerSection-5KHCMU6B.mjs +0 -12
  109. package/dist/client/locationMap-7HIADW76.mjs +0 -14
  110. package/dist/client/newsletterForm-5N4YTMU3.mjs +0 -60
  111. package/dist/client/productDetail-IZUA7ZP3.mjs +0 -11
  112. package/dist/client/productList-KWIIJE6I.mjs +0 -11
  113. package/dist/client/shop-XZQFRQWZ.mjs +0 -13
@@ -0,0 +1,146 @@
1
+ import * as React from 'react';
2
+ import { createPortal } from 'react-dom';
3
+ import { jsxs, jsx } from 'react/jsx-runtime';
4
+
5
+ // ../blocks/src/system/runtime/shared/components/ModalShell.tsx
6
+ var modalBodyScrollLockCount = 0;
7
+ var modalBodyOriginalOverflow = null;
8
+ function lockBodyScroll() {
9
+ if (typeof document === "undefined") {
10
+ return;
11
+ }
12
+ if (modalBodyScrollLockCount === 0) {
13
+ modalBodyOriginalOverflow = document.body.style.overflow;
14
+ document.body.style.overflow = "hidden";
15
+ }
16
+ modalBodyScrollLockCount += 1;
17
+ }
18
+ function unlockBodyScroll() {
19
+ if (typeof document === "undefined" || modalBodyScrollLockCount === 0) {
20
+ return;
21
+ }
22
+ modalBodyScrollLockCount -= 1;
23
+ if (modalBodyScrollLockCount === 0) {
24
+ document.body.style.overflow = modalBodyOriginalOverflow ?? "";
25
+ modalBodyOriginalOverflow = null;
26
+ }
27
+ }
28
+ function ModalShell({
29
+ title,
30
+ titleId,
31
+ onClose,
32
+ children,
33
+ portalRoot,
34
+ portal = false,
35
+ overlayClassName,
36
+ modalClassName,
37
+ renderSrOnlyTitle = false,
38
+ renderHeader,
39
+ headerClassName,
40
+ titleClassName,
41
+ closeButtonClassName,
42
+ closeIcon
43
+ }) {
44
+ const closeButtonRef = React.useRef(null);
45
+ const onCloseRef = React.useRef(onClose);
46
+ onCloseRef.current = onClose;
47
+ React.useEffect(() => {
48
+ closeButtonRef.current?.focus();
49
+ const onKeyDown = (event) => {
50
+ if (event.key === "Escape") {
51
+ onCloseRef.current();
52
+ }
53
+ };
54
+ document.addEventListener("keydown", onKeyDown);
55
+ lockBodyScroll();
56
+ return () => {
57
+ document.removeEventListener("keydown", onKeyDown);
58
+ unlockBodyScroll();
59
+ };
60
+ }, []);
61
+ const srOnlyTitle = renderSrOnlyTitle ? /* @__PURE__ */ jsx(
62
+ "h2",
63
+ {
64
+ id: titleId,
65
+ style: {
66
+ position: "absolute",
67
+ width: 1,
68
+ height: 1,
69
+ padding: 0,
70
+ margin: -1,
71
+ overflow: "hidden",
72
+ clip: "rect(0,0,0,0)",
73
+ whiteSpace: "nowrap",
74
+ border: 0
75
+ },
76
+ children: title
77
+ }
78
+ ) : null;
79
+ const header = renderHeader ? renderHeader({ title, titleId, onClose, closeButtonRef }) : /* @__PURE__ */ jsxs("div", { className: headerClassName, children: [
80
+ !renderSrOnlyTitle ? /* @__PURE__ */ jsx("h3", { className: titleClassName, id: titleId, children: title }) : null,
81
+ /* @__PURE__ */ jsx(
82
+ "button",
83
+ {
84
+ ref: closeButtonRef,
85
+ type: "button",
86
+ className: closeButtonClassName,
87
+ onClick: onClose,
88
+ "aria-label": "Close",
89
+ children: closeIcon ?? "\xD7"
90
+ }
91
+ )
92
+ ] });
93
+ const modal = /* @__PURE__ */ jsx("div", { className: overlayClassName, onClick: onClose, children: /* @__PURE__ */ jsxs(
94
+ "div",
95
+ {
96
+ className: modalClassName,
97
+ onClick: (event) => event.stopPropagation(),
98
+ role: "dialog",
99
+ "aria-modal": "true",
100
+ "aria-labelledby": titleId,
101
+ children: [
102
+ srOnlyTitle,
103
+ header,
104
+ children
105
+ ]
106
+ }
107
+ ) });
108
+ if (!portal) {
109
+ return modal;
110
+ }
111
+ if (typeof document === "undefined") {
112
+ return null;
113
+ }
114
+ if (!portalRoot) {
115
+ return null;
116
+ }
117
+ return createPortal(modal, portalRoot);
118
+ }
119
+
120
+ // ../blocks/src/system/runtime/shared/utils/checkoutRoute.ts
121
+ function resolveDedicatedCheckoutTarget(pathname) {
122
+ const internalPublishedMatch = pathname.match(
123
+ /^\/internal-sites\/([^/]+)\/([^/]+)\/published(?:\/.*)?$/
124
+ );
125
+ if (internalPublishedMatch) {
126
+ const hostKey = internalPublishedMatch[1];
127
+ const siteIdentifier = internalPublishedMatch[2];
128
+ if (hostKey && siteIdentifier) {
129
+ return {
130
+ kind: "internal_published_preview",
131
+ hostKey,
132
+ siteIdentifier
133
+ };
134
+ }
135
+ }
136
+ return { kind: "public" };
137
+ }
138
+ function resolveDedicatedCheckoutPath(pathname) {
139
+ const target = resolveDedicatedCheckoutTarget(pathname);
140
+ if (target.kind === "internal_published_preview") {
141
+ return `/internal-sites/${target.hostKey}/${target.siteIdentifier}/published/checkout`;
142
+ }
143
+ return "/checkout";
144
+ }
145
+
146
+ export { ModalShell, resolveDedicatedCheckoutPath };
@@ -0,0 +1,204 @@
1
+ "use client";
2
+ import { useBlockApi, BlockApiError } from './chunk-M3L3KYYR.mjs';
3
+ import { themeButtonClassName } from './chunk-FU2QRZMX.mjs';
4
+ import { useState, useSyncExternalStore, useEffect } from 'react';
5
+ import { jsxs, jsx } from 'react/jsx-runtime';
6
+
7
+ function MagicLinkForm({
8
+ initialEmail = "",
9
+ title,
10
+ subtitle,
11
+ buttonText = "Send login link",
12
+ successMessage = "Check your email for a login link to sign in.",
13
+ onSuccess,
14
+ classPrefix = "er",
15
+ compact = false
16
+ }) {
17
+ const api = useBlockApi();
18
+ const [email, setEmail] = useState(initialEmail);
19
+ const [loading, setLoading] = useState(false);
20
+ const [success, setSuccess] = useState(false);
21
+ const [error, setError] = useState(null);
22
+ const handleSubmit = async (e) => {
23
+ e.preventDefault();
24
+ const normalizedEmail = email.trim().toLowerCase();
25
+ if (!normalizedEmail || loading) return;
26
+ setLoading(true);
27
+ setError(null);
28
+ try {
29
+ const redirectTo = `${window.location.pathname}${window.location.search}${window.location.hash}`;
30
+ await api.sendMagicLink({
31
+ email: normalizedEmail,
32
+ redirectUrl: `${window.location.origin}/api/portal/callback?redirect_to=${encodeURIComponent(redirectTo)}`
33
+ });
34
+ setSuccess(true);
35
+ onSuccess?.();
36
+ } catch (err) {
37
+ console.error("Magic link error:", err);
38
+ setError(err instanceof Error ? err.message : "Failed to send. Please try again.");
39
+ } finally {
40
+ setLoading(false);
41
+ }
42
+ };
43
+ const handleReset = () => {
44
+ setSuccess(false);
45
+ setEmail("");
46
+ setError(null);
47
+ };
48
+ if (success) {
49
+ return /* @__PURE__ */ jsxs("div", { className: `${classPrefix}-magic-link-success`, children: [
50
+ /* @__PURE__ */ jsx("p", { className: `${classPrefix}-portal-auth-text ${classPrefix}-portal-auth-text--success`, children: successMessage }),
51
+ !compact && /* @__PURE__ */ jsx(
52
+ "button",
53
+ {
54
+ type: "button",
55
+ className: classPrefix === "cp" ? themeButtonClassName({ variant: "secondary", size: "md" }) : `${classPrefix}-modal-btn ${classPrefix}-modal-btn--secondary`,
56
+ onClick: handleReset,
57
+ children: "Try a different email"
58
+ }
59
+ )
60
+ ] });
61
+ }
62
+ return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: `${classPrefix}-magic-link-form`, children: [
63
+ title && /* @__PURE__ */ jsx("h3", { className: `${classPrefix}-magic-link-title`, children: title }),
64
+ subtitle && /* @__PURE__ */ jsx("p", { className: `${classPrefix}-portal-auth-text`, children: subtitle }),
65
+ /* @__PURE__ */ jsx(
66
+ "input",
67
+ {
68
+ type: "email",
69
+ className: classPrefix === "cp" ? "cp-input" : `${classPrefix}-form__input`,
70
+ placeholder: "your@email.com",
71
+ value: email,
72
+ onChange: (e) => setEmail(e.target.value),
73
+ autoFocus: !compact,
74
+ required: true,
75
+ disabled: loading
76
+ }
77
+ ),
78
+ error && /* @__PURE__ */ jsx("p", { className: `${classPrefix}-portal-auth-text ${classPrefix}-portal-auth-text--error`, children: error }),
79
+ /* @__PURE__ */ jsx(
80
+ "button",
81
+ {
82
+ type: "submit",
83
+ className: classPrefix === "cp" ? themeButtonClassName({ variant: "primary", size: "md" }) : `${classPrefix}-modal-btn`,
84
+ disabled: !email.trim() || loading,
85
+ children: loading ? "Sending..." : buttonText
86
+ }
87
+ )
88
+ ] });
89
+ }
90
+ var WAITLIST_CLAIM_LOCATION_EVENT = "riverbank:waitlist-claim-location-change";
91
+ var historyPatched = false;
92
+ function emitWaitlistClaimLocationChange() {
93
+ if (typeof window === "undefined") return;
94
+ window.dispatchEvent(new Event(WAITLIST_CLAIM_LOCATION_EVENT));
95
+ }
96
+ function ensureWaitlistClaimLocationTracking() {
97
+ if (typeof window === "undefined" || historyPatched) {
98
+ return;
99
+ }
100
+ historyPatched = true;
101
+ const history = window.history;
102
+ if (history.__riverbankWaitlistClaimPatched__) {
103
+ return;
104
+ }
105
+ const wrapHistoryMethod = (method) => {
106
+ return function patched(...args) {
107
+ method.apply(this, args);
108
+ emitWaitlistClaimLocationChange();
109
+ };
110
+ };
111
+ try {
112
+ history.pushState = wrapHistoryMethod(history.pushState);
113
+ history.replaceState = wrapHistoryMethod(history.replaceState);
114
+ history.__riverbankWaitlistClaimPatched__ = true;
115
+ } catch {
116
+ }
117
+ window.addEventListener("popstate", emitWaitlistClaimLocationChange);
118
+ }
119
+ function getWaitlistClaimTokenFromUrl() {
120
+ if (typeof window === "undefined") {
121
+ return null;
122
+ }
123
+ const token = new URLSearchParams(window.location.search).get("waitlist_claim")?.trim() ?? "";
124
+ return token.length > 0 ? token : null;
125
+ }
126
+ function subscribeToWaitlistClaimToken(callback) {
127
+ if (typeof window === "undefined") {
128
+ return () => {
129
+ };
130
+ }
131
+ ensureWaitlistClaimLocationTracking();
132
+ window.addEventListener(WAITLIST_CLAIM_LOCATION_EVENT, callback);
133
+ return () => {
134
+ window.removeEventListener(WAITLIST_CLAIM_LOCATION_EVENT, callback);
135
+ };
136
+ }
137
+ function getWaitlistClaimTokenSnapshot() {
138
+ return getWaitlistClaimTokenFromUrl();
139
+ }
140
+ function useWaitlistClaim() {
141
+ const api = useBlockApi();
142
+ const token = useSyncExternalStore(
143
+ subscribeToWaitlistClaimToken,
144
+ getWaitlistClaimTokenSnapshot,
145
+ () => null
146
+ );
147
+ const [claim, setClaim] = useState(null);
148
+ const [error, setError] = useState(null);
149
+ const [loginMessage, setLoginMessage] = useState(null);
150
+ const [requiresPortalLogin, setRequiresPortalLogin] = useState(false);
151
+ const [isLoading, setIsLoading] = useState(() => Boolean(token));
152
+ useEffect(() => {
153
+ let cancelled = false;
154
+ async function resolveClaim() {
155
+ if (!token) {
156
+ setClaim(null);
157
+ setError(null);
158
+ setLoginMessage(null);
159
+ setRequiresPortalLogin(false);
160
+ setIsLoading(false);
161
+ return;
162
+ }
163
+ setIsLoading(true);
164
+ setClaim(null);
165
+ setError(null);
166
+ setLoginMessage(null);
167
+ setRequiresPortalLogin(false);
168
+ try {
169
+ const result = await api.resolveWaitlistClaim({ claimToken: token });
170
+ if (cancelled) return;
171
+ setClaim(result);
172
+ } catch (claimError) {
173
+ if (cancelled) return;
174
+ const message = claimError instanceof Error ? claimError.message : "Failed to resolve waitlist claim";
175
+ setClaim(null);
176
+ if (claimError instanceof BlockApiError && claimError.status === 401) {
177
+ setRequiresPortalLogin(true);
178
+ setLoginMessage(message);
179
+ setError(null);
180
+ } else {
181
+ setError(message);
182
+ }
183
+ } finally {
184
+ if (!cancelled) {
185
+ setIsLoading(false);
186
+ }
187
+ }
188
+ }
189
+ resolveClaim();
190
+ return () => {
191
+ cancelled = true;
192
+ };
193
+ }, [api, token]);
194
+ return {
195
+ token,
196
+ claim,
197
+ error,
198
+ loginMessage,
199
+ requiresPortalLogin,
200
+ isLoading
201
+ };
202
+ }
203
+
204
+ export { MagicLinkForm, useWaitlistClaim };
@@ -0,0 +1,146 @@
1
+ "use client";
2
+ import { isRecord } from './chunk-I2MMZO53.mjs';
3
+ import { useRef, useState, useEffect } from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ var LEAFLET_CSS = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.css";
7
+ var LEAFLET_CSS_INTEGRITY = "sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=";
8
+ var LEAFLET_JS = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.js";
9
+ var LEAFLET_JS_INTEGRITY = "sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=";
10
+ var leafletLoaded = false;
11
+ var leafletLoadPromise = null;
12
+ function isLeafletApi(value) {
13
+ if (!isRecord(value)) return false;
14
+ return typeof value.map === "function" && typeof value.tileLayer === "function" && typeof value.marker === "function";
15
+ }
16
+ function loadLeaflet() {
17
+ if (leafletLoaded) return Promise.resolve();
18
+ if (leafletLoadPromise) return leafletLoadPromise;
19
+ leafletLoadPromise = new Promise((resolve, reject) => {
20
+ if (typeof window !== "undefined" && isLeafletApi(Reflect.get(window, "L"))) {
21
+ leafletLoaded = true;
22
+ resolve();
23
+ return;
24
+ }
25
+ const link = document.createElement("link");
26
+ link.rel = "stylesheet";
27
+ link.href = LEAFLET_CSS;
28
+ link.integrity = LEAFLET_CSS_INTEGRITY;
29
+ link.crossOrigin = "anonymous";
30
+ document.head.appendChild(link);
31
+ const script = document.createElement("script");
32
+ script.src = LEAFLET_JS;
33
+ script.integrity = LEAFLET_JS_INTEGRITY;
34
+ script.crossOrigin = "anonymous";
35
+ script.async = true;
36
+ script.onload = () => {
37
+ leafletLoaded = true;
38
+ resolve();
39
+ };
40
+ script.onerror = () => {
41
+ leafletLoadPromise = null;
42
+ reject(new Error("Failed to load Leaflet"));
43
+ };
44
+ document.head.appendChild(script);
45
+ });
46
+ return leafletLoadPromise;
47
+ }
48
+ var LeafletStaticMap = ({
49
+ location,
50
+ label,
51
+ className = "",
52
+ height = 200,
53
+ zoom = 15
54
+ }) => {
55
+ const mapContainerRef = useRef(null);
56
+ const mapRef = useRef(null);
57
+ const markerRef = useRef(null);
58
+ const [loading, setLoading] = useState(true);
59
+ const [error, setError] = useState(null);
60
+ useEffect(() => {
61
+ let mounted = true;
62
+ async function initMap() {
63
+ try {
64
+ await loadLeaflet();
65
+ if (!mounted || !mapContainerRef.current) return;
66
+ const L = Reflect.get(window, "L");
67
+ if (!isLeafletApi(L)) {
68
+ throw new Error("Leaflet not available");
69
+ }
70
+ if (!mapRef.current) {
71
+ const map = L.map(mapContainerRef.current, {
72
+ scrollWheelZoom: false,
73
+ dragging: true,
74
+ zoomControl: true
75
+ });
76
+ const tileLayer = L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
77
+ attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>'
78
+ });
79
+ tileLayer.addTo(map);
80
+ const marker = L.marker([location.lat, location.lng]);
81
+ marker.addTo(map);
82
+ map.setView([location.lat, location.lng], zoom);
83
+ if (label) {
84
+ marker.bindPopup(label);
85
+ }
86
+ mapRef.current = map;
87
+ markerRef.current = {
88
+ bindPopup(content) {
89
+ marker.bindPopup(content);
90
+ return this;
91
+ },
92
+ setLatLng(latlng) {
93
+ marker.setLatLng(latlng);
94
+ return this;
95
+ }
96
+ };
97
+ }
98
+ setLoading(false);
99
+ } catch (err) {
100
+ if (mounted) {
101
+ setError(err instanceof Error ? err.message : "Failed to load map");
102
+ setLoading(false);
103
+ }
104
+ }
105
+ }
106
+ initMap();
107
+ return () => {
108
+ mounted = false;
109
+ if (mapRef.current) {
110
+ mapRef.current.remove();
111
+ mapRef.current = null;
112
+ markerRef.current = null;
113
+ }
114
+ };
115
+ }, []);
116
+ useEffect(() => {
117
+ if (!mapRef.current || !markerRef.current) {
118
+ return;
119
+ }
120
+ mapRef.current.setView([location.lat, location.lng], zoom);
121
+ markerRef.current.setLatLng([location.lat, location.lng]);
122
+ if (label) {
123
+ markerRef.current.bindPopup(label);
124
+ }
125
+ }, [location.lat, location.lng, label, zoom]);
126
+ if (error) {
127
+ return null;
128
+ }
129
+ return /* @__PURE__ */ jsx(
130
+ "div",
131
+ {
132
+ ref: mapContainerRef,
133
+ className: `leaflet-static-map ${className}`,
134
+ style: {
135
+ height,
136
+ width: "100%",
137
+ borderRadius: "0.5rem",
138
+ overflow: "hidden",
139
+ backgroundColor: loading ? "rgb(var(--tb-surface))" : void 0
140
+ },
141
+ "aria-label": label ? `Map showing ${label}` : "Location map"
142
+ }
143
+ );
144
+ };
145
+
146
+ export { LeafletStaticMap };
@@ -5228,7 +5228,7 @@ var COLUMN_CLASSES = {
5228
5228
  };
5229
5229
  function getContainerClass(layout, columns) {
5230
5230
  if (layout === "compact") {
5231
- return "rb-flex rb-flex-col rb-gap-2";
5231
+ return "event-listing-compact-container rb-flex rb-flex-col rb-gap-2";
5232
5232
  }
5233
5233
  if (layout === "stack") {
5234
5234
  return "rb-flex rb-flex-col rb-gap-6";
@@ -5359,7 +5359,7 @@ function formatEventPrice(event) {
5359
5359
  }
5360
5360
  function resolveEventCta(event, buttonText) {
5361
5361
  const { isFull: isSoldOut } = getEventAvailability(event);
5362
- const defaultButtonText = event.kind === "course_session" ? "View course" : "View event";
5362
+ const defaultButtonText = event.kind === "course_session" ? "Book course" : "Book now";
5363
5363
  const effectiveButtonText = buttonText ?? defaultButtonText;
5364
5364
  if (isSoldOut) {
5365
5365
  return { label: "Sold out", href: event.path, hidden: true };
@@ -5771,7 +5771,7 @@ var eventListingBlockRuntime = defineProgressiveBlockRuntime({
5771
5771
  containerClass: getContainerClass(layout, source.columns ?? "3"),
5772
5772
  cardVariant: source.cardVariant ?? "default",
5773
5773
  buttonVariant: source.buttonVariant ?? "primary",
5774
- buttonText: source.buttonText ?? "View event",
5774
+ buttonText: source.buttonText ?? "Book now",
5775
5775
  showVenue: source.showVenue ?? true,
5776
5776
  showMap: source.showMap ?? true,
5777
5777
  showCapacity: source.showCapacity ?? true,
@@ -5945,7 +5945,7 @@ function buildEventCalendarDisplay(source) {
5945
5945
  ),
5946
5946
  filterVenueId: normalizeEventVenueId(source.filterVenueId),
5947
5947
  buttonVariant: source.buttonVariant ?? "primary",
5948
- buttonText: source.buttonText ?? "View event",
5948
+ buttonText: source.buttonText ?? "Book now",
5949
5949
  showVenue: source.showVenue ?? true,
5950
5950
  showMap: source.showMap ?? true,
5951
5951
  showCapacity: source.showCapacity ?? true,
@@ -6150,7 +6150,7 @@ function buildEventCombinedDisplay(source) {
6150
6150
  showMap: source.showMap ?? true,
6151
6151
  showCapacity: source.showCapacity ?? true,
6152
6152
  buttonVariant: source.buttonVariant ?? "primary",
6153
- buttonText: source.buttonText ?? "View event",
6153
+ buttonText: source.buttonText ?? "Book now",
6154
6154
  emptyMessage: source.emptyMessage ?? "No upcoming events scheduled."
6155
6155
  };
6156
6156
  }
@@ -7614,4 +7614,4 @@ function defineIslandPropsDecoder(kind) {
7614
7614
  };
7615
7615
  }
7616
7616
 
7617
- export { BOOKING_FORM_DATA_RESERVED_KEYS, DateTimeTile, EMPTY_COMMERCE_CART_STATE, EmptyState, EventCard, EventCompactRow, MAX_EVENTS_PER_DAY, MONTH_NAMES, addMonths, assertNever, buildCartDisplay, buildEventCalendarListingRender, buildPassCartItem, buildProductCardDisplay, buildProductCartItem, buildProductDetailDisplay, buildTimetableModel, defineIslandPropsDecoder, deriveBookingFormViewState, err, formatBookingSubmissionPreparationError, formatCalendarTitle, formatCommercePrice, formatCoursePriceAmount, formatCoursePriceDisplay, formatDate, formatDateKey, formatEventDateParts, formatEventPrice, formatEventTeacherLine, formatInterval, formatTime, getBookingRedirectStateFromLocation, getBookingSuccessMessage, getCardOrientation, getContainerClass, getEventAvailability, getMonthCalendarDays, getOrderedDayNames, getShopDisplayForItems, getThreeMonthRange, getWeekCalendarDays, groupEventsByDate, isEventContentType, isToday, normalizeEventBlockKind, normalizeIdList, ok, okWith, parseStoredCommerceCartState, prepareBookingSubmission, productItemKey, reduceCommerceCart, resolveAppointmentCheckoutVerificationState, resolveBookingPaymentStep, resolveBookingSiteId, resolveCoursePricingState, resolveDefaultBookingServiceId, themeButtonClassName, themeColorTokenSchema, toSelectedCollectionOptionKind };
7617
+ export { BOOKING_FORM_DATA_RESERVED_KEYS, DateTimeTile, EMPTY_COMMERCE_CART_STATE, EmptyState, EventCard, EventCompactRow, MAX_EVENTS_PER_DAY, MONTH_NAMES, addMonths, assertNever, buildCartDisplay, buildEventCalendarListingRender, buildPassCartItem, buildProductCardDisplay, buildProductCartItem, buildProductDetailDisplay, buildTimetableModel, defineIslandPropsDecoder, deriveBookingFormViewState, err, formatBookingSubmissionPreparationError, formatCalendarTitle, formatCommercePrice, formatCoursePriceAmount, formatCoursePriceDisplay, formatDate, formatDateKey, formatEventDateParts, formatEventPrice, formatEventTeacherLine, formatInterval, formatTime, getBookingRedirectStateFromLocation, getBookingSuccessMessage, getCardOrientation, getContainerClass, getEventAvailability, getMonthCalendarDays, getOrderedDayNames, getShopDisplayForItems, getThreeMonthRange, getWeekCalendarDays, groupEventsByDate, isEventContentType, isToday, normalizeEventBlockKind, normalizeIdList, ok, okWith, parseStoredCommerceCartState, prepareBookingSubmission, productItemKey, reduceCommerceCart, resolveAppointmentCheckoutVerificationState, resolveBookingPaymentStep, resolveBookingSiteId, resolveCoursePricingState, resolveDefaultBookingServiceId, themeButtonClassName, toSelectedCollectionOptionKind };
@@ -0,0 +1,6 @@
1
+ // ../blocks/src/lib/typeGuards.ts
2
+ function isRecord(value) {
3
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4
+ }
5
+
6
+ export { isRecord };