@burdenoff/website-sdk 2026.1031.3 → 2026.1101.2

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 (274) hide show
  1. package/README.md +42 -8
  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 +10 -30
  11. package/dist/avatar-live-view/index.js.map +1 -1
  12. package/dist/avatar-live-view/index.mjs +4 -24
  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.js +4145 -20599
  255. package/dist/index.js.map +1 -1
  256. package/dist/index.mjs +3766 -20567
  257. package/dist/index.mjs.map +1 -1
  258. package/dist/product/index.js +20 -393
  259. package/dist/product/index.js.map +1 -1
  260. package/dist/product/index.mjs +5 -394
  261. package/dist/product/index.mjs.map +1 -1
  262. package/dist/seo/index.js +8 -76
  263. package/dist/seo/index.js.map +1 -1
  264. package/dist/seo/index.mjs +3 -78
  265. package/dist/seo/index.mjs.map +1 -1
  266. package/dist/store/index.js +51 -2650
  267. package/dist/store/index.js.map +1 -1
  268. package/dist/store/index.mjs +13 -2619
  269. package/dist/store/index.mjs.map +1 -1
  270. package/dist/utils/index.js +69 -134
  271. package/dist/utils/index.js.map +1 -1
  272. package/dist/utils/index.mjs +5 -122
  273. package/dist/utils/index.mjs.map +1 -1
  274. package/package.json +2 -1
@@ -1,118 +1,14 @@
1
1
  'use strict';
2
2
 
3
- var react = require('react');
4
- var lucideReact = require('lucide-react');
5
- var clsx = require('clsx');
6
- var tailwindMerge = require('tailwind-merge');
7
- var jsxRuntime = require('react/jsx-runtime');
3
+ var chunkOYEUNZJY_js = require('../chunk-OYEUNZJY.js');
4
+ require('../chunk-C6OJIHNO.js');
5
+ require('../chunk-ZSTFX7FV.js');
8
6
 
9
- function cn(...inputs) {
10
- return tailwindMerge.twMerge(clsx.clsx(inputs));
11
- }
12
- function useCurrentPath(explicit) {
13
- const [path, setPath] = react.useState(explicit ?? null);
14
- react.useEffect(() => {
15
- if (explicit !== void 0) {
16
- setPath(explicit);
17
- return;
18
- }
19
- if (typeof window === "undefined") return;
20
- const read = () => setPath(window.location.pathname);
21
- read();
22
- window.addEventListener("popstate", read);
23
- return () => window.removeEventListener("popstate", read);
24
- }, [explicit]);
25
- return path;
26
- }
27
- function samePath(a, b) {
28
- if (!a) return false;
29
- const norm = (v) => v.length > 1 ? v.replace(/\/+$/, "") : v;
30
- return norm(a) === norm(b);
31
- }
32
- var ExploreCta = react.forwardRef(
33
- function ExploreCta2({
34
- variant,
35
- href = "/explore",
36
- label = "Ask AI",
37
- className,
38
- onNavigate,
39
- onClick,
40
- currentPath,
41
- expanded,
42
- controls
43
- }, ref) {
44
- const path = useCurrentPath(currentPath);
45
- const isActive = samePath(path, href);
46
- if (variant === "floating" && isActive) return null;
47
- const handleClick = (event) => {
48
- onClick?.();
49
- if (!onNavigate) return;
50
- if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0) {
51
- return;
52
- }
53
- event.preventDefault();
54
- onNavigate(href);
55
- };
56
- const classes = {
57
- // A quiet icon control, deliberately NOT a second gradient pill: a header should carry one
58
- // primary CTA ("Get started"), and a competing coloured button next to it reads as clutter.
59
- // This matches the theme toggle's visual weight, so the row scans as [utilities] [CTA].
60
- // The prominent, labelled entry point to /explore is the floating bubble, which is visible
61
- // on every page without scrolling. `shrink-0` keeps it from squeezing the nav.
62
- header: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
63
- mobile: "inline-flex w-full items-center gap-2 rounded-lg border border-border bg-card px-3 py-2 text-sm font-medium text-card-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
64
- floating: "fixed bottom-5 right-5 z-40 inline-flex items-center gap-2 rounded-full bg-gradient-to-r from-primary to-primary/70 px-4 py-3 text-sm font-medium text-primary-foreground shadow-lg transition-opacity hover:opacity-90"
65
- };
66
- const hooks = {
67
- header: "cta-header",
68
- mobile: "cta-mobile",
69
- floating: "cta-floating"
70
- };
71
- return /* @__PURE__ */ jsxRuntime.jsxs(
72
- "a",
73
- {
74
- ref,
75
- "data-boff-explore": hooks[variant],
76
- href,
77
- onClick: handleClick,
78
- "aria-label": label,
79
- "aria-current": isActive ? "page" : void 0,
80
- "aria-expanded": expanded,
81
- "aria-haspopup": expanded === void 0 ? void 0 : "dialog",
82
- "aria-controls": expanded === void 0 ? void 0 : controls,
83
- className: cn(
84
- classes[variant],
85
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
86
- className
87
- ),
88
- children: [
89
- /* @__PURE__ */ jsxRuntime.jsx(
90
- lucideReact.Sparkles,
91
- {
92
- className: cn(
93
- "shrink-0",
94
- variant === "floating" ? "h-4 w-4" : variant === "header" ? "h-5 w-5" : "h-3.5 w-3.5"
95
- ),
96
- "aria-hidden": "true"
97
- }
98
- ),
99
- /* @__PURE__ */ jsxRuntime.jsx(
100
- "span",
101
- {
102
- className: cn(
103
- variant === "floating" && "hidden sm:inline",
104
- // Never labelled in the header — see the class comment above.
105
- variant === "header" && "hidden"
106
- ),
107
- children: label
108
- }
109
- )
110
- ]
111
- }
112
- );
113
- }
114
- );
115
7
 
