@neowhale/storefront 0.2.43 → 0.2.45

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.
@@ -2301,30 +2301,41 @@ function CollageHeroSection({ section, theme, tracking, onEvent }) {
2301
2301
  if (images.length === 0) return null;
2302
2302
  c.overlay_opacity ?? 0.45;
2303
2303
  const count = Math.min(images.length, 5);
2304
+ const imgStyle = {
2305
+ width: "100%",
2306
+ height: "100%",
2307
+ objectFit: "cover",
2308
+ objectPosition: "center top",
2309
+ display: "block"
2310
+ };
2304
2311
  return /* @__PURE__ */ jsxs("div", { style: { width: "100%", overflow: "hidden", position: "relative" }, children: [
2305
- /* @__PURE__ */ jsx("div", { style: {
2312
+ /* @__PURE__ */ jsxs("div", { style: {
2306
2313
  display: "grid",
2307
- gridTemplateColumns: count >= 4 ? "repeat(4, 1fr)" : "repeat(2, 1fr)",
2308
- gridTemplateRows: count >= 4 ? "minmax(0, 28vh) minmax(0, 28vh)" : "minmax(0, 50vh)",
2309
- gap: "2px"
2310
- }, children: images.slice(0, count).map((img, i) => /* @__PURE__ */ jsx("div", { style: {
2311
- gridColumn: i === 0 && count >= 4 ? "span 2" : void 0,
2312
- gridRow: i === 0 && count >= 4 ? "span 2" : void 0,
2313
- overflow: "hidden",
2314
- background: theme.surface
2315
- }, children: /* @__PURE__ */ jsx(
2316
- "img",
2317
- {
2318
- src: img.url,
2319
- alt: img.alt || "",
2320
- loading: i < 3 ? "eager" : "lazy",
2321
- style: { width: "100%", height: "100%", objectFit: "cover", display: "block" }
2322
- }
2323
- ) }, i)) }),
2314
+ gridTemplateColumns: count >= 3 ? "3fr 2fr" : "1fr",
2315
+ gridTemplateRows: count >= 3 ? "1fr 1fr" : "auto",
2316
+ gap: "2px",
2317
+ height: "100vh",
2318
+ maxHeight: "900px"
2319
+ }, children: [
2320
+ count > 0 && /* @__PURE__ */ jsx("div", { style: {
2321
+ gridRow: count >= 3 ? "1 / -1" : void 0,
2322
+ overflow: "hidden",
2323
+ background: theme.surface
2324
+ }, children: /* @__PURE__ */ jsx("img", { src: images[0].url, alt: images[0].alt || "", loading: "eager", style: imgStyle }) }),
2325
+ count >= 2 && /* @__PURE__ */ jsx("div", { style: { overflow: "hidden", background: theme.surface }, children: /* @__PURE__ */ jsx("img", { src: images[1].url, alt: images[1].alt || "", loading: "eager", style: imgStyle }) }),
2326
+ count >= 3 && /* @__PURE__ */ jsx("div", { style: {
2327
+ overflow: "hidden",
2328
+ background: theme.surface,
2329
+ ...count >= 4 ? { display: "grid", gridTemplateColumns: count >= 5 ? "1fr 1fr" : count >= 4 ? "1fr 1fr" : "1fr", gap: "2px" } : {}
2330
+ }, children: count < 4 ? /* @__PURE__ */ jsx("img", { src: images[2].url, alt: images[2].alt || "", loading: "lazy", style: imgStyle }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2331
+ /* @__PURE__ */ jsx("div", { style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx("img", { src: images[2].url, alt: images[2].alt || "", loading: "lazy", style: imgStyle }) }),
2332
+ count >= 4 && /* @__PURE__ */ jsx("div", { style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx("img", { src: images[3].url, alt: images[3].alt || "", loading: "lazy", style: imgStyle }) })
2333
+ ] }) })
2334
+ ] }),
2324
2335
  /* @__PURE__ */ jsx("div", { style: {
2325
2336
  position: "absolute",
2326
2337
  inset: 0,
2327
- background: "linear-gradient(to top, rgba(0,0,0,0.7) 0%, rgba(0,0,0,0.2) 40%, transparent 60%)",
2338
+ background: "linear-gradient(to top, rgba(0,0,0,0.75) 0%, rgba(0,0,0,0.15) 35%, transparent 55%)",
2328
2339
  pointerEvents: "none"
2329
2340
  } }),
2330
2341
  /* @__PURE__ */ jsxs("div", { style: {
@@ -2778,6 +2789,300 @@ function SuccessState({ theme, heading, message, couponCode }) {
2778
2789
  }, children: couponCode })
2779
2790
  ] }) });
