@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/dist/auth.cjs ADDED
@@ -0,0 +1,232 @@
1
+ 'use client';
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/auth.js
21
+ var auth_exports = {};
22
+ __export(auth_exports, {
23
+ AuthShell: () => AuthShell,
24
+ brandStyle: () => brandStyle,
25
+ brands: () => brands,
26
+ getBrand: () => getBrand
27
+ });
28
+ module.exports = __toCommonJS(auth_exports);
29
+
30
+ // src/AuthShell.jsx
31
+ var import_react = require("react");
32
+ var import_jsx_runtime = require("react/jsx-runtime");
33
+ var DEFAULT_LEGAL = [
34
+ { label: "Privacy Policy", href: "/privacy" },
35
+ { label: "Terms", href: "/terms" },
36
+ { label: "Data Policy", href: "/data-policy" }
37
+ ];
38
+ function BrandMark({ brand, size }) {
39
+ if (brand.logoSrc) {
40
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { className: "dt-auth-mark-img", src: brand.logoSrc, alt: "", width: size, height: size });
41
+ }
42
+ if (brand.mark) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dt-auth-mark-node", children: brand.mark });
43
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dt-auth-monogram", style: { width: size, height: size }, "aria-hidden": "true", children: brand.name.charAt(0) });
44
+ }
45
+ function brandStyle(brand) {
46
+ return {
47
+ "--dt-brand": brand.primary,
48
+ "--dt-brand-accent": brand.accent || brand.primary,
49
+ ...brand.panel ? { "--dt-brand-panel": brand.panel } : {}
50
+ };
51
+ }
52
+ function AuthShell({
53
+ brand,
54
+ title,
55
+ subtitle,
56
+ children,
57
+ footer,
58
+ variant = "tenant",
59
+ legalLinks = DEFAULT_LEGAL,
60
+ linkComponent: LinkComponent,
61
+ className = ""
62
+ }) {
63
+ var _a;
64
+ const headingId = (0, import_react.useId)();
65
+ const isPlatform = variant === "platform";
66
+ const headline = isPlatform ? brand.platformHeadline || "Platform administration" : brand.headline;
67
+ const pitch = isPlatform ? brand.platformPitch || `Super administrator console for ${brand.name}. Every action here is audited.` : brand.pitch;
68
+ const renderLink = (l) => LinkComponent ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LinkComponent, { to: l.href, href: l.href, className: "dt-auth-legal-link", children: l.label }, l.href) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: l.href, className: "dt-auth-legal-link", children: l.label }, l.href);
69
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
70
+ "div",
71
+ {
72
+ className: `dt-auth ${isPlatform ? "dt-auth--platform" : ""} ${className}`,
73
+ style: brandStyle(brand),
74
+ "data-product": brand.id,
75
+ children: [
76
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("aside", { className: "dt-auth-panel", children: [
77
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", { href: "/", className: "dt-auth-brand", children: [
78
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BrandMark, { brand, size: 28 }),
79
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dt-auth-brand-name", children: brand.name }),
80
+ isPlatform ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dt-auth-badge", children: "Platform" }) : null
81
+ ] }),
82
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dt-auth-pitch", children: [
83
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { children: headline }),
84
+ pitch ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: pitch }) : null,
85
+ !isPlatform && ((_a = brand.points) == null ? void 0 : _a.length) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { children: brand.points.map((p) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("li", { children: p }, p)) }) : null
86
+ ] }),
87
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "dt-auth-panel-foot", children: brand.category || "by Dreamtree-Org" })
88
+ ] }),
89
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("main", { className: "dt-auth-main", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "dt-auth-column", children: [
90
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("a", { href: "/", className: "dt-auth-brand dt-auth-brand--mobile", children: [
91
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(BrandMark, { brand, size: 24 }),
92
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dt-auth-brand-name", children: brand.name }),
93
+ isPlatform ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "dt-auth-badge", children: "Platform" }) : null
94
+ ] }),
95
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("section", { className: "dt-auth-card", "aria-labelledby": headingId, children: [
96
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("header", { className: "dt-auth-head", children: [
97
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { id: headingId, children: title }),
98
+ subtitle ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { children: subtitle }) : null
99
+ ] }),
100
+ children
101
+ ] }),
102
+ footer ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "dt-auth-footer", children: footer }) : null,
103
+ (legalLinks == null ? void 0 : legalLinks.length) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("nav", { className: "dt-auth-legal", "aria-label": "Legal", children: legalLinks.map((l, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "dt-auth-legal-item", children: [
104
+ i > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", children: "\xB7" }) : null,
105
+ renderLink(l)
106
+ ] }, l.href)) }) : null
107
+ ] }) })
108
+ ]
109
+ }
110
+ );
111
+ }
112
+
113
+ // src/brands.js
114
+ var brands = {
115
+ billpro: {
116
+ id: "billpro",
117
+ name: "BillPro",
118
+ primary: "#15803d",
119
+ // current #19a249, darkened one step for AA contrast on white
120
+ accent: "#4ade80",
121
+ logoSrc: "/brand/billpro-mark.svg",
122
+ headline: "Billing, inventory and GST \u2014 done right, every day.",
123
+ pitch: "GST invoices, stock, purchases and accounts for growing Indian businesses.",
124
+ points: ["GST-ready invoices and returns", "Live inventory across branches", "Payments, ledgers and reports"],
125
+ category: "Billing & Inventory \xB7 by Dreamtree-Org"
126
+ },
127
+ taskpro: {
128
+ id: "taskpro",
129
+ name: "TaskPro",
130
+ primary: "#065f46",
131
+ accent: "#34d399",
132
+ logoSrc: "/taskpro-mark-48.webp",
133
+ headline: "Projects and workflows, shaped the way your team works.",
134
+ pitch: "Configurable project types, statuses and automations \u2014 one place for every task.",
135
+ points: ["Your own workflows and statuses", "Boards, timelines and my-work", "Automations and audit trail"],
136
+ category: "Project & Workflow Management \xB7 by Dreamtree-Org"
137
+ },
138
+ venturepro: {
139
+ id: "venturepro",
140
+ name: "VenturePro",
141
+ primary: "#1e3a6e",
142
+ accent: "#e5ad42",
143
+ // accent-400, as shipped
144
+ panel: "#182e57",
145
+ // primary-700, as shipped
146
+ logoSrc: "/brand/venturepro-mark.svg",
147
+ headline: "Every venture, block and flat \u2014 in one place.",
148
+ pitch: "Create ventures, lay out blocks and units, track sales, rentals and collections across your whole portfolio.",
149
+ points: [],
150
+ category: "Builder Property & Apartment Management System"
151
+ },
152
+ campaignpro: {
153
+ id: "campaignpro",
154
+ name: "CampaignPro",
155
+ primary: "#6d28d9",
156
+ // PROPOSED — was the same red as firepro
157
+ accent: "#a78bfa",
158
+ headline: "Run every campaign from one pipeline.",
159
+ pitch: "Plan, send and track campaigns across channels with your whole team.",
160
+ points: ["Multi-channel campaigns", "Pipeline and follow-ups", "Team roles and approvals"],
161
+ category: "Campaign Management \xB7 by Dreamtree-Org"
162
+ },
163
+ firepro: {
164
+ id: "firepro",
165
+ name: "FirePro",
166
+ primary: "#b42318",
167
+ // keeps the red — it is the fire-safety product
168
+ accent: "#fb923c",
169
+ headline: "Fire safety compliance, inspections and service \u2014 on schedule.",
170
+ pitch: "Assets, inspections, service jobs and certificates for fire-safety teams.",
171
+ points: ["Scheduled inspections", "Asset and site registers", "Certificates and reports"],
172
+ category: "Fire Safety Operations \xB7 by Dreamtree-Org"
173
+ },
174
+ procurementpro: {
175
+ id: "procurementpro",
176
+ name: "ProcurementPro",
177
+ primary: "#1d4ed8",
178
+ // current #2563eb, one step darker for panel contrast
179
+ accent: "#60a5fa",
180
+ headline: "From request to purchase order, without the chase.",
181
+ pitch: "RFQs, quotations, approvals and purchase orders in one audited flow.",
182
+ points: ["RFQs and quotation comparison", "Approval workflows", "Purchase orders and vendors"],
183
+ category: "Procurement \xB7 by Dreamtree-Org"
184
+ },
185
+ fitweavepro: {
186
+ id: "fitweavepro",
187
+ name: "FitWeavePro",
188
+ primary: "#be185d",
189
+ // PROPOSED — was Tailwind blue
190
+ accent: "#f9a8d4",
191
+ headline: "Made-to-measure, made simple.",
192
+ pitch: "Measurements, patterns and orders for tailoring shops.",
193
+ points: ["Customer measurements", "Pattern and cutting plans", "Orders and deliveries"],
194
+ category: "Tailoring Shop Management \xB7 by Dreamtree-Org"
195
+ },
196
+ aiagentbuilder: {
197
+ id: "aiagentbuilder",
198
+ name: "AI Agent Builder",
199
+ primary: "#0f766e",
200
+ // PROPOSED — was blue, same as procurementpro
201
+ accent: "#5eead4",
202
+ headline: "Build, approve and ship AI agents your team can trust.",
203
+ pitch: "Multi-provider agents with approvals, knowledge bases, voice and an MCP server.",
204
+ points: ["Human-in-the-loop approvals", "Knowledge bases (RAG)", "Voice calls and campaigns"],
205
+ category: "AI Agent Platform \xB7 by Dreamtree-Org"
206
+ },
207
+ runloompro: {
208
+ id: "runloompro",
209
+ name: "RunLoom",
210
+ primary: "#4f46e5",
211
+ accent: "#a5b4fc",
212
+ headline: "Missions, run reliably.",
213
+ pitch: "Orchestrate long-running work across workers with full telemetry.",
214
+ points: ["Durable missions", "Node and Python workers", "Telemetry built in"],
215
+ category: "by Dreamtree-Org"
216
+ },
217
+ appforge: {
218
+ id: "appforge",
219
+ name: "AppForge",
220
+ primary: "#1f3864",
221
+ accent: "#2563eb",
222
+ headline: "Design, build and publish business apps.",
223
+ pitch: "Schema-driven apps with policy, review and one-click release.",
224
+ points: ["Visual builder", "Policies and RBAC", "Review and publish"],
225
+ category: "by Dreamtree-Org"
226
+ }
227
+ };
228
+ function getBrand(id) {
229
+ const b = brands[id];
230
+ if (!b) throw new Error(`landing-kit: unknown brand "${id}" (known: ${Object.keys(brands).join(", ")})`);
231
+ return b;
232
+ }
package/dist/auth.js ADDED
@@ -0,0 +1,211 @@
1
+ 'use client';
2
+
3
+ // src/AuthShell.jsx
4
+ import { useId } from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ var DEFAULT_LEGAL = [
7
+ { label: "Privacy Policy", href: "/privacy" },
8
+ { label: "Terms", href: "/terms" },
9
+ { label: "Data Policy", href: "/data-policy" }
10
+ ];
11
+ function BrandMark({ brand, size }) {
12
+ if (brand.logoSrc) {
13
+ return /* @__PURE__ */ jsx("img", { className: "dt-auth-mark-img", src: brand.logoSrc, alt: "", width: size, height: size });
14
+ }
15
+ if (brand.mark) return /* @__PURE__ */ jsx("span", { className: "dt-auth-mark-node", children: brand.mark });
16
+ return /* @__PURE__ */ jsx("span", { className: "dt-auth-monogram", style: { width: size, height: size }, "aria-hidden": "true", children: brand.name.charAt(0) });
17
+ }
18
+ function brandStyle(brand) {
19
+ return {
20
+ "--dt-brand": brand.primary,
21
+ "--dt-brand-accent": brand.accent || brand.primary,
22
+ ...brand.panel ? { "--dt-brand-panel": brand.panel } : {}
23
+ };
24
+ }
25
+ function AuthShell({
26
+ brand,
27
+ title,
28
+ subtitle,
29
+ children,
30
+ footer,
31
+ variant = "tenant",
32
+ legalLinks = DEFAULT_LEGAL,
33
+ linkComponent: LinkComponent,
34
+ className = ""
35
+ }) {
36
+ var _a;
37
+ const headingId = useId();
38
+ const isPlatform = variant === "platform";
39
+ const headline = isPlatform ? brand.platformHeadline || "Platform administration" : brand.headline;
40
+ const pitch = isPlatform ? brand.platformPitch || `Super administrator console for ${brand.name}. Every action here is audited.` : brand.pitch;
41
+ 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);
42
+ return /* @__PURE__ */ jsxs(
43
+ "div",
44
+ {
45
+ className: `dt-auth ${isPlatform ? "dt-auth--platform" : ""} ${className}`,
46
+ style: brandStyle(brand),
47
+ "data-product": brand.id,
48
+ children: [
49
+ /* @__PURE__ */ jsxs("aside", { className: "dt-auth-panel", children: [
50
+ /* @__PURE__ */ jsxs("a", { href: "/", className: "dt-auth-brand", children: [
51
+ /* @__PURE__ */ jsx(BrandMark, { brand, size: 28 }),
52
+ /* @__PURE__ */ jsx("span", { className: "dt-auth-brand-name", children: brand.name }),
53
+ isPlatform ? /* @__PURE__ */ jsx("span", { className: "dt-auth-badge", children: "Platform" }) : null
54
+ ] }),
55
+ /* @__PURE__ */ jsxs("div", { className: "dt-auth-pitch", children: [
56
+ /* @__PURE__ */ jsx("h2", { children: headline }),
57
+ pitch ? /* @__PURE__ */ jsx("p", { children: pitch }) : null,
58
+ !isPlatform && ((_a = brand.points) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsx("ul", { children: brand.points.map((p) => /* @__PURE__ */ jsx("li", { children: p }, p)) }) : null
59
+ ] }),
60
+ /* @__PURE__ */ jsx("p", { className: "dt-auth-panel-foot", children: brand.category || "by Dreamtree-Org" })
61
+ ] }),
62
+ /* @__PURE__ */ jsx("main", { className: "dt-auth-main", children: /* @__PURE__ */ jsxs("div", { className: "dt-auth-column", children: [
63
+ /* @__PURE__ */ jsxs("a", { href: "/", className: "dt-auth-brand dt-auth-brand--mobile", children: [
64
+ /* @__PURE__ */ jsx(BrandMark, { brand, size: 24 }),
65
+ /* @__PURE__ */ jsx("span", { className: "dt-auth-brand-name", children: brand.name }),
66
+ isPlatform ? /* @__PURE__ */ jsx("span", { className: "dt-auth-badge", children: "Platform" }) : null
67
+ ] }),
68
+ /* @__PURE__ */ jsxs("section", { className: "dt-auth-card", "aria-labelledby": headingId, children: [
69
+ /* @__PURE__ */ jsxs("header", { className: "dt-auth-head", children: [
70
+ /* @__PURE__ */ jsx("h1", { id: headingId, children: title }),
71
+ subtitle ? /* @__PURE__ */ jsx("p", { children: subtitle }) : null
72
+ ] }),
73
+ children
74
+ ] }),
75
+ footer ? /* @__PURE__ */ jsx("div", { className: "dt-auth-footer", children: footer }) : null,
76
+ (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: [
77
+ i > 0 ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }) : null,
78
+ renderLink(l)
79
+ ] }, l.href)) }) : null
80
+ ] }) })
81
+ ]
82
+ }
83
+ );
84
+ }
85
+
86
+ // src/brands.js
87
+ var brands = {
88
+ billpro: {
89
+ id: "billpro",
90
+ name: "BillPro",
91
+ primary: "#15803d",
92
+ // current #19a249, darkened one step for AA contrast on white
93
+ accent: "#4ade80",
94
+ logoSrc: "/brand/billpro-mark.svg",
95
+ headline: "Billing, inventory and GST \u2014 done right, every day.",
96
+ pitch: "GST invoices, stock, purchases and accounts for growing Indian businesses.",
97
+ points: ["GST-ready invoices and returns", "Live inventory across branches", "Payments, ledgers and reports"],
98
+ category: "Billing & Inventory \xB7 by Dreamtree-Org"
99
+ },
100
+ taskpro: {
101
+ id: "taskpro",
102
+ name: "TaskPro",
103
+ primary: "#065f46",
104
+ accent: "#34d399",
105
+ logoSrc: "/taskpro-mark-48.webp",
106
+ headline: "Projects and workflows, shaped the way your team works.",
107
+ pitch: "Configurable project types, statuses and automations \u2014 one place for every task.",
108
+ points: ["Your own workflows and statuses", "Boards, timelines and my-work", "Automations and audit trail"],
109
+ category: "Project & Workflow Management \xB7 by Dreamtree-Org"
110
+ },
111
+ venturepro: {
112
+ id: "venturepro",
113
+ name: "VenturePro",
114
+ primary: "#1e3a6e",
115
+ accent: "#e5ad42",
116
+ // accent-400, as shipped
117
+ panel: "#182e57",
118
+ // primary-700, as shipped
119
+ logoSrc: "/brand/venturepro-mark.svg",
120
+ headline: "Every venture, block and flat \u2014 in one place.",
121
+ pitch: "Create ventures, lay out blocks and units, track sales, rentals and collections across your whole portfolio.",
122
+ points: [],
123
+ category: "Builder Property & Apartment Management System"
124
+ },
125
+ campaignpro: {
126
+ id: "campaignpro",
127
+ name: "CampaignPro",
128
+ primary: "#6d28d9",
129
+ // PROPOSED — was the same red as firepro
130
+ accent: "#a78bfa",
131
+ headline: "Run every campaign from one pipeline.",
132
+ pitch: "Plan, send and track campaigns across channels with your whole team.",
133
+ points: ["Multi-channel campaigns", "Pipeline and follow-ups", "Team roles and approvals"],
134
+ category: "Campaign Management \xB7 by Dreamtree-Org"
135
+ },
136
+ firepro: {
137
+ id: "firepro",
138
+ name: "FirePro",
139
+ primary: "#b42318",
140
+ // keeps the red — it is the fire-safety product
141
+ accent: "#fb923c",
142
+ headline: "Fire safety compliance, inspections and service \u2014 on schedule.",
143
+ pitch: "Assets, inspections, service jobs and certificates for fire-safety teams.",
144
+ points: ["Scheduled inspections", "Asset and site registers", "Certificates and reports"],
145
+ category: "Fire Safety Operations \xB7 by Dreamtree-Org"
146
+ },
147
+ procurementpro: {
148
+ id: "procurementpro",
149
+ name: "ProcurementPro",
150
+ primary: "#1d4ed8",
151
+ // current #2563eb, one step darker for panel contrast
152
+ accent: "#60a5fa",
153
+ headline: "From request to purchase order, without the chase.",
154
+ pitch: "RFQs, quotations, approvals and purchase orders in one audited flow.",
155
+ points: ["RFQs and quotation comparison", "Approval workflows", "Purchase orders and vendors"],
156
+ category: "Procurement \xB7 by Dreamtree-Org"
157
+ },
158
+ fitweavepro: {
159
+ id: "fitweavepro",
160
+ name: "FitWeavePro",
161
+ primary: "#be185d",
162
+ // PROPOSED — was Tailwind blue
163
+ accent: "#f9a8d4",
164
+ headline: "Made-to-measure, made simple.",
165
+ pitch: "Measurements, patterns and orders for tailoring shops.",
166
+ points: ["Customer measurements", "Pattern and cutting plans", "Orders and deliveries"],
167
+ category: "Tailoring Shop Management \xB7 by Dreamtree-Org"
168
+ },
169
+ aiagentbuilder: {
170
+ id: "aiagentbuilder",
171
+ name: "AI Agent Builder",
172
+ primary: "#0f766e",
173
+ // PROPOSED — was blue, same as procurementpro
174
+ accent: "#5eead4",
175
+ headline: "Build, approve and ship AI agents your team can trust.",
176
+ pitch: "Multi-provider agents with approvals, knowledge bases, voice and an MCP server.",
177
+ points: ["Human-in-the-loop approvals", "Knowledge bases (RAG)", "Voice calls and campaigns"],
178
+ category: "AI Agent Platform \xB7 by Dreamtree-Org"
179
+ },
180
+ runloompro: {
181
+ id: "runloompro",
182
+ name: "RunLoom",
183
+ primary: "#4f46e5",
184
+ accent: "#a5b4fc",
185
+ headline: "Missions, run reliably.",
186
+ pitch: "Orchestrate long-running work across workers with full telemetry.",
187
+ points: ["Durable missions", "Node and Python workers", "Telemetry built in"],
188
+ category: "by Dreamtree-Org"
189
+ },
190
+ appforge: {
191
+ id: "appforge",
192
+ name: "AppForge",
193
+ primary: "#1f3864",
194
+ accent: "#2563eb",
195
+ headline: "Design, build and publish business apps.",
196
+ pitch: "Schema-driven apps with policy, review and one-click release.",
197
+ points: ["Visual builder", "Policies and RBAC", "Review and publish"],
198
+ category: "by Dreamtree-Org"
199
+ }
200
+ };
201
+ function getBrand(id) {
202
+ const b = brands[id];
203
+ if (!b) throw new Error(`landing-kit: unknown brand "${id}" (known: ${Object.keys(brands).join(", ")})`);
204
+ return b;
205
+ }
206
+ export {
207
+ AuthShell,
208
+ brandStyle,
209
+ brands,
210
+ getBrand
211
+ };
@@ -0,0 +1,83 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
5
+ var __export = (target, all) => {
6
+ for (var name in all)
7
+ __defProp(target, name, { get: all[name], enumerable: true });
8
+ };
9
+ var __copyProps = (to, from, except, desc) => {
10
+ if (from && typeof from === "object" || typeof from === "function") {
11
+ for (let key of __getOwnPropNames(from))
12
+ if (!__hasOwnProp.call(to, key) && key !== except)
13
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
14
+ }
15
+ return to;
16
+ };
17
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
18
+
19
+ // src/enhance.js
20
+ var enhance_exports = {};
21
+ __export(enhance_exports, {
22
+ default: () => enhance_default,
23
+ enhanceLanding: () => enhanceLanding
24
+ });
25
+ module.exports = __toCommonJS(enhance_exports);
26
+ function enhanceLanding(root = document, { openDemo, loadDemo, warmDemo, hash = "#book-demo" } = {}) {
27
+ const offs = [];
28
+ const on = (el, type, fn, opts) => {
29
+ el.addEventListener(type, fn, opts);
30
+ offs.push(() => el.removeEventListener(type, fn, opts));
31
+ };
32
+ const doc = root.ownerDocument || root;
33
+ let mod;
34
+ const load = loadDemo ? () => mod || (mod = Promise.resolve(loadDemo())) : null;
35
+ const warm = warmDemo || load || (() => {
36
+ });
37
+ const open = async (btn) => {
38
+ if (btn) btn.setAttribute("aria-busy", "true");
39
+ try {
40
+ if (openDemo) await openDemo(btn);
41
+ else if (load) (await load()).openDemo(btn);
42
+ } finally {
43
+ if (btn) btn.removeAttribute("aria-busy");
44
+ }
45
+ };
46
+ const toggle = root.querySelector("[data-menu-toggle]");
47
+ const menu = doc.getElementById("mobile-nav");
48
+ if (toggle && menu) {
49
+ const set = (isOpen) => {
50
+ toggle.setAttribute("aria-expanded", String(isOpen));
51
+ toggle.setAttribute("aria-label", isOpen ? "Close menu" : "Open menu");
52
+ menu.hidden = !isOpen;
53
+ };
54
+ set(false);
55
+ on(toggle, "click", () => set(menu.hidden));
56
+ on(menu, "click", (e) => {
57
+ if (e.target.closest && e.target.closest("a")) set(false);
58
+ });
59
+ on(doc, "keydown", (e) => {
60
+ if (e.key === "Escape" && !menu.hidden) {
61
+ set(false);
62
+ toggle.focus();
63
+ }
64
+ });
65
+ }
66
+ for (const btn of root.querySelectorAll("[data-scroll-to]")) {
67
+ on(btn, "click", () => {
68
+ const el = doc.getElementById(btn.getAttribute("data-scroll-to"));
69
+ if (el && el.scrollIntoView) el.scrollIntoView({ behavior: "smooth" });
70
+ });
71
+ }
72
+ if (openDemo || load) {
73
+ for (const btn of root.querySelectorAll("[data-book-demo]")) {
74
+ on(btn, "pointerenter", warm, { once: true });
75
+ on(btn, "focus", warm, { once: true });
76
+ on(btn, "click", () => open(btn));
77
+ }
78
+ const loc = doc.defaultView && doc.defaultView.location;
79
+ if (hash && loc && loc.hash === hash) open();
80
+ }
81
+ return () => offs.forEach((off) => off());
82
+ }
83
+ var enhance_default = enhanceLanding;
@@ -0,0 +1,63 @@
1
+ // src/enhance.js
2
+ function enhanceLanding(root = document, { openDemo, loadDemo, warmDemo, hash = "#book-demo" } = {}) {
3
+ const offs = [];
4
+ const on = (el, type, fn, opts) => {
5
+ el.addEventListener(type, fn, opts);
6
+ offs.push(() => el.removeEventListener(type, fn, opts));
7
+ };
8
+ const doc = root.ownerDocument || root;
9
+ let mod;
10
+ const load = loadDemo ? () => mod || (mod = Promise.resolve(loadDemo())) : null;
11
+ const warm = warmDemo || load || (() => {
12
+ });
13
+ const open = async (btn) => {
14
+ if (btn) btn.setAttribute("aria-busy", "true");
15
+ try {
16
+ if (openDemo) await openDemo(btn);
17
+ else if (load) (await load()).openDemo(btn);
18
+ } finally {
19
+ if (btn) btn.removeAttribute("aria-busy");
20
+ }
21
+ };
22
+ const toggle = root.querySelector("[data-menu-toggle]");
23
+ const menu = doc.getElementById("mobile-nav");
24
+ if (toggle && menu) {
25
+ const set = (isOpen) => {
26
+ toggle.setAttribute("aria-expanded", String(isOpen));
27
+ toggle.setAttribute("aria-label", isOpen ? "Close menu" : "Open menu");
28
+ menu.hidden = !isOpen;
29
+ };
30
+ set(false);
31
+ on(toggle, "click", () => set(menu.hidden));
32
+ on(menu, "click", (e) => {
33
+ if (e.target.closest && e.target.closest("a")) set(false);
34
+ });
35
+ on(doc, "keydown", (e) => {
36
+ if (e.key === "Escape" && !menu.hidden) {
37
+ set(false);
38
+ toggle.focus();
39
+ }
40
+ });
41
+ }
42
+ for (const btn of root.querySelectorAll("[data-scroll-to]")) {
43
+ on(btn, "click", () => {
44
+ const el = doc.getElementById(btn.getAttribute("data-scroll-to"));
45
+ if (el && el.scrollIntoView) el.scrollIntoView({ behavior: "smooth" });
46
+ });
47
+ }
48
+ if (openDemo || load) {
49
+ for (const btn of root.querySelectorAll("[data-book-demo]")) {
50
+ on(btn, "pointerenter", warm, { once: true });
51
+ on(btn, "focus", warm, { once: true });
52
+ on(btn, "click", () => open(btn));
53
+ }
54
+ const loc = doc.defaultView && doc.defaultView.location;
55
+ if (hash && loc && loc.hash === hash) open();
56
+ }
57
+ return () => offs.forEach((off) => off());
58
+ }
59
+ var enhance_default = enhanceLanding;
60
+ export {
61
+ enhance_default as default,
62
+ enhanceLanding
63
+ };