@neowhale/storefront 0.2.56 → 0.2.58

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.
@@ -2863,6 +2863,25 @@ function COAModal({ coa, theme, onClose }) {
2863
2863
  /* @__PURE__ */ jsx("iframe", { src: coa.url, style: { flex: 1, border: "none", background: "#fff" }, title: "Lab Results" })
2864
2864
  ] });
2865
2865
  }
2866
+ var TURNSTILE_SITE_KEY = "0x4AAAAAACwmUPgmyfw6pWfT";
2867
+ var TURNSTILE_SCRIPT_URL = "https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit";
2868
+ var turnstilePromise = null;
2869
+ function loadTurnstileScript() {
2870
+ if (turnstilePromise) return turnstilePromise;
2871
+ if (typeof window !== "undefined" && window.turnstile) {
2872
+ turnstilePromise = Promise.resolve();
2873
+ return turnstilePromise;
2874
+ }
2875
+ turnstilePromise = new Promise((resolve, reject) => {
2876
+ const script = document.createElement("script");
2877
+ script.src = TURNSTILE_SCRIPT_URL;
2878
+ script.async = true;
2879
+ script.onload = () => resolve();
2880
+ script.onerror = () => reject(new Error("Failed to load Turnstile script"));
2881
+ document.head.appendChild(script);
2882
+ });
2883
+ return turnstilePromise;
2884
+ }
2866
2885
  function LeadCaptureSection({ section, data, theme, onEvent }) {
2867
2886
  const c = section.content;
2868
2887
  const [firstName, setFirstName] = useState("");
@@ -2871,6 +2890,41 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
2871
2890
  const [status, setStatus] = useState("idle");
2872
2891
  const [errorMsg, setErrorMsg] = useState("");
2873
2892
  const [serverMessage, setServerMessage] = useState(null);
2893
+ const turnstileRef = useRef(null);
2894
+ const turnstileToken = useRef(null);
2895
+ const turnstileWidgetId = useRef(null);
2896
+ const pendingSubmit = useRef(null);
2897
+ const onTurnstileToken = useCallback((token) => {
2898
+ turnstileToken.current = token;
2899
+ if (pendingSubmit.current) {
2900
+ const cb = pendingSubmit.current;
2901
+ pendingSubmit.current = null;
2902
+ cb();
2903
+ }
2904
+ }, []);
2905
+ useEffect(() => {
2906
+ if (typeof window === "undefined") return;
2907
+ let widgetId = null;
2908
+ loadTurnstileScript().then(() => {
2909
+ const el = turnstileRef.current;
2910
+ if (!el || !window.turnstile) return;
2911
+ widgetId = window.turnstile.render(el, {
2912
+ sitekey: TURNSTILE_SITE_KEY,
2913
+ callback: onTurnstileToken,
2914
+ "expired-callback": () => {
2915
+ turnstileToken.current = null;
2916
+ },
2917
+ size: "invisible"
2918
+ });
2919
+ turnstileWidgetId.current = widgetId;
2920
+ }).catch(() => {
2921
+ });
2922
+ return () => {
2923
+ if (widgetId != null && window.turnstile) {
2924
+ window.turnstile.remove(widgetId);
2925
+ }
2926
+ };
2927
+ }, [onTurnstileToken]);
2874
2928
  const gatewayUrl = c.gateway_url || data.gatewayUrl || "https://whale-gateway.fly.dev";
2875
2929
  const storeId = c.store_id || data.store?.id;
2876
2930
  const slug = c.landing_page_slug || data.landing_page?.slug;
@@ -2879,11 +2933,7 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
2879
2933
  const buttonText = c.button_text || "Claim My Discount";
2880
2934
  const successHeading = c.success_heading || "You\u2019re in!";
2881
2935
  const successMessage = c.success_message || "Check your inbox for the discount code.";
2882
- async function handleSubmit(e) {
2883
- e.preventDefault();
2884
- if (!email || !storeId) return;
2885
- setStatus("loading");
2886
- setErrorMsg("");
2936
+ async function submitLead(cfToken) {
2887
2937
  const urlParams = typeof window !== "undefined" ? new URLSearchParams(window.location.search) : null;
2888
2938
  try {
2889
2939
  const res = await fetch(`${gatewayUrl}/v1/stores/${storeId}/storefront/leads`, {
@@ -2905,7 +2955,8 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
2905
2955
  utm_source: urlParams?.get("utm_source") || void 0,
2906
2956
  utm_medium: urlParams?.get("utm_medium") || void 0,
2907
2957
  utm_campaign: urlParams?.get("utm_campaign") || void 0,
2908
- utm_content: urlParams?.get("utm_content") || void 0
2958
+ utm_content: urlParams?.get("utm_content") || void 0,
2959
+ cf_turnstile_response: cfToken || void 0
2909
2960
  })
2910
2961
  });
2911
2962
  if (!res.ok) {
@@ -2926,6 +2977,22 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
2926
2977
  setStatus("error");
2927
2978
  }
2928
2979
  }
2980
+ async function handleSubmit(e) {
2981
+ e.preventDefault();
2982
+ if (!email || !storeId) return;
2983
+ setStatus("loading");
2984
+ setErrorMsg("");
2985
+ if (turnstileToken.current) {
2986
+ return submitLead(turnstileToken.current);
2987
+ }
2988
+ const turnstile = window.turnstile;
2989
+ if (turnstile && turnstileWidgetId.current != null) {
2990
+ pendingSubmit.current = () => submitLead(turnstileToken.current);
2991
+ turnstile.execute(turnstileWidgetId.current);
2992
+ } else {
2993
+ return submitLead(null);
2994
+ }
2995
+ }
2929
2996
  const inputStyle = {
2930
2997
  flex: 1,
2931
2998
  minWidth: 0,
@@ -2940,7 +3007,7 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
2940
3007
  fontFamily: "inherit",
2941
3008
  transition: "border-color 0.2s"
2942
3009
  };
2943
- if (status === "success") return /* @__PURE__ */ jsx(SuccessState, { theme, heading: serverMessage?.heading || successHeading, message: serverMessage?.message || successMessage, couponCode: c.coupon_code });
3010
+ if (status === "success") return /* @__PURE__ */ jsx(SuccessState, { theme, heading: serverMessage?.heading || successHeading, message: serverMessage?.message || successMessage, couponCode: c.coupon_code, ctaText: c.success_cta_text, ctaUrl: c.success_cta_url });
2944
3011
  return /* @__PURE__ */ jsxs("div", { style: { padding: "3.5rem 1.5rem", maxWidth: 560, margin: "0 auto" }, children: [
2945
3012
  /* @__PURE__ */ jsx("style", { children: `@keyframes lc-spin { to { transform: rotate(360deg) } }` }),
2946
3013
  /* @__PURE__ */ jsxs("div", { style: { background: theme.surface, border: `1px solid ${theme.fg}12`, padding: "clamp(2rem, 6vw, 3rem)" }, children: [
@@ -3019,12 +3086,13 @@ function LeadCaptureSection({ section, data, theme, onEvent }) {
3019
3086
  animation: "lc-spin 0.8s linear infinite"
3020
3087
  } }),
3021
3088
  buttonText
3022
- ] })
3089
+ ] }),
3090
+ /* @__PURE__ */ jsx("div", { ref: turnstileRef, style: { display: "none" } })
3023
3091
  ] })
