@dreamtree-org/landing-kit 0.0.0-stage → 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/LICENSE +21 -0
- package/MIGRATION.md +87 -0
- package/README.md +191 -2
- package/auth.css +195 -0
- package/auth.d.ts +2 -0
- package/dist/auth.cjs +232 -0
- package/dist/auth.js +211 -0
- package/dist/enhance.cjs +83 -0
- package/dist/enhance.js +63 -0
- package/dist/index.cjs +1138 -0
- package/dist/index.js +1117 -0
- package/dist/seo.cjs +343 -0
- package/dist/seo.js +305 -0
- package/dist/server.cjs +569 -0
- package/dist/server.js +512 -0
- package/enhance.d.ts +12 -0
- package/index.d.ts +224 -0
- package/package.json +94 -4
- package/seo.d.ts +50 -0
- package/server.d.ts +43 -0
- package/styles.css +836 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1117 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
// src/LandingPage.jsx
|
|
4
|
+
import { Fragment as Fragment4, cloneElement, isValidElement as isValidElement2 } from "react";
|
|
5
|
+
|
|
6
|
+
// src/AuthShell.jsx
|
|
7
|
+
import { useId } from "react";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
var DEFAULT_LEGAL = [
|
|
10
|
+
{ label: "Privacy Policy", href: "/privacy" },
|
|
11
|
+
{ label: "Terms", href: "/terms" },
|
|
12
|
+
{ label: "Data Policy", href: "/data-policy" }
|
|
13
|
+
];
|
|
14
|
+
function BrandMark({ brand, size }) {
|
|
15
|
+
if (brand.logoSrc) {
|
|
16
|
+
return /* @__PURE__ */ jsx("img", { className: "dt-auth-mark-img", src: brand.logoSrc, alt: "", width: size, height: size });
|
|
17
|
+
}
|
|
18
|
+
if (brand.mark) return /* @__PURE__ */ jsx("span", { className: "dt-auth-mark-node", children: brand.mark });
|
|
19
|
+
return /* @__PURE__ */ jsx("span", { className: "dt-auth-monogram", style: { width: size, height: size }, "aria-hidden": "true", children: brand.name.charAt(0) });
|
|
20
|
+
}
|
|
21
|
+
function brandStyle(brand) {
|
|
22
|
+
return {
|
|
23
|
+
"--dt-brand": brand.primary,
|
|
24
|
+
"--dt-brand-accent": brand.accent || brand.primary,
|
|
25
|
+
...brand.panel ? { "--dt-brand-panel": brand.panel } : {}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
function AuthShell({
|
|
29
|
+
brand,
|
|
30
|
+
title,
|
|
31
|
+
subtitle,
|
|
32
|
+
children,
|
|
33
|
+
footer,
|
|
34
|
+
variant = "tenant",
|
|
35
|
+
legalLinks = DEFAULT_LEGAL,
|
|
36
|
+
linkComponent: LinkComponent,
|
|
37
|
+
className = ""
|
|
38
|
+
}) {
|
|
39
|
+
var _a;
|
|
40
|
+
const headingId = useId();
|
|
41
|
+
const isPlatform = variant === "platform";
|
|
42
|
+
const headline = isPlatform ? brand.platformHeadline || "Platform administration" : brand.headline;
|
|
43
|
+
const pitch = isPlatform ? brand.platformPitch || `Super administrator console for ${brand.name}. Every action here is audited.` : brand.pitch;
|
|
44
|
+
const renderLink = (l) => LinkComponent ? /* @__PURE__ */ jsx(LinkComponent, { to: l.href, href: l.href, className: "dt-auth-legal-link", children: l.label }, l.href) : /* @__PURE__ */ jsx("a", { href: l.href, className: "dt-auth-legal-link", children: l.label }, l.href);
|
|
45
|
+
return /* @__PURE__ */ jsxs(
|
|
46
|
+
"div",
|
|
47
|
+
{
|
|
48
|
+
className: `dt-auth ${isPlatform ? "dt-auth--platform" : ""} ${className}`,
|
|
49
|
+
style: brandStyle(brand),
|
|
50
|
+
"data-product": brand.id,
|
|
51
|
+
children: [
|
|
52
|
+
/* @__PURE__ */ jsxs("aside", { className: "dt-auth-panel", children: [
|
|
53
|
+
/* @__PURE__ */ jsxs("a", { href: "/", className: "dt-auth-brand", children: [
|
|
54
|
+
/* @__PURE__ */ jsx(BrandMark, { brand, size: 28 }),
|
|
55
|
+
/* @__PURE__ */ jsx("span", { className: "dt-auth-brand-name", children: brand.name }),
|
|
56
|
+
isPlatform ? /* @__PURE__ */ jsx("span", { className: "dt-auth-badge", children: "Platform" }) : null
|
|
57
|
+
] }),
|
|
58
|
+
/* @__PURE__ */ jsxs("div", { className: "dt-auth-pitch", children: [
|
|
59
|
+
/* @__PURE__ */ jsx("h2", { children: headline }),
|
|
60
|
+
pitch ? /* @__PURE__ */ jsx("p", { children: pitch }) : null,
|
|
61
|
+
!isPlatform && ((_a = brand.points) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsx("ul", { children: brand.points.map((p) => /* @__PURE__ */ jsx("li", { children: p }, p)) }) : null
|
|
62
|
+
] }),
|
|
63
|
+
/* @__PURE__ */ jsx("p", { className: "dt-auth-panel-foot", children: brand.category || "by Dreamtree-Org" })
|
|
64
|
+
] }),
|
|
65
|
+
/* @__PURE__ */ jsx("main", { className: "dt-auth-main", children: /* @__PURE__ */ jsxs("div", { className: "dt-auth-column", children: [
|
|
66
|
+
/* @__PURE__ */ jsxs("a", { href: "/", className: "dt-auth-brand dt-auth-brand--mobile", children: [
|
|
67
|
+
/* @__PURE__ */ jsx(BrandMark, { brand, size: 24 }),
|
|
68
|
+
/* @__PURE__ */ jsx("span", { className: "dt-auth-brand-name", children: brand.name }),
|
|
69
|
+
isPlatform ? /* @__PURE__ */ jsx("span", { className: "dt-auth-badge", children: "Platform" }) : null
|
|
70
|
+
] }),
|
|
71
|
+
/* @__PURE__ */ jsxs("section", { className: "dt-auth-card", "aria-labelledby": headingId, children: [
|
|
72
|
+
/* @__PURE__ */ jsxs("header", { className: "dt-auth-head", children: [
|
|
73
|
+
/* @__PURE__ */ jsx("h1", { id: headingId, children: title }),
|
|
74
|
+
subtitle ? /* @__PURE__ */ jsx("p", { children: subtitle }) : null
|
|
75
|
+
] }),
|
|
76
|
+
children
|
|
77
|
+
] }),
|
|
78
|
+
footer ? /* @__PURE__ */ jsx("div", { className: "dt-auth-footer", children: footer }) : null,
|
|
79
|
+
(legalLinks == null ? void 0 : legalLinks.length) ? /* @__PURE__ */ jsx("nav", { className: "dt-auth-legal", "aria-label": "Legal", children: legalLinks.map((l, i) => /* @__PURE__ */ jsxs("span", { className: "dt-auth-legal-item", children: [
|
|
80
|
+
i > 0 ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }) : null,
|
|
81
|
+
renderLink(l)
|
|
82
|
+
] }, l.href)) }) : null
|
|
83
|
+
] }) })
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/context.jsx
|
|
90
|
+
import { createContext, useContext } from "react";
|
|
91
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
92
|
+
var LandingContext = createContext({ brand: null, linkComponent: null, onBookDemo: null, home: true });
|
|
93
|
+
var LandingProvider = LandingContext.Provider;
|
|
94
|
+
var useLanding = () => useContext(LandingContext);
|
|
95
|
+
function resolveHref(href, home) {
|
|
96
|
+
if (!href) return href;
|
|
97
|
+
return !home && href.startsWith("#") ? `/${href}` : href;
|
|
98
|
+
}
|
|
99
|
+
function SmartLink({ href, children, className, reload, ...rest }) {
|
|
100
|
+
const { linkComponent: Link, home } = useLanding();
|
|
101
|
+
const to = resolveHref(href, home);
|
|
102
|
+
const internal = to && to.startsWith("/") && !to.startsWith("//") && !to.includes("#");
|
|
103
|
+
if (Link && internal && !reload) {
|
|
104
|
+
return /* @__PURE__ */ jsx2(Link, { to, href: to, className, ...rest, children });
|
|
105
|
+
}
|
|
106
|
+
return /* @__PURE__ */ jsx2("a", { href: to, className, ...rest, children });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/Header.jsx
|
|
110
|
+
import { useState } from "react";
|
|
111
|
+
|
|
112
|
+
// src/icons.jsx
|
|
113
|
+
import { createElement, isValidElement } from "react";
|
|
114
|
+
import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
115
|
+
var base = {
|
|
116
|
+
viewBox: "0 0 24 24",
|
|
117
|
+
fill: "none",
|
|
118
|
+
stroke: "currentColor",
|
|
119
|
+
strokeWidth: 2,
|
|
120
|
+
strokeLinecap: "round",
|
|
121
|
+
strokeLinejoin: "round",
|
|
122
|
+
"aria-hidden": "true",
|
|
123
|
+
focusable: "false"
|
|
124
|
+
};
|
|
125
|
+
var make = (paths) => function Icon({ size = 16, className = "dt-lp-icon" }) {
|
|
126
|
+
return /* @__PURE__ */ jsx3("svg", { ...base, width: size, height: size, className, children: paths });
|
|
127
|
+
};
|
|
128
|
+
var ArrowRight = make(/* @__PURE__ */ jsx3("path", { d: "M5 12h14M13 6l6 6-6 6" }));
|
|
129
|
+
var ChevronRight = make(/* @__PURE__ */ jsx3("path", { d: "m9 6 6 6-6 6" }));
|
|
130
|
+
var Check = make(/* @__PURE__ */ jsx3("path", { d: "M20 6 9 17l-5-5" }));
|
|
131
|
+
var Help = make(
|
|
132
|
+
/* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
133
|
+
/* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "10" }),
|
|
134
|
+
/* @__PURE__ */ jsx3("path", { d: "M9.1 9a3 3 0 0 1 5.8 1c0 2-3 3-3 3M12 17h.01" })
|
|
135
|
+
] })
|
|
136
|
+
);
|
|
137
|
+
var Alert = make(
|
|
138
|
+
/* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
139
|
+
/* @__PURE__ */ jsx3("path", { d: "M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z" }),
|
|
140
|
+
/* @__PURE__ */ jsx3("path", { d: "M12 9v4M12 17h.01" })
|
|
141
|
+
] })
|
|
142
|
+
);
|
|
143
|
+
var MenuIcon = make(/* @__PURE__ */ jsx3("path", { d: "M4 6h16M4 12h16M4 18h16" }));
|
|
144
|
+
var Close = make(/* @__PURE__ */ jsx3("path", { d: "M18 6 6 18M6 6l12 12" }));
|
|
145
|
+
var Calendar = make(
|
|
146
|
+
/* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
147
|
+
/* @__PURE__ */ jsx3("rect", { x: "3", y: "4", width: "18", height: "18", rx: "2" }),
|
|
148
|
+
/* @__PURE__ */ jsx3("path", { d: "M16 2v4M8 2v4M3 10h18m-12 6 2 2 4-4" })
|
|
149
|
+
] })
|
|
150
|
+
);
|
|
151
|
+
function renderIcon(icon, size = 20, className = "dt-lp-icon") {
|
|
152
|
+
if (!icon) return null;
|
|
153
|
+
if (isValidElement(icon)) return icon;
|
|
154
|
+
return createElement(icon, { size, "aria-hidden": true, className, strokeWidth: 1.8 });
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// src/Brand.jsx
|
|
158
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
159
|
+
function BrandMark2({ brand, size = 36 }) {
|
|
160
|
+
if (brand.logoSrc) {
|
|
161
|
+
return /* @__PURE__ */ jsx4("img", { className: "dt-lp-mark-img", src: brand.logoSrc, alt: "", width: size, height: size });
|
|
162
|
+
}
|
|
163
|
+
if (brand.mark) return /* @__PURE__ */ jsx4("span", { className: "dt-lp-mark-node", "aria-hidden": "true", children: brand.mark });
|
|
164
|
+
return /* @__PURE__ */ jsx4("span", { className: "dt-lp-monogram", style: { width: size, height: size }, "aria-hidden": "true", children: brand.name.charAt(0) });
|
|
165
|
+
}
|
|
166
|
+
function Wordmark({ name }) {
|
|
167
|
+
const m = /^(.+?)(Pro)$/.exec(name);
|
|
168
|
+
if (!m) return /* @__PURE__ */ jsx4("span", { className: "dt-lp-wordmark", children: name });
|
|
169
|
+
return /* @__PURE__ */ jsxs3("span", { className: "dt-lp-wordmark", children: [
|
|
170
|
+
m[1],
|
|
171
|
+
/* @__PURE__ */ jsx4("span", { className: "dt-lp-wordmark-hi", children: m[2] })
|
|
172
|
+
] });
|
|
173
|
+
}
|
|
174
|
+
function BrandLockup({ brand: own, byline = "by Dreamtree-Org", href = "/" }) {
|
|
175
|
+
const ctx = useLanding();
|
|
176
|
+
const brand = own || ctx.brand;
|
|
177
|
+
if (!brand) return null;
|
|
178
|
+
return /* @__PURE__ */ jsxs3("a", { href, className: "dt-lp-brand", "aria-label": `${brand.name}${byline ? ` ${byline}` : ""}, home`, children: [
|
|
179
|
+
/* @__PURE__ */ jsx4(BrandMark2, { brand }),
|
|
180
|
+
/* @__PURE__ */ jsxs3("span", { className: "dt-lp-brand-text", "aria-hidden": "true", children: [
|
|
181
|
+
/* @__PURE__ */ jsx4(Wordmark, { name: brand.name }),
|
|
182
|
+
byline ? /* @__PURE__ */ jsx4("span", { className: "dt-lp-byline", children: byline }) : null
|
|
183
|
+
] })
|
|
184
|
+
] });
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// src/BookDemoButton.jsx
|
|
188
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
189
|
+
function BookDemoButton({ size = "md", variant = "primary", className = "", children = "Book a demo", onClick }) {
|
|
190
|
+
const { onBookDemo } = useLanding();
|
|
191
|
+
const handler = onClick || (onBookDemo ? (e) => onBookDemo(e.currentTarget) : void 0);
|
|
192
|
+
return /* @__PURE__ */ jsx5(
|
|
193
|
+
"button",
|
|
194
|
+
{
|
|
195
|
+
type: "button",
|
|
196
|
+
className: `dt-lp-btn dt-lp-btn--${variant} dt-lp-btn--${size} ${className}`.trim(),
|
|
197
|
+
"data-book-demo": "",
|
|
198
|
+
"aria-haspopup": "dialog",
|
|
199
|
+
onClick: handler,
|
|
200
|
+
children
|
|
201
|
+
}
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// src/Section.jsx
|
|
206
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
207
|
+
function Wrap({ className = "", narrow, children }) {
|
|
208
|
+
return /* @__PURE__ */ jsx6("div", { className: `dt-lp-wrap${narrow ? " dt-lp-wrap--narrow" : ""} ${className}`.trim(), children });
|
|
209
|
+
}
|
|
210
|
+
function Eyebrow({ children, className = "" }) {
|
|
211
|
+
if (!children) return null;
|
|
212
|
+
return /* @__PURE__ */ jsx6("p", { className: `dt-lp-eyebrow ${className}`.trim(), children });
|
|
213
|
+
}
|
|
214
|
+
function SectionIntro({ id, eyebrow, title, body, align = "start", children }) {
|
|
215
|
+
return /* @__PURE__ */ jsxs4("div", { className: `dt-lp-intro dt-lp-intro--${align}`, children: [
|
|
216
|
+
/* @__PURE__ */ jsx6(Eyebrow, { children: eyebrow }),
|
|
217
|
+
/* @__PURE__ */ jsx6("h2", { id, className: "dt-lp-h2", children: title }),
|
|
218
|
+
body ? /* @__PURE__ */ jsx6("p", { className: "dt-lp-lead", children: body }) : null,
|
|
219
|
+
children
|
|
220
|
+
] });
|
|
221
|
+
}
|
|
222
|
+
function Section({ id, labelledBy, tone = "plain", className = "", children, narrow }) {
|
|
223
|
+
return /* @__PURE__ */ jsx6("section", { id, "aria-labelledby": labelledBy, className: `dt-lp-section dt-lp-tone--${tone} ${className}`.trim(), children: /* @__PURE__ */ jsx6(Wrap, { narrow, children }) });
|
|
224
|
+
}
|
|
225
|
+
function TextLink({ href, children, className = "", ...rest }) {
|
|
226
|
+
return /* @__PURE__ */ jsxs4(SmartLink, { href, className: `dt-lp-textlink ${className}`.trim(), ...rest, children: [
|
|
227
|
+
children,
|
|
228
|
+
" ",
|
|
229
|
+
/* @__PURE__ */ jsx6(ArrowRight, {})
|
|
230
|
+
] });
|
|
231
|
+
}
|
|
232
|
+
function Cta({ cta, className = "" }) {
|
|
233
|
+
if (!cta) return null;
|
|
234
|
+
if (Array.isArray(cta)) {
|
|
235
|
+
if (!cta.length) return null;
|
|
236
|
+
return /* @__PURE__ */ jsx6("div", { className: `dt-lp-ctas ${className}`.trim(), children: cta.map((c2, i) => /* @__PURE__ */ jsx6(Cta, { cta: c2 }, i)) });
|
|
237
|
+
}
|
|
238
|
+
const c = typeof cta === "string" ? { label: cta, demo: true } : cta;
|
|
239
|
+
if (c.href && !c.demo) return /* @__PURE__ */ jsx6(TextLink, { href: c.href, className, children: c.label });
|
|
240
|
+
return /* @__PURE__ */ jsxs4(BookDemoButton, { size: "lg", className, children: [
|
|
241
|
+
c.label,
|
|
242
|
+
" ",
|
|
243
|
+
/* @__PURE__ */ jsx6(ArrowRight, {})
|
|
244
|
+
] });
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// src/Header.jsx
|
|
248
|
+
import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
249
|
+
function Header({ nav = [], login = { label: "Log in", href: "/login" }, cta = "Book a demo", brand }) {
|
|
250
|
+
const { home } = useLanding();
|
|
251
|
+
const [open, setOpen] = useState(false);
|
|
252
|
+
const items = login ? [...nav, login] : nav;
|
|
253
|
+
return /* @__PURE__ */ jsxs5("header", { className: "dt-lp-header", children: [
|
|
254
|
+
/* @__PURE__ */ jsxs5(Wrap, { className: "dt-lp-header-bar", children: [
|
|
255
|
+
/* @__PURE__ */ jsx7(BrandLockup, { brand }),
|
|
256
|
+
nav.length ? /* @__PURE__ */ jsx7("nav", { "aria-label": "Primary", className: "dt-lp-nav", children: nav.map((n) => /* @__PURE__ */ jsx7(SmartLink, { href: n.href, className: "dt-lp-nav-link", children: n.label }, n.href)) }) : null,
|
|
257
|
+
/* @__PURE__ */ jsxs5("div", { className: "dt-lp-header-actions", children: [
|
|
258
|
+
login ? /* @__PURE__ */ jsx7(SmartLink, { href: login.href, className: "dt-lp-nav-link dt-lp-login", reload: true, children: login.label }) : null,
|
|
259
|
+
cta ? /* @__PURE__ */ jsx7(BookDemoButton, { size: "sm", children: cta }) : null,
|
|
260
|
+
items.length ? /* @__PURE__ */ jsxs5(
|
|
261
|
+
"button",
|
|
262
|
+
{
|
|
263
|
+
type: "button",
|
|
264
|
+
className: "dt-lp-menu-btn",
|
|
265
|
+
"aria-label": open ? "Close menu" : "Open menu",
|
|
266
|
+
"aria-expanded": open ? "true" : "false",
|
|
267
|
+
"aria-controls": "mobile-nav",
|
|
268
|
+
"data-menu-toggle": "",
|
|
269
|
+
onClick: () => setOpen((o) => !o),
|
|
270
|
+
children: [
|
|
271
|
+
/* @__PURE__ */ jsx7("span", { className: "dt-lp-menu-open", children: /* @__PURE__ */ jsx7(MenuIcon, { size: 20 }) }),
|
|
272
|
+
/* @__PURE__ */ jsx7("span", { className: "dt-lp-menu-close", children: /* @__PURE__ */ jsx7(Close, { size: 20 }) })
|
|
273
|
+
]
|
|
274
|
+
}
|
|
275
|
+
) : null
|
|
276
|
+
] })
|
|
277
|
+
] }),
|
|
278
|
+
items.length ? /* @__PURE__ */ jsx7("nav", { id: "mobile-nav", "aria-label": "Mobile", className: "dt-lp-mobile-nav", hidden: !open, onClick: (e) => {
|
|
279
|
+
var _a, _b;
|
|
280
|
+
return ((_b = (_a = e.target).closest) == null ? void 0 : _b.call(_a, "a")) && setOpen(false);
|
|
281
|
+
}, children: /* @__PURE__ */ jsx7(Wrap, { children: /* @__PURE__ */ jsx7("ul", { children: items.map((n) => /* @__PURE__ */ jsx7("li", { children: /* @__PURE__ */ jsx7(SmartLink, { href: n.href, reload: n === login, children: n.label }) }, n.href)) }) }) }) : null
|
|
282
|
+
] });
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// src/DreamtreeFooter.jsx
|
|
286
|
+
import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
287
|
+
function DreamtreeMark({ size = 28 }) {
|
|
288
|
+
return /* @__PURE__ */ jsxs6("span", { className: "dt-lp-org", role: "img", "aria-label": "Dreamtree-Org", children: [
|
|
289
|
+
/* @__PURE__ */ jsx8("svg", { viewBox: "0 0 48.35 48.35", width: size, height: size, "aria-hidden": "true", children: /* @__PURE__ */ jsxs6("g", { fill: "none", strokeWidth: "4", strokeLinecap: "round", strokeLinejoin: "round", stroke: "#0f766e", children: [
|
|
290
|
+
/* @__PURE__ */ jsx8("path", { d: "M23.01,44.02c-9.02.03-16.36-7.27-16.39-16.29-.02-7.98,5.72-14.81,13.59-16.16,13.31-2.57,16.81-3.78,21.48-9.57,2.33,4.67,4.67,9.76,4.67,18.67,0,12.84-11.16,23.34-23.34,23.34Z" }),
|
|
291
|
+
/* @__PURE__ */ jsx8("path", { d: "M2,46.35c0-7,4.32-12.51,11.86-14.01,5.65-1.12,11.49-4.67,13.82-7" })
|
|
292
|
+
] }) }),
|
|
293
|
+
/* @__PURE__ */ jsx8("span", { "aria-hidden": "true", className: "dt-lp-org-name", children: "Dreamtree-Org" })
|
|
294
|
+
] });
|
|
295
|
+
}
|
|
296
|
+
function DreamtreeFooter({
|
|
297
|
+
blurb,
|
|
298
|
+
columns = [],
|
|
299
|
+
org = "Dreamtree-Org",
|
|
300
|
+
tagline,
|
|
301
|
+
legal = [],
|
|
302
|
+
year = (/* @__PURE__ */ new Date()).getFullYear(),
|
|
303
|
+
brand: own
|
|
304
|
+
}) {
|
|
305
|
+
const ctx = useLanding();
|
|
306
|
+
const brand = own || ctx.brand;
|
|
307
|
+
return /* @__PURE__ */ jsxs6("footer", { className: "dt-lp-footer", children: [
|
|
308
|
+
/* @__PURE__ */ jsxs6(Wrap, { className: `dt-lp-footer-grid dt-lp-footer-grid--${Math.min(columns.length, 3)}`, children: [
|
|
309
|
+
/* @__PURE__ */ jsxs6("div", { className: "dt-lp-footer-about", children: [
|
|
310
|
+
/* @__PURE__ */ jsx8(DreamtreeMark, {}),
|
|
311
|
+
blurb ? /* @__PURE__ */ jsx8("p", { children: blurb }) : null
|
|
312
|
+
] }),
|
|
313
|
+
columns.map((col) => /* @__PURE__ */ jsxs6("nav", { "aria-label": col.label || col.title, className: "dt-lp-footer-col", children: [
|
|
314
|
+
/* @__PURE__ */ jsx8("p", { className: "dt-lp-footer-title", children: col.title }),
|
|
315
|
+
/* @__PURE__ */ jsx8("ul", { className: col.links.length > 5 && col.compact !== false ? "dt-lp-footer-links" : "dt-lp-footer-links dt-lp-footer-links--one", children: col.links.map((l) => /* @__PURE__ */ jsx8("li", { children: /* @__PURE__ */ jsx8(SmartLink, { href: l.href, reload: l.reload, children: l.label }) }, l.href)) })
|
|
316
|
+
] }, col.title))
|
|
317
|
+
] }),
|
|
318
|
+
/* @__PURE__ */ jsx8("div", { className: "dt-lp-footer-bar", children: /* @__PURE__ */ jsxs6(Wrap, { className: "dt-lp-footer-bar-inner", children: [
|
|
319
|
+
/* @__PURE__ */ jsxs6("p", { children: [
|
|
320
|
+
"\xA9 ",
|
|
321
|
+
year,
|
|
322
|
+
" ",
|
|
323
|
+
org,
|
|
324
|
+
". All rights reserved."
|
|
325
|
+
] }),
|
|
326
|
+
legal.length ? /* @__PURE__ */ jsx8("nav", { "aria-label": "Legal", className: "dt-lp-footer-legal", children: legal.map((l) => /* @__PURE__ */ jsx8(SmartLink, { href: l.href, children: l.label }, l.href)) }) : null,
|
|
327
|
+
brand && tagline ? /* @__PURE__ */ jsxs6("p", { children: [
|
|
328
|
+
brand.name,
|
|
329
|
+
": ",
|
|
330
|
+
tagline
|
|
331
|
+
] }) : null
|
|
332
|
+
] }) })
|
|
333
|
+
] });
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// src/MarketingLayout.jsx
|
|
337
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
338
|
+
function MarketingLayout({
|
|
339
|
+
brand,
|
|
340
|
+
nav = [],
|
|
341
|
+
login,
|
|
342
|
+
cta,
|
|
343
|
+
footer,
|
|
344
|
+
home = true,
|
|
345
|
+
linkComponent = null,
|
|
346
|
+
onBookDemo = null,
|
|
347
|
+
className = "",
|
|
348
|
+
children
|
|
349
|
+
}) {
|
|
350
|
+
if (!brand || !brand.name) {
|
|
351
|
+
throw new Error(`landing-kit: "brand" is missing. Pass getBrand('<product>') from @dreamtree-org/auth-kit, or your own { id, name, primary }.`);
|
|
352
|
+
}
|
|
353
|
+
return /* @__PURE__ */ jsx9(LandingProvider, { value: { brand, linkComponent, onBookDemo, home }, children: /* @__PURE__ */ jsxs7("div", { className: `dt-landing ${className}`.trim(), style: brandStyle(brand), "data-product": brand.id, children: [
|
|
354
|
+
/* @__PURE__ */ jsx9("a", { href: "#main", className: "dt-lp-skip", children: "Skip to content" }),
|
|
355
|
+
/* @__PURE__ */ jsx9(Header, { nav, ...login !== void 0 ? { login } : {}, ...cta !== void 0 ? { cta } : {} }),
|
|
356
|
+
/* @__PURE__ */ jsx9("main", { id: "main", children }),
|
|
357
|
+
footer === false ? null : /* @__PURE__ */ jsx9(DreamtreeFooter, { ...footer || {} })
|
|
358
|
+
] }) });
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// src/Hero.jsx
|
|
362
|
+
import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
363
|
+
function Hero({
|
|
364
|
+
eyebrow,
|
|
365
|
+
title,
|
|
366
|
+
subtitle,
|
|
367
|
+
lead,
|
|
368
|
+
chips,
|
|
369
|
+
chipsLabel = "Who it is for",
|
|
370
|
+
cta = "Book a demo",
|
|
371
|
+
secondary,
|
|
372
|
+
overlap = false,
|
|
373
|
+
id = "hero",
|
|
374
|
+
backdrop
|
|
375
|
+
}) {
|
|
376
|
+
const [first, hi] = Array.isArray(title) ? title : [title, null];
|
|
377
|
+
return /* @__PURE__ */ jsxs8("section", { id, "aria-labelledby": "hero-title", className: `dt-lp-hero${overlap ? " dt-lp-hero--overlap" : ""}`, children: [
|
|
378
|
+
/* @__PURE__ */ jsx10("div", { className: "dt-lp-hero-glow", "aria-hidden": "true" }),
|
|
379
|
+
backdrop ? /* @__PURE__ */ jsx10("div", { className: "dt-lp-hero-backdrop", "aria-hidden": "true", children: backdrop }) : null,
|
|
380
|
+
/* @__PURE__ */ jsxs8(Wrap, { className: "dt-lp-hero-inner", children: [
|
|
381
|
+
/* @__PURE__ */ jsx10(Eyebrow, { children: eyebrow }),
|
|
382
|
+
/* @__PURE__ */ jsxs8("h1", { id: "hero-title", className: "dt-lp-h1", children: [
|
|
383
|
+
first,
|
|
384
|
+
hi ? /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
385
|
+
" ",
|
|
386
|
+
/* @__PURE__ */ jsx10("span", { className: "dt-lp-h1-hi", children: hi })
|
|
387
|
+
] }) : null
|
|
388
|
+
] }),
|
|
389
|
+
subtitle ? /* @__PURE__ */ jsx10("p", { className: "dt-lp-hero-subtitle", children: subtitle }) : null,
|
|
390
|
+
lead ? /* @__PURE__ */ jsx10("p", { className: "dt-lp-hero-lead", children: lead }) : null,
|
|
391
|
+
/* @__PURE__ */ jsxs8("div", { className: "dt-lp-actions", children: [
|
|
392
|
+
cta ? /* @__PURE__ */ jsx10(BookDemoButton, { size: "lg", children: cta }) : null,
|
|
393
|
+
secondary ? /* @__PURE__ */ jsx10(TextLink, { href: secondary.href, children: secondary.label }) : null
|
|
394
|
+
] }),
|
|
395
|
+
(chips == null ? void 0 : chips.length) ? /* @__PURE__ */ jsx10("ul", { className: "dt-lp-chips", "aria-label": chipsLabel, children: chips.map((c) => /* @__PURE__ */ jsx10("li", { children: c }, c)) }) : null
|
|
396
|
+
] })
|
|
397
|
+
] });
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// src/FeatureSection.jsx
|
|
401
|
+
import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
402
|
+
var asItem = (x) => typeof x === "string" ? { title: x } : x;
|
|
403
|
+
function Items({ items, kind }) {
|
|
404
|
+
return /* @__PURE__ */ jsx11("ul", { className: `dt-lp-grid dt-lp-grid--${kind}`, children: items.map(asItem).map((f) => /* @__PURE__ */ jsxs9("li", { className: `dt-lp-card dt-lp-card--${kind}`, children: [
|
|
405
|
+
f.icon ? /* @__PURE__ */ jsx11("span", { className: "dt-lp-icon-tile", children: renderIcon(f.icon, 20) }) : null,
|
|
406
|
+
/* @__PURE__ */ jsxs9("div", { className: "dt-lp-card-text", children: [
|
|
407
|
+
f.label ? /* @__PURE__ */ jsx11("p", { className: "dt-lp-kicker", children: f.label }) : null,
|
|
408
|
+
/* @__PURE__ */ jsx11("h3", { className: "dt-lp-h3", children: f.href ? /* @__PURE__ */ jsx11(SmartLink, { href: f.href, children: f.title }) : f.title }),
|
|
409
|
+
f.body ? /* @__PURE__ */ jsx11("p", { children: f.body }) : null
|
|
410
|
+
] })
|
|
411
|
+
] }, f.title)) });
|
|
412
|
+
}
|
|
413
|
+
function Checklist({ items, icon: Icon = Check, tone = "good", labelledBy }) {
|
|
414
|
+
return /* @__PURE__ */ jsx11("ul", { className: `dt-lp-checklist dt-lp-checklist--${tone}`, "aria-labelledby": labelledBy, children: items.map((x) => /* @__PURE__ */ jsxs9("li", { children: [
|
|
415
|
+
/* @__PURE__ */ jsx11(Icon, { size: 18 }),
|
|
416
|
+
/* @__PURE__ */ jsx11("span", { children: x })
|
|
417
|
+
] }, x)) });
|
|
418
|
+
}
|
|
419
|
+
function InlineItems({ items }) {
|
|
420
|
+
if (!(items == null ? void 0 : items.length)) return null;
|
|
421
|
+
return /* @__PURE__ */ jsx11("ul", { className: "dt-lp-inline-items", children: items.map(asItem).map((f) => /* @__PURE__ */ jsxs9("li", { children: [
|
|
422
|
+
f.icon ? renderIcon(f.icon, 22) : null,
|
|
423
|
+
/* @__PURE__ */ jsxs9("span", { children: [
|
|
424
|
+
/* @__PURE__ */ jsx11("span", { className: "dt-lp-inline-title", children: f.title }),
|
|
425
|
+
f.body ? /* @__PURE__ */ jsx11("span", { className: "dt-lp-inline-body", children: f.body }) : null
|
|
426
|
+
] })
|
|
427
|
+
] }, f.title)) });
|
|
428
|
+
}
|
|
429
|
+
function Media({ children }) {
|
|
430
|
+
return /* @__PURE__ */ jsx11("div", { className: "dt-lp-media", children });
|
|
431
|
+
}
|
|
432
|
+
function Pair({ className, reverse, text, side }) {
|
|
433
|
+
return /* @__PURE__ */ jsxs9("div", { className: `${className}${reverse ? " dt-lp-pair--reverse" : ""}`, children: [
|
|
434
|
+
reverse ? side : text,
|
|
435
|
+
reverse ? text : side
|
|
436
|
+
] });
|
|
437
|
+
}
|
|
438
|
+
function Chips({ items, label, className = "" }) {
|
|
439
|
+
if (!(items == null ? void 0 : items.length)) return null;
|
|
440
|
+
return /* @__PURE__ */ jsx11("ul", { className: `dt-lp-chips dt-lp-chips--start ${className}`.trim(), "aria-label": label, children: items.map((c) => /* @__PURE__ */ jsx11("li", { children: c }, c)) });
|
|
441
|
+
}
|
|
442
|
+
function FeatureSection(props) {
|
|
443
|
+
const { id, variant = "cards", tone, eyebrow, title, body, items = [], cta, footnote, media, reverse, bullets } = props;
|
|
444
|
+
const hid = `${id || variant}-title`;
|
|
445
|
+
const defaultTone = { highlight: "dark", split: "tinted", compare: "muted" }[variant] || "plain";
|
|
446
|
+
const shell = (children, extra = {}) => /* @__PURE__ */ jsx11(Section, { id, labelledBy: hid, tone: tone || defaultTone, className: `dt-lp-feature dt-lp-feature--${variant}`, ...extra, children });
|
|
447
|
+
switch (variant) {
|
|
448
|
+
case "split":
|
|
449
|
+
return shell(
|
|
450
|
+
/* @__PURE__ */ jsx11(
|
|
451
|
+
Pair,
|
|
452
|
+
{
|
|
453
|
+
className: "dt-lp-split",
|
|
454
|
+
reverse,
|
|
455
|
+
text: /* @__PURE__ */ jsxs9(SectionIntro, { id: hid, eyebrow, title, body, children: [
|
|
456
|
+
media ? /* @__PURE__ */ jsx11(InlineItems, { items }) : null,
|
|
457
|
+
(bullets == null ? void 0 : bullets.length) ? /* @__PURE__ */ jsx11(Checklist, { items: bullets }) : null,
|
|
458
|
+
/* @__PURE__ */ jsx11(Cta, { cta, className: "dt-lp-mt" })
|
|
459
|
+
] }, "text"),
|
|
460
|
+
side: media ? /* @__PURE__ */ jsx11(Media, { children: media }, "side") : /* @__PURE__ */ jsx11(Items, { items, kind: "split" }, "side")
|
|
461
|
+
}
|
|
462
|
+
)
|
|
463
|
+
);
|
|
464
|
+
case "list":
|
|
465
|
+
return shell(
|
|
466
|
+
/* @__PURE__ */ jsxs9(Fragment3, { children: [
|
|
467
|
+
/* @__PURE__ */ jsx11(SectionIntro, { id: hid, eyebrow, title, body, align: "center" }),
|
|
468
|
+
/* @__PURE__ */ jsx11(Items, { items, kind: "list" }),
|
|
469
|
+
/* @__PURE__ */ jsx11(Cta, { cta, className: "dt-lp-mt" })
|
|
470
|
+
] })
|
|
471
|
+
);
|
|
472
|
+
case "intro": {
|
|
473
|
+
const { subtitle, detail, note, glance = [], glanceTitle = "At a glance", link } = props;
|
|
474
|
+
return shell(
|
|
475
|
+
/* @__PURE__ */ jsxs9("div", { className: "dt-lp-intro-grid", children: [
|
|
476
|
+
/* @__PURE__ */ jsxs9("div", { children: [
|
|
477
|
+
/* @__PURE__ */ jsx11(SectionIntro, { id: hid, eyebrow, title, body }),
|
|
478
|
+
subtitle ? /* @__PURE__ */ jsx11("h3", { className: "dt-lp-h3 dt-lp-h3--lg", children: subtitle }) : null,
|
|
479
|
+
detail ? /* @__PURE__ */ jsx11("p", { className: "dt-lp-body", children: detail }) : null,
|
|
480
|
+
note ? /* @__PURE__ */ jsx11("p", { className: "dt-lp-note", children: note }) : null,
|
|
481
|
+
/* @__PURE__ */ jsx11(Cta, { cta, className: "dt-lp-mt" })
|
|
482
|
+
] }),
|
|
483
|
+
glance.length ? /* @__PURE__ */ jsxs9("aside", { className: "dt-lp-glance", "aria-labelledby": `${hid}-glance`, children: [
|
|
484
|
+
/* @__PURE__ */ jsx11("p", { id: `${hid}-glance`, className: "dt-lp-eyebrow", children: glanceTitle }),
|
|
485
|
+
/* @__PURE__ */ jsx11(Checklist, { items: glance }),
|
|
486
|
+
props.glanceNote ? /* @__PURE__ */ jsx11("p", { className: "dt-lp-note", children: props.glanceNote }) : null,
|
|
487
|
+
link ? /* @__PURE__ */ jsx11(TextLink, { href: link.href, className: "dt-lp-mt", children: link.label }) : null
|
|
488
|
+
] }) : null
|
|
489
|
+
] })
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
case "highlight": {
|
|
493
|
+
const { note, noteLabel = "Important:" } = props;
|
|
494
|
+
const text = /* @__PURE__ */ jsxs9("div", { className: "dt-lp-intro", children: [
|
|
495
|
+
/* @__PURE__ */ jsx11(Eyebrow, { children: eyebrow }),
|
|
496
|
+
/* @__PURE__ */ jsx11("h2", { id: hid, className: "dt-lp-h2", children: title }),
|
|
497
|
+
body ? /* @__PURE__ */ jsx11("p", { className: "dt-lp-lead", children: body }) : null,
|
|
498
|
+
note ? /* @__PURE__ */ jsxs9("p", { className: "dt-lp-callout", children: [
|
|
499
|
+
/* @__PURE__ */ jsx11(Alert, { size: 20 }),
|
|
500
|
+
/* @__PURE__ */ jsxs9("span", { children: [
|
|
501
|
+
/* @__PURE__ */ jsx11("strong", { children: noteLabel }),
|
|
502
|
+
" ",
|
|
503
|
+
note
|
|
504
|
+
] })
|
|
505
|
+
] }) : null,
|
|
506
|
+
media ? /* @__PURE__ */ jsx11(InlineItems, { items }) : null,
|
|
507
|
+
/* @__PURE__ */ jsx11(Cta, { cta, className: "dt-lp-mt" })
|
|
508
|
+
] }, "text");
|
|
509
|
+
const side = media ? /* @__PURE__ */ jsx11(Media, { children: media }, "side") : /* @__PURE__ */ jsx11("ul", { className: "dt-lp-grid dt-lp-grid--chips", children: items.map(asItem).map((f) => /* @__PURE__ */ jsxs9("li", { className: "dt-lp-chip-card", children: [
|
|
510
|
+
renderIcon(f.icon, 22),
|
|
511
|
+
/* @__PURE__ */ jsx11("span", { children: f.title })
|
|
512
|
+
] }, f.title)) }, "side");
|
|
513
|
+
return shell(/* @__PURE__ */ jsx11(Pair, { className: "dt-lp-split dt-lp-split--wide", reverse, text, side }));
|
|
514
|
+
}
|
|
515
|
+
case "band": {
|
|
516
|
+
const { examples, examplesLabel = "Examples" } = props;
|
|
517
|
+
const text = /* @__PURE__ */ jsxs9("div", { children: [
|
|
518
|
+
/* @__PURE__ */ jsx11(SectionIntro, { id: hid, eyebrow, title, body }),
|
|
519
|
+
/* @__PURE__ */ jsx11(Chips, { items: examples, label: examplesLabel, className: "dt-lp-mt" }),
|
|
520
|
+
media ? /* @__PURE__ */ jsx11(InlineItems, { items }) : null,
|
|
521
|
+
/* @__PURE__ */ jsx11(Cta, { cta, className: "dt-lp-mt" })
|
|
522
|
+
] }, "text");
|
|
523
|
+
const side = media ? /* @__PURE__ */ jsx11(Media, { children: media }, "side") : /* @__PURE__ */ jsx11("ul", { className: "dt-lp-band-list", children: items.map(asItem).map((f) => /* @__PURE__ */ jsxs9("li", { children: [
|
|
524
|
+
renderIcon(f.icon, 22),
|
|
525
|
+
/* @__PURE__ */ jsx11("span", { children: f.title })
|
|
526
|
+
] }, f.title)) }, "side");
|
|
527
|
+
return shell(/* @__PURE__ */ jsx11(Pair, { className: "dt-lp-band", reverse, text, side }));
|
|
528
|
+
}
|
|
529
|
+
case "compare": {
|
|
530
|
+
const { columns = [] } = props;
|
|
531
|
+
return shell(
|
|
532
|
+
/* @__PURE__ */ jsxs9(Fragment3, { children: [
|
|
533
|
+
/* @__PURE__ */ jsx11(SectionIntro, { id: hid, eyebrow, title, body }),
|
|
534
|
+
/* @__PURE__ */ jsx11("div", { className: "dt-lp-compare", children: columns.map((col, i) => {
|
|
535
|
+
const cid = `${id || "compare"}-${i + 1}`;
|
|
536
|
+
const tone2 = col.tone || (i === 0 ? "good" : "check");
|
|
537
|
+
return /* @__PURE__ */ jsxs9("div", { className: "dt-lp-card dt-lp-card--compare", children: [
|
|
538
|
+
/* @__PURE__ */ jsx11("h3", { id: cid, className: "dt-lp-h3 dt-lp-h3--lg", children: col.title }),
|
|
539
|
+
/* @__PURE__ */ jsx11(Checklist, { items: col.items, tone: tone2, icon: tone2 === "good" ? Check : Help, labelledBy: cid })
|
|
540
|
+
] }, cid);
|
|
541
|
+
}) })
|
|
542
|
+
] })
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
case "links":
|
|
546
|
+
return shell(
|
|
547
|
+
/* @__PURE__ */ jsxs9(Fragment3, { children: [
|
|
548
|
+
/* @__PURE__ */ jsx11(SectionIntro, { id: hid, eyebrow, title, body }),
|
|
549
|
+
/* @__PURE__ */ jsx11("ul", { className: "dt-lp-grid dt-lp-grid--links", children: items.map((s) => /* @__PURE__ */ jsx11("li", { children: /* @__PURE__ */ jsxs9(SmartLink, { href: s.href, className: "dt-lp-linkcard", children: [
|
|
550
|
+
/* @__PURE__ */ jsxs9("span", { className: "dt-lp-linkcard-title", children: [
|
|
551
|
+
s.title,
|
|
552
|
+
" ",
|
|
553
|
+
/* @__PURE__ */ jsx11(ArrowRight, {})
|
|
554
|
+
] }),
|
|
555
|
+
s.body ? /* @__PURE__ */ jsx11("span", { className: "dt-lp-linkcard-body", children: s.body }) : null
|
|
556
|
+
] }) }, s.href)) })
|
|
557
|
+
] })
|
|
558
|
+
);
|
|
559
|
+
case "detail": {
|
|
560
|
+
return shell(
|
|
561
|
+
/* @__PURE__ */ jsxs9("div", { className: "dt-lp-detail", children: [
|
|
562
|
+
/* @__PURE__ */ jsx11("h2", { id: hid, className: "dt-lp-h2", children: title }),
|
|
563
|
+
/* @__PURE__ */ jsxs9("div", { children: [
|
|
564
|
+
body ? /* @__PURE__ */ jsx11("p", { className: "dt-lp-body", children: body }) : null,
|
|
565
|
+
(bullets == null ? void 0 : bullets.length) ? /* @__PURE__ */ jsx11(Checklist, { items: bullets }) : null
|
|
566
|
+
] })
|
|
567
|
+
] })
|
|
568
|
+
);
|
|
569
|
+
}
|
|
570
|
+
default:
|
|
571
|
+
return shell(
|
|
572
|
+
/* @__PURE__ */ jsxs9(Fragment3, { children: [
|
|
573
|
+
/* @__PURE__ */ jsx11(SectionIntro, { id: hid, eyebrow, title, body }),
|
|
574
|
+
/* @__PURE__ */ jsx11(Items, { items, kind: "cards" }),
|
|
575
|
+
footnote ? /* @__PURE__ */ jsx11("p", { className: "dt-lp-footnote", children: footnote }) : null,
|
|
576
|
+
/* @__PURE__ */ jsx11(Cta, { cta, className: "dt-lp-mt" })
|
|
577
|
+
] })
|
|
578
|
+
);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
// src/Audiences.jsx
|
|
583
|
+
import { jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
584
|
+
function Audiences({ id = "audiences", eyebrow, title, body, items = [], linkLabel = "See how it works", tone = "muted" }) {
|
|
585
|
+
const hid = `${id}-title`;
|
|
586
|
+
return /* @__PURE__ */ jsxs10(Section, { id, labelledBy: hid, tone, className: "dt-lp-audiences", children: [
|
|
587
|
+
/* @__PURE__ */ jsx12(SectionIntro, { id: hid, eyebrow, title, body, align: "center" }),
|
|
588
|
+
/* @__PURE__ */ jsx12("div", { className: `dt-lp-grid dt-lp-grid--audiences dt-lp-grid--n${Math.min(items.length, 4)}`, children: items.map((a, i) => {
|
|
589
|
+
var _a;
|
|
590
|
+
const aid = a.id || `${id}-${i + 1}`;
|
|
591
|
+
return /* @__PURE__ */ jsxs10("article", { id: aid, "aria-labelledby": `${aid}-title`, className: "dt-lp-card dt-lp-card--audience", children: [
|
|
592
|
+
a.icon ? /* @__PURE__ */ jsx12("span", { className: "dt-lp-audience-icon", children: renderIcon(a.icon, 30) }) : null,
|
|
593
|
+
/* @__PURE__ */ jsxs10("div", { className: a.media ? "dt-lp-audience-head" : void 0, children: [
|
|
594
|
+
/* @__PURE__ */ jsxs10("div", { children: [
|
|
595
|
+
a.keyword ? /* @__PURE__ */ jsx12("p", { className: "dt-lp-kicker", children: a.keyword }) : null,
|
|
596
|
+
/* @__PURE__ */ jsx12("h3", { id: `${aid}-title`, className: "dt-lp-h3 dt-lp-h3--lg", children: a.title }),
|
|
597
|
+
/* @__PURE__ */ jsx12("p", { className: a.media || a.features ? void 0 : "dt-lp-grow", children: a.body })
|
|
598
|
+
] }),
|
|
599
|
+
a.media ? /* @__PURE__ */ jsx12("div", { className: "dt-lp-audience-media", "aria-hidden": "true", children: a.media }) : null
|
|
600
|
+
] }),
|
|
601
|
+
((_a = a.features) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsx12("ul", { className: "dt-lp-audience-features dt-lp-grow", children: a.features.map((f) => {
|
|
602
|
+
const it = typeof f === "string" ? { title: f } : f;
|
|
603
|
+
return /* @__PURE__ */ jsxs10("li", { children: [
|
|
604
|
+
it.icon ? renderIcon(it.icon, 22) : null,
|
|
605
|
+
/* @__PURE__ */ jsx12("span", { children: it.title })
|
|
606
|
+
] }, it.title);
|
|
607
|
+
}) }) : null,
|
|
608
|
+
a.href ? /* @__PURE__ */ jsx12(TextLink, { href: a.href, "aria-label": `${a.keyword || a.title}: ${(a.linkLabel || linkLabel).toLowerCase()}`, children: a.linkLabel || linkLabel }) : null
|
|
609
|
+
] }, aid);
|
|
610
|
+
}) })
|
|
611
|
+
] });
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
// src/HowItWorks.jsx
|
|
615
|
+
import { jsx as jsx13, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
616
|
+
function HowItWorks({ id = "how-it-works", eyebrow, title, body, steps, items, tone = "plain", cta }) {
|
|
617
|
+
const list = steps || items || [];
|
|
618
|
+
const hid = `${id}-title`;
|
|
619
|
+
return /* @__PURE__ */ jsxs11(Section, { id, labelledBy: hid, tone, className: "dt-lp-steps", children: [
|
|
620
|
+
/* @__PURE__ */ jsx13(SectionIntro, { id: hid, eyebrow, title, body }),
|
|
621
|
+
/* @__PURE__ */ jsx13("ol", { className: "dt-lp-grid dt-lp-grid--steps", children: list.map((st, i) => /* @__PURE__ */ jsxs11("li", { className: "dt-lp-card", children: [
|
|
622
|
+
/* @__PURE__ */ jsx13("span", { className: "dt-lp-step-num", "aria-hidden": "true", children: i + 1 }),
|
|
623
|
+
/* @__PURE__ */ jsx13("h3", { className: "dt-lp-h3", children: st.name || st.title }),
|
|
624
|
+
/* @__PURE__ */ jsx13("p", { children: st.text || st.body })
|
|
625
|
+
] }, st.name || st.title)) }),
|
|
626
|
+
/* @__PURE__ */ jsx13(Cta, { cta, className: "dt-lp-mt" })
|
|
627
|
+
] });
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
// src/Faq.jsx
|
|
631
|
+
import { jsx as jsx14, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
632
|
+
function Faq({ id = "faq", eyebrow, title = "Frequently asked questions", intro, items = [], openFirst = true, tone = "muted" }) {
|
|
633
|
+
const hid = `${id}-title`;
|
|
634
|
+
return /* @__PURE__ */ jsxs12(Section, { id, labelledBy: hid, tone, narrow: true, className: "dt-lp-faq", children: [
|
|
635
|
+
/* @__PURE__ */ jsx14(SectionIntro, { id: hid, eyebrow, title, body: intro, align: "center" }),
|
|
636
|
+
/* @__PURE__ */ jsx14("div", { className: "dt-lp-faq-list", children: items.map((f, i) => /* @__PURE__ */ jsxs12("details", { className: "dt-lp-faq-item", open: openFirst && i === 0, children: [
|
|
637
|
+
/* @__PURE__ */ jsxs12("summary", { children: [
|
|
638
|
+
/* @__PURE__ */ jsx14("h3", { className: "dt-lp-h3", children: f.q }),
|
|
639
|
+
/* @__PURE__ */ jsx14(ChevronRight, { size: 18, className: "dt-lp-icon dt-lp-faq-chevron" })
|
|
640
|
+
] }),
|
|
641
|
+
/* @__PURE__ */ jsx14("p", { children: f.a })
|
|
642
|
+
] }, f.q)) })
|
|
643
|
+
] });
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// src/DemoCta.jsx
|
|
647
|
+
import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
648
|
+
function DemoCta({ id = "demo", eyebrow, title, body, label = "Book a demo", chips, chipsLabel = "Business types", note, link }) {
|
|
649
|
+
return /* @__PURE__ */ jsx15("section", { id, "aria-labelledby": `${id}-title`, className: "dt-lp-section dt-lp-cta", children: /* @__PURE__ */ jsx15(Wrap, { children: /* @__PURE__ */ jsxs13("div", { className: "dt-lp-cta-panel", children: [
|
|
650
|
+
eyebrow ? /* @__PURE__ */ jsx15("p", { className: "dt-lp-eyebrow dt-lp-eyebrow--inverse", children: eyebrow }) : null,
|
|
651
|
+
/* @__PURE__ */ jsx15("h2", { id: `${id}-title`, className: "dt-lp-h2 dt-lp-h2--cta", children: title }),
|
|
652
|
+
body ? /* @__PURE__ */ jsx15("p", { className: "dt-lp-cta-body", children: body }) : null,
|
|
653
|
+
/* @__PURE__ */ jsx15(BookDemoButton, { size: "lg", variant: "inverse", children: label }),
|
|
654
|
+
(chips == null ? void 0 : chips.length) ? /* @__PURE__ */ jsx15("ul", { className: "dt-lp-chips dt-lp-chips--inverse", "aria-label": chipsLabel, children: chips.map((k) => /* @__PURE__ */ jsx15("li", { children: k }, k)) }) : null,
|
|
655
|
+
note ? /* @__PURE__ */ jsxs13("div", { className: "dt-lp-cta-note", children: [
|
|
656
|
+
note.title ? /* @__PURE__ */ jsx15("h3", { className: "dt-lp-h3", children: note.title }) : null,
|
|
657
|
+
note.body ? /* @__PURE__ */ jsx15("p", { children: note.body }) : null
|
|
658
|
+
] }) : null,
|
|
659
|
+
link ? /* @__PURE__ */ jsx15("p", { className: "dt-lp-cta-link", children: /* @__PURE__ */ jsx15(SmartLink, { href: link.href, reload: link.reload, children: link.label }) }) : null
|
|
660
|
+
] }) }) });
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
// src/LandingPage.jsx
|
|
664
|
+
import { jsx as jsx16, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
665
|
+
var BLOCKS = { audiences: Audiences, steps: HowItWorks, faq: Faq, cta: DemoCta };
|
|
666
|
+
var TAIL = ["audiences", "steps", "faq", "cta"];
|
|
667
|
+
function LandingPage({ brand, content, preview = null, slots = {}, linkComponent, onBookDemo, home = true, className }) {
|
|
668
|
+
if (!content || !content.hero) {
|
|
669
|
+
throw new Error('landing-kit: "content.hero" is missing. LandingPage needs at least { hero: { title } }; see README "Content".');
|
|
670
|
+
}
|
|
671
|
+
const { nav = [], login, hero, sections = [], footer, header = {} } = content;
|
|
672
|
+
const used = new Set(sections.filter((s) => s && s.use).map((s) => s.use));
|
|
673
|
+
const previewInline = used.has("preview");
|
|
674
|
+
const render = (s, i) => {
|
|
675
|
+
var _a;
|
|
676
|
+
if (!s) return null;
|
|
677
|
+
if (isValidElement2(s)) return cloneElement(s, { key: (_a = s.key) != null ? _a : `el-${i}` });
|
|
678
|
+
if (s.use === "preview") return preview ? /* @__PURE__ */ jsx16("div", { children: preview }, "preview") : null;
|
|
679
|
+
if (s.use) {
|
|
680
|
+
if (slots && Object.prototype.hasOwnProperty.call(slots, s.use)) {
|
|
681
|
+
const node = slots[s.use];
|
|
682
|
+
return node ? /* @__PURE__ */ jsx16(Fragment4, { children: node }, `slot-${s.use}`) : null;
|
|
683
|
+
}
|
|
684
|
+
const Block = BLOCKS[s.use];
|
|
685
|
+
if (!Block) {
|
|
686
|
+
const known = ["preview", ...TAIL, ...Object.keys(slots || {})].join(", ");
|
|
687
|
+
throw new Error(`landing-kit: unknown section use "${s.use}" (known: ${known}). Pass custom sections as <LandingPage slots={{ ${s.use}: <YourSection /> }} />.`);
|
|
688
|
+
}
|
|
689
|
+
return content[s.use] ? /* @__PURE__ */ jsx16(Block, { ...content[s.use] }, s.use) : null;
|
|
690
|
+
}
|
|
691
|
+
return /* @__PURE__ */ jsx16(FeatureSection, { ...s }, s.id || `section-${i}`);
|
|
692
|
+
};
|
|
693
|
+
return /* @__PURE__ */ jsxs14(
|
|
694
|
+
MarketingLayout,
|
|
695
|
+
{
|
|
696
|
+
brand,
|
|
697
|
+
nav,
|
|
698
|
+
login,
|
|
699
|
+
cta: header.cta,
|
|
700
|
+
footer,
|
|
701
|
+
home,
|
|
702
|
+
linkComponent,
|
|
703
|
+
onBookDemo,
|
|
704
|
+
className,
|
|
705
|
+
children: [
|
|
706
|
+
/* @__PURE__ */ jsx16(Hero, { ...hero, overlap: !!preview && !previewInline }),
|
|
707
|
+
preview && !previewInline ? preview : null,
|
|
708
|
+
sections.map(render),
|
|
709
|
+
TAIL.filter((k) => !used.has(k) && content[k]).map((k) => {
|
|
710
|
+
const Block = BLOCKS[k];
|
|
711
|
+
return /* @__PURE__ */ jsx16(Block, { ...content[k] }, k);
|
|
712
|
+
})
|
|
713
|
+
]
|
|
714
|
+
}
|
|
715
|
+
);
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// src/PreviewFrame.jsx
|
|
719
|
+
import { jsx as jsx17, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
720
|
+
function PreviewFrame({
|
|
721
|
+
id = "product",
|
|
722
|
+
heading,
|
|
723
|
+
caption,
|
|
724
|
+
meta,
|
|
725
|
+
badge = "Demo data",
|
|
726
|
+
brand: own,
|
|
727
|
+
children
|
|
728
|
+
}) {
|
|
729
|
+
const ctx = useLanding();
|
|
730
|
+
const brand = own || ctx.brand;
|
|
731
|
+
return /* @__PURE__ */ jsxs15("section", { id, "aria-labelledby": `${id}-title`, className: "dt-lp-preview", children: [
|
|
732
|
+
/* @__PURE__ */ jsx17("h2", { id: `${id}-title`, className: "dt-lp-sr-only", children: heading || `${brand ? brand.name : "Product"} overview` }),
|
|
733
|
+
/* @__PURE__ */ jsx17(Wrap, { children: /* @__PURE__ */ jsxs15("figure", { className: "dt-lp-preview-frame", children: [
|
|
734
|
+
/* @__PURE__ */ jsxs15("div", { className: "dt-lp-preview-bar", children: [
|
|
735
|
+
/* @__PURE__ */ jsxs15("div", { className: "dt-lp-preview-title", children: [
|
|
736
|
+
brand ? /* @__PURE__ */ jsx17(Wordmark, { name: brand.name }) : null,
|
|
737
|
+
meta ? /* @__PURE__ */ jsx17("span", { className: "dt-lp-preview-meta", children: meta }) : null
|
|
738
|
+
] }),
|
|
739
|
+
badge ? /* @__PURE__ */ jsx17("span", { className: "dt-lp-preview-badge", children: badge }) : null
|
|
740
|
+
] }),
|
|
741
|
+
/* @__PURE__ */ jsx17("div", { className: "dt-lp-preview-body", children }),
|
|
742
|
+
caption ? /* @__PURE__ */ jsx17("figcaption", { className: "dt-lp-sr-only", children: caption }) : null
|
|
743
|
+
] }) })
|
|
744
|
+
] });
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// src/DemoDialog.jsx
|
|
748
|
+
import { useEffect, useRef, useState as useState2 } from "react";
|
|
749
|
+
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
750
|
+
var DEFAULT_DEMO_FIELDS = [
|
|
751
|
+
{ name: "name", label: "Your name", required: true, maxLength: 120, autoComplete: "name" },
|
|
752
|
+
{ name: "phone", label: "Mobile", type: "tel", required: true, maxLength: 20, autoComplete: "tel", inputMode: "tel" },
|
|
753
|
+
{ name: "email", label: "Email", type: "email", maxLength: 190, autoComplete: "email" },
|
|
754
|
+
{ name: "company", label: "Business name", maxLength: 160, autoComplete: "organization" }
|
|
755
|
+
];
|
|
756
|
+
var initial = (fields) => Object.fromEntries(fields.map((f) => [f.name, ""]));
|
|
757
|
+
function Field({ f, value, onChange, error }) {
|
|
758
|
+
const id = `dt-demo-${f.name}`;
|
|
759
|
+
const errId = `${id}-error`;
|
|
760
|
+
const common = {
|
|
761
|
+
id,
|
|
762
|
+
name: f.name,
|
|
763
|
+
value,
|
|
764
|
+
onChange,
|
|
765
|
+
required: !!f.required,
|
|
766
|
+
className: "dt-lp-input",
|
|
767
|
+
...error ? { "aria-invalid": "true", "aria-describedby": errId } : {}
|
|
768
|
+
};
|
|
769
|
+
let control;
|
|
770
|
+
if (f.type === "select") {
|
|
771
|
+
control = /* @__PURE__ */ jsxs16("select", { ...common, children: [
|
|
772
|
+
/* @__PURE__ */ jsx18("option", { value: "", children: f.placeholder || "Choose one" }),
|
|
773
|
+
(f.options || []).map((o) => /* @__PURE__ */ jsx18("option", { value: o.value, children: o.label }, o.value))
|
|
774
|
+
] });
|
|
775
|
+
} else if (f.type === "textarea") {
|
|
776
|
+
control = /* @__PURE__ */ jsx18("textarea", { ...common, rows: f.rows || 3, maxLength: f.maxLength });
|
|
777
|
+
} else {
|
|
778
|
+
control = /* @__PURE__ */ jsx18(
|
|
779
|
+
"input",
|
|
780
|
+
{
|
|
781
|
+
...common,
|
|
782
|
+
type: f.type || "text",
|
|
783
|
+
maxLength: f.maxLength,
|
|
784
|
+
min: f.min,
|
|
785
|
+
inputMode: f.inputMode,
|
|
786
|
+
autoComplete: f.autoComplete,
|
|
787
|
+
placeholder: f.placeholder
|
|
788
|
+
}
|
|
789
|
+
);
|
|
790
|
+
}
|
|
791
|
+
return /* @__PURE__ */ jsxs16("label", { htmlFor: id, className: `dt-lp-field${f.wide || f.type === "textarea" ? " dt-lp-field--wide" : ""}`, children: [
|
|
792
|
+
/* @__PURE__ */ jsxs16("span", { children: [
|
|
793
|
+
f.label,
|
|
794
|
+
f.required ? " *" : ""
|
|
795
|
+
] }),
|
|
796
|
+
control,
|
|
797
|
+
error ? /* @__PURE__ */ jsx18("span", { id: errId, className: "dt-lp-field-error", children: error }) : null
|
|
798
|
+
] });
|
|
799
|
+
}
|
|
800
|
+
function DemoDialog({
|
|
801
|
+
brand,
|
|
802
|
+
open = true,
|
|
803
|
+
onClose = () => {
|
|
804
|
+
},
|
|
805
|
+
onSubmit,
|
|
806
|
+
fields = DEFAULT_DEMO_FIELDS,
|
|
807
|
+
title,
|
|
808
|
+
intro = "Tell us a little about your business and we will walk you through the workflows that matter to your team.",
|
|
809
|
+
fiduciary = "Dreamtree-Org",
|
|
810
|
+
consentText,
|
|
811
|
+
privacyHref = "/privacy",
|
|
812
|
+
policyVersion,
|
|
813
|
+
submitLabel = "Request my demo",
|
|
814
|
+
successMessage,
|
|
815
|
+
validate
|
|
816
|
+
}) {
|
|
817
|
+
const ref = useRef(null);
|
|
818
|
+
const [form, setForm] = useState2(() => initial(fields));
|
|
819
|
+
const [website, setWebsite] = useState2("");
|
|
820
|
+
const [consent, setConsent] = useState2(false);
|
|
821
|
+
const [busy, setBusy] = useState2(false);
|
|
822
|
+
const [err, setErr] = useState2("");
|
|
823
|
+
const [fieldErrors, setFieldErrors] = useState2({});
|
|
824
|
+
const [sent, setSent] = useState2(false);
|
|
825
|
+
const name = brand ? brand.name : "a";
|
|
826
|
+
useEffect(() => {
|
|
827
|
+
const dlg = ref.current;
|
|
828
|
+
if (open && dlg && !dlg.open && typeof dlg.showModal === "function") dlg.showModal();
|
|
829
|
+
}, [open]);
|
|
830
|
+
if (!open) return null;
|
|
831
|
+
if (typeof onSubmit !== "function") {
|
|
832
|
+
throw new Error('landing-kit DemoDialog: "onSubmit" is missing. Pass async (data) => { /* POST the demo request */ }.');
|
|
833
|
+
}
|
|
834
|
+
const set = (k) => (e) => {
|
|
835
|
+
setForm((f) => ({ ...f, [k]: e.target.value }));
|
|
836
|
+
if (fieldErrors[k]) setFieldErrors(({ [k]: _gone, ...rest }) => rest);
|
|
837
|
+
};
|
|
838
|
+
const ready = consent && (typeof validate === "function" || fields.every((f) => !f.required || String(form[f.name] || "").trim()));
|
|
839
|
+
const submit = async (e) => {
|
|
840
|
+
e.preventDefault();
|
|
841
|
+
if (!ready || busy) return;
|
|
842
|
+
setErr("");
|
|
843
|
+
if (typeof validate === "function") {
|
|
844
|
+
const found = validate(form) || {};
|
|
845
|
+
setFieldErrors(found);
|
|
846
|
+
if (Object.keys(found).length) return;
|
|
847
|
+
}
|
|
848
|
+
setBusy(true);
|
|
849
|
+
try {
|
|
850
|
+
await onSubmit({ ...form, website, consent: true, source_path: typeof window === "undefined" ? "/" : window.location.pathname });
|
|
851
|
+
setSent(true);
|
|
852
|
+
} catch (ex) {
|
|
853
|
+
if (ex && ex.fields && typeof ex.fields === "object") setFieldErrors(ex.fields);
|
|
854
|
+
setErr(ex && ex.message || "Could not send your request. Please try again.");
|
|
855
|
+
} finally {
|
|
856
|
+
setBusy(false);
|
|
857
|
+
}
|
|
858
|
+
};
|
|
859
|
+
const first = String(form.name || "").trim().split(/\s+/)[0] || "there";
|
|
860
|
+
const thanks = typeof successMessage === "function" ? successMessage(form) : successMessage || `Thanks, ${first}. We have your request. Someone from the ${name} team will call you within one working day to fix a time.`;
|
|
861
|
+
return /* @__PURE__ */ jsxs16(
|
|
862
|
+
"dialog",
|
|
863
|
+
{
|
|
864
|
+
ref,
|
|
865
|
+
className: "dt-lp-dialog",
|
|
866
|
+
style: brand ? brandStyle(brand) : void 0,
|
|
867
|
+
"aria-labelledby": "dt-demo-title",
|
|
868
|
+
onClose,
|
|
869
|
+
onCancel: (e) => {
|
|
870
|
+
e.preventDefault();
|
|
871
|
+
onClose();
|
|
872
|
+
},
|
|
873
|
+
children: [
|
|
874
|
+
/* @__PURE__ */ jsxs16("div", { className: "dt-lp-dialog-head", children: [
|
|
875
|
+
/* @__PURE__ */ jsx18("h2", { id: "dt-demo-title", children: sent ? "Thank you" : title || `Book a ${name} demo` }),
|
|
876
|
+
/* @__PURE__ */ jsx18("button", { type: "button", className: "dt-lp-dialog-x", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ jsx18(Close, { size: 18 }) })
|
|
877
|
+
] }),
|
|
878
|
+
/* @__PURE__ */ jsx18("div", { className: "dt-lp-dialog-body", children: sent ? /* @__PURE__ */ jsxs16("div", { className: "dt-lp-stack", children: [
|
|
879
|
+
/* @__PURE__ */ jsx18("p", { role: "status", children: thanks }),
|
|
880
|
+
/* @__PURE__ */ jsx18("button", { type: "button", className: "dt-lp-btn dt-lp-btn--outline dt-lp-btn--md", onClick: onClose, children: "Close" })
|
|
881
|
+
] }) : /* @__PURE__ */ jsxs16("form", { className: "dt-lp-stack", onSubmit: submit, noValidate: true, children: [
|
|
882
|
+
intro ? /* @__PURE__ */ jsx18("p", { className: "dt-lp-muted", children: intro }) : null,
|
|
883
|
+
err ? /* @__PURE__ */ jsx18("p", { role: "alert", className: "dt-lp-error", children: err }) : null,
|
|
884
|
+
/* @__PURE__ */ jsx18("div", { className: "dt-lp-fields", children: fields.map((f) => /* @__PURE__ */ jsx18(Field, { f, value: form[f.name], onChange: set(f.name), error: fieldErrors[f.name] }, f.name)) }),
|
|
885
|
+
/* @__PURE__ */ jsx18("div", { "aria-hidden": "true", className: "dt-lp-honeypot", children: /* @__PURE__ */ jsxs16("label", { children: [
|
|
886
|
+
"Website",
|
|
887
|
+
/* @__PURE__ */ jsx18("input", { type: "text", name: "website", tabIndex: -1, autoComplete: "off", value: website, onChange: (e) => setWebsite(e.target.value) })
|
|
888
|
+
] }) }),
|
|
889
|
+
/* @__PURE__ */ jsxs16("label", { className: "dt-lp-consent", children: [
|
|
890
|
+
/* @__PURE__ */ jsx18("input", { type: "checkbox", checked: consent, onChange: (e) => setConsent(e.target.checked) }),
|
|
891
|
+
/* @__PURE__ */ jsx18("span", { children: consentText || `I agree that ${fiduciary} may call, message or email me about this demo.` })
|
|
892
|
+
] }),
|
|
893
|
+
privacyHref ? /* @__PURE__ */ jsxs16("p", { className: "dt-lp-fineprint", children: [
|
|
894
|
+
"Used only to arrange your demo. See the ",
|
|
895
|
+
/* @__PURE__ */ jsx18("a", { href: privacyHref, children: "privacy policy" }),
|
|
896
|
+
policyVersion ? ` (v${policyVersion})` : "",
|
|
897
|
+
"."
|
|
898
|
+
] }) : null,
|
|
899
|
+
/* @__PURE__ */ jsxs16("button", { type: "submit", className: "dt-lp-btn dt-lp-btn--primary dt-lp-btn--md", disabled: !ready || busy, "aria-busy": busy ? "true" : void 0, children: [
|
|
900
|
+
/* @__PURE__ */ jsx18(Calendar, { size: 16 }),
|
|
901
|
+
busy ? "Sending\u2026" : submitLabel
|
|
902
|
+
] })
|
|
903
|
+
] }) })
|
|
904
|
+
]
|
|
905
|
+
}
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// src/PageHero.jsx
|
|
910
|
+
import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
911
|
+
function Breadcrumbs({ items = [] }) {
|
|
912
|
+
if (!items.length) return null;
|
|
913
|
+
return /* @__PURE__ */ jsx19("nav", { "aria-label": "Breadcrumb", className: "dt-lp-crumbs", children: /* @__PURE__ */ jsx19("ol", { children: items.map((c, i) => {
|
|
914
|
+
const last = i === items.length - 1;
|
|
915
|
+
return /* @__PURE__ */ jsxs17("li", { children: [
|
|
916
|
+
i > 0 ? /* @__PURE__ */ jsx19(ChevronRight, { size: 14 }) : null,
|
|
917
|
+
last || !c.href ? /* @__PURE__ */ jsx19("span", { "aria-current": last ? "page" : void 0, children: c.label }) : /* @__PURE__ */ jsx19(SmartLink, { href: c.href, children: c.label })
|
|
918
|
+
] }, `${c.label}-${i}`);
|
|
919
|
+
}) }) });
|
|
920
|
+
}
|
|
921
|
+
function PageHero({ breadcrumbs, eyebrow, title, lead, cta = "Book a demo", secondary }) {
|
|
922
|
+
return /* @__PURE__ */ jsx19("section", { "aria-labelledby": "hero-title", className: "dt-lp-hero dt-lp-hero--page", children: /* @__PURE__ */ jsxs17(Wrap, { className: "dt-lp-hero-inner dt-lp-hero-inner--start", children: [
|
|
923
|
+
/* @__PURE__ */ jsx19(Breadcrumbs, { items: breadcrumbs }),
|
|
924
|
+
/* @__PURE__ */ jsx19(Eyebrow, { className: "dt-lp-mt-lg", children: eyebrow }),
|
|
925
|
+
/* @__PURE__ */ jsx19("h1", { id: "hero-title", className: "dt-lp-h1 dt-lp-h1--page", children: title }),
|
|
926
|
+
lead ? /* @__PURE__ */ jsx19("p", { id: "answer", className: "dt-lp-hero-lead", children: lead }) : null,
|
|
927
|
+
/* @__PURE__ */ jsxs17("div", { className: "dt-lp-actions dt-lp-actions--start", children: [
|
|
928
|
+
cta ? /* @__PURE__ */ jsx19(BookDemoButton, { size: "lg", children: cta }) : null,
|
|
929
|
+
secondary ? /* @__PURE__ */ jsx19(TextLink, { href: secondary.href, children: secondary.label }) : null
|
|
930
|
+
] })
|
|
931
|
+
] }) });
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
// src/island.jsx
|
|
935
|
+
import { createRoot } from "react-dom/client";
|
|
936
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
937
|
+
function createDemoIsland(props) {
|
|
938
|
+
let root;
|
|
939
|
+
let returnTo = null;
|
|
940
|
+
const close = () => {
|
|
941
|
+
root.render(null);
|
|
942
|
+
const target = returnTo;
|
|
943
|
+
if (target) setTimeout(() => target.focus(), 0);
|
|
944
|
+
};
|
|
945
|
+
return {
|
|
946
|
+
openDemo(trigger) {
|
|
947
|
+
returnTo = trigger || null;
|
|
948
|
+
if (!root) {
|
|
949
|
+
const host = document.createElement("div");
|
|
950
|
+
host.id = "demo-dialog-root";
|
|
951
|
+
document.body.appendChild(host);
|
|
952
|
+
root = createRoot(host);
|
|
953
|
+
}
|
|
954
|
+
const p = typeof props === "function" ? props() : props;
|
|
955
|
+
root.render(/* @__PURE__ */ jsx20(DemoDialog, { ...p, onClose: close }, Date.now()));
|
|
956
|
+
},
|
|
957
|
+
close
|
|
958
|
+
};
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
// src/brands.js
|
|
962
|
+
var brands = {
|
|
963
|
+
billpro: {
|
|
964
|
+
id: "billpro",
|
|
965
|
+
name: "BillPro",
|
|
966
|
+
primary: "#15803d",
|
|
967
|
+
// current #19a249, darkened one step for AA contrast on white
|
|
968
|
+
accent: "#4ade80",
|
|
969
|
+
logoSrc: "/brand/billpro-mark.svg",
|
|
970
|
+
headline: "Billing, inventory and GST \u2014 done right, every day.",
|
|
971
|
+
pitch: "GST invoices, stock, purchases and accounts for growing Indian businesses.",
|
|
972
|
+
points: ["GST-ready invoices and returns", "Live inventory across branches", "Payments, ledgers and reports"],
|
|
973
|
+
category: "Billing & Inventory \xB7 by Dreamtree-Org"
|
|
974
|
+
},
|
|
975
|
+
taskpro: {
|
|
976
|
+
id: "taskpro",
|
|
977
|
+
name: "TaskPro",
|
|
978
|
+
primary: "#065f46",
|
|
979
|
+
accent: "#34d399",
|
|
980
|
+
logoSrc: "/taskpro-mark-48.webp",
|
|
981
|
+
headline: "Projects and workflows, shaped the way your team works.",
|
|
982
|
+
pitch: "Configurable project types, statuses and automations \u2014 one place for every task.",
|
|
983
|
+
points: ["Your own workflows and statuses", "Boards, timelines and my-work", "Automations and audit trail"],
|
|
984
|
+
category: "Project & Workflow Management \xB7 by Dreamtree-Org"
|
|
985
|
+
},
|
|
986
|
+
venturepro: {
|
|
987
|
+
id: "venturepro",
|
|
988
|
+
name: "VenturePro",
|
|
989
|
+
primary: "#1e3a6e",
|
|
990
|
+
accent: "#e5ad42",
|
|
991
|
+
// accent-400, as shipped
|
|
992
|
+
panel: "#182e57",
|
|
993
|
+
// primary-700, as shipped
|
|
994
|
+
logoSrc: "/brand/venturepro-mark.svg",
|
|
995
|
+
headline: "Every venture, block and flat \u2014 in one place.",
|
|
996
|
+
pitch: "Create ventures, lay out blocks and units, track sales, rentals and collections across your whole portfolio.",
|
|
997
|
+
points: [],
|
|
998
|
+
category: "Builder Property & Apartment Management System"
|
|
999
|
+
},
|
|
1000
|
+
campaignpro: {
|
|
1001
|
+
id: "campaignpro",
|
|
1002
|
+
name: "CampaignPro",
|
|
1003
|
+
primary: "#6d28d9",
|
|
1004
|
+
// PROPOSED — was the same red as firepro
|
|
1005
|
+
accent: "#a78bfa",
|
|
1006
|
+
headline: "Run every campaign from one pipeline.",
|
|
1007
|
+
pitch: "Plan, send and track campaigns across channels with your whole team.",
|
|
1008
|
+
points: ["Multi-channel campaigns", "Pipeline and follow-ups", "Team roles and approvals"],
|
|
1009
|
+
category: "Campaign Management \xB7 by Dreamtree-Org"
|
|
1010
|
+
},
|
|
1011
|
+
firepro: {
|
|
1012
|
+
id: "firepro",
|
|
1013
|
+
name: "FirePro",
|
|
1014
|
+
primary: "#b42318",
|
|
1015
|
+
// keeps the red — it is the fire-safety product
|
|
1016
|
+
accent: "#fb923c",
|
|
1017
|
+
headline: "Fire safety compliance, inspections and service \u2014 on schedule.",
|
|
1018
|
+
pitch: "Assets, inspections, service jobs and certificates for fire-safety teams.",
|
|
1019
|
+
points: ["Scheduled inspections", "Asset and site registers", "Certificates and reports"],
|
|
1020
|
+
category: "Fire Safety Operations \xB7 by Dreamtree-Org"
|
|
1021
|
+
},
|
|
1022
|
+
procurementpro: {
|
|
1023
|
+
id: "procurementpro",
|
|
1024
|
+
name: "ProcurementPro",
|
|
1025
|
+
primary: "#1d4ed8",
|
|
1026
|
+
// current #2563eb, one step darker for panel contrast
|
|
1027
|
+
accent: "#60a5fa",
|
|
1028
|
+
headline: "From request to purchase order, without the chase.",
|
|
1029
|
+
pitch: "RFQs, quotations, approvals and purchase orders in one audited flow.",
|
|
1030
|
+
points: ["RFQs and quotation comparison", "Approval workflows", "Purchase orders and vendors"],
|
|
1031
|
+
category: "Procurement \xB7 by Dreamtree-Org"
|
|
1032
|
+
},
|
|
1033
|
+
fitweavepro: {
|
|
1034
|
+
id: "fitweavepro",
|
|
1035
|
+
name: "FitWeavePro",
|
|
1036
|
+
primary: "#be185d",
|
|
1037
|
+
// PROPOSED — was Tailwind blue
|
|
1038
|
+
accent: "#f9a8d4",
|
|
1039
|
+
headline: "Made-to-measure, made simple.",
|
|
1040
|
+
pitch: "Measurements, patterns and orders for tailoring shops.",
|
|
1041
|
+
points: ["Customer measurements", "Pattern and cutting plans", "Orders and deliveries"],
|
|
1042
|
+
category: "Tailoring Shop Management \xB7 by Dreamtree-Org"
|
|
1043
|
+
},
|
|
1044
|
+
aiagentbuilder: {
|
|
1045
|
+
id: "aiagentbuilder",
|
|
1046
|
+
name: "AI Agent Builder",
|
|
1047
|
+
primary: "#0f766e",
|
|
1048
|
+
// PROPOSED — was blue, same as procurementpro
|
|
1049
|
+
accent: "#5eead4",
|
|
1050
|
+
headline: "Build, approve and ship AI agents your team can trust.",
|
|
1051
|
+
pitch: "Multi-provider agents with approvals, knowledge bases, voice and an MCP server.",
|
|
1052
|
+
points: ["Human-in-the-loop approvals", "Knowledge bases (RAG)", "Voice calls and campaigns"],
|
|
1053
|
+
category: "AI Agent Platform \xB7 by Dreamtree-Org"
|
|
1054
|
+
},
|
|
1055
|
+
runloompro: {
|
|
1056
|
+
id: "runloompro",
|
|
1057
|
+
name: "RunLoom",
|
|
1058
|
+
primary: "#4f46e5",
|
|
1059
|
+
accent: "#a5b4fc",
|
|
1060
|
+
headline: "Missions, run reliably.",
|
|
1061
|
+
pitch: "Orchestrate long-running work across workers with full telemetry.",
|
|
1062
|
+
points: ["Durable missions", "Node and Python workers", "Telemetry built in"],
|
|
1063
|
+
category: "by Dreamtree-Org"
|
|
1064
|
+
},
|
|
1065
|
+
appforge: {
|
|
1066
|
+
id: "appforge",
|
|
1067
|
+
name: "AppForge",
|
|
1068
|
+
primary: "#1f3864",
|
|
1069
|
+
accent: "#2563eb",
|
|
1070
|
+
headline: "Design, build and publish business apps.",
|
|
1071
|
+
pitch: "Schema-driven apps with policy, review and one-click release.",
|
|
1072
|
+
points: ["Visual builder", "Policies and RBAC", "Review and publish"],
|
|
1073
|
+
category: "by Dreamtree-Org"
|
|
1074
|
+
}
|
|
1075
|
+
};
|
|
1076
|
+
function getBrand(id) {
|
|
1077
|
+
const b = brands[id];
|
|
1078
|
+
if (!b) throw new Error(`landing-kit: unknown brand "${id}" (known: ${Object.keys(brands).join(", ")})`);
|
|
1079
|
+
return b;
|
|
1080
|
+
}
|
|
1081
|
+
export {
|
|
1082
|
+
Audiences,
|
|
1083
|
+
AuthShell,
|
|
1084
|
+
BookDemoButton,
|
|
1085
|
+
BrandLockup,
|
|
1086
|
+
BrandMark2 as BrandMark,
|
|
1087
|
+
Breadcrumbs,
|
|
1088
|
+
Cta,
|
|
1089
|
+
DEFAULT_DEMO_FIELDS,
|
|
1090
|
+
DemoCta,
|
|
1091
|
+
DemoDialog,
|
|
1092
|
+
DreamtreeFooter,
|
|
1093
|
+
DreamtreeMark,
|
|
1094
|
+
Eyebrow,
|
|
1095
|
+
Faq,
|
|
1096
|
+
FeatureSection,
|
|
1097
|
+
Header,
|
|
1098
|
+
Hero,
|
|
1099
|
+
HowItWorks,
|
|
1100
|
+
LandingPage,
|
|
1101
|
+
LandingProvider,
|
|
1102
|
+
MarketingLayout,
|
|
1103
|
+
PageHero,
|
|
1104
|
+
PreviewFrame,
|
|
1105
|
+
Section,
|
|
1106
|
+
SectionIntro,
|
|
1107
|
+
SmartLink,
|
|
1108
|
+
TextLink,
|
|
1109
|
+
Wordmark,
|
|
1110
|
+
Wrap,
|
|
1111
|
+
brandStyle,
|
|
1112
|
+
brands,
|
|
1113
|
+
createDemoIsland,
|
|
1114
|
+
getBrand,
|
|
1115
|
+
resolveHref,
|
|
1116
|
+
useLanding
|
|
1117
|
+
};
|