@spectare-personalisation/react 0.1.4 → 0.2.0

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/index.js CHANGED
@@ -1,101 +1,127 @@
1
1
  import { useState, useRef, useEffect } from 'react';
2
2
  import { marked } from 'marked';
3
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
4
4
 
5
5
  // src/PersonalisedSection.tsx
6
+
7
+ // src/types.ts
8
+ var COMPONENT_ZONES = {
9
+ HeroStatement: "hero",
10
+ ImageCtaHero: "hero",
11
+ AtomCard: "body",
12
+ StatGrid: "body",
13
+ CodeBlock: "body",
14
+ ComparisonTable: "body",
15
+ FeatureList: "body",
16
+ TestimonialCard: "proof",
17
+ CtaStrip: "cta"
18
+ };
19
+ function filterAssemblyByZone(assembly, zone) {
20
+ return assembly.filter((item) => {
21
+ var _a;
22
+ const effectiveZone = (_a = item.zone) != null ? _a : COMPONENT_ZONES[item.component];
23
+ return effectiveZone === zone;
24
+ });
25
+ }
6
26
  function renderMarkdown(content) {
7
27
  return marked.parse(content, { async: false });
8
28
  }
9
29
  var HALF_COMPONENTS = /* @__PURE__ */ new Set(["TestimonialCard"]);
10
30
  function HeroStatement({ headline, subheading }) {
11
- return /* @__PURE__ */ jsxs("div", { style: { paddingTop: "1.5rem", paddingBottom: "1.5rem" }, children: [
12
- /* @__PURE__ */ jsx("h2", { style: { fontSize: "2rem", fontWeight: 700, letterSpacing: "-0.025em", lineHeight: 1.2, color: "var(--sp-text)", margin: "0 0 0.75rem" }, children: headline }),
13
- subheading && /* @__PURE__ */ jsx("p", { style: { fontSize: "1.125rem", color: "var(--sp-text-sub)", lineHeight: 1.6, maxWidth: "42rem", margin: 0 }, children: subheading })
31
+ return /* @__PURE__ */ jsxs("div", { style: { paddingTop: "24px", paddingBottom: "24px" }, children: [
32
+ /* @__PURE__ */ jsx("h2", { style: { fontSize: "32px", fontWeight: 700, letterSpacing: "-0.025em", lineHeight: 1.2, color: "var(--sp-text)", margin: "0 0 12px" }, children: headline }),
33
+ subheading && /* @__PURE__ */ jsx("p", { style: { fontSize: "18px", color: "var(--sp-text-sub)", lineHeight: 1.6, maxWidth: "672px", margin: 0 }, children: subheading })
14
34
  ] });
15
35
  }
16
36
  function AtomCard({ title, content }) {
17
- return /* @__PURE__ */ jsxs("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "0.75rem", padding: "1.5rem", height: "100%" }, children: [
18
- title && /* @__PURE__ */ jsx("h3", { style: { fontSize: "1rem", fontWeight: 600, color: "var(--sp-text)", margin: "0 0 0.75rem" }, children: title }),
37
+ return /* @__PURE__ */ jsxs("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "12px", padding: "24px", height: "100%" }, children: [
38
+ title && /* @__PURE__ */ jsx("h3", { style: { fontSize: "16px", fontWeight: 600, color: "var(--sp-text)", margin: "0 0 12px" }, children: title }),
19
39
  content && /* @__PURE__ */ jsx(
20
40
  "div",
21
41
  {
22
42
  className: "sp-prose",
23
- style: { fontSize: "0.875rem", color: "var(--sp-text-sub)", lineHeight: 1.6 },
43
+ style: { fontSize: "15px", color: "var(--sp-text-sub)", lineHeight: 1.6 },
24
44
  dangerouslySetInnerHTML: { __html: renderMarkdown(content) }
25
45
  }
26
46
  )
27
47
  ] });
28
48
  }
29
- function StatGrid({ stats, caption }) {
49
+ function StatGrid({ stats = [], caption }) {
30
50
  const cols = stats.length === 2 ? 2 : stats.length === 3 ? 3 : 4;
31
- return /* @__PURE__ */ jsxs("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "0.75rem", padding: "1.5rem" }, children: [
32
- /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: "1.5rem" }, children: stats.map(({ value, label }) => /* @__PURE__ */ jsxs("div", { style: { textAlign: "center" }, children: [
33
- /* @__PURE__ */ jsx("p", { style: { fontSize: "1.875rem", fontWeight: 700, color: "var(--sp-text)", fontVariantNumeric: "tabular-nums", margin: 0 }, children: value }),
34
- /* @__PURE__ */ jsx("p", { style: { fontSize: "0.75rem", color: "var(--sp-text-muted)", marginTop: "0.375rem", textTransform: "uppercase", letterSpacing: "0.05em" }, children: label })
51
+ return /* @__PURE__ */ jsxs("div", { children: [
52
+ /* @__PURE__ */ jsx("div", { style: { display: "grid", gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: "12px" }, children: stats.map(({ value, label }) => /* @__PURE__ */ jsxs("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "10px", padding: "16px 20px", display: "flex", flexDirection: "column", justifyContent: "space-between", minHeight: "88px" }, children: [
53
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "11px", color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em", margin: "0 0 12px", lineHeight: 1.3 }, children: label }),
54
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "20px", fontWeight: 500, color: "var(--sp-text)", fontVariantNumeric: "tabular-nums", lineHeight: 1, margin: 0 }, children: value })
35
55
  ] }, label)) }),
36
- caption && /* @__PURE__ */ jsx("p", { style: { fontSize: "0.75rem", color: "var(--sp-text-muted)", textAlign: "center", marginTop: "1.25rem", borderTop: "1px solid var(--sp-border)", paddingTop: "1rem" }, children: caption })
56
+ caption && /* @__PURE__ */ jsx("p", { style: { fontSize: "13px", color: "var(--sp-text-muted)", margin: "12px 0 0" }, children: caption })
37
57
  ] });
38
58
  }
39
59
  function CodeBlock({ code, lang = "typescript", caption }) {
40
- return /* @__PURE__ */ jsxs("div", { style: { borderRadius: "0.75rem", overflow: "hidden", border: "1px solid var(--sp-border)" }, children: [
41
- /* @__PURE__ */ jsxs("div", { style: { background: "var(--sp-bg)", padding: "0.625rem 1rem", display: "flex", alignItems: "center", justifyContent: "space-between", borderBottom: "1px solid var(--sp-border)" }, children: [
42
- /* @__PURE__ */ jsx("span", { style: { fontSize: "0.75rem", color: "var(--sp-text-muted)", fontFamily: "monospace" }, children: lang }),
43
- caption && /* @__PURE__ */ jsx("span", { style: { fontSize: "0.75rem", color: "var(--sp-text-muted)" }, children: caption })
60
+ return /* @__PURE__ */ jsxs("div", { style: { borderRadius: "12px", overflow: "hidden", border: "1px solid var(--sp-border)" }, children: [
61
+ /* @__PURE__ */ jsxs("div", { style: { background: "var(--sp-bg)", padding: "10px 16px", display: "flex", alignItems: "center", justifyContent: "space-between", borderBottom: "1px solid var(--sp-border)" }, children: [
62
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: "var(--sp-text-muted)", fontFamily: "monospace" }, children: lang }),
63
+ caption && /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: "var(--sp-text-muted)" }, children: caption })
44
64
  ] }),
45
- /* @__PURE__ */ jsx("pre", { style: { background: "var(--sp-surface)", padding: "1.25rem", fontSize: "0.75rem", color: "var(--sp-text-sub)", overflowX: "auto", lineHeight: 1.6, fontFamily: "monospace", whiteSpace: "pre", margin: 0 }, children: code })
65
+ /* @__PURE__ */ jsx("pre", { style: { background: "var(--sp-surface)", padding: "20px", fontSize: "13px", color: "var(--sp-text-sub)", overflowX: "auto", lineHeight: 1.6, fontFamily: "monospace", whiteSpace: "pre", margin: 0 }, children: code })
46
66
  ] });
47
67
  }
48
- function ComparisonTable({ brand = "Us", competitor, rows }) {
49
- return /* @__PURE__ */ jsx("div", { style: { border: "1px solid var(--sp-border)", borderRadius: "0.75rem", overflow: "hidden" }, children: /* @__PURE__ */ jsx("div", { style: { overflowX: "auto" }, children: /* @__PURE__ */ jsxs("table", { style: { width: "100%", fontSize: "0.875rem", borderCollapse: "collapse" }, children: [
68
+ function ComparisonTable({ brand = "Us", competitor, rows = [] }) {
69
+ return /* @__PURE__ */ jsx("div", { style: { border: "1px solid var(--sp-border)", borderRadius: "12px", overflow: "hidden" }, children: /* @__PURE__ */ jsx("div", { style: { overflowX: "auto" }, children: /* @__PURE__ */ jsxs("table", { style: { width: "100%", fontSize: "14px", borderCollapse: "collapse" }, children: [
50
70
  /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { style: { borderBottom: "1px solid var(--sp-border)", background: "var(--sp-bg)" }, children: [
51
- /* @__PURE__ */ jsx("th", { style: { textAlign: "left", padding: "0.75rem 1rem", color: "var(--sp-text-muted)", fontWeight: 500, fontSize: "0.75rem", width: "33%" } }),
52
- /* @__PURE__ */ jsx("th", { style: { textAlign: "left", padding: "0.75rem 1rem", fontWeight: 600, color: "var(--sp-accent)", fontSize: "0.75rem" }, children: brand }),
53
- /* @__PURE__ */ jsx("th", { style: { textAlign: "left", padding: "0.75rem 1rem", color: "var(--sp-text-muted)", fontWeight: 500, fontSize: "0.75rem" }, children: competitor })
71
+ /* @__PURE__ */ jsx("th", { style: { textAlign: "left", padding: "12px 16px", color: "var(--sp-text-muted)", fontWeight: 500, fontSize: "12px", width: "33%" } }),
72
+ /* @__PURE__ */ jsx("th", { style: { textAlign: "left", padding: "12px 16px", fontWeight: 600, color: "var(--sp-accent)", fontSize: "12px" }, children: brand }),
73
+ /* @__PURE__ */ jsx("th", { style: { textAlign: "left", padding: "12px 16px", color: "var(--sp-text-muted)", fontWeight: 500, fontSize: "12px" }, children: competitor })
54
74
  ] }) }),
55
75
  /* @__PURE__ */ jsx("tbody", { children: rows.map(({ label, spectare, them }) => /* @__PURE__ */ jsxs("tr", { style: { borderBottom: "1px solid var(--sp-border)" }, children: [
56
- /* @__PURE__ */ jsx("td", { style: { padding: "0.75rem 1rem", fontSize: "0.75rem", color: "var(--sp-text-muted)", fontWeight: 500 }, children: label }),
57
- /* @__PURE__ */ jsx("td", { style: { padding: "0.75rem 1rem", fontSize: "0.75rem", color: "var(--sp-positive)", fontWeight: 500 }, children: spectare }),
58
- /* @__PURE__ */ jsx("td", { style: { padding: "0.75rem 1rem", fontSize: "0.75rem", color: "var(--sp-text-muted)" }, children: them })
76
+ /* @__PURE__ */ jsx("td", { style: { padding: "12px 16px", fontSize: "13px", color: "var(--sp-text-muted)", fontWeight: 500 }, children: label }),
77
+ /* @__PURE__ */ jsx("td", { style: { padding: "12px 16px", fontSize: "13px", color: "var(--sp-positive)", fontWeight: 500 }, children: spectare }),
78
+ /* @__PURE__ */ jsx("td", { style: { padding: "12px 16px", fontSize: "13px", color: "var(--sp-text-muted)" }, children: them })
59
79
  ] }, label)) })
60
80
  ] }) }) });
61
81
  }
62
- function FeatureList({ items }) {
63
- return /* @__PURE__ */ jsx("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "0.75rem", padding: "1.5rem" }, children: /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: "1rem" }, children: items.map(({ text, sub }) => /* @__PURE__ */ jsxs("li", { style: { display: "flex", gap: "0.75rem" }, children: [
64
- /* @__PURE__ */ jsx("span", { style: { color: "var(--sp-accent)", flexShrink: 0, fontSize: "0.875rem", marginTop: "0.125rem" }, children: "\u2713" }),
82
+ function FeatureList({ items = [] }) {
83
+ return /* @__PURE__ */ jsx("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "12px", padding: "24px" }, children: /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", margin: 0, padding: 0, display: "flex", flexDirection: "column", gap: "16px" }, children: items.map(({ text, sub }) => /* @__PURE__ */ jsxs("li", { style: { display: "flex", gap: "12px" }, children: [
84
+ /* @__PURE__ */ jsx("span", { style: { color: "var(--sp-accent)", flexShrink: 0, fontSize: "15px", marginTop: "2px" }, children: "\u2713" }),
65
85
  /* @__PURE__ */ jsxs("div", { children: [
66
- /* @__PURE__ */ jsx("p", { style: { fontSize: "0.875rem", fontWeight: 500, color: "var(--sp-text)", lineHeight: 1.4, margin: 0 }, children: text }),
67
- sub && /* @__PURE__ */ jsx("p", { style: { fontSize: "0.75rem", color: "var(--sp-text-muted)", marginTop: "0.25rem", lineHeight: 1.5, margin: "0.25rem 0 0" }, children: sub })
86
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "15px", fontWeight: 500, color: "var(--sp-text)", lineHeight: 1.4, margin: 0 }, children: text }),
87
+ sub && /* @__PURE__ */ jsx("p", { style: { fontSize: "13px", color: "var(--sp-text-muted)", lineHeight: 1.5, margin: "4px 0 0" }, children: sub })
68
88
  ] })
69
89
  ] }, text)) }) });
70
90
  }
71
91
  function TestimonialCard({ quote, name, role, company }) {
72
- return /* @__PURE__ */ jsxs("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "0.75rem", padding: "1.5rem", display: "flex", flexDirection: "column", gap: "1.25rem", height: "100%" }, children: [
73
- /* @__PURE__ */ jsxs("p", { style: { fontSize: "0.875rem", color: "var(--sp-text-sub)", lineHeight: 1.6, flex: 1, margin: 0 }, children: [
74
- /* @__PURE__ */ jsx("span", { style: { color: "var(--sp-text-dim)", fontSize: "1.125rem", lineHeight: 1, marginRight: "0.25rem" }, children: '"' }),
92
+ return /* @__PURE__ */ jsxs("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: "12px", padding: "24px", display: "flex", flexDirection: "column", gap: "20px", height: "100%" }, children: [
93
+ /* @__PURE__ */ jsxs("p", { style: { fontSize: "15px", color: "var(--sp-text-sub)", lineHeight: 1.6, flex: 1, margin: 0 }, children: [
94
+ /* @__PURE__ */ jsx("span", { style: { color: "var(--sp-text-dim)", fontSize: "18px", lineHeight: 1, marginRight: "4px" }, children: '"' }),
75
95
  quote,
76
- /* @__PURE__ */ jsx("span", { style: { color: "var(--sp-text-dim)", fontSize: "1.125rem", lineHeight: 1, marginLeft: "0.25rem" }, children: '"' })
96
+ /* @__PURE__ */ jsx("span", { style: { color: "var(--sp-text-dim)", fontSize: "18px", lineHeight: 1, marginLeft: "4px" }, children: '"' })
77
97
  ] }),
78
- /* @__PURE__ */ jsxs("div", { style: { borderTop: "1px solid var(--sp-border)", paddingTop: "1rem" }, children: [
79
- /* @__PURE__ */ jsx("p", { style: { fontSize: "0.875rem", fontWeight: 600, color: "var(--sp-text)", margin: 0 }, children: name }),
80
- /* @__PURE__ */ jsxs("p", { style: { fontSize: "0.75rem", color: "var(--sp-text-muted)", marginTop: "0.125rem", margin: "0.125rem 0 0" }, children: [
98
+ /* @__PURE__ */ jsxs("div", { style: { borderTop: "1px solid var(--sp-border)", paddingTop: "16px" }, children: [
99
+ /* @__PURE__ */ jsx("p", { style: { fontSize: "14px", fontWeight: 600, color: "var(--sp-text)", margin: 0 }, children: name }),
100
+ /* @__PURE__ */ jsxs("p", { style: { fontSize: "13px", color: "var(--sp-text-muted)", margin: "2px 0 0" }, children: [
81
101
  role,
82
102
  company ? `, ${company}` : ""
83
103
  ] })
84
104
  ] })
85
105
  ] });
86
106
  }
87
- function ImageHero({ src, alt = "", ratio = "16:9" }) {
107
+ function ImageCtaHero({ src, alt = "", headline, subheading, ctaLabel, ctaHref }) {
88
108
  if (!src) return null;
89
- const [w, h] = ratio.split(":").map(Number);
90
- const paddingBottom = w && h ? `${h / w * 100}%` : "56.25%";
91
- return /* @__PURE__ */ jsx("div", { style: { borderRadius: "0.75rem", overflow: "hidden", position: "relative", width: "100%", paddingBottom }, children: /* @__PURE__ */ jsx("img", { src, alt, style: { position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" } }) });
109
+ return /* @__PURE__ */ jsxs("div", { style: { borderRadius: "12px", overflow: "hidden", position: "relative", width: "100%", paddingBottom: "56.25%" }, children: [
110
+ /* @__PURE__ */ jsx("img", { src, alt, style: { position: "absolute", inset: 0, width: "100%", height: "100%", objectFit: "cover" } }),
111
+ /* @__PURE__ */ jsx("div", { style: { position: "absolute", inset: 0, background: "linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.3) 55%, transparent 100%)" } }),
112
+ /* @__PURE__ */ jsxs("div", { style: { position: "absolute", bottom: 0, left: 0, right: 0, padding: "28px" }, children: [
113
+ headline && /* @__PURE__ */ jsx("h2", { style: { fontSize: "24px", fontWeight: 700, color: "#fff", lineHeight: 1.2, margin: "0 0 8px", letterSpacing: "-0.02em" }, children: headline }),
114
+ subheading && /* @__PURE__ */ jsx("p", { style: { fontSize: "15px", color: "rgba(255,255,255,0.75)", lineHeight: 1.5, margin: "0 0 20px" }, children: subheading }),
115
+ ctaHref && ctaLabel && /* @__PURE__ */ jsx("a", { href: ctaHref, style: { display: "inline-block", background: "#fff", color: "#09090b", padding: "8px 20px", borderRadius: "8px", fontWeight: 600, fontSize: "14px", textDecoration: "none" }, children: ctaLabel })
116
+ ] })
117
+ ] });
92
118
  }
93
119
  function CtaStrip({ headline, primary, secondary }) {
94
- return /* @__PURE__ */ jsxs("div", { style: { border: "1px solid var(--sp-border)", borderRadius: "0.75rem", padding: "2rem", textAlign: "center", background: "var(--sp-bg)" }, children: [
95
- /* @__PURE__ */ jsx("h3", { style: { fontSize: "1.5rem", fontWeight: 700, color: "var(--sp-text)", margin: "0 0 1.5rem" }, children: headline }),
96
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "1rem", flexWrap: "wrap" }, children: [
97
- /* @__PURE__ */ jsx("a", { href: primary.href, style: { background: "#fff", color: "#09090b", padding: "0.625rem 1.5rem", borderRadius: "0.75rem", fontWeight: 600, fontSize: "0.875rem", textDecoration: "none" }, children: primary.label }),
98
- secondary && /* @__PURE__ */ jsxs("a", { href: secondary.href, style: { fontSize: "0.875rem", color: "var(--sp-text-sub)", textDecoration: "none" }, children: [
120
+ return /* @__PURE__ */ jsxs("div", { style: { border: "1px solid var(--sp-border)", borderRadius: "12px", padding: "32px", textAlign: "center", background: "var(--sp-bg)" }, children: [
121
+ /* @__PURE__ */ jsx("h3", { style: { fontSize: "24px", fontWeight: 700, color: "var(--sp-text)", margin: "0 0 24px" }, children: headline }),
122
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "16px", flexWrap: "wrap" }, children: [
123
+ /* @__PURE__ */ jsx("a", { href: primary.href, style: { background: "#fff", color: "#09090b", padding: "10px 24px", borderRadius: "12px", fontWeight: 600, fontSize: "15px", textDecoration: "none" }, children: primary.label }),
124
+ secondary && /* @__PURE__ */ jsxs("a", { href: secondary.href, style: { fontSize: "15px", color: "var(--sp-text-sub)", textDecoration: "none" }, children: [
99
125
  secondary.label,
100
126
  " \u2192"
101
127
  ] })
@@ -120,8 +146,8 @@ function renderSingle(item, brand) {
120
146
  return /* @__PURE__ */ jsx(FeatureList, { items: s.items });
121
147
  case "TestimonialCard":
122
148
  return /* @__PURE__ */ jsx(TestimonialCard, { quote: s.quote, name: s.name, role: s.role, company: s.company });
123
- case "ImageHero":
124
- return /* @__PURE__ */ jsx(ImageHero, { src: s.src, alt: s.alt, ratio: s.ratio });
149
+ case "ImageCtaHero":
150
+ return /* @__PURE__ */ jsx(ImageCtaHero, { src: s.src, alt: s.alt, headline: s.headline, subheading: s.subheading, ctaLabel: s.ctaLabel, ctaHref: s.ctaHref });
125
151
  case "CtaStrip":
126
152
  return /* @__PURE__ */ jsx(CtaStrip, { headline: s.headline, primary: s.primary, secondary: s.secondary });
127
153
  default:
@@ -152,48 +178,44 @@ function buildLayout(assembly) {
152
178
  return groups;
153
179
  }
154
180
  function XrayBadge({ name, size }) {
155
- return /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: "0.5rem", left: "0.5rem", zIndex: 10, display: "flex", alignItems: "center", gap: "0.375rem", pointerEvents: "none", userSelect: "none" }, children: [
156
- /* @__PURE__ */ jsx("span", { style: { fontSize: "0.625rem", fontFamily: "monospace", background: "rgba(59,130,246,0.9)", color: "#fff", padding: "0.125rem 0.375rem", borderRadius: "0.25rem", lineHeight: 1 }, children: name }),
157
- /* @__PURE__ */ jsx("span", { style: { fontSize: "0.625rem", fontFamily: "monospace", color: "#71717a", lineHeight: 1 }, children: size })
181
+ return /* @__PURE__ */ jsxs("div", { style: { position: "absolute", top: "8px", left: "8px", zIndex: 10, display: "flex", alignItems: "center", gap: "6px", pointerEvents: "none", userSelect: "none" }, children: [
182
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "10px", fontFamily: "monospace", background: "rgba(59,130,246,0.9)", color: "#fff", padding: "2px 6px", borderRadius: "4px", lineHeight: 1 }, children: name }),
183
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "10px", fontFamily: "monospace", color: "#71717a", lineHeight: 1 }, children: size })
158
184
  ] });
159
185
  }
160
- function ComponentRenderer({ assembly, brand, xray = false }) {
161
- const layout = buildLayout(assembly);
162
- return /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", gap: "1.25rem" }, children: layout.map((group, i) => {
163
- if (group.type === "full") {
186
+ var PAIR_STYLE = ".sp-pair{display:grid;grid-template-columns:1fr 1fr;gap:20px}@media(max-width:640px){.sp-pair{grid-template-columns:1fr}}";
187
+ function ComponentRenderer({ assembly, brand, xray = false, zone }) {
188
+ const filtered = zone ? filterAssemblyByZone(assembly, zone) : assembly;
189
+ const layout = buildLayout(filtered);
190
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "20px", fontSize: "16px" }, children: [
191
+ /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: PAIR_STYLE } }),
192
+ layout.map((group, i) => {
193
+ if (group.type === "full") {
194
+ return /* @__PURE__ */ jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
195
+ xray && /* @__PURE__ */ jsx(XrayBadge, { name: group.item.component, size: "full" }),
196
+ renderSingle(group.item, brand)
197
+ ] }, i);
198
+ }
199
+ if (group.type === "pair") {
200
+ return /* @__PURE__ */ jsxs("div", { className: "sp-pair", children: [
201
+ /* @__PURE__ */ jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
202
+ xray && /* @__PURE__ */ jsx(XrayBadge, { name: group.items[0].component, size: "half" }),
203
+ renderSingle(group.items[0], brand)
204
+ ] }),
205
+ /* @__PURE__ */ jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
206
+ xray && /* @__PURE__ */ jsx(XrayBadge, { name: group.items[1].component, size: "half" }),
207
+ renderSingle(group.items[1], brand)
208
+ ] })
209
+ ] }, i);
210
+ }
164
211
  return /* @__PURE__ */ jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
165
212
  xray && /* @__PURE__ */ jsx(XrayBadge, { name: group.item.component, size: "full" }),
166
213
  renderSingle(group.item, brand)
167
214
  ] }, i);
168
- }
169
- if (group.type === "pair") {
170
- return /* @__PURE__ */ jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "1.25rem" }, children: [
171
- /* @__PURE__ */ jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
172
- xray && /* @__PURE__ */ jsx(XrayBadge, { name: group.items[0].component, size: "half" }),
173
- renderSingle(group.items[0], brand)
174
- ] }),
175
- /* @__PURE__ */ jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
176
- xray && /* @__PURE__ */ jsx(XrayBadge, { name: group.items[1].component, size: "half" }),
177
- renderSingle(group.items[1], brand)
178
- ] })
179
- ] }, i);
180
- }
181
- return /* @__PURE__ */ jsxs("div", { style: xray ? { position: "relative" } : void 0, children: [
182
- xray && /* @__PURE__ */ jsx(XrayBadge, { name: group.item.component, size: "full" }),
183
- renderSingle(group.item, brand)
184
- ] }, i);
185
- }) });
215
+ })
216
+ ] });
186
217
  }
