@neowhale/storefront 0.2.34 → 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 +448 -525
- 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/landing.global.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var WhaleStorefront = (function (exports
|
|
1
|
+
var WhaleStorefront = (function (exports) {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
var __defProp = Object.defineProperty;
|
|
@@ -345,14 +345,65 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
345
345
|
};
|
|
346
346
|
}
|
|
347
347
|
});
|
|
348
|
-
|
|
348
|
+
|
|
349
|
+
// src/shims/react-global.ts
|
|
350
|
+
var R = globalThis.React;
|
|
351
|
+
var {
|
|
352
|
+
createElement,
|
|
353
|
+
createContext,
|
|
354
|
+
forwardRef,
|
|
355
|
+
memo,
|
|
356
|
+
lazy,
|
|
357
|
+
useCallback,
|
|
358
|
+
useContext,
|
|
359
|
+
useEffect,
|
|
360
|
+
useId,
|
|
361
|
+
useImperativeHandle,
|
|
362
|
+
useLayoutEffect,
|
|
363
|
+
useMemo,
|
|
364
|
+
useReducer,
|
|
365
|
+
useRef,
|
|
366
|
+
useState,
|
|
367
|
+
Fragment,
|
|
368
|
+
Children,
|
|
369
|
+
cloneElement,
|
|
370
|
+
isValidElement,
|
|
371
|
+
Suspense,
|
|
372
|
+
startTransition,
|
|
373
|
+
useTransition,
|
|
374
|
+
useDeferredValue,
|
|
375
|
+
useSyncExternalStore,
|
|
376
|
+
useInsertionEffect,
|
|
377
|
+
useDebugValue
|
|
378
|
+
} = R;
|
|
379
|
+
|
|
380
|
+
// src/shims/jsx-runtime-global.ts
|
|
381
|
+
var R2 = globalThis.React;
|
|
382
|
+
var jsx = R2.createElement;
|
|
383
|
+
var jsxs = R2.createElement;
|
|
384
|
+
R2.createElement;
|
|
385
|
+
var Fragment2 = R2.Fragment;
|
|
386
|
+
|
|
387
|
+
// src/react/components/sections/shared.tsx
|
|
388
|
+
function trackClick(tracking, label, url, position) {
|
|
389
|
+
if (!tracking?.gatewayUrl || !tracking?.code) return;
|
|
390
|
+
const body = JSON.stringify({ label, url, position });
|
|
391
|
+
if (typeof navigator !== "undefined" && navigator.sendBeacon) {
|
|
392
|
+
navigator.sendBeacon(
|
|
393
|
+
`${tracking.gatewayUrl}/q/${encodeURIComponent(tracking.code)}/click`,
|
|
394
|
+
new Blob([body], { type: "application/json" })
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
var NUM_SPLIT = /(\$?[\d,]+\.?\d*[+★%]?)/g;
|
|
399
|
+
var NUM_TEST = /^\$?[\d,]+\.?\d*[+★%]?$/;
|
|
349
400
|
function easeOutQuart(t) {
|
|
350
401
|
return 1 - Math.pow(1 - t, 4);
|
|
351
402
|
}
|
|
352
403
|
function useCountUp(target, duration, start) {
|
|
353
|
-
const [value, setValue] =
|
|
354
|
-
const raf =
|
|
355
|
-
|
|
404
|
+
const [value, setValue] = useState(0);
|
|
405
|
+
const raf = useRef(0);
|
|
406
|
+
useEffect(() => {
|
|
356
407
|
if (!start) return;
|
|
357
408
|
const t0 = performance.now();
|
|
358
409
|
function tick(now) {
|
|
@@ -367,9 +418,9 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
367
418
|
return value;
|
|
368
419
|
}
|
|
369
420
|
function AnimatedNumber({ raw }) {
|
|
370
|
-
const ref =
|
|
371
|
-
const [visible, setVisible] =
|
|
372
|
-
|
|
421
|
+
const ref = useRef(null);
|
|
422
|
+
const [visible, setVisible] = useState(false);
|
|
423
|
+
useEffect(() => {
|
|
373
424
|
const el = ref.current;
|
|
374
425
|
if (!el || typeof IntersectionObserver === "undefined") {
|
|
375
426
|
setVisible(true);
|
|
@@ -395,160 +446,84 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
395
446
|
visible
|
|
396
447
|
);
|
|
397
448
|
const display = decimals > 0 ? (count / Math.pow(10, decimals)).toFixed(decimals) : hasCommas ? count.toLocaleString() : String(count);
|
|
398
|
-
return /* @__PURE__ */
|
|
449
|
+
return /* @__PURE__ */ jsxs("span", { ref, children: [
|
|
399
450
|
prefix,
|
|
400
451
|
display,
|
|
401
452
|
suffix
|
|
402
453
|
] });
|
|
403
454
|
}
|
|
404
455
|
function AnimatedText({ text }) {
|
|
405
|
-
const parts = text.split(
|
|
406
|
-
return /* @__PURE__ */
|
|
407
|
-
(part, i) =>
|
|
456
|
+
const parts = text.split(NUM_SPLIT);
|
|
457
|
+
return /* @__PURE__ */ jsx(Fragment2, { children: parts.map(
|
|
458
|
+
(part, i) => NUM_TEST.test(part) ? /* @__PURE__ */ jsx(AnimatedNumber, { raw: part }, i) : part
|
|
408
459
|
) });
|
|
409
460
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
const body = JSON.stringify({ label, url, position });
|
|
413
|
-
if (typeof navigator !== "undefined" && navigator.sendBeacon) {
|
|
414
|
-
navigator.sendBeacon(
|
|
415
|
-
`${tracking.gatewayUrl}/q/${encodeURIComponent(tracking.code)}/click`,
|
|
416
|
-
new Blob([body], { type: "application/json" })
|
|
417
|
-
);
|
|
418
|
-
}
|
|
419
|
-
}
|
|
420
|
-
function SectionRenderer({
|
|
421
|
-
section,
|
|
422
|
-
data,
|
|
423
|
-
theme,
|
|
424
|
-
tracking,
|
|
425
|
-
onEvent
|
|
426
|
-
}) {
|
|
427
|
-
const [showCOA, setShowCOA] = react.useState(false);
|
|
428
|
-
const el = (() => {
|
|
429
|
-
switch (section.type) {
|
|
430
|
-
case "hero":
|
|
431
|
-
return /* @__PURE__ */ jsxRuntime.jsx(HeroSection, { section, theme, tracking, onEvent });
|
|
432
|
-
case "text":
|
|
433
|
-
return /* @__PURE__ */ jsxRuntime.jsx(TextSection, { section, theme });
|
|
434
|
-
case "image":
|
|
435
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ImageSection, { section, theme });
|
|
436
|
-
case "video":
|
|
437
|
-
return /* @__PURE__ */ jsxRuntime.jsx(VideoSection, { section, theme });
|
|
438
|
-
case "gallery":
|
|
439
|
-
return /* @__PURE__ */ jsxRuntime.jsx(GallerySection, { section, theme });
|
|
440
|
-
case "cta":
|
|
441
|
-
return /* @__PURE__ */ jsxRuntime.jsx(CTASection, { section, theme, tracking, onEvent });
|
|
442
|
-
case "stats":
|
|
443
|
-
return /* @__PURE__ */ jsxRuntime.jsx(StatsSection, { section, theme });
|
|
444
|
-
case "product_card":
|
|
445
|
-
return /* @__PURE__ */ jsxRuntime.jsx(ProductCardSection, { section, data, theme, tracking });
|
|
446
|
-
case "coa_viewer":
|
|
447
|
-
return /* @__PURE__ */ jsxRuntime.jsx(COAViewerSection, { section, data, theme, onShowCOA: () => setShowCOA(true), tracking });
|
|
448
|
-
case "social_links":
|
|
449
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SocialLinksSection, { section, theme });
|
|
450
|
-
case "lead_capture":
|
|
451
|
-
return /* @__PURE__ */ jsxRuntime.jsx(LeadCaptureSection, { section, data, theme, onEvent });
|
|
452
|
-
case "divider":
|
|
453
|
-
return /* @__PURE__ */ jsxRuntime.jsx(DividerSection, { theme });
|
|
454
|
-
default:
|
|
455
|
-
return null;
|
|
456
|
-
}
|
|
457
|
-
})();
|
|
458
|
-
const sectionRef = react.useRef(null);
|
|
459
|
-
react.useEffect(() => {
|
|
460
|
-
const el2 = sectionRef.current;
|
|
461
|
-
if (!el2 || typeof IntersectionObserver === "undefined") return;
|
|
462
|
-
const obs = new IntersectionObserver(
|
|
463
|
-
([entry]) => {
|
|
464
|
-
if (entry.isIntersecting) {
|
|
465
|
-
onEvent?.("section_view", {
|
|
466
|
-
section_id: section.id,
|
|
467
|
-
section_type: section.type
|
|
468
|
-
});
|
|
469
|
-
obs.disconnect();
|
|
470
|
-
}
|
|
471
|
-
},
|
|
472
|
-
{ threshold: 0.5 }
|
|
473
|
-
);
|
|
474
|
-
obs.observe(el2);
|
|
475
|
-
return () => obs.disconnect();
|
|
476
|
-
}, [section.id, section.type, onEvent]);
|
|
477
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: sectionRef, "data-section-id": section.id, "data-section-type": section.type, children: [
|
|
478
|
-
el,
|
|
479
|
-
showCOA && data?.coa && /* @__PURE__ */ jsxRuntime.jsx(COAModal, { coa: data.coa, theme, onClose: () => setShowCOA(false) })
|
|
480
|
-
] });
|
|
481
|
-
}
|
|
461
|
+
|
|
462
|
+
// src/react/components/sections/content-sections.tsx
|
|
482
463
|
function HeroSection({ section, theme, tracking, onEvent }) {
|
|
483
464
|
const { title, subtitle, background_image, cta_text, cta_url } = section.content;
|
|
484
|
-
return /* @__PURE__ */
|
|
485
|
-
"
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
465
|
+
return /* @__PURE__ */ jsxs("div", { style: {
|
|
466
|
+
position: "relative",
|
|
467
|
+
minHeight: "60vh",
|
|
468
|
+
display: "flex",
|
|
469
|
+
flexDirection: "column",
|
|
470
|
+
justifyContent: "center",
|
|
471
|
+
alignItems: "center",
|
|
472
|
+
textAlign: "center",
|
|
473
|
+
padding: "3rem 1.5rem",
|
|
474
|
+
backgroundImage: background_image ? `url(${background_image})` : void 0,
|
|
475
|
+
backgroundSize: "cover",
|
|
476
|
+
backgroundPosition: "center"
|
|
477
|
+
}, children: [
|
|
478
|
+
background_image && /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: "rgba(0,0,0,0.5)" } }),
|
|
479
|
+
/* @__PURE__ */ jsxs("div", { style: { position: "relative", zIndex: 1, maxWidth: 640 }, children: [
|
|
480
|
+
title && /* @__PURE__ */ jsx("h1", { style: {
|
|
481
|
+
fontSize: "clamp(2rem, 8vw, 3rem)",
|
|
482
|
+
fontWeight: 300,
|
|
483
|
+
fontFamily: theme.fontDisplay || "inherit",
|
|
484
|
+
margin: "0 0 1rem",
|
|
485
|
+
lineHeight: 1.15,
|
|
486
|
+
letterSpacing: "-0.02em",
|
|
487
|
+
color: theme.fg
|
|
488
|
+
}, children: /* @__PURE__ */ jsx(AnimatedText, { text: title }) }),
|
|
489
|
+
subtitle && /* @__PURE__ */ jsx("p", { style: {
|
|
490
|
+
fontSize: "0.85rem",
|
|
491
|
+
color: theme.accent,
|
|
492
|
+
margin: "0 0 2rem",
|
|
493
|
+
lineHeight: 1.6,
|
|
494
|
+
textTransform: "uppercase",
|
|
495
|
+
letterSpacing: "0.15em"
|
|
496
|
+
}, children: subtitle }),
|
|
497
|
+
cta_text && cta_url && /* @__PURE__ */ jsx(
|
|
498
|
+
"a",
|
|
499
|
+
{
|
|
500
|
+
href: cta_url,
|
|
501
|
+
onClick: () => {
|
|
502
|
+
trackClick(tracking, cta_text, cta_url);
|
|
503
|
+
onEvent?.("cta_click", { label: cta_text, url: cta_url });
|
|
504
|
+
},
|
|
505
|
+
style: {
|
|
506
|
+
display: "inline-block",
|
|
507
|
+
padding: "0.875rem 2rem",
|
|
508
|
+
background: theme.fg,
|
|
509
|
+
color: theme.bg,
|
|
510
|
+
textDecoration: "none",
|
|
513
511
|
fontSize: "0.85rem",
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
href: cta_url,
|
|
524
|
-
onClick: () => {
|
|
525
|
-
trackClick(tracking, cta_text, cta_url);
|
|
526
|
-
onEvent?.("cta_click", { label: cta_text, url: cta_url });
|
|
527
|
-
},
|
|
528
|
-
style: {
|
|
529
|
-
display: "inline-block",
|
|
530
|
-
padding: "0.875rem 2rem",
|
|
531
|
-
background: theme.fg,
|
|
532
|
-
color: theme.bg,
|
|
533
|
-
textDecoration: "none",
|
|
534
|
-
fontSize: "0.85rem",
|
|
535
|
-
fontWeight: 500,
|
|
536
|
-
letterSpacing: "0.08em",
|
|
537
|
-
textTransform: "uppercase"
|
|
538
|
-
},
|
|
539
|
-
children: cta_text
|
|
540
|
-
}
|
|
541
|
-
)
|
|
542
|
-
] })
|
|
543
|
-
]
|
|
544
|
-
}
|
|
545
|
-
);
|
|
512
|
+
fontWeight: 500,
|
|
513
|
+
letterSpacing: "0.08em",
|
|
514
|
+
textTransform: "uppercase"
|
|
515
|
+
},
|
|
516
|
+
children: cta_text
|
|
517
|
+
}
|
|
518
|
+
)
|
|
519
|
+
] })
|
|
520
|
+
] });
|
|
546
521
|
}
|
|
547
522
|
function TextSection({ section, theme }) {
|
|
548
523
|
const { heading, body } = section.content;
|
|
549
524
|
const align = section.config?.align || "left";
|
|
550
|
-
return /* @__PURE__ */
|
|
551
|
-
heading && /* @__PURE__ */
|
|
525
|
+
return /* @__PURE__ */ jsxs("div", { style: { padding: "2rem 1.5rem", maxWidth: 640, margin: "0 auto", textAlign: align }, children: [
|
|
526
|
+
heading && /* @__PURE__ */ jsx("h2", { style: {
|
|
552
527
|
fontSize: 11,
|
|
553
528
|
fontWeight: 500,
|
|
554
529
|
textTransform: "uppercase",
|
|
@@ -556,65 +531,62 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
556
531
|
color: `${theme.fg}40`,
|
|
557
532
|
margin: "0 0 0.75rem"
|
|
558
533
|
}, children: heading }),
|
|
559
|
-
body && /* @__PURE__ */
|
|
534
|
+
body && /* @__PURE__ */ jsx("div", { style: { color: `${theme.fg}99`, lineHeight: 1.7, fontSize: "0.9rem", fontWeight: 300, whiteSpace: "pre-wrap" }, children: body })
|
|
560
535
|
] });
|
|
561
536
|
}
|
|
562
537
|
function ImageSection({ section, theme }) {
|
|
563
538
|
const { url, alt, caption } = section.content;
|
|
564
539
|
const contained = section.config?.contained !== false;
|
|
565
540
|
if (!url) return null;
|
|
566
|
-
return /* @__PURE__ */
|
|
567
|
-
/* @__PURE__ */
|
|
568
|
-
|
|
569
|
-
{
|
|
570
|
-
src: url,
|
|
571
|
-
alt: alt || "",
|
|
572
|
-
style: { width: "100%", display: "block", objectFit: "cover" }
|
|
573
|
-
}
|
|
574
|
-
),
|
|
575
|
-
caption && /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: "0.8rem", color: theme.muted, textAlign: "center", marginTop: "0.75rem" }, children: caption })
|
|
541
|
+
return /* @__PURE__ */ jsxs("div", { style: { padding: contained ? "1.5rem" : 0, maxWidth: contained ? 640 : void 0, margin: contained ? "0 auto" : void 0 }, children: [
|
|
542
|
+
/* @__PURE__ */ jsx("img", { src: url, alt: alt || "", style: { width: "100%", display: "block", objectFit: "cover" } }),
|
|
543
|
+
caption && /* @__PURE__ */ jsx("p", { style: { fontSize: "0.8rem", color: theme.muted, textAlign: "center", marginTop: "0.75rem" }, children: caption })
|
|
576
544
|
] });
|
|
577
545
|
}
|
|
578
546
|
function VideoSection({ section, theme }) {
|
|
579
547
|
const { url, poster } = section.content;
|
|
580
548
|
if (!url) return null;
|
|
581
549
|
const isEmbed = url.includes("youtube") || url.includes("youtu.be") || url.includes("vimeo");
|
|
582
|
-
return /* @__PURE__ */
|
|
583
|
-
"iframe",
|
|
584
|
-
{
|
|
585
|
-
src: toEmbedUrl(url),
|
|
586
|
-
style: { position: "absolute", top: 0, left: 0, width: "100%", height: "100%", border: "none" },
|
|
587
|
-
allow: "autoplay; fullscreen",
|
|
588
|
-
title: "Video"
|
|
589
|
-
}
|
|
590
|
-
) }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
591
|
-
"video",
|
|
592
|
-
{
|
|
593
|
-
src: url,
|
|
594
|
-
poster,
|
|
595
|
-
controls: true,
|
|
596
|
-
style: { width: "100%", display: "block", background: theme.surface }
|
|
597
|
-
}
|
|
598
|
-
) });
|
|
550
|
+
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 } }) });
|
|
599
551
|
}
|
|
600
552
|
function GallerySection({ section, theme }) {
|
|
601
553
|
const { images } = section.content;
|
|
602
554
|
const columns = section.config?.columns || 3;
|
|
603
555
|
if (!images || images.length === 0) return null;
|
|
604
|
-
return /* @__PURE__ */
|
|
605
|
-
|
|
556
|
+
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)) }) });
|
|
557
|
+
}
|
|
558
|
+
function SocialLinksSection({ section, theme }) {
|
|
559
|
+
const { links } = section.content;
|
|
560
|
+
if (!links || links.length === 0) return null;
|
|
561
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", display: "flex", justifyContent: "center", gap: "1.5rem", flexWrap: "wrap" }, children: links.map((link, i) => /* @__PURE__ */ jsx(
|
|
562
|
+
"a",
|
|
606
563
|
{
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
564
|
+
href: link.url,
|
|
565
|
+
target: "_blank",
|
|
566
|
+
rel: "noopener noreferrer",
|
|
567
|
+
style: { color: theme.muted, textDecoration: "none", fontSize: "0.85rem", fontWeight: 500, textTransform: "capitalize", letterSpacing: "0.03em" },
|
|
568
|
+
children: link.platform
|
|
569
|
+
},
|
|
570
|
+
i
|
|
571
|
+
)) });
|
|
572
|
+
}
|
|
573
|
+
function DividerSection({ theme }) {
|
|
574
|
+
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 } }) });
|
|
612
575
|
}
|
|
576
|
+
function toEmbedUrl(url) {
|
|
577
|
+
const ytMatch = url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([\w-]+)/);
|
|
578
|
+
if (ytMatch) return `https://www.youtube.com/embed/${ytMatch[1]}`;
|
|
579
|
+
const vimeoMatch = url.match(/vimeo\.com\/(\d+)/);
|
|
580
|
+
if (vimeoMatch) return `https://player.vimeo.com/video/${vimeoMatch[1]}`;
|
|
581
|
+
return url;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
// src/react/components/sections/interactive-sections.tsx
|
|
613
585
|
function CTASection({ section, theme, tracking, onEvent }) {
|
|
614
586
|
const { title, subtitle, buttons } = section.content;
|
|
615
587
|
if (!buttons || buttons.length === 0) return null;
|
|
616
|
-
return /* @__PURE__ */
|
|
617
|
-
title && /* @__PURE__ */
|
|
588
|
+
return /* @__PURE__ */ jsxs("div", { style: { padding: "2rem 1.5rem", maxWidth: 480, margin: "0 auto", display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
589
|
+
title && /* @__PURE__ */ jsx("h2", { style: {
|
|
618
590
|
fontSize: "clamp(1.25rem, 4vw, 1.5rem)",
|
|
619
591
|
fontWeight: 300,
|
|
620
592
|
fontFamily: theme.fontDisplay || "inherit",
|
|
@@ -624,7 +596,7 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
624
596
|
color: theme.fg,
|
|
625
597
|
textAlign: "center"
|
|
626
598
|
}, children: title }),
|
|
627
|
-
subtitle && /* @__PURE__ */
|
|
599
|
+
subtitle && /* @__PURE__ */ jsx("p", { style: {
|
|
628
600
|
fontSize: "0.8rem",
|
|
629
601
|
color: theme.accent,
|
|
630
602
|
margin: "0 0 0.75rem",
|
|
@@ -635,7 +607,7 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
635
607
|
}, children: subtitle }),
|
|
636
608
|
buttons.map((btn, i) => {
|
|
637
609
|
const isPrimary = btn.style !== "outline";
|
|
638
|
-
return /* @__PURE__ */
|
|
610
|
+
return /* @__PURE__ */ jsx(
|
|
639
611
|
"a",
|
|
640
612
|
{
|
|
641
613
|
href: btn.url,
|
|
@@ -670,42 +642,28 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
670
642
|
const layout = section.config?.layout;
|
|
671
643
|
if (!stats || stats.length === 0) return null;
|
|
672
644
|
if (layout === "list") {
|
|
673
|
-
return /* @__PURE__ */
|
|
674
|
-
/* @__PURE__ */
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
alignItems: "baseline",
|
|
678
|
-
padding: "0.625rem 0"
|
|
679
|
-
}, children: [
|
|
680
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: {
|
|
681
|
-
fontSize: 12,
|
|
682
|
-
textTransform: "uppercase",
|
|
683
|
-
letterSpacing: "0.15em",
|
|
684
|
-
color: `${theme.fg}66`
|
|
685
|
-
}, children: stat.label }),
|
|
686
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 14, fontWeight: 300, color: `${theme.fg}CC` }, children: /* @__PURE__ */ jsxRuntime.jsx(AnimatedText, { text: stat.value }) })
|
|
645
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", maxWidth: 640, margin: "0 auto" }, children: stats.map((stat, i) => /* @__PURE__ */ jsxs("div", { children: [
|
|
646
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "baseline", padding: "0.625rem 0" }, children: [
|
|
647
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 12, textTransform: "uppercase", letterSpacing: "0.15em", color: `${theme.fg}66` }, children: stat.label }),
|
|
648
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14, fontWeight: 300, color: `${theme.fg}CC` }, children: /* @__PURE__ */ jsx(AnimatedText, { text: stat.value }) })
|
|
687
649
|
] }),
|
|
688
|
-
i < stats.length - 1 && /* @__PURE__ */
|
|
650
|
+
i < stats.length - 1 && /* @__PURE__ */ jsx("hr", { style: { border: "none", borderTop: `1px solid ${theme.fg}0A`, margin: 0 } })
|
|
689
651
|
] }, i)) });
|
|
690
652
|
}
|
|
691
653
|
const columns = Math.min(stats.length, 4);
|
|
692
|
-
return /* @__PURE__ */
|
|
693
|
-
display: "grid",
|
|
694
|
-
gridTemplateColumns: `repeat(${columns}, 1fr)`,
|
|
695
|
-
border: `1px solid ${theme.fg}0F`
|
|
696
|
-
}, children: stats.map((stat, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { style: {
|
|
654
|
+
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: {
|
|
697
655
|
padding: "1.25rem 0.5rem",
|
|
698
656
|
textAlign: "center",
|
|
699
657
|
borderRight: i < stats.length - 1 ? `1px solid ${theme.fg}0F` : void 0
|
|
700
658
|
}, children: [
|
|
701
|
-
/* @__PURE__ */
|
|
659
|
+
/* @__PURE__ */ jsx("div", { style: {
|
|
702
660
|
fontFamily: theme.fontDisplay || "inherit",
|
|
703
661
|
fontSize: "clamp(1.5rem, 5vw, 2rem)",
|
|
704
662
|
fontWeight: 300,
|
|
705
663
|
lineHeight: 1,
|
|
706
664
|
color: theme.fg
|
|
707
|
-
}, children: /* @__PURE__ */
|
|
708
|
-
/* @__PURE__ */
|
|
665
|
+
}, children: /* @__PURE__ */ jsx(AnimatedText, { text: stat.value }) }),
|
|
666
|
+
/* @__PURE__ */ jsx("div", { style: {
|
|
709
667
|
fontSize: 11,
|
|
710
668
|
fontWeight: 500,
|
|
711
669
|
textTransform: "uppercase",
|
|
@@ -722,12 +680,12 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
722
680
|
const description = c.description || product?.description || "";
|
|
723
681
|
const imageUrl = c.image_url || product?.featured_image || null;
|
|
724
682
|
const url = c.url || null;
|
|
725
|
-
return /* @__PURE__ */
|
|
726
|
-
imageUrl && /* @__PURE__ */
|
|
727
|
-
/* @__PURE__ */
|
|
728
|
-
/* @__PURE__ */
|
|
729
|
-
description && /* @__PURE__ */
|
|
730
|
-
url && /* @__PURE__ */
|
|
683
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", maxWidth: 480, margin: "0 auto" }, children: /* @__PURE__ */ jsxs("div", { style: { background: theme.surface, overflow: "hidden" }, children: [
|
|
684
|
+
imageUrl && /* @__PURE__ */ jsx("div", { style: { width: "100%", aspectRatio: "1", overflow: "hidden" }, children: /* @__PURE__ */ jsx("img", { src: imageUrl, alt: name, style: { width: "100%", height: "100%", objectFit: "cover", display: "block" } }) }),
|
|
685
|
+
/* @__PURE__ */ jsxs("div", { style: { padding: "1.25rem" }, children: [
|
|
686
|
+
/* @__PURE__ */ jsx("h3", { style: { fontSize: "1.25rem", fontWeight: 600, margin: "0 0 0.5rem", color: theme.fg }, children: name }),
|
|
687
|
+
description && /* @__PURE__ */ jsx("p", { style: { fontSize: "0.9rem", color: theme.muted, margin: "0 0 1rem", lineHeight: 1.5 }, children: description }),
|
|
688
|
+
url && /* @__PURE__ */ jsx(
|
|
731
689
|
"a",
|
|
732
690
|
{
|
|
733
691
|
href: url,
|
|
@@ -752,13 +710,7 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
752
710
|
] })
|
|
753
711
|
] }) });
|
|
754
712
|
}
|
|
755
|
-
function COAViewerSection({
|
|
756
|
-
section,
|
|
757
|
-
data,
|
|
758
|
-
theme,
|
|
759
|
-
onShowCOA,
|
|
760
|
-
tracking
|
|
761
|
-
}) {
|
|
713
|
+
function COAViewerSection({ section, data, theme, onShowCOA, tracking }) {
|
|
762
714
|
const coa = data?.coa;
|
|
763
715
|
const c = section.content;
|
|
764
716
|
if (!coa) return null;
|
|
@@ -780,7 +732,7 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
780
732
|
};
|
|
781
733
|
const buttonLabel = c.button_text || "View Lab Results";
|
|
782
734
|
if (coa.viewer_url) {
|
|
783
|
-
return /* @__PURE__ */
|
|
735
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", maxWidth: 480, margin: "0 auto" }, children: /* @__PURE__ */ jsx(
|
|
784
736
|
"a",
|
|
785
737
|
{
|
|
786
738
|
href: coa.viewer_url,
|
|
@@ -792,28 +744,56 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
792
744
|
}
|
|
793
745
|
) });
|
|
794
746
|
}
|
|
795
|
-
return /* @__PURE__ */
|
|
747
|
+
return /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", maxWidth: 480, margin: "0 auto" }, children: /* @__PURE__ */ jsx("button", { onClick: () => {
|
|
796
748
|
trackClick(tracking, buttonLabel, coa.url);
|
|
797
749
|
onShowCOA();
|
|
798
750
|
}, style: buttonStyle, children: buttonLabel }) });
|
|
799
751
|
}
|
|
752
|
+
function COAModal({ coa, theme, onClose }) {
|
|
753
|
+
return /* @__PURE__ */ jsxs("div", { style: { position: "fixed", inset: 0, zIndex: 9999, background: "rgba(0,0,0,0.95)", display: "flex", flexDirection: "column" }, children: [
|
|
754
|
+
/* @__PURE__ */ jsxs("div", { style: {
|
|
755
|
+
display: "flex",
|
|
756
|
+
justifyContent: "space-between",
|
|
757
|
+
alignItems: "center",
|
|
758
|
+
padding: "0.75rem 1rem",
|
|
759
|
+
borderBottom: `1px solid ${theme.fg}10`
|
|
760
|
+
}, children: [
|
|
761
|
+
/* @__PURE__ */ jsx("span", { style: { color: "#fff", fontWeight: 500, fontSize: "0.85rem" }, children: coa.document_name || "Lab Results" }),
|
|
762
|
+
/* @__PURE__ */ jsx("button", { onClick: onClose, style: {
|
|
763
|
+
background: `${theme.fg}10`,
|
|
764
|
+
border: "none",
|
|
765
|
+
color: "#fff",
|
|
766
|
+
fontSize: "0.85rem",
|
|
767
|
+
cursor: "pointer",
|
|
768
|
+
padding: "0.375rem 0.75rem"
|
|
769
|
+
}, children: "Close" })
|
|
770
|
+
] }),
|
|
771
|
+
/* @__PURE__ */ jsx("iframe", { src: coa.url, style: { flex: 1, border: "none", background: "#fff" }, title: "Lab Results" })
|
|
772
|
+
] });
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
// src/react/components/sections/lead-capture-section.tsx
|
|
800
776
|
function LeadCaptureSection({ section, data, theme, onEvent }) {
|
|
801
777
|
const c = section.content;
|
|
802
|
-
const [firstName, setFirstName] =
|
|
803
|
-
const [email, setEmail] =
|
|
804
|
-
const [newsletterOptIn, setNewsletterOptIn] =
|
|
805
|
-
const [status, setStatus] =
|
|
806
|
-
const [errorMsg, setErrorMsg] =
|
|
778
|
+
const [firstName, setFirstName] = useState("");
|
|
779
|
+
const [email, setEmail] = useState("");
|
|
780
|
+
const [newsletterOptIn, setNewsletterOptIn] = useState(false);
|
|
781
|
+
const [status, setStatus] = useState("idle");
|
|
782
|
+
const [errorMsg, setErrorMsg] = useState("");
|
|
807
783
|
const gatewayUrl = c.gateway_url || data.gatewayUrl || "https://whale-gateway.fly.dev";
|
|
808
784
|
const storeId = c.store_id || data.store?.id;
|
|
809
785
|
const slug = c.landing_page_slug || data.landing_page?.slug;
|
|
786
|
+
const heading = c.heading || "get 10% off your first visit.";
|
|
787
|
+
const subtitle = c.subtitle || "drop your email and we will send you the code.";
|
|
788
|
+
const buttonText = c.button_text || "Claim My Discount";
|
|
789
|
+
const successHeading = c.success_heading || "You\u2019re in!";
|
|
790
|
+
const successMessage = c.success_message || "Check your inbox for the discount code.";
|
|
810
791
|
async function handleSubmit(e) {
|
|
811
792
|
e.preventDefault();
|
|
812
793
|
if (!email || !storeId) return;
|
|
813
794
|
setStatus("loading");
|
|
814
795
|
setErrorMsg("");
|
|
815
796
|
const urlParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
|
|
816
|
-
const analyticsData = data.analyticsContext;
|
|
817
797
|
try {
|
|
818
798
|
const res = await fetch(`${gatewayUrl}/v1/stores/${storeId}/storefront/leads`, {
|
|
819
799
|
method: "POST",
|
|
@@ -829,8 +809,8 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
829
809
|
if (newsletterOptIn) t.push(c.newsletter_tag || "newsletter-subscriber");
|
|
830
810
|
return t.length > 0 ? t : void 0;
|
|
831
811
|
})(),
|
|
832
|
-
visitor_id:
|
|
833
|
-
session_id:
|
|
812
|
+
visitor_id: data.analyticsContext?.visitorId || void 0,
|
|
813
|
+
session_id: data.analyticsContext?.sessionId || void 0,
|
|
834
814
|
utm_source: urlParams?.get("utm_source") || void 0,
|
|
835
815
|
utm_medium: urlParams?.get("utm_medium") || void 0,
|
|
836
816
|
utm_campaign: urlParams?.get("utm_campaign") || void 0,
|
|
@@ -848,11 +828,6 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
848
828
|
setStatus("error");
|
|
849
829
|
}
|
|
850
830
|
}
|
|
851
|
-
const heading = c.heading || "get 10% off your first visit.";
|
|
852
|
-
const subtitle = c.subtitle || "drop your email and we will send you the code.";
|
|
853
|
-
const buttonText = c.button_text || "Claim My Discount";
|
|
854
|
-
const successHeading = c.success_heading || "You\u2019re in!";
|
|
855
|
-
const successMessage = c.success_message || "Check your inbox for the discount code.";
|
|
856
831
|
const inputStyle = {
|
|
857
832
|
flex: 1,
|
|
858
833
|
minWidth: 0,
|
|
@@ -867,43 +842,12 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
867
842
|
fontFamily: "inherit",
|
|
868
843
|
transition: "border-color 0.2s"
|
|
869
844
|
};
|
|
870
|
-
return /* @__PURE__ */
|
|
871
|
-
|
|
872
|
-
/* @__PURE__ */
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
}, children: status === "success" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center" }, children: [
|
|
877
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { style: {
|
|
878
|
-
fontSize: "clamp(1.5rem, 5vw, 2rem)",
|
|
879
|
-
fontWeight: 300,
|
|
880
|
-
fontFamily: theme.fontDisplay || "inherit",
|
|
881
|
-
margin: "0 0 0.75rem",
|
|
882
|
-
lineHeight: 1.2,
|
|
883
|
-
letterSpacing: "-0.02em",
|
|
884
|
-
color: theme.fg
|
|
885
|
-
}, children: successHeading }),
|
|
886
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { style: {
|
|
887
|
-
fontSize: "0.9rem",
|
|
888
|
-
color: `${theme.fg}99`,
|
|
889
|
-
margin: "0 0 1.5rem",
|
|
890
|
-
lineHeight: 1.6,
|
|
891
|
-
fontWeight: 300
|
|
892
|
-
}, children: successMessage }),
|
|
893
|
-
c.coupon_code && /* @__PURE__ */ jsxRuntime.jsx("div", { style: {
|
|
894
|
-
display: "inline-block",
|
|
895
|
-
padding: "0.75rem 2rem",
|
|
896
|
-
background: `${theme.fg}08`,
|
|
897
|
-
border: `1px dashed ${theme.fg}30`,
|
|
898
|
-
fontSize: "clamp(1.25rem, 4vw, 1.75rem)",
|
|
899
|
-
fontWeight: 500,
|
|
900
|
-
fontFamily: "monospace",
|
|
901
|
-
letterSpacing: "0.12em",
|
|
902
|
-
color: theme.accent
|
|
903
|
-
}, children: c.coupon_code })
|
|
904
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
905
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { textAlign: "center", marginBottom: "clamp(1.5rem, 4vw, 2rem)" }, children: [
|
|
906
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { style: {
|
|
845
|
+
if (status === "success") return /* @__PURE__ */ jsx(SuccessState, { theme, heading: successHeading, message: successMessage, couponCode: c.coupon_code });
|
|
846
|
+
return /* @__PURE__ */ jsxs("div", { style: { padding: "3.5rem 1.5rem", maxWidth: 560, margin: "0 auto" }, children: [
|
|
847
|
+
/* @__PURE__ */ jsx("style", { children: `@keyframes lc-spin { to { transform: rotate(360deg) } }` }),
|
|
848
|
+
/* @__PURE__ */ jsxs("div", { style: { background: theme.surface, border: `1px solid ${theme.fg}12`, padding: "clamp(2rem, 6vw, 3rem)" }, children: [
|
|
849
|
+
/* @__PURE__ */ jsxs("div", { style: { textAlign: "center", marginBottom: "clamp(1.5rem, 4vw, 2rem)" }, children: [
|
|
850
|
+
/* @__PURE__ */ jsx("h2", { style: {
|
|
907
851
|
fontSize: "clamp(1.5rem, 5vw, 2.25rem)",
|
|
908
852
|
fontWeight: 300,
|
|
909
853
|
fontFamily: theme.fontDisplay || "inherit",
|
|
@@ -912,7 +856,7 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
912
856
|
letterSpacing: "-0.02em",
|
|
913
857
|
color: theme.fg
|
|
914
858
|
}, children: heading }),
|
|
915
|
-
/* @__PURE__ */
|
|
859
|
+
/* @__PURE__ */ jsx("p", { style: {
|
|
916
860
|
fontSize: "0.85rem",
|
|
917
861
|
color: theme.accent,
|
|
918
862
|
margin: 0,
|
|
@@ -921,31 +865,12 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
921
865
|
letterSpacing: "0.15em"
|
|
922
866
|
}, children: subtitle })
|
|
923
867
|
] }),
|
|
924
|
-
/* @__PURE__ */
|
|
925
|
-
/* @__PURE__ */
|
|
926
|
-
/* @__PURE__ */
|
|
927
|
-
|
|
928
|
-
{
|
|
929
|
-
type: "text",
|
|
930
|
-
placeholder: "First name",
|
|
931
|
-
value: firstName,
|
|
932
|
-
onChange: (e) => setFirstName(e.target.value),
|
|
933
|
-
style: inputStyle
|
|
934
|
-
}
|
|
935
|
-
),
|
|
936
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
937
|
-
"input",
|
|
938
|
-
{
|
|
939
|
-
type: "email",
|
|
940
|
-
placeholder: "Email address",
|
|
941
|
-
value: email,
|
|
942
|
-
onChange: (e) => setEmail(e.target.value),
|
|
943
|
-
required: true,
|
|
944
|
-
style: inputStyle
|
|
945
|
-
}
|
|
946
|
-
)
|
|
868
|
+
/* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
|
|
869
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.75rem", flexWrap: "wrap" }, children: [
|
|
870
|
+
/* @__PURE__ */ jsx("input", { type: "text", placeholder: "First name", value: firstName, onChange: (e) => setFirstName(e.target.value), style: inputStyle }),
|
|
871
|
+
/* @__PURE__ */ jsx("input", { type: "email", placeholder: "Email address", value: email, onChange: (e) => setEmail(e.target.value), required: true, style: inputStyle })
|
|
947
872
|
] }),
|
|
948
|
-
c.show_newsletter_opt_in !== false && /* @__PURE__ */
|
|
873
|
+
c.show_newsletter_opt_in !== false && /* @__PURE__ */ jsxs("label", { style: {
|
|
949
874
|
display: "flex",
|
|
950
875
|
alignItems: "center",
|
|
951
876
|
gap: "0.5rem",
|
|
@@ -955,126 +880,145 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
955
880
|
fontWeight: 300,
|
|
956
881
|
lineHeight: 1.4
|
|
957
882
|
}, children: [
|
|
958
|
-
/* @__PURE__ */
|
|
883
|
+
/* @__PURE__ */ jsx(
|
|
959
884
|
"input",
|
|
960
885
|
{
|
|
961
886
|
type: "checkbox",
|
|
962
887
|
checked: newsletterOptIn,
|
|
963
888
|
onChange: (e) => setNewsletterOptIn(e.target.checked),
|
|
964
|
-
style: {
|
|
965
|
-
width: 16,
|
|
966
|
-
height: 16,
|
|
967
|
-
accentColor: theme.accent,
|
|
968
|
-
cursor: "pointer",
|
|
969
|
-
flexShrink: 0
|
|
970
|
-
}
|
|
889
|
+
style: { width: 16, height: 16, accentColor: theme.accent, cursor: "pointer", flexShrink: 0 }
|
|
971
890
|
}
|
|
972
891
|
),
|
|
973
892
|
c.newsletter_label || "Also sign me up for the newsletter \u2014 new drops, deals, and company news."
|
|
974
893
|
] }),
|
|
975
|
-
status === "error" && errorMsg && /* @__PURE__ */
|
|
976
|
-
/* @__PURE__ */
|
|
977
|
-
"
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
borderTopColor: theme.bg,
|
|
1007
|
-
borderRadius: "50%",
|
|
1008
|
-
animation: "lc-spin 0.8s linear infinite"
|
|
1009
|
-
} }),
|
|
1010
|
-
buttonText
|
|
1011
|
-
]
|
|
1012
|
-
}
|
|
1013
|
-
)
|
|
894
|
+
status === "error" && errorMsg && /* @__PURE__ */ jsx("p", { style: { fontSize: "0.8rem", color: "#e55", margin: 0, fontWeight: 400 }, children: errorMsg }),
|
|
895
|
+
/* @__PURE__ */ jsxs("button", { type: "submit", disabled: status === "loading", style: {
|
|
896
|
+
width: "100%",
|
|
897
|
+
padding: "0.875rem",
|
|
898
|
+
background: theme.fg,
|
|
899
|
+
color: theme.bg,
|
|
900
|
+
border: "none",
|
|
901
|
+
fontSize: "0.85rem",
|
|
902
|
+
fontWeight: 500,
|
|
903
|
+
cursor: status === "loading" ? "wait" : "pointer",
|
|
904
|
+
letterSpacing: "0.08em",
|
|
905
|
+
textTransform: "uppercase",
|
|
906
|
+
fontFamily: "inherit",
|
|
907
|
+
display: "flex",
|
|
908
|
+
alignItems: "center",
|
|
909
|
+
justifyContent: "center",
|
|
910
|
+
gap: "0.5rem",
|
|
911
|
+
opacity: status === "loading" ? 0.7 : 1,
|
|
912
|
+
transition: "opacity 0.2s"
|
|
913
|
+
}, children: [
|
|
914
|
+
status === "loading" && /* @__PURE__ */ jsx("span", { style: {
|
|
915
|
+
display: "inline-block",
|
|
916
|
+
width: 16,
|
|
917
|
+
height: 16,
|
|
918
|
+
border: `2px solid ${theme.bg}40`,
|
|
919
|
+
borderTopColor: theme.bg,
|
|
920
|
+
borderRadius: "50%",
|
|
921
|
+
animation: "lc-spin 0.8s linear infinite"
|
|
922
|
+
} }),
|
|
923
|
+
buttonText
|
|
924
|
+
] })
|
|
1014
925
|
] })
|
|
1015
|
-
] })
|
|
926
|
+
] })
|
|
1016
927
|
] });
|
|
1017
928
|
}
|
|
1018
|
-
function
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
929
|
+
function SuccessState({ theme, heading, message, couponCode }) {
|
|
930
|
+
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: [
|
|
931
|
+
/* @__PURE__ */ jsx("h2", { style: {
|
|
932
|
+
fontSize: "clamp(1.5rem, 5vw, 2rem)",
|
|
933
|
+
fontWeight: 300,
|
|
934
|
+
fontFamily: theme.fontDisplay || "inherit",
|
|
935
|
+
margin: "0 0 0.75rem",
|
|
936
|
+
lineHeight: 1.2,
|
|
937
|
+
letterSpacing: "-0.02em",
|
|
938
|
+
color: theme.fg
|
|
939
|
+
}, children: heading }),
|
|
940
|
+
/* @__PURE__ */ jsx("p", { style: { fontSize: "0.9rem", color: `${theme.fg}99`, margin: "0 0 1.5rem", lineHeight: 1.6, fontWeight: 300 }, children: message }),
|
|
941
|
+
couponCode && /* @__PURE__ */ jsx("div", { style: {
|
|
942
|
+
display: "inline-block",
|
|
943
|
+
padding: "0.75rem 2rem",
|
|
944
|
+
background: `${theme.fg}08`,
|
|
945
|
+
border: `1px dashed ${theme.fg}30`,
|
|
946
|
+
fontSize: "clamp(1.25rem, 4vw, 1.75rem)",
|
|
947
|
+
fontWeight: 500,
|
|
948
|
+
fontFamily: "monospace",
|
|
949
|
+
letterSpacing: "0.12em",
|
|
950
|
+
color: theme.accent
|
|
951
|
+
}, children: couponCode })
|
|
952
|
+
] }) });
|
|
1042
953
|
}
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
954
|
+
|
|
955
|
+
// src/react/components/section-renderer.tsx
|
|
956
|
+
function SectionRenderer({
|
|
957
|
+
section,
|
|
958
|
+
data,
|
|
959
|
+
theme,
|
|
960
|
+
tracking,
|
|
961
|
+
onEvent
|
|
962
|
+
}) {
|
|
963
|
+
const [showCOA, setShowCOA] = useState(false);
|
|
964
|
+
const el = (() => {
|
|
965
|
+
switch (section.type) {
|
|
966
|
+
case "hero":
|
|
967
|
+
return /* @__PURE__ */ jsx(HeroSection, { section, theme, tracking, onEvent });
|
|
968
|
+
case "text":
|
|
969
|
+
return /* @__PURE__ */ jsx(TextSection, { section, theme });
|
|
970
|
+
case "image":
|
|
971
|
+
return /* @__PURE__ */ jsx(ImageSection, { section, theme });
|
|
972
|
+
case "video":
|
|
973
|
+
return /* @__PURE__ */ jsx(VideoSection, { section, theme });
|
|
974
|
+
case "gallery":
|
|
975
|
+
return /* @__PURE__ */ jsx(GallerySection, { section, theme });
|
|
976
|
+
case "cta":
|
|
977
|
+
return /* @__PURE__ */ jsx(CTASection, { section, theme, tracking, onEvent });
|
|
978
|
+
case "stats":
|
|
979
|
+
return /* @__PURE__ */ jsx(StatsSection, { section, theme });
|
|
980
|
+
case "product_card":
|
|
981
|
+
return /* @__PURE__ */ jsx(ProductCardSection, { section, data, theme, tracking });
|
|
982
|
+
case "coa_viewer":
|
|
983
|
+
return /* @__PURE__ */ jsx(COAViewerSection, { section, data, theme, onShowCOA: () => setShowCOA(true), tracking });
|
|
984
|
+
case "social_links":
|
|
985
|
+
return /* @__PURE__ */ jsx(SocialLinksSection, { section, theme });
|
|
986
|
+
case "lead_capture":
|
|
987
|
+
return /* @__PURE__ */ jsx(LeadCaptureSection, { section, data, theme, onEvent });
|
|
988
|
+
case "divider":
|
|
989
|
+
return /* @__PURE__ */ jsx(DividerSection, { theme });
|
|
990
|
+
default:
|
|
991
|
+
return null;
|
|
992
|
+
}
|
|
993
|
+
})();
|
|
994
|
+
const sectionRef = useRef(null);
|
|
995
|
+
useEffect(() => {
|
|
996
|
+
const el2 = sectionRef.current;
|
|
997
|
+
if (!el2 || typeof IntersectionObserver === "undefined") return;
|
|
998
|
+
const obs = new IntersectionObserver(
|
|
999
|
+
([entry]) => {
|
|
1000
|
+
if (entry.isIntersecting) {
|
|
1001
|
+
onEvent?.("section_view", { section_id: section.id, section_type: section.type });
|
|
1002
|
+
obs.disconnect();
|
|
1066
1003
|
}
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1004
|
+
},
|
|
1005
|
+
{ threshold: 0.5 }
|
|
1006
|
+
);
|
|
1007
|
+
obs.observe(el2);
|
|
1008
|
+
return () => obs.disconnect();
|
|
1009
|
+
}, [section.id, section.type, onEvent]);
|
|
1010
|
+
return /* @__PURE__ */ jsxs("div", { ref: sectionRef, "data-section-id": section.id, "data-section-type": section.type, children: [
|
|
1011
|
+
el,
|
|
1012
|
+
showCOA && data?.coa && /* @__PURE__ */ jsx(COAModal, { coa: data.coa, theme, onClose: () => setShowCOA(false) })
|
|
1070
1013
|
] });
|
|
1071
1014
|
}
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1015
|
+
|
|
1016
|
+
// src/react/components/landing-page.tsx
|
|
1017
|
+
function getInlinedData() {
|
|
1018
|
+
if (typeof window !== "undefined" && window.__LANDING_DATA__) {
|
|
1019
|
+
return window.__LANDING_DATA__;
|
|
1020
|
+
}
|
|
1021
|
+
return null;
|
|
1078
1022
|
}
|
|
1079
1023
|
function LandingPage({
|
|
1080
1024
|
slug,
|
|
@@ -1086,47 +1030,43 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
1086
1030
|
analyticsContext,
|
|
1087
1031
|
enableAnalytics = true
|
|
1088
1032
|
}) {
|
|
1089
|
-
const
|
|
1090
|
-
const [
|
|
1091
|
-
const [
|
|
1092
|
-
|
|
1033
|
+
const inlined = useRef(getInlinedData()).current;
|
|
1034
|
+
const [state, setState] = useState(inlined ? "ready" : "loading");
|
|
1035
|
+
const [data, setData] = useState(inlined);
|
|
1036
|
+
const [errorMsg, setErrorMsg] = useState("");
|
|
1037
|
+
useEffect(() => {
|
|
1093
1038
|
if (!slug) return;
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
const json = window.__LANDING_DATA__;
|
|
1097
|
-
setData(json);
|
|
1098
|
-
setState("ready");
|
|
1099
|
-
onDataLoaded?.(json);
|
|
1039
|
+
if (data) {
|
|
1040
|
+
onDataLoaded?.(data);
|
|
1100
1041
|
return;
|
|
1101
1042
|
}
|
|
1043
|
+
let cancelled = false;
|
|
1102
1044
|
async function load() {
|
|
1103
1045
|
try {
|
|
1104
1046
|
const res = await fetch(`${gatewayUrl}/l/${encodeURIComponent(slug)}`);
|
|
1105
|
-
if (
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
}
|
|
1110
|
-
if (res.status === 410) {
|
|
1111
|
-
setState("expired");
|
|
1112
|
-
return;
|
|
1113
|
-
}
|
|
1114
|
-
if (!res.ok) {
|
|
1115
|
-
const body = await res.json().catch(() => ({}));
|
|
1116
|
-
throw new Error(body?.error?.message ?? `Failed to load: ${res.status}`);
|
|
1117
|
-
}
|
|
1118
|
-
const json = await res.json();
|
|
1119
|
-
setData(json);
|
|
1120
|
-
setState("ready");
|
|
1121
|
-
onDataLoaded?.(json);
|
|
1047
|
+
if (cancelled) return;
|
|
1048
|
+
if (res.status === 404) {
|
|
1049
|
+
setState("not_found");
|
|
1050
|
+
return;
|
|
1122
1051
|
}
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1052
|
+
if (res.status === 410) {
|
|
1053
|
+
setState("expired");
|
|
1054
|
+
return;
|
|
1055
|
+
}
|
|
1056
|
+
if (!res.ok) {
|
|
1057
|
+
const body = await res.json().catch(() => ({}));
|
|
1058
|
+
throw new Error(body?.error?.message ?? `Failed to load: ${res.status}`);
|
|
1129
1059
|
}
|
|
1060
|
+
const json = await res.json();
|
|
1061
|
+
setData(json);
|
|
1062
|
+
setState("ready");
|
|
1063
|
+
onDataLoaded?.(json);
|
|
1064
|
+
} catch (err) {
|
|
1065
|
+
if (cancelled) return;
|
|
1066
|
+
const e = err instanceof Error ? err : new Error(String(err));
|
|
1067
|
+
setErrorMsg(e.message);
|
|
1068
|
+
setState("error");
|
|
1069
|
+
onError?.(e);
|
|
1130
1070
|
}
|
|
1131
1071
|
}
|
|
1132
1072
|
load();
|
|
@@ -1134,12 +1074,22 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
1134
1074
|
cancelled = true;
|
|
1135
1075
|
};
|
|
1136
1076
|
}, [slug, gatewayUrl]);
|
|
1137
|
-
if (state === "loading") return /* @__PURE__ */
|
|
1138
|
-
if (state === "not_found") return /* @__PURE__ */
|
|
1139
|
-
if (state === "expired") return /* @__PURE__ */
|
|
1140
|
-
if (state === "error") return /* @__PURE__ */
|
|
1077
|
+
if (state === "loading") return /* @__PURE__ */ jsx(StateScreen, { title: "", loading: true });
|
|
1078
|
+
if (state === "not_found") return /* @__PURE__ */ jsx(StateScreen, { title: "Page Not Found", subtitle: "This page does not exist or has been removed." });
|
|
1079
|
+
if (state === "expired") return /* @__PURE__ */ jsx(StateScreen, { title: "Page Expired", subtitle: "This page is no longer active." });
|
|
1080
|
+
if (state === "error") return /* @__PURE__ */ jsx(StateScreen, { title: "Something Went Wrong", subtitle: errorMsg || "Please try again later." });
|
|
1141
1081
|
if (!data) return null;
|
|
1142
|
-
return /* @__PURE__ */
|
|
1082
|
+
return /* @__PURE__ */ jsx(
|
|
1083
|
+
PageLayout,
|
|
1084
|
+
{
|
|
1085
|
+
data,
|
|
1086
|
+
gatewayUrl,
|
|
1087
|
+
renderSection,
|
|
1088
|
+
onEvent,
|
|
1089
|
+
analyticsContext,
|
|
1090
|
+
enableAnalytics
|
|
1091
|
+
}
|
|
1092
|
+
);
|
|
1143
1093
|
}
|
|
1144
1094
|
function isSectionVisible(section, urlParams) {
|
|
1145
1095
|
const vis = section.config?.visibility;
|
|
@@ -1159,11 +1109,11 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
1159
1109
|
enableAnalytics
|
|
1160
1110
|
}) {
|
|
1161
1111
|
const { landing_page: lp, store } = data;
|
|
1162
|
-
const trackerRef =
|
|
1163
|
-
|
|
1112
|
+
const trackerRef = useRef(null);
|
|
1113
|
+
useEffect(() => {
|
|
1164
1114
|
if (!enableAnalytics || typeof window === "undefined") return;
|
|
1165
|
-
const
|
|
1166
|
-
if (!
|
|
1115
|
+
const config = window.__LANDING_ANALYTICS__;
|
|
1116
|
+
if (!config?.slug) return;
|
|
1167
1117
|
let visitorId = localStorage.getItem("wt_vid") || "";
|
|
1168
1118
|
if (!visitorId) {
|
|
1169
1119
|
visitorId = crypto.randomUUID();
|
|
@@ -1175,8 +1125,8 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
1175
1125
|
sessionStorage.setItem("wt_sid", sessionId);
|
|
1176
1126
|
}
|
|
1177
1127
|
Promise.resolve().then(() => (init_tracker(), tracker_exports)).then(({ BehavioralTracker: BehavioralTracker2 }) => {
|
|
1178
|
-
const gwUrl =
|
|
1179
|
-
const slug =
|
|
1128
|
+
const gwUrl = config.gatewayUrl || gatewayUrl;
|
|
1129
|
+
const slug = config.slug;
|
|
1180
1130
|
const utmParams = new URLSearchParams(window.location.search);
|
|
1181
1131
|
const tracker = new BehavioralTracker2({
|
|
1182
1132
|
sessionId,
|
|
@@ -1187,65 +1137,44 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
1187
1137
|
event_data: e.data,
|
|
1188
1138
|
session_id: batch.session_id,
|
|
1189
1139
|
visitor_id: batch.visitor_id,
|
|
1190
|
-
campaign_id:
|
|
1140
|
+
campaign_id: config.campaignId || utmParams.get("utm_campaign_id") || void 0,
|
|
1191
1141
|
utm_source: utmParams.get("utm_source") || void 0,
|
|
1192
1142
|
utm_medium: utmParams.get("utm_medium") || void 0,
|
|
1193
1143
|
utm_campaign: utmParams.get("utm_campaign") || void 0
|
|
1194
1144
|
}));
|
|
1195
|
-
|
|
1196
|
-
if (typeof navigator !== "undefined" && navigator.sendBeacon) {
|
|
1197
|
-
navigator.sendBeacon(
|
|
1198
|
-
`${gwUrl}/l/${encodeURIComponent(slug)}/events`,
|
|
1199
|
-
new Blob([body], { type: "application/json" })
|
|
1200
|
-
);
|
|
1201
|
-
} else {
|
|
1202
|
-
await fetch(`${gwUrl}/l/${encodeURIComponent(slug)}/events`, {
|
|
1203
|
-
method: "POST",
|
|
1204
|
-
headers: { "Content-Type": "application/json" },
|
|
1205
|
-
body,
|
|
1206
|
-
keepalive: true
|
|
1207
|
-
});
|
|
1208
|
-
}
|
|
1145
|
+
sendEvents(gwUrl, slug, events);
|
|
1209
1146
|
}
|
|
1210
1147
|
});
|
|
1211
1148
|
tracker.setPageContext(window.location.href, window.location.pathname);
|
|
1212
1149
|
tracker.start();
|
|
1213
1150
|
trackerRef.current = tracker;
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
utm_source: utmParams.get("utm_source") || void 0,
|
|
1222
|
-
utm_medium: utmParams.get("utm_medium") || void 0,
|
|
1223
|
-
utm_campaign: utmParams.get("utm_campaign") || void 0
|
|
1224
|
-
}]
|
|
1225
|
-
});
|
|
1226
|
-
if (navigator.sendBeacon) {
|
|
1227
|
-
navigator.sendBeacon(
|
|
1228
|
-
`${gwUrl}/l/${encodeURIComponent(slug)}/events`,
|
|
1229
|
-
new Blob([pageViewBody], { type: "application/json" })
|
|
1230
|
-
);
|
|
1231
|
-
} else {
|
|
1232
|
-
fetch(`${gwUrl}/l/${encodeURIComponent(slug)}/events`, {
|
|
1233
|
-
method: "POST",
|
|
1234
|
-
headers: { "Content-Type": "application/json" },
|
|
1235
|
-
body: pageViewBody,
|
|
1236
|
-
keepalive: true
|
|
1237
|
-
}).catch(() => {
|
|
1238
|
-
});
|
|
1239
|
-
}
|
|
1151
|
+
sendEvents(gwUrl, slug, [{
|
|
1152
|
+
event_type: "page_view",
|
|
1153
|
+
event_data: { referrer: document.referrer, url: window.location.href },
|
|
1154
|
+
session_id: sessionId,
|
|
1155
|
+
visitor_id: visitorId,
|
|
1156
|
+
campaign_id: config.campaignId || void 0
|
|
1157
|
+
}]);
|
|
1240
1158
|
}).catch(() => {
|
|
1241
1159
|
});
|
|
1242
1160
|
return () => {
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
trackerRef.current = null;
|
|
1246
|
-
}
|
|
1161
|
+
trackerRef.current?.stop();
|
|
1162
|
+
trackerRef.current = null;
|
|
1247
1163
|
};
|
|
1248
1164
|
}, [enableAnalytics, gatewayUrl]);
|
|
1165
|
+
const handleEvent = useCallback((event, eventData) => {
|
|
1166
|
+
onEvent?.(event, eventData);
|
|
1167
|
+
if (!enableAnalytics || typeof window === "undefined") return;
|
|
1168
|
+
const config = window.__LANDING_ANALYTICS__;
|
|
1169
|
+
if (!config?.slug) return;
|
|
1170
|
+
sendEvents(config.gatewayUrl || gatewayUrl, config.slug, [{
|
|
1171
|
+
event_type: event,
|
|
1172
|
+
event_data: eventData,
|
|
1173
|
+
session_id: sessionStorage.getItem("wt_sid") || void 0,
|
|
1174
|
+
visitor_id: localStorage.getItem("wt_vid") || void 0,
|
|
1175
|
+
campaign_id: config.campaignId || void 0
|
|
1176
|
+
}]);
|
|
1177
|
+
}, [onEvent, enableAnalytics, gatewayUrl]);
|
|
1249
1178
|
const theme = {
|
|
1250
1179
|
bg: lp.background_color || store?.theme?.background || "#050505",
|
|
1251
1180
|
fg: lp.text_color || store?.theme?.foreground || "#fafafa",
|
|
@@ -1260,23 +1189,31 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
1260
1189
|
const urlParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : new URLSearchParams();
|
|
1261
1190
|
const sorted = [...lp.sections].sort((a, b) => a.order - b.order).filter((s) => isSectionVisible(s, urlParams));
|
|
1262
1191
|
const sectionData = { ...data, gatewayUrl, landing_page: { slug: lp.slug }, analyticsContext };
|
|
1263
|
-
return /* @__PURE__ */
|
|
1264
|
-
lp.custom_css && /* @__PURE__ */
|
|
1265
|
-
logoUrl && /* @__PURE__ */
|
|
1192
|
+
return /* @__PURE__ */ jsxs("div", { style: { minHeight: "100dvh", background: theme.bg, color: theme.fg, fontFamily }, children: [
|
|
1193
|
+
lp.custom_css && /* @__PURE__ */ jsx("style", { children: lp.custom_css }),
|
|
1194
|
+
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" } }) }),
|
|
1266
1195
|
sorted.map((section) => {
|
|
1267
|
-
const defaultRenderer = () => /* @__PURE__ */
|
|
1268
|
-
if (renderSection) {
|
|
1269
|
-
|
|
1270
|
-
}
|
|
1271
|
-
return /* @__PURE__ */ jsxRuntime.jsx(SectionRenderer, { section, data: sectionData, theme, onEvent }, section.id);
|
|
1196
|
+
const defaultRenderer = () => /* @__PURE__ */ jsx(SectionRenderer, { section, data: sectionData, theme, onEvent: handleEvent }, section.id);
|
|
1197
|
+
if (renderSection) return /* @__PURE__ */ jsx("div", { children: renderSection(section, defaultRenderer) }, section.id);
|
|
1198
|
+
return /* @__PURE__ */ jsx(SectionRenderer, { section, data: sectionData, theme, onEvent: handleEvent }, section.id);
|
|
1272
1199
|
}),
|
|
1273
|
-
store?.name && /* @__PURE__ */
|
|
1200
|
+
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: [
|
|
1274
1201
|
"Powered by ",
|
|
1275
1202
|
store.name
|
|
1276
1203
|
] }) })
|
|
1277
1204
|
] });
|
|
1278
1205
|
}
|
|
1279
|
-
|
|
1206
|
+
function sendEvents(gwUrl, slug, events) {
|
|
1207
|
+
const body = JSON.stringify({ events });
|
|
1208
|
+
const url = `${gwUrl}/l/${encodeURIComponent(slug)}/events`;
|
|
1209
|
+
if (typeof navigator !== "undefined" && navigator.sendBeacon) {
|
|
1210
|
+
navigator.sendBeacon(url, new Blob([body], { type: "application/json" }));
|
|
1211
|
+
} else {
|
|
1212
|
+
fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body, keepalive: true }).catch(() => {
|
|
1213
|
+
});
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
var screenStyle = {
|
|
1280
1217
|
minHeight: "100dvh",
|
|
1281
1218
|
display: "flex",
|
|
1282
1219
|
justifyContent: "center",
|
|
@@ -1287,28 +1224,14 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
1287
1224
|
textAlign: "center",
|
|
1288
1225
|
padding: "2rem"
|
|
1289
1226
|
};
|
|
1290
|
-
function
|
|
1291
|
-
return /* @__PURE__ */
|
|
1292
|
-
/* @__PURE__ */
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { style: { fontSize: "1.5rem", marginBottom: "0.5rem" }, children: "Page Not Found" }),
|
|
1299
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "#888" }, children: "This page does not exist or has been removed." })
|
|
1300
|
-
] }) });
|
|
1301
|
-
}
|
|
1302
|
-
function DefaultExpired() {
|
|
1303
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: containerStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1304
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { style: { fontSize: "1.5rem", marginBottom: "0.5rem" }, children: "Page Expired" }),
|
|
1305
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "#888" }, children: "This page is no longer active." })
|
|
1306
|
-
] }) });
|
|
1307
|
-
}
|
|
1308
|
-
function DefaultError({ message }) {
|
|
1309
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: containerStyle, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1310
|
-
/* @__PURE__ */ jsxRuntime.jsx("h1", { style: { fontSize: "1.5rem", marginBottom: "0.5rem" }, children: "Something Went Wrong" }),
|
|
1311
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { color: "#888" }, children: message || "Please try again later." })
|
|
1227
|
+
function StateScreen({ title, subtitle, loading }) {
|
|
1228
|
+
return /* @__PURE__ */ jsx("div", { style: screenStyle, children: /* @__PURE__ */ jsxs("div", { children: [
|
|
1229
|
+
loading && /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
1230
|
+
/* @__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" } }),
|
|
1231
|
+
/* @__PURE__ */ jsx("style", { children: `@keyframes spin { to { transform: rotate(360deg) } }` })
|
|
1232
|
+
] }),
|
|
1233
|
+
title && /* @__PURE__ */ jsx("h1", { style: { fontSize: "1.5rem", marginBottom: "0.5rem" }, children: title }),
|
|
1234
|
+
subtitle && /* @__PURE__ */ jsx("p", { style: { color: "#888" }, children: subtitle })
|
|
1312
1235
|
] }) });
|
|
1313
1236
|
}
|
|
1314
1237
|
|
|
@@ -1320,4 +1243,4 @@ var WhaleStorefront = (function (exports, react, jsxRuntime) {
|
|
|
1320
1243
|
|
|
1321
1244
|
return exports;
|
|
1322
1245
|
|
|
1323
|
-
})({}
|
|
1246
|
+
})({});
|