3024
3092
  ] })
3025
3093
  ] });
3026
3094
  }
3027
- function SuccessState({ theme, heading, message, couponCode }) {
3095
+ function SuccessState({ theme, heading, message, couponCode, ctaText, ctaUrl }) {
3028
3096
  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: [
3029
3097
  /* @__PURE__ */ jsx("h2", { style: {
3030
3098
  fontSize: "clamp(1.5rem, 5vw, 2rem)",
@@ -3046,7 +3114,30 @@ function SuccessState({ theme, heading, message, couponCode }) {
3046
3114
  fontFamily: "monospace",
3047
3115
  letterSpacing: "0.12em",
3048
3116
  color: theme.accent
3049
- }, children: couponCode })
3117
+ }, children: couponCode }),
3118
+ /* @__PURE__ */ jsx(
3119
+ "button",
3120
+ {
3121
+ onClick: () => {
3122
+ window.location.href = ctaUrl || "/shop";
3123
+ },
3124
+ style: {
3125
+ marginTop: "1.5rem",
3126
+ width: "100%",
3127
+ padding: "0.875rem",
3128
+ background: theme.accent,
3129
+ color: "#fff",
3130
+ border: "none",
3131
+ fontSize: "0.85rem",
3132
+ fontWeight: 500,
3133
+ cursor: "pointer",
3134
+ letterSpacing: "0.08em",
3135
+ textTransform: "uppercase",
3136
+ fontFamily: "inherit"
3137
+ },
3138
+ children: ctaText || "shop now"
3139
+ }
3140
+ )
3050
3141
  ] }) });
3051
3142
  }
3052
3143
  var GOOGLE_G_LG = '<svg width="28" height="28" viewBox="0 0 48 48"><path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"/><path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/><path fill="#FBBC05" d="M10.53 28.59a14.5 14.5 0 010-9.18l-7.98-6.19a24.03 24.03 0 000 21.56l7.98-6.19z"/><path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/></svg>';