2780
2791
  }
2792
+ function TestimonialsSection({ section, theme }) {
2793
+ const c = section.content;
2794
+ const layout = section.config?.layout || "grid";
2795
+ const reviews = c.reviews || [];
2796
+ if (reviews.length === 0) return null;
2797
+ const overallRating = c.rating ?? 5;
2798
+ const reviewCount = c.review_count ?? reviews.length;
2799
+ return /* @__PURE__ */ jsxs("div", { style: { padding: "3rem 1.5rem", maxWidth: 640, margin: "0 auto" }, children: [
2800
+ /* @__PURE__ */ jsxs("div", { style: { textAlign: "center", marginBottom: "2rem" }, children: [
2801
+ c.heading && /* @__PURE__ */ jsx("h2", { style: {
2802
+ fontSize: "clamp(1.25rem, 4vw, 1.75rem)",
2803
+ fontWeight: 300,
2804
+ fontFamily: theme.fontDisplay || "inherit",
2805
+ margin: "0 0 0.75rem",
2806
+ lineHeight: 1.2,
2807
+ letterSpacing: "-0.02em",
2808
+ color: theme.fg
2809
+ }, children: /* @__PURE__ */ jsx(AnimatedText, { text: c.heading }) }),
2810
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "0.5rem", marginBottom: "0.25rem" }, children: [
2811
+ /* @__PURE__ */ jsx(Stars, { rating: overallRating, color: theme.accent, size: 18 }),
2812
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "1.1rem", fontWeight: 500, color: theme.fg }, children: /* @__PURE__ */ jsx(AnimatedText, { text: overallRating.toFixed(1) }) })
2813
+ ] }),
2814
+ c.subtitle ? /* @__PURE__ */ jsx("p", { style: { fontSize: "0.8rem", color: theme.muted, margin: 0, letterSpacing: "0.1em", textTransform: "uppercase" }, children: c.subtitle }) : /* @__PURE__ */ jsxs("p", { style: { fontSize: "0.8rem", color: theme.muted, margin: 0, letterSpacing: "0.1em", textTransform: "uppercase" }, children: [
2815
+ "from ",
2816
+ /* @__PURE__ */ jsx(AnimatedText, { text: String(reviewCount) }),
2817
+ " reviews"
2818
+ ] })
2819
+ ] }),
2820
+ /* @__PURE__ */ jsx("div", { style: {
2821
+ display: "grid",
2822
+ gridTemplateColumns: layout === "list" ? "1fr" : `repeat(${Math.min(reviews.length, 2)}, 1fr)`,
2823
+ gap: "0.75rem"
2824
+ }, children: reviews.map((review, i) => /* @__PURE__ */ jsxs("div", { style: {
2825
+ background: theme.surface,
2826
+ border: `1px solid ${theme.fg}08`,
2827
+ padding: "1.25rem"
2828
+ }, children: [
2829
+ /* @__PURE__ */ jsx(Stars, { rating: review.rating ?? 5, color: theme.accent, size: 14 }),
2830
+ /* @__PURE__ */ jsxs("p", { style: {
2831
+ fontSize: "0.88rem",
2832
+ color: `${theme.fg}CC`,
2833
+ margin: "0.75rem 0",
2834
+ lineHeight: 1.6,
2835
+ fontWeight: 300,
2836
+ fontStyle: "italic"
2837
+ }, children: [
2838
+ '"',
2839
+ review.text,
2840
+ '"'
2841
+ ] }),
2842
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: "0.375rem" }, children: [
2843
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "0.8rem", fontWeight: 500, color: theme.fg }, children: review.name }),
2844
+ review.location && /* @__PURE__ */ jsx("span", { style: { fontSize: "0.7rem", color: theme.muted }, children: review.location })
2845
+ ] })
2846
+ ] }, i)) })
2847
+ ] });
2848
+ }
2849
+ function Stars({ rating, color, size }) {
2850
+ return /* @__PURE__ */ jsx("span", { style: { display: "inline-flex", gap: "1px" }, children: [1, 2, 3, 4, 5].map((n) => /* @__PURE__ */ jsx(
2851
+ "svg",
2852
+ {
2853
+ width: size,
2854
+ height: size,
2855
+ viewBox: "0 0 20 20",
2856
+ fill: n <= Math.round(rating) ? color : "none",
2857
+ stroke: color,
2858
+ strokeWidth: 1.5,
2859
+ children: /* @__PURE__ */ jsx("path", { d: "M10 1.5l2.47 5.01 5.53.8-4 3.9.94 5.5L10 14.26 5.06 16.7l.94-5.5-4-3.9 5.53-.8z" })
2860
+ },
2861
+ n
2862
+ )) });
2863
+ }
2864
+ function ValueStackSection({ section, theme }) {
2865
+ const c = section.content;
2866
+ const items = c.items || [];
2867
+ if (items.length === 0) return null;
2868
+ return /* @__PURE__ */ jsx("div", { style: { padding: "3rem 1.5rem", maxWidth: 520, margin: "0 auto" }, children: /* @__PURE__ */ jsxs("div", { style: { background: theme.surface, border: `1px solid ${theme.fg}08`, padding: "clamp(1.5rem, 5vw, 2.5rem)" }, children: [
2869
+ c.heading && /* @__PURE__ */ jsx("h2", { style: {
2870
+ fontSize: "clamp(1.25rem, 4vw, 1.5rem)",
2871
+ fontWeight: 300,
2872
+ fontFamily: theme.fontDisplay || "inherit",
2873
+ margin: "0 0 0.25rem",
2874
+ lineHeight: 1.2,
2875
+ letterSpacing: "-0.02em",
2876
+ color: theme.fg,
2877
+ textAlign: "center"
2878
+ }, children: c.heading }),
2879
+ c.subtitle && /* @__PURE__ */ jsx("p", { style: {
2880
+ fontSize: "0.8rem",
2881
+ color: theme.accent,
2882
+ margin: "0 0 1.5rem",
2883
+ letterSpacing: "0.15em",
2884
+ textTransform: "uppercase",
2885
+ textAlign: "center"
2886
+ }, children: c.subtitle }),
2887
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: "0.625rem" }, children: items.map((item, i) => /* @__PURE__ */ jsxs("div", { style: {
2888
+ display: "flex",
2889
+ alignItems: "flex-start",
2890
+ gap: "0.75rem",
2891
+ padding: "0.5rem 0",
2892
+ borderBottom: i < items.length - 1 ? `1px solid ${theme.fg}08` : void 0
2893
+ }, children: [
2894
+ /* @__PURE__ */ jsx("span", { style: { color: theme.accent, fontSize: "1rem", lineHeight: 1, flexShrink: 0, marginTop: "0.1rem" }, children: "\u2713" }),
2895
+ /* @__PURE__ */ jsx("span", { style: { flex: 1, fontSize: "0.9rem", color: `${theme.fg}CC`, fontWeight: 300, lineHeight: 1.5 }, children: item.text }),
2896
+ item.value && /* @__PURE__ */ jsx("span", { style: {
2897
+ fontSize: "0.8rem",
2898
+ color: theme.muted,
2899
+ fontWeight: 400,
2900
+ textDecoration: "line-through",
2901
+ flexShrink: 0
2902
+ }, children: item.value })
2903
+ ] }, i)) }),
2904
+ (c.total_value || c.offer_label) && /* @__PURE__ */ jsxs("div", { style: {
2905
+ marginTop: "1.5rem",
2906
+ padding: "1rem",
2907
+ background: `${theme.accent}0A`,
2908
+ border: `1px dashed ${theme.accent}30`,
2909
+ textAlign: "center"
2910
+ }, children: [
2911
+ c.total_value && /* @__PURE__ */ jsxs("div", { style: { fontSize: "0.75rem", color: theme.muted, marginBottom: "0.25rem", letterSpacing: "0.1em", textTransform: "uppercase" }, children: [
2912
+ "Total value: ",
2913
+ /* @__PURE__ */ jsx("span", { style: { textDecoration: "line-through" }, children: c.total_value })
2914
+ ] }),
2915
+ /* @__PURE__ */ jsx("div", { style: {
2916
+ fontSize: "clamp(1.25rem, 4vw, 1.5rem)",
2917
+ fontWeight: 500,
2918
+ fontFamily: theme.fontDisplay || "inherit",
2919
+ color: theme.accent
2920
+ }, children: c.offer_label || "Free" })
2921
+ ] })
2922
+ ] }) });
2923
+ }
2924
+ function FAQSection({ section, theme }) {
2925
+ const c = section.content;
2926
+ const items = c.items || [];
2927
+ if (items.length === 0) return null;
2928
+ return /* @__PURE__ */ jsxs("div", { style: { padding: "2.5rem 1.5rem", maxWidth: 580, margin: "0 auto" }, children: [
2929
+ c.heading && /* @__PURE__ */ jsx("h2", { style: {
2930
+ fontSize: 11,
2931
+ fontWeight: 500,
2932
+ textTransform: "uppercase",
2933
+ letterSpacing: "0.25em",
2934
+ color: `${theme.fg}40`,
2935
+ margin: "0 0 1.25rem",
2936
+ textAlign: "center"
2937
+ }, children: c.heading }),
2938
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: 0 }, children: items.map((item, i) => /* @__PURE__ */ jsx(FAQItem, { question: item.question, answer: item.answer, theme }, i)) })
2939
+ ] });
2940
+ }
2941
+ function FAQItem({ question, answer, theme }) {
2942
+ const [open, setOpen] = useState(false);
2943
+ return /* @__PURE__ */ jsxs("div", { style: { borderBottom: `1px solid ${theme.fg}0A` }, children: [
2944
+ /* @__PURE__ */ jsxs(
2945
+ "button",
2946
+ {
2947
+ onClick: () => setOpen(!open),
2948
+ style: {
2949
+ width: "100%",
2950
+ display: "flex",
2951
+ justifyContent: "space-between",
2952
+ alignItems: "center",
2953
+ padding: "1rem 0",
2954
+ background: "none",
2955
+ border: "none",
2956
+ cursor: "pointer",
2957
+ color: theme.fg,
2958
+ fontFamily: "inherit",
2959
+ textAlign: "left"
2960
+ },
2961
+ children: [
2962
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "0.9rem", fontWeight: 400, lineHeight: 1.4 }, children: question }),
2963
+ /* @__PURE__ */ jsx("span", { style: {
2964
+ fontSize: "1.25rem",
2965
+ fontWeight: 200,
2966
+ color: theme.muted,
2967
+ transition: "transform 0.2s",
2968
+ transform: open ? "rotate(45deg)" : "none",
2969
+ flexShrink: 0,
2970
+ marginLeft: "1rem"
2971
+ }, children: "+" })
2972
+ ]
2973
+ }
2974
+ ),
2975
+ /* @__PURE__ */ jsx("div", { style: {
2976
+ maxHeight: open ? "20rem" : 0,
2977
+ overflow: "hidden",
2978
+ transition: "max-height 0.3s ease"
2979
+ }, children: /* @__PURE__ */ jsx("p", { style: {
2980
+ fontSize: "0.85rem",
2981
+ color: `${theme.fg}88`,
2982
+ lineHeight: 1.7,
2983
+ fontWeight: 300,
2984
+ margin: 0,
2985
+ padding: "0 0 1rem"
2986
+ }, children: answer }) })
2987
+ ] });
2988
+ }
2989
+ function TrustBadgesSection({ section, theme }) {
2990
+ const c = section.content;
2991
+ const badges = c.badges || [];
2992
+ if (badges.length === 0) return null;
2993
+ return /* @__PURE__ */ jsx("div", { style: {
2994
+ padding: "1.25rem 1.5rem",
2995
+ borderTop: `1px solid ${theme.fg}08`,
2996
+ borderBottom: `1px solid ${theme.fg}08`
2997
+ }, children: /* @__PURE__ */ jsx("div", { style: {
2998
+ display: "flex",
2999
+ justifyContent: "center",
3000
+ alignItems: "center",
3001
+ gap: "clamp(1rem, 4vw, 2.5rem)",
3002
+ flexWrap: "wrap"
3003
+ }, children: badges.map((badge, i) => /* @__PURE__ */ jsxs("div", { style: {
3004
+ display: "flex",
3005
+ alignItems: "center",
3006
+ gap: "0.375rem"
3007
+ }, children: [
3008
+ badge.icon && /* @__PURE__ */ jsx("span", { style: { fontSize: "0.9rem" }, children: badge.icon }),
3009
+ /* @__PURE__ */ jsx("span", { style: {
3010
+ fontSize: "0.7rem",
3011
+ fontWeight: 500,
3012
+ textTransform: "uppercase",
3013
+ letterSpacing: "0.15em",
3014
+ color: theme.muted
3015
+ }, children: badge.label })
3016
+ ] }, i)) }) });
3017
+ }
3018
+ function CountdownSection({ section, theme }) {
3019
+ const c = section.content;
3020
+ const endDate = c.end_date ? new Date(c.end_date) : null;
3021
+ const [remaining, setRemaining] = useState(null);
3022
+ const [expired, setExpired] = useState(false);
3023
+ useEffect(() => {
3024
+ if (!endDate) return;
3025
+ function tick() {
3026
+ const diff = endDate.getTime() - Date.now();
3027
+ if (diff <= 0) {
3028
+ setExpired(true);
3029
+ return;
3030
+ }
3031
+ setRemaining({
3032
+ d: Math.floor(diff / 864e5),
3033
+ h: Math.floor(diff % 864e5 / 36e5),
3034
+ m: Math.floor(diff % 36e5 / 6e4),
3035
+ s: Math.floor(diff % 6e4 / 1e3)
3036
+ });
3037
+ }
3038
+ tick();
3039
+ const id = setInterval(tick, 1e3);
3040
+ return () => clearInterval(id);
3041
+ }, [endDate?.getTime()]);
3042
+ if (!endDate) return null;
3043
+ if (expired) {
3044
+ return c.expired_text ? /* @__PURE__ */ jsx("div", { style: { padding: "1.5rem", textAlign: "center" }, children: /* @__PURE__ */ jsx("p", { style: { fontSize: "0.85rem", color: theme.muted, margin: 0 }, children: c.expired_text }) }) : null;
3045
+ }
3046
+ if (!remaining) return null;
3047
+ const units = [
3048
+ { label: "Days", value: remaining.d },
3049
+ { label: "Hours", value: remaining.h },
3050
+ { label: "Min", value: remaining.m },
3051
+ { label: "Sec", value: remaining.s }
3052
+ ];
3053
+ return /* @__PURE__ */ jsxs("div", { style: { padding: "2rem 1.5rem", maxWidth: 480, margin: "0 auto", textAlign: "center" }, children: [
3054
+ c.heading && /* @__PURE__ */ jsx("p", { style: {
3055
+ fontSize: "0.8rem",
3056
+ color: theme.accent,
3057
+ margin: "0 0 1rem",
3058
+ letterSpacing: "0.15em",
3059
+ textTransform: "uppercase"
3060
+ }, children: c.heading }),
3061
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", justifyContent: "center", gap: "0.5rem" }, children: units.map((u) => /* @__PURE__ */ jsxs("div", { style: {
3062
+ minWidth: "clamp(3.5rem, 12vw, 4.5rem)",
3063
+ padding: "0.75rem 0.25rem",
3064
+ background: theme.surface,
3065
+ border: `1px solid ${theme.fg}08`
3066
+ }, children: [
3067
+ /* @__PURE__ */ jsx("div", { style: {
3068
+ fontFamily: theme.fontDisplay || "inherit",
3069
+ fontSize: "clamp(1.5rem, 5vw, 2rem)",
3070
+ fontWeight: 300,
3071
+ lineHeight: 1,
3072
+ color: theme.fg,
3073
+ fontVariantNumeric: "tabular-nums"
3074
+ }, children: String(u.value).padStart(2, "0") }),
3075
+ /* @__PURE__ */ jsx("div", { style: {
3076
+ fontSize: "0.6rem",
3077
+ fontWeight: 500,
3078
+ textTransform: "uppercase",
3079
+ letterSpacing: "0.2em",
3080
+ color: theme.muted,
3081
+ marginTop: "0.375rem"
3082
+ }, children: u.label })
3083
+ ] }, u.label)) })
3084
+ ] });
3085
+ }
2781
3086
  function SectionRenderer({
2782
3087
  section,
2783
3088
  data,
@@ -2812,6 +3117,16 @@ function SectionRenderer({
2812
3117
  return /* @__PURE__ */ jsx(SocialLinksSection, { section, theme });
2813
3118
  case "lead_capture":
2814
3119
  return /* @__PURE__ */ jsx(LeadCaptureSection, { section, data, theme, onEvent });
3120
+ case "testimonials":
3121
+ return /* @__PURE__ */ jsx(TestimonialsSection, { section, theme });
3122
+ case "value_stack":
3123
+ return /* @__PURE__ */ jsx(ValueStackSection, { section, theme });
3124
+ case "faq":
3125
+ return /* @__PURE__ */ jsx(FAQSection, { section, theme });
3126
+ case "trust_badges":
3127
+ return /* @__PURE__ */ jsx(TrustBadgesSection, { section, theme });
3128
+ case "countdown":
3129
+ return /* @__PURE__ */ jsx(CountdownSection, { section, theme });
2815
3130
  case "divider":
2816
3131
  return /* @__PURE__ */ jsx(DividerSection, { theme });
2817
3132
  default: