@spectare-personalisation/react 0.5.0 → 0.7.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.cjs +69 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +59 -46
- package/dist/index.d.ts +59 -46
- package/dist/index.js +69 -28
- package/dist/index.js.map +1 -1
- package/dist/tokens.css +2 -2
- package/dist/tokens.css.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -92,19 +92,47 @@ var COMPONENT_CATEGORIES = {
|
|
|
92
92
|
|
|
93
93
|
// src/tokens.ts
|
|
94
94
|
var DEFAULT_ACCENT = "#60a5fa";
|
|
95
|
+
var DEFAULT_ACCENT_LIGHT = "#2563eb";
|
|
95
96
|
var SP_ROOT = "sp-root";
|
|
96
97
|
var STYLESHEET_SCOPE = `:where(:root),.${SP_ROOT}`;
|
|
97
|
-
function palette(accent) {
|
|
98
|
-
|
|
98
|
+
function palette(accent, theme) {
|
|
99
|
+
const shared = {
|
|
99
100
|
"--sp-accent": accent,
|
|
100
101
|
"--sp-accent-bg": `color-mix(in srgb,${accent} 10%,transparent)`,
|
|
101
|
-
"--sp-accent-border": `color-mix(in srgb,${accent} 20%,transparent)
|
|
102
|
+
"--sp-accent-border": `color-mix(in srgb,${accent} 20%,transparent)`
|
|
103
|
+
};
|
|
104
|
+
if (theme === "light") {
|
|
105
|
+
return {
|
|
106
|
+
...shared,
|
|
107
|
+
"--sp-bg": "#ffffff",
|
|
108
|
+
"--sp-surface": "#f4f4f5",
|
|
109
|
+
"--sp-border": "#e4e4e7",
|
|
110
|
+
"--sp-text": "#18181b",
|
|
111
|
+
"--sp-text-sub": "#3f3f46",
|
|
112
|
+
"--sp-text-strong": "#27272a",
|
|
113
|
+
"--sp-text-muted": "#6b6b74",
|
|
114
|
+
"--sp-text-dim": "#82828b",
|
|
115
|
+
"--sp-text-body": "#52525b",
|
|
116
|
+
"--sp-positive": "#047857",
|
|
117
|
+
"--sp-cta-bg": "#18181b",
|
|
118
|
+
"--sp-cta-text": "#ffffff",
|
|
119
|
+
"--sp-divider": "rgba(0,0,0,0.06)",
|
|
120
|
+
"--sp-code-bg": "rgba(0,0,0,0.05)",
|
|
121
|
+
"--sp-code-border": "rgba(0,0,0,0.08)",
|
|
122
|
+
"--sp-pre-bg": "rgba(0,0,0,0.04)"
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
...shared,
|
|
102
127
|
"--sp-bg": "#18181b",
|
|
103
128
|
"--sp-surface": "#09090b",
|
|
104
129
|
"--sp-border": "#27272a",
|
|
105
130
|
"--sp-text": "#f4f4f5",
|
|
106
|
-
|
|
107
|
-
|
|
131
|
+
// Body prose colour. Was #d4d4d8, judged too grey against near-black at reading
|
|
132
|
+
// sizes; one step brighter keeps the hierarchy below --sp-text while reading as
|
|
133
|
+
// text rather than chrome.
|
|
134
|
+
"--sp-text-sub": "#e4e4e7",
|
|
135
|
+
"--sp-text-strong": "#ececee",
|
|
108
136
|
"--sp-text-muted": "#82828b",
|
|
109
137
|
"--sp-text-dim": "#6b6b74",
|
|
110
138
|
"--sp-text-body": "#a1a1aa",
|
|
@@ -133,8 +161,9 @@ function rules(unit) {
|
|
|
133
161
|
"@media(max-width:640px){.sp-root .sp-pair{grid-template-columns:1fr}}"
|
|
134
162
|
].join("");
|
|
135
163
|
}
|
|
136
|
-
function buildTokenCss({ accent
|
|
137
|
-
const
|
|
164
|
+
function buildTokenCss({ accent, unit = "px", scope = `.${SP_ROOT}`, theme = "dark" } = {}) {
|
|
165
|
+
const resolved = accent != null ? accent : theme === "light" ? DEFAULT_ACCENT_LIGHT : DEFAULT_ACCENT;
|
|
166
|
+
const decls = Object.entries(palette(resolved, theme)).map(([k, v]) => `${k}:${v}`).join(";");
|
|
138
167
|
return `${scope}{${decls}}${rules(unit)}`;
|
|
139
168
|
}
|
|
140
169
|
|
|
@@ -188,17 +217,28 @@ var clampStyle = {
|
|
|
188
217
|
WebkitBoxOrient: "vertical",
|
|
189
218
|
overflow: "hidden"
|
|
190
219
|
};
|
|
191
|
-
function AtomCard({ title, content, layout, stats = [], ctaText, ctaUrl, full, unit = "px" }) {
|
|
220
|
+
function AtomCard({ title, content, summary, layout, stats = [], ctaText, ctaUrl, full, variant, unit = "px" }) {
|
|
192
221
|
const u = scaler(unit);
|
|
222
|
+
if (variant === "card") {
|
|
223
|
+
const face = (summary == null ? void 0 : summary.trim()) || (content ? `${content.replace(/\s+/g, " ").split(/(?<=[.!?])\s/)[0]}` : "");
|
|
224
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: u(12), padding: u(20) }, children: [
|
|
225
|
+
title && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: { fontSize: u(18), fontWeight: 600, color: "var(--sp-text)", margin: 0, lineHeight: 1.35 }, children: title }),
|
|
226
|
+
face && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(16), color: "var(--sp-text-sub)", lineHeight: 1.6, margin: `${u(8)} 0 0` }, children: face }),
|
|
227
|
+
content && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("details", { style: { marginTop: u(10) }, children: [
|
|
228
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("summary", { style: { cursor: "pointer", fontSize: u(14), fontWeight: 600, color: "var(--sp-accent)", listStyle: "none" }, children: "Read more" }),
|
|
229
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sp-prose", style: { fontSize: u(16), color: "var(--sp-text-sub)", lineHeight: 1.6, marginTop: u(10) }, dangerouslySetInnerHTML: { __html: renderMarkdown(content) } })
|
|
230
|
+
] })
|
|
231
|
+
] });
|
|
232
|
+
}
|
|
193
233
|
const order = layout && layout.length ? layout : ATOM_LAYOUT_DEFAULT;
|
|
194
234
|
const element = (name) => {
|
|
195
|
-
if (name === "title") return title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: { fontSize: u(
|
|
196
|
-
if (name === "content") return content ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sp-prose", style: { fontSize: u(
|
|
197
|
-
if (name === "stats") return stats.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: u(20), margin:
|
|
235
|
+
if (name === "title") return title ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h3", { style: { fontSize: u(18), fontWeight: 600, color: "var(--sp-text)", margin: `0 0 ${u(12)}` }, children: title }, "title") : null;
|
|
236
|
+
if (name === "content") return content ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "sp-prose", style: { fontSize: u(16), color: "var(--sp-text-sub)", lineHeight: 1.6, ...full ? {} : clampStyle }, dangerouslySetInnerHTML: { __html: renderMarkdown(content) } }, "content") : null;
|
|
237
|
+
if (name === "stats") return stats.length ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", flexWrap: "wrap", gap: u(20), margin: `${u(18)} 0 ${u(12)}`, padding: `0 0 ${u(14)}`, borderBottom: "1px solid var(--sp-border)" }, children: stats.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: u(2) }, children: [
|
|
198
238
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: u(22), fontWeight: 700, color: "var(--sp-text)", lineHeight: 1, fontVariantNumeric: "tabular-nums" }, children: s.value }),
|
|
199
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: u(
|
|
239
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: u(12), color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em" }, children: s.label })
|
|
200
240
|
] }, i)) }, "stats") : null;
|
|
201
|
-
if (name === "cta") return ctaText && ctaUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", { href: ctaUrl, style: { display: "inline-flex", alignItems: "center", gap: u(4), marginTop: u(12), fontSize: u(
|
|
241
|
+
if (name === "cta") return ctaText && ctaUrl ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", { href: ctaUrl, style: { display: "inline-flex", alignItems: "center", gap: u(4), marginTop: u(12), fontSize: u(14), fontWeight: 600, color: "var(--sp-accent)", textDecoration: "none" }, children: [
|
|
202
242
|
ctaText,
|
|
203
243
|
" \u2192"
|
|
204
244
|
] }, "cta") : null;
|
|
@@ -211,10 +251,10 @@ function StatGrid({ stats = [], caption, unit = "px" }) {
|
|
|
211
251
|
const cols = stats.length === 2 ? 2 : stats.length === 3 ? 3 : 4;
|
|
212
252
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
213
253
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "grid", gridTemplateColumns: `repeat(${cols}, 1fr)`, gap: u(12) }, children: stats.map(({ value, label }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { background: "var(--sp-bg)", border: "1px solid var(--sp-border)", borderRadius: u(10), padding: `${u(16)} ${u(20)}`, display: "flex", flexDirection: "column", justifyContent: "space-between", minHeight: u(88) }, children: [
|
|
214
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(
|
|
254
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(12), color: "var(--sp-text-muted)", textTransform: "uppercase", letterSpacing: "0.06em", margin: `0 0 ${u(12)}`, lineHeight: 1.3 }, children: label }),
|
|
215
255
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(20), fontWeight: 500, color: "var(--sp-text)", fontVariantNumeric: "tabular-nums", lineHeight: 1, margin: 0 }, children: value })
|
|
216
256
|
] }, label)) }),
|
|
217
|
-
caption && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(
|
|
257
|
+
caption && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(14), color: "var(--sp-text-muted)", margin: `${u(12)} 0 0` }, children: caption })
|
|
218
258
|
] });
|
|
219
259
|
}
|
|
220
260
|
function CodeBlock({ code, lang = "typescript", caption, unit = "px" }) {
|
|
@@ -232,14 +272,14 @@ function ComparisonTable({ brand = "Us", competitor, rows = [], unit = "px" }) {
|
|
|
232
272
|
const cell = { textAlign: "left", padding: `${u(12)} ${u(16)}` };
|
|
233
273
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { border: "1px solid var(--sp-border)", borderRadius: u(12), overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { overflowX: "auto" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("table", { style: { width: "100%", fontSize: u(14), borderCollapse: "collapse" }, children: [
|
|
234
274
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { style: { borderBottom: "1px solid var(--sp-border)", background: "var(--sp-bg)" }, children: [
|
|
235
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(
|
|
236
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", style: { ...cell, fontWeight: 600, color: "var(--sp-accent)", fontSize: u(
|
|
237
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(
|
|
275
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(13), width: "33%" } }),
|
|
276
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", style: { ...cell, fontWeight: 600, color: "var(--sp-accent)", fontSize: u(13) }, children: brand }),
|
|
277
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "col", style: { ...cell, color: "var(--sp-text-muted)", fontWeight: 500, fontSize: u(13) }, children: competitor })
|
|
238
278
|
] }) }),
|
|
239
279
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("tbody", { children: rows.map(({ label, spectare, them }) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("tr", { style: { borderBottom: "1px solid var(--sp-border)" }, children: [
|
|
240
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "row", style: { ...cell, fontSize: u(
|
|
241
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { ...cell, fontSize: u(
|
|
242
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { ...cell, fontSize: u(
|
|
280
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("th", { scope: "row", style: { ...cell, fontSize: u(14), color: "var(--sp-text-muted)", fontWeight: 500 }, children: label }),
|
|
281
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { ...cell, fontSize: u(14), color: "var(--sp-positive)", fontWeight: 500 }, children: spectare }),
|
|
282
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("td", { style: { ...cell, fontSize: u(14), color: "var(--sp-text-muted)" }, children: them })
|
|
243
283
|
] }, label)) })
|
|
244
284
|
] }) }) });
|
|
245
285
|
}
|
|
@@ -249,7 +289,7 @@ function FeatureList({ items = [], unit = "px" }) {
|
|
|
249
289
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { color: "var(--sp-accent)", flexShrink: 0, fontSize: u(15), marginTop: u(2) }, children: "\u2713" }),
|
|
250
290
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
251
291
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(15), fontWeight: 500, color: "var(--sp-text)", lineHeight: 1.4, margin: 0 }, children: text }),
|
|
252
|
-
sub && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(
|
|
292
|
+
sub && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(14), color: "var(--sp-text-muted)", lineHeight: 1.5, margin: `${u(4)} 0 0` }, children: sub })
|
|
253
293
|
] })
|
|
254
294
|
] }, text)) }) });
|
|
255
295
|
}
|
|
@@ -263,7 +303,7 @@ function TestimonialCard({ quote, name, role, company, unit = "px" }) {
|
|
|
263
303
|
] }),
|
|
264
304
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { borderTop: "1px solid var(--sp-border)", paddingTop: u(16) }, children: [
|
|
265
305
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { fontSize: u(14), fontWeight: 600, color: "var(--sp-text)", margin: 0 }, children: name }),
|
|
266
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: { fontSize: u(
|
|
306
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { style: { fontSize: u(14), color: "var(--sp-text-muted)", margin: `${u(2)} 0 0` }, children: [
|
|
267
307
|
role,
|
|
268
308
|
company ? `, ${company}` : ""
|
|
269
309
|
] })
|
|
@@ -307,7 +347,7 @@ function renderSingle(item, brand, align, unit = "px") {
|
|
|
307
347
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(HeroStatement, { headline: s.headline, subheading: s.subheading, align, unit });
|
|
308
348
|
// A full-width card has nothing beside it, so there is nothing for a clamp to protect.
|
|
309
349
|
case "AtomCard":
|
|
310
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AtomCard, { title: s.title, content: s.content, layout: s.layout, stats: s.stats, ctaText: s.ctaText, ctaUrl: s.ctaUrl, full: s.full || resolvedSize(item) === "full", unit });
|
|
350
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(AtomCard, { title: s.title, content: s.content, summary: s.summary, layout: s.layout, stats: s.stats, ctaText: s.ctaText, ctaUrl: s.ctaUrl, full: s.full || resolvedSize(item) === "full", variant: s.variant, unit });
|
|
311
351
|
case "StatGrid":
|
|
312
352
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatGrid, { stats: s.stats, caption: s.caption, unit });
|
|
313
353
|
case "CodeBlock":
|
|
@@ -373,7 +413,7 @@ function XrayBadge({ name, size }) {
|
|
|
373
413
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: PX(10), fontFamily: "monospace", color: "#71717a", lineHeight: 1 }, children: size })
|
|
374
414
|
] });
|
|
375
415
|
}
|
|
376
|
-
function ComponentRenderer({ assembly, brand, xray = false, zone, align, accent, unit = "px", renderOverride, renderItem, rootProps }) {
|
|
416
|
+
function ComponentRenderer({ assembly, brand, xray = false, zone, align, accent, theme, unit = "px", renderOverride, renderItem, rootProps }) {
|
|
377
417
|
const u = scaler(unit);
|
|
378
418
|
const filtered = zone ? filterAssemblyByZone(assembly, zone) : assembly;
|
|
379
419
|
const layout = buildLayout(filtered);
|
|
@@ -384,7 +424,7 @@ function ComponentRenderer({ assembly, brand, xray = false, zone, align, accent,
|
|
|
384
424
|
return renderItem ? renderItem(item, node) : node;
|
|
385
425
|
};
|
|
386
426
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: extraClass ? `${SP_ROOT} ${extraClass}` : SP_ROOT, ...restRoot, style: { ...extraStyle, display: "flex", flexDirection: "column", gap: u(20), ...unit === "px" ? { fontSize: "16px" } : {} }, children: [
|
|
387
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { dangerouslySetInnerHTML: { __html: buildTokenCss({ accent, unit }) } }),
|
|
427
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { dangerouslySetInnerHTML: { __html: buildTokenCss({ accent, unit, theme }) } }),
|
|
388
428
|
layout.map((group, i) => {
|
|
389
429
|
if (group.type === "pair") {
|
|
390
430
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "sp-pair", children: [
|
|
@@ -477,7 +517,8 @@ function PersonalisedSection({
|
|
|
477
517
|
directSummary,
|
|
478
518
|
zone,
|
|
479
519
|
align,
|
|
480
|
-
accent
|
|
520
|
+
accent,
|
|
521
|
+
theme
|
|
481
522
|
}) {
|
|
482
523
|
const [assembly, setAssembly] = (0, import_react.useState)(initialAssembly != null ? initialAssembly : []);
|
|
483
524
|
const [loading, setLoading] = (0, import_react.useState)(!initialAssembly);
|
|
@@ -728,7 +769,7 @@ function PersonalisedSection({
|
|
|
728
769
|
debugIntent.stage
|
|
729
770
|
] })
|
|
730
771
|
] }),
|
|
731
|
-
loading && assembly.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Shimmer, {}) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ComponentRenderer, { assembly: zone ? filterAssemblyByZone(assembly, zone) : assembly, brand: brand != null ? brand : orgName, align, accent })
|
|
772
|
+
loading && assembly.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Shimmer, {}) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ComponentRenderer, { assembly: zone ? filterAssemblyByZone(assembly, zone) : assembly, brand: brand != null ? brand : orgName, align, accent, theme })
|
|
732
773
|
] })
|
|
733
774
|
] });
|
|
734
775
|
}
|