@contractspec/bundle.marketing 1.12.0 → 1.13.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.
Files changed (262) hide show
  1. package/.turbo/turbo-build.log +146 -175
  2. package/.turbo/turbo-prebuild.log +1 -0
  3. package/CHANGELOG.md +29 -0
  4. package/dist/browser/components/marketing/ChangelogPage.js +92 -0
  5. package/dist/browser/components/marketing/CofounderPage.js +581 -0
  6. package/dist/browser/components/marketing/ContactClient.js +1379 -0
  7. package/dist/browser/components/marketing/ContributePage.js +487 -0
  8. package/dist/browser/components/marketing/DesignPartnerPage.js +272 -0
  9. package/dist/browser/components/marketing/LandingPage.js +629 -0
  10. package/dist/browser/components/marketing/PricingClient.js +1972 -0
  11. package/dist/browser/components/marketing/ProductClientPage.js +563 -0
  12. package/dist/browser/components/marketing/index.js +4818 -0
  13. package/dist/browser/components/marketing/pricing-thinking-modal.js +258 -0
  14. package/dist/browser/components/marketing/sections/AudienceSection.js +90 -0
  15. package/dist/browser/components/marketing/sections/CorePositioningSection.js +72 -0
  16. package/dist/browser/components/marketing/sections/CtaSection.js +67 -0
  17. package/dist/browser/components/marketing/sections/DevelopersSection.js +50 -0
  18. package/dist/browser/components/marketing/sections/FearsSection.js +105 -0
  19. package/dist/browser/components/marketing/sections/HeroMarketingSection.js +93 -0
  20. package/dist/browser/components/marketing/sections/IconGridSection.js +63 -0
  21. package/dist/browser/components/marketing/sections/OutputsSection.js +116 -0
  22. package/dist/browser/components/marketing/sections/ProblemSection.js +103 -0
  23. package/dist/browser/components/marketing/sections/SolutionSection.js +103 -0
  24. package/dist/browser/components/marketing/sections/StepsSection.js +109 -0
  25. package/dist/browser/components/marketing/waitlist-section.js +1104 -0
  26. package/dist/browser/components/templates/TemplatesClientPage.js +5662 -0
  27. package/dist/browser/components/templates/TemplatesPage.js +177 -0
  28. package/dist/browser/components/templates/TemplatesPreviewModal.js +124 -0
  29. package/dist/browser/components/templates/index.js +5831 -0
  30. package/dist/browser/index.js +6485 -0
  31. package/dist/browser/libs/email/client.js +122 -0
  32. package/dist/browser/libs/email/contact.js +190 -0
  33. package/dist/browser/libs/email/newsletter.js +215 -0
  34. package/dist/browser/libs/email/types.js +2 -0
  35. package/dist/browser/libs/email/utils.js +16 -0
  36. package/dist/browser/libs/email/waitlist-application.js +295 -0
  37. package/dist/browser/libs/email/waitlist.js +225 -0
  38. package/dist/browser/libs/pricing-examples.js +26 -0
  39. package/dist/browser/registry/engine.js +5293 -0
  40. package/dist/browser/registry/factory.js +52 -0
  41. package/dist/browser/registry/index.js +5358 -0
  42. package/dist/browser/registry/registry-docs.js +343 -0
  43. package/dist/browser/registry/registry-landing.js +4937 -0
  44. package/dist/browser/registry/registry.js +5279 -0
  45. package/dist/browser/registry/types.js +0 -0
  46. package/dist/browser/registry/utils.js +5340 -0
  47. package/dist/components/marketing/ChangelogPage.d.ts +11 -17
  48. package/dist/components/marketing/ChangelogPage.d.ts.map +1 -1
  49. package/dist/components/marketing/ChangelogPage.js +84 -62
  50. package/dist/components/marketing/CofounderPage.d.ts +1 -6
  51. package/dist/components/marketing/CofounderPage.d.ts.map +1 -1
  52. package/dist/components/marketing/CofounderPage.js +544 -436
  53. package/dist/components/marketing/ContactClient.d.ts +1 -6
  54. package/dist/components/marketing/ContactClient.d.ts.map +1 -1
  55. package/dist/components/marketing/ContactClient.js +1371 -155
  56. package/dist/components/marketing/ContributePage.d.ts +3 -8
  57. package/dist/components/marketing/ContributePage.d.ts.map +1 -1
  58. package/dist/components/marketing/ContributePage.js +478 -358
  59. package/dist/components/marketing/DesignPartnerPage.d.ts +3 -8
  60. package/dist/components/marketing/DesignPartnerPage.d.ts.map +1 -1
  61. package/dist/components/marketing/DesignPartnerPage.js +263 -211
  62. package/dist/components/marketing/LandingPage.d.ts +1 -6
  63. package/dist/components/marketing/LandingPage.d.ts.map +1 -1
  64. package/dist/components/marketing/LandingPage.js +623 -37
  65. package/dist/components/marketing/PricingClient.d.ts +1 -6
  66. package/dist/components/marketing/PricingClient.d.ts.map +1 -1
  67. package/dist/components/marketing/PricingClient.js +1962 -516
  68. package/dist/components/marketing/ProductClientPage.d.ts +1 -6
  69. package/dist/components/marketing/ProductClientPage.d.ts.map +1 -1
  70. package/dist/components/marketing/ProductClientPage.js +556 -458
  71. package/dist/components/marketing/index.d.ts +11 -11
  72. package/dist/components/marketing/index.d.ts.map +1 -0
  73. package/dist/components/marketing/index.js +4813 -12
  74. package/dist/components/marketing/pricing-thinking-modal.d.ts +5 -13
  75. package/dist/components/marketing/pricing-thinking-modal.d.ts.map +1 -1
  76. package/dist/components/marketing/pricing-thinking-modal.js +248 -197
  77. package/dist/components/marketing/sections/AudienceSection.d.ts +1 -6
  78. package/dist/components/marketing/sections/AudienceSection.d.ts.map +1 -1
  79. package/dist/components/marketing/sections/AudienceSection.js +80 -63
  80. package/dist/components/marketing/sections/CorePositioningSection.d.ts +1 -6
  81. package/dist/components/marketing/sections/CorePositioningSection.d.ts.map +1 -1
  82. package/dist/components/marketing/sections/CorePositioningSection.js +62 -54
  83. package/dist/components/marketing/sections/CtaSection.d.ts +1 -6
  84. package/dist/components/marketing/sections/CtaSection.d.ts.map +1 -1
  85. package/dist/components/marketing/sections/CtaSection.js +58 -50
  86. package/dist/components/marketing/sections/DevelopersSection.d.ts +1 -6
  87. package/dist/components/marketing/sections/DevelopersSection.d.ts.map +1 -1
  88. package/dist/components/marketing/sections/DevelopersSection.js +40 -40
  89. package/dist/components/marketing/sections/FearsSection.d.ts +1 -6
  90. package/dist/components/marketing/sections/FearsSection.d.ts.map +1 -1
  91. package/dist/components/marketing/sections/FearsSection.js +96 -44
  92. package/dist/components/marketing/sections/HeroMarketingSection.d.ts +1 -6
  93. package/dist/components/marketing/sections/HeroMarketingSection.d.ts.map +1 -1
  94. package/dist/components/marketing/sections/HeroMarketingSection.js +82 -71
  95. package/dist/components/marketing/sections/IconGridSection.d.ts +25 -39
  96. package/dist/components/marketing/sections/IconGridSection.d.ts.map +1 -1
  97. package/dist/components/marketing/sections/IconGridSection.js +55 -41
  98. package/dist/components/marketing/sections/OutputsSection.d.ts +1 -6
  99. package/dist/components/marketing/sections/OutputsSection.d.ts.map +1 -1
  100. package/dist/components/marketing/sections/OutputsSection.js +107 -55
  101. package/dist/components/marketing/sections/ProblemSection.d.ts +1 -6
  102. package/dist/components/marketing/sections/ProblemSection.d.ts.map +1 -1
  103. package/dist/components/marketing/sections/ProblemSection.js +94 -42
  104. package/dist/components/marketing/sections/SolutionSection.d.ts +1 -6
  105. package/dist/components/marketing/sections/SolutionSection.d.ts.map +1 -1
  106. package/dist/components/marketing/sections/SolutionSection.js +94 -42
  107. package/dist/components/marketing/sections/StepsSection.d.ts +1 -6
  108. package/dist/components/marketing/sections/StepsSection.d.ts.map +1 -1
  109. package/dist/components/marketing/sections/StepsSection.js +100 -48
  110. package/dist/components/marketing/waitlist-section.d.ts +5 -12
  111. package/dist/components/marketing/waitlist-section.d.ts.map +1 -1
  112. package/dist/components/marketing/waitlist-section.js +1089 -568
  113. package/dist/components/templates/TemplatesClientPage.d.ts +1 -6
  114. package/dist/components/templates/TemplatesClientPage.d.ts.map +1 -1
  115. package/dist/components/templates/TemplatesClientPage.js +5649 -617
  116. package/dist/components/templates/TemplatesPage.d.ts +1 -6
  117. package/dist/components/templates/TemplatesPage.d.ts.map +1 -1
  118. package/dist/components/templates/TemplatesPage.js +163 -116
  119. package/dist/components/templates/TemplatesPreviewModal.d.ts +5 -12
  120. package/dist/components/templates/TemplatesPreviewModal.d.ts.map +1 -1
  121. package/dist/components/templates/TemplatesPreviewModal.js +113 -131
  122. package/dist/components/templates/index.d.ts +4 -4
  123. package/dist/components/templates/index.d.ts.map +1 -0
  124. package/dist/components/templates/index.js +5825 -4
  125. package/dist/index.d.ts +9 -29
  126. package/dist/index.d.ts.map +1 -0
  127. package/dist/index.js +6480 -28
  128. package/dist/libs/email/client.d.ts +9 -12
  129. package/dist/libs/email/client.d.ts.map +1 -1
  130. package/dist/libs/email/client.js +109 -105
  131. package/dist/libs/email/client.test.d.ts +2 -0
  132. package/dist/libs/email/client.test.d.ts.map +1 -0
  133. package/dist/libs/email/contact.d.ts +2 -6
  134. package/dist/libs/email/contact.d.ts.map +1 -1
  135. package/dist/libs/email/contact.js +155 -41
  136. package/dist/libs/email/newsletter.d.ts +2 -6
  137. package/dist/libs/email/newsletter.d.ts.map +1 -1
  138. package/dist/libs/email/newsletter.js +169 -54
  139. package/dist/libs/email/types.d.ts +48 -52
  140. package/dist/libs/email/types.d.ts.map +1 -1
  141. package/dist/libs/email/types.js +3 -1
  142. package/dist/libs/email/utils.d.ts +2 -5
  143. package/dist/libs/email/utils.d.ts.map +1 -1
  144. package/dist/libs/email/utils.js +10 -6
  145. package/dist/libs/email/waitlist-application.d.ts +2 -6
  146. package/dist/libs/email/waitlist-application.d.ts.map +1 -1
  147. package/dist/libs/email/waitlist-application.js +191 -71
  148. package/dist/libs/email/waitlist.d.ts +2 -6
  149. package/dist/libs/email/waitlist.d.ts.map +1 -1
  150. package/dist/libs/email/waitlist.js +171 -56
  151. package/dist/libs/pricing-examples.d.ts +13 -16
  152. package/dist/libs/pricing-examples.d.ts.map +1 -1
  153. package/dist/libs/pricing-examples.js +20 -20
  154. package/dist/node/components/marketing/ChangelogPage.js +87 -0
  155. package/dist/node/components/marketing/CofounderPage.js +576 -0
  156. package/dist/node/components/marketing/ContactClient.js +1374 -0
  157. package/dist/node/components/marketing/ContributePage.js +482 -0
  158. package/dist/node/components/marketing/DesignPartnerPage.js +267 -0
  159. package/dist/node/components/marketing/LandingPage.js +624 -0
  160. package/dist/node/components/marketing/PricingClient.js +1967 -0
  161. package/dist/node/components/marketing/ProductClientPage.js +558 -0
  162. package/dist/node/components/marketing/index.js +4813 -0
  163. package/dist/node/components/marketing/pricing-thinking-modal.js +253 -0
  164. package/dist/node/components/marketing/sections/AudienceSection.js +85 -0
  165. package/dist/node/components/marketing/sections/CorePositioningSection.js +67 -0
  166. package/dist/node/components/marketing/sections/CtaSection.js +62 -0
  167. package/dist/node/components/marketing/sections/DevelopersSection.js +45 -0
  168. package/dist/node/components/marketing/sections/FearsSection.js +100 -0
  169. package/dist/node/components/marketing/sections/HeroMarketingSection.js +88 -0
  170. package/dist/node/components/marketing/sections/IconGridSection.js +58 -0
  171. package/dist/node/components/marketing/sections/OutputsSection.js +111 -0
  172. package/dist/node/components/marketing/sections/ProblemSection.js +98 -0
  173. package/dist/node/components/marketing/sections/SolutionSection.js +98 -0
  174. package/dist/node/components/marketing/sections/StepsSection.js +104 -0
  175. package/dist/node/components/marketing/waitlist-section.js +1099 -0
  176. package/dist/node/components/templates/TemplatesClientPage.js +5657 -0
  177. package/dist/node/components/templates/TemplatesPage.js +172 -0
  178. package/dist/node/components/templates/TemplatesPreviewModal.js +119 -0
  179. package/dist/node/components/templates/index.js +5826 -0
  180. package/dist/node/index.js +6480 -0
  181. package/dist/node/libs/email/client.js +117 -0
  182. package/dist/node/libs/email/contact.js +185 -0
  183. package/dist/node/libs/email/newsletter.js +210 -0
  184. package/dist/node/libs/email/types.js +2 -0
  185. package/dist/node/libs/email/utils.js +11 -0
  186. package/dist/node/libs/email/waitlist-application.js +290 -0
  187. package/dist/node/libs/email/waitlist.js +220 -0
  188. package/dist/node/libs/pricing-examples.js +21 -0
  189. package/dist/node/registry/engine.js +5288 -0
  190. package/dist/node/registry/factory.js +47 -0
  191. package/dist/node/registry/index.js +5353 -0
  192. package/dist/node/registry/registry-docs.js +338 -0
  193. package/dist/node/registry/registry-landing.js +4932 -0
  194. package/dist/node/registry/registry.js +5274 -0
  195. package/dist/node/registry/types.js +0 -0
  196. package/dist/node/registry/utils.js +5335 -0
  197. package/dist/registry/engine.d.ts +4 -8
  198. package/dist/registry/engine.d.ts.map +1 -1
  199. package/dist/registry/engine.js +5287 -23
  200. package/dist/registry/factory.d.ts +30 -34
  201. package/dist/registry/factory.d.ts.map +1 -1
  202. package/dist/registry/factory.js +42 -56
  203. package/dist/registry/index.d.ts +8 -8
  204. package/dist/registry/index.d.ts.map +1 -0
  205. package/dist/registry/index.js +5353 -8
  206. package/dist/registry/registry-docs.d.ts +4 -8
  207. package/dist/registry/registry-docs.d.ts.map +1 -1
  208. package/dist/registry/registry-docs.js +242 -209
  209. package/dist/registry/registry-landing.d.ts +5 -9
  210. package/dist/registry/registry-landing.d.ts.map +1 -1
  211. package/dist/registry/registry-landing.js +4930 -93
  212. package/dist/registry/registry.d.ts +7 -11
  213. package/dist/registry/registry.d.ts.map +1 -1
  214. package/dist/registry/registry.js +5262 -49
  215. package/dist/registry/types.d.ts +6 -10
  216. package/dist/registry/types.d.ts.map +1 -1
  217. package/dist/registry/types.js +1 -0
  218. package/dist/registry/utils.d.ts +10 -14
  219. package/dist/registry/utils.d.ts.map +1 -1
  220. package/dist/registry/utils.js +5330 -49
  221. package/package.json +355 -73
  222. package/tsdown.config.js +1 -2
  223. package/.turbo/turbo-build$colon$types.log +0 -1
  224. package/.turbo/turbo-lint.log +0 -3
  225. package/dist/components/marketing/ChangelogPage.js.map +0 -1
  226. package/dist/components/marketing/CofounderPage.js.map +0 -1
  227. package/dist/components/marketing/ContactClient.js.map +0 -1
  228. package/dist/components/marketing/ContributePage.js.map +0 -1
  229. package/dist/components/marketing/DesignPartnerPage.js.map +0 -1
  230. package/dist/components/marketing/LandingPage.js.map +0 -1
  231. package/dist/components/marketing/PricingClient.js.map +0 -1
  232. package/dist/components/marketing/ProductClientPage.js.map +0 -1
  233. package/dist/components/marketing/pricing-thinking-modal.js.map +0 -1
  234. package/dist/components/marketing/sections/AudienceSection.js.map +0 -1
  235. package/dist/components/marketing/sections/CorePositioningSection.js.map +0 -1
  236. package/dist/components/marketing/sections/CtaSection.js.map +0 -1
  237. package/dist/components/marketing/sections/DevelopersSection.js.map +0 -1
  238. package/dist/components/marketing/sections/FearsSection.js.map +0 -1
  239. package/dist/components/marketing/sections/HeroMarketingSection.js.map +0 -1
  240. package/dist/components/marketing/sections/IconGridSection.js.map +0 -1
  241. package/dist/components/marketing/sections/OutputsSection.js.map +0 -1
  242. package/dist/components/marketing/sections/ProblemSection.js.map +0 -1
  243. package/dist/components/marketing/sections/SolutionSection.js.map +0 -1
  244. package/dist/components/marketing/sections/StepsSection.js.map +0 -1
  245. package/dist/components/marketing/waitlist-section.js.map +0 -1
  246. package/dist/components/templates/TemplatesClientPage.js.map +0 -1
  247. package/dist/components/templates/TemplatesPage.js.map +0 -1
  248. package/dist/components/templates/TemplatesPreviewModal.js.map +0 -1
  249. package/dist/libs/email/client.js.map +0 -1
  250. package/dist/libs/email/contact.js.map +0 -1
  251. package/dist/libs/email/newsletter.js.map +0 -1
  252. package/dist/libs/email/utils.js.map +0 -1
  253. package/dist/libs/email/waitlist-application.js.map +0 -1
  254. package/dist/libs/email/waitlist.js.map +0 -1
  255. package/dist/libs/pricing-examples.js.map +0 -1
  256. package/dist/registry/engine.js.map +0 -1
  257. package/dist/registry/factory.js.map +0 -1
  258. package/dist/registry/registry-docs.js.map +0 -1
  259. package/dist/registry/registry-landing.js.map +0 -1
  260. package/dist/registry/registry.js.map +0 -1
  261. package/dist/registry/utils.js.map +0 -1
  262. package/tsconfig.tsbuildinfo +0 -1
