@neowhale/storefront 0.2.43 → 0.2.44

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