@burdenoff/website-sdk 2026.1101.1 → 2026.1101.3

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 (276) hide show
  1. package/README.md +52 -11
  2. package/dist/analytics/index.js +19 -69
  3. package/dist/analytics/index.js.map +1 -1
  4. package/dist/analytics/index.mjs +3 -69
  5. package/dist/analytics/index.mjs.map +1 -1
  6. package/dist/avatar-live/index.js +1 -0
  7. package/dist/avatar-live/index.js.map +1 -1
  8. package/dist/avatar-live/index.mjs +1 -0
  9. package/dist/avatar-live/index.mjs.map +1 -1
  10. package/dist/avatar-live-view/index.js +25 -30
  11. package/dist/avatar-live-view/index.js.map +1 -1
  12. package/dist/avatar-live-view/index.mjs +20 -25
  13. package/dist/avatar-live-view/index.mjs.map +1 -1
  14. package/dist/chunk-23H4JUL4.js +41 -0
  15. package/dist/chunk-23H4JUL4.js.map +1 -0
  16. package/dist/chunk-34RX5P75.mjs +25 -0
  17. package/dist/chunk-34RX5P75.mjs.map +1 -0
  18. package/dist/chunk-3LFFY7AZ.js +184 -0
  19. package/dist/chunk-3LFFY7AZ.js.map +1 -0
  20. package/dist/chunk-3X26GE4S.js +2794 -0
  21. package/dist/chunk-3X26GE4S.js.map +1 -0
  22. package/dist/chunk-45GCA4GG.js +85 -0
  23. package/dist/chunk-45GCA4GG.js.map +1 -0
  24. package/dist/chunk-4SAGVLHN.js +876 -0
  25. package/dist/chunk-4SAGVLHN.js.map +1 -0
  26. package/dist/chunk-4U6YAII5.js +218 -0
  27. package/dist/chunk-4U6YAII5.js.map +1 -0
  28. package/dist/chunk-5GMTBOO6.js +21 -0
  29. package/dist/chunk-5GMTBOO6.js.map +1 -0
  30. package/dist/chunk-5JRJ57CL.mjs +329 -0
  31. package/dist/chunk-5JRJ57CL.mjs.map +1 -0
  32. package/dist/chunk-6C2DKIC7.js +4 -0
  33. package/dist/chunk-6C2DKIC7.js.map +1 -0
  34. package/dist/chunk-6IBFBWC5.mjs +17 -0
  35. package/dist/chunk-6IBFBWC5.mjs.map +1 -0
  36. package/dist/chunk-6KY2ZRVI.js +116 -0
  37. package/dist/chunk-6KY2ZRVI.js.map +1 -0
  38. package/dist/chunk-6VJT3SM4.mjs +182 -0
  39. package/dist/chunk-6VJT3SM4.mjs.map +1 -0
  40. package/dist/chunk-6YZUFMK2.mjs +40 -0
  41. package/dist/chunk-6YZUFMK2.mjs.map +1 -0
  42. package/dist/chunk-7A6R7CGG.js +47 -0
  43. package/dist/chunk-7A6R7CGG.js.map +1 -0
  44. package/dist/chunk-7PWL4V2R.js +4 -0
  45. package/dist/chunk-7PWL4V2R.js.map +1 -0
  46. package/dist/chunk-AA33WDYS.js +161 -0
  47. package/dist/chunk-AA33WDYS.js.map +1 -0
  48. package/dist/chunk-AHRGFXV2.js +525 -0
  49. package/dist/chunk-AHRGFXV2.js.map +1 -0
  50. package/dist/chunk-B63XLDZH.mjs +109 -0
  51. package/dist/chunk-B63XLDZH.mjs.map +1 -0
  52. package/dist/chunk-BX2USEWF.mjs +35 -0
  53. package/dist/chunk-BX2USEWF.mjs.map +1 -0
  54. package/dist/chunk-BYSZT35R.js +150 -0
  55. package/dist/chunk-BYSZT35R.js.map +1 -0
  56. package/dist/chunk-C6OJIHNO.js +12 -0
  57. package/dist/chunk-C6OJIHNO.js.map +1 -0
  58. package/dist/chunk-COOELBX7.mjs +63 -0
  59. package/dist/chunk-COOELBX7.mjs.map +1 -0
  60. package/dist/chunk-D2TW7MNC.mjs +2771 -0
  61. package/dist/chunk-D2TW7MNC.mjs.map +1 -0
  62. package/dist/chunk-D5KEZ6V6.mjs +3 -0
  63. package/dist/chunk-D5KEZ6V6.mjs.map +1 -0
  64. package/dist/chunk-E3GUGJMY.js +46 -0
  65. package/dist/chunk-E3GUGJMY.js.map +1 -0
  66. package/dist/chunk-EBZ2HGJ2.mjs +52 -0
  67. package/dist/chunk-EBZ2HGJ2.mjs.map +1 -0
  68. package/dist/chunk-EDLTUOIA.mjs +210 -0
  69. package/dist/chunk-EDLTUOIA.mjs.map +1 -0
  70. package/dist/chunk-EJQSOT4X.js +4 -0
  71. package/dist/chunk-EJQSOT4X.js.map +1 -0
  72. package/dist/chunk-EUPFS6MZ.mjs +2019 -0
  73. package/dist/chunk-EUPFS6MZ.mjs.map +1 -0
  74. package/dist/chunk-F3XWDC3B.js +77 -0
  75. package/dist/chunk-F3XWDC3B.js.map +1 -0
  76. package/dist/chunk-FFADMVIK.mjs +5127 -0
  77. package/dist/chunk-FFADMVIK.mjs.map +1 -0
  78. package/dist/chunk-FJWS7BKT.mjs +3 -0
  79. package/dist/chunk-FJWS7BKT.mjs.map +1 -0
  80. package/dist/chunk-FJZJDUOR.mjs +3 -0
  81. package/dist/chunk-FJZJDUOR.mjs.map +1 -0
  82. package/dist/chunk-GCFLCO2Z.mjs +145 -0
  83. package/dist/chunk-GCFLCO2Z.mjs.map +1 -0
  84. package/dist/chunk-GEXC4LRP.js +61 -0
  85. package/dist/chunk-GEXC4LRP.js.map +1 -0
  86. package/dist/chunk-GTRAXQGC.mjs +3 -0
  87. package/dist/chunk-GTRAXQGC.mjs.map +1 -0
  88. package/dist/chunk-IKOIRUKW.js +270 -0
  89. package/dist/chunk-IKOIRUKW.js.map +1 -0
  90. package/dist/chunk-IXTWOPRN.js +45 -0
  91. package/dist/chunk-IXTWOPRN.js.map +1 -0
  92. package/dist/chunk-JDXOXGOK.js +547 -0
  93. package/dist/chunk-JDXOXGOK.js.map +1 -0
  94. package/dist/chunk-JSLDWYV7.mjs +558 -0
  95. package/dist/chunk-JSLDWYV7.mjs.map +1 -0
  96. package/dist/chunk-JXLSTVBK.js +336 -0
  97. package/dist/chunk-JXLSTVBK.js.map +1 -0
  98. package/dist/chunk-KHYXK7FG.mjs +49 -0
  99. package/dist/chunk-KHYXK7FG.mjs.map +1 -0
  100. package/dist/chunk-KSMBOWQQ.js +2034 -0
  101. package/dist/chunk-KSMBOWQQ.js.map +1 -0
  102. package/dist/chunk-KU2PXHGB.mjs +83 -0
  103. package/dist/chunk-KU2PXHGB.mjs.map +1 -0
  104. package/dist/chunk-KZANIV3S.mjs +37 -0
  105. package/dist/chunk-KZANIV3S.mjs.map +1 -0
  106. package/dist/chunk-L4BP6YOB.js +20 -0
  107. package/dist/chunk-L4BP6YOB.js.map +1 -0
  108. package/dist/chunk-MRKA2OAF.mjs +75 -0
  109. package/dist/chunk-MRKA2OAF.mjs.map +1 -0
  110. package/dist/chunk-N5EC53MH.mjs +80 -0
  111. package/dist/chunk-N5EC53MH.mjs.map +1 -0
  112. package/dist/chunk-NZANQGDM.mjs +34 -0
  113. package/dist/chunk-NZANQGDM.mjs.map +1 -0
  114. package/dist/chunk-O4GS3XPZ.js +10 -0
  115. package/dist/chunk-O4GS3XPZ.js.map +1 -0
  116. package/dist/chunk-O76QDGRM.js +5154 -0
  117. package/dist/chunk-O76QDGRM.js.map +1 -0
  118. package/dist/chunk-OYEUNZJY.js +114 -0
  119. package/dist/chunk-OYEUNZJY.js.map +1 -0
  120. package/dist/chunk-PHXAGQNB.js +74 -0
  121. package/dist/chunk-PHXAGQNB.js.map +1 -0
  122. package/dist/chunk-PIHHPP7J.mjs +16 -0
  123. package/dist/chunk-PIHHPP7J.mjs.map +1 -0
  124. package/dist/chunk-PXRHVVOU.mjs +499 -0
  125. package/dist/chunk-PXRHVVOU.mjs.map +1 -0
  126. package/dist/chunk-QMA6U6AU.js +36 -0
  127. package/dist/chunk-QMA6U6AU.js.map +1 -0
  128. package/dist/chunk-R6J7IULF.js +44 -0
  129. package/dist/chunk-R6J7IULF.js.map +1 -0
  130. package/dist/chunk-R7G6TWIS.mjs +10 -0
  131. package/dist/chunk-R7G6TWIS.mjs.map +1 -0
  132. package/dist/chunk-RUMGFI6L.mjs +544 -0
  133. package/dist/chunk-RUMGFI6L.mjs.map +1 -0
  134. package/dist/chunk-S54JWSJF.js +565 -0
  135. package/dist/chunk-S54JWSJF.js.map +1 -0
  136. package/dist/chunk-SK5UGG6A.js +2041 -0
  137. package/dist/chunk-SK5UGG6A.js.map +1 -0
  138. package/dist/chunk-SKIYDKIS.mjs +70 -0
  139. package/dist/chunk-SKIYDKIS.mjs.map +1 -0
  140. package/dist/chunk-SZNS5IK6.mjs +322 -0
  141. package/dist/chunk-SZNS5IK6.mjs.map +1 -0
  142. package/dist/chunk-T7JIPZAC.js +66 -0
  143. package/dist/chunk-T7JIPZAC.js.map +1 -0
  144. package/dist/chunk-TGYQHO2E.mjs +864 -0
  145. package/dist/chunk-TGYQHO2E.mjs.map +1 -0
  146. package/dist/chunk-TT3MHN42.mjs +8 -0
  147. package/dist/chunk-TT3MHN42.mjs.map +1 -0
  148. package/dist/chunk-UM55U65W.mjs +268 -0
  149. package/dist/chunk-UM55U65W.mjs.map +1 -0
  150. package/dist/chunk-UQ2HALUD.js +72 -0
  151. package/dist/chunk-UQ2HALUD.js.map +1 -0
  152. package/dist/chunk-UXWT7G77.js +82 -0
  153. package/dist/chunk-UXWT7G77.js.map +1 -0
  154. package/dist/chunk-VNS5WDWO.mjs +7 -0
  155. package/dist/chunk-VNS5WDWO.mjs.map +1 -0
  156. package/dist/chunk-VRWZLGR7.js +4 -0
  157. package/dist/chunk-VRWZLGR7.js.map +1 -0
  158. package/dist/chunk-VZLDSNH4.mjs +22 -0
  159. package/dist/chunk-VZLDSNH4.mjs.map +1 -0
  160. package/dist/chunk-W6P3YETJ.js +92 -0
  161. package/dist/chunk-W6P3YETJ.js.map +1 -0
  162. package/dist/chunk-WPKFFQCR.mjs +90 -0
  163. package/dist/chunk-WPKFFQCR.mjs.map +1 -0
  164. package/dist/chunk-WTVTI5TO.mjs +22 -0
  165. package/dist/chunk-WTVTI5TO.mjs.map +1 -0
  166. package/dist/chunk-XJOBZ4RJ.js +44 -0
  167. package/dist/chunk-XJOBZ4RJ.js.map +1 -0
  168. package/dist/chunk-XP2JDNDU.js +325 -0
  169. package/dist/chunk-XP2JDNDU.js.map +1 -0
  170. package/dist/chunk-Y4V5CEWD.mjs +112 -0
  171. package/dist/chunk-Y4V5CEWD.mjs.map +1 -0
  172. package/dist/chunk-YERN2UWM.js +116 -0
  173. package/dist/chunk-YERN2UWM.js.map +1 -0
  174. package/dist/chunk-ZKJQWFAA.mjs +114 -0
  175. package/dist/chunk-ZKJQWFAA.mjs.map +1 -0
  176. package/dist/chunk-ZOON3S3Y.mjs +138 -0
  177. package/dist/chunk-ZOON3S3Y.mjs.map +1 -0
  178. package/dist/chunk-ZP6QRAYC.mjs +2024 -0
  179. package/dist/chunk-ZP6QRAYC.mjs.map +1 -0
  180. package/dist/chunk-ZSTFX7FV.js +9 -0
  181. package/dist/chunk-ZSTFX7FV.js.map +1 -0
  182. package/dist/client/index.js +23 -331
  183. package/dist/client/index.js.map +1 -1
  184. package/dist/client/index.mjs +3 -330
  185. package/dist/client/index.mjs.map +1 -1
  186. package/dist/comparison/index.js +28 -111
  187. package/dist/comparison/index.js.map +1 -1
  188. package/dist/comparison/index.mjs +2 -107
  189. package/dist/comparison/index.mjs.map +1 -1
  190. package/dist/components/contact.js +21 -931
  191. package/dist/components/contact.js.map +1 -1
  192. package/dist/components/contact.mjs +12 -909
  193. package/dist/components/contact.mjs.map +1 -1
  194. package/dist/components/electron-download.js +12 -124
  195. package/dist/components/electron-download.js.map +1 -1
  196. package/dist/components/electron-download.mjs +4 -106
  197. package/dist/components/electron-download.mjs.map +1 -1
  198. package/dist/components/explore-cta.js +8 -112
  199. package/dist/components/explore-cta.js.map +1 -1
  200. package/dist/components/explore-cta.mjs +3 -114
  201. package/dist/components/explore-cta.mjs.map +1 -1
  202. package/dist/components/explore.js +62 -7833
  203. package/dist/components/explore.js.map +1 -1
  204. package/dist/components/explore.mjs +13 -7800
  205. package/dist/components/explore.mjs.map +1 -1
  206. package/dist/components/launch-countdown.js +8 -83
  207. package/dist/components/launch-countdown.js.map +1 -1
  208. package/dist/components/launch-countdown.mjs +3 -85
  209. package/dist/components/launch-countdown.mjs.map +1 -1
  210. package/dist/components/newsletter.js +20 -993
  211. package/dist/components/newsletter.js.map +1 -1
  212. package/dist/components/newsletter.mjs +11 -971
  213. package/dist/components/newsletter.mjs.map +1 -1
  214. package/dist/components/partners.js +24 -1302
  215. package/dist/components/partners.js.map +1 -1
  216. package/dist/components/partners.mjs +15 -1276
  217. package/dist/components/partners.mjs.map +1 -1
  218. package/dist/components/pricing.js +49 -1249
  219. package/dist/components/pricing.js.map +1 -1
  220. package/dist/components/pricing.mjs +8 -1226
  221. package/dist/components/pricing.mjs.map +1 -1
  222. package/dist/components/problems-solved.js +8 -150
  223. package/dist/components/problems-solved.js.map +1 -1
  224. package/dist/components/problems-solved.mjs +4 -133
  225. package/dist/components/problems-solved.mjs.map +1 -1
  226. package/dist/components/resource-links.js +8 -304
  227. package/dist/components/resource-links.js.map +1 -1
  228. package/dist/components/resource-links.mjs +5 -308
  229. package/dist/components/resource-links.mjs.map +1 -1
  230. package/dist/components/social-links.js +8 -343
  231. package/dist/components/social-links.js.map +1 -1
  232. package/dist/components/social-links.mjs +5 -347
  233. package/dist/components/social-links.mjs.map +1 -1
  234. package/dist/components/unsubscribe.js +10 -627
  235. package/dist/components/unsubscribe.js.map +1 -1
  236. package/dist/components/unsubscribe.mjs +6 -611
  237. package/dist/components/unsubscribe.mjs.map +1 -1
  238. package/dist/components/waitlist.js +21 -1001
  239. package/dist/components/waitlist.js.map +1 -1
  240. package/dist/components/waitlist.mjs +12 -982
  241. package/dist/components/waitlist.mjs.map +1 -1
  242. package/dist/components/website-switcher.js +12 -175
  243. package/dist/components/website-switcher.js.map +1 -1
  244. package/dist/components/website-switcher.mjs +4 -157
  245. package/dist/components/website-switcher.mjs.map +1 -1
  246. package/dist/content/index.js +118 -3616
  247. package/dist/content/index.js.map +1 -1
  248. package/dist/content/index.mjs +12 -3567
  249. package/dist/content/index.mjs.map +1 -1
  250. package/dist/hooks/index.js +37 -2321
  251. package/dist/hooks/index.js.map +1 -1
  252. package/dist/hooks/index.mjs +6 -2318
  253. package/dist/hooks/index.mjs.map +1 -1
  254. package/dist/index.d.mts +1 -1
  255. package/dist/index.d.ts +1 -1
  256. package/dist/index.js +4145 -20599
  257. package/dist/index.js.map +1 -1
  258. package/dist/index.mjs +3766 -20567
  259. package/dist/index.mjs.map +1 -1
  260. package/dist/product/index.js +20 -393
  261. package/dist/product/index.js.map +1 -1
  262. package/dist/product/index.mjs +5 -394
  263. package/dist/product/index.mjs.map +1 -1
  264. package/dist/seo/index.js +8 -76
  265. package/dist/seo/index.js.map +1 -1
  266. package/dist/seo/index.mjs +3 -78
  267. package/dist/seo/index.mjs.map +1 -1
  268. package/dist/store/index.js +51 -2650
  269. package/dist/store/index.js.map +1 -1
  270. package/dist/store/index.mjs +13 -2619
  271. package/dist/store/index.mjs.map +1 -1
  272. package/dist/utils/index.js +69 -134
  273. package/dist/utils/index.js.map +1 -1
  274. package/dist/utils/index.mjs +5 -122
  275. package/dist/utils/index.mjs.map +1 -1
  276. package/package.json +2 -1