@@ -1,578 +1,1099 @@
1
- 'use client';
1
+ // @bun
2
+ var __require = import.meta.require;
2
3
 
3
- import { joinWaitlist } from "../../libs/email/waitlist.js";
4
- import { submitWaitlistApplication } from "../../libs/email/waitlist-application.js";
5
- import { Button, Input, Textarea } from "@contractspec/lib.design-system";
6
- import { AlertCircle, CheckCircle } from "lucide-react";
7
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+ // src/libs/email/client.ts
5
+ import { createClient, Temv1alpha1 } from "@scaleway/sdk";
6
+ import { Logger } from "@contractspec/lib.logger";
7
+ var DEFAULT_FROM = {
8
+ email: "noreply@transactional.contractspec.io",
9
+ name: "ContractSpec"
10
+ };
11
+ var DEFAULT_TEAM_INBOX = {
12
+ email: "contact@contractspec.io",
13
+ name: "ContractSpec Team"
14
+ };
15
+ var DEFAULT_REGION = "fr-par";
16
+ var cachedConfig = null;
17
+ var cachedClient = null;
18
+ var apiFactory = (client) => new Temv1alpha1.API(client);
19
+ var mapRegion = (value) => {
20
+ const normalized = value?.trim().toLowerCase();
21
+ if (normalized === "par" || normalized === "fr-par")
22
+ return "fr-par";
23
+ if (normalized === "ams" || normalized === "nl-ams")
24
+ return "nl-ams";
25
+ if (normalized === "waw" || normalized === "pl-waw")
26
+ return "pl-waw";
27
+ return DEFAULT_REGION;
28
+ };
29
+ var getEmailConfig = () => {
30
+ if (cachedConfig) {
31
+ return { ok: true, config: cachedConfig };
32
+ }
33
+ const accessKey = process.env.SCALEWAY_ACCESS_KEY || process.env.SCALEWAY_ACCESS_KEY_QUEUE;
34
+ const secretKey = process.env.SCALEWAY_SECRET_KEY || process.env.SCALEWAY_SECRET_KEY_QUEUE;
35
+ const projectId = process.env.SCALEWAY_PROJECT_ID;
36
+ if (!accessKey || !secretKey || !projectId) {
37
+ return {
38
+ ok: false,
39
+ errorMessage: "Email service is not configured. Please contact us directly at contact@contractspec.io."
40
+ };
41
+ }
42
+ const region = mapRegion(process.env.SCALEWAY_REGION);
43
+ cachedConfig = {
44
+ accessKey,
45
+ secretKey,
46
+ projectId,
47
+ region,
48
+ defaultZone: `${region}-1`,
49
+ from: {
50
+ email: process.env.SCALEWAY_EMAIL_FROM_EMAIL ?? DEFAULT_FROM.email,
51
+ name: process.env.SCALEWAY_EMAIL_FROM_NAME ?? DEFAULT_FROM.name
52
+ },
53
+ teamInbox: {
54
+ email: process.env.SCALEWAY_EMAIL_TEAM_EMAIL ?? DEFAULT_TEAM_INBOX.email,
55
+ name: process.env.SCALEWAY_EMAIL_TEAM_NAME ?? DEFAULT_TEAM_INBOX.name
56
+ }
57
+ };
58
+ return { ok: true, config: cachedConfig };
59
+ };
60
+ var getTemClient = (config) => {
61
+ if (cachedClient) {
62
+ return cachedClient;
63
+ }
64
+ const client = createClient({
65
+ accessKey: config.accessKey,
66
+ secretKey: config.secretKey,
67
+ defaultProjectId: config.projectId,
68
+ defaultRegion: config.region,
69
+ defaultZone: config.defaultZone
70
+ });
71
+ cachedClient = apiFactory(client);
72
+ return cachedClient;
73
+ };
74
+ var sendEmail = async (config, request) => {
75
+ try {
76
+ const client = getTemClient(config);
77
+ await client.createEmail({
78
+ region: config.region,
79
+ projectId: config.projectId,
80
+ from: config.from,
81
+ to: request.to,
82
+ subject: request.subject,
83
+ text: request.text,
84
+ html: request.html || request.text,
85
+ additionalHeaders: request.replyTo ? [{ key: "Reply-To", value: request.replyTo }] : undefined
86
+ });
87
+ return { success: true };
88
+ } catch (error) {
89
+ new Logger().error("scaleway_tem_email_send_failed", {
90
+ context: request.context ?? "email",
91
+ error: error instanceof Error ? error.message : error
92
+ });
93
+ return {
94
+ success: false,
95
+ error,
96
+ errorMessage: "Failed to send email via Scaleway."
97
+ };
98
+ }
99
+ };
100
+ var __internal = {
101
+ resetCaches() {
102
+ cachedClient = null;
103
+ cachedConfig = null;
104
+ apiFactory = (client) => new Temv1alpha1.API(client);
105
+ },
106
+ setApiFactory(factory) {
107
+ apiFactory = factory;
108
+ },
109
+ setClient(client) {
110
+ cachedClient = client;
111
+ }
112
+ };
113
+
114
+ // src/libs/email/utils.ts
115
+ var escapeHtml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
116
+ var formatMultilineHtml = (value) => escapeHtml(value).replaceAll(`
117
+ `, "<br />");
118
+
119
+ // src/libs/email/waitlist.ts
120
+ "use server";
121
+ var WAITLIST_MISSING_CONFIG = "Waitlist service is not configured. Please try again later.";
122
+ var WAITLIST_SEND_ERROR = "Failed to join waitlist. Please try again later or contact us directly.";
123
+ var joinWaitlist = async (formData) => {
124
+ const email = (formData.get("email") ?? "").toString().trim();
125
+ if (!email || !email.includes("@")) {
126
+ return {
127
+ success: false,
128
+ text: "Please enter a valid email address."
129
+ };
130
+ }
131
+ const configResult = getEmailConfig();
132
+ if (!configResult.ok || !configResult.config) {
133
+ return {
134
+ success: false,
135
+ text: configResult.errorMessage ?? WAITLIST_MISSING_CONFIG
136
+ };
137
+ }
138
+ const waitlistText = `
139
+ You're on the waitlist!
140
+
141
+ Thanks for joining the ContractSpec waitlist. You're now in line for early access to:
142
+
143
+ \u2022 Stabilize your AI-generated code with ContractSpec
144
+ \u2022 Multi-surface consistency (API, DB, UI, events)
145
+ \u2022 Safe regeneration without breaking changes
146
+ \u2022 AI governance and contract enforcement
147
+
148
+ We'll notify you as soon as early access is available. In the meantime, you can:
149
+
150
+ \u2022 Check out our docs: https://contractspec.io/docs
151
+ \u2022 Follow our progress on GitHub
152
+ \u2022 Book a demo call to see ContractSpec in action
153
+
154
+ We're excited to have you on board!
155
+
156
+ ---
157
+ ContractSpec Team
158
+ https://contractspec.io
159
+
160
+ To remove yourself from the waitlist, reply to this email with "remove"
161
+ `.trim();
162
+ const waitlistHtml = `
163
+ <div style="font-family: sans-serif; max-width: 640px; margin: 0 auto;">
164
+ <h1 style="color: #8b5cf6;">You're on the waitlist!</h1>
165
+ <p>Thanks for joining the ContractSpec waitlist. You're now in line for early access to:</p>
166
+ <ul style="line-height: 1.8;">
167
+ <li>Stabilize your AI-generated code with ContractSpec</li>
168
+ <li>Multi-surface consistency (API, DB, UI, events)</li>
169
+ <li>Safe regeneration without breaking changes</li>
170
+ <li>AI governance and contract enforcement</li>
171
+ </ul>
172
+ <p>We'll notify you as soon as early access is available. In the meantime, you can:</p>
173
+ <ul style="line-height: 1.8;">
174
+ <li>Check out our <a href="https://contractspec.io/docs" style="color: #8b5cf6;">docs</a></li>
175
+ <li>Follow our progress on GitHub</li>
176
+ <li>Book a demo call to see ContractSpec in action</li>
177
+ </ul>
178
+ <p>We're excited to have you on board!</p>
179
+ <hr style="margin: 30px 0; border: none; border-top: 1px solid #e5e7eb;" />
180
+ <p style="color: #6b7280; font-size: 14px;">
181
+ ContractSpec Team<br />
182
+ <a href="https://contractspec.io" style="color: #8b5cf6;">contractspec.io</a>
183
+ </p>
184
+ <p style="color: #9ca3af; font-size: 12px;">
185
+ To remove yourself from the waitlist, reply to this email with "remove"
186
+ </p>
187
+ </div>
188
+ `;
189
+ const userSend = await sendEmail(configResult.config, {
190
+ to: [{ email }],
191
+ subject: "You're on the ContractSpec waitlist!",
192
+ text: waitlistText,
193
+ html: waitlistHtml,
194
+ context: "waitlist-welcome"
195
+ });
196
+ if (!userSend.success) {
197
+ return { success: false, text: WAITLIST_SEND_ERROR };
198
+ }
199
+ const teamNotificationText = `New waitlist signup from: ${email}`;
200
+ const teamNotificationHtml = `
201
+ <div style="font-family: sans-serif; max-width: 640px; margin: 0 auto;">
202
+ <p style="margin: 0 0 8px;">New waitlist signup</p>
203
+ <p style="margin: 0;"><strong>Email:</strong> ${formatMultilineHtml(email)}</p>
204
+ </div>
205
+ `;
206
+ const teamSend = await sendEmail(configResult.config, {
207
+ to: [configResult.config.teamInbox],
208
+ subject: `New Waitlist Signup: ${email}`,
209
+ text: teamNotificationText,
210
+ html: teamNotificationHtml,
211
+ context: "waitlist-team-notification"
212
+ });
213
+ if (!teamSend.success) {
214
+ return { success: false, text: WAITLIST_SEND_ERROR };
215
+ }
216
+ return { success: true, text: "Successfully joined waitlist!" };
217
+ };
218
+
219
+ // src/libs/email/waitlist-application.ts
220
+ "use server";
221
+ var APPLICATION_MISSING_CONFIG = "Waitlist application service is not configured. Please try again later.";
222
+ var APPLICATION_SEND_ERROR = "Failed to submit application. Please try again later or contact us directly.";
223
+ var submitWaitlistApplication = async (formData) => {
224
+ const email = (formData.get("email") ?? "").toString().trim();
225
+ const name = (formData.get("name") ?? "").toString().trim();
226
+ const company = (formData.get("company") ?? "").toString().trim();
227
+ const role = (formData.get("role") ?? "").toString().trim();
228
+ const useCase = (formData.get("useCase") ?? "").toString().trim();
229
+ const currentStack = (formData.get("currentStack") ?? "").toString().trim();
230
+ const whatBuilding = (formData.get("whatBuilding") ?? "").toString().trim();
231
+ const whatSolving = (formData.get("whatSolving") ?? "").toString().trim();
232
+ const teamSize = (formData.get("teamSize") ?? "").toString().trim();
233
+ const timeline = (formData.get("timeline") ?? "").toString().trim();
234
+ const openToSessions = formData.get("openToSessions") === "on";
235
+ const okayWithCaseStudies = formData.get("okayWithCaseStudies") === "on";
236
+ if (!email || !email.includes("@")) {
237
+ return {
238
+ success: false,
239
+ text: "Please enter a valid email address."
240
+ };
241
+ }
242
+ if (!name || !whatBuilding || !whatSolving) {
243
+ return {
244
+ success: false,
245
+ text: "Please fill in all required fields."
246
+ };
247
+ }
248
+ const configResult = getEmailConfig();
249
+ if (!configResult.ok || !configResult.config) {
250
+ return {
251
+ success: false,
252
+ text: configResult.errorMessage ?? APPLICATION_MISSING_CONFIG
253
+ };
254
+ }
255
+ const applicantText = `
256
+ You're on the list.
257
+
258
+ Thanks for applying to the ContractSpec design partner program. We're slowly onboarding design partners in waves. If your use case is a good fit, we'll reach out personally.
259
+
260
+ What happens next:
261
+ \u2022 We review applications weekly
262
+ \u2022 If selected, we'll reach out via email to schedule an intro call
263
+ \u2022 During early access, you'll get hands-on support and influence over the roadmap
264
+
265
+ In the meantime:
266
+ \u2022 Check out our docs: https://contractspec.io/docs
267
+ \u2022 Book a demo call: https://contractspec.io/contact
268
+
269
+ We're excited about the possibility of working together!
270
+
271
+ ---
272
+ ContractSpec Team
273
+ https://contractspec.io
274
+ `.trim();
275
+ const applicantHtml = `
276
+ <div style="font-family: sans-serif; max-width: 640px; margin: 0 auto;">
277
+ <h1 style="color: #8b5cf6;">You're on the list.</h1>
278
+ <p>Thanks for applying to the ContractSpec design partner program. We're slowly onboarding design partners in waves. If your use case is a good fit, we'll reach out personally.</p>
279
+ <h2 style="color: #8b5cf6; margin-top: 24px;">What happens next:</h2>
280
+ <ul style="line-height: 1.8;">
281
+ <li>We review applications weekly</li>
282
+ <li>If selected, we'll reach out via email to schedule an intro call</li>
283
+ <li>During early access, you'll get hands-on support and influence over the roadmap</li>
284
+ </ul>
285
+ <h2 style="color: #8b5cf6; margin-top: 24px;">In the meantime:</h2>
286
+ <ul style="line-height: 1.8;">
287
+ <li>Check out our <a href="https://contractspec.io/docs" style="color: #8b5cf6;">docs</a></li>
288
+ <li>Book a demo call: <a href="https://contractspec.io/contact" style="color: #8b5cf6;">contractspec.io/contact</a></li>
289
+ </ul>
290
+ <p>We're excited about the possibility of working together!</p>
291
+ <hr style="margin: 30px 0; border: none; border-top: 1px solid #e5e7eb;" />
292
+ <p style="color: #6b7280; font-size: 14px;">
293
+ ContractSpec Team<br />
294
+ <a href="https://contractspec.io" style="color: #8b5cf6;">contractspec.io</a>
295
+ </p>
296
+ </div>
297
+ `;
298
+ const applicantSend = await sendEmail(configResult.config, {
299
+ to: [{ email }],
300
+ subject: "You're on the ContractSpec design partner waitlist!",
301
+ text: applicantText,
302
+ html: applicantHtml,
303
+ context: "waitlist-application-welcome"
304
+ });
305
+ if (!applicantSend.success) {
306
+ return { success: false, text: APPLICATION_SEND_ERROR };
307
+ }
308
+ const preferencesText = `
309
+ Open to 1:1 product/design sessions: ${openToSessions ? "Yes" : "No"}
310
+ Okay with anonymized case studies: ${okayWithCaseStudies ? "Yes" : "No"}
311
+ `.trim();
312
+ const teamEmailText = `
313
+ New Design Partner Waitlist Application
314
+
315
+ Contact Information:
316
+ - Name: ${name}
317
+ - Email: ${email}
318
+ ${company ? `- Company/Project: ${company}` : ""}
319
+ ${role ? `- Role: ${role}` : ""}
320
+
321
+ Application Details:
322
+ - What are you building with AI today?
323
+ ${whatBuilding}
324
+
325
+ - What do you hope ContractSpec will solve for you?
326
+ ${whatSolving}
327
+
328
+ - Primary use case: ${useCase || "Not specified"}
329
+ - Current stack: ${currentStack || "Not specified"}
330
+ - Team Size: ${teamSize || "Not specified"}
331
+ - Timeline: ${timeline || "Not specified"}
332
+
333
+ Preferences:
334
+ - Open to 1:1 product/design sessions: ${openToSessions ? "Yes" : "No"}
335
+ - Okay with anonymized case studies: ${okayWithCaseStudies ? "Yes" : "No"}
336
+
337
+ ---
338
+ Submitted via ContractSpec waitlist application form
339
+ `.trim();
340
+ const teamEmailHtml = `
341
+ <div style="font-family: sans-serif; max-width: 720px; margin: 0 auto;">
342
+ <h1 style="color: #8b5cf6;">New Design Partner Waitlist Application</h1>
343
+ <h2 style="color: #8b5cf6; margin: 16px 0 8px;">Contact Information</h2>
344
+ <ul style="padding-left: 16px; line-height: 1.6; margin: 0 0 16px;">
345
+ <li>Name: ${escapeHtml(name)}</li>
346
+ <li>Email: ${escapeHtml(email)}</li>
347
+ ${company ? `<li>Company/Project: ${escapeHtml(company)}</li>` : ""}
348
+ ${role ? `<li>Role: ${escapeHtml(role)}</li>` : ""}
349
+ </ul>
350
+ <h2 style="color: #8b5cf6; margin: 16px 0 8px;">Application Details</h2>
351
+ <p style="margin: 0 0 8px; font-weight: 600;">What are you building with AI today?</p>
352
+ <div style="border: 1px solid #e5e7eb; border-radius: 8px; padding: 12px; background: #f9fafb; white-space: pre-wrap; line-height: 1.6;">
353
+ ${formatMultilineHtml(whatBuilding)}
354
+ </div>
355
+ <p style="margin: 16px 0 8px; font-weight: 600;">What do you hope ContractSpec will solve for you?</p>
356
+ <div style="border: 1px solid #e5e7eb; border-radius: 8px; padding: 12px; background: #f9fafb; white-space: pre-wrap; line-height: 1.6;">
357
+ ${formatMultilineHtml(whatSolving)}
358
+ </div>
359
+ <ul style="padding-left: 16px; line-height: 1.6; margin: 16px 0;">
360
+ <li>Primary use case: ${escapeHtml(useCase || "Not specified")}</li>
361
+ <li>Current stack: ${escapeHtml(currentStack || "Not specified")}</li>
362
+ <li>Team Size: ${escapeHtml(teamSize || "Not specified")}</li>
363
+ <li>Timeline: ${escapeHtml(timeline || "Not specified")}</li>
364
+ </ul>
365
+ <h2 style="color: #8b5cf6; margin: 16px 0 8px;">Preferences</h2>
366
+ <div style="border: 1px solid #e5e7eb; border-radius: 8px; padding: 12px; background: #f9fafb; line-height: 1.6;">
367
+ ${formatMultilineHtml(preferencesText)}
368
+ </div>
369
+ <p style="color: #6b7280; font-size: 12px; margin-top: 20px;">Submitted via ContractSpec waitlist application form</p>
370
+ </div>
371
+ `;
372
+ const teamSend = await sendEmail(configResult.config, {
373
+ to: [configResult.config.teamInbox],
374
+ subject: `New Design Partner Application: ${name} (${email})`,
375
+ text: teamEmailText,
376
+ html: teamEmailHtml,
377
+ replyTo: email,
378
+ context: "waitlist-application-team-notification"
379
+ });
380
+ if (!teamSend.success) {
381
+ return { success: false, text: APPLICATION_SEND_ERROR };
382
+ }
383
+ return {
384
+ success: true,
385
+ text: "Application submitted successfully!"
386
+ };
387
+ };
388
+
389
+ // src/components/marketing/waitlist-section.tsx
8
390
  import { useEffect, useState } from "react";
