@clay-ds/react 0.2.1 → 0.3.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/catalog.json +14 -13
- package/dist/{footerDefaults-zo_Pjl3n.cjs → footerDefaults-BILm5CMK.cjs} +551 -459
- package/dist/footerDefaults-BILm5CMK.cjs.map +1 -0
- package/dist/{footerDefaults-CByEGl8Q.js → footerDefaults-Dx94Jc_F.js} +551 -459
- package/dist/footerDefaults-Dx94Jc_F.js.map +1 -0
- package/dist/icons.cjs +2419 -0
- package/dist/icons.cjs.map +1 -0
- package/dist/icons.d.ts +20 -0
- package/dist/icons.js +2419 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.cjs +3 -1199
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +829 -658
- package/dist/index.js +3 -1199
- package/dist/index.js.map +1 -1
- package/dist/page-spec.cjs +20 -2
- package/dist/page-spec.cjs.map +1 -1
- package/dist/page-spec.d.ts +42 -0
- package/dist/page-spec.js +20 -2
- package/dist/page-spec.js.map +1 -1
- package/dist/render.cjs +28 -3
- package/dist/render.cjs.map +1 -1
- package/dist/render.js +28 -3
- package/dist/render.js.map +1 -1
- package/package.json +6 -2
- package/dist/footerDefaults-CByEGl8Q.js.map +0 -1
- package/dist/footerDefaults-zo_Pjl3n.cjs.map +0 -1
package/dist/render.cjs
CHANGED
|
@@ -9,7 +9,7 @@ const node_url = require("node:url");
|
|
|
9
9
|
const node_module = require("node:module");
|
|
10
10
|
const logos_resolve = require("./logos/resolve.cjs");
|
|
11
11
|
const pageSpec = require("./page-spec.cjs");
|
|
12
|
-
const footerDefaults = require("./footerDefaults-
|
|
12
|
+
const footerDefaults = require("./footerDefaults-BILm5CMK.cjs");
|
|
13
13
|
var _documentCurrentScript = typeof document !== "undefined" ? document.currentScript : null;
|
|
14
14
|
const __dirname$1 = node_path.dirname(node_url.fileURLToPath(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("render.cjs", document.baseURI).href));
|
|
15
15
|
const require$1 = node_module.createRequire(typeof document === "undefined" ? require("url").pathToFileURL(__filename).href : _documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === "SCRIPT" && _documentCurrentScript.src || new URL("render.cjs", document.baseURI).href);
|
|
@@ -25,6 +25,21 @@ function makeCtas(ctas) {
|
|
|
25
25
|
if (!(ctas == null ? void 0 : ctas.length)) return void 0;
|
|
26
26
|
return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: ctas.map((c, i) => /* @__PURE__ */ jsxRuntime.jsx("a", { href: c.href, style: { display: "contents" }, children: /* @__PURE__ */ jsxRuntime.jsx(footerDefaults.Button, { buttonStyle: i === 0 ? "primary" : "secondary", size: "regular", children: c.label }) }, i)) });
|
|
27
27
|
}
|
|
28
|
+
function makeMedia(m) {
|
|
29
|
+
if (!(m == null ? void 0 : m.src)) return void 0;
|
|
30
|
+
const isVideo = m.type === "video";
|
|
31
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
32
|
+
footerDefaults.MediaSlot,
|
|
33
|
+
{
|
|
34
|
+
type: isVideo ? "video" : "image",
|
|
35
|
+
src: m.src,
|
|
36
|
+
alt: m.alt,
|
|
37
|
+
fit: m.fit,
|
|
38
|
+
aspectRatio: m.aspectRatio,
|
|
39
|
+
...isVideo ? { autoPlay: true, loop: true } : {}
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
}
|
|
28
43
|
let _css = null;
|
|
29
44
|
function loadCss() {
|
|
30
45
|
if (_css) return _css;
|
|
@@ -52,6 +67,7 @@ const SECTION_REGISTRY = {
|
|
|
52
67
|
actionCaption: data.actionCaption,
|
|
53
68
|
actions: makeCtas(data.ctas),
|
|
54
69
|
logos,
|
|
70
|
+
media: makeMedia(data.media),
|
|
55
71
|
containerWidth: data.containerWidth
|
|
56
72
|
}
|
|
57
73
|
);
|
|
@@ -72,6 +88,10 @@ const SECTION_REGISTRY = {
|
|
|
72
88
|
);
|
|
73
89
|
},
|
|
74
90
|
FeaturesSection(data) {
|
|
91
|
+
const items = data.items.map((it) => ({
|
|
92
|
+
...it,
|
|
93
|
+
media: makeMedia(it.media)
|
|
94
|
+
}));
|
|
75
95
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
76
96
|
footerDefaults.FeaturesSection,
|
|
77
97
|
{
|
|
@@ -79,12 +99,17 @@ const SECTION_REGISTRY = {
|
|
|
79
99
|
sectionHeading: data.sectionHeading,
|
|
80
100
|
sectionTopic: data.sectionTopic,
|
|
81
101
|
sectionDescription: data.sectionDescription,
|
|
82
|
-
items
|
|
102
|
+
items,
|
|
83
103
|
containerWidth: data.containerWidth
|
|
84
104
|
}
|
|
85
105
|
);
|
|
86
106
|
},
|
|
87
107
|
CardsSection(data) {
|
|
108
|
+
var _a;
|
|
109
|
+
const cards = (_a = data.cards) == null ? void 0 : _a.map((c) => ({
|
|
110
|
+
...c,
|
|
111
|
+
media: makeMedia(c.media)
|
|
112
|
+
}));
|
|
88
113
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
89
114
|
footerDefaults.CardsSection,
|
|
90
115
|
{
|
|
@@ -92,7 +117,7 @@ const SECTION_REGISTRY = {
|
|
|
92
117
|
tagline: data.tagline,
|
|
93
118
|
sectionHeading: data.sectionHeading,
|
|
94
119
|
sectionDescription: data.sectionDescription,
|
|
95
|
-
cards
|
|
120
|
+
cards,
|
|
96
121
|
revealCards: data.revealCards,
|
|
97
122
|
valueCards: data.valueCards,
|
|
98
123
|
iconLinkCards: data.iconLinkCards,
|
package/dist/render.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.cjs","sources":["../src/ssr/renderPageSpec.tsx"],"sourcesContent":["/**\n * renderPageSpec — maps a typed PageSpec to real Clay React components and\n * returns self-contained static HTML + CSS.\n *\n * Node-safe (no import.meta.glob, no Vite-only APIs).\n * v1 is static-only (renderToStaticMarkup); no hydration.\n *\n * Naming skew resolved here (not in the public PageSpec contract):\n * IntegrationsSection → exported `Integrations` component\n * TrustSection layout=\"bento\" → TrustSection with layout=\"bento\"\n */\n\nimport type { ReactNode } from 'react'\nimport { Fragment } from 'react'\nimport { renderToStaticMarkup } from 'react-dom/server'\nimport { readFileSync } from 'node:fs'\nimport { join, dirname } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { createRequire } from 'node:module'\n\nimport {\n Button,\n CustomerLogo,\n CustomerLogoSection,\n HeaderSection,\n FeaturesSection,\n CardsSection,\n TestimonialsSection,\n FaqSection,\n BulletsSection,\n CtaSection,\n FooterSection,\n FOOTER_DEFAULTS,\n ContactSection,\n TrustSection,\n NumbersSection,\n Integrations,\n NavbarMenu,\n} from '../index'\n\nimport { logoSvg } from '../logos/resolve'\nimport { PageSpec, sectionSchemas, type SectionType } from '../page-spec/index'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\nconst require = createRequire(import.meta.url)\n\n// ── helpers ─────────────────────────────────────────────────────────────────\n\nfunction svgDataUrl(svg: string): string {\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`\n}\n\nfunction resolveLogoSrc(key: string): string | null {\n const svg = logoSvg(key)\n return svg ? svgDataUrl(svg) : null\n}\n\nconst BulletDefaultIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"10\" cy=\"10\" r=\"6\" fill=\"currentColor\" />\n </svg>\n)\n\nfunction makeCtas(ctas: { label: string; href: string }[] | undefined): ReactNode {\n if (!ctas?.length) return undefined\n return (\n <>\n {ctas.map((c, i) => (\n <a key={i} href={c.href} style={{ display: 'contents' }}>\n {/* Adapter sets semantics (first CTA = primary) only; color is Clay's to decide\n (Button defaults to the brand color). Never hard-code a color here. */}\n <Button buttonStyle={i === 0 ? 'primary' : 'secondary'} size=\"regular\">\n {c.label}\n </Button>\n </a>\n ))}\n </>\n )\n}\n\n// ── CSS loader (cached) ──────────────────────────────────────────────────────\n\nlet _css: string | null = null\n\nfunction loadCss(): string {\n if (_css) return _css\n const tokensCssPath = require.resolve('@clay-ds/tokens/css')\n const tokensCss = readFileSync(tokensCssPath, 'utf8')\n const componentCss = readFileSync(join(__dirname, 'index.css'), 'utf8')\n _css = tokensCss + '\\n' + componentCss\n return _css\n}\n\n// ── section registry ─────────────────────────────────────────────────────────\n\ntype SectionRenderers = {\n [K in SectionType]: (props: import('zod').infer<(typeof sectionSchemas)[K]>) => ReactNode\n}\n\nconst SECTION_REGISTRY: SectionRenderers = {\n HeaderSection(data) {\n const logos = data.logoKeys?.length ? (\n <>\n {data.logoKeys.map((key, i) => {\n const src = resolveLogoSrc(key)\n if (!src) return null\n const name = key.split('/').pop() ?? key\n return <CustomerLogo key={i} src={src} name={name} placement=\"web\" />\n })}\n </>\n ) : undefined\n return (\n <HeaderSection\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n actionCaption={data.actionCaption}\n actions={makeCtas(data.ctas)}\n logos={logos}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n CustomerLogoSection(data) {\n // Drop unresolved keys rather than emit a broken <img src=\"\">.\n const logos = data.logoKeys\n .map((key) => {\n const src = resolveLogoSrc(key)\n if (!src) return null\n return { name: key.split('/').pop() ?? key, srcBlack: src, srcColored: src }\n })\n .filter((l): l is { name: string; srcBlack: string; srcColored: string } => l !== null)\n return (\n <CustomerLogoSection\n heading={data.heading}\n logos={logos}\n colorMode={data.colorMode}\n />\n )\n },\n\n FeaturesSection(data) {\n return (\n <FeaturesSection\n layout={data.layout}\n sectionHeading={data.sectionHeading}\n sectionTopic={data.sectionTopic}\n sectionDescription={data.sectionDescription}\n items={data.items}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n CardsSection(data) {\n return (\n <CardsSection\n layout={data.layout}\n tagline={data.tagline}\n sectionHeading={data.sectionHeading}\n sectionDescription={data.sectionDescription}\n cards={data.cards}\n revealCards={data.revealCards}\n valueCards={data.valueCards}\n iconLinkCards={data.iconLinkCards}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n TestimonialsSection(data) {\n const cards = data.cards?.map((c) => ({\n quote: c.quote,\n authorName: c.authorName,\n authorRole: c.authorRole,\n stars: c.stars,\n stat: c.stat,\n statLabel: c.statLabel,\n ctaLabel: c.ctaLabel,\n ctaHref: c.ctaHref,\n logo: c.logoKey\n ? (() => {\n const src = resolveLogoSrc(c.logoKey)\n if (!src) return undefined\n return (\n <CustomerLogo\n src={src}\n name={c.logoKey.split('/').pop() ?? c.logoKey}\n placement=\"marketing\"\n />\n )\n })()\n : undefined,\n }))\n return (\n <TestimonialsSection\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n miniTitle={data.miniTitle}\n ctaLabel={data.ctaLabel}\n ctaHref={data.ctaHref}\n cards={cards}\n carouselCards={data.carouselCards}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n FaqSection(data) {\n return (\n <FaqSection\n layout={data.layout}\n heading={data.heading}\n items={data.items}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n BulletsSection(data) {\n const action = data.cta ? (\n <a href={data.cta.href} style={{ display: 'contents' }}>\n <Button buttonStyle=\"secondary\" size=\"regular\">\n {data.cta.label}\n </Button>\n </a>\n ) : undefined\n return (\n <BulletsSection\n layout={data.layout}\n miniTitle={data.miniTitle}\n heading={data.heading}\n description={data.description}\n columns={data.columns}\n items={data.items.map((item) => ({\n icon: <BulletDefaultIcon />,\n title: item.title,\n description: item.description,\n }))}\n action={action}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n CtaSection(data) {\n return (\n <CtaSection\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n actions={makeCtas(data.ctas)}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n FooterSection(data) {\n const logoSrcValue = data.logoKey ? resolveLogoSrc(data.logoKey) : undefined\n // FOOTER_DEFAULTS deliberately omits logo (consumers supply per-brand).\n // Only pass logo when we have a resolvable src — never an empty string,\n // which would render a broken <img> and trigger a React warning.\n const logo = logoSrcValue\n ? { src: logoSrcValue, alt: data.logoAlt ?? 'monday.com', href: '/' }\n : undefined\n return <FooterSection {...FOOTER_DEFAULTS} logo={logo} />\n },\n\n ContactSection(data) {\n const logos = data.logos\n ?.map((item) => {\n const src = resolveLogoSrc(item.key)\n return src ? { src, name: item.name } : null\n })\n .filter((l): l is { src: string; name: string } => l !== null)\n return (\n <ContactSection\n heading={data.heading}\n description={data.description}\n ratingValue={data.ratingValue}\n ratingLabel={data.ratingLabel}\n formTitle={data.formTitle}\n submitLabel={data.submitLabel}\n fields={data.fields}\n logos={logos}\n badges={data.badges}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n TrustSection(data) {\n return (\n <TrustSection\n layout={data.layout}\n heading={data.heading}\n ratingValue={data.ratingValue}\n ratingOut={data.ratingOut}\n ratingLabel={data.ratingLabel}\n badges={data.badges}\n ctaLabel={data.ctaLabel}\n ctaHref={data.ctaHref}\n topicLabel={data.topicLabel}\n securityTitle={data.securityTitle}\n securityDescription={data.securityDescription}\n securityLinkLabel={data.securityLinkLabel}\n securityLinkHref={data.securityLinkHref}\n complianceLogos={data.complianceLogos}\n statCards={data.statCards}\n />\n )\n },\n\n NumbersSection(data) {\n return (\n <NumbersSection\n layout={data.layout}\n heading={data.heading}\n items={data.items}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n IntegrationsSection(data) {\n // naming skew: IntegrationsSection (agent-facing) → Integrations (React export)\n const integrations = data.integrations\n ?.map((item) => {\n const src =\n resolveLogoSrc(item.key) ??\n resolveLogoSrc(`integrations/${item.name.toLowerCase()}`)\n return src ? { name: item.name, src } : null\n })\n .filter((i): i is { name: string; src: string } => i !== null)\n return (\n <Integrations\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n integrations={integrations}\n statValue={data.statValue}\n statLabel={data.statLabel}\n ctaLabel={data.ctaLabel}\n ctaHref={data.ctaHref}\n />\n )\n },\n}\n\n// ── public API ───────────────────────────────────────────────────────────────\n\nexport interface RenderResult {\n /** Complete self-contained HTML document */\n html: string\n /** Combined CSS (tokens + component styles) for reference */\n css: string\n}\n\n/**\n * Parse a PageSpec and render it to static HTML using real Clay React components.\n * Throws a ZodError on invalid input.\n */\nexport function renderPageSpec(input: unknown): RenderResult {\n const spec = PageSpec.parse(input)\n\n const sectionElements = spec.sections.map((section, i) => {\n const schema = sectionSchemas[section.type as SectionType]\n const props = schema.parse(section.props)\n const render = SECTION_REGISTRY[section.type as SectionType]\n return <Fragment key={i}>{render(props as never)}</Fragment>\n })\n\n const css = loadCss()\n\n const bodyHtml = renderToStaticMarkup(\n <>\n <NavbarMenu />\n {sectionElements}\n </>\n )\n\n const html = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<title>${spec.brand ?? 'Landing Page'}</title>\n<style>${css}</style>\n</head>\n<body>\n${bodyHtml}\n</body>\n</html>`\n\n return { html, css }\n}\n"],"names":["__dirname","dirname","fileURLToPath","require","createRequire","logoSvg","jsx","Fragment","Button","readFileSync","join","CustomerLogo","HeaderSection","CustomerLogoSection","FeaturesSection","CardsSection","TestimonialsSection","FaqSection","BulletsSection","CtaSection","FooterSection","FOOTER_DEFAULTS","ContactSection","TrustSection","NumbersSection","Integrations","PageSpec","sectionSchemas","renderToStaticMarkup","jsxs","NavbarMenu"],"mappings":";;;;;;;;;;;;;AA2CA,MAAMA,cAAYC,UAAAA,QAAQC,uBAAc,OAAA,aAAA,cAAA,QAAA,KAAA,EAAA,cAAA,UAAA,EAAA,OAAA,0BAAA,uBAAA,QAAA,YAAA,MAAA,YAAA,uBAAA,OAAA,IAAA,IAAA,cAAA,SAAA,OAAA,EAAA,IAAe,CAAC;AACxD,MAAMC,YAAUC,YAAAA,iQAA6B;AAI7C,SAAS,WAAW,KAAqB;AACvC,SAAO,oCAAoC,mBAAmB,GAAG,CAAC;AACpE;AAEA,SAAS,eAAe,KAA4B;AAClD,QAAM,MAAMC,cAAAA,QAAQ,GAAG;AACvB,SAAO,MAAM,WAAW,GAAG,IAAI;AACjC;AAEA,MAAM,oBAAoB,MACxBC,2BAAAA,IAAC,OAAA,EAAI,OAAM,MAAK,QAAO,MAAK,SAAQ,aAAY,MAAK,QAAO,eAAY,QACtE,UAAAA,2BAAAA,IAAC,UAAA,EAAO,IAAG,MAAK,IAAG,MAAK,GAAE,KAAI,MAAK,eAAA,CAAe,EAAA,CACpD;AAGF,SAAS,SAAS,MAAgE;AAChF,MAAI,EAAC,6BAAM,QAAQ,QAAO;AAC1B,SACEA,2BAAAA,IAAAC,WAAAA,UAAA,EACG,UAAA,KAAK,IAAI,CAAC,GAAG,MACZD,2BAAAA,IAAC,KAAA,EAAU,MAAM,EAAE,MAAM,OAAO,EAAE,SAAS,WAAA,GAGzC,UAAAA,2BAAAA,IAACE,eAAAA,QAAA,EAAO,aAAa,MAAM,IAAI,YAAY,aAAa,MAAK,WAC1D,UAAA,EAAE,MAAA,CACL,KALM,CAMR,CACD,GACH;AAEJ;AAIA,IAAI,OAAsB;AAE1B,SAAS,UAAkB;AACzB,MAAI,KAAM,QAAO;AACjB,QAAM,gBAAgBL,UAAQ,QAAQ,qBAAqB;AAC3D,QAAM,YAAYM,QAAAA,aAAa,eAAe,MAAM;AACpD,QAAM,eAAeA,QAAAA,aAAaC,UAAAA,KAAKV,aAAW,WAAW,GAAG,MAAM;AACtE,SAAO,YAAY,OAAO;AAC1B,SAAO;AACT;AAQA,MAAM,mBAAqC;AAAA,EACzC,cAAc,MAAM;;AAClB,UAAM,UAAQ,UAAK,aAAL,mBAAe,UAC3BM,2BAAAA,IAAAC,WAAAA,UAAA,EACG,eAAK,SAAS,IAAI,CAAC,KAAK,MAAM;AAC7B,YAAM,MAAM,eAAe,GAAG;AAC9B,UAAI,CAAC,IAAK,QAAO;AACjB,YAAM,OAAO,IAAI,MAAM,GAAG,EAAE,SAAS;AACrC,4CAAQI,eAAAA,cAAA,EAAqB,KAAU,MAAY,WAAU,SAAnC,CAAyC;AAAA,IACrE,CAAC,GACH,IACE;AACJ,WACEL,2BAAAA;AAAAA,MAACM,eAAAA;AAAAA,MAAA;AAAA,QACC,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK;AAAA,QACd,aAAa,KAAK;AAAA,QAClB,eAAe,KAAK;AAAA,QACpB,SAAS,SAAS,KAAK,IAAI;AAAA,QAC3B;AAAA,QACA,gBAAgB,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAG3B;AAAA,EAEA,oBAAoB,MAAM;AAExB,UAAM,QAAQ,KAAK,SAChB,IAAI,CAAC,QAAQ;AACZ,YAAM,MAAM,eAAe,GAAG;AAC9B,UAAI,CAAC,IAAK,QAAO;AACjB,aAAO,EAAE,MAAM,IAAI,MAAM,GAAG,EAAE,IAAA,KAAS,KAAK,UAAU,KAAK,YAAY,IAAA;AAAA,IACzE,CAAC,EACA,OAAO,CAAC,MAAmE,MAAM,IAAI;AACxF,WACEN,2BAAAA;AAAAA,MAACO,eAAAA;AAAAA,MAAA;AAAA,QACC,SAAS,KAAK;AAAA,QACd;AAAA,QACA,WAAW,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAGtB;AAAA,EAEA,gBAAgB,MAAM;AACpB,WACEP,2BAAAA;AAAAA,MAACQ,eAAAA;AAAAA,MAAA;AAAA,QACC,QAAQ,KAAK;AAAA,QACb,gBAAgB,KAAK;AAAA,QACrB,cAAc,KAAK;AAAA,QACnB,oBAAoB,KAAK;AAAA,QACzB,OAAO,KAAK;AAAA,QACZ,gBAAgB,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAG3B;AAAA,EAEA,aAAa,MAAM;AACjB,WACER,2BAAAA;AAAAA,MAACS,eAAAA;AAAAA,MAAA;AAAA,QACC,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK;AAAA,QACd,gBAAgB,KAAK;AAAA,QACrB,oBAAoB,KAAK;AAAA,QACzB,OAAO,KAAK;AAAA,QACZ,aAAa,KAAK;AAAA,QAClB,YAAY,KAAK;AAAA,QACjB,eAAe,KAAK;AAAA,QACpB,gBAAgB,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAG3B;AAAA,EAEA,oBAAoB,MAAM;;AACxB,UAAM,SAAQ,UAAK,UAAL,mBAAY,IAAI,CAAC,OAAO;AAAA,MACpC,OAAO,EAAE;AAAA,MACT,YAAY,EAAE;AAAA,MACd,YAAY,EAAE;AAAA,MACd,OAAO,EAAE;AAAA,MACT,MAAM,EAAE;AAAA,MACR,WAAW,EAAE;AAAA,MACb,UAAU,EAAE;AAAA,MACZ,SAAS,EAAE;AAAA,MACX,MAAM,EAAE,WACH,MAAM;AACL,cAAM,MAAM,eAAe,EAAE,OAAO;AACpC,YAAI,CAAC,IAAK,QAAO;AACjB,eACET,2BAAAA;AAAAA,UAACK,eAAAA;AAAAA,UAAA;AAAA,YACC;AAAA,YACA,MAAM,EAAE,QAAQ,MAAM,GAAG,EAAE,IAAA,KAAS,EAAE;AAAA,YACtC,WAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MAGhB,OACA;AAAA,IAAA;AAEN,WACEL,2BAAAA;AAAAA,MAACU,eAAAA;AAAAA,MAAA;AAAA,QACC,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK;AAAA,QACd,aAAa,KAAK;AAAA,QAClB,WAAW,KAAK;AAAA,QAChB,UAAU,KAAK;AAAA,QACf,SAAS,KAAK;AAAA,QACd;AAAA,QACA,eAAe,KAAK;AAAA,QACpB,gBAAgB,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAG3B;AAAA,EAEA,WAAW,MAAM;AACf,WACEV,2BAAAA;AAAAA,MAACW,eAAAA;AAAAA,MAAA;AAAA,QACC,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK;AAAA,QACd,OAAO,KAAK;AAAA,QACZ,gBAAgB,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAG3B;AAAA,EAEA,eAAe,MAAM;AACnB,UAAM,SAAS,KAAK,MAClBX,2BAAAA,IAAC,KAAA,EAAE,MAAM,KAAK,IAAI,MAAM,OAAO,EAAE,SAAS,cACxC,UAAAA,2BAAAA,IAACE,eAAAA,QAAA,EAAO,aAAY,aAAY,MAAK,WAClC,UAAA,KAAK,IAAI,MAAA,CACZ,EAAA,CACF,IACE;AACJ,WACEF,2BAAAA;AAAAA,MAACY,eAAAA;AAAAA,MAAA;AAAA,QACC,QAAQ,KAAK;AAAA,QACb,WAAW,KAAK;AAAA,QAChB,SAAS,KAAK;AAAA,QACd,aAAa,KAAK;AAAA,QAClB,SAAS,KAAK;AAAA,QACd,OAAO,KAAK,MAAM,IAAI,CAAC,UAAU;AAAA,UAC/B,qCAAO,mBAAA,EAAkB;AAAA,UACzB,OAAO,KAAK;AAAA,UACZ,aAAa,KAAK;AAAA,QAAA,EAClB;AAAA,QACF;AAAA,QACA,gBAAgB,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAG3B;AAAA,EAEA,WAAW,MAAM;AACf,WACEZ,2BAAAA;AAAAA,MAACa,eAAAA;AAAAA,MAAA;AAAA,QACC,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK;AAAA,QACd,aAAa,KAAK;AAAA,QAClB,SAAS,SAAS,KAAK,IAAI;AAAA,QAC3B,gBAAgB,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAG3B;AAAA,EAEA,cAAc,MAAM;AAClB,UAAM,eAAe,KAAK,UAAU,eAAe,KAAK,OAAO,IAAI;AAInE,UAAM,OAAO,eACT,EAAE,KAAK,cAAc,KAAK,KAAK,WAAW,cAAc,MAAM,IAAA,IAC9D;AACJ,WAAOb,2BAAAA,IAACc,eAAAA,eAAA,EAAe,GAAGC,eAAAA,iBAAiB,KAAA,CAAY;AAAA,EACzD;AAAA,EAEA,eAAe,MAAM;;AACnB,UAAM,SAAQ,UAAK,UAAL,mBACV,IAAI,CAAC,SAAS;AACd,YAAM,MAAM,eAAe,KAAK,GAAG;AACnC,aAAO,MAAM,EAAE,KAAK,MAAM,KAAK,SAAS;AAAA,IAC1C,GACC,OAAO,CAAC,MAA0C,MAAM;AAC3D,WACEf,2BAAAA;AAAAA,MAACgB,eAAAA;AAAAA,MAAA;AAAA,QACC,SAAS,KAAK;AAAA,QACd,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK;AAAA,QAClB,aAAa,KAAK;AAAA,QAClB,WAAW,KAAK;AAAA,QAChB,aAAa,KAAK;AAAA,QAClB,QAAQ,KAAK;AAAA,QACb;AAAA,QACA,QAAQ,KAAK;AAAA,QACb,gBAAgB,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAG3B;AAAA,EAEA,aAAa,MAAM;AACjB,WACEhB,2BAAAA;AAAAA,MAACiB,eAAAA;AAAAA,MAAA;AAAA,QACC,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK;AAAA,QACd,aAAa,KAAK;AAAA,QAClB,WAAW,KAAK;AAAA,QAChB,aAAa,KAAK;AAAA,QAClB,QAAQ,KAAK;AAAA,QACb,UAAU,KAAK;AAAA,QACf,SAAS,KAAK;AAAA,QACd,YAAY,KAAK;AAAA,QACjB,eAAe,KAAK;AAAA,QACpB,qBAAqB,KAAK;AAAA,QAC1B,mBAAmB,KAAK;AAAA,QACxB,kBAAkB,KAAK;AAAA,QACvB,iBAAiB,KAAK;AAAA,QACtB,WAAW,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAGtB;AAAA,EAEA,eAAe,MAAM;AACnB,WACEjB,2BAAAA;AAAAA,MAACkB,eAAAA;AAAAA,MAAA;AAAA,QACC,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK;AAAA,QACd,OAAO,KAAK;AAAA,QACZ,gBAAgB,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAG3B;AAAA,EAEA,oBAAoB,MAAM;;AAExB,UAAM,gBAAe,UAAK,iBAAL,mBACjB,IAAI,CAAC,SAAS;AACd,YAAM,MACJ,eAAe,KAAK,GAAG,KACvB,eAAe,gBAAgB,KAAK,KAAK,YAAA,CAAa,EAAE;AAC1D,aAAO,MAAM,EAAE,MAAM,KAAK,MAAM,QAAQ;AAAA,IAC1C,GACC,OAAO,CAAC,MAA0C,MAAM;AAC3D,WACElB,2BAAAA;AAAAA,MAACmB,eAAAA;AAAAA,MAAA;AAAA,QACC,QAAQ,KAAK;AAAA,QACb,SAAS,KAAK;AAAA,QACd,aAAa,KAAK;AAAA,QAClB;AAAA,QACA,WAAW,KAAK;AAAA,QAChB,WAAW,KAAK;AAAA,QAChB,UAAU,KAAK;AAAA,QACf,SAAS,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EAGpB;AACF;AAeO,SAAS,eAAe,OAA8B;AAC3D,QAAM,OAAOC,SAAAA,SAAS,MAAM,KAAK;AAEjC,QAAM,kBAAkB,KAAK,SAAS,IAAI,CAAC,SAAS,MAAM;AACxD,UAAM,SAASC,SAAAA,eAAe,QAAQ,IAAmB;AACzD,UAAM,QAAQ,OAAO,MAAM,QAAQ,KAAK;AACxC,UAAM,SAAS,iBAAiB,QAAQ,IAAmB;AAC3D,0CAAQpB,MAAAA,UAAA,EAAkB,UAAA,OAAO,KAAc,KAAzB,CAA2B;AAAA,EACnD,CAAC;AAED,QAAM,MAAM,QAAA;AAEZ,QAAM,WAAWqB,OAAAA;AAAAA,IACfC,gCAAAtB,WAAAA,UAAA,EACE,UAAA;AAAA,MAAAD,2BAAAA,IAACwB,eAAAA,YAAA,EAAW;AAAA,MACX;AAAA,IAAA,EAAA,CACH;AAAA,EAAA;AAGF,QAAM,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,SAKN,KAAK,SAAS,cAAc;AAAA,SAC5B,GAAG;AAAA;AAAA;AAAA,EAGV,QAAQ;AAAA;AAAA;AAIR,SAAO,EAAE,MAAM,IAAA;AACjB;;"}
|
|
1
|
+
{"version":3,"file":"render.cjs","sources":["../src/ssr/renderPageSpec.tsx"],"sourcesContent":["/**\n * renderPageSpec — maps a typed PageSpec to real Clay React components and\n * returns self-contained static HTML + CSS.\n *\n * Node-safe (no import.meta.glob, no Vite-only APIs).\n * v1 is static-only (renderToStaticMarkup); no hydration.\n *\n * Naming skew resolved here (not in the public PageSpec contract):\n * IntegrationsSection → exported `Integrations` component\n * TrustSection layout=\"bento\" → TrustSection with layout=\"bento\"\n */\n\nimport type { ReactNode } from 'react'\nimport { Fragment } from 'react'\nimport { renderToStaticMarkup } from 'react-dom/server'\nimport { readFileSync } from 'node:fs'\nimport { join, dirname } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { createRequire } from 'node:module'\n\nimport {\n Button,\n CustomerLogo,\n CustomerLogoSection,\n HeaderSection,\n FeaturesSection,\n CardsSection,\n TestimonialsSection,\n FaqSection,\n BulletsSection,\n CtaSection,\n FooterSection,\n FOOTER_DEFAULTS,\n ContactSection,\n TrustSection,\n NumbersSection,\n Integrations,\n NavbarMenu,\n MediaSlot,\n} from '../index'\n\nimport { logoSvg } from '../logos/resolve'\nimport { PageSpec, sectionSchemas, type SectionType } from '../page-spec/index'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\nconst require = createRequire(import.meta.url)\n\n// ── helpers ─────────────────────────────────────────────────────────────────\n\nfunction svgDataUrl(svg: string): string {\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`\n}\n\nfunction resolveLogoSrc(key: string): string | null {\n const svg = logoSvg(key)\n return svg ? svgDataUrl(svg) : null\n}\n\nconst BulletDefaultIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"10\" cy=\"10\" r=\"6\" fill=\"currentColor\" />\n </svg>\n)\n\nfunction makeCtas(ctas: { label: string; href: string }[] | undefined): ReactNode {\n if (!ctas?.length) return undefined\n return (\n <>\n {ctas.map((c, i) => (\n <a key={i} href={c.href} style={{ display: 'contents' }}>\n {/* Adapter sets semantics (first CTA = primary) only; color is Clay's to decide\n (Button defaults to the brand color). Never hard-code a color here. */}\n <Button buttonStyle={i === 0 ? 'primary' : 'secondary'} size=\"regular\">\n {c.label}\n </Button>\n </a>\n ))}\n </>\n )\n}\n\nfunction makeMedia(\n m:\n | {\n src: string\n type?: 'image' | 'video'\n alt?: string\n fit?: 'contain' | 'cover' | 'fill'\n aspectRatio?: string\n }\n | undefined\n): ReactNode {\n if (!m?.src) return undefined\n const isVideo = m.type === 'video'\n return (\n <MediaSlot\n type={isVideo ? 'video' : 'image'}\n src={m.src}\n alt={m.alt}\n fit={m.fit}\n aspectRatio={m.aspectRatio}\n {...(isVideo ? { autoPlay: true, loop: true } : {})}\n />\n )\n}\n\n// ── CSS loader (cached) ──────────────────────────────────────────────────────\n\nlet _css: string | null = null\n\nfunction loadCss(): string {\n if (_css) return _css\n const tokensCssPath = require.resolve('@clay-ds/tokens/css')\n const tokensCss = readFileSync(tokensCssPath, 'utf8')\n const componentCss = readFileSync(join(__dirname, 'index.css'), 'utf8')\n _css = tokensCss + '\\n' + componentCss\n return _css\n}\n\n// ── section registry ─────────────────────────────────────────────────────────\n\ntype SectionRenderers = {\n [K in SectionType]: (props: import('zod').infer<(typeof sectionSchemas)[K]>) => ReactNode\n}\n\nconst SECTION_REGISTRY: SectionRenderers = {\n HeaderSection(data) {\n const logos = data.logoKeys?.length ? (\n <>\n {data.logoKeys.map((key, i) => {\n const src = resolveLogoSrc(key)\n if (!src) return null\n const name = key.split('/').pop() ?? key\n return <CustomerLogo key={i} src={src} name={name} placement=\"web\" />\n })}\n </>\n ) : undefined\n return (\n <HeaderSection\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n actionCaption={data.actionCaption}\n actions={makeCtas(data.ctas)}\n logos={logos}\n media={makeMedia(data.media)}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n CustomerLogoSection(data) {\n // Drop unresolved keys rather than emit a broken <img src=\"\">.\n const logos = data.logoKeys\n .map((key) => {\n const src = resolveLogoSrc(key)\n if (!src) return null\n return { name: key.split('/').pop() ?? key, srcBlack: src, srcColored: src }\n })\n .filter((l): l is { name: string; srcBlack: string; srcColored: string } => l !== null)\n return (\n <CustomerLogoSection\n heading={data.heading}\n logos={logos}\n colorMode={data.colorMode}\n />\n )\n },\n\n FeaturesSection(data) {\n const items = data.items.map((it) => ({\n ...it,\n media: makeMedia(it.media),\n }))\n return (\n <FeaturesSection\n layout={data.layout}\n sectionHeading={data.sectionHeading}\n sectionTopic={data.sectionTopic}\n sectionDescription={data.sectionDescription}\n items={items}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n CardsSection(data) {\n const cards = data.cards?.map((c) => ({\n ...c,\n media: makeMedia(c.media),\n }))\n return (\n <CardsSection\n layout={data.layout}\n tagline={data.tagline}\n sectionHeading={data.sectionHeading}\n sectionDescription={data.sectionDescription}\n cards={cards}\n revealCards={data.revealCards}\n valueCards={data.valueCards}\n iconLinkCards={data.iconLinkCards}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n TestimonialsSection(data) {\n const cards = data.cards?.map((c) => ({\n quote: c.quote,\n authorName: c.authorName,\n authorRole: c.authorRole,\n stars: c.stars,\n stat: c.stat,\n statLabel: c.statLabel,\n ctaLabel: c.ctaLabel,\n ctaHref: c.ctaHref,\n logo: c.logoKey\n ? (() => {\n const src = resolveLogoSrc(c.logoKey)\n if (!src) return undefined\n return (\n <CustomerLogo\n src={src}\n name={c.logoKey.split('/').pop() ?? c.logoKey}\n placement=\"marketing\"\n />\n )\n })()\n : undefined,\n }))\n return (\n <TestimonialsSection\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n miniTitle={data.miniTitle}\n ctaLabel={data.ctaLabel}\n ctaHref={data.ctaHref}\n cards={cards}\n carouselCards={data.carouselCards}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n FaqSection(data) {\n return (\n <FaqSection\n layout={data.layout}\n heading={data.heading}\n items={data.items}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n BulletsSection(data) {\n const action = data.cta ? (\n <a href={data.cta.href} style={{ display: 'contents' }}>\n <Button buttonStyle=\"secondary\" size=\"regular\">\n {data.cta.label}\n </Button>\n </a>\n ) : undefined\n return (\n <BulletsSection\n layout={data.layout}\n miniTitle={data.miniTitle}\n heading={data.heading}\n description={data.description}\n columns={data.columns}\n items={data.items.map((item) => ({\n icon: <BulletDefaultIcon />,\n title: item.title,\n description: item.description,\n }))}\n action={action}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n CtaSection(data) {\n return (\n <CtaSection\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n actions={makeCtas(data.ctas)}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n FooterSection(data) {\n const logoSrcValue = data.logoKey ? resolveLogoSrc(data.logoKey) : undefined\n // FOOTER_DEFAULTS deliberately omits logo (consumers supply per-brand).\n // Only pass logo when we have a resolvable src — never an empty string,\n // which would render a broken <img> and trigger a React warning.\n const logo = logoSrcValue\n ? { src: logoSrcValue, alt: data.logoAlt ?? 'monday.com', href: '/' }\n : undefined\n return <FooterSection {...FOOTER_DEFAULTS} logo={logo} />\n },\n\n ContactSection(data) {\n const logos = data.logos\n ?.map((item) => {\n const src = resolveLogoSrc(item.key)\n return src ? { src, name: item.name } : null\n })\n .filter((l): l is { src: string; name: string } => l !== null)\n return (\n <ContactSection\n heading={data.heading}\n description={data.description}\n ratingValue={data.ratingValue}\n ratingLabel={data.ratingLabel}\n formTitle={data.formTitle}\n submitLabel={data.submitLabel}\n fields={data.fields}\n logos={logos}\n badges={data.badges}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n TrustSection(data) {\n return (\n <TrustSection\n layout={data.layout}\n heading={data.heading}\n ratingValue={data.ratingValue}\n ratingOut={data.ratingOut}\n ratingLabel={data.ratingLabel}\n badges={data.badges}\n ctaLabel={data.ctaLabel}\n ctaHref={data.ctaHref}\n topicLabel={data.topicLabel}\n securityTitle={data.securityTitle}\n securityDescription={data.securityDescription}\n securityLinkLabel={data.securityLinkLabel}\n securityLinkHref={data.securityLinkHref}\n complianceLogos={data.complianceLogos}\n statCards={data.statCards}\n />\n )\n },\n\n NumbersSection(data) {\n return (\n <NumbersSection\n layout={data.layout}\n heading={data.heading}\n items={data.items}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n IntegrationsSection(data) {\n // naming skew: IntegrationsSection (agent-facing) → Integrations (React export)\n const integrations = data.integrations\n ?.map((item) => {\n const src =\n resolveLogoSrc(item.key) ??\n resolveLogoSrc(`integrations/${item.name.toLowerCase()}`)\n return src ? { name: item.name, src } : null\n })\n .filter((i): i is { name: string; src: string } => i !== null)\n return (\n <Integrations\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n integrations={integrations}\n statValue={data.statValue}\n statLabel={data.statLabel}\n ctaLabel={data.ctaLabel}\n ctaHref={data.ctaHref}\n />\n )\n },\n}\n\n// ── public API ───────────────────────────────────────────────────────────────\n\nexport interface RenderResult {\n /** Complete self-contained HTML document */\n html: string\n /** Combined CSS (tokens + component styles) for reference */\n css: string\n}\n\n/**\n * Parse a PageSpec and render it to static HTML using real Clay React components.\n * Throws a ZodError on invalid input.\n */\nexport function renderPageSpec(input: unknown): RenderResult {\n const spec = PageSpec.parse(input)\n\n const sectionElements = spec.sections.map((section, i) => {\n const schema = sectionSchemas[section.type as SectionType]\n const props = schema.parse(section.props)\n const render = SECTION_REGISTRY[section.type as SectionType]\n return <Fragment key={i}>{render(props as never)}</Fragment>\n })\n\n const css = loadCss()\n\n const bodyHtml = renderToStaticMarkup(\n <>\n <NavbarMenu />\n {sectionElements}\n </>\n )\n\n const html = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<title>${spec.brand ?? 'Landing Page'}</title>\n<style>${css}</style>\n</head>\n<body>\n${bodyHtml}\n</body>\n</html>`\n\n return { html, css }\n}\n"],"names":["__dirname","dirname","fileURLToPath","require","createRequire","logoSvg","jsx","Fragment","Button","MediaSlot","readFileSync","join","CustomerLogo","HeaderSection","CustomerLogoSection","FeaturesSection","CardsSection","TestimonialsSection","FaqSection","BulletsSection","CtaSection","FooterSection","FOOTER_DEFAULTS","ContactSection","TrustSection","NumbersSection","Integrations","PageSpec","sectionSchemas","renderToStaticMarkup","jsxs","NavbarMenu"],"mappings":"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"}
|
package/dist/render.js
CHANGED
|
@@ -7,7 +7,7 @@ import { fileURLToPath } from "node:url";
|
|
|
7
7
|
import { createRequire } from "node:module";
|
|
8
8
|
import { logoSvg } from "./logos/resolve.js";
|
|
9
9
|
import { PageSpec, sectionSchemas } from "./page-spec.js";
|
|
10
|
-
import { N as NavbarMenu, l as Integrations, m as NumbersSection, v as TrustSection, b as ContactSection, j as FooterSection, g as FOOTER_DEFAULTS, d as CtaSection, a as Button, B as BulletsSection, h as FaqSection, e as CustomerLogo, s as TestimonialsSection, C as CardsSection, i as FeaturesSection, f as CustomerLogoSection, H as HeaderSection } from "./footerDefaults-
|
|
10
|
+
import { N as NavbarMenu, l as Integrations, m as NumbersSection, v as TrustSection, b as ContactSection, j as FooterSection, g as FOOTER_DEFAULTS, d as CtaSection, a as Button, B as BulletsSection, h as FaqSection, e as CustomerLogo, s as TestimonialsSection, C as CardsSection, i as FeaturesSection, f as CustomerLogoSection, H as HeaderSection, M as MediaSlot } from "./footerDefaults-Dx94Jc_F.js";
|
|
11
11
|
const __dirname$1 = dirname(fileURLToPath(import.meta.url));
|
|
12
12
|
const require$1 = createRequire(import.meta.url);
|
|
13
13
|
function svgDataUrl(svg) {
|
|
@@ -22,6 +22,21 @@ function makeCtas(ctas) {
|
|
|
22
22
|
if (!(ctas == null ? void 0 : ctas.length)) return void 0;
|
|
23
23
|
return /* @__PURE__ */ jsx(Fragment$1, { children: ctas.map((c, i) => /* @__PURE__ */ jsx("a", { href: c.href, style: { display: "contents" }, children: /* @__PURE__ */ jsx(Button, { buttonStyle: i === 0 ? "primary" : "secondary", size: "regular", children: c.label }) }, i)) });
|
|
24
24
|
}
|
|
25
|
+
function makeMedia(m) {
|
|
26
|
+
if (!(m == null ? void 0 : m.src)) return void 0;
|
|
27
|
+
const isVideo = m.type === "video";
|
|
28
|
+
return /* @__PURE__ */ jsx(
|
|
29
|
+
MediaSlot,
|
|
30
|
+
{
|
|
31
|
+
type: isVideo ? "video" : "image",
|
|
32
|
+
src: m.src,
|
|
33
|
+
alt: m.alt,
|
|
34
|
+
fit: m.fit,
|
|
35
|
+
aspectRatio: m.aspectRatio,
|
|
36
|
+
...isVideo ? { autoPlay: true, loop: true } : {}
|
|
37
|
+
}
|
|
38
|
+
);
|
|
39
|
+
}
|
|
25
40
|
let _css = null;
|
|
26
41
|
function loadCss() {
|
|
27
42
|
if (_css) return _css;
|
|
@@ -49,6 +64,7 @@ const SECTION_REGISTRY = {
|
|
|
49
64
|
actionCaption: data.actionCaption,
|
|
50
65
|
actions: makeCtas(data.ctas),
|
|
51
66
|
logos,
|
|
67
|
+
media: makeMedia(data.media),
|
|
52
68
|
containerWidth: data.containerWidth
|
|
53
69
|
}
|
|
54
70
|
);
|
|
@@ -69,6 +85,10 @@ const SECTION_REGISTRY = {
|
|
|
69
85
|
);
|
|
70
86
|
},
|
|
71
87
|
FeaturesSection(data) {
|
|
88
|
+
const items = data.items.map((it) => ({
|
|
89
|
+
...it,
|
|
90
|
+
media: makeMedia(it.media)
|
|
91
|
+
}));
|
|
72
92
|
return /* @__PURE__ */ jsx(
|
|
73
93
|
FeaturesSection,
|
|
74
94
|
{
|
|
@@ -76,12 +96,17 @@ const SECTION_REGISTRY = {
|
|
|
76
96
|
sectionHeading: data.sectionHeading,
|
|
77
97
|
sectionTopic: data.sectionTopic,
|
|
78
98
|
sectionDescription: data.sectionDescription,
|
|
79
|
-
items
|
|
99
|
+
items,
|
|
80
100
|
containerWidth: data.containerWidth
|
|
81
101
|
}
|
|
82
102
|
);
|
|
83
103
|
},
|
|
84
104
|
CardsSection(data) {
|
|
105
|
+
var _a;
|
|
106
|
+
const cards = (_a = data.cards) == null ? void 0 : _a.map((c) => ({
|
|
107
|
+
...c,
|
|
108
|
+
media: makeMedia(c.media)
|
|
109
|
+
}));
|
|
85
110
|
return /* @__PURE__ */ jsx(
|
|
86
111
|
CardsSection,
|
|
87
112
|
{
|
|
@@ -89,7 +114,7 @@ const SECTION_REGISTRY = {
|
|
|
89
114
|
tagline: data.tagline,
|
|
90
115
|
sectionHeading: data.sectionHeading,
|
|
91
116
|
sectionDescription: data.sectionDescription,
|
|
92
|
-
cards
|
|
117
|
+
cards,
|
|
93
118
|
revealCards: data.revealCards,
|
|
94
119
|
valueCards: data.valueCards,
|
|
95
120
|
iconLinkCards: data.iconLinkCards,
|
package/dist/render.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sources":["../src/ssr/renderPageSpec.tsx"],"sourcesContent":["/**\n * renderPageSpec — maps a typed PageSpec to real Clay React components and\n * returns self-contained static HTML + CSS.\n *\n * Node-safe (no import.meta.glob, no Vite-only APIs).\n * v1 is static-only (renderToStaticMarkup); no hydration.\n *\n * Naming skew resolved here (not in the public PageSpec contract):\n * IntegrationsSection → exported `Integrations` component\n * TrustSection layout=\"bento\" → TrustSection with layout=\"bento\"\n */\n\nimport type { ReactNode } from 'react'\nimport { Fragment } from 'react'\nimport { renderToStaticMarkup } from 'react-dom/server'\nimport { readFileSync } from 'node:fs'\nimport { join, dirname } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { createRequire } from 'node:module'\n\nimport {\n Button,\n CustomerLogo,\n CustomerLogoSection,\n HeaderSection,\n FeaturesSection,\n CardsSection,\n TestimonialsSection,\n FaqSection,\n BulletsSection,\n CtaSection,\n FooterSection,\n FOOTER_DEFAULTS,\n ContactSection,\n TrustSection,\n NumbersSection,\n Integrations,\n NavbarMenu,\n} from '../index'\n\nimport { logoSvg } from '../logos/resolve'\nimport { PageSpec, sectionSchemas, type SectionType } from '../page-spec/index'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\nconst require = createRequire(import.meta.url)\n\n// ── helpers ─────────────────────────────────────────────────────────────────\n\nfunction svgDataUrl(svg: string): string {\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`\n}\n\nfunction resolveLogoSrc(key: string): string | null {\n const svg = logoSvg(key)\n return svg ? svgDataUrl(svg) : null\n}\n\nconst BulletDefaultIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"10\" cy=\"10\" r=\"6\" fill=\"currentColor\" />\n </svg>\n)\n\nfunction makeCtas(ctas: { label: string; href: string }[] | undefined): ReactNode {\n if (!ctas?.length) return undefined\n return (\n <>\n {ctas.map((c, i) => (\n <a key={i} href={c.href} style={{ display: 'contents' }}>\n {/* Adapter sets semantics (first CTA = primary) only; color is Clay's to decide\n (Button defaults to the brand color). Never hard-code a color here. */}\n <Button buttonStyle={i === 0 ? 'primary' : 'secondary'} size=\"regular\">\n {c.label}\n </Button>\n </a>\n ))}\n </>\n )\n}\n\n// ── CSS loader (cached) ──────────────────────────────────────────────────────\n\nlet _css: string | null = null\n\nfunction loadCss(): string {\n if (_css) return _css\n const tokensCssPath = require.resolve('@clay-ds/tokens/css')\n const tokensCss = readFileSync(tokensCssPath, 'utf8')\n const componentCss = readFileSync(join(__dirname, 'index.css'), 'utf8')\n _css = tokensCss + '\\n' + componentCss\n return _css\n}\n\n// ── section registry ─────────────────────────────────────────────────────────\n\ntype SectionRenderers = {\n [K in SectionType]: (props: import('zod').infer<(typeof sectionSchemas)[K]>) => ReactNode\n}\n\nconst SECTION_REGISTRY: SectionRenderers = {\n HeaderSection(data) {\n const logos = data.logoKeys?.length ? (\n <>\n {data.logoKeys.map((key, i) => {\n const src = resolveLogoSrc(key)\n if (!src) return null\n const name = key.split('/').pop() ?? key\n return <CustomerLogo key={i} src={src} name={name} placement=\"web\" />\n })}\n </>\n ) : undefined\n return (\n <HeaderSection\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n actionCaption={data.actionCaption}\n actions={makeCtas(data.ctas)}\n logos={logos}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n CustomerLogoSection(data) {\n // Drop unresolved keys rather than emit a broken <img src=\"\">.\n const logos = data.logoKeys\n .map((key) => {\n const src = resolveLogoSrc(key)\n if (!src) return null\n return { name: key.split('/').pop() ?? key, srcBlack: src, srcColored: src }\n })\n .filter((l): l is { name: string; srcBlack: string; srcColored: string } => l !== null)\n return (\n <CustomerLogoSection\n heading={data.heading}\n logos={logos}\n colorMode={data.colorMode}\n />\n )\n },\n\n FeaturesSection(data) {\n return (\n <FeaturesSection\n layout={data.layout}\n sectionHeading={data.sectionHeading}\n sectionTopic={data.sectionTopic}\n sectionDescription={data.sectionDescription}\n items={data.items}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n CardsSection(data) {\n return (\n <CardsSection\n layout={data.layout}\n tagline={data.tagline}\n sectionHeading={data.sectionHeading}\n sectionDescription={data.sectionDescription}\n cards={data.cards}\n revealCards={data.revealCards}\n valueCards={data.valueCards}\n iconLinkCards={data.iconLinkCards}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n TestimonialsSection(data) {\n const cards = data.cards?.map((c) => ({\n quote: c.quote,\n authorName: c.authorName,\n authorRole: c.authorRole,\n stars: c.stars,\n stat: c.stat,\n statLabel: c.statLabel,\n ctaLabel: c.ctaLabel,\n ctaHref: c.ctaHref,\n logo: c.logoKey\n ? (() => {\n const src = resolveLogoSrc(c.logoKey)\n if (!src) return undefined\n return (\n <CustomerLogo\n src={src}\n name={c.logoKey.split('/').pop() ?? c.logoKey}\n placement=\"marketing\"\n />\n )\n })()\n : undefined,\n }))\n return (\n <TestimonialsSection\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n miniTitle={data.miniTitle}\n ctaLabel={data.ctaLabel}\n ctaHref={data.ctaHref}\n cards={cards}\n carouselCards={data.carouselCards}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n FaqSection(data) {\n return (\n <FaqSection\n layout={data.layout}\n heading={data.heading}\n items={data.items}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n BulletsSection(data) {\n const action = data.cta ? (\n <a href={data.cta.href} style={{ display: 'contents' }}>\n <Button buttonStyle=\"secondary\" size=\"regular\">\n {data.cta.label}\n </Button>\n </a>\n ) : undefined\n return (\n <BulletsSection\n layout={data.layout}\n miniTitle={data.miniTitle}\n heading={data.heading}\n description={data.description}\n columns={data.columns}\n items={data.items.map((item) => ({\n icon: <BulletDefaultIcon />,\n title: item.title,\n description: item.description,\n }))}\n action={action}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n CtaSection(data) {\n return (\n <CtaSection\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n actions={makeCtas(data.ctas)}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n FooterSection(data) {\n const logoSrcValue = data.logoKey ? resolveLogoSrc(data.logoKey) : undefined\n // FOOTER_DEFAULTS deliberately omits logo (consumers supply per-brand).\n // Only pass logo when we have a resolvable src — never an empty string,\n // which would render a broken <img> and trigger a React warning.\n const logo = logoSrcValue\n ? { src: logoSrcValue, alt: data.logoAlt ?? 'monday.com', href: '/' }\n : undefined\n return <FooterSection {...FOOTER_DEFAULTS} logo={logo} />\n },\n\n ContactSection(data) {\n const logos = data.logos\n ?.map((item) => {\n const src = resolveLogoSrc(item.key)\n return src ? { src, name: item.name } : null\n })\n .filter((l): l is { src: string; name: string } => l !== null)\n return (\n <ContactSection\n heading={data.heading}\n description={data.description}\n ratingValue={data.ratingValue}\n ratingLabel={data.ratingLabel}\n formTitle={data.formTitle}\n submitLabel={data.submitLabel}\n fields={data.fields}\n logos={logos}\n badges={data.badges}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n TrustSection(data) {\n return (\n <TrustSection\n layout={data.layout}\n heading={data.heading}\n ratingValue={data.ratingValue}\n ratingOut={data.ratingOut}\n ratingLabel={data.ratingLabel}\n badges={data.badges}\n ctaLabel={data.ctaLabel}\n ctaHref={data.ctaHref}\n topicLabel={data.topicLabel}\n securityTitle={data.securityTitle}\n securityDescription={data.securityDescription}\n securityLinkLabel={data.securityLinkLabel}\n securityLinkHref={data.securityLinkHref}\n complianceLogos={data.complianceLogos}\n statCards={data.statCards}\n />\n )\n },\n\n NumbersSection(data) {\n return (\n <NumbersSection\n layout={data.layout}\n heading={data.heading}\n items={data.items}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n IntegrationsSection(data) {\n // naming skew: IntegrationsSection (agent-facing) → Integrations (React export)\n const integrations = data.integrations\n ?.map((item) => {\n const src =\n resolveLogoSrc(item.key) ??\n resolveLogoSrc(`integrations/${item.name.toLowerCase()}`)\n return src ? { name: item.name, src } : null\n })\n .filter((i): i is { name: string; src: string } => i !== null)\n return (\n <Integrations\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n integrations={integrations}\n statValue={data.statValue}\n statLabel={data.statLabel}\n ctaLabel={data.ctaLabel}\n ctaHref={data.ctaHref}\n />\n )\n },\n}\n\n// ── public API ───────────────────────────────────────────────────────────────\n\nexport interface RenderResult {\n /** Complete self-contained HTML document */\n html: string\n /** Combined CSS (tokens + component styles) for reference */\n css: string\n}\n\n/**\n * Parse a PageSpec and render it to static HTML using real Clay React components.\n * Throws a ZodError on invalid input.\n */\nexport function renderPageSpec(input: unknown): RenderResult {\n const spec = PageSpec.parse(input)\n\n const sectionElements = spec.sections.map((section, i) => {\n const schema = sectionSchemas[section.type as SectionType]\n const props = schema.parse(section.props)\n const render = SECTION_REGISTRY[section.type as SectionType]\n return <Fragment key={i}>{render(props as never)}</Fragment>\n })\n\n const css = loadCss()\n\n const bodyHtml = renderToStaticMarkup(\n <>\n <NavbarMenu />\n {sectionElements}\n </>\n )\n\n const html = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<title>${spec.brand ?? 'Landing Page'}</title>\n<style>${css}</style>\n</head>\n<body>\n${bodyHtml}\n</body>\n</html>`\n\n return { html, css }\n}\n"],"names":["__dirname","require","Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"render.js","sources":["../src/ssr/renderPageSpec.tsx"],"sourcesContent":["/**\n * renderPageSpec — maps a typed PageSpec to real Clay React components and\n * returns self-contained static HTML + CSS.\n *\n * Node-safe (no import.meta.glob, no Vite-only APIs).\n * v1 is static-only (renderToStaticMarkup); no hydration.\n *\n * Naming skew resolved here (not in the public PageSpec contract):\n * IntegrationsSection → exported `Integrations` component\n * TrustSection layout=\"bento\" → TrustSection with layout=\"bento\"\n */\n\nimport type { ReactNode } from 'react'\nimport { Fragment } from 'react'\nimport { renderToStaticMarkup } from 'react-dom/server'\nimport { readFileSync } from 'node:fs'\nimport { join, dirname } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { createRequire } from 'node:module'\n\nimport {\n Button,\n CustomerLogo,\n CustomerLogoSection,\n HeaderSection,\n FeaturesSection,\n CardsSection,\n TestimonialsSection,\n FaqSection,\n BulletsSection,\n CtaSection,\n FooterSection,\n FOOTER_DEFAULTS,\n ContactSection,\n TrustSection,\n NumbersSection,\n Integrations,\n NavbarMenu,\n MediaSlot,\n} from '../index'\n\nimport { logoSvg } from '../logos/resolve'\nimport { PageSpec, sectionSchemas, type SectionType } from '../page-spec/index'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\nconst require = createRequire(import.meta.url)\n\n// ── helpers ─────────────────────────────────────────────────────────────────\n\nfunction svgDataUrl(svg: string): string {\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svg)}`\n}\n\nfunction resolveLogoSrc(key: string): string | null {\n const svg = logoSvg(key)\n return svg ? svgDataUrl(svg) : null\n}\n\nconst BulletDefaultIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\" aria-hidden=\"true\">\n <circle cx=\"10\" cy=\"10\" r=\"6\" fill=\"currentColor\" />\n </svg>\n)\n\nfunction makeCtas(ctas: { label: string; href: string }[] | undefined): ReactNode {\n if (!ctas?.length) return undefined\n return (\n <>\n {ctas.map((c, i) => (\n <a key={i} href={c.href} style={{ display: 'contents' }}>\n {/* Adapter sets semantics (first CTA = primary) only; color is Clay's to decide\n (Button defaults to the brand color). Never hard-code a color here. */}\n <Button buttonStyle={i === 0 ? 'primary' : 'secondary'} size=\"regular\">\n {c.label}\n </Button>\n </a>\n ))}\n </>\n )\n}\n\nfunction makeMedia(\n m:\n | {\n src: string\n type?: 'image' | 'video'\n alt?: string\n fit?: 'contain' | 'cover' | 'fill'\n aspectRatio?: string\n }\n | undefined\n): ReactNode {\n if (!m?.src) return undefined\n const isVideo = m.type === 'video'\n return (\n <MediaSlot\n type={isVideo ? 'video' : 'image'}\n src={m.src}\n alt={m.alt}\n fit={m.fit}\n aspectRatio={m.aspectRatio}\n {...(isVideo ? { autoPlay: true, loop: true } : {})}\n />\n )\n}\n\n// ── CSS loader (cached) ──────────────────────────────────────────────────────\n\nlet _css: string | null = null\n\nfunction loadCss(): string {\n if (_css) return _css\n const tokensCssPath = require.resolve('@clay-ds/tokens/css')\n const tokensCss = readFileSync(tokensCssPath, 'utf8')\n const componentCss = readFileSync(join(__dirname, 'index.css'), 'utf8')\n _css = tokensCss + '\\n' + componentCss\n return _css\n}\n\n// ── section registry ─────────────────────────────────────────────────────────\n\ntype SectionRenderers = {\n [K in SectionType]: (props: import('zod').infer<(typeof sectionSchemas)[K]>) => ReactNode\n}\n\nconst SECTION_REGISTRY: SectionRenderers = {\n HeaderSection(data) {\n const logos = data.logoKeys?.length ? (\n <>\n {data.logoKeys.map((key, i) => {\n const src = resolveLogoSrc(key)\n if (!src) return null\n const name = key.split('/').pop() ?? key\n return <CustomerLogo key={i} src={src} name={name} placement=\"web\" />\n })}\n </>\n ) : undefined\n return (\n <HeaderSection\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n actionCaption={data.actionCaption}\n actions={makeCtas(data.ctas)}\n logos={logos}\n media={makeMedia(data.media)}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n CustomerLogoSection(data) {\n // Drop unresolved keys rather than emit a broken <img src=\"\">.\n const logos = data.logoKeys\n .map((key) => {\n const src = resolveLogoSrc(key)\n if (!src) return null\n return { name: key.split('/').pop() ?? key, srcBlack: src, srcColored: src }\n })\n .filter((l): l is { name: string; srcBlack: string; srcColored: string } => l !== null)\n return (\n <CustomerLogoSection\n heading={data.heading}\n logos={logos}\n colorMode={data.colorMode}\n />\n )\n },\n\n FeaturesSection(data) {\n const items = data.items.map((it) => ({\n ...it,\n media: makeMedia(it.media),\n }))\n return (\n <FeaturesSection\n layout={data.layout}\n sectionHeading={data.sectionHeading}\n sectionTopic={data.sectionTopic}\n sectionDescription={data.sectionDescription}\n items={items}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n CardsSection(data) {\n const cards = data.cards?.map((c) => ({\n ...c,\n media: makeMedia(c.media),\n }))\n return (\n <CardsSection\n layout={data.layout}\n tagline={data.tagline}\n sectionHeading={data.sectionHeading}\n sectionDescription={data.sectionDescription}\n cards={cards}\n revealCards={data.revealCards}\n valueCards={data.valueCards}\n iconLinkCards={data.iconLinkCards}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n TestimonialsSection(data) {\n const cards = data.cards?.map((c) => ({\n quote: c.quote,\n authorName: c.authorName,\n authorRole: c.authorRole,\n stars: c.stars,\n stat: c.stat,\n statLabel: c.statLabel,\n ctaLabel: c.ctaLabel,\n ctaHref: c.ctaHref,\n logo: c.logoKey\n ? (() => {\n const src = resolveLogoSrc(c.logoKey)\n if (!src) return undefined\n return (\n <CustomerLogo\n src={src}\n name={c.logoKey.split('/').pop() ?? c.logoKey}\n placement=\"marketing\"\n />\n )\n })()\n : undefined,\n }))\n return (\n <TestimonialsSection\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n miniTitle={data.miniTitle}\n ctaLabel={data.ctaLabel}\n ctaHref={data.ctaHref}\n cards={cards}\n carouselCards={data.carouselCards}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n FaqSection(data) {\n return (\n <FaqSection\n layout={data.layout}\n heading={data.heading}\n items={data.items}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n BulletsSection(data) {\n const action = data.cta ? (\n <a href={data.cta.href} style={{ display: 'contents' }}>\n <Button buttonStyle=\"secondary\" size=\"regular\">\n {data.cta.label}\n </Button>\n </a>\n ) : undefined\n return (\n <BulletsSection\n layout={data.layout}\n miniTitle={data.miniTitle}\n heading={data.heading}\n description={data.description}\n columns={data.columns}\n items={data.items.map((item) => ({\n icon: <BulletDefaultIcon />,\n title: item.title,\n description: item.description,\n }))}\n action={action}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n CtaSection(data) {\n return (\n <CtaSection\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n actions={makeCtas(data.ctas)}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n FooterSection(data) {\n const logoSrcValue = data.logoKey ? resolveLogoSrc(data.logoKey) : undefined\n // FOOTER_DEFAULTS deliberately omits logo (consumers supply per-brand).\n // Only pass logo when we have a resolvable src — never an empty string,\n // which would render a broken <img> and trigger a React warning.\n const logo = logoSrcValue\n ? { src: logoSrcValue, alt: data.logoAlt ?? 'monday.com', href: '/' }\n : undefined\n return <FooterSection {...FOOTER_DEFAULTS} logo={logo} />\n },\n\n ContactSection(data) {\n const logos = data.logos\n ?.map((item) => {\n const src = resolveLogoSrc(item.key)\n return src ? { src, name: item.name } : null\n })\n .filter((l): l is { src: string; name: string } => l !== null)\n return (\n <ContactSection\n heading={data.heading}\n description={data.description}\n ratingValue={data.ratingValue}\n ratingLabel={data.ratingLabel}\n formTitle={data.formTitle}\n submitLabel={data.submitLabel}\n fields={data.fields}\n logos={logos}\n badges={data.badges}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n TrustSection(data) {\n return (\n <TrustSection\n layout={data.layout}\n heading={data.heading}\n ratingValue={data.ratingValue}\n ratingOut={data.ratingOut}\n ratingLabel={data.ratingLabel}\n badges={data.badges}\n ctaLabel={data.ctaLabel}\n ctaHref={data.ctaHref}\n topicLabel={data.topicLabel}\n securityTitle={data.securityTitle}\n securityDescription={data.securityDescription}\n securityLinkLabel={data.securityLinkLabel}\n securityLinkHref={data.securityLinkHref}\n complianceLogos={data.complianceLogos}\n statCards={data.statCards}\n />\n )\n },\n\n NumbersSection(data) {\n return (\n <NumbersSection\n layout={data.layout}\n heading={data.heading}\n items={data.items}\n containerWidth={data.containerWidth}\n />\n )\n },\n\n IntegrationsSection(data) {\n // naming skew: IntegrationsSection (agent-facing) → Integrations (React export)\n const integrations = data.integrations\n ?.map((item) => {\n const src =\n resolveLogoSrc(item.key) ??\n resolveLogoSrc(`integrations/${item.name.toLowerCase()}`)\n return src ? { name: item.name, src } : null\n })\n .filter((i): i is { name: string; src: string } => i !== null)\n return (\n <Integrations\n layout={data.layout}\n heading={data.heading}\n description={data.description}\n integrations={integrations}\n statValue={data.statValue}\n statLabel={data.statLabel}\n ctaLabel={data.ctaLabel}\n ctaHref={data.ctaHref}\n />\n )\n },\n}\n\n// ── public API ───────────────────────────────────────────────────────────────\n\nexport interface RenderResult {\n /** Complete self-contained HTML document */\n html: string\n /** Combined CSS (tokens + component styles) for reference */\n css: string\n}\n\n/**\n * Parse a PageSpec and render it to static HTML using real Clay React components.\n * Throws a ZodError on invalid input.\n */\nexport function renderPageSpec(input: unknown): RenderResult {\n const spec = PageSpec.parse(input)\n\n const sectionElements = spec.sections.map((section, i) => {\n const schema = sectionSchemas[section.type as SectionType]\n const props = schema.parse(section.props)\n const render = SECTION_REGISTRY[section.type as SectionType]\n return <Fragment key={i}>{render(props as never)}</Fragment>\n })\n\n const css = loadCss()\n\n const bodyHtml = renderToStaticMarkup(\n <>\n <NavbarMenu />\n {sectionElements}\n </>\n )\n\n const html = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\" />\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n<title>${spec.brand ?? 'Landing Page'}</title>\n<style>${css}</style>\n</head>\n<body>\n${bodyHtml}\n</body>\n</html>`\n\n return { html, css }\n}\n"],"names":["__dirname","require","Fragment"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@clay-ds/react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css"
|
|
@@ -30,7 +30,11 @@
|
|
|
30
30
|
},
|
|
31
31
|
"./logos/manifest.json": "./dist/logos/manifest.json",
|
|
32
32
|
"./catalog.json": "./dist/catalog.json",
|
|
33
|
-
"./icons":
|
|
33
|
+
"./icons": {
|
|
34
|
+
"types": "./dist/icons.d.ts",
|
|
35
|
+
"import": "./dist/icons.js",
|
|
36
|
+
"require": "./dist/icons.cjs"
|
|
37
|
+
},
|
|
34
38
|
"./package.json": "./package.json"
|
|
35
39
|
},
|
|
36
40
|
"files": [
|