@riverbankcms/sdk 0.72.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 (146) hide show
  1. package/README.md +1 -1
  2. package/dist/{PreviewEditorSidebar-44T64SAR.mjs → PreviewEditorSidebar-U2IHCBYN.mjs} +3 -3
  3. package/dist/{PreviewEditorUI-4WKHZTXW.mjs → PreviewEditorUI-ZGH2RQNP.mjs} +3 -3
  4. package/dist/SdkPreviewModeRuntime-MTUGBTLQ.mjs +8 -0
  5. package/dist/_dts/ai/src/contracts/proposals.d.ts +10 -10
  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/publicExperienceEndpoints.d.ts +2 -1
  10. package/dist/_dts/block-form/src/blockDraftSaveability.d.ts +4 -1
  11. package/dist/_dts/blocks/src/client/booking-form.d.ts +2 -0
  12. package/dist/_dts/blocks/src/client/carousel.d.ts +1 -0
  13. package/dist/_dts/blocks/src/client/course-registration.d.ts +2 -0
  14. package/dist/_dts/blocks/src/client/events.d.ts +4 -0
  15. package/dist/_dts/blocks/src/client/form.d.ts +2 -0
  16. package/dist/_dts/blocks/src/client/header.d.ts +1 -0
  17. package/dist/_dts/blocks/src/client/location-map.d.ts +1 -0
  18. package/dist/_dts/blocks/src/client/newsletter-form.d.ts +2 -0
  19. package/dist/_dts/blocks/src/client/shop.d.ts +6 -0
  20. package/dist/_dts/blocks/src/lib/video.d.ts +2 -0
  21. package/dist/_dts/blocks/src/system/manifest/fieldValidation/index.d.ts +21 -1
  22. package/dist/_dts/blocks/src/system/manifest/schema.d.ts +6 -6
  23. package/dist/_dts/blocks/src/system/node/fragments/backgroundLayer.d.ts +15 -1
  24. package/dist/_dts/blocks/src/system/node/fragments/styledSection.d.ts +11 -0
  25. package/dist/_dts/blocks/src/system/runtime/components/registry.client.d.ts +1 -0
  26. package/dist/_dts/blocks/src/system/runtime/header/enhanceHeaderSection.d.ts +13 -0
  27. package/dist/_dts/blocks/src/system/runtime/nodes/booking-form.headless.state.d.ts +3 -2
  28. package/dist/_dts/blocks/src/system/runtime/nodes/events/index.d.ts +3 -0
  29. package/dist/_dts/blocks/src/system/runtime/nodes/header-section.client.d.ts +1 -0
  30. package/dist/_dts/blocks/src/system/runtime/nodes/header-section.server.d.ts +1 -0
  31. package/dist/_dts/blocks/src/system/runtime/nodes/media.d.ts +6 -0
  32. package/dist/_dts/content-editor/src/hooks/validateBlocksForPublish.d.ts +5 -0
  33. package/dist/_dts/preview-next/src/client/preview/SiteChromeEditableSurface.d.ts +12 -2
  34. package/dist/_dts/sdk/src/public-api/contracts.d.ts +1 -0
  35. package/dist/_dts/sdk/src/rendering/components/Layout.d.ts +2 -2
  36. package/dist/_dts/sdk/src/rendering/islands/deferredVideoEmbeds.d.ts +2 -0
  37. package/dist/_dts/sdk/src/rendering/islands/enhancers/accordion.d.ts +1 -0
  38. package/dist/_dts/sdk/src/rendering/islands/enhancers/bookingForm.d.ts +1 -0
  39. package/dist/_dts/sdk/src/rendering/islands/enhancers/carousel.d.ts +1 -0
  40. package/dist/_dts/sdk/src/rendering/islands/enhancers/cart.d.ts +1 -0
  41. package/dist/_dts/sdk/src/rendering/islands/enhancers/checkout.d.ts +1 -0
  42. package/dist/_dts/sdk/src/rendering/islands/enhancers/courseRegistration.d.ts +1 -0
  43. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventCalendar.d.ts +1 -0
  44. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventCombined.d.ts +1 -0
  45. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventDetails.d.ts +1 -0
  46. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventListing.d.ts +1 -0
  47. package/dist/_dts/sdk/src/rendering/islands/enhancers/eventRegistration.d.ts +1 -0
  48. package/dist/_dts/sdk/src/rendering/islands/enhancers/form.d.ts +1 -0
  49. package/dist/_dts/sdk/src/rendering/islands/enhancers/headerSection.d.ts +1 -0
  50. package/dist/_dts/sdk/src/rendering/islands/enhancers/locationMap.d.ts +1 -0
  51. package/dist/_dts/sdk/src/rendering/islands/enhancers/newsletterForm.d.ts +1 -0
  52. package/dist/_dts/sdk/src/rendering/islands/enhancers/productDetail.d.ts +1 -0
  53. package/dist/_dts/sdk/src/rendering/islands/enhancers/productList.d.ts +1 -0
  54. package/dist/_dts/sdk/src/rendering/islands/enhancers/shop.d.ts +1 -0
  55. package/dist/_dts/sdk/src/rendering/islands/hydrateBlocksIslands.d.ts +2 -2
  56. package/dist/_dts/sdk/src/rendering/islands/propsDecoder.d.ts +7 -0
  57. package/dist/_dts/sdk/src/rendering/islands/types.d.ts +9 -0
  58. package/dist/_dts/sdk/src/rendering/server.d.ts +3 -0
  59. package/dist/_dts/sdk/src/version.d.ts +1 -1
  60. package/dist/_dts/theme-core/src/accordions/types.d.ts +3 -3
  61. package/dist/_dts/theme-core/src/buttons/personalities/types.d.ts +7 -7
  62. package/dist/_dts/theme-core/src/buttons/types.d.ts +20 -20
  63. package/dist/_dts/theme-core/src/cards/types.d.ts +2 -2
  64. package/dist/_dts/theme-core/src/generated/containerResponsiveThemeCss.d.ts +1 -1
  65. package/dist/_dts/theme-core/src/header/navDropdownSizing.d.ts +7 -0
  66. package/dist/_dts/theme-core/src/inputs/types.d.ts +3 -3
  67. package/dist/_dts/theme-core/src/interactive/baseSchema.d.ts +1 -1
  68. package/dist/_dts/theme-core/src/mock-themes/all.d.ts +156 -156
  69. package/dist/_dts/theme-core/src/navigation/types.d.ts +1 -1
  70. package/dist/_dts/theme-core/src/palette/variants/types.d.ts +4 -4
  71. package/dist/_dts/theme-core/src/schema.d.ts +178 -178
  72. package/dist/_dts/theme-core/src/shared/componentStyles.d.ts +2 -2
  73. package/dist/_dts/theme-core/src/site-styles/designState.d.ts +8 -8
  74. package/dist/_dts/theme-core/src/site-styles/generatedSchemas.d.ts +5 -5
  75. package/dist/_dts/theme-core/src/tokens/themeColorTokens.d.ts +2 -2
  76. package/dist/{chunk-G4NLITC2.mjs → chunk-BGMNDF6T.mjs} +7 -7
  77. package/dist/{chunk-3YNCQG5N.mjs → chunk-GFE74WRD.mjs} +457 -98
  78. package/dist/{chunk-HV745JYE.mjs → chunk-RWXQBRQZ.mjs} +1 -1
  79. package/dist/{chunk-7RX72SK2.mjs → chunk-VX7B5VAC.mjs} +36 -25
  80. package/dist/{chunk-YRJKZEQ3.mjs → chunk-Z7JLNTJR.mjs} +1 -1
  81. package/dist/{chunk-KWQPAJYS.mjs → chunk-ZSHFGFUG.mjs} +2 -2
  82. package/dist/cli/index.mjs +3498 -3826
  83. package/dist/client/accordion-T2UD2ZTH.mjs +120 -0
  84. package/dist/client/altcha-LIGLPZS5.mjs +2755 -0
  85. package/dist/client/bookingForm-GUP75FKN.mjs +3022 -0
  86. package/dist/client/bookings.mjs +32 -10
  87. package/dist/client/carousel-2NQA6V57.mjs +47 -0
  88. package/dist/client/cart-5TFIAFDS.mjs +18 -0
  89. package/dist/client/checkout-TP4WAHZE.mjs +18 -0
  90. package/dist/client/chunk-2PHQZ666.mjs +383 -0
  91. package/dist/client/chunk-3DCJ45Z2.mjs +36 -0
  92. package/dist/client/chunk-3PEDD5KJ.mjs +146 -0
  93. package/dist/client/chunk-CY2ZTSE5.mjs +204 -0
  94. package/dist/client/chunk-F7LHOKEH.mjs +146 -0
  95. package/dist/client/chunk-FU2QRZMX.mjs +7617 -0
  96. package/dist/client/chunk-I2MMZO53.mjs +6 -0
  97. package/dist/client/chunk-II7O4XN3.mjs +2206 -0
  98. package/dist/client/chunk-M3L3KYYR.mjs +1181 -0
  99. package/dist/client/chunk-N7PBWBWQ.mjs +26 -0
  100. package/dist/client/chunk-NWOUL6JY.mjs +1378 -0
  101. package/dist/client/chunk-OJPZEZU2.mjs +31 -0
  102. package/dist/client/chunk-PMAIXMAB.mjs +1960 -0
  103. package/dist/client/chunk-RTZ3JKKX.mjs +178 -0
  104. package/dist/client/chunk-TQ5MSPDX.mjs +74 -0
  105. package/dist/client/chunk-VUAOE3AG.mjs +5592 -0
  106. package/dist/client/chunk-WJXXNDSE.mjs +245 -0
  107. package/dist/client/chunk-YLMKMCSJ.mjs +86 -0
  108. package/dist/client/chunk-ZLMS67RR.mjs +106 -0
  109. package/dist/client/client.mjs +51865 -52071
  110. package/dist/client/courseRegistration-5DPU6PDY.mjs +1737 -0
  111. package/dist/client/eventCalendar-F3GZGTEF.mjs +40 -0
  112. package/dist/client/eventCombined-BQOB6QMY.mjs +37 -0
  113. package/dist/client/eventDetails-PEM2EJWE.mjs +25 -0
  114. package/dist/client/eventListing-YMIQPVME.mjs +40 -0
  115. package/dist/client/eventRegistration-4I6ZNDUF.mjs +40 -0
  116. package/dist/client/form-ZJVAYZ6G.mjs +300 -0
  117. package/dist/client/headerSection-TOT5MGTF.mjs +729 -0
  118. package/dist/client/hooks.mjs +91 -42
  119. package/dist/client/locationMap-J66NZREU.mjs +227 -0
  120. package/dist/client/newsletterForm-ET2XUMRO.mjs +208 -0
  121. package/dist/client/productDetail-C2XIH7C5.mjs +18 -0
  122. package/dist/client/productList-T2AZLFTP.mjs +18 -0
  123. package/dist/client/rendering/client.mjs +12796 -18295
  124. package/dist/client/rendering/islands.mjs +108 -44022
  125. package/dist/client/rendering.mjs +45141 -45346
  126. package/dist/client/shop-UZ6IUZXD.mjs +20 -0
  127. package/dist/preview-next/before-render.mjs +37 -25
  128. package/dist/preview-next/client/runtime.mjs +5 -5
  129. package/dist/preview-next/middleware.mjs +37 -25
  130. package/dist/{sdk-runtime-NGDWSWOS.mjs → sdk-runtime-JCUQM63Y.mjs} +6 -6
  131. package/dist/server/components.mjs +472 -276
  132. package/dist/server/config-validation.mjs +91 -42
  133. package/dist/server/config.mjs +91 -42
  134. package/dist/server/data.mjs +91 -42
  135. package/dist/server/index.mjs +45 -33
  136. package/dist/server/next.mjs +468 -272
  137. package/dist/server/page-converter.mjs +41 -17
  138. package/dist/server/prebuild.mjs +1 -1
  139. package/dist/server/rendering/server.mjs +556 -275
  140. package/dist/server/rendering.mjs +474 -278
  141. package/dist/server/routing.mjs +99 -43
  142. package/dist/server/server.mjs +92 -43
  143. package/dist/server/theme-bridge.mjs +29 -0
  144. package/dist/styles/index.css +16 -0
  145. package/package.json +2 -1
  146. package/dist/SdkPreviewModeRuntime-FO6V7YVY.mjs +0 -8
@@ -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 };