9
391
  import { useForm } from "react-hook-form";
10
392
  import { zodResolver } from "@hookform/resolvers/zod";
11
393
  import z from "zod";
394
+ import { AlertCircle, CheckCircle } from "lucide-react";
395
+ import { Button } from "@contractspec/lib.design-system";
396
+ import { Textarea } from "@contractspec/lib.design-system";
12
397
  import { Label } from "@contractspec/lib.ui-kit-web/ui/label";
13
- import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@contractspec/lib.ui-kit-web/ui/select";
398
+ import {
399
+ Select,
400
+ SelectContent,
401
+ SelectItem,
402
+ SelectTrigger,
403
+ SelectValue
404
+ } from "@contractspec/lib.ui-kit-web/ui/select";
14
405
  import { Checkbox } from "@contractspec/lib.ui-kit-web/ui/checkbox";
15
406
  import { Switch } from "@contractspec/lib.ui-kit-web/ui/switch";
16
-
17
- //#region src/components/marketing/waitlist-section.tsx
18
- const simpleWaitlistSchema = z.object({ email: z.email("Please enter a valid email address") });
19
- const designPartnerSchema = z.object({
20
- name: z.string().min(1, "Name is required"),
21
- email: z.email("Please enter a valid email address"),
22
- company: z.string().optional(),
23
- role: z.string().optional(),
24
- useCase: z.string().optional(),
25
- currentStack: z.string().optional(),
26
- whatBuilding: z.string().min(1, "Please tell us what you are building"),
27
- whatSolving: z.string().min(1, "Please tell us what ContractSpec will solve for you"),
28
- teamSize: z.string().optional(),
29
- timeline: z.string().optional(),
30
- openToSessions: z.boolean().default(false),
31
- okayWithCaseStudies: z.boolean().default(false)
407
+ import { Input } from "@contractspec/lib.design-system";
408
+ import { jsxDEV, Fragment } from "react/jsx-dev-runtime";
409
+ "use client";
410
+ var simpleWaitlistSchema = z.object({
411
+ email: z.email("Please enter a valid email address")
412
+ });
413
+ var designPartnerSchema = z.object({
414
+ name: z.string().min(1, "Name is required"),
415
+ email: z.email("Please enter a valid email address"),
416
+ company: z.string().optional(),
417
+ role: z.string().optional(),
418
+ useCase: z.string().optional(),
419
+ currentStack: z.string().optional(),
420
+ whatBuilding: z.string().min(1, "Please tell us what you are building"),
421
+ whatSolving: z.string().min(1, "Please tell us what ContractSpec will solve for you"),
422
+ teamSize: z.string().optional(),
423
+ timeline: z.string().optional(),
424
+ openToSessions: z.boolean().default(false),
425
+ okayWithCaseStudies: z.boolean().default(false)
32
426
  });
33
- function WaitlistSection({ variant = "default", context = "pricing" }) {
34
- const [isDesignPartner, setIsDesignPartner] = useState(false);
35
- const [submitResult, setSubmitResult] = useState(null);
36
- const [isPending, setIsPending] = useState(false);
37
- const simpleForm = useForm({
38
- resolver: zodResolver(simpleWaitlistSchema),
39
- defaultValues: { email: "" }
40
- });
41
- const designPartnerForm = useForm({
42
- resolver: zodResolver(designPartnerSchema),
43
- defaultValues: {
44
- name: "",
45
- email: "",
46
- company: "",
47
- role: "",
48
- useCase: "",
49
- currentStack: "",
50
- whatBuilding: "",
51
- whatSolving: "",
52
- teamSize: "",
53
- timeline: "",
54
- openToSessions: false,
55
- okayWithCaseStudies: false
56
- }
57
- });
58
- const simpleEmail = simpleForm.watch("email");
59
- const designPartnerEmail = designPartnerForm.watch("email");
60
- useEffect(() => {
61
- const currentDesignPartnerEmail = designPartnerForm.getValues("email");
62
- if (simpleEmail && simpleEmail !== currentDesignPartnerEmail) designPartnerForm.setValue("email", simpleEmail, { shouldDirty: false });
63
- }, [simpleEmail, designPartnerForm]);
64
- useEffect(() => {
65
- const currentSimpleEmail = simpleForm.getValues("email");
66
- if (designPartnerEmail && designPartnerEmail !== currentSimpleEmail) simpleForm.setValue("email", designPartnerEmail, { shouldDirty: false });
67
- }, [designPartnerEmail, simpleForm]);
68
- const handleSimpleSubmit = async (data) => {
69
- setIsPending(true);
70
- setSubmitResult(null);
71
- try {
72
- const formData = new FormData();
73
- formData.set("email", data.email);
74
- const result = await joinWaitlist(formData);
75
- if (result.success) {
76
- setSubmitResult({
77
- success: true,
78
- text: "Thanks for joining the waitlist! Check your inbox for a confirmation."
79
- });
80
- simpleForm.reset();
81
- } else setSubmitResult({
82
- success: false,
83
- text: result.text || "Failed to join waitlist. Please try again."
84
- });
85
- } catch (_error) {
86
- setSubmitResult({
87
- success: false,
88
- text: "Failed to join waitlist. Please try again."
89
- });
90
- } finally {
91
- setIsPending(false);
92
- }
93
- };
94
- const handleDesignPartnerSubmit = async (data) => {
95
- setIsPending(true);
96
- setSubmitResult(null);
97
- try {
98
- const formData = new FormData();
99
- formData.set("email", data.email);
100
- formData.set("name", data.name);
101
- if (data.company) formData.set("company", data.company);
102
- if (data.role) formData.set("role", data.role);
103
- if (data.useCase) formData.set("useCase", data.useCase);
104
- if (data.currentStack) formData.set("currentStack", data.currentStack);
105
- formData.set("whatBuilding", data.whatBuilding);
106
- formData.set("whatSolving", data.whatSolving);
107
- if (data.teamSize) formData.set("teamSize", data.teamSize);
108
- if (data.timeline) formData.set("timeline", data.timeline);
109
- if (data.openToSessions) formData.set("openToSessions", "on");
110
- if (data.okayWithCaseStudies) formData.set("okayWithCaseStudies", "on");
111
- const result = await submitWaitlistApplication(formData);
112
- if (result.success) {
113
- setSubmitResult({
114
- success: true,
115
- text: "You're on the list. Thanks for applying. We're slowly onboarding design partners in waves. If your use case is a good fit, we'll reach out personally."
116
- });
117
- designPartnerForm.reset();
118
- } else setSubmitResult({
119
- success: false,
120
- text: result.text || "Failed to submit application. Please try again."
121
- });
122
- } catch (_error) {
123
- setSubmitResult({
124
- success: false,
125
- text: "Failed to submit application. Please try again."
126
- });
127
- } finally {
128
- setIsPending(false);
129
- }
130
- };
131
- const onSubmit = isDesignPartner ? designPartnerForm.handleSubmit(handleDesignPartnerSubmit) : simpleForm.handleSubmit(handleSimpleSubmit);
132
- const isCompact = variant === "compact";
133
- return /* @__PURE__ */ jsxs("div", {
134
- id: "waitlist",
135
- className: isCompact ? "space-y-4" : "card-subtle space-y-6 p-8",
136
- children: [
137
- !isCompact && /* @__PURE__ */ jsxs("div", {
138
- className: "space-y-4",
139
- children: [
140
- /* @__PURE__ */ jsx("div", {
141
- className: "inline-flex items-center gap-2 rounded-full border border-violet-500/20 bg-violet-500/10 px-3 py-1",
142
- children: /* @__PURE__ */ jsx("span", {
143
- className: "text-sm font-medium text-violet-300",
144
- children: isDesignPartner ? "Design Partner Waitlist" : "Join the Waitlist"
145
- })
146
- }),
147
- /* @__PURE__ */ jsx("h2", {
148
- className: "text-2xl font-bold",
149
- children: isDesignPartner ? "Apply for early access to ContractSpec" : "Get early access to ContractSpec"
150
- }),
151
- /* @__PURE__ */ jsx("p", {
152
- className: "text-muted-foreground text-sm",
153
- children: isDesignPartner ? "Tell us what you're building. We'll prioritize teams where ContractSpec can have a big impact, and where we can learn the most." : "Join the waitlist to be notified when ContractSpec becomes available."
154
- })
155
- ]
156
- }),
157
- !isCompact && /* @__PURE__ */ jsxs("div", {
158
- className: "border-border bg-muted/20 flex items-center justify-between gap-4 rounded-lg border p-4",
159
- children: [/* @__PURE__ */ jsxs("div", {
160
- className: "space-y-1",
161
- children: [/* @__PURE__ */ jsx(Label, {
162
- htmlFor: "design-partner-toggle",
163
- className: "text-sm font-medium",
164
- children: "Apply as a design partner"
165
- }), /* @__PURE__ */ jsx("p", {
166
- className: "text-muted-foreground text-xs",
167
- children: isDesignPartner ? "Get hands-on support, influence the roadmap, and founding discount" : "Get priority access, 1:1 onboarding, and help shape ContractSpec"
168
- })]
169
- }), /* @__PURE__ */ jsx(Switch, {
170
- id: "design-partner-toggle",
171
- checked: isDesignPartner,
172
- onCheckedChange: setIsDesignPartner,
173
- disabled: isPending || submitResult?.success
174
- })]
175
- }),
176
- !isCompact && isDesignPartner && /* @__PURE__ */ jsxs("div", {
177
- className: "space-y-2",
178
- children: [/* @__PURE__ */ jsx("p", {
179
- className: "text-sm font-medium",
180
- children: "Benefits:"
181
- }), /* @__PURE__ */ jsxs("ul", {
182
- className: "text-muted-foreground space-y-1 text-sm",
183
- children: [
184
- /* @__PURE__ */ jsx("li", { children: "• Early access to ContractSpec Studio" }),
185
- /* @__PURE__ */ jsx("li", { children: "• 1:1 onboarding and architecture sessions" }),
186
- /* @__PURE__ */ jsx("li", { children: " Priority support via direct channels" }),
187
- /* @__PURE__ */ jsx("li", { children: " Influence over roadmap and features" }),
188
- /* @__PURE__ */ jsx("li", { children: "• Founding discount when paid plans launch" })
189
- ]
190
- })]
191
- }),
192
- /* @__PURE__ */ jsxs("form", {
193
- onSubmit,
194
- className: "space-y-4",
195
- children: [
196
- isDesignPartner ? /* @__PURE__ */ jsxs(Fragment, { children: [
197
- /* @__PURE__ */ jsxs("div", {
198
- className: "grid gap-4 md:grid-cols-2",
199
- children: [/* @__PURE__ */ jsxs("div", {
200
- className: "space-y-2",
201
- children: [
202
- /* @__PURE__ */ jsxs(Label, {
203
- htmlFor: "waitlist-name",
204
- className: "text-sm font-medium",
205
- children: ["Name ", /* @__PURE__ */ jsx("span", {
206
- className: "text-red-400",
207
- children: "*"
208
- })]
209
- }),
210
- /* @__PURE__ */ jsx(Input, {
211
- id: "waitlist-name",
212
- ...designPartnerForm.register("name"),
213
- type: "text",
214
- placeholder: "Your name",
215
- disabled: isPending || submitResult?.success
216
- }),
217
- designPartnerForm.formState.errors.name && /* @__PURE__ */ jsx("p", {
218
- className: "text-xs text-red-400",
219
- children: designPartnerForm.formState.errors.name.message
220
- })
221
- ]
222
- }), /* @__PURE__ */ jsxs("div", {
223
- className: "space-y-2",
224
- children: [
225
- /* @__PURE__ */ jsxs(Label, {
226
- htmlFor: "waitlist-email",
227
- className: "text-sm font-medium",
228
- children: ["Email ", /* @__PURE__ */ jsx("span", {
229
- className: "text-red-400",
230
- children: "*"
231
- })]
232
- }),
233
- /* @__PURE__ */ jsx(Input, {
234
- id: "waitlist-email",
235
- ...designPartnerForm.register("email"),
236
- type: "email",
237
- placeholder: "your@email.com",
238
- disabled: isPending || submitResult?.success
239
- }),
240
- designPartnerForm.formState.errors.email && /* @__PURE__ */ jsx("p", {
241
- className: "text-xs text-red-400",
242
- children: designPartnerForm.formState.errors.email.message
243
- })
244
- ]
245
- })]
246
- }),
247
- /* @__PURE__ */ jsxs("div", {
248
- className: "grid gap-4 md:grid-cols-2",
249
- children: [/* @__PURE__ */ jsxs("div", {
250
- className: "space-y-2",
251
- children: [/* @__PURE__ */ jsx(Label, {
252
- htmlFor: "waitlist-company",
253
- className: "text-sm font-medium",
254
- children: "Company / Project Name"
255
- }), /* @__PURE__ */ jsx(Input, {
256
- id: "waitlist-company",
257
- ...designPartnerForm.register("company"),
258
- type: "text",
259
- placeholder: "Your company or project",
260
- disabled: isPending || submitResult?.success
261
- })]
262
- }), /* @__PURE__ */ jsxs("div", {
263
- className: "space-y-2",
264
- children: [/* @__PURE__ */ jsx(Label, {
265
- htmlFor: "waitlist-role",
266
- className: "text-sm font-medium",
267
- children: "Role"
268
- }), /* @__PURE__ */ jsxs(Select, {
269
- value: designPartnerForm.watch("role") || "",
270
- onValueChange: (value) => designPartnerForm.setValue("role", value),
271
- disabled: isPending || submitResult?.success,
272
- children: [/* @__PURE__ */ jsx(SelectTrigger, {
273
- id: "waitlist-role",
274
- className: "w-full",
275
- children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select your role" })
276
- }), /* @__PURE__ */ jsxs(SelectContent, { children: [
277
- /* @__PURE__ */ jsx(SelectItem, {
278
- value: "founder",
279
- children: "Founder"
280
- }),
281
- /* @__PURE__ */ jsx(SelectItem, {
282
- value: "cto",
283
- children: "CTO"
284
- }),
285
- /* @__PURE__ */ jsx(SelectItem, {
286
- value: "lead-engineer",
287
- children: "Lead Engineer"
288
- }),
289
- /* @__PURE__ */ jsx(SelectItem, {
290
- value: "engineer",
291
- children: "Engineer"
292
- }),
293
- /* @__PURE__ */ jsx(SelectItem, {
294
- value: "product-manager",
295
- children: "Product Manager"
296
- }),
297
- /* @__PURE__ */ jsx(SelectItem, {
298
- value: "other",
299
- children: "Other"
300
- })
301
- ] })]
302
- })]
303
- })]
304
- }),
305
- /* @__PURE__ */ jsxs("div", {
306
- className: "grid gap-4 md:grid-cols-2",
307
- children: [/* @__PURE__ */ jsxs("div", {
308
- className: "space-y-2",
309
- children: [/* @__PURE__ */ jsx(Label, {
310
- htmlFor: "waitlist-use-case",
311
- className: "text-sm font-medium",
312
- children: "Primary use case"
313
- }), /* @__PURE__ */ jsxs(Select, {
314
- value: designPartnerForm.watch("useCase") || "",
315
- onValueChange: (value) => designPartnerForm.setValue("useCase", value),
316
- disabled: isPending || submitResult?.success,
317
- children: [/* @__PURE__ */ jsx(SelectTrigger, {
318
- id: "waitlist-use-case",
319
- className: "w-full",
320
- children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select a use case" })
321
- }), /* @__PURE__ */ jsxs(SelectContent, { children: [
322
- /* @__PURE__ */ jsx(SelectItem, {
323
- value: "api-platform",
324
- children: "API platform"
325
- }),
326
- /* @__PURE__ */ jsx(SelectItem, {
327
- value: "ai-ops",
328
- children: "AI operations"
329
- }),
330
- /* @__PURE__ */ jsx(SelectItem, {
331
- value: "integration-hub",
332
- children: "Integration hub"
333
- }),
334
- /* @__PURE__ */ jsx(SelectItem, {
335
- value: "internal-tools",
336
- children: "Internal tools"
337
- }),
338
- /* @__PURE__ */ jsx(SelectItem, {
339
- value: "data-pipelines",
340
- children: "Data pipelines"
341
- }),
342
- /* @__PURE__ */ jsx(SelectItem, {
343
- value: "other",
344
- children: "Other"
345
- })
346
- ] })]
347
- })]
348
- }), /* @__PURE__ */ jsxs("div", {
349
- className: "space-y-2",
350
- children: [/* @__PURE__ */ jsx(Label, {
351
- htmlFor: "waitlist-current-stack",
352
- className: "text-sm font-medium",
353
- children: "Current stack"
354
- }), /* @__PURE__ */ jsx(Input, {
355
- id: "waitlist-current-stack",
356
- ...designPartnerForm.register("currentStack"),
357
- type: "text",
358
- placeholder: "e.g. Next.js, Postgres, OpenAPI",
359
- disabled: isPending || submitResult?.success
360
- })]
361
- })]
362
- }),
363
- /* @__PURE__ */ jsxs("div", {
364
- className: "space-y-2",
365
- children: [
366
- /* @__PURE__ */ jsxs(Label, {
367
- htmlFor: "waitlist-what-building",
368
- className: "text-sm font-medium",
369
- children: [
370
- "What are you building with AI today?",
371
- " ",
372
- /* @__PURE__ */ jsx("span", {
373
- className: "text-red-400",
374
- children: "*"
375
- })
376
- ]
377
- }),
378
- /* @__PURE__ */ jsx(Textarea, {
379
- id: "waitlist-what-building",
380
- ...designPartnerForm.register("whatBuilding"),
381
- placeholder: "Tell us about your project...",
382
- disabled: isPending || submitResult?.success,
383
- rows: 4
384
- }),
385
- designPartnerForm.formState.errors.whatBuilding && /* @__PURE__ */ jsx("p", {
386
- className: "text-xs text-red-400",
387
- children: designPartnerForm.formState.errors.whatBuilding.message
388
- })
389
- ]
390
- }),
391
- /* @__PURE__ */ jsxs("div", {
392
- className: "space-y-2",
393
- children: [
394
- /* @__PURE__ */ jsxs(Label, {
395
- htmlFor: "waitlist-what-solving",
396
- className: "text-sm font-medium",
397
- children: [
398
- "What do you hope ContractSpec will solve for you?",
399
- " ",
400
- /* @__PURE__ */ jsx("span", {
401
- className: "text-red-400",
402
- children: "*"
403
- })
404
- ]
405
- }),
406
- /* @__PURE__ */ jsx(Textarea, {
407
- id: "waitlist-what-solving",
408
- ...designPartnerForm.register("whatSolving"),
409
- placeholder: "What problems are you trying to solve?",
410
- disabled: isPending || submitResult?.success,
411
- rows: 4
412
- }),
413
- designPartnerForm.formState.errors.whatSolving && /* @__PURE__ */ jsx("p", {
414
- className: "text-xs text-red-400",
415
- children: designPartnerForm.formState.errors.whatSolving.message
416
- })
417
- ]
418
- }),
419
- /* @__PURE__ */ jsxs("div", {
420
- className: "grid gap-4 md:grid-cols-2",
421
- children: [/* @__PURE__ */ jsxs("div", {
422
- className: "space-y-2",
423
- children: [/* @__PURE__ */ jsx(Label, {
424
- htmlFor: "waitlist-team-size",
425
- className: "text-sm font-medium",
426
- children: "Team Size"
427
- }), /* @__PURE__ */ jsxs(Select, {
428
- value: designPartnerForm.watch("teamSize") || "",
429
- onValueChange: (value) => designPartnerForm.setValue("teamSize", value),
430
- disabled: isPending || submitResult?.success,
431
- children: [/* @__PURE__ */ jsx(SelectTrigger, {
432
- id: "waitlist-team-size",
433
- className: "w-full",
434
- children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select team size" })
435
- }), /* @__PURE__ */ jsxs(SelectContent, { children: [
436
- /* @__PURE__ */ jsx(SelectItem, {
437
- value: "solo",
438
- children: "Solo"
439
- }),
440
- /* @__PURE__ */ jsx(SelectItem, {
441
- value: "2-5",
442
- children: "2-5"
443
- }),
444
- /* @__PURE__ */ jsx(SelectItem, {
445
- value: "6-20",
446
- children: "6-20"
447
- }),
448
- /* @__PURE__ */ jsx(SelectItem, {
449
- value: "20+",
450
- children: "20+"
451
- })
452
- ] })]
453
- })]
454
- }), /* @__PURE__ */ jsxs("div", {
455
- className: "space-y-2",
456
- children: [/* @__PURE__ */ jsx(Label, {
457
- htmlFor: "waitlist-timeline",
458
- className: "text-sm font-medium",
459
- children: "Timeline"
460
- }), /* @__PURE__ */ jsxs(Select, {
461
- value: designPartnerForm.watch("timeline") || "",
462
- onValueChange: (value) => designPartnerForm.setValue("timeline", value),
463
- disabled: isPending || submitResult?.success,
464
- children: [/* @__PURE__ */ jsx(SelectTrigger, {
465
- id: "waitlist-timeline",
466
- className: "w-full",
467
- children: /* @__PURE__ */ jsx(SelectValue, { placeholder: "Select timeline" })
468
- }), /* @__PURE__ */ jsxs(SelectContent, { children: [
469
- /* @__PURE__ */ jsx(SelectItem, {
470
- value: "now",
471
- children: "Now"
472
- }),
473
- /* @__PURE__ */ jsx(SelectItem, {
474
- value: "1-3-months",
475
- children: "1-3 months"
476
- }),
477
- /* @__PURE__ */ jsx(SelectItem, {
478
- value: "3-6-months",
479
- children: "3-6 months"
480
- }),
481
- /* @__PURE__ */ jsx(SelectItem, {
482
- value: "exploring",
483
- children: "Exploring"
484
- })
485
- ] })]
486
- })]
487
- })]
488
- }),
489
- /* @__PURE__ */ jsxs("div", {
490
- className: "space-y-3",
491
- children: [/* @__PURE__ */ jsxs("div", {
492
- className: "flex items-start gap-3",
493
- children: [/* @__PURE__ */ jsx(Checkbox, {
494
- id: "waitlist-open-to-sessions",
495
- checked: designPartnerForm.watch("openToSessions"),
496
- onCheckedChange: (checked) => designPartnerForm.setValue("openToSessions", checked === true),
497
- disabled: isPending || submitResult?.success
498
- }), /* @__PURE__ */ jsx(Label, {
499
- htmlFor: "waitlist-open-to-sessions",
500
- className: "cursor-pointer text-sm leading-relaxed",
501
- children: "I'm open to 1:1 product/design sessions"
502
- })]
503
- }), /* @__PURE__ */ jsxs("div", {
504
- className: "flex items-start gap-3",
505
- children: [/* @__PURE__ */ jsx(Checkbox, {
506
- id: "waitlist-case-studies",
507
- checked: designPartnerForm.watch("okayWithCaseStudies"),
508
- onCheckedChange: (checked) => designPartnerForm.setValue("okayWithCaseStudies", checked === true),
509
- disabled: isPending || submitResult?.success
510
- }), /* @__PURE__ */ jsx(Label, {
511
- htmlFor: "waitlist-case-studies",
512
- className: "cursor-pointer text-sm leading-relaxed",
513
- children: "I'm okay with anonymized case studies about our usage"
514
- })]
515
- })]
516
- })
517
- ] }) : /* @__PURE__ */ jsxs("div", {
518
- className: "space-y-2",
519
- children: [
520
- /* @__PURE__ */ jsxs(Label, {
521
- htmlFor: "waitlist-email",
522
- className: "text-sm font-medium",
523
- children: ["Email ", /* @__PURE__ */ jsx("span", {
524
- className: "text-red-400",
525
- children: "*"
526
- })]
527
- }),
528
- /* @__PURE__ */ jsx(Input, {
529
- id: "waitlist-email",
530
- ...simpleForm.register("email"),
531
- type: "email",
532
- placeholder: "your@email.com",
533
- disabled: isPending || submitResult?.success
534
- }),
535
- simpleForm.formState.errors.email && /* @__PURE__ */ jsx("p", {
536
- className: "text-xs text-red-400",
537
- children: simpleForm.formState.errors.email.message
538
- })
539
- ]
540
- }),
541
- submitResult && !isPending && /* @__PURE__ */ jsxs("div", {
542
- className: `flex items-start gap-2 rounded-lg p-4 text-sm ${submitResult.success ? "border border-green-500/20 bg-green-500/10 text-green-400" : "border border-red-500/20 bg-red-500/10 text-red-400"}`,
543
- children: [submitResult.success ? /* @__PURE__ */ jsx(CheckCircle, {
544
- size: 20,
545
- className: "mt-0.5 shrink-0"
546
- }) : /* @__PURE__ */ jsx(AlertCircle, {
547
- size: 20,
548
- className: "mt-0.5 shrink-0"
549
- }), /* @__PURE__ */ jsx("div", {
550
- className: "flex-1",
551
- children: submitResult.success ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("p", {
552
- className: "mb-1 font-semibold",
553
- children: "You're on the list."
554
- }), /* @__PURE__ */ jsx("p", {
555
- className: "text-sm",
556
- children: submitResult.text
557
- })] }) : /* @__PURE__ */ jsx("p", { children: submitResult.text })
558
- })]
559
- }),
560
- /* @__PURE__ */ jsx(Button, {
561
- type: "submit",
562
- disabled: isPending || submitResult?.success,
563
- className: "w-full",
564
- children: isPending ? "Submitting..." : isDesignPartner ? "Apply to the waitlist" : "Join waitlist"
565
- }),
566
- /* @__PURE__ */ jsx("p", {
567
- className: "text-muted-foreground text-center text-xs",
568
- children: "No spam. We'll only email you about ContractSpec and your application."
569
- })
570
- ]
571
- })
572
- ]
573
- });
427
+ function WaitlistSection({
428
+ variant = "default",
429
+ context = "pricing"
430
+ }) {
431
+ const [isDesignPartner, setIsDesignPartner] = useState(false);
432
+ const [submitResult, setSubmitResult] = useState(null);
433
+ const [isPending, setIsPending] = useState(false);
434
+ const simpleForm = useForm({
435
+ resolver: zodResolver(simpleWaitlistSchema),
436
+ defaultValues: {
437
+ email: ""
438
+ }
439
+ });
440
+ const designPartnerForm = useForm({
441
+ resolver: zodResolver(designPartnerSchema),
442
+ defaultValues: {
443
+ name: "",
444
+ email: "",
445
+ company: "",
446
+ role: "",
447
+ useCase: "",
448
+ currentStack: "",
449
+ whatBuilding: "",
450
+ whatSolving: "",
451
+ teamSize: "",
452
+ timeline: "",
453
+ openToSessions: false,
454
+ okayWithCaseStudies: false
455
+ }
456
+ });
457
+ const simpleEmail = simpleForm.watch("email");
458
+ const designPartnerEmail = designPartnerForm.watch("email");
459
+ useEffect(() => {
460
+ const currentDesignPartnerEmail = designPartnerForm.getValues("email");
461
+ if (simpleEmail && simpleEmail !== currentDesignPartnerEmail) {
462
+ designPartnerForm.setValue("email", simpleEmail, { shouldDirty: false });
463
+ }
464
+ }, [simpleEmail, designPartnerForm]);
465
+ useEffect(() => {
466
+ const currentSimpleEmail = simpleForm.getValues("email");
467
+ if (designPartnerEmail && designPartnerEmail !== currentSimpleEmail) {
468
+ simpleForm.setValue("email", designPartnerEmail, { shouldDirty: false });
469
+ }
470
+ }, [designPartnerEmail, simpleForm]);
471
+ const handleSimpleSubmit = async (data) => {
472
+ setIsPending(true);
473
+ setSubmitResult(null);
474
+ try {
475
+ const formData = new FormData;
476
+ formData.set("email", data.email);
477
+ const result = await joinWaitlist(formData);
478
+ if (result.success) {
479
+ setSubmitResult({
480
+ success: true,
481
+ text: "Thanks for joining the waitlist! Check your inbox for a confirmation."
482
+ });
483
+ simpleForm.reset();
484
+ } else {
485
+ setSubmitResult({
486
+ success: false,
487
+ text: result.text || "Failed to join waitlist. Please try again."
488
+ });
489
+ }
490
+ } catch (_error) {
491
+ setSubmitResult({
492
+ success: false,
493
+ text: "Failed to join waitlist. Please try again."
494
+ });
495
+ } finally {
496
+ setIsPending(false);
497
+ }
498
+ };
499
+ const handleDesignPartnerSubmit = async (data) => {
500
+ setIsPending(true);
501
+ setSubmitResult(null);
502
+ try {
503
+ const formData = new FormData;
504
+ formData.set("email", data.email);
505
+ formData.set("name", data.name);
506
+ if (data.company)
507
+ formData.set("company", data.company);
508
+ if (data.role)
509
+ formData.set("role", data.role);
510
+ if (data.useCase)
511
+ formData.set("useCase", data.useCase);
512
+ if (data.currentStack)
513
+ formData.set("currentStack", data.currentStack);
514
+ formData.set("whatBuilding", data.whatBuilding);
515
+ formData.set("whatSolving", data.whatSolving);
516
+ if (data.teamSize)
517
+ formData.set("teamSize", data.teamSize);
518
+ if (data.timeline)
519
+ formData.set("timeline", data.timeline);
520
+ if (data.openToSessions)
521
+ formData.set("openToSessions", "on");
522
+ if (data.okayWithCaseStudies)
523
+ formData.set("okayWithCaseStudies", "on");
524
+ const result = await submitWaitlistApplication(formData);
525
+ if (result.success) {
526
+ setSubmitResult({
527
+ success: true,
528
+ text: "You're on the list. Thanks for applying. We're slowly onboarding design partners in waves. If your use case is a good fit, we'll reach out personally."
529
+ });
530
+ designPartnerForm.reset();
531
+ } else {
532
+ setSubmitResult({
533
+ success: false,
534
+ text: result.text || "Failed to submit application. Please try again."
535
+ });
536
+ }
537
+ } catch (_error) {
538
+ setSubmitResult({
539
+ success: false,
540
+ text: "Failed to submit application. Please try again."
541
+ });
542
+ } finally {
543
+ setIsPending(false);
544
+ }
545
+ };
546
+ const onSubmit = isDesignPartner ? designPartnerForm.handleSubmit(handleDesignPartnerSubmit) : simpleForm.handleSubmit(handleSimpleSubmit);
547
+ const isCompact = variant === "compact";
548
+ return /* @__PURE__ */ jsxDEV("div", {
549
+ id: "waitlist",
550
+ className: isCompact ? "space-y-4" : "card-subtle space-y-6 p-8",
551
+ children: [
552
+ !isCompact && /* @__PURE__ */ jsxDEV("div", {
553
+ className: "space-y-4",
554
+ children: [
555
+ /* @__PURE__ */ jsxDEV("div", {
556
+ className: "inline-flex items-center gap-2 rounded-full border border-violet-500/20 bg-violet-500/10 px-3 py-1",
557
+ children: /* @__PURE__ */ jsxDEV("span", {
558
+ className: "text-sm font-medium text-violet-300",
559
+ children: isDesignPartner ? "Design Partner Waitlist" : "Join the Waitlist"
560
+ }, undefined, false, undefined, this)
561
+ }, undefined, false, undefined, this),
562
+ /* @__PURE__ */ jsxDEV("h2", {
563
+ className: "text-2xl font-bold",
564
+ children: isDesignPartner ? "Apply for early access to ContractSpec" : "Get early access to ContractSpec"
565
+ }, undefined, false, undefined, this),
566
+ /* @__PURE__ */ jsxDEV("p", {
567
+ className: "text-muted-foreground text-sm",
568
+ children: isDesignPartner ? "Tell us what you're building. We'll prioritize teams where ContractSpec can have a big impact, and where we can learn the most." : "Join the waitlist to be notified when ContractSpec becomes available."
569
+ }, undefined, false, undefined, this)
570
+ ]
571
+ }, undefined, true, undefined, this),
572
+ !isCompact && /* @__PURE__ */ jsxDEV("div", {
573
+ className: "border-border bg-muted/20 flex items-center justify-between gap-4 rounded-lg border p-4",
574
+ children: [
575
+ /* @__PURE__ */ jsxDEV("div", {
576
+ className: "space-y-1",
577
+ children: [
578
+ /* @__PURE__ */ jsxDEV(Label, {
579
+ htmlFor: "design-partner-toggle",
580
+ className: "text-sm font-medium",
581
+ children: "Apply as a design partner"
582
+ }, undefined, false, undefined, this),
583
+ /* @__PURE__ */ jsxDEV("p", {
584
+ className: "text-muted-foreground text-xs",
585
+ children: isDesignPartner ? "Get hands-on support, influence the roadmap, and founding discount" : "Get priority access, 1:1 onboarding, and help shape ContractSpec"
586
+ }, undefined, false, undefined, this)
587
+ ]
588
+ }, undefined, true, undefined, this),
589
+ /* @__PURE__ */ jsxDEV(Switch, {
590
+ id: "design-partner-toggle",
591
+ checked: isDesignPartner,
592
+ onCheckedChange: setIsDesignPartner,
593
+ disabled: isPending || submitResult?.success
594
+ }, undefined, false, undefined, this)
595
+ ]
596
+ }, undefined, true, undefined, this),
597
+ !isCompact && isDesignPartner && /* @__PURE__ */ jsxDEV("div", {
598
+ className: "space-y-2",
599
+ children: [
600
+ /* @__PURE__ */ jsxDEV("p", {
601
+ className: "text-sm font-medium",
602
+ children: "Benefits:"
603
+ }, undefined, false, undefined, this),
604
+ /* @__PURE__ */ jsxDEV("ul", {
605
+ className: "text-muted-foreground space-y-1 text-sm",
606
+ children: [
607
+ /* @__PURE__ */ jsxDEV("li", {
608
+ children: "\u2022 Early access to ContractSpec Studio"
609
+ }, undefined, false, undefined, this),
610
+ /* @__PURE__ */ jsxDEV("li", {
611
+ children: "\u2022 1:1 onboarding and architecture sessions"
612
+ }, undefined, false, undefined, this),
613
+ /* @__PURE__ */ jsxDEV("li", {
614
+ children: "\u2022 Priority support via direct channels"
615
+ }, undefined, false, undefined, this),
616
+ /* @__PURE__ */ jsxDEV("li", {
617
+ children: "\u2022 Influence over roadmap and features"
618
+ }, undefined, false, undefined, this),
619
+ /* @__PURE__ */ jsxDEV("li", {
620
+ children: "\u2022 Founding discount when paid plans launch"
621
+ }, undefined, false, undefined, this)
622
+ ]
623
+ }, undefined, true, undefined, this)
624
+ ]
625
+ }, undefined, true, undefined, this),
626
+ /* @__PURE__ */ jsxDEV("form", {
627
+ onSubmit,
628
+ className: "space-y-4",
629
+ children: [
630
+ isDesignPartner ? /* @__PURE__ */ jsxDEV(Fragment, {
631
+ children: [
632
+ /* @__PURE__ */ jsxDEV("div", {
633
+ className: "grid gap-4 md:grid-cols-2",
634
+ children: [
635
+ /* @__PURE__ */ jsxDEV("div", {
636
+ className: "space-y-2",
637
+ children: [
638
+ /* @__PURE__ */ jsxDEV(Label, {
639
+ htmlFor: "waitlist-name",
640
+ className: "text-sm font-medium",
641
+ children: [
642
+ "Name ",
643
+ /* @__PURE__ */ jsxDEV("span", {
644
+ className: "text-red-400",
645
+ children: "*"
646
+ }, undefined, false, undefined, this)
647
+ ]
648
+ }, undefined, true, undefined, this),
649
+ /* @__PURE__ */ jsxDEV(Input, {
650
+ id: "waitlist-name",
651
+ ...designPartnerForm.register("name"),
652
+ type: "text",
653
+ placeholder: "Your name",
654
+ disabled: isPending || submitResult?.success
655
+ }, undefined, false, undefined, this),
656
+ designPartnerForm.formState.errors.name && /* @__PURE__ */ jsxDEV("p", {
657
+ className: "text-xs text-red-400",
658
+ children: designPartnerForm.formState.errors.name.message
659
+ }, undefined, false, undefined, this)
660
+ ]
661
+ }, undefined, true, undefined, this),
662
+ /* @__PURE__ */ jsxDEV("div", {
663
+ className: "space-y-2",
664
+ children: [
665
+ /* @__PURE__ */ jsxDEV(Label, {
666
+ htmlFor: "waitlist-email",
667
+ className: "text-sm font-medium",
668
+ children: [
669
+ "Email ",
670
+ /* @__PURE__ */ jsxDEV("span", {
671
+ className: "text-red-400",
672
+ children: "*"
673
+ }, undefined, false, undefined, this)
674
+ ]
675
+ }, undefined, true, undefined, this),
676
+ /* @__PURE__ */ jsxDEV(Input, {
677
+ id: "waitlist-email",
678
+ ...designPartnerForm.register("email"),
679
+ type: "email",
680
+ placeholder: "your@email.com",
681
+ disabled: isPending || submitResult?.success
682
+ }, undefined, false, undefined, this),
683
+ designPartnerForm.formState.errors.email && /* @__PURE__ */ jsxDEV("p", {
684
+ className: "text-xs text-red-400",
685
+ children: designPartnerForm.formState.errors.email.message
686
+ }, undefined, false, undefined, this)
687
+ ]
688
+ }, undefined, true, undefined, this)
689
+ ]
690
+ }, undefined, true, undefined, this),
691
+ /* @__PURE__ */ jsxDEV("div", {
692
+ className: "grid gap-4 md:grid-cols-2",
693
+ children: [
694
+ /* @__PURE__ */ jsxDEV("div", {
695
+ className: "space-y-2",
696
+ children: [
697
+ /* @__PURE__ */ jsxDEV(Label, {
698
+ htmlFor: "waitlist-company",
699
+ className: "text-sm font-medium",
700
+ children: "Company / Project Name"
701
+ }, undefined, false, undefined, this),
702
+ /* @__PURE__ */ jsxDEV(Input, {
703
+ id: "waitlist-company",
704
+ ...designPartnerForm.register("company"),
705
+ type: "text",
706
+ placeholder: "Your company or project",
707
+ disabled: isPending || submitResult?.success
708
+ }, undefined, false, undefined, this)
709
+ ]
710
+ }, undefined, true, undefined, this),
711
+ /* @__PURE__ */ jsxDEV("div", {
712
+ className: "space-y-2",
713
+ children: [
714
+ /* @__PURE__ */ jsxDEV(Label, {
715
+ htmlFor: "waitlist-role",
716
+ className: "text-sm font-medium",
717
+ children: "Role"
718
+ }, undefined, false, undefined, this),
719
+ /* @__PURE__ */ jsxDEV(Select, {
720
+ value: designPartnerForm.watch("role") || "",
721
+ onValueChange: (value) => designPartnerForm.setValue("role", value),
722
+ disabled: isPending || submitResult?.success,
723
+ children: [
724
+ /* @__PURE__ */ jsxDEV(SelectTrigger, {
725
+ id: "waitlist-role",
726
+ className: "w-full",
727
+ children: /* @__PURE__ */ jsxDEV(SelectValue, {
728
+ placeholder: "Select your role"
729
+ }, undefined, false, undefined, this)
730
+ }, undefined, false, undefined, this),
731
+ /* @__PURE__ */ jsxDEV(SelectContent, {
732
+ children: [
733
+ /* @__PURE__ */ jsxDEV(SelectItem, {
734
+ value: "founder",
735
+ children: "Founder"
736
+ }, undefined, false, undefined, this),
737
+ /* @__PURE__ */ jsxDEV(SelectItem, {
738
+ value: "cto",
739
+ children: "CTO"
740
+ }, undefined, false, undefined, this),
741
+ /* @__PURE__ */ jsxDEV(SelectItem, {
742
+ value: "lead-engineer",
743
+ children: "Lead Engineer"
744
+ }, undefined, false, undefined, this),
745
+ /* @__PURE__ */ jsxDEV(SelectItem, {
746
+ value: "engineer",
747
+ children: "Engineer"
748
+ }, undefined, false, undefined, this),
749
+ /* @__PURE__ */ jsxDEV(SelectItem, {
750
+ value: "product-manager",
751
+ children: "Product Manager"
752
+ }, undefined, false, undefined, this),
753
+ /* @__PURE__ */ jsxDEV(SelectItem, {
754
+ value: "other",
755
+ children: "Other"
756
+ }, undefined, false, undefined, this)
757
+ ]
758
+ }, undefined, true, undefined, this)
759
+ ]
760
+ }, undefined, true, undefined, this)
761
+ ]
762
+ }, undefined, true, undefined, this)
763
+ ]
764
+ }, undefined, true, undefined, this),
765
+ /* @__PURE__ */ jsxDEV("div", {
766
+ className: "grid gap-4 md:grid-cols-2",
767
+ children: [
768
+ /* @__PURE__ */ jsxDEV("div", {
769
+ className: "space-y-2",
770
+ children: [
771
+ /* @__PURE__ */ jsxDEV(Label, {
772
+ htmlFor: "waitlist-use-case",
773
+ className: "text-sm font-medium",
774
+ children: "Primary use case"
775
+ }, undefined, false, undefined, this),
776
+ /* @__PURE__ */ jsxDEV(Select, {
777
+ value: designPartnerForm.watch("useCase") || "",
778
+ onValueChange: (value) => designPartnerForm.setValue("useCase", value),
779
+ disabled: isPending || submitResult?.success,
780
+ children: [
781
+ /* @__PURE__ */ jsxDEV(SelectTrigger, {
782
+ id: "waitlist-use-case",
783
+ className: "w-full",
784
+ children: /* @__PURE__ */ jsxDEV(SelectValue, {
785
+ placeholder: "Select a use case"
786
+ }, undefined, false, undefined, this)
787
+ }, undefined, false, undefined, this),
788
+ /* @__PURE__ */ jsxDEV(SelectContent, {
789
+ children: [
790
+ /* @__PURE__ */ jsxDEV(SelectItem, {
791
+ value: "api-platform",
792
+ children: "API platform"
793
+ }, undefined, false, undefined, this),
794
+ /* @__PURE__ */ jsxDEV(SelectItem, {
795
+ value: "ai-ops",
796
+ children: "AI operations"
797
+ }, undefined, false, undefined, this),
798
+ /* @__PURE__ */ jsxDEV(SelectItem, {
799
+ value: "integration-hub",
800
+ children: "Integration hub"
801
+ }, undefined, false, undefined, this),
802
+ /* @__PURE__ */ jsxDEV(SelectItem, {
803
+ value: "internal-tools",
804
+ children: "Internal tools"
805
+ }, undefined, false, undefined, this),
806
+ /* @__PURE__ */ jsxDEV(SelectItem, {
807
+ value: "data-pipelines",
808
+ children: "Data pipelines"
809
+ }, undefined, false, undefined, this),
810
+ /* @__PURE__ */ jsxDEV(SelectItem, {
811
+ value: "other",
812
+ children: "Other"
813
+ }, undefined, false, undefined, this)
814
+ ]
815
+ }, undefined, true, undefined, this)
816
+ ]
817
+ }, undefined, true, undefined, this)
818
+ ]
819
+ }, undefined, true, undefined, this),
820
+ /* @__PURE__ */ jsxDEV("div", {
821
+ className: "space-y-2",
822
+ children: [
823
+ /* @__PURE__ */ jsxDEV(Label, {
824
+ htmlFor: "waitlist-current-stack",
825
+ className: "text-sm font-medium",
826
+ children: "Current stack"
827
+ }, undefined, false, undefined, this),
828
+ /* @__PURE__ */ jsxDEV(Input, {
829
+ id: "waitlist-current-stack",
830
+ ...designPartnerForm.register("currentStack"),
831
+ type: "text",
832
+ placeholder: "e.g. Next.js, Postgres, OpenAPI",
833
+ disabled: isPending || submitResult?.success
834
+ }, undefined, false, undefined, this)
835
+ ]
836
+ }, undefined, true, undefined, this)
837
+ ]
838
+ }, undefined, true, undefined, this),
839
+ /* @__PURE__ */ jsxDEV("div", {
840
+ className: "space-y-2",
841
+ children: [
842
+ /* @__PURE__ */ jsxDEV(Label, {
843
+ htmlFor: "waitlist-what-building",
844
+ className: "text-sm font-medium",
845
+ children: [
846
+ "What are you building with AI today?",
847
+ " ",
848
+ /* @__PURE__ */ jsxDEV("span", {
849
+ className: "text-red-400",
850
+ children: "*"
851
+ }, undefined, false, undefined, this)
852
+ ]
853
+ }, undefined, true, undefined, this),
854
+ /* @__PURE__ */ jsxDEV(Textarea, {
855
+ id: "waitlist-what-building",
856
+ ...designPartnerForm.register("whatBuilding"),
857
+ placeholder: "Tell us about your project...",
858
+ disabled: isPending || submitResult?.success,
859
+ rows: 4
860
+ }, undefined, false, undefined, this),
861
+ designPartnerForm.formState.errors.whatBuilding && /* @__PURE__ */ jsxDEV("p", {
862
+ className: "text-xs text-red-400",
863
+ children: designPartnerForm.formState.errors.whatBuilding.message
864
+ }, undefined, false, undefined, this)
865
+ ]
866
+ }, undefined, true, undefined, this),
867
+ /* @__PURE__ */ jsxDEV("div", {
868
+ className: "space-y-2",
869
+ children: [
870
+ /* @__PURE__ */ jsxDEV(Label, {
871
+ htmlFor: "waitlist-what-solving",
872
+ className: "text-sm font-medium",
873
+ children: [
874
+ "What do you hope ContractSpec will solve for you?",
875
+ " ",
876
+ /* @__PURE__ */ jsxDEV("span", {
877
+ className: "text-red-400",
878
+ children: "*"
879
+ }, undefined, false, undefined, this)
880
+ ]
881
+ }, undefined, true, undefined, this),
882
+ /* @__PURE__ */ jsxDEV(Textarea, {
883
+ id: "waitlist-what-solving",
884
+ ...designPartnerForm.register("whatSolving"),
885
+ placeholder: "What problems are you trying to solve?",
886
+ disabled: isPending || submitResult?.success,
887
+ rows: 4
888
+ }, undefined, false, undefined, this),
889
+ designPartnerForm.formState.errors.whatSolving && /* @__PURE__ */ jsxDEV("p", {
890
+ className: "text-xs text-red-400",
891
+ children: designPartnerForm.formState.errors.whatSolving.message
892
+ }, undefined, false, undefined, this)
893
+ ]
894
+ }, undefined, true, undefined, this),
895
+ /* @__PURE__ */ jsxDEV("div", {
896
+ className: "grid gap-4 md:grid-cols-2",
897
+ children: [
898
+ /* @__PURE__ */ jsxDEV("div", {
899
+ className: "space-y-2",
900
+ children: [
901
+ /* @__PURE__ */ jsxDEV(Label, {
902
+ htmlFor: "waitlist-team-size",
903
+ className: "text-sm font-medium",
904
+ children: "Team Size"
905
+ }, undefined, false, undefined, this),
906
+ /* @__PURE__ */ jsxDEV(Select, {
907
+ value: designPartnerForm.watch("teamSize") || "",
908
+ onValueChange: (value) => designPartnerForm.setValue("teamSize", value),
909
+ disabled: isPending || submitResult?.success,
910
+ children: [
911
+ /* @__PURE__ */ jsxDEV(SelectTrigger, {
912
+ id: "waitlist-team-size",
913
+ className: "w-full",
914
+ children: /* @__PURE__ */ jsxDEV(SelectValue, {
915
+ placeholder: "Select team size"
916
+ }, undefined, false, undefined, this)
917
+ }, undefined, false, undefined, this),
918
+ /* @__PURE__ */ jsxDEV(SelectContent, {
919
+ children: [
920
+ /* @__PURE__ */ jsxDEV(SelectItem, {
921
+ value: "solo",
922
+ children: "Solo"
923
+ }, undefined, false, undefined, this),
924
+ /* @__PURE__ */ jsxDEV(SelectItem, {
925
+ value: "2-5",
926
+ children: "2-5"
927
+ }, undefined, false, undefined, this),
928
+ /* @__PURE__ */ jsxDEV(SelectItem, {
929
+ value: "6-20",
930
+ children: "6-20"
931
+ }, undefined, false, undefined, this),
932
+ /* @__PURE__ */ jsxDEV(SelectItem, {
933
+ value: "20+",
934
+ children: "20+"
935
+ }, undefined, false, undefined, this)
936
+ ]
937
+ }, undefined, true, undefined, this)
938
+ ]
939
+ }, undefined, true, undefined, this)
940
+ ]
941
+ }, undefined, true, undefined, this),
942
+ /* @__PURE__ */ jsxDEV("div", {
943
+ className: "space-y-2",
944
+ children: [
945
+ /* @__PURE__ */ jsxDEV(Label, {
946
+ htmlFor: "waitlist-timeline",
947
+ className: "text-sm font-medium",
948
+ children: "Timeline"
949
+ }, undefined, false, undefined, this),
950
+ /* @__PURE__ */ jsxDEV(Select, {
951
+ value: designPartnerForm.watch("timeline") || "",
952
+ onValueChange: (value) => designPartnerForm.setValue("timeline", value),
953
+ disabled: isPending || submitResult?.success,
954
+ children: [
955
+ /* @__PURE__ */ jsxDEV(SelectTrigger, {
956
+ id: "waitlist-timeline",
957
+ className: "w-full",
958
+ children: /* @__PURE__ */ jsxDEV(SelectValue, {
959
+ placeholder: "Select timeline"
960
+ }, undefined, false, undefined, this)
961
+ }, undefined, false, undefined, this),
962
+ /* @__PURE__ */ jsxDEV(SelectContent, {
963
+ children: [
964
+ /* @__PURE__ */ jsxDEV(SelectItem, {
965
+ value: "now",
966
+ children: "Now"
967
+ }, undefined, false, undefined, this),
968
+ /* @__PURE__ */ jsxDEV(SelectItem, {
969
+ value: "1-3-months",
970
+ children: "1-3 months"
971
+ }, undefined, false, undefined, this),
972
+ /* @__PURE__ */ jsxDEV(SelectItem, {
973
+ value: "3-6-months",
974
+ children: "3-6 months"
975
+ }, undefined, false, undefined, this),
976
+ /* @__PURE__ */ jsxDEV(SelectItem, {
977
+ value: "exploring",
978
+ children: "Exploring"
979
+ }, undefined, false, undefined, this)
980
+ ]
981
+ }, undefined, true, undefined, this)
982
+ ]
983
+ }, undefined, true, undefined, this)
984
+ ]
985
+ }, undefined, true, undefined, this)
986
+ ]
987
+ }, undefined, true, undefined, this),
988
+ /* @__PURE__ */ jsxDEV("div", {
989
+ className: "space-y-3",
990
+ children: [
991
+ /* @__PURE__ */ jsxDEV("div", {
992
+ className: "flex items-start gap-3",
993
+ children: [
994
+ /* @__PURE__ */ jsxDEV(Checkbox, {
995
+ id: "waitlist-open-to-sessions",
996
+ checked: designPartnerForm.watch("openToSessions"),
997
+ onCheckedChange: (checked) => designPartnerForm.setValue("openToSessions", checked === true),
998
+ disabled: isPending || submitResult?.success
999
+ }, undefined, false, undefined, this),
1000
+ /* @__PURE__ */ jsxDEV(Label, {
1001
+ htmlFor: "waitlist-open-to-sessions",
1002
+ className: "cursor-pointer text-sm leading-relaxed",
1003
+ children: "I'm open to 1:1 product/design sessions"
1004
+ }, undefined, false, undefined, this)
1005
+ ]
1006
+ }, undefined, true, undefined, this),
1007
+ /* @__PURE__ */ jsxDEV("div", {
1008
+ className: "flex items-start gap-3",
1009
+ children: [
1010
+ /* @__PURE__ */ jsxDEV(Checkbox, {
1011
+ id: "waitlist-case-studies",
1012
+ checked: designPartnerForm.watch("okayWithCaseStudies"),
1013
+ onCheckedChange: (checked) => designPartnerForm.setValue("okayWithCaseStudies", checked === true),
1014
+ disabled: isPending || submitResult?.success
1015
+ }, undefined, false, undefined, this),
1016
+ /* @__PURE__ */ jsxDEV(Label, {
1017
+ htmlFor: "waitlist-case-studies",
1018
+ className: "cursor-pointer text-sm leading-relaxed",
1019
+ children: "I'm okay with anonymized case studies about our usage"
1020
+ }, undefined, false, undefined, this)
1021
+ ]
1022
+ }, undefined, true, undefined, this)
1023
+ ]
1024
+ }, undefined, true, undefined, this)
1025
+ ]
1026
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV("div", {
1027
+ className: "space-y-2",
1028
+ children: [
1029
+ /* @__PURE__ */ jsxDEV(Label, {
1030
+ htmlFor: "waitlist-email",
1031
+ className: "text-sm font-medium",
1032
+ children: [
1033
+ "Email ",
1034
+ /* @__PURE__ */ jsxDEV("span", {
1035
+ className: "text-red-400",
1036
+ children: "*"
1037
+ }, undefined, false, undefined, this)
1038
+ ]
1039
+ }, undefined, true, undefined, this),
1040
+ /* @__PURE__ */ jsxDEV(Input, {
1041
+ id: "waitlist-email",
1042
+ ...simpleForm.register("email"),
1043
+ type: "email",
1044
+ placeholder: "your@email.com",
1045
+ disabled: isPending || submitResult?.success
1046
+ }, undefined, false, undefined, this),
1047
+ simpleForm.formState.errors.email && /* @__PURE__ */ jsxDEV("p", {
1048
+ className: "text-xs text-red-400",
1049
+ children: simpleForm.formState.errors.email.message
1050
+ }, undefined, false, undefined, this)
1051
+ ]
1052
+ }, undefined, true, undefined, this),
1053
+ submitResult && !isPending && /* @__PURE__ */ jsxDEV("div", {
1054
+ className: `flex items-start gap-2 rounded-lg p-4 text-sm ${submitResult.success ? "border border-green-500/20 bg-green-500/10 text-green-400" : "border border-red-500/20 bg-red-500/10 text-red-400"}`,
1055
+ children: [
1056
+ submitResult.success ? /* @__PURE__ */ jsxDEV(CheckCircle, {
1057
+ size: 20,
1058
+ className: "mt-0.5 shrink-0"
1059
+ }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV(AlertCircle, {
1060
+ size: 20,
1061
+ className: "mt-0.5 shrink-0"
1062
+ }, undefined, false, undefined, this),
1063
+ /* @__PURE__ */ jsxDEV("div", {
1064
+ className: "flex-1",
1065
+ children: submitResult.success ? /* @__PURE__ */ jsxDEV(Fragment, {
1066
+ children: [
1067
+ /* @__PURE__ */ jsxDEV("p", {
1068
+ className: "mb-1 font-semibold",
1069
+ children: "You're on the list."
1070
+ }, undefined, false, undefined, this),
1071
+ /* @__PURE__ */ jsxDEV("p", {
1072
+ className: "text-sm",
1073
+ children: submitResult.text
1074
+ }, undefined, false, undefined, this)
1075
+ ]
1076
+ }, undefined, true, undefined, this) : /* @__PURE__ */ jsxDEV("p", {
1077
+ children: submitResult.text
1078
+ }, undefined, false, undefined, this)
1079
+ }, undefined, false, undefined, this)
1080
+ ]
1081
+ }, undefined, true, undefined, this),
1082
+ /* @__PURE__ */ jsxDEV(Button, {
1083
+ type: "submit",
1084
+ disabled: isPending || submitResult?.success,
1085
+ className: "w-full",
1086
+ children: isPending ? "Submitting..." : isDesignPartner ? "Apply to the waitlist" : "Join waitlist"
1087
+ }, undefined, false, undefined, this),
1088
+ /* @__PURE__ */ jsxDEV("p", {
1089
+ className: "text-muted-foreground text-center text-xs",
1090
+ children: "No spam. We'll only email you about ContractSpec and your application."
1091
+ }, undefined, false, undefined, this)
1092
+ ]
1093
+ }, undefined, true, undefined, this)
1094
+ ]
1095
+ }, undefined, true, undefined, this);
574
1096
  }
575
-
576
- //#endregion
577
- export { WaitlistSection };
578
- //# sourceMappingURL=waitlist-section.js.map
1097
+ export {
1098
+ WaitlistSection
1099
+ };