116
- exports.ExploreCta = ExploreCta;
8
+
9
+ Object.defineProperty(exports, "ExploreCta", {
10
+ enumerable: true,
11
+ get: function () { return chunkOYEUNZJY_js.ExploreCta; }
12
+ });
117
13
  //# sourceMappingURL=explore-cta.js.map
118
14
  //# sourceMappingURL=explore-cta.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/cn.ts","../../src/components/explore-cta.tsx"],"names":["twMerge","clsx","useState","useEffect","forwardRef","ExploreCta","jsxs","jsx","Sparkles"],"mappings":"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","file":"explore-cta.js","sourcesContent":["/**\n * Utility function to merge Tailwind CSS classes\n * Combines clsx and tailwind-merge for optimal class handling\n */\n\nimport { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge multiple class names intelligently\n * - Handles conditional classes via clsx\n * - Deduplicates and resolves Tailwind conflicts via tailwind-merge\n *\n * @example\n * ```ts\n * cn('px-4 py-2', 'bg-blue-500', { 'text-white': isActive })\n * // => 'px-4 py-2 bg-blue-500 text-white' (if isActive is true)\n * ```\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","/**\n * ExploreCta — the entry point to `/explore` from a site's navigation.\n *\n * Three shapes of the same link, so a product site can place it once in the\n * desktop header, once in the mobile menu, and optionally as a floating bubble\n * on content pages, without any of them re-implementing the styling:\n *\n * - `header` — a gradient sparkle pill for the desktop nav.\n * - `mobile` — a compact full-width row for a mobile menu list.\n * - `floating` — a fixed bottom-right bubble; hides itself on `/explore`\n * so it never covers the page it links to.\n *\n * Import from the package ROOT (`@burdenoff/website-sdk`) for consistency with\n * `ExplorePage`, which must be root-imported because of tsup's\n * `splitting: false`. This component holds no context of its own, so a\n * sub-path import also works — but keeping both on the root import is one less\n * footgun for the 38 sites that ship them together.\n *\n * @example\n * ```tsx\n * import { ExploreCta } from '@burdenoff/website-sdk'\n *\n * <ExploreCta variant=\"header\" onNavigate={(href) => navigate(href)} />\n * <ExploreCta variant=\"floating\" currentPath={location.pathname} />\n * ```\n */\n\"use client\";\n\nimport { forwardRef, useEffect, useState } from \"react\";\n\nimport { Sparkles } from \"lucide-react\";\n\nimport { cn } from \"../utils/cn\";\n\nexport interface ExploreCtaProps {\n /** Which of the three presentations to render. */\n variant: \"header\" | \"mobile\" | \"floating\";\n /** Target route. Default `/explore`. */\n href?: string;\n /** Visible label / accessible name. Default `Ask AI`. */\n label?: string;\n /** Extra classes for the rendered element. */\n className?: string;\n /** SPA navigation. When omitted the component renders a plain `<a href>`. */\n onNavigate?: (href: string) => void;\n /** Extra click handler (analytics, closing a mobile menu, …). */\n onClick?: () => void;\n /**\n * Current route, when the host knows it (`useLocation().pathname`).\n * Used to mark the link as `aria-current=\"page\"` and to hide the floating\n * bubble on the Explore page itself. Falls back to `window.location.pathname`,\n * which cannot observe SPA `pushState` navigations on its own.\n */\n currentPath?: string;\n /**\n * BOFF-9697. For a host whose floating button opens the site-wide assistant panel (`ExplorePanel`) instead of\n * navigating: whether that panel is open. When set, the link also says it opens a dialog (`aria-haspopup`) and\n * which one (`controls`). Unset (every other site): the link renders exactly as before.\n */\n expanded?: boolean;\n /** BOFF-9697. The id of the panel the button opens; used only together with `expanded`. */\n controls?: string;\n}\n\n/**\n * Resolve the active path without breaking SSR/prerender: the first render\n * always returns `null` (matching the server output), and the real value lands\n * in an effect. `popstate` covers back/forward; hosts that navigate with\n * `pushState` should pass `currentPath` from their router.\n */\nfunction useCurrentPath(explicit?: string): string | null {\n const [path, setPath] = useState<string | null>(explicit ?? null);\n\n useEffect(() => {\n if (explicit !== undefined) {\n setPath(explicit);\n return;\n }\n if (typeof window === \"undefined\") return;\n const read = () => setPath(window.location.pathname);\n read();\n window.addEventListener(\"popstate\", read);\n return () => window.removeEventListener(\"popstate\", read);\n }, [explicit]);\n\n return path;\n}\n\n/** `/explore` and `/explore/` are the same page. */\nfunction samePath(a: string | null, b: string): boolean {\n if (!a) return false;\n const norm = (v: string) => (v.length > 1 ? v.replace(/\\/+$/, \"\") : v);\n return norm(a) === norm(b);\n}\n\n/** The rendered `<a>` is forwarded, so a panel can return focus to the button that opened it (BOFF-9697). */\nexport const ExploreCta = forwardRef<HTMLAnchorElement, ExploreCtaProps>(\n function ExploreCta(\n {\n variant,\n href = \"/explore\",\n label = \"Ask AI\",\n className,\n onNavigate,\n onClick,\n currentPath,\n expanded,\n controls,\n },\n ref,\n ) {\n const path = useCurrentPath(currentPath);\n const isActive = samePath(path, href);\n\n // The floating bubble exists to get visitors TO /explore. On /explore it is\n // pure obstruction, so it removes itself.\n if (variant === \"floating\" && isActive) return null;\n\n const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {\n onClick?.();\n if (!onNavigate) return;\n // Let the browser handle modified clicks (new tab, download, …).\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey ||\n event.button !== 0\n ) {\n return;\n }\n event.preventDefault();\n onNavigate(href);\n };\n\n const classes: Record<ExploreCtaProps[\"variant\"], string> = {\n // A quiet icon control, deliberately NOT a second gradient pill: a header should carry one\n // primary CTA (\"Get started\"), and a competing coloured button next to it reads as clutter.\n // This matches the theme toggle's visual weight, so the row scans as [utilities] [CTA].\n // The prominent, labelled entry point to /explore is the floating bubble, which is visible\n // on every page without scrolling. `shrink-0` keeps it from squeezing the nav.\n header:\n \"inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground\",\n mobile:\n \"inline-flex w-full items-center gap-2 rounded-lg border border-border bg-card px-3 py-2 text-sm font-medium text-card-foreground transition-colors hover:bg-accent hover:text-accent-foreground\",\n floating:\n \"fixed bottom-5 right-5 z-40 inline-flex items-center gap-2 rounded-full bg-gradient-to-r from-primary to-primary/70 px-4 py-3 text-sm font-medium text-primary-foreground shadow-lg transition-opacity hover:opacity-90\",\n };\n\n const hooks: Record<ExploreCtaProps[\"variant\"], string> = {\n header: \"cta-header\",\n mobile: \"cta-mobile\",\n floating: \"cta-floating\",\n };\n\n return (\n <a\n ref={ref}\n data-boff-explore={hooks[variant]}\n href={href}\n onClick={handleClick}\n aria-label={label}\n aria-current={isActive ? \"page\" : undefined}\n aria-expanded={expanded}\n aria-haspopup={expanded === undefined ? undefined : \"dialog\"}\n aria-controls={expanded === undefined ? undefined : controls}\n className={cn(\n classes[variant],\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n className,\n )}\n >\n <Sparkles\n className={cn(\n \"shrink-0\",\n variant === \"floating\"\n ? \"h-4 w-4\"\n : variant === \"header\"\n ? \"h-5 w-5\"\n : \"h-3.5 w-3.5\",\n )}\n aria-hidden=\"true\"\n />\n {/* The icon alone carries the affordance where space is tight; `aria-label` carries\n the accessible name at every width, so hiding the text costs nothing to a\n screen reader. Floating shows its label from `sm` up, header from `2xl`. */}\n <span\n className={cn(\n variant === \"floating\" && \"hidden sm:inline\",\n // Never labelled in the header — see the class comment above.\n variant === \"header\" && \"hidden\",\n )}\n >\n {label}\n </span>\n </a>\n );\n },\n);\n"]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"explore-cta.js"}
