@neowhale/storefront 0.2.35 → 0.2.36
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/landing.global.js +352 -471
- package/dist/react/index.cjs +343 -470
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +9 -0
- package/dist/react/index.d.ts +9 -0
- package/dist/react/index.js +343 -470
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
package/dist/react/index.js
CHANGED
|
@@ -2133,7 +2133,18 @@ function useReferral() {
|
|
|
2133
2133
|
referredBy: status?.referred_by ?? null
|
|
2134
2134
|
};
|
|
2135
2135
|
}
|
|
2136
|
-
|
|
2136
|
+
function trackClick(tracking, label, url, position) {
|
|
2137
|
+
if (!tracking?.gatewayUrl || !tracking?.code) return;
|
|
2138
|
+
const body = JSON.stringify({ label, url, position });
|
|
2139
|
+
if (typeof navigator !== "undefined" && navigator.sendBeacon) {
|
|
2140
|
+
navigator.sendBeacon(
|
|
2141
|
+
`${tracking.gatewayUrl}/q/${encodeURIComponent(tracking.code)}/click`,
|
|
2142
|
+
new Blob([body], { type: "application/json" })
|
|
2143
|
+
);
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
var NUM_SPLIT = /(\$?[\d,]+\.?\d*[+★%]?)/g;
|
|
2147
|
+
var NUM_TEST = /^\$?[\d,]+\.?\d*[+★%]?$/;
|
|
2137
2148
|
function easeOutQuart(t) {
|
|
2138
2149
|
return 1 - Math.pow(1 - t, 4);
|
|
2139
2150
|
}
|
|
@@ -2190,147 +2201,69 @@ function AnimatedNumber({ raw }) {
|
|
|
2190
2201
|
] });
|
|
2191
2202
|
}
|
|
2192
2203
|
function AnimatedText({ text }) {
|
|
2193
|
-
const parts = text.split(
|
|
2204
|
+
const parts = text.split(NUM_SPLIT);
|
|
2194
2205
|
return /* @__PURE__ */ jsx(Fragment, { children: parts.map(
|
|
2195
|
-
(part, i) =>
|
|
2206
|
+
(part, i) => NUM_TEST.test(part) ? /* @__PURE__ */ jsx(AnimatedNumber, { raw: part }, i) : part
|
|
2196
2207
|
) });
|
|
2197
2208
|
}
|
|
2198
|
-
function trackClick(tracking, label, url, position) {
|
|
2199
|
-
if (!tracking?.gatewayUrl || !tracking?.code) return;
|
|
2200
|
-
const body = JSON.stringify({ label, url, position });
|
|
2201
|
-
if (typeof navigator !== "undefined" && navigator.sendBeacon) {
|
|
2202
|
-
navigator.sendBeacon(
|
|
2203
|
-
`${tracking.gatewayUrl}/q/${encodeURIComponent(tracking.code)}/click`,
|
|
2204
|
-
new Blob([body], { type: "application/json" })
|
|
2205
|
-
);
|
|
2206
|
-
}
|
|
2207
|
-
}
|
|
2208
|
-
function SectionRenderer({
|
|
2209
|
-
section,
|
|
2210
|
-
data,
|
|
2211
|
-
theme,
|
|
2212
|
-
tracking,
|
|
2213
|
-
onEvent
|
|
2214
|
-
}) {
|
|
2215
|
-
const [showCOA, setShowCOA] = useState(false);
|
|
2216
|
-
const el = (() => {
|
|
2217
|
-
switch (section.type) {
|
|
2218
|
-
case "hero":
|
|
2219
|
-
return /* @__PURE__ */ jsx(HeroSection, { section, theme, tracking, onEvent });
|
|
2220
|
-
case "text":
|
|
2221
|
-
return /* @__PURE__ */ jsx(TextSection, { section, theme });
|
|
2222
|
-
case "image":
|
|
2223
|
-
return /* @__PURE__ */ jsx(ImageSection, { section, theme });
|
|
2224
|
-
case "video":
|
|
2225
|
-
return /* @__PURE__ */ jsx(VideoSection, { section, theme });
|
|
2226
|
-
case "gallery":
|
|
2227
|
-
return /* @__PURE__ */ jsx(GallerySection, { section, theme });
|
|
2228
|
-
case "cta":
|
|
2229
|
-
return /* @__PURE__ */ jsx(CTASection, { section, theme, tracking, onEvent });
|
|
2230
|
-
case "stats":
|
|
2231
|
-
return /* @__PURE__ */ jsx(StatsSection, { section, theme });
|
|
2232
|
-
case "product_card":
|
|
2233
|
-
return /* @__PURE__ */ jsx(ProductCardSection, { section, data, theme, tracking });
|
|
2234
|
-
case "coa_viewer":
|
|
2235
|
-
return /* @__PURE__ */ jsx(COAViewerSection, { section, data, theme, onShowCOA: () => setShowCOA(true), tracking });
|
|
2236
|
-
case "social_links":
|
|
2237
|
-
return /* @__PURE__ */ jsx(SocialLinksSection, { section, theme });
|
|
2238
|
-
case "lead_capture":
|
|
2239
|
-
return /* @__PURE__ */ jsx(LeadCaptureSection, { section, data, theme, onEvent });
|
|
2240
|
-
case "divider":
|
|
2241
|
-
return /* @__PURE__ */ jsx(DividerSection, { theme });
|
|
2242
|
-
default:
|
|
2243
|
-
return null;
|
|
2244
|
-
}
|
|
2245
|
-
})();
|
|
2246
|
-
const sectionRef = useRef(null);
|
|
2247
|
-
useEffect(() => {
|
|
2248
|
-
const el2 = sectionRef.current;
|
|
2249
|
-
if (!el2 || typeof IntersectionObserver === "undefined") return;
|
|
2250
|
-
const obs = new IntersectionObserver(
|
|
2251
|
-
([entry]) => {
|
|
2252
|
-
if (entry.isIntersecting) {
|
|
2253
|
-
onEvent?.("section_view", {
|
|
2254
|
-
section_id: section.id,
|
|
2255
|
-
section_type: section.type
|
|
2256
|
-
});
|
|
2257
|
-
obs.disconnect();
|
|
2258
|
-
}
|
|
2259
|
-
},
|
|
2260
|
-
{ threshold: 0.5 }
|
|
2261
|
-
);
|
|
2262
|
-
obs.observe(el2);
|
|
2263
|
-
return () => obs.disconnect();
|
|
2264
|
-
}, [section.id, section.type, onEvent]);
|
|
2265
|
-
return /* @__PURE__ */ jsxs("div", { ref: sectionRef, "data-section-id": section.id, "data-section-type": section.type, children: [
|
|
2266
|
-
el,
|
|
2267
|
-
showCOA && data?.coa && /* @__PURE__ */ jsx(COAModal, { coa: data.coa, theme, onClose: () => setShowCOA(false) })
|
|
2268
|
-
] });
|
|
2269
|
-
}
|
|
2270
2209
|
function HeroSection({ section, theme, tracking, onEvent }) {
|
|
2271
2210
|
const { title, subtitle, background_image, cta_text, cta_url } = section.content;
|
|
2272
|
-
return /* @__PURE__ */ jsxs(
|
|
2273
|
-
"
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2211
|
+
return /* @__PURE__ */ jsxs("div", { style: {
|
|
2212
|
+
position: "relative",
|
|
2213
|
+
minHeight: "60vh",
|
|
2214
|
+
display: "flex",
|
|
2215
|
+
flexDirection: "column",
|
|
2216
|
+
justifyContent: "center",
|
|
2217
|
+
alignItems: "center",
|
|
2218
|
+
textAlign: "center",
|
|
2219
|
+
padding: "3rem 1.5rem",
|
|
2220
|
+
backgroundImage: background_image ? `url(${background_image})` : void 0,
|
|
2221
|
+
backgroundSize: "cover",
|
|
2222
|
+
backgroundPosition: "center"
|
|
2223
|
+
}, children: [
|
|
2224
|
+
background_image && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: "rgba(0,0,0,0.5)" } }),
|
|
2225
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative", zIndex: 1, maxWidth: 640 }, children: [
|
|
2226
|
+
title && /* @__PURE__ */ jsx("h1", { style: {
|
|
2227
|
+
fontSize: "clamp(2rem, 8vw, 3rem)",
|
|
2228
|
+
fontWeight: 300,
|
|
2229
|
+
fontFamily: theme.fontDisplay || "inherit",
|
|
2230
|
+
margin: "0 0 1rem",
|
|
2231
|
+
lineHeight: 1.15,
|
|
2232
|
+
letterSpacing: "-0.02em",
|
|
2233
|
+
color: theme.fg
|
|
2234
|
+
}, children: /* @__PURE__ */ jsx(AnimatedText, { text: title }) }),
|
|
2235
|
+
subtitle && /* @__PURE__ */ jsx("p", { style: {
|
|
2236
|
+
fontSize: "0.85rem",
|
|
2237
|
+
color: theme.accent,
|
|
2238
|
+
margin: "0 0 2rem",
|
|
2239
|
+
lineHeight: 1.6,
|
|
2240
|
+
textTransform: "uppercase",
|
|
2241
|
+
letterSpacing: "0.15em"
|
|
2242
|
+
}, children: subtitle }),
|
|
2243
|
+
cta_text && cta_url && /* @__PURE__ */ jsx(
|
|
2244
|
+
"a",
|
|
2245
|
+
{
|
|
2246
|
+
href: cta_url,
|
|
2247
|
+
onClick: () => {
|
|
2248
|
+
trackClick(tracking, cta_text, cta_url);
|
|
2249
|
+
onEvent?.("cta_click", { label: cta_text, url: cta_url });
|
|
2250
|
+
},
|
|
2251
|
+
style: {
|
|
2252
|
+
display: "inline-block",
|
|
2253
|
+
padding: "0.875rem 2rem",
|
|
2254
|
+
background: theme.fg,
|
|
2255
|
+
color: theme.bg,
|
|
2256
|
+
textDecoration: "none",
|
|
2301
2257
|
fontSize: "0.85rem",
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
href: cta_url,
|
|
2312
|
-
onClick: () => {
|
|
2313
|
-
trackClick(tracking, cta_text, cta_url);
|
|
2314
|
-
onEvent?.("cta_click", { label: cta_text, url: cta_url });
|
|
2315
|
-
},
|
|
2316
|
-
style: {
|
|
2317
|
-
display: "inline-block",
|
|
2318
|
-
padding: "0.875rem 2rem",
|
|
2319
|
-
background: theme.fg,
|
|
2320
|
-
color: theme.bg,
|
|
2321
|
-
textDecoration: "none",
|
|
2322
|
-
fontSize: "0.85rem",
|
|
2323
|
-
fontWeight: 500,
|
|
2324
|
-
letterSpacing: "0.08em",
|
|
2325
|
-
textTransform: "uppercase"
|
|
2326
|
-
},
|
|
2327
|
-
children: cta_text
|
|
2328
|
-
}
|
|
2329
|
-
)
|
|
2330
|
-
] })
|
|
2331
|
-
]
|
|
2332
|
-
}
|
|
2333
|
-
);
|
|
2258
|
+
fontWeight: 500,
|
|
2259
|
+
letterSpacing: "0.08em",
|
|
2260
|
+
textTransform: "uppercase"
|
|
2261
|
+
},
|
|
2262
|
+
children: cta_text
|
|
2263
|
+
}
|
|
2264
|
+
)
|
|
2265
|
+
] })
|
|
2266
|
+
] });
|
|
2334
2267
|
}
|
|
2335
2268
|
function TextSection({ section, theme }) {
|
|
2336
2269
|
const { heading, body } = section.content;
|
|
@@ -2352,14 +2285,7 @@ function ImageSection({ section, theme }) {
|
|
|
2352
2285
|
const contained = section.config?.contained !== false;
|
|
2353
2286
|
if (!url) return null;
|
|
2354
2287
|
return /* @__PURE__ */ jsxs("div", { style: { padding: contained ? "1.5rem" : 0, maxWidth: contained ? 640 : void 0, margin: contained ? "0 auto" : void 0 }, children: [
|
|
2355
|
-
/* @__PURE__ */ jsx(
|
|
2356
|
-
"img",
|
|
2357
|
-
{
|
|
2358
|
-
src: url,
|
|
2359
|
-
alt: alt || "",
|
|
2360
|
-
style: { width: "100%", display: "block", objectFit: "cover" }
|
|
2361
|
-
}
|
|
2362
|
-
),
|
|
2288
|
+
/* @__PURE__ */ jsx("img", { src: url, alt: alt || "", style: { width: "100%", display: "block", objectFit: "cover" } }),
|
|
2363
2289
|
caption && /* @__PURE__ */ jsx("p", { style: { fontSize: "0.8rem", color: theme.muted, textAlign: "center", marginTop: "0.75rem" }, children: caption })
|
|
2364
2290
|
] });
|
|
2365
2291
|
}
|
|
@@ -2367,36 +2293,38 @@ function VideoSection({ section, theme }) {
|
|
|
2367
2293
|
const { url, poster } = section.content;
|
|
2368
2294
|
if (!url) return null;
|
|
2369
2295
|
const isEmbed = url.includes("youtube") || url.includes("youtu.be") || url.includes("vimeo");
|
|
2370
|
-
return /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", maxWidth: 640, margin: "0 auto" }, children: isEmbed ? /* @__PURE__ */ jsx("div", { style: { position: "relative", paddingBottom: "56.25%", height: 0 }, children: /* @__PURE__ */ jsx(
|
|
2371
|
-
"iframe",
|
|
2372
|
-
{
|
|
2373
|
-
src: toEmbedUrl(url),
|
|
2374
|
-
style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%", border: "none" },
|
|
2375
|
-
allow: "autoplay; fullscreen",
|
|
2376
|
-
title: "Video"
|
|
2377
|
-
}
|
|
2378
|
-
) }) : /* @__PURE__ */ jsx(
|
|
2379
|
-
"video",
|
|
2380
|
-
{
|
|
2381
|
-
src: url,
|
|
2382
|
-
poster,
|
|
2383
|
-
controls: true,
|
|
2384
|
-
style: { width: "100%", display: "block", background: theme.surface }
|
|
2385
|
-
}
|
|
2386
|
-
) });
|
|
2296
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", maxWidth: 640, margin: "0 auto" }, children: isEmbed ? /* @__PURE__ */ jsx("div", { style: { position: "relative", paddingBottom: "56.25%", height: 0 }, children: /* @__PURE__ */ jsx("iframe", { src: toEmbedUrl(url), style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%", border: "none" }, allow: "autoplay; fullscreen", title: "Video" }) }) : /* @__PURE__ */ jsx("video", { src: url, poster, controls: true, style: { width: "100%", display: "block", background: theme.surface } }) });
|
|
2387
2297
|
}
|
|
2388
2298
|
function GallerySection({ section, theme }) {
|
|
2389
2299
|
const { images } = section.content;
|
|
2390
2300
|
const columns = section.config?.columns || 3;
|
|
2391
2301
|
if (!images || images.length === 0) return null;
|
|
2392
|
-
return /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", maxWidth: 800, margin: "0 auto" }, children: /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: `repeat(${columns}, 1fr)`, gap: "0.5rem" }, children: images.map((img, i) => /* @__PURE__ */ jsx("div", { style: { aspectRatio: "1", overflow: "hidden", background: theme.surface }, children: /* @__PURE__ */ jsx(
|
|
2393
|
-
|
|
2302
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", maxWidth: 800, margin: "0 auto" }, children: /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: `repeat(${columns}, 1fr)`, gap: "0.5rem" }, children: images.map((img, i) => /* @__PURE__ */ jsx("div", { style: { aspectRatio: "1", overflow: "hidden", background: theme.surface }, children: /* @__PURE__ */ jsx("img", { src: img.url, alt: img.alt || "", style: { width: "100%", height: "100%", objectFit: "cover", display: "block" } }) }, i)) }) });
|
|
2303
|
+
}
|
|
2304
|
+
function SocialLinksSection({ section, theme }) {
|
|
2305
|
+
const { links } = section.content;
|
|
2306
|
+
if (!links || links.length === 0) return null;
|
|
2307
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", display: "flex", justifyContent: "center", gap: "1.5rem", flexWrap: "wrap" }, children: links.map((link, i) => /* @__PURE__ */ jsx(
|
|
2308
|
+
"a",
|
|
2394
2309
|
{
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2310
|
+
href: link.url,
|
|
2311
|
+
target: "_blank",
|
|
2312
|
+
rel: "noopener noreferrer",
|
|
2313
|
+
style: { color: theme.muted, textDecoration: "none", fontSize: "0.85rem", fontWeight: 500, textTransform: "capitalize", letterSpacing: "0.03em" },
|
|
2314
|
+
children: link.platform
|
|
2315
|
+
},
|
|
2316
|
+
i
|
|
2317
|
+
)) });
|
|
2318
|
+
}
|
|
2319
|
+
function DividerSection({ theme }) {
|
|
2320
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "1rem 1.5rem", maxWidth: 640, margin: "0 auto" }, children: /* @__PURE__ */ jsx("hr", { style: { border: "none", borderTop: `1px solid ${theme.fg}0A`, margin: 0 } }) });
|
|
2321
|
+
}
|
|
2322
|
+
function toEmbedUrl(url) {
|
|
2323
|
+
const ytMatch = url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([\w-]+)/);
|
|
2324
|
+
if (ytMatch) return `https://www.youtube.com/embed/${ytMatch[1]}`;
|
|
2325
|
+
const vimeoMatch = url.match(/vimeo\.com\/(\d+)/);
|
|
2326
|
+
if (vimeoMatch) return `https://player.vimeo.com/video/${vimeoMatch[1]}`;
|
|
2327
|
+
return url;
|
|
2400
2328
|
}
|
|
2401
2329
|
function CTASection({ section, theme, tracking, onEvent }) {
|
|
2402
2330
|
const { title, subtitle, buttons } = section.content;
|
|
@@ -2459,29 +2387,15 @@ function StatsSection({ section, theme }) {
|
|
|
2459
2387
|
if (!stats || stats.length === 0) return null;
|
|
2460
2388
|
if (layout === "list") {
|
|
2461
2389
|
return /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", maxWidth: 640, margin: "0 auto" }, children: stats.map((stat, i) => /* @__PURE__ */ jsxs("div", { children: [
|
|
2462
|
-
/* @__PURE__ */ jsxs("div", { style: {
|
|
2463
|
-
|
|
2464
|
-
justifyContent: "space-between",
|
|
2465
|
-
alignItems: "baseline",
|
|
2466
|
-
padding: "0.625rem 0"
|
|
2467
|
-
}, children: [
|
|
2468
|
-
/* @__PURE__ */ jsx("span", { style: {
|
|
2469
|
-
fontSize: 12,
|
|
2470
|
-
textTransform: "uppercase",
|
|
2471
|
-
letterSpacing: "0.15em",
|
|
2472
|
-
color: `${theme.fg}66`
|
|
2473
|
-
}, children: stat.label }),
|
|
2390
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "baseline", padding: "0.625rem 0" }, children: [
|
|
2391
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 12, textTransform: "uppercase", letterSpacing: "0.15em", color: `${theme.fg}66` }, children: stat.label }),
|
|
2474
2392
|
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, fontWeight: 300, color: `${theme.fg}CC` }, children: /* @__PURE__ */ jsx(AnimatedText, { text: stat.value }) })
|
|
2475
2393
|
] }),
|
|
2476
2394
|
i < stats.length - 1 && /* @__PURE__ */ jsx("hr", { style: { border: "none", borderTop: `1px solid ${theme.fg}0A`, margin: 0 } })
|
|
2477
2395
|
] }, i)) });
|
|
2478
2396
|
}
|
|
2479
2397
|
const columns = Math.min(stats.length, 4);
|
|
2480
|
-
return /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", maxWidth: 640, margin: "0 auto" }, children: /* @__PURE__ */ jsx("div", { style: {
|
|
2481
|
-
display: "grid",
|
|
2482
|
-
gridTemplateColumns: `repeat(${columns}, 1fr)`,
|
|
2483
|
-
border: `1px solid ${theme.fg}0F`
|
|
2484
|
-
}, children: stats.map((stat, i) => /* @__PURE__ */ jsxs("div", { style: {
|
|
2398
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", maxWidth: 640, margin: "0 auto" }, children: /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: `repeat(${columns}, 1fr)`, border: `1px solid ${theme.fg}0F` }, children: stats.map((stat, i) => /* @__PURE__ */ jsxs("div", { style: {
|
|
2485
2399
|
padding: "1.25rem 0.5rem",
|
|
2486
2400
|
textAlign: "center",
|
|
2487
2401
|
borderRight: i < stats.length - 1 ? `1px solid ${theme.fg}0F` : void 0
|
|
@@ -2540,13 +2454,7 @@ function ProductCardSection({ section, data, theme, tracking }) {
|
|
|
2540
2454
|
] })
|
|
2541
2455
|
] }) });
|
|
2542
2456
|
}
|
|
2543
|
-
function COAViewerSection({
|
|
2544
|
-
section,
|
|
2545
|
-
data,
|
|
2546
|
-
theme,
|
|
2547
|
-
onShowCOA,
|
|
2548
|
-
tracking
|
|
2549
|
-
}) {
|
|
2457
|
+
function COAViewerSection({ section, data, theme, onShowCOA, tracking }) {
|
|
2550
2458
|
const coa = data?.coa;
|
|
2551
2459
|
const c = section.content;
|
|
2552
2460
|
if (!coa) return null;
|
|
@@ -2585,6 +2493,28 @@ function COAViewerSection({
|
|
|
2585
2493
|
onShowCOA();
|
|
2586
2494
|
}, style: buttonStyle, children: buttonLabel }) });
|
|
2587
2495
|
}
|
|
2496
|
+
function COAModal({ coa, theme, onClose }) {
|
|
2497
|
+
return /* @__PURE__ */ jsxs("div", { style: { position: "fixed", inset: 0, zIndex: 9999, background: "rgba(0,0,0,0.95)", display: "flex", flexDirection: "column" }, children: [
|
|
2498
|
+
/* @__PURE__ */ jsxs("div", { style: {
|
|
2499
|
+
display: "flex",
|
|
2500
|
+
justifyContent: "space-between",
|
|
2501
|
+
alignItems: "center",
|
|
2502
|
+
padding: "0.75rem 1rem",
|
|
2503
|
+
borderBottom: `1px solid ${theme.fg}10`
|
|
2504
|
+
}, children: [
|
|
2505
|
+
/* @__PURE__ */ jsx("span", { style: { color: "#fff", fontWeight: 500, fontSize: "0.85rem" }, children: coa.document_name || "Lab Results" }),
|
|
2506
|
+
/* @__PURE__ */ jsx("button", { onClick: onClose, style: {
|
|
2507
|
+
background: `${theme.fg}10`,
|
|
2508
|
+
border: "none",
|
|
2509
|
+
color: "#fff",
|
|
2510
|
+
fontSize: "0.85rem",
|
|
2511
|
+
cursor: "pointer",
|
|
2512
|
+
padding: "0.375rem 0.75rem"
|
|
2513
|
+
}, children: "Close" })
|
|
2514
|
+
] }),
|
|
2515
|
+
/* @__PURE__ */ jsx("iframe", { src: coa.url, style: { flex: 1, border: "none", background: "#fff" }, title: "Lab Results" })
|
|
2516
|
+
] });
|
|
2517
|
+
}
|
|
2588
2518
|
function LeadCaptureSection({ section, data, theme, onEvent }) {
|
|
2589
2519
|
const c = section.content;
|
|
2590
2520
|
const [firstName, setFirstName] = useState("");
|
|
@@ -2595,13 +2525,17 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
|
|
|
2595
2525
|
const gatewayUrl = c.gateway_url || data.gatewayUrl || "https://whale-gateway.fly.dev";
|
|
2596
2526
|
const storeId = c.store_id || data.store?.id;
|
|
2597
2527
|
const slug = c.landing_page_slug || data.landing_page?.slug;
|
|
2528
|
+
const heading = c.heading || "get 10% off your first visit.";
|
|
2529
|
+
const subtitle = c.subtitle || "drop your email and we will send you the code.";
|
|
2530
|
+
const buttonText = c.button_text || "Claim My Discount";
|
|
2531
|
+
const successHeading = c.success_heading || "You\u2019re in!";
|
|
2532
|
+
const successMessage = c.success_message || "Check your inbox for the discount code.";
|
|
2598
2533
|
async function handleSubmit(e) {
|
|
2599
2534
|
e.preventDefault();
|
|
2600
2535
|
if (!email || !storeId) return;
|
|
2601
2536
|
setStatus("loading");
|
|
2602
2537
|
setErrorMsg("");
|
|
2603
2538
|
const urlParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
|
|
2604
|
-
const analyticsData = data.analyticsContext;
|
|
2605
2539
|
try {
|
|
2606
2540
|
const res = await fetch(`${gatewayUrl}/v1/stores/${storeId}/storefront/leads`, {
|
|
2607
2541
|
method: "POST",
|
|
@@ -2617,8 +2551,8 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
|
|
|
2617
2551
|
if (newsletterOptIn) t.push(c.newsletter_tag || "newsletter-subscriber");
|
|
2618
2552
|
return t.length > 0 ? t : void 0;
|
|
2619
2553
|
})(),
|
|
2620
|
-
visitor_id:
|
|
2621
|
-
session_id:
|
|
2554
|
+
visitor_id: data.analyticsContext?.visitorId || void 0,
|
|
2555
|
+
session_id: data.analyticsContext?.sessionId || void 0,
|
|
2622
2556
|
utm_source: urlParams?.get("utm_source") || void 0,
|
|
2623
2557
|
utm_medium: urlParams?.get("utm_medium") || void 0,
|
|
2624
2558
|
utm_campaign: urlParams?.get("utm_campaign") || void 0,
|
|
@@ -2636,11 +2570,6 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
|
|
|
2636
2570
|
setStatus("error");
|
|
2637
2571
|
}
|
|
2638
2572
|
}
|
|
2639
|
-
const heading = c.heading || "get 10% off your first visit.";
|
|
2640
|
-
const subtitle = c.subtitle || "drop your email and we will send you the code.";
|
|
2641
|
-
const buttonText = c.button_text || "Claim My Discount";
|
|
2642
|
-
const successHeading = c.success_heading || "You\u2019re in!";
|
|
2643
|
-
const successMessage = c.success_message || "Check your inbox for the discount code.";
|
|
2644
2573
|
const inputStyle = {
|
|
2645
2574
|
flex: 1,
|
|
2646
2575
|
minWidth: 0,
|
|
@@ -2655,41 +2584,10 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
|
|
|
2655
2584
|
fontFamily: "inherit",
|
|
2656
2585
|
transition: "border-color 0.2s"
|
|
2657
2586
|
};
|
|
2587
|
+
if (status === "success") return /* @__PURE__ */ jsx(SuccessState, { theme, heading: successHeading, message: successMessage, couponCode: c.coupon_code });
|
|
2658
2588
|
return /* @__PURE__ */ jsxs("div", { style: { padding: "3.5rem 1.5rem", maxWidth: 560, margin: "0 auto" }, children: [
|
|
2659
2589
|
/* @__PURE__ */ jsx("style", { children: `@keyframes lc-spin { to { transform: rotate(360deg) } }` }),
|
|
2660
|
-
/* @__PURE__ */
|
|
2661
|
-
background: theme.surface,
|
|
2662
|
-
border: `1px solid ${theme.fg}12`,
|
|
2663
|
-
padding: "clamp(2rem, 6vw, 3rem)"
|
|
2664
|
-
}, children: status === "success" ? /* @__PURE__ */ jsxs("div", { style: { textAlign: "center" }, children: [
|
|
2665
|
-
/* @__PURE__ */ jsx("h2", { style: {
|
|
2666
|
-
fontSize: "clamp(1.5rem, 5vw, 2rem)",
|
|
2667
|
-
fontWeight: 300,
|
|
2668
|
-
fontFamily: theme.fontDisplay || "inherit",
|
|
2669
|
-
margin: "0 0 0.75rem",
|
|
2670
|
-
lineHeight: 1.2,
|
|
2671
|
-
letterSpacing: "-0.02em",
|
|
2672
|
-
color: theme.fg
|
|
2673
|
-
}, children: successHeading }),
|
|
2674
|
-
/* @__PURE__ */ jsx("p", { style: {
|
|
2675
|
-
fontSize: "0.9rem",
|
|
2676
|
-
color: `${theme.fg}99`,
|
|
2677
|
-
margin: "0 0 1.5rem",
|
|
2678
|
-
lineHeight: 1.6,
|
|
2679
|
-
fontWeight: 300
|
|
2680
|
-
}, children: successMessage }),
|
|
2681
|
-
c.coupon_code && /* @__PURE__ */ jsx("div", { style: {
|
|
2682
|
-
display: "inline-block",
|
|
2683
|
-
padding: "0.75rem 2rem",
|
|
2684
|
-
background: `${theme.fg}08`,
|
|
2685
|
-
border: `1px dashed ${theme.fg}30`,
|
|
2686
|
-
fontSize: "clamp(1.25rem, 4vw, 1.75rem)",
|
|
2687
|
-
fontWeight: 500,
|
|
2688
|
-
fontFamily: "monospace",
|
|
2689
|
-
letterSpacing: "0.12em",
|
|
2690
|
-
color: theme.accent
|
|
2691
|
-
}, children: c.coupon_code })
|
|
2692
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2590
|
+
/* @__PURE__ */ jsxs("div", { style: { background: theme.surface, border: `1px solid ${theme.fg}12`, padding: "clamp(2rem, 6vw, 3rem)" }, children: [
|
|
2693
2591
|
/* @__PURE__ */ jsxs("div", { style: { textAlign: "center", marginBottom: "clamp(1.5rem, 4vw, 2rem)" }, children: [
|
|
2694
2592
|
/* @__PURE__ */ jsx("h2", { style: {
|
|
2695
2593
|
fontSize: "clamp(1.5rem, 5vw, 2.25rem)",
|
|
@@ -2711,27 +2609,8 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
|
|
|
2711
2609
|
] }),
|
|
2712
2610
|
/* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
2713
2611
|
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.75rem", flexWrap: "wrap" }, children: [
|
|
2714
|
-
/* @__PURE__ */ jsx(
|
|
2715
|
-
|
|
2716
|
-
{
|
|
2717
|
-
type: "text",
|
|
2718
|
-
placeholder: "First name",
|
|
2719
|
-
value: firstName,
|
|
2720
|
-
onChange: (e) => setFirstName(e.target.value),
|
|
2721
|
-
style: inputStyle
|
|
2722
|
-
}
|
|
2723
|
-
),
|
|
2724
|
-
/* @__PURE__ */ jsx(
|
|
2725
|
-
"input",
|
|
2726
|
-
{
|
|
2727
|
-
type: "email",
|
|
2728
|
-
placeholder: "Email address",
|
|
2729
|
-
value: email,
|
|
2730
|
-
onChange: (e) => setEmail(e.target.value),
|
|
2731
|
-
required: true,
|
|
2732
|
-
style: inputStyle
|
|
2733
|
-
}
|
|
2734
|
-
)
|
|
2612
|
+
/* @__PURE__ */ jsx("input", { type: "text", placeholder: "First name", value: firstName, onChange: (e) => setFirstName(e.target.value), style: inputStyle }),
|
|
2613
|
+
/* @__PURE__ */ jsx("input", { type: "email", placeholder: "Email address", value: email, onChange: (e) => setEmail(e.target.value), required: true, style: inputStyle })
|
|
2735
2614
|
] }),
|
|
2736
2615
|
c.show_newsletter_opt_in !== false && /* @__PURE__ */ jsxs("label", { style: {
|
|
2737
2616
|
display: "flex",
|
|
@@ -2749,121 +2628,130 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
|
|
|
2749
2628
|
type: "checkbox",
|
|
2750
2629
|
checked: newsletterOptIn,
|
|
2751
2630
|
onChange: (e) => setNewsletterOptIn(e.target.checked),
|
|
2752
|
-
style: {
|
|
2753
|
-
width: 16,
|
|
2754
|
-
height: 16,
|
|
2755
|
-
accentColor: theme.accent,
|
|
2756
|
-
cursor: "pointer",
|
|
2757
|
-
flexShrink: 0
|
|
2758
|
-
}
|
|
2631
|
+
style: { width: 16, height: 16, accentColor: theme.accent, cursor: "pointer", flexShrink: 0 }
|
|
2759
2632
|
}
|
|
2760
2633
|
),
|
|
2761
2634
|
c.newsletter_label || "Also sign me up for the newsletter \u2014 new drops, deals, and company news."
|
|
2762
2635
|
] }),
|
|
2763
2636
|
status === "error" && errorMsg && /* @__PURE__ */ jsx("p", { style: { fontSize: "0.8rem", color: "#e55", margin: 0, fontWeight: 400 }, children: errorMsg }),
|
|
2764
|
-
/* @__PURE__ */ jsxs(
|
|
2765
|
-
"
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
}
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
borderTopColor: theme.bg,
|
|
2795
|
-
borderRadius: "50%",
|
|
2796
|
-
animation: "lc-spin 0.8s linear infinite"
|
|
2797
|
-
} }),
|
|
2798
|
-
buttonText
|
|
2799
|
-
]
|
|
2800
|
-
}
|
|
2801
|
-
)
|
|
2637
|
+
/* @__PURE__ */ jsxs("button", { type: "submit", disabled: status === "loading", style: {
|
|
2638
|
+
width: "100%",
|
|
2639
|
+
padding: "0.875rem",
|
|
2640
|
+
background: theme.fg,
|
|
2641
|
+
color: theme.bg,
|
|
2642
|
+
border: "none",
|
|
2643
|
+
fontSize: "0.85rem",
|
|
2644
|
+
fontWeight: 500,
|
|
2645
|
+
cursor: status === "loading" ? "wait" : "pointer",
|
|
2646
|
+
letterSpacing: "0.08em",
|
|
2647
|
+
textTransform: "uppercase",
|
|
2648
|
+
fontFamily: "inherit",
|
|
2649
|
+
display: "flex",
|
|
2650
|
+
alignItems: "center",
|
|
2651
|
+
justifyContent: "center",
|
|
2652
|
+
gap: "0.5rem",
|
|
2653
|
+
opacity: status === "loading" ? 0.7 : 1,
|
|
2654
|
+
transition: "opacity 0.2s"
|
|
2655
|
+
}, children: [
|
|
2656
|
+
status === "loading" && /* @__PURE__ */ jsx("span", { style: {
|
|
2657
|
+
display: "inline-block",
|
|
2658
|
+
width: 16,
|
|
2659
|
+
height: 16,
|
|
2660
|
+
border: `2px solid ${theme.bg}40`,
|
|
2661
|
+
borderTopColor: theme.bg,
|
|
2662
|
+
borderRadius: "50%",
|
|
2663
|
+
animation: "lc-spin 0.8s linear infinite"
|
|
2664
|
+
} }),
|
|
2665
|
+
buttonText
|
|
2666
|
+
] })
|
|
2802
2667
|
] })
|
|
2803
|
-
] })
|
|
2668
|
+
] })
|
|
2804
2669
|
] });
|
|
2805
2670
|
}
|
|
2806
|
-
function
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
}
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2671
|
+
function SuccessState({ theme, heading, message, couponCode }) {
|
|
2672
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "3.5rem 1.5rem", maxWidth: 560, margin: "0 auto" }, children: /* @__PURE__ */ jsxs("div", { style: { background: theme.surface, border: `1px solid ${theme.fg}12`, padding: "clamp(2rem, 6vw, 3rem)", textAlign: "center" }, children: [
|
|
2673
|
+
/* @__PURE__ */ jsx("h2", { style: {
|
|
2674
|
+
fontSize: "clamp(1.5rem, 5vw, 2rem)",
|
|
2675
|
+
fontWeight: 300,
|
|
2676
|
+
fontFamily: theme.fontDisplay || "inherit",
|
|
2677
|
+
margin: "0 0 0.75rem",
|
|
2678
|
+
lineHeight: 1.2,
|
|
2679
|
+
letterSpacing: "-0.02em",
|
|
2680
|
+
color: theme.fg
|
|
2681
|
+
}, children: heading }),
|
|
2682
|
+
/* @__PURE__ */ jsx("p", { style: { fontSize: "0.9rem", color: `${theme.fg}99`, margin: "0 0 1.5rem", lineHeight: 1.6, fontWeight: 300 }, children: message }),
|
|
2683
|
+
couponCode && /* @__PURE__ */ jsx("div", { style: {
|
|
2684
|
+
display: "inline-block",
|
|
2685
|
+
padding: "0.75rem 2rem",
|
|
2686
|
+
background: `${theme.fg}08`,
|
|
2687
|
+
border: `1px dashed ${theme.fg}30`,
|
|
2688
|
+
fontSize: "clamp(1.25rem, 4vw, 1.75rem)",
|
|
2689
|
+
fontWeight: 500,
|
|
2690
|
+
fontFamily: "monospace",
|
|
2691
|
+
letterSpacing: "0.12em",
|
|
2692
|
+
color: theme.accent
|
|
2693
|
+
}, children: couponCode })
|
|
2694
|
+
] }) });
|
|
2830
2695
|
}
|
|
2831
|
-
function
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2696
|
+
function SectionRenderer({
|
|
2697
|
+
section,
|
|
2698
|
+
data,
|
|
2699
|
+
theme,
|
|
2700
|
+
tracking,
|
|
2701
|
+
onEvent
|
|
2702
|
+
}) {
|
|
2703
|
+
const [showCOA, setShowCOA] = useState(false);
|
|
2704
|
+
const el = (() => {
|
|
2705
|
+
switch (section.type) {
|
|
2706
|
+
case "hero":
|
|
2707
|
+
return /* @__PURE__ */ jsx(HeroSection, { section, theme, tracking, onEvent });
|
|
2708
|
+
case "text":
|
|
2709
|
+
return /* @__PURE__ */ jsx(TextSection, { section, theme });
|
|
2710
|
+
case "image":
|
|
2711
|
+
return /* @__PURE__ */ jsx(ImageSection, { section, theme });
|
|
2712
|
+
case "video":
|
|
2713
|
+
return /* @__PURE__ */ jsx(VideoSection, { section, theme });
|
|
2714
|
+
case "gallery":
|
|
2715
|
+
return /* @__PURE__ */ jsx(GallerySection, { section, theme });
|
|
2716
|
+
case "cta":
|
|
2717
|
+
return /* @__PURE__ */ jsx(CTASection, { section, theme, tracking, onEvent });
|
|
2718
|
+
case "stats":
|
|
2719
|
+
return /* @__PURE__ */ jsx(StatsSection, { section, theme });
|
|
2720
|
+
case "product_card":
|
|
2721
|
+
return /* @__PURE__ */ jsx(ProductCardSection, { section, data, theme, tracking });
|
|
2722
|
+
case "coa_viewer":
|
|
2723
|
+
return /* @__PURE__ */ jsx(COAViewerSection, { section, data, theme, onShowCOA: () => setShowCOA(true), tracking });
|
|
2724
|
+
case "social_links":
|
|
2725
|
+
return /* @__PURE__ */ jsx(SocialLinksSection, { section, theme });
|
|
2726
|
+
case "lead_capture":
|
|
2727
|
+
return /* @__PURE__ */ jsx(LeadCaptureSection, { section, data, theme, onEvent });
|
|
2728
|
+
case "divider":
|
|
2729
|
+
return /* @__PURE__ */ jsx(DividerSection, { theme });
|
|
2730
|
+
default:
|
|
2731
|
+
return null;
|
|
2732
|
+
}
|
|
2733
|
+
})();
|
|
2734
|
+
const sectionRef = useRef(null);
|
|
2735
|
+
useEffect(() => {
|
|
2736
|
+
const el2 = sectionRef.current;
|
|
2737
|
+
if (!el2 || typeof IntersectionObserver === "undefined") return;
|
|
2738
|
+
const obs = new IntersectionObserver(
|
|
2739
|
+
([entry]) => {
|
|
2740
|
+
if (entry.isIntersecting) {
|
|
2741
|
+
onEvent?.("section_view", { section_id: section.id, section_type: section.type });
|
|
2742
|
+
obs.disconnect();
|
|
2854
2743
|
}
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2744
|
+
},
|
|
2745
|
+
{ threshold: 0.5 }
|
|
2746
|
+
);
|
|
2747
|
+
obs.observe(el2);
|
|
2748
|
+
return () => obs.disconnect();
|
|
2749
|
+
}, [section.id, section.type, onEvent]);
|
|
2750
|
+
return /* @__PURE__ */ jsxs("div", { ref: sectionRef, "data-section-id": section.id, "data-section-type": section.type, children: [
|
|
2751
|
+
el,
|
|
2752
|
+
showCOA && data?.coa && /* @__PURE__ */ jsx(COAModal, { coa: data.coa, theme, onClose: () => setShowCOA(false) })
|
|
2858
2753
|
] });
|
|
2859
2754
|
}
|
|
2860
|
-
function toEmbedUrl(url) {
|
|
2861
|
-
const ytMatch = url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([\w-]+)/);
|
|
2862
|
-
if (ytMatch) return `https://www.youtube.com/embed/${ytMatch[1]}`;
|
|
2863
|
-
const vimeoMatch = url.match(/vimeo\.com\/(\d+)/);
|
|
2864
|
-
if (vimeoMatch) return `https://player.vimeo.com/video/${vimeoMatch[1]}`;
|
|
2865
|
-
return url;
|
|
2866
|
-
}
|
|
2867
2755
|
function QRLandingPage({
|
|
2868
2756
|
code,
|
|
2869
2757
|
gatewayUrl = "https://whale-gateway.fly.dev",
|
|
@@ -3162,6 +3050,12 @@ function DefaultError({ message }) {
|
|
|
3162
3050
|
/* @__PURE__ */ jsx("p", { style: { color: "#888" }, children: message || "Please try scanning again." })
|
|
3163
3051
|
] }) });
|
|
3164
3052
|
}
|
|
3053
|
+
function getInlinedData() {
|
|
3054
|
+
if (typeof window !== "undefined" && window.__LANDING_DATA__) {
|
|
3055
|
+
return window.__LANDING_DATA__;
|
|
3056
|
+
}
|
|
3057
|
+
return null;
|
|
3058
|
+
}
|
|
3165
3059
|
function LandingPage({
|
|
3166
3060
|
slug,
|
|
3167
3061
|
gatewayUrl = "https://whale-gateway.fly.dev",
|
|
@@ -3172,47 +3066,43 @@ function LandingPage({
|
|
|
3172
3066
|
analyticsContext,
|
|
3173
3067
|
enableAnalytics = true
|
|
3174
3068
|
}) {
|
|
3175
|
-
const
|
|
3176
|
-
const [
|
|
3069
|
+
const inlined = useRef(getInlinedData()).current;
|
|
3070
|
+
const [state, setState] = useState(inlined ? "ready" : "loading");
|
|
3071
|
+
const [data, setData] = useState(inlined);
|
|
3177
3072
|
const [errorMsg, setErrorMsg] = useState("");
|
|
3178
3073
|
useEffect(() => {
|
|
3179
3074
|
if (!slug) return;
|
|
3180
|
-
|
|
3181
|
-
|
|
3182
|
-
const json = window.__LANDING_DATA__;
|
|
3183
|
-
setData(json);
|
|
3184
|
-
setState("ready");
|
|
3185
|
-
onDataLoaded?.(json);
|
|
3075
|
+
if (data) {
|
|
3076
|
+
onDataLoaded?.(data);
|
|
3186
3077
|
return;
|
|
3187
3078
|
}
|
|
3079
|
+
let cancelled = false;
|
|
3188
3080
|
async function load() {
|
|
3189
3081
|
try {
|
|
3190
3082
|
const res = await fetch(`${gatewayUrl}/l/${encodeURIComponent(slug)}`);
|
|
3191
|
-
if (
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
}
|
|
3196
|
-
if (res.status === 410) {
|
|
3197
|
-
setState("expired");
|
|
3198
|
-
return;
|
|
3199
|
-
}
|
|
3200
|
-
if (!res.ok) {
|
|
3201
|
-
const body = await res.json().catch(() => ({}));
|
|
3202
|
-
throw new Error(body?.error?.message ?? `Failed to load: ${res.status}`);
|
|
3203
|
-
}
|
|
3204
|
-
const json = await res.json();
|
|
3205
|
-
setData(json);
|
|
3206
|
-
setState("ready");
|
|
3207
|
-
onDataLoaded?.(json);
|
|
3083
|
+
if (cancelled) return;
|
|
3084
|
+
if (res.status === 404) {
|
|
3085
|
+
setState("not_found");
|
|
3086
|
+
return;
|
|
3208
3087
|
}
|
|
3209
|
-
|
|
3210
|
-
|
|
3211
|
-
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
|
|
3088
|
+
if (res.status === 410) {
|
|
3089
|
+
setState("expired");
|
|
3090
|
+
return;
|
|
3091
|
+
}
|
|
3092
|
+
if (!res.ok) {
|
|
3093
|
+
const body = await res.json().catch(() => ({}));
|
|
3094
|
+
throw new Error(body?.error?.message ?? `Failed to load: ${res.status}`);
|
|
3215
3095
|
}
|
|
3096
|
+
const json = await res.json();
|
|
3097
|
+
setData(json);
|
|
3098
|
+
setState("ready");
|
|
3099
|
+
onDataLoaded?.(json);
|
|
3100
|
+
} catch (err) {
|
|
3101
|
+
if (cancelled) return;
|
|
3102
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
3103
|
+
setErrorMsg(e.message);
|
|
3104
|
+
setState("error");
|
|
3105
|
+
onError?.(e);
|
|
3216
3106
|
}
|
|
3217
3107
|
}
|
|
3218
3108
|
load();
|
|
@@ -3220,12 +3110,22 @@ function LandingPage({
|
|
|
3220
3110
|
cancelled = true;
|
|
3221
3111
|
};
|
|
3222
3112
|
}, [slug, gatewayUrl]);
|
|
3223
|
-
if (state === "loading") return /* @__PURE__ */ jsx(
|
|
3224
|
-
if (state === "not_found") return /* @__PURE__ */ jsx(
|
|
3225
|
-
if (state === "expired") return /* @__PURE__ */ jsx(
|
|
3226
|
-
if (state === "error") return /* @__PURE__ */ jsx(
|
|
3113
|
+
if (state === "loading") return /* @__PURE__ */ jsx(StateScreen, { title: "", loading: true });
|
|
3114
|
+
if (state === "not_found") return /* @__PURE__ */ jsx(StateScreen, { title: "Page Not Found", subtitle: "This page does not exist or has been removed." });
|
|
3115
|
+
if (state === "expired") return /* @__PURE__ */ jsx(StateScreen, { title: "Page Expired", subtitle: "This page is no longer active." });
|
|
3116
|
+
if (state === "error") return /* @__PURE__ */ jsx(StateScreen, { title: "Something Went Wrong", subtitle: errorMsg || "Please try again later." });
|
|
3227
3117
|
if (!data) return null;
|
|
3228
|
-
return /* @__PURE__ */ jsx(
|
|
3118
|
+
return /* @__PURE__ */ jsx(
|
|
3119
|
+
PageLayout,
|
|
3120
|
+
{
|
|
3121
|
+
data,
|
|
3122
|
+
gatewayUrl,
|
|
3123
|
+
renderSection,
|
|
3124
|
+
onEvent,
|
|
3125
|
+
analyticsContext,
|
|
3126
|
+
enableAnalytics
|
|
3127
|
+
}
|
|
3128
|
+
);
|
|
3229
3129
|
}
|
|
3230
3130
|
function isSectionVisible(section, urlParams) {
|
|
3231
3131
|
const vis = section.config?.visibility;
|
|
@@ -3248,8 +3148,8 @@ function PageLayout({
|
|
|
3248
3148
|
const trackerRef = useRef(null);
|
|
3249
3149
|
useEffect(() => {
|
|
3250
3150
|
if (!enableAnalytics || typeof window === "undefined") return;
|
|
3251
|
-
const
|
|
3252
|
-
if (!
|
|
3151
|
+
const config = window.__LANDING_ANALYTICS__;
|
|
3152
|
+
if (!config?.slug) return;
|
|
3253
3153
|
let visitorId = localStorage.getItem("wt_vid") || "";
|
|
3254
3154
|
if (!visitorId) {
|
|
3255
3155
|
visitorId = crypto.randomUUID();
|
|
@@ -3261,8 +3161,8 @@ function PageLayout({
|
|
|
3261
3161
|
sessionStorage.setItem("wt_sid", sessionId);
|
|
3262
3162
|
}
|
|
3263
3163
|
import('../tracker-34GTXU54.js').then(({ BehavioralTracker: BehavioralTracker2 }) => {
|
|
3264
|
-
const gwUrl =
|
|
3265
|
-
const slug =
|
|
3164
|
+
const gwUrl = config.gatewayUrl || gatewayUrl;
|
|
3165
|
+
const slug = config.slug;
|
|
3266
3166
|
const utmParams = new URLSearchParams(window.location.search);
|
|
3267
3167
|
const tracker = new BehavioralTracker2({
|
|
3268
3168
|
sessionId,
|
|
@@ -3273,65 +3173,44 @@ function PageLayout({
|
|
|
3273
3173
|
event_data: e.data,
|
|
3274
3174
|
session_id: batch.session_id,
|
|
3275
3175
|
visitor_id: batch.visitor_id,
|
|
3276
|
-
campaign_id:
|
|
3176
|
+
campaign_id: config.campaignId || utmParams.get("utm_campaign_id") || void 0,
|
|
3277
3177
|
utm_source: utmParams.get("utm_source") || void 0,
|
|
3278
3178
|
utm_medium: utmParams.get("utm_medium") || void 0,
|
|
3279
3179
|
utm_campaign: utmParams.get("utm_campaign") || void 0
|
|
3280
3180
|
}));
|
|
3281
|
-
|
|
3282
|
-
if (typeof navigator !== "undefined" && navigator.sendBeacon) {
|
|
3283
|
-
navigator.sendBeacon(
|
|
3284
|
-
`${gwUrl}/l/${encodeURIComponent(slug)}/events`,
|
|
3285
|
-
new Blob([body], { type: "application/json" })
|
|
3286
|
-
);
|
|
3287
|
-
} else {
|
|
3288
|
-
await fetch(`${gwUrl}/l/${encodeURIComponent(slug)}/events`, {
|
|
3289
|
-
method: "POST",
|
|
3290
|
-
headers: { "Content-Type": "application/json" },
|
|
3291
|
-
body,
|
|
3292
|
-
keepalive: true
|
|
3293
|
-
});
|
|
3294
|
-
}
|
|
3181
|
+
sendEvents(gwUrl, slug, events);
|
|
3295
3182
|
}
|
|
3296
3183
|
});
|
|
3297
3184
|
tracker.setPageContext(window.location.href, window.location.pathname);
|
|
3298
3185
|
tracker.start();
|
|
3299
3186
|
trackerRef.current = tracker;
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
utm_source: utmParams.get("utm_source") || void 0,
|
|
3308
|
-
utm_medium: utmParams.get("utm_medium") || void 0,
|
|
3309
|
-
utm_campaign: utmParams.get("utm_campaign") || void 0
|
|
3310
|
-
}]
|
|
3311
|
-
});
|
|
3312
|
-
if (navigator.sendBeacon) {
|
|
3313
|
-
navigator.sendBeacon(
|
|
3314
|
-
`${gwUrl}/l/${encodeURIComponent(slug)}/events`,
|
|
3315
|
-
new Blob([pageViewBody], { type: "application/json" })
|
|
3316
|
-
);
|
|
3317
|
-
} else {
|
|
3318
|
-
fetch(`${gwUrl}/l/${encodeURIComponent(slug)}/events`, {
|
|
3319
|
-
method: "POST",
|
|
3320
|
-
headers: { "Content-Type": "application/json" },
|
|
3321
|
-
body: pageViewBody,
|
|
3322
|
-
keepalive: true
|
|
3323
|
-
}).catch(() => {
|
|
3324
|
-
});
|
|
3325
|
-
}
|
|
3187
|
+
sendEvents(gwUrl, slug, [{
|
|
3188
|
+
event_type: "page_view",
|
|
3189
|
+
event_data: { referrer: document.referrer, url: window.location.href },
|
|
3190
|
+
session_id: sessionId,
|
|
3191
|
+
visitor_id: visitorId,
|
|
3192
|
+
campaign_id: config.campaignId || void 0
|
|
3193
|
+
}]);
|
|
3326
3194
|
}).catch(() => {
|
|
3327
3195
|
});
|
|
3328
3196
|
return () => {
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
trackerRef.current = null;
|
|
3332
|
-
}
|
|
3197
|
+
trackerRef.current?.stop();
|
|
3198
|
+
trackerRef.current = null;
|
|
3333
3199
|
};
|
|
3334
3200
|
}, [enableAnalytics, gatewayUrl]);
|
|
3201
|
+
const handleEvent = useCallback((event, eventData) => {
|
|
3202
|
+
onEvent?.(event, eventData);
|
|
3203
|
+
if (!enableAnalytics || typeof window === "undefined") return;
|
|
3204
|
+
const config = window.__LANDING_ANALYTICS__;
|
|
3205
|
+
if (!config?.slug) return;
|
|
3206
|
+
sendEvents(config.gatewayUrl || gatewayUrl, config.slug, [{
|
|
3207
|
+
event_type: event,
|
|
3208
|
+
event_data: eventData,
|
|
3209
|
+
session_id: sessionStorage.getItem("wt_sid") || void 0,
|
|
3210
|
+
visitor_id: localStorage.getItem("wt_vid") || void 0,
|
|
3211
|
+
campaign_id: config.campaignId || void 0
|
|
3212
|
+
}]);
|
|
3213
|
+
}, [onEvent, enableAnalytics, gatewayUrl]);
|
|
3335
3214
|
const theme = {
|
|
3336
3215
|
bg: lp.background_color || store?.theme?.background || "#050505",
|
|
3337
3216
|
fg: lp.text_color || store?.theme?.foreground || "#fafafa",
|
|
@@ -3350,11 +3229,9 @@ function PageLayout({
|
|
|
3350
3229
|
lp.custom_css && /* @__PURE__ */ jsx("style", { children: lp.custom_css }),
|
|
3351
3230
|
logoUrl && /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", display: "flex", justifyContent: "center" }, children: /* @__PURE__ */ jsx("img", { src: logoUrl, alt: store?.name || "Store", style: { height: 40, objectFit: "contain" } }) }),
|
|
3352
3231
|
sorted.map((section) => {
|
|
3353
|
-
const defaultRenderer = () => /* @__PURE__ */ jsx(SectionRenderer, { section, data: sectionData, theme, onEvent }, section.id);
|
|
3354
|
-
if (renderSection) {
|
|
3355
|
-
|
|
3356
|
-
}
|
|
3357
|
-
return /* @__PURE__ */ jsx(SectionRenderer, { section, data: sectionData, theme, onEvent }, section.id);
|
|
3232
|
+
const defaultRenderer = () => /* @__PURE__ */ jsx(SectionRenderer, { section, data: sectionData, theme, onEvent: handleEvent }, section.id);
|
|
3233
|
+
if (renderSection) return /* @__PURE__ */ jsx("div", { children: renderSection(section, defaultRenderer) }, section.id);
|
|
3234
|
+
return /* @__PURE__ */ jsx(SectionRenderer, { section, data: sectionData, theme, onEvent: handleEvent }, section.id);
|
|
3358
3235
|
}),
|
|
3359
3236
|
store?.name && /* @__PURE__ */ jsx("div", { style: { padding: "2rem 1.5rem", borderTop: `1px solid ${theme.surface}`, textAlign: "center" }, children: /* @__PURE__ */ jsxs("p", { style: { fontSize: "0.75rem", color: theme.muted, margin: 0 }, children: [
|
|
3360
3237
|
"Powered by ",
|
|
@@ -3362,7 +3239,17 @@ function PageLayout({
|
|
|
3362
3239
|
] }) })
|
|
3363
3240
|
] });
|
|
3364
3241
|
}
|
|
3365
|
-
|
|
3242
|
+
function sendEvents(gwUrl, slug, events) {
|
|
3243
|
+
const body = JSON.stringify({ events });
|
|
3244
|
+
const url = `${gwUrl}/l/${encodeURIComponent(slug)}/events`;
|
|
3245
|
+
if (typeof navigator !== "undefined" && navigator.sendBeacon) {
|
|
3246
|
+
navigator.sendBeacon(url, new Blob([body], { type: "application/json" }));
|
|
3247
|
+
} else {
|
|
3248
|
+
fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body, keepalive: true }).catch(() => {
|
|
3249
|
+
});
|
|
3250
|
+
}
|
|
3251
|
+
}
|
|
3252
|
+
var screenStyle = {
|
|
3366
3253
|
minHeight: "100dvh",
|
|
3367
3254
|
display: "flex",
|
|
3368
3255
|
justifyContent: "center",
|
|
@@ -3373,28 +3260,14 @@ var containerStyle2 = {
|
|
|
3373
3260
|
textAlign: "center",
|
|
3374
3261
|
padding: "2rem"
|
|
3375
3262
|
};
|
|
3376
|
-
function
|
|
3377
|
-
return /* @__PURE__ */ jsx("div", { style:
|
|
3378
|
-
/* @__PURE__ */
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
}
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
/* @__PURE__ */ jsx("h1", { style: { fontSize: "1.5rem", marginBottom: "0.5rem" }, children: "Page Not Found" }),
|
|
3385
|
-
/* @__PURE__ */ jsx("p", { style: { color: "#888" }, children: "This page does not exist or has been removed." })
|
|
3386
|
-
] }) });
|
|
3387
|
-
}
|
|
3388
|
-
function DefaultExpired2() {
|
|
3389
|
-
return /* @__PURE__ */ jsx("div", { style: containerStyle2, children: /* @__PURE__ */ jsxs("div", { children: [
|
|
3390
|
-
/* @__PURE__ */ jsx("h1", { style: { fontSize: "1.5rem", marginBottom: "0.5rem" }, children: "Page Expired" }),
|
|
3391
|
-
/* @__PURE__ */ jsx("p", { style: { color: "#888" }, children: "This page is no longer active." })
|
|
3392
|
-
] }) });
|
|
3393
|
-
}
|
|
3394
|
-
function DefaultError2({ message }) {
|
|
3395
|
-
return /* @__PURE__ */ jsx("div", { style: containerStyle2, children: /* @__PURE__ */ jsxs("div", { children: [
|
|
3396
|
-
/* @__PURE__ */ jsx("h1", { style: { fontSize: "1.5rem", marginBottom: "0.5rem" }, children: "Something Went Wrong" }),
|
|
3397
|
-
/* @__PURE__ */ jsx("p", { style: { color: "#888" }, children: message || "Please try again later." })
|
|
3263
|
+
function StateScreen({ title, subtitle, loading }) {
|
|
3264
|
+
return /* @__PURE__ */ jsx("div", { style: screenStyle, children: /* @__PURE__ */ jsxs("div", { children: [
|
|
3265
|
+
loading && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3266
|
+
/* @__PURE__ */ jsx("div", { style: { width: 32, height: 32, border: "2px solid #333", borderTopColor: "#fafafa", borderRadius: "50%", animation: "spin 0.8s linear infinite", margin: "0 auto 1rem" } }),
|
|
3267
|
+
/* @__PURE__ */ jsx("style", { children: `@keyframes spin { to { transform: rotate(360deg) } }` })
|
|
3268
|
+
] }),
|
|
3269
|
+
title && /* @__PURE__ */ jsx("h1", { style: { fontSize: "1.5rem", marginBottom: "0.5rem" }, children: title }),
|
|
3270
|
+
subtitle && /* @__PURE__ */ jsx("p", { style: { color: "#888" }, children: subtitle })
|
|
3398
3271
|
] }) });
|
|
3399
3272
|
}
|
|
3400
3273
|
|