@@ -1,1007 +1,27 @@
1
1
  'use strict';
2
2
 
3
- var React = require('react');
4
- var zod$1 = require('@hookform/resolvers/zod');
5
- var reactHookForm = require('react-hook-form');
6
- var sonner = require('sonner');
7
- var zod = require('zod');
8
- var jsxRuntime = require('react/jsx-runtime');
9
- var reactHelmetAsync = require('react-helmet-async');
10
- var reactSlot = require('@radix-ui/react-slot');
11
- var classVarianceAuthority = require('class-variance-authority');
12
- var clsx = require('clsx');
13
- var tailwindMerge = require('tailwind-merge');
14
- var LabelPrimitive = require('@radix-ui/react-label');
15
-
16
- function _interopNamespace(e) {
17
- if (e && e.__esModule) return e;
18
- var n = Object.create(null);
19
- if (e) {
20
- Object.keys(e).forEach(function (k) {
21
- if (k !== 'default') {
22
- var d = Object.getOwnPropertyDescriptor(e, k);
23
- Object.defineProperty(n, k, d.get ? d : {
24
- enumerable: true,
25
- get: function () { return e[k]; }
26
- });
27
- }
28
- });
29
- }
30
- n.default = e;
31
- return Object.freeze(n);
32
- }
33
-
34
- var React__namespace = /*#__PURE__*/_interopNamespace(React);
35
- var LabelPrimitive__namespace = /*#__PURE__*/_interopNamespace(LabelPrimitive);
36
-
37
- var __defProp = Object.defineProperty;
38
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
39
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
40
-
41
- // src/analytics/events.ts
42
- var MAX_PROPERTY_LENGTH = 64;
43
- var EMAIL_LIKE = /[^\s@]+@[^\s@]+/;
44
- function sanitizeWebsiteEventProperties(properties) {
45
- const safe = {};
46
- if (!properties) return safe;
47
- for (const [key, value] of Object.entries(properties)) {
48
- if (typeof value === "boolean") {
49
- safe[key] = value;
50
- } else if (typeof value === "number") {
51
- if (Number.isFinite(value)) safe[key] = value;
52
- } else if (typeof value === "string") {
53
- const trimmed = value.trim();
54
- if (trimmed.length > 0 && trimmed.length <= MAX_PROPERTY_LENGTH && !EMAIL_LIKE.test(trimmed)) {
55
- safe[key] = trimmed;
56
- }
57
- }
58
- }
59
- return safe;
60
- }
61
- function trackWebsiteEvent(name, properties) {
62
- if (typeof window === "undefined") return false;
63
- try {
64
- const rybbit = window.rybbit;
65
- if (typeof rybbit?.event !== "function") return false;
66
- const safe = sanitizeWebsiteEventProperties(properties);
67
- if (Object.keys(safe).length > 0) {
68
- rybbit.event(name, safe);
69
- } else {
70
- rybbit.event(name);
71
- }
72
- return true;
73
- } catch {
74
- return false;
75
- }
76
- }
77
-
78
- // src/client/security.ts
79
- var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "::1"]);
80
- var RESERVED_HEADERS = /* @__PURE__ */ new Set([
81
- "authorization",
82
- "cookie",
83
- "x-actor-id",
84
- "x-actor-type",
85
- "x-consent-granted-by",
86
- "x-consent-scope",
87
- "x-consent-granted-at",
88
- "x-consent-expires-at"
89
- ]);
90
- function validateGatewayUrl(value) {
91
- let url;
92
- try {
93
- url = new URL(value);
94
- } catch {
95
- throw new Error("Gateway URL must be a valid absolute URL");
96
- }
97
- if (url.protocol === "https:") {
98
- return url.toString();
99
- }
100
- if (url.protocol === "http:" && LOOPBACK_HOSTS.has(url.hostname.toLowerCase())) {
101
- return url.toString();
102
- }
103
- throw new Error("Gateway URL must use HTTPS unless it targets localhost");
104
- }
105
- function sanitizeHeaders(headers) {
106
- if (!headers) return void 0;
107
- return Object.fromEntries(
108
- Object.entries(headers).filter(
109
- ([key]) => !RESERVED_HEADERS.has(key.toLowerCase())
110
- )
111
- );
112
- }
113
- var CF_ACCESS_GATED_HOSTS = /* @__PURE__ */ new Set([
114
- "alphagraphql.burdenoff.com",
115
- "alphagraphqlworkspaces.burdenoff.com"
116
- ]);
117
- function cfAccessHeaders(gatewayUrl, cfAccess) {
118
- const clientId = cfAccess?.clientId?.trim();
119
- const clientSecret = cfAccess?.clientSecret?.trim();
120
- if (!clientId || !clientSecret) return {};
121
- let host;
122
- try {
123
- host = new URL(gatewayUrl).hostname.toLowerCase();
124
- } catch {
125
- return {};
126
- }
127
- if (!CF_ACCESS_GATED_HOSTS.has(host)) return {};
128
- return {
129
- "CF-Access-Client-Id": clientId,
130
- "CF-Access-Client-Secret": clientSecret
131
- };
132
- }
133
-
134
- // src/client/graphql-client.ts
135
- var _WebSDKClient = class _WebSDKClient {
136
- constructor(config) {
137
- __publicField(this, "config");
138
- __publicField(this, "queryCache", /* @__PURE__ */ new Map());
139
- __publicField(this, "inflight", /* @__PURE__ */ new Map());
140
- this.config = {
141
- ...config,
142
- gatewayUrl: validateGatewayUrl(config.gatewayUrl),
143
- headers: sanitizeHeaders(config.headers)
144
- };
145
- }
146
- getConfig() {
147
- return this.config;
148
- }
149
- /**
150
- * Execute a GraphQL query (with deduplication and caching).
151
- *
152
- * Pass `{ cache: false }` to bypass the cache entirely — required for poll
153
- * loops, where every tick must reach the network.
154
- */
155
- async query(query, variables, options) {
156
- if (options?.cache === false) {
157
- return this.request(query, variables, true, options.timeoutMs);
158
- }
159
- const cacheKey = JSON.stringify({ query, variables });
160
- const cached = this.queryCache.get(cacheKey);
161
- if (cached) {
162
- if (Date.now() - cached.ts < _WebSDKClient.CACHE_TTL) {
163
- return cached.data;
164
- }
165
- this.queryCache.delete(cacheKey);
166
- }
167
- const existing = this.inflight.get(cacheKey);
168
- if (existing) {
169
- return existing;
170
- }
171
- const promise = this.request(query, variables, true, options?.timeoutMs).then((result) => {
172
- if (result.data && !result.errors?.length) {
173
- if (this.queryCache.size >= _WebSDKClient.MAX_CACHE_ENTRIES) {
174
- const oldestEntry = this.queryCache.keys().next().value;
175
- if (oldestEntry) {
176
- this.queryCache.delete(oldestEntry);
177
- }
178
- }
179
- this.queryCache.set(cacheKey, { data: result, ts: Date.now() });
180
- }
181
- return result;
182
- }).finally(() => {
183
- this.inflight.delete(cacheKey);
184
- });
185
- this.inflight.set(cacheKey, promise);
186
- return promise;
187
- }
188
- /**
189
- * Execute a GraphQL mutation
190
- */
191
- async mutate(mutation, variables, options) {
192
- return this.request(mutation, variables, false, options?.timeoutMs);
193
- }
194
- /** HTTP statuses worth another attempt — transient server/edge conditions. */
195
- static isRetriableStatus(status) {
196
- return status === 429 || status === 408 || status >= 500 && status < 600;
197
- }
198
- static sleep(ms) {
199
- return new Promise((resolve) => setTimeout(resolve, ms));
200
- }
201
- /**
202
- * Perform the HTTP call with a hard timeout. Every outcome resolves to a
203
- * GraphQLResponse — callers never hang, so a UI's `loading` state always
204
- * settles into data or a renderable error.
205
- */
206
- async attempt(query, variables, timeoutMs) {
207
- const controller = new AbortController();
208
- const timer = setTimeout(() => controller.abort(), timeoutMs);
209
- try {
210
- const response = await fetch(this.config.gatewayUrl, {
211
- method: "POST",
212
- headers: {
213
- "Content-Type": "application/json",
214
- "x-product-id": this.config.productId,
215
- ...this.config.headers,
216
- ...cfAccessHeaders(this.config.gatewayUrl, this.config.cfAccess)
217
- },
218
- body: JSON.stringify({ query, variables }),
219
- signal: controller.signal
220
- });
221
- if (!response.ok) {
222
- console.error(
223
- "[WebSDK] GraphQL request failed",
224
- response.status,
225
- response.statusText
226
- );
227
- return {
228
- res: {
229
- errors: [
230
- {
231
- message: `HTTP ${response.status}: ${response.statusText}`,
232
- extensions: { code: `HTTP_${response.status}` }
233
- }
234
- ]
235
- },
236
- retriable: _WebSDKClient.isRetriableStatus(response.status)
237
- };
238
- }
239
- return {
240
- res: await response.json(),
241
- retriable: false
242
- };
243
- } catch (error) {
244
- const aborted = error instanceof Error && (error.name === "AbortError" || controller.signal.aborted);
245
- const message = aborted ? `Request timed out after ${timeoutMs}ms` : error instanceof Error ? error.message : "Network error";
246
- console.error("[WebSDK] Network error", message);
247
- return {
248
- res: {
249
- errors: [
250
- {
251
- message,
252
- extensions: { code: aborted ? "TIMEOUT" : "NETWORK_ERROR" }
253
- }
254
- ]
255
- },
256
- // Transport-level failures are worth one more try; a genuine outage
257
- // just fails twice quickly and still renders an error state.
258
- retriable: true
259
- };
260
- } finally {
261
- clearTimeout(timer);
262
- }
263
- }
264
- async request(query, variables, retry = true, timeoutOverrideMs) {
265
- const timeoutMs = timeoutOverrideMs ?? this.config.timeoutMs ?? _WebSDKClient.DEFAULT_TIMEOUT_MS;
266
- const maxRetries = retry ? this.config.maxRetries ?? _WebSDKClient.DEFAULT_MAX_RETRIES : 0;
267
- let last;
268
- for (let i = 0; i <= maxRetries; i++) {
269
- const { res, retriable } = await this.attempt(
270
- query,
271
- variables,
272
- timeoutMs
273
- );
274
- if (!retriable || i === maxRetries) return res;
275
- last = res;
276
- await _WebSDKClient.sleep(
277
- _WebSDKClient.RETRY_BASE_DELAY_MS * (i + 1) + Math.random() * 200
278
- );
279
- }
280
- return last;
281
- }
282
- };
283
- __publicField(_WebSDKClient, "CACHE_TTL", 5 * 60 * 1e3);
284
- // 5 minutes
285
- __publicField(_WebSDKClient, "MAX_CACHE_ENTRIES", 100);
286
- __publicField(_WebSDKClient, "DEFAULT_TIMEOUT_MS", 12e3);
287
- __publicField(_WebSDKClient, "DEFAULT_MAX_RETRIES", 1);
288
- __publicField(_WebSDKClient, "RETRY_BASE_DELAY_MS", 400);
289
- var WebSDKContext = React.createContext(null);
290
- function useWebSDK() {
291
- const client = React.useContext(WebSDKContext);
292
- if (!client) {
293
- throw new Error("useWebSDK must be used within a WebSDKProvider");
294
- }
295
- return client;
296
- }
297
- function useWebSDKConfig() {
298
- const client = useWebSDK();
299
- return client.getConfig();
300
- }
301
-
302
- // src/utils/product-slug.ts
303
- var PRODUCT_SLUG_RENAMES = Object.freeze(
304
- [Object.freeze({ legacy: "botlit", current: "botmanor" })]
305
- );
306
- Object.freeze(
307
- Object.fromEntries(PRODUCT_SLUG_RENAMES.map((r) => [r.legacy, r.current]))
308
- );
309
- var ProductContext = React.createContext({
310
- product: null,
311
- loading: true,
312
- error: null,
313
- hasProvider: false,
314
- refetch: () => {
315
- }
3
+ var chunkJDXOXGOK_js = require('../chunk-JDXOXGOK.js');
4
+ require('../chunk-XJOBZ4RJ.js');
5
+ require('../chunk-R6J7IULF.js');
6
+ require('../chunk-IXTWOPRN.js');
7
+ require('../chunk-7A6R7CGG.js');
8
+ require('../chunk-UXWT7G77.js');
9
+ require('../chunk-UQ2HALUD.js');
10
+ require('../chunk-C6OJIHNO.js');
11
+ require('../chunk-BYSZT35R.js');
12
+ require('../chunk-E3GUGJMY.js');
13
+ require('../chunk-JXLSTVBK.js');
14
+ require('../chunk-ZSTFX7FV.js');
15
+
16
+
17
+
18
+ Object.defineProperty(exports, "WaitlistForm", {
19
+ enumerable: true,
20
+ get: function () { return chunkJDXOXGOK_js.WaitlistForm; }
316
21
  });
317
- function useProduct() {
318
- return React.useContext(ProductContext);
319
- }
320
- function canonicalFromLocation() {
321
- if (typeof window === "undefined" || !window.location) return void 0;
322
- const { origin, pathname } = window.location;
323
- if (!origin || origin === "null") return void 0;
324
- const path = pathname === "/" ? "/" : pathname.replace(/\/+$/, "");
325
- return `${origin}${path}`;
326
- }
327
- function resolveImageUrl(image, base) {
328
- if (!image || /^https?:\/\//i.test(image)) return image;
329
- if (!base) return image;
330
- try {
331
- return new URL(image, base).toString();
332
- } catch {
333
- return image;
334
- }
335
- }
336
- function serializeJsonLd(data) {
337
- return JSON.stringify(data).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
338
- }
339
- function PageHead({
340
- title,
341
- description,
342
- productName,
343
- keywords,
344
- image,
345
- url,
346
- favicon,
347
- robots = "index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1",
348
- locale = "en_US",
349
- twitterHandle,
350
- themeColor = "#000000",
351
- author,
352
- structuredData,
353
- additionalMeta
354
- }) {
355
- const fullTitle = productName && !title.includes(productName) ? `${title} | ${productName}` : title;
356
- const resolvedUrl = url ?? canonicalFromLocation();
357
- const fullImageUrl = resolveImageUrl(image, resolvedUrl);
358
- const structuredDataItems = structuredData ? Array.isArray(structuredData) ? structuredData : [structuredData] : [];
359
- return /* @__PURE__ */ jsxRuntime.jsxs(reactHelmetAsync.Helmet, { children: [
360
- /* @__PURE__ */ jsxRuntime.jsx("title", { children: fullTitle }),
361
- /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "title", content: fullTitle }),
362
- description ? /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "description", content: description }) : null,
363
- keywords ? /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "keywords", content: keywords }) : null,
364
- author ? /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "author", content: author }) : null,
365
- /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "robots", content: robots }),
366
- resolvedUrl ? /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "canonical", href: resolvedUrl }) : null,
367
- favicon ? /* @__PURE__ */ jsxRuntime.jsx("link", { rel: "icon", href: favicon }) : null,
368
- /* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:type", content: "website" }),
369
- /* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:title", content: fullTitle }),
370
- description ? /* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:description", content: description }) : null,
371
- fullImageUrl ? /* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:image", content: fullImageUrl }) : null,
372
- resolvedUrl ? /* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:url", content: resolvedUrl }) : null,
373
- /* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:locale", content: locale }),
374
- productName ? /* @__PURE__ */ jsxRuntime.jsx("meta", { property: "og:site_name", content: productName }) : null,
375
- /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "twitter:card", content: "summary_large_image" }),
376
- /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "twitter:title", content: fullTitle }),
377
- description ? /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "twitter:description", content: description }) : null,
378
- fullImageUrl ? /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "twitter:image", content: fullImageUrl }) : null,
379
- twitterHandle ? /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "twitter:creator", content: twitterHandle }) : null,
380
- /* @__PURE__ */ jsxRuntime.jsx("meta", { name: "theme-color", content: themeColor }),
381
- structuredDataItems.map((data, index) => /* @__PURE__ */ jsxRuntime.jsx("script", { type: "application/ld+json", children: serializeJsonLd(data) }, `ld-${index}`)),
382
- additionalMeta?.map((meta, index) => /* @__PURE__ */ jsxRuntime.jsx(
383
- "meta",
384
- {
385
- ...meta.name ? { name: meta.name } : {},
386
- ...meta.property ? { property: meta.property } : {},
387
- content: meta.content
388
- },
389
- `meta-${index}`
390
- ))
391
- ] });
392
- }
393
- function cn(...inputs) {
394
- return tailwindMerge.twMerge(clsx.clsx(inputs));
395
- }
396
- var buttonVariants = classVarianceAuthority.cva(
397
- "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
398
- {
399
- variants: {
400
- variant: {
401
- default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
402
- destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
403
- outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
404
- secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
405
- ghost: "hover:bg-accent hover:text-accent-foreground",
406
- link: "text-primary underline-offset-4 hover:underline"
407
- },
408
- size: {
409
- default: "h-9 px-4 py-2",
410
- sm: "h-8 rounded-md px-3 text-xs",
411
- lg: "h-10 rounded-md px-8",
412
- icon: "h-9 w-9"
413
- }
414
- },
415
- defaultVariants: {
416
- variant: "default",
417
- size: "default"
418
- }
419
- }
420
- );
421
- var Button = React__namespace.forwardRef(
422
- ({ className, variant, size, asChild = false, ...props }, ref) => {
423
- const Comp = asChild ? reactSlot.Slot : "button";
424
- return /* @__PURE__ */ jsxRuntime.jsx(
425
- Comp,
426
- {
427
- className: cn(buttonVariants({ variant, size, className })),
428
- ref,
429
- ...props
430
- }
431
- );
432
- }
433
- );
434
- Button.displayName = "Button";
435
- var Input = React__namespace.forwardRef(
436
- ({ className, type, ...props }, ref) => {
437
- return /* @__PURE__ */ jsxRuntime.jsx(
438
- "input",
439
- {
440
- type,
441
- className: cn(
442
- "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
443
- className
444
- ),
445
- ref,
446
- ...props
447
- }
448
- );
449
- }
450
- );
451
- Input.displayName = "Input";
452
- var labelVariants = classVarianceAuthority.cva(
453
- "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
454
- );
455
- var Label = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
456
- LabelPrimitive__namespace.Root,
457
- {
458
- ref,
459
- className: cn(labelVariants(), className),
460
- ...props
461
- }
462
- ));
463
- Label.displayName = LabelPrimitive__namespace.Root.displayName;
464
- var Textarea = React__namespace.forwardRef(({ className, ...props }, ref) => {
465
- return /* @__PURE__ */ jsxRuntime.jsx(
466
- "textarea",
467
- {
468
- className: cn(
469
- "flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
470
- className
471
- ),
472
- ref,
473
- ...props
474
- }
475
- );
22
+ Object.defineProperty(exports, "WaitlistPage", {
23
+ enumerable: true,
24
+ get: function () { return chunkJDXOXGOK_js.WaitlistPage; }
476
25
  });
477
- Textarea.displayName = "Textarea";
478
- var waitlistPageSchema = zod.z.object({
479
- name: zod.z.string().min(1, "Name is required"),
480
- email: zod.z.string().email("Please enter a valid email address"),
481
- company: zod.z.string().optional(),
482
- reason: zod.z.string().optional()
483
- });
484
- var JOIN_WAITLIST_MUTATION = (
485
- /* GraphQL */
486
- `
487
- mutation JoinWaitlist($input: JoinWaitlistInput!) {
488
- joinWaitlist(input: $input) {
489
- id
490
- email
491
- name
492
- status
493
- createdAt
494
- }
495
- }
496
- `
497
- );
498
- async function joinWaitlist(client, data, productId) {
499
- try {
500
- const result = await client.mutate(JOIN_WAITLIST_MUTATION, {
501
- input: {
502
- email: data.email.trim().toLowerCase(),
503
- platformProductId: productId,
504
- name: data.name?.trim() || void 0,
505
- company: data.company?.trim() || void 0,
506
- reason: data.reason?.trim() || void 0,
507
- context: {
508
- source: "website",
509
- referrer: typeof window !== "undefined" ? window.location.href : "",
510
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
511
- }
512
- }
513
- });
514
- if (result.errors?.length) {
515
- const errorMsg = result.errors[0]?.message ?? "Failed to join waitlist";
516
- if (errorMsg.toLowerCase().includes("already")) {
517
- return {
518
- success: false,
519
- message: "You are already on the waitlist!"
520
- };
521
- }
522
- return { success: false, message: errorMsg };
523
- }
524
- return { success: true, message: "You have been added to the waitlist!" };
525
- } catch (error) {
526
- console.error("Waitlist signup error:", error);
527
- return { success: false, message: "Network error. Please try again." };
528
- }
529
- }
530
- function useRateLimit(maxAttempts, windowMinutes) {
531
- const rateLimitRef = React.useRef(null);
532
- const [isLimited, setIsLimited] = React.useState(false);
533
- const [resetTime, setResetTime] = React.useState(null);
534
- function recordAttempt() {
535
- const now = Date.now();
536
- const state = rateLimitRef.current;
537
- if (state && now > state.resetTime) {
538
- rateLimitRef.current = null;
539
- }
540
- const current = rateLimitRef.current;
541
- if (!current) {
542
- rateLimitRef.current = {
543
- attempts: 1,
544
- resetTime: now + windowMinutes * 60 * 1e3
545
- };
546
- return false;
547
- }
548
- current.attempts += 1;
549
- if (current.attempts >= maxAttempts) {
550
- setIsLimited(true);
551
- setResetTime(new Date(current.resetTime));
552
- return true;
553
- }
554
- return false;
555
- }
556
- function checkLimit() {
557
- const state = rateLimitRef.current;
558
- if (!state) return false;
559
- if (Date.now() > state.resetTime) {
560
- rateLimitRef.current = null;
561
- setIsLimited(false);
562
- setResetTime(null);
563
- return false;
564
- }
565
- return state.attempts >= maxAttempts;
566
- }
567
- return { isLimited, resetTime, recordAttempt, checkLimit };
568
- }
569
- function WaitlistPage({
570
- productName,
571
- heroTitle = "Join the Waitlist",
572
- heroSubtitle = "Be among the first to experience what's coming next",
573
- heroDescription,
574
- successMessage = "You have been added to the waitlist!",
575
- errorMessage = "Failed to join waitlist. Please try again.",
576
- className,
577
- seo
578
- }) {
579
- const client = useWebSDK();
580
- const config = useWebSDKConfig();
581
- const {
582
- product,
583
- loading: productLoading,
584
- error: productError,
585
- hasProvider
586
- } = useProduct();
587
- const displayName = productName ?? product?.name ?? config.productId;
588
- const productStatus = product?.status;
589
- const canCheckStatus = Boolean(config.productSlug);
590
- const [isSubmitting, setIsSubmitting] = React.useState(false);
591
- const { isLimited, resetTime, recordAttempt, checkLimit } = useRateLimit(
592
- 3,
593
- 15
594
- );
595
- const {
596
- register,
597
- handleSubmit,
598
- formState: { errors },
599
- reset
600
- } = reactHookForm.useForm({
601
- resolver: zod$1.zodResolver(waitlistPageSchema)
602
- });
603
- if (canCheckStatus && !hasProvider) {
604
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
605
- seo && /* @__PURE__ */ jsxRuntime.jsx(
606
- PageHead,
607
- {
608
- title: seo.title ?? "",
609
- description: seo.description ?? "",
610
- keywords: seo.keywords,
611
- image: seo.image,
612
- url: seo.url
613
- }
614
- ),
615
- /* @__PURE__ */ jsxRuntime.jsx("section", { className: "relative overflow-hidden py-24 lg:py-32", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 text-center space-y-6", children: [
616
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-4xl font-bold tracking-tight sm:text-5xl text-foreground", children: "Waitlist Unavailable" }),
617
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-lg text-muted-foreground", children: [
618
- "Product status checks require ",
619
- /* @__PURE__ */ jsxRuntime.jsx("code", { children: "ProductProvider" }),
620
- " to be mounted. Please update your integration configuration."
621
- ] })
622
- ] }) })
623
- ] });
624
- }
625
- if (canCheckStatus && productLoading) {
626
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
627
- seo && /* @__PURE__ */ jsxRuntime.jsx(
628
- PageHead,
629
- {
630
- title: seo.title ?? "",
631
- description: seo.description ?? "",
632
- keywords: seo.keywords,
633
- image: seo.image,
634
- url: seo.url
635
- }
636
- ),
637
- /* @__PURE__ */ jsxRuntime.jsx("section", { className: "relative overflow-hidden py-24 lg:py-32", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 text-center space-y-6", children: [
638
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-4xl font-bold tracking-tight sm:text-5xl text-foreground", children: "Loading\u2026" }),
639
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg text-muted-foreground", children: "Fetching product status." })
640
- ] }) })
641
- ] });
642
- }
643
- if (canCheckStatus && (productError || !productStatus)) {
644
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
645
- seo && /* @__PURE__ */ jsxRuntime.jsx(
646
- PageHead,
647
- {
648
- title: seo.title ?? "",
649
- description: seo.description ?? "",
650
- keywords: seo.keywords,
651
- image: seo.image,
652
- url: seo.url
653
- }
654
- ),
655
- /* @__PURE__ */ jsxRuntime.jsx("section", { className: "relative overflow-hidden py-24 lg:py-32", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 text-center space-y-6", children: [
656
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-4xl font-bold tracking-tight sm:text-5xl text-foreground", children: "Waitlist Unavailable" }),
657
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg text-muted-foreground", children: "We can\u2019t confirm waitlist availability right now. Please try again later." })
658
- ] }) })
659
- ] });
660
- }
661
- if (canCheckStatus && (productStatus === "ACTIVE" || productStatus === "RELEASED")) {
662
- const appUrl = product?.appUrl || product?.website || "#";
663
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
664
- seo && /* @__PURE__ */ jsxRuntime.jsx(
665
- PageHead,
666
- {
667
- title: seo.title ?? "",
668
- description: seo.description ?? "",
669
- keywords: seo.keywords,
670
- image: seo.image,
671
- url: seo.url
672
- }
673
- ),
674
- /* @__PURE__ */ jsxRuntime.jsx("section", { className: "relative overflow-hidden py-24 lg:py-32", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 text-center space-y-8", children: [
675
- /* @__PURE__ */ jsxRuntime.jsxs("h1", { className: "text-4xl font-bold tracking-tight sm:text-5xl text-foreground", children: [
676
- displayName,
677
- " is now available!"
678
- ] }),
679
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-lg text-muted-foreground", children: [
680
- "Great news \u2014 ",
681
- displayName,
682
- " is open to everyone. Sign up or log in to get started."
683
- ] }),
684
- /* @__PURE__ */ jsxRuntime.jsx(Button, { size: "lg", asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("a", { href: appUrl, target: "_blank", rel: "noopener noreferrer", children: "Get Started" }) })
685
- ] }) })
686
- ] });
687
- }
688
- if (canCheckStatus && (productStatus === "DRAFT" || productStatus === "COMING_SOON")) {
689
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
690
- seo && /* @__PURE__ */ jsxRuntime.jsx(
691
- PageHead,
692
- {
693
- title: seo.title ?? "",
694
- description: seo.description ?? "",
695
- keywords: seo.keywords,
696
- image: seo.image,
697
- url: seo.url
698
- }
699
- ),
700
- /* @__PURE__ */ jsxRuntime.jsx("section", { className: "relative overflow-hidden py-24 lg:py-32", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 text-center space-y-8", children: [
701
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-4xl font-bold tracking-tight sm:text-5xl text-foreground", children: "Coming Soon" }),
702
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-lg text-muted-foreground", children: [
703
- displayName,
704
- " is not yet accepting waitlist signups. Check back soon!"
705
- ] })
706
- ] }) })
707
- ] });
708
- }
709
- if (canCheckStatus && productStatus !== "WAITLIST") {
710
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
711
- seo && /* @__PURE__ */ jsxRuntime.jsx(
712
- PageHead,
713
- {
714
- title: seo.title ?? "",
715
- description: seo.description ?? "",
716
- keywords: seo.keywords,
717
- image: seo.image,
718
- url: seo.url
719
- }
720
- ),
721
- /* @__PURE__ */ jsxRuntime.jsx("section", { className: "relative overflow-hidden py-24 lg:py-32", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 text-center space-y-6", children: [
722
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-4xl font-bold tracking-tight sm:text-5xl text-foreground", children: "Waitlist Unavailable" }),
723
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-lg text-muted-foreground", children: [
724
- displayName,
725
- " is not accepting waitlist signups right now."
726
- ] })
727
- ] }) })
728
- ] });
729
- }
730
- const onSubmit = async (data) => {
731
- if (canCheckStatus && productStatus !== "WAITLIST") {
732
- sonner.toast.error("This product is not accepting waitlist signups right now.");
733
- return;
734
- }
735
- if (checkLimit()) {
736
- sonner.toast.error(
737
- `Too many attempts. Please try again after ${resetTime?.toLocaleTimeString()}`
738
- );
739
- return;
740
- }
741
- setIsSubmitting(true);
742
- try {
743
- const result = await joinWaitlist(
744
- client,
745
- data,
746
- product?.id || config.productId
747
- );
748
- if (result.success) {
749
- trackWebsiteEvent("waitlist.signed_up", { form: "page" });
750
- sonner.toast.success(result.message ?? successMessage);
751
- reset();
752
- } else {
753
- sonner.toast.error(result.message ?? errorMessage);
754
- }
755
- recordAttempt();
756
- } catch (_error) {
757
- sonner.toast.error(errorMessage);
758
- } finally {
759
- setIsSubmitting(false);
760
- }
761
- };
762
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
763
- seo && /* @__PURE__ */ jsxRuntime.jsx(
764
- PageHead,
765
- {
766
- title: seo.title ?? `Join the Waitlist - ${displayName}`,
767
- description: seo.description ?? heroDescription ?? heroSubtitle,
768
- productName: displayName,
769
- keywords: seo.keywords,
770
- image: seo.image,
771
- url: seo.url
772
- }
773
- ),
774
- /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-screen flex items-center justify-center px-4 py-12", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-lg w-full space-y-8", children: [
775
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
776
- /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-4xl font-bold tracking-tight", children: heroTitle }),
777
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-lg text-muted-foreground", children: heroSubtitle }),
778
- heroDescription && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-4 text-sm text-muted-foreground", children: heroDescription })
779
- ] }),
780
- /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit(onSubmit), className: "space-y-5", children: [
781
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
782
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "waitlist-name", children: "Name *" }),
783
- /* @__PURE__ */ jsxRuntime.jsx(
784
- Input,
785
- {
786
- id: "waitlist-name",
787
- type: "text",
788
- placeholder: "Your name",
789
- disabled: isSubmitting || isLimited,
790
- ...register("name")
791
- }
792
- ),
793
- errors.name && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: errors.name.message })
794
- ] }),
795
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
796
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "waitlist-email", children: "Email *" }),
797
- /* @__PURE__ */ jsxRuntime.jsx(
798
- Input,
799
- {
800
- id: "waitlist-email",
801
- type: "email",
802
- placeholder: "you@example.com",
803
- disabled: isSubmitting || isLimited,
804
- ...register("email")
805
- }
806
- ),
807
- errors.email && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: errors.email.message })
808
- ] }),
809
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
810
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "waitlist-company", children: "Company" }),
811
- /* @__PURE__ */ jsxRuntime.jsx(
812
- Input,
813
- {
814
- id: "waitlist-company",
815
- type: "text",
816
- placeholder: "Your company (optional)",
817
- disabled: isSubmitting || isLimited,
818
- ...register("company")
819
- }
820
- )
821
- ] }),
822
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
823
- /* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "waitlist-reason", children: "Why are you interested?" }),
824
- /* @__PURE__ */ jsxRuntime.jsx(
825
- Textarea,
826
- {
827
- id: "waitlist-reason",
828
- placeholder: "Tell us what excites you about the product (optional)",
829
- rows: 3,
830
- disabled: isSubmitting || isLimited,
831
- className: "resize-y",
832
- ...register("reason")
833
- }
834
- )
835
- ] }),
836
- /* @__PURE__ */ jsxRuntime.jsx(
837
- Button,
838
- {
839
- type: "submit",
840
- className: "w-full",
841
- disabled: isSubmitting || isLimited,
842
- children: isSubmitting ? "Joining..." : "Join Waitlist"
843
- }
844
- ),
845
- isLimited && resetTime && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground text-center", children: [
846
- "Rate limit reached. Try again after",
847
- " ",
848
- resetTime.toLocaleTimeString()
849
- ] })
850
- ] }),
851
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground text-center", children: [
852
- "By joining the waitlist, you agree to receive updates from",
853
- " ",
854
- displayName,
855
- ". We respect your privacy and will never share your information."
856
- ] })
857
- ] }) }) })
858
- ] });
859
- }
860
- function WaitlistForm({
861
- variant = "inline",
862
- showLabel = false,
863
- showDescription = false,
864
- showNameField = false,
865
- description = "Join our waitlist to get early access",
866
- buttonText = "Join Waitlist",
867
- className = ""
868
- }) {
869
- const client = useWebSDK();
870
- const config = useWebSDKConfig();
871
- const {
872
- product,
873
- loading: productLoading,
874
- error: productError,
875
- hasProvider
876
- } = useProduct();
877
- const productStatus = product?.status;
878
- const canCheckStatus = Boolean(config.productSlug);
879
- const [email, setEmail] = React.useState("");
880
- const [name, setName] = React.useState("");
881
- const [isLoading, setIsLoading] = React.useState(false);
882
- const handleSubmit = async (e) => {
883
- e.preventDefault();
884
- if (canCheckStatus && productStatus !== "WAITLIST") {
885
- sonner.toast.error("This product is not accepting waitlist signups right now.");
886
- return;
887
- }
888
- if (!email || !email.includes("@")) {
889
- sonner.toast.error("Please enter a valid email address");
890
- return;
891
- }
892
- setIsLoading(true);
893
- try {
894
- const result = await joinWaitlist(
895
- client,
896
- { email, name: name || void 0 },
897
- product?.id || config.productId
898
- );
899
- if (result.success) {
900
- trackWebsiteEvent("waitlist.signed_up", { form: "inline" });
901
- sonner.toast.success(result.message ?? "You have been added to the waitlist!");
902
- setEmail("");
903
- setName("");
904
- } else {
905
- sonner.toast.error(result.message ?? "Failed to join waitlist");
906
- }
907
- } catch (_error) {
908
- sonner.toast.error("An error occurred. Please try again.");
909
- } finally {
910
- setIsLoading(false);
911
- }
912
- };
913
- const isInline = variant === "inline";
914
- if (canCheckStatus && !hasProvider) {
915
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
916
- showDescription && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mb-3", children: description }),
917
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-muted-foreground", children: [
918
- "Product status checks require ",
919
- /* @__PURE__ */ jsxRuntime.jsx("code", { children: "ProductProvider" }),
920
- " to be mounted."
921
- ] })
922
- ] });
923
- }
924
- if (canCheckStatus && productLoading) {
925
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
926
- showDescription && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mb-3", children: description }),
927
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Loading waitlist\u2026" })
928
- ] });
929
- }
930
- if (canCheckStatus && (productError || productStatus !== "WAITLIST")) {
931
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
932
- showDescription && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mb-3", children: description }),
933
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: "Waitlist signups are not available right now." })
934
- ] });
935
- }
936
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
937
- showDescription && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground mb-3", children: description }),
938
- /* @__PURE__ */ jsxRuntime.jsxs(
939
- "form",
940
- {
941
- onSubmit: handleSubmit,
942
- className: isInline ? "flex gap-2" : "flex flex-col gap-2",
943
- children: [
944
- showNameField && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: isInline ? "flex-1" : "w-full", children: [
945
- showLabel && /* @__PURE__ */ jsxRuntime.jsx(
946
- Label,
947
- {
948
- htmlFor: "waitlist-inline-name",
949
- className: "text-sm mb-1 block",
950
- children: "Name"
951
- }
952
- ),
953
- /* @__PURE__ */ jsxRuntime.jsx(
954
- Input,
955
- {
956
- id: "waitlist-inline-name",
957
- type: "text",
958
- placeholder: "Your name",
959
- value: name,
960
- onChange: (e) => setName(e.target.value),
961
- disabled: isLoading,
962
- className: "w-full"
963
- }
964
- )
965
- ] }),
966
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: isInline ? "flex-1" : "w-full", children: [
967
- showLabel && /* @__PURE__ */ jsxRuntime.jsx(
968
- Label,
969
- {
970
- htmlFor: "waitlist-inline-email",
971
- className: "text-sm mb-1 block",
972
- children: "Email"
973
- }
974
- ),
975
- /* @__PURE__ */ jsxRuntime.jsx(
976
- Input,
977
- {
978
- id: "waitlist-inline-email",
979
- type: "email",
980
- placeholder: "Enter your email",
981
- value: email,
982
- onChange: (e) => setEmail(e.target.value),
983
- disabled: isLoading,
984
- required: true,
985
- className: "w-full"
986
- }
987
- )
988
- ] }),
989
- /* @__PURE__ */ jsxRuntime.jsx(
990
- Button,
991
- {
992
- type: "submit",
993
- disabled: isLoading,
994
- className: isInline ? "whitespace-nowrap" : "w-full",
995
- children: isLoading ? "Joining..." : buttonText
996
- }
997
- )
998
- ]
999
- }
1000
- )
1001
- ] });
1002
- }
1003
-
1004
- exports.WaitlistForm = WaitlistForm;
1005
- exports.WaitlistPage = WaitlistPage;
1006
26
  //# sourceMappingURL=waitlist.js.map
1007
27
  //# sourceMappingURL=waitlist.js.map