@@ -1,116 +1,5 @@
1
- import { forwardRef, useState, useEffect } from 'react';
2
- import { Sparkles } from 'lucide-react';
3
- import { clsx } from 'clsx';
4
- import { twMerge } from 'tailwind-merge';
5
- import { jsxs, jsx } from 'react/jsx-runtime';
6
-
7
- function cn(...inputs) {
8
- return twMerge(clsx(inputs));
9
- }
10
- function useCurrentPath(explicit) {
11
- const [path, setPath] = useState(explicit ?? null);
12
- useEffect(() => {
13
- if (explicit !== void 0) {
14
- setPath(explicit);
15
- return;
16
- }
17
- if (typeof window === "undefined") return;
18
- const read = () => setPath(window.location.pathname);
19
- read();
20
- window.addEventListener("popstate", read);
21
- return () => window.removeEventListener("popstate", read);
22
- }, [explicit]);
23
- return path;
24
- }
25
- function samePath(a, b) {
26
- if (!a) return false;
27
- const norm = (v) => v.length > 1 ? v.replace(/\/+$/, "") : v;
28
- return norm(a) === norm(b);
29
- }
30
- var ExploreCta = forwardRef(
31
- function ExploreCta2({
32
- variant,
33
- href = "/explore",
34
- label = "Ask AI",
35
- className,
36
- onNavigate,
37
- onClick,
38
- currentPath,
39
- expanded,
40
- controls
41
- }, ref) {
42
- const path = useCurrentPath(currentPath);
43
- const isActive = samePath(path, href);
44
- if (variant === "floating" && isActive) return null;
45
- const handleClick = (event) => {
46
- onClick?.();
47
- if (!onNavigate) return;
48
- if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey || event.button !== 0) {
49
- return;
50
- }
51
- event.preventDefault();
52
- onNavigate(href);
53
- };
54
- const classes = {
55
- // A quiet icon control, deliberately NOT a second gradient pill: a header should carry one
56
- // primary CTA ("Get started"), and a competing coloured button next to it reads as clutter.
57
- // This matches the theme toggle's visual weight, so the row scans as [utilities] [CTA].
58
- // The prominent, labelled entry point to /explore is the floating bubble, which is visible
59
- // on every page without scrolling. `shrink-0` keeps it from squeezing the nav.
60
- header: "inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
61
- mobile: "inline-flex w-full items-center gap-2 rounded-lg border border-border bg-card px-3 py-2 text-sm font-medium text-card-foreground transition-colors hover:bg-accent hover:text-accent-foreground",
62
- floating: "fixed bottom-5 right-5 z-40 inline-flex items-center gap-2 rounded-full bg-gradient-to-r from-primary to-primary/70 px-4 py-3 text-sm font-medium text-primary-foreground shadow-lg transition-opacity hover:opacity-90"
63
- };
64
- const hooks = {
65
- header: "cta-header",
66
- mobile: "cta-mobile",
67
- floating: "cta-floating"
68
- };
69
- return /* @__PURE__ */ jsxs(
70
- "a",
71
- {
72
- ref,
73
- "data-boff-explore": hooks[variant],
74
- href,
75
- onClick: handleClick,
76
- "aria-label": label,
77
- "aria-current": isActive ? "page" : void 0,
78
- "aria-expanded": expanded,
79
- "aria-haspopup": expanded === void 0 ? void 0 : "dialog",
80
- "aria-controls": expanded === void 0 ? void 0 : controls,
81
- className: cn(
82
- classes[variant],
83
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
84
- className
85
- ),
86
- children: [
87
- /* @__PURE__ */ jsx(
88
- Sparkles,
89
- {
90
- className: cn(
91
- "shrink-0",
92
- variant === "floating" ? "h-4 w-4" : variant === "header" ? "h-5 w-5" : "h-3.5 w-3.5"
93
- ),
94
- "aria-hidden": "true"
95
- }
96
- ),
97
- /* @__PURE__ */ jsx(
98
- "span",
99
- {
100
- className: cn(
101
- variant === "floating" && "hidden sm:inline",
102
- // Never labelled in the header — see the class comment above.
103
- variant === "header" && "hidden"
104
- ),
105
- children: label
106
- }
107
- )
108
- ]
109
- }
110
- );
111
- }
112
- );
113
-
114
- export { ExploreCta };
1
+ export { ExploreCta } from '../chunk-Y4V5CEWD.mjs';
2
+ import '../chunk-R7G6TWIS.mjs';
3
+ import '../chunk-VNS5WDWO.mjs';
115
4
  //# sourceMappingURL=explore-cta.mjs.map
116
5
  //# sourceMappingURL=explore-cta.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/utils/cn.ts","../../src/components/explore-cta.tsx"],"names":["ExploreCta"],"mappings":"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","file":"explore-cta.mjs","sourcesContent":["/**\n * Utility function to merge Tailwind CSS classes\n * Combines clsx and tailwind-merge for optimal class handling\n */\n\nimport { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/**\n * Merge multiple class names intelligently\n * - Handles conditional classes via clsx\n * - Deduplicates and resolves Tailwind conflicts via tailwind-merge\n *\n * @example\n * ```ts\n * cn('px-4 py-2', 'bg-blue-500', { 'text-white': isActive })\n * // => 'px-4 py-2 bg-blue-500 text-white' (if isActive is true)\n * ```\n */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","/**\n * ExploreCta — the entry point to `/explore` from a site's navigation.\n *\n * Three shapes of the same link, so a product site can place it once in the\n * desktop header, once in the mobile menu, and optionally as a floating bubble\n * on content pages, without any of them re-implementing the styling:\n *\n * - `header` — a gradient sparkle pill for the desktop nav.\n * - `mobile` — a compact full-width row for a mobile menu list.\n * - `floating` — a fixed bottom-right bubble; hides itself on `/explore`\n * so it never covers the page it links to.\n *\n * Import from the package ROOT (`@burdenoff/website-sdk`) for consistency with\n * `ExplorePage`, which must be root-imported because of tsup's\n * `splitting: false`. This component holds no context of its own, so a\n * sub-path import also works — but keeping both on the root import is one less\n * footgun for the 38 sites that ship them together.\n *\n * @example\n * ```tsx\n * import { ExploreCta } from '@burdenoff/website-sdk'\n *\n * <ExploreCta variant=\"header\" onNavigate={(href) => navigate(href)} />\n * <ExploreCta variant=\"floating\" currentPath={location.pathname} />\n * ```\n */\n\"use client\";\n\nimport { forwardRef, useEffect, useState } from \"react\";\n\nimport { Sparkles } from \"lucide-react\";\n\nimport { cn } from \"../utils/cn\";\n\nexport interface ExploreCtaProps {\n /** Which of the three presentations to render. */\n variant: \"header\" | \"mobile\" | \"floating\";\n /** Target route. Default `/explore`. */\n href?: string;\n /** Visible label / accessible name. Default `Ask AI`. */\n label?: string;\n /** Extra classes for the rendered element. */\n className?: string;\n /** SPA navigation. When omitted the component renders a plain `<a href>`. */\n onNavigate?: (href: string) => void;\n /** Extra click handler (analytics, closing a mobile menu, …). */\n onClick?: () => void;\n /**\n * Current route, when the host knows it (`useLocation().pathname`).\n * Used to mark the link as `aria-current=\"page\"` and to hide the floating\n * bubble on the Explore page itself. Falls back to `window.location.pathname`,\n * which cannot observe SPA `pushState` navigations on its own.\n */\n currentPath?: string;\n /**\n * BOFF-9697. For a host whose floating button opens the site-wide assistant panel (`ExplorePanel`) instead of\n * navigating: whether that panel is open. When set, the link also says it opens a dialog (`aria-haspopup`) and\n * which one (`controls`). Unset (every other site): the link renders exactly as before.\n */\n expanded?: boolean;\n /** BOFF-9697. The id of the panel the button opens; used only together with `expanded`. */\n controls?: string;\n}\n\n/**\n * Resolve the active path without breaking SSR/prerender: the first render\n * always returns `null` (matching the server output), and the real value lands\n * in an effect. `popstate` covers back/forward; hosts that navigate with\n * `pushState` should pass `currentPath` from their router.\n */\nfunction useCurrentPath(explicit?: string): string | null {\n const [path, setPath] = useState<string | null>(explicit ?? null);\n\n useEffect(() => {\n if (explicit !== undefined) {\n setPath(explicit);\n return;\n }\n if (typeof window === \"undefined\") return;\n const read = () => setPath(window.location.pathname);\n read();\n window.addEventListener(\"popstate\", read);\n return () => window.removeEventListener(\"popstate\", read);\n }, [explicit]);\n\n return path;\n}\n\n/** `/explore` and `/explore/` are the same page. */\nfunction samePath(a: string | null, b: string): boolean {\n if (!a) return false;\n const norm = (v: string) => (v.length > 1 ? v.replace(/\\/+$/, \"\") : v);\n return norm(a) === norm(b);\n}\n\n/** The rendered `<a>` is forwarded, so a panel can return focus to the button that opened it (BOFF-9697). */\nexport const ExploreCta = forwardRef<HTMLAnchorElement, ExploreCtaProps>(\n function ExploreCta(\n {\n variant,\n href = \"/explore\",\n label = \"Ask AI\",\n className,\n onNavigate,\n onClick,\n currentPath,\n expanded,\n controls,\n },\n ref,\n ) {\n const path = useCurrentPath(currentPath);\n const isActive = samePath(path, href);\n\n // The floating bubble exists to get visitors TO /explore. On /explore it is\n // pure obstruction, so it removes itself.\n if (variant === \"floating\" && isActive) return null;\n\n const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {\n onClick?.();\n if (!onNavigate) return;\n // Let the browser handle modified clicks (new tab, download, …).\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey ||\n event.altKey ||\n event.button !== 0\n ) {\n return;\n }\n event.preventDefault();\n onNavigate(href);\n };\n\n const classes: Record<ExploreCtaProps[\"variant\"], string> = {\n // A quiet icon control, deliberately NOT a second gradient pill: a header should carry one\n // primary CTA (\"Get started\"), and a competing coloured button next to it reads as clutter.\n // This matches the theme toggle's visual weight, so the row scans as [utilities] [CTA].\n // The prominent, labelled entry point to /explore is the floating bubble, which is visible\n // on every page without scrolling. `shrink-0` keeps it from squeezing the nav.\n header:\n \"inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground\",\n mobile:\n \"inline-flex w-full items-center gap-2 rounded-lg border border-border bg-card px-3 py-2 text-sm font-medium text-card-foreground transition-colors hover:bg-accent hover:text-accent-foreground\",\n floating:\n \"fixed bottom-5 right-5 z-40 inline-flex items-center gap-2 rounded-full bg-gradient-to-r from-primary to-primary/70 px-4 py-3 text-sm font-medium text-primary-foreground shadow-lg transition-opacity hover:opacity-90\",\n };\n\n const hooks: Record<ExploreCtaProps[\"variant\"], string> = {\n header: \"cta-header\",\n mobile: \"cta-mobile\",\n floating: \"cta-floating\",\n };\n\n return (\n <a\n ref={ref}\n data-boff-explore={hooks[variant]}\n href={href}\n onClick={handleClick}\n aria-label={label}\n aria-current={isActive ? \"page\" : undefined}\n aria-expanded={expanded}\n aria-haspopup={expanded === undefined ? undefined : \"dialog\"}\n aria-controls={expanded === undefined ? undefined : controls}\n className={cn(\n classes[variant],\n \"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n className,\n )}\n >\n <Sparkles\n className={cn(\n \"shrink-0\",\n variant === \"floating\"\n ? \"h-4 w-4\"\n : variant === \"header\"\n ? \"h-5 w-5\"\n : \"h-3.5 w-3.5\",\n )}\n aria-hidden=\"true\"\n />\n {/* The icon alone carries the affordance where space is tight; `aria-label` carries\n the accessible name at every width, so hiding the text costs nothing to a\n screen reader. Floating shows its label from `sm` up, header from `2xl`. */}\n <span\n className={cn(\n variant === \"floating\" && \"hidden sm:inline\",\n // Never labelled in the header — see the class comment above.\n variant === \"header\" && \"hidden\",\n )}\n >\n {label}\n </span>\n </a>\n );\n },\n);\n"]}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"explore-cta.mjs"}