187
218
  var CSS_TOKENS = `:root{--sp-accent:#60a5fa;--sp-accent-bg:rgba(96,165,250,0.1);--sp-accent-border:rgba(96,165,250,0.2);--sp-bg:#18181b;--sp-surface:#09090b;--sp-border:#27272a;--sp-text:#f4f4f5;--sp-text-sub:#d4d4d8;--sp-text-strong:#e4e4e7;--sp-text-muted:#71717a;--sp-text-dim:#52525b;--sp-text-body:#a1a1aa;--sp-positive:#6ee7b7;--sp-divider:rgba(255,255,255,0.06);--sp-code-bg:rgba(255,255,255,0.07);--sp-code-border:rgba(255,255,255,0.08);--sp-pre-bg:rgba(0,0,0,0.4)}.sp-prose p{margin-bottom:.625rem}.sp-prose p:last-child{margin-bottom:0}.sp-prose ul{list-style:disc;padding-left:1.25rem;margin-bottom:.625rem}.sp-prose ol{list-style:decimal;padding-left:1.25rem;margin-bottom:.625rem}.sp-prose li{margin-bottom:.25rem}.sp-prose strong{color:var(--sp-text-strong);font-weight:600}.sp-prose h2,.sp-prose h3{color:var(--sp-text);font-weight:600;margin:.875rem 0 .375rem;font-size:1rem}.sp-prose code{background:var(--sp-code-bg);border:1px solid var(--sp-code-border);padding:.1rem .35rem;border-radius:.25rem;font-size:.82em;color:var(--sp-text)}.sp-prose blockquote{border-left:3px solid var(--sp-border);padding-left:1rem;color:var(--sp-text-muted);margin:.75rem 0}`;
188
- function extractAtomIds(assembly) {
189
- var _a;
190
- const ids = [];
191
- for (const item of assembly) {
192
- const id = (_a = item.slots) == null ? void 0 : _a.atomId;
193
- if (typeof id === "number") ids.push(id);
194
- }
195
- return ids;
196
- }
197
219
  function buildSummary(pageHint, orgSlug) {
198
220
  const parts = [pageHint];
199
221
  const referrer = document.referrer;
@@ -215,11 +237,11 @@ function buildSummary(pageHint, orgSlug) {
215
237
  return parts.filter(Boolean).join(". ");
216
238
  }
217
239
  function Shimmer() {
218
- return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.75rem" }, children: [
219
- /* @__PURE__ */ jsx("div", { style: { height: "1.25rem", background: "rgba(39,39,42,0.6)", borderRadius: "0.5rem", width: "75%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
220
- /* @__PURE__ */ jsx("div", { style: { height: "0.875rem", background: "rgba(39,39,42,0.4)", borderRadius: "0.5rem", width: "100%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
221
- /* @__PURE__ */ jsx("div", { style: { height: "0.875rem", background: "rgba(39,39,42,0.4)", borderRadius: "0.5rem", width: "83%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
222
- /* @__PURE__ */ jsx("div", { style: { height: "0.875rem", background: "rgba(39,39,42,0.4)", borderRadius: "0.5rem", width: "67%", animation: "sp-pulse 1.5s ease-in-out infinite" } })
240
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
241
+ /* @__PURE__ */ jsx("div", { style: { height: "20px", background: "rgba(39,39,42,0.6)", borderRadius: "8px", width: "75%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
242
+ /* @__PURE__ */ jsx("div", { style: { height: "14px", background: "rgba(39,39,42,0.4)", borderRadius: "8px", width: "100%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
243
+ /* @__PURE__ */ jsx("div", { style: { height: "14px", background: "rgba(39,39,42,0.4)", borderRadius: "8px", width: "83%", animation: "sp-pulse 1.5s ease-in-out infinite" } }),
244
+ /* @__PURE__ */ jsx("div", { style: { height: "14px", background: "rgba(39,39,42,0.4)", borderRadius: "8px", width: "67%", animation: "sp-pulse 1.5s ease-in-out infinite" } })
223
245
  ] });
224
246
  }
225
247
  function PersonalisedSection({
@@ -231,13 +253,13 @@ function PersonalisedSection({
231
253
  style,
232
254
  initialAssembly,
233
255
  initialIntent,
234
- conversionUrlPatterns
256
+ zone
235
257
  }) {
236
- const [assembly, setAssembly] = useState(initialAssembly != null ? initialAssembly : null);
258
+ const [assembly, setAssembly] = useState(initialAssembly != null ? initialAssembly : []);
237
259
  const [loading, setLoading] = useState(!initialAssembly);
260
+ const [orgName, setOrgName] = useState(void 0);
238
261
  const tokenRef = useRef(null);
239
262
  const conversionFiredRef = useRef(false);
240
- const conversionPatternsRef = useRef(conversionUrlPatterns != null ? conversionUrlPatterns : []);
241
263
  useEffect(() => {
242
264
  let cancelled = false;
243
265
  async function load() {
@@ -261,11 +283,10 @@ function PersonalisedSection({
261
283
  setLoading(false);
262
284
  return;
263
285
  }
264
- const data2 = await res2.json();
265
- token = (_a = data2.token) != null ? _a : null;
286
+ const data = await res2.json();
287
+ token = (_a = data.token) != null ? _a : null;
266
288
  if (token) sessionStorage.setItem(tokenKey, token);
267
- const orgPatterns = (_b = data2.conversionUrlPatterns) != null ? _b : [];
268
- conversionPatternsRef.current = [.../* @__PURE__ */ new Set([...conversionUrlPatterns != null ? conversionUrlPatterns : [], ...orgPatterns])];
289
+ if (data.orgName) setOrgName(data.orgName);
269
290
  }
270
291
  if (!token || cancelled) {
271
292
  setLoading(false);
@@ -290,12 +311,10 @@ function PersonalisedSection({
290
311
  return;
291
312
  }
292
313
  const qData = await qRes.json();
293
- token = (_c = qData.token) != null ? _c : null;
314
+ token = (_b = qData.token) != null ? _b : null;
294
315
  if (token) {
295
316
  sessionStorage.setItem(tokenKey, token);
296
317
  tokenRef.current = token;
297
- const orgPatterns = (_d = qData.conversionUrlPatterns) != null ? _d : [];
298
- conversionPatternsRef.current = [.../* @__PURE__ */ new Set([...conversionUrlPatterns != null ? conversionUrlPatterns : [], ...orgPatterns])];
299
318
  }
300
319
  if (!token || cancelled) {
301
320
  setLoading(false);
@@ -311,13 +330,47 @@ function PersonalisedSection({
311
330
  setLoading(false);
312
331
  return;
313
332
  }
314
- const data = await res.json();
315
- if (cancelled) return;
316
- const clientAudience = (_f = (_e = data.intent) == null ? void 0 : _e.userContext) == null ? void 0 : _f.audience;
317
- const clientStage = (_h = (_g = data.intent) == null ? void 0 : _g.userContext) == null ? void 0 : _h.stage;
318
- const ssrMatches = initialIntent && clientAudience === initialIntent.audience && clientStage === initialIntent.stage;
319
- if (!ssrMatches && Array.isArray(data.assembly) && data.assembly.length > 0) {
320
- setAssembly(data.assembly);
333
+ const contentType = (_c = res.headers.get("content-type")) != null ? _c : "";
334
+ if (contentType.includes("text/event-stream")) {
335
+ const reader = res.body.getReader();
336
+ const decoder = new TextDecoder();
337
+ let buf = "";
338
+ let loadingCleared = false;
339
+ try {
340
+ while (!cancelled) {
341
+ const { done, value } = await reader.read();
342
+ if (done || cancelled) break;
343
+ buf += decoder.decode(value, { stream: true });
344
+ const lines = buf.split("\n");
345
+ buf = (_d = lines.pop()) != null ? _d : "";
346
+ for (const line of lines) {
347
+ if (!line.startsWith("data: ")) continue;
348
+ const payload = line.slice(6).trim();
349
+ if (payload === "[DONE]") break;
350
+ try {
351
+ const comp = JSON.parse(payload);
352
+ if (!loadingCleared) {
353
+ setLoading(false);
354
+ loadingCleared = true;
355
+ }
356
+ setAssembly((prev) => [...prev, comp]);
357
+ } catch (e) {
358
+ }
359
+ }
360
+ }
361
+ } finally {
362
+ reader.cancel().catch(() => {
363
+ });
364
+ }
365
+ } else {
366
+ const data = await res.json();
367
+ if (cancelled) return;
368
+ const clientAudience = (_f = (_e = data.intent) == null ? void 0 : _e.userContext) == null ? void 0 : _f.audience;
369
+ const clientStage = (_h = (_g = data.intent) == null ? void 0 : _g.userContext) == null ? void 0 : _h.stage;
370
+ const ssrMatches = initialIntent && clientAudience === initialIntent.audience && clientStage === initialIntent.stage;
371
+ if (!ssrMatches && Array.isArray(data.assembly) && data.assembly.length > 0) {
372
+ setAssembly(data.assembly);
373
+ }
321
374
  }
322
375
  } catch (e) {
323
376
  } finally {
@@ -330,27 +383,60 @@ function PersonalisedSection({
330
383
  };
331
384
  }, [orgSlug, baseUrl, pageHint, initialAssembly, initialIntent]);
332
385
  useEffect(() => {
333
- if (!assembly || !conversionPatternsRef.current.length || conversionFiredRef.current) return;
334
- const url = window.location.href;
335
- if (!conversionPatternsRef.current.some((p) => url.includes(p))) return;
336
- conversionFiredRef.current = true;
386
+ if (!assembly.length || conversionFiredRef.current) return;
337
387
  const token = tokenRef.current;
338
388
  if (!token) return;
339
- fetch(`${baseUrl}/api/conversion`, {
389
+ const url = window.location.href;
390
+ fetch(`${baseUrl}/api/conversion-check`, {
340
391
  method: "POST",
341
392
  headers: { "Content-Type": "application/json" },
342
- body: JSON.stringify({ token, orgSlug, url, atomsShown: extractAtomIds(assembly) })
393
+ body: JSON.stringify({ orgSlug, url })
394
+ }).then((r) => r.json()).then((data) => {
395
+ var _a, _b;
396
+ if (!data.matched) return;
397
+ conversionFiredRef.current = true;
398
+ let goalValue = null;
399
+ let goalCurrency = data.defaultCurrency;
400
+ if (data.valueSelector) {
401
+ try {
402
+ const el = document.querySelector(data.valueSelector);
403
+ if (el) {
404
+ const num = parseFloat(((_a = el.textContent) != null ? _a : "").trim().replace(/[^0-9.]/g, ""));
405
+ if (!isNaN(num)) goalValue = num;
406
+ }
407
+ } catch (e) {
408
+ }
409
+ }
410
+ if (data.currencySelector) {
411
+ try {
412
+ const el = document.querySelector(data.currencySelector);
413
+ if (el) goalCurrency = ((_b = el.textContent) != null ? _b : "").trim() || goalCurrency;
414
+ } catch (e) {
415
+ }
416
+ }
417
+ fetch(`${baseUrl}/api/conversion`, {
418
+ method: "POST",
419
+ headers: { "Content-Type": "application/json" },
420
+ body: JSON.stringify({
421
+ token,
422
+ orgSlug,
423
+ url,
424
+ ...data.goalName ? { goalName: data.goalName } : {},
425
+ ...goalValue !== null ? { goalValue, goalCurrency } : {}
426
+ })
427
+ }).catch(() => {
428
+ });
343
429
  }).catch(() => {
344
430
  });
345
431
  }, [assembly, orgSlug, baseUrl]);
346
- if (!loading && !assembly) return null;
432
+ if (!loading && assembly.length === 0) return null;
347
433
  return /* @__PURE__ */ jsxs(Fragment, { children: [
348
434
  /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: CSS_TOKENS } }),
349
435
  /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: "@keyframes sp-pulse{0%,100%{opacity:1}50%{opacity:0.4}}" } }),
350
- /* @__PURE__ */ jsx("div", { className, style, children: loading ? /* @__PURE__ */ jsx(Shimmer, {}) : assembly && /* @__PURE__ */ jsx(ComponentRenderer, { assembly, brand }) })
436
+ /* @__PURE__ */ jsx("div", { className, style, children: loading && assembly.length === 0 ? /* @__PURE__ */ jsx(Shimmer, {}) : /* @__PURE__ */ jsx(ComponentRenderer, { assembly: zone ? filterAssemblyByZone(assembly, zone) : assembly, brand: brand != null ? brand : orgName }) })
351
437
  ] });
352
438
  }
353
439
 
354
- export { ComponentRenderer, PersonalisedSection };
440
+ export { ComponentRenderer, PersonalisedSection, filterAssemblyByZone };
355
441
  //# sourceMappingURL=index.js.map
356
442
  //# sourceMappingURL=index.js.map