@neowhale/storefront 0.2.29 → 0.2.30

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.
@@ -2452,6 +2452,68 @@ function useReferral() {
2452
2452
  referredBy: status?.referred_by ?? null
2453
2453
  };
2454
2454
  }
2455
+ var NUM_PATTERN = /(\$?[\d,]+\.?\d*[+★%]?)/g;
2456
+ function easeOutQuart(t) {
2457
+ return 1 - Math.pow(1 - t, 4);
2458
+ }
2459
+ function useCountUp(target, duration, start) {
2460
+ const [value, setValue] = useState(0);
2461
+ const raf = useRef(0);
2462
+ useEffect(() => {
2463
+ if (!start) return;
2464
+ const t0 = performance.now();
2465
+ function tick(now2) {
2466
+ const elapsed = now2 - t0;
2467
+ const progress = Math.min(elapsed / duration, 1);
2468
+ setValue(Math.round(easeOutQuart(progress) * target));
2469
+ if (progress < 1) raf.current = requestAnimationFrame(tick);
2470
+ }
2471
+ raf.current = requestAnimationFrame(tick);
2472
+ return () => cancelAnimationFrame(raf.current);
2473
+ }, [target, duration, start]);
2474
+ return value;
2475
+ }
2476
+ function AnimatedNumber({ raw }) {
2477
+ const ref = useRef(null);
2478
+ const [visible, setVisible] = useState(false);
2479
+ useEffect(() => {
2480
+ const el = ref.current;
2481
+ if (!el || typeof IntersectionObserver === "undefined") {
2482
+ setVisible(true);
2483
+ return;
2484
+ }
2485
+ const obs = new IntersectionObserver(([entry]) => {
2486
+ if (entry.isIntersecting) {
2487
+ setVisible(true);
2488
+ obs.disconnect();
2489
+ }
2490
+ }, { threshold: 0.3 });
2491
+ obs.observe(el);
2492
+ return () => obs.disconnect();
2493
+ }, []);
2494
+ const prefix = raw.startsWith("$") ? "$" : "";
2495
+ const suffix = raw.match(/[+★%]$/)?.[0] || "";
2496
+ const numeric = parseFloat(raw.replace(/[\$,+★%]/g, ""));
2497
+ const hasCommas = raw.includes(",");
2498
+ const decimals = raw.includes(".") ? raw.split(".")[1]?.replace(/[+★%]/g, "").length || 0 : 0;
2499
+ const count = useCountUp(
2500
+ decimals > 0 ? Math.round(numeric * Math.pow(10, decimals)) : numeric,
2501
+ 1400,
2502
+ visible
2503
+ );
2504
+ const display = decimals > 0 ? (count / Math.pow(10, decimals)).toFixed(decimals) : hasCommas ? count.toLocaleString() : String(count);
2505
+ return /* @__PURE__ */ jsxs("span", { ref, children: [
2506
+ prefix,
2507
+ display,
2508
+ suffix
2509
+ ] });
2510
+ }
2511
+ function AnimatedText({ text }) {
2512
+ const parts = text.split(NUM_PATTERN);
2513
+ return /* @__PURE__ */ jsx(Fragment, { children: parts.map(
2514
+ (part, i) => NUM_PATTERN.test(part) ? /* @__PURE__ */ jsx(AnimatedNumber, { raw: part }, i) : part
2515
+ ) });
2516
+ }
2455
2517
  function trackClick(tracking, label, url, position) {
2456
2518
  if (!tracking?.gatewayUrl || !tracking?.code) return;
2457
2519
  const body = JSON.stringify({ label, url, position });
@@ -2534,7 +2596,7 @@ function HeroSection({ section, theme, tracking, onEvent }) {
2534
2596
  lineHeight: 1.15,
2535
2597
  letterSpacing: "-0.02em",
2536
2598
  color: theme.fg
2537
- }, children: title }),
2599
+ }, children: /* @__PURE__ */ jsx(AnimatedText, { text: title }) }),
2538
2600
  subtitle && /* @__PURE__ */ jsx("p", { style: {
2539
2601
  fontSize: "0.85rem",
2540
2602
  color: theme.accent,
@@ -2709,7 +2771,7 @@ function StatsSection({ section, theme }) {
2709
2771
  letterSpacing: "0.15em",
2710
2772
  color: `${theme.fg}66`
2711
2773
  }, children: stat.label }),
2712
- /* @__PURE__ */ jsx("span", { style: { fontSize: 14, fontWeight: 300, color: `${theme.fg}CC` }, children: stat.value })
2774
+ /* @__PURE__ */ jsx("span", { style: { fontSize: 14, fontWeight: 300, color: `${theme.fg}CC` }, children: /* @__PURE__ */ jsx(AnimatedText, { text: stat.value }) })
2713
2775
  ] }),
2714
2776
  i < stats.length - 1 && /* @__PURE__ */ jsx("hr", { style: { border: "none", borderTop: `1px solid ${theme.fg}0A`, margin: 0 } })
2715
2777
  ] }, i)) });
@@ -2730,7 +2792,7 @@ function StatsSection({ section, theme }) {
2730
2792
  fontWeight: 300,
2731
2793
  lineHeight: 1,
2732
2794
  color: theme.fg
2733
- }, children: stat.value }),
2795
+ }, children: /* @__PURE__ */ jsx(AnimatedText, { text: stat.value }) }),
2734
2796
  /* @__PURE__ */ jsx("div", { style: {
2735
2797
  fontSize: 11,
2736
2798
  fontWeight: 500,