@riverbankcms/sdk 0.74.0 → 0.76.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 (145) hide show
  1. package/README.md +2 -0
  2. package/dist/{PreviewEditorSidebar-5XL7M3OM.mjs → PreviewEditorSidebar-X2HWXFOL.mjs} +172 -89
  3. package/dist/{PreviewEditorUI-ZDFRDJID.mjs → PreviewEditorUI-AQXIXPOH.mjs} +3 -3
  4. package/dist/SdkPreviewModeRuntime-ZQNDCASH.mjs +8 -0
  5. package/dist/_dts/api/src/bookingOperations.d.ts +12 -0
  6. package/dist/_dts/api/src/cache-tags.d.ts +22 -0
  7. package/dist/_dts/api/src/contentRuntime.d.ts +1 -0
  8. package/dist/_dts/api/src/endpoints.d.ts +24 -24
  9. package/dist/_dts/api/src/index.d.ts +1 -1
  10. package/dist/_dts/api/src/publicExperienceEndpoints.d.ts +13 -4
  11. package/dist/_dts/block-form/src/blockDraftSaveability.d.ts +4 -2
  12. package/dist/_dts/block-form/src/client/index.d.ts +1 -1
  13. package/dist/_dts/block-form/src/manifest/utils.d.ts +24 -0
  14. package/dist/_dts/blocks/src/client/booking-form.d.ts +2 -0
  15. package/dist/_dts/blocks/src/client/carousel.d.ts +1 -0
  16. package/dist/_dts/blocks/src/client/course-registration.d.ts +2 -0
  17. package/dist/_dts/blocks/src/client/events.d.ts +6 -0
  18. package/dist/_dts/blocks/src/client/form.d.ts +2 -0
  19. package/dist/_dts/blocks/src/client/header.d.ts +1 -0
  20. package/dist/_dts/blocks/src/client/location-map.d.ts +1 -0
  21. package/dist/_dts/blocks/src/client/newsletter-form.d.ts +2 -0
  22. package/dist/_dts/blocks/src/client/shop.d.ts +6 -0
  23. package/dist/_dts/blocks/src/contracts/proof-block-islands.d.ts +4 -4
  24. package/dist/_dts/blocks/src/lib/video.d.ts +2 -0
  25. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +21 -1
  26. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +7 -6
  27. package/dist/_dts/blocks/src/system/runtime/components/runtime-backed-blocks.d.ts +3 -3
  28. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +3 -2
  29. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.interactive.d.ts +3 -27
  30. package/dist/_dts/blocks/src/system/runtime/nodes/booking-runtime-sources.d.ts +163 -0
  31. package/dist/_dts/blocks/src/system/runtime/nodes/event-registration.interactive.d.ts +5 -5
  32. package/dist/_dts/blocks/src/system/runtime/nodes/events/index.d.ts +3 -0
  33. package/dist/_dts/blocks/src/system/runtime/nodes/header-section.client.d.ts +1 -0
  34. package/dist/_dts/blocks/src/system/runtime/nodes/header-section.server.d.ts +1 -0
  35. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionCompactRow.d.ts +29 -0
  36. package/dist/_dts/blocks/src/system/runtime/shared/components/BookingOptionList.d.ts +13 -0
  37. package/dist/_dts/blocks/src/system/runtime/shared/components/index.d.ts +4 -0
  38. package/dist/_dts/blocks/src/system/runtime/shared/index.d.ts +4 -3
  39. package/dist/_dts/blocks/src/system/runtime/shared/utils/bookingRoute.d.ts +20 -0
  40. package/dist/_dts/blocks/src/system/runtime/shared/utils/index.d.ts +2 -1
  41. package/dist/_dts/blocks/src/system/types/link.d.ts +12 -0
  42. package/dist/_dts/content-editor/src/hooks/validateBlocksForPublish.d.ts +5 -0
  43. package/dist/_dts/editor-blocks/src/BlockEditor.d.ts +2 -0
  44. package/dist/_dts/editor-blocks/src/block-editor/BlockCard.d.ts +3 -1
  45. package/dist/_dts/editor-blocks/src/block-editor/BlockCardHeader.d.ts +3 -1
  46. package/dist/_dts/editor-blocks/src/block-editor/BlockSettingsModal.d.ts +5 -1
  47. package/dist/_dts/editor-blocks/src/block-editor/SortableBlockItem.d.ts +2 -0
  48. package/dist/_dts/editor-blocks/src/block-editor/actionControlMode.d.ts +2 -0
  49. package/dist/_dts/editor-blocks/src/index.d.ts +1 -1
  50. package/dist/_dts/preview-next/src/client/preview/SiteChromeEditableSurface.d.ts +12 -2
  51. package/dist/_dts/preview-next/src/client/preview/themeOverlay.d.ts +21 -3
  52. package/dist/_dts/sdk/src/components.d.ts +2 -2
  53. package/dist/_dts/sdk/src/public-api/contracts.d.ts +1 -0
  54. package/dist/_dts/sdk/src/rendering/index.d.ts +2 -2
  55. package/dist/_dts/sdk/src/rendering/islands/deferredVideoEmbeds.d.ts +2 -0
  56. package/dist/_dts/sdk/src/rendering/overrideResolution.d.ts +6 -0
  57. package/dist/_dts/sdk/src/rendering/overrides.d.ts +21 -1
  58. package/dist/_dts/sdk/src/rendering/server.d.ts +4 -0
  59. package/dist/_dts/sdk/src/version.d.ts +1 -1
  60. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  61. package/dist/{chunk-2MIWNFJM.mjs → chunk-LYI7TEMH.mjs} +494 -171
  62. package/dist/{chunk-YY7K3QD2.mjs → chunk-Q4OLG66B.mjs} +9 -9
  63. package/dist/{chunk-CEQBBLMJ.mjs → chunk-TW2Y4RR5.mjs} +69 -14
  64. package/dist/{chunk-CBD47MTM.mjs → chunk-V5VORNEJ.mjs} +2 -2
  65. package/dist/{chunk-7RX72SK2.mjs → chunk-VX7B5VAC.mjs} +36 -25
  66. package/dist/{chunk-YRJKZEQ3.mjs → chunk-Z7JLNTJR.mjs} +1 -1
  67. package/dist/cli/index.mjs +3395 -3753
  68. package/dist/client/{accordion-ZZVXWV3N.mjs → accordion-2YHIBOZH.mjs} +1 -1
  69. package/dist/client/bookingForm-35IBDWAS.mjs +3012 -0
  70. package/dist/client/bookings.mjs +30 -21
  71. package/dist/client/{carousel-25WK2H7G.mjs → carousel-K6XG7NZQ.mjs} +3 -2
  72. package/dist/client/cart-HCFYUTTU.mjs +18 -0
  73. package/dist/client/checkout-J3U4XR7K.mjs +18 -0
  74. package/dist/client/chunk-3DCJ45Z2.mjs +36 -0
  75. package/dist/client/chunk-3PEDD5KJ.mjs +146 -0
  76. package/dist/client/{chunk-6VGXRE34.mjs → chunk-7UOSCYY4.mjs} +76 -29
  77. package/dist/client/chunk-BOIHIU7E.mjs +106 -0
  78. package/dist/client/chunk-F7LHOKEH.mjs +146 -0
  79. package/dist/client/chunk-FGUIVT2B.mjs +204 -0
  80. package/dist/client/chunk-I2MMZO53.mjs +6 -0
  81. package/dist/client/chunk-II7O4XN3.mjs +2206 -0
  82. package/dist/client/chunk-J227A3CQ.mjs +245 -0
  83. package/dist/client/chunk-JEZECJ3W.mjs +383 -0
  84. package/dist/client/chunk-M3L3KYYR.mjs +1181 -0
  85. package/dist/client/chunk-OJPZEZU2.mjs +31 -0
  86. package/dist/client/chunk-PFBX3IQL.mjs +1378 -0
  87. package/dist/client/chunk-RTZ3JKKX.mjs +178 -0
  88. package/dist/client/chunk-SNSWVZEP.mjs +5592 -0
  89. package/dist/client/chunk-TQ5MSPDX.mjs +74 -0
  90. package/dist/client/chunk-YLMKMCSJ.mjs +86 -0
  91. package/dist/client/client.mjs +54052 -54518
  92. package/dist/client/courseRegistration-ZBXS7VGI.mjs +1737 -0
  93. package/dist/client/{eventCalendar-X6GIPYFM.mjs → eventCalendar-EQQZHJBA.mjs} +13 -2
  94. package/dist/client/{eventCombined-EZUOPM3G.mjs → eventCombined-JCFTGBFQ.mjs} +13 -2
  95. package/dist/client/eventDetails-HLUTQSYY.mjs +25 -0
  96. package/dist/client/{eventListing-HEFGAETC.mjs → eventListing-FG4MICVB.mjs} +13 -2
  97. package/dist/client/{eventRegistration-3LCP2V3P.mjs → eventRegistration-GUEB7LBT.mjs} +13 -2
  98. package/dist/client/form-YQEW4YIT.mjs +300 -0
  99. package/dist/client/headerSection-GTR3TTRM.mjs +729 -0
  100. package/dist/client/hooks.mjs +49 -33
  101. package/dist/client/locationMap-SPC7VGUH.mjs +227 -0
  102. package/dist/client/newsletterForm-4IW5BLID.mjs +208 -0
  103. package/dist/client/productDetail-KP5H2WJO.mjs +18 -0
  104. package/dist/client/productList-3M3M72XZ.mjs +18 -0
  105. package/dist/client/rendering/client.mjs +15580 -16277
  106. package/dist/client/rendering/islands.mjs +98 -21
  107. package/dist/client/rendering.mjs +48730 -49191
  108. package/dist/client/shop-ACQKVGOM.mjs +20 -0
  109. package/dist/preview-next/before-render.mjs +37 -25
  110. package/dist/preview-next/chrome.css +1 -1
  111. package/dist/preview-next/client/runtime.mjs +5 -5
  112. package/dist/preview-next/editor-base.css +2 -148
  113. package/dist/preview-next/editor-chrome.css +179 -0
  114. package/dist/preview-next/middleware.mjs +37 -25
  115. package/dist/{sdk-runtime-OHNONZ5U.mjs → sdk-runtime-K7HNB4U2.mjs} +6 -6
  116. package/dist/server/components.mjs +1294 -1103
  117. package/dist/server/config-validation.mjs +49 -33
  118. package/dist/server/config.mjs +49 -33
  119. package/dist/server/data.mjs +49 -33
  120. package/dist/server/index.mjs +45 -33
  121. package/dist/server/next.mjs +1240 -1050
  122. package/dist/server/page-converter.mjs +12 -8
  123. package/dist/server/prebuild.mjs +1 -1
  124. package/dist/server/rendering/server.mjs +1389 -1104
  125. package/dist/server/rendering.mjs +1300 -1109
  126. package/dist/server/routing.mjs +49 -33
  127. package/dist/server/server.mjs +50 -34
  128. package/dist/server/theme-bridge.mjs +5 -0
  129. package/dist/styles/index.css +5 -0
  130. package/package.json +2 -1
  131. package/dist/SdkPreviewModeRuntime-CRYNDSPL.mjs +0 -8
  132. package/dist/client/bookingForm-4X77HKDS.mjs +0 -34
  133. package/dist/client/cart-JWD2VRFU.mjs +0 -11
  134. package/dist/client/checkout-V7KYGWL7.mjs +0 -11
  135. package/dist/client/chunk-5IYGMTUE.mjs +0 -18614
  136. package/dist/client/chunk-RKCFVIMS.mjs +0 -26
  137. package/dist/client/courseRegistration-O6ZPK4YT.mjs +0 -29
  138. package/dist/client/eventDetails-3WODIXET.mjs +0 -14
  139. package/dist/client/form-AKXQMY6Z.mjs +0 -85
  140. package/dist/client/headerSection-5KHCMU6B.mjs +0 -12
  141. package/dist/client/locationMap-7HIADW76.mjs +0 -14
  142. package/dist/client/newsletterForm-5N4YTMU3.mjs +0 -60
  143. package/dist/client/productDetail-IZUA7ZP3.mjs +0 -11
  144. package/dist/client/productList-KWIIJE6I.mjs +0 -11
  145. package/dist/client/shop-XZQFRQWZ.mjs +0 -13
@@ -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 };
@@ -0,0 +1,204 @@
1
+ "use client";
2
+ import { useBlockApi, BlockApiError } from './chunk-M3L3KYYR.mjs';
3
+ import { themeButtonClassName } from './chunk-7UOSCYY4.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,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 };