shared-features 0.0.1 → 0.0.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 (48) hide show
  1. package/README.md +84 -7
  2. package/dist/AdBanner-B9918Vst.cjs +1427 -0
  3. package/dist/AdBanner-B9918Vst.cjs.map +1 -0
  4. package/dist/AdBanner-z1osYgog.js +1428 -0
  5. package/dist/AdBanner-z1osYgog.js.map +1 -0
  6. package/dist/components/ads/AdBanner.d.ts +25 -0
  7. package/dist/components/ads/AdBanner.d.ts.map +1 -0
  8. package/dist/components/ads/AdModal.d.ts +27 -0
  9. package/dist/components/ads/AdModal.d.ts.map +1 -0
  10. package/dist/components/ads/AdSlider.d.ts +21 -0
  11. package/dist/components/ads/AdSlider.d.ts.map +1 -0
  12. package/dist/components/ads/AdUpdateModal.d.ts +27 -0
  13. package/dist/components/ads/AdUpdateModal.d.ts.map +1 -0
  14. package/dist/components/ads/index.d.ts +9 -0
  15. package/dist/components/ads/index.d.ts.map +1 -1
  16. package/dist/components/ads/variants/LargePanelVariants.d.ts +34 -0
  17. package/dist/components/ads/variants/LargePanelVariants.d.ts.map +1 -0
  18. package/dist/components/ads/variants/SmallPanelVariants.d.ts +34 -0
  19. package/dist/components/ads/variants/SmallPanelVariants.d.ts.map +1 -0
  20. package/dist/components/ads/variants/index.d.ts +12 -0
  21. package/dist/components/ads/variants/index.d.ts.map +1 -0
  22. package/dist/components/index.cjs +20 -2
  23. package/dist/components/index.cjs.map +1 -1
  24. package/dist/components/index.js +20 -2
  25. package/dist/hooks/index.cjs +3 -1
  26. package/dist/hooks/index.cjs.map +1 -1
  27. package/dist/hooks/index.d.ts +1 -1
  28. package/dist/hooks/index.d.ts.map +1 -1
  29. package/dist/hooks/index.js +4 -2
  30. package/dist/hooks/useCampaigns.d.ts +44 -0
  31. package/dist/hooks/useCampaigns.d.ts.map +1 -1
  32. package/dist/index.cjs +23 -3
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.js +23 -3
  35. package/dist/types/campaigns.d.ts +20 -32
  36. package/dist/types/campaigns.d.ts.map +1 -1
  37. package/dist/types/index.cjs.map +1 -1
  38. package/dist/types/index.js.map +1 -1
  39. package/dist/{useCampaigns-BNOHpETm.cjs → useCampaigns-BKGqKAUo.cjs} +56 -1
  40. package/dist/useCampaigns-BKGqKAUo.cjs.map +1 -0
  41. package/dist/{useCampaigns-3NxODLLs.js → useCampaigns-osYDc6WC.js} +56 -1
  42. package/dist/{useCampaigns-3NxODLLs.js.map → useCampaigns-osYDc6WC.js.map} +1 -1
  43. package/package.json +3 -1
  44. package/dist/AdPanel-D0BiV6Xb.cjs +0 -88
  45. package/dist/AdPanel-D0BiV6Xb.cjs.map +0 -1
  46. package/dist/AdPanel-RGRBf4ub.js +0 -89
  47. package/dist/AdPanel-RGRBf4ub.js.map +0 -1
  48. package/dist/useCampaigns-BNOHpETm.cjs.map +0 -1
@@ -0,0 +1,1427 @@
1
+ "use strict";
2
+ const jsxRuntime = require("react/jsx-runtime");
3
+ const react = require("react");
4
+ const themes = require("@radix-ui/themes");
5
+ const reactIcons = require("@radix-ui/react-icons");
6
+ const useCampaigns = require("./useCampaigns-BKGqKAUo.cjs");
7
+ const lucideReact = require("lucide-react");
8
+ const analytics = require("./analytics-6shJHRZG.cjs");
9
+ function AdPanel({
10
+ placement,
11
+ variant: _variant = "small_panel_2",
12
+ className
13
+ }) {
14
+ const { campaign, loading, error, recordImpression, recordClick, recordClose } = useCampaigns.useCampaign({ placement });
15
+ const hasRecordedImpression = react.useRef(false);
16
+ react.useEffect(() => {
17
+ if (campaign && !hasRecordedImpression.current) {
18
+ hasRecordedImpression.current = true;
19
+ recordImpression(campaign);
20
+ }
21
+ }, [campaign, recordImpression]);
22
+ if (loading || error || !campaign) {
23
+ return null;
24
+ }
25
+ const handleClick = () => {
26
+ recordClick(campaign);
27
+ const url = campaign.customCtaUrl || campaign.product.url;
28
+ window.open(url, "_blank", "noopener,noreferrer");
29
+ };
30
+ const handleClose = () => {
31
+ recordClose(campaign);
32
+ };
33
+ const title = campaign.customTitle || campaign.product.name;
34
+ const tagline = campaign.customTagline || campaign.product.tagline;
35
+ const ctaText = campaign.customCta || "Learn More";
36
+ const color = campaign.customProductColor || campaign.product.color;
37
+ return /* @__PURE__ */ jsxRuntime.jsxs(
38
+ themes.Box,
39
+ {
40
+ className,
41
+ style: {
42
+ border: `1px solid ${color}`,
43
+ borderRadius: "8px",
44
+ padding: "12px",
45
+ backgroundColor: `${color}10`,
46
+ position: "relative"
47
+ },
48
+ children: [
49
+ /* @__PURE__ */ jsxRuntime.jsx(
50
+ themes.IconButton,
51
+ {
52
+ size: "1",
53
+ variant: "ghost",
54
+ onClick: handleClose,
55
+ style: {
56
+ position: "absolute",
57
+ top: "4px",
58
+ right: "4px"
59
+ },
60
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactIcons.Cross2Icon, {})
61
+ }
62
+ ),
63
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { direction: "column", gap: "2", children: [
64
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "2", children: [
65
+ campaign.product.icon64 && /* @__PURE__ */ jsxRuntime.jsx(
66
+ themes.Box,
67
+ {
68
+ dangerouslySetInnerHTML: { __html: campaign.product.icon64 },
69
+ style: { width: 32, height: 32 }
70
+ }
71
+ ),
72
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { weight: "bold", size: "3", style: { color }, children: title })
73
+ ] }),
74
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", color: "gray", children: tagline }),
75
+ /* @__PURE__ */ jsxRuntime.jsx(
76
+ themes.Button,
77
+ {
78
+ size: "2",
79
+ onClick: handleClick,
80
+ style: { backgroundColor: color },
81
+ children: ctaText
82
+ }
83
+ )
84
+ ] })
85
+ ]
86
+ }
87
+ );
88
+ }
89
+ function getDisplayValues$1(campaign) {
90
+ const isCustomProduct = !campaign.product.icon64 && campaign.customIcon;
91
+ return {
92
+ displayTitle: campaign.customTitle || campaign.product.name,
93
+ displayTagline: campaign.customTagline || campaign.product.tagline,
94
+ displayCta: campaign.customCta || "Learn More",
95
+ displayUrl: campaign.customCtaUrl || campaign.product.url,
96
+ displayIcon: campaign.customIcon || campaign.product.icon64 || "",
97
+ displayColor: campaign.customProductColor || campaign.product.color || "#3B82F6",
98
+ displayFeatures: campaign.customFeatures || campaign.product.features || [],
99
+ isCustomProduct
100
+ };
101
+ }
102
+ function MinimalVariant({ campaign, onCTAClick, onClose }) {
103
+ const { displayTitle, displayCta, displayUrl, displayIcon, displayColor } = getDisplayValues$1(campaign);
104
+ return /* @__PURE__ */ jsxRuntime.jsx(themes.Card, { size: "1", children: /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", justify: "between", gap: "3", p: "2", children: [
105
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "3", children: [
106
+ /* @__PURE__ */ jsxRuntime.jsx(
107
+ themes.Box,
108
+ {
109
+ style: {
110
+ width: 32,
111
+ height: 32,
112
+ borderRadius: "var(--radius-2)",
113
+ background: `color-mix(in srgb, ${displayColor} 15%, transparent)`,
114
+ display: "flex",
115
+ alignItems: "center",
116
+ justifyContent: "center"
117
+ },
118
+ dangerouslySetInnerHTML: { __html: displayIcon }
119
+ }
120
+ ),
121
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", weight: "medium", children: displayTitle })
122
+ ] }),
123
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "2", children: [
124
+ /* @__PURE__ */ jsxRuntime.jsx(
125
+ themes.Link,
126
+ {
127
+ href: displayUrl,
128
+ target: "_blank",
129
+ onClick: onCTAClick,
130
+ style: { textDecoration: "none" },
131
+ children: /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "1", children: [
132
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", color: "blue", children: displayCta }),
133
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { size: 14 })
134
+ ] })
135
+ }
136
+ ),
137
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Button, { variant: "ghost", size: "1", color: "gray", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 14 }) })
138
+ ] })
139
+ ] }) });
140
+ }
141
+ function TaglineVariant({ campaign, onCTAClick, onClose }) {
142
+ const { displayTitle, displayTagline, displayCta, displayUrl, displayIcon, displayColor } = getDisplayValues$1(campaign);
143
+ return /* @__PURE__ */ jsxRuntime.jsx(themes.Card, { size: "1", children: /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", justify: "between", gap: "3", p: "3", children: [
144
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "3", children: [
145
+ /* @__PURE__ */ jsxRuntime.jsx(
146
+ themes.Box,
147
+ {
148
+ style: {
149
+ width: 40,
150
+ height: 40,
151
+ borderRadius: "var(--radius-2)",
152
+ background: `color-mix(in srgb, ${displayColor} 15%, transparent)`,
153
+ display: "flex",
154
+ alignItems: "center",
155
+ justifyContent: "center",
156
+ flexShrink: 0
157
+ },
158
+ dangerouslySetInnerHTML: { __html: displayIcon }
159
+ }
160
+ ),
161
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Box, { children: [
162
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", weight: "bold", children: displayTitle }),
163
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "1", color: "gray", children: displayTagline })
164
+ ] })
165
+ ] }),
166
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "2", children: [
167
+ /* @__PURE__ */ jsxRuntime.jsx(
168
+ themes.Button,
169
+ {
170
+ size: "1",
171
+ style: { background: displayColor },
172
+ onClick: () => {
173
+ onCTAClick?.();
174
+ window.open(displayUrl, "_blank");
175
+ },
176
+ children: displayCta
177
+ }
178
+ ),
179
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Button, { variant: "ghost", size: "1", color: "gray", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 14 }) })
180
+ ] })
181
+ ] }) });
182
+ }
183
+ function FeaturesVariant({ campaign, onCTAClick, onClose }) {
184
+ const { displayTitle, displayCta, displayUrl, displayIcon, displayColor, displayFeatures } = getDisplayValues$1(campaign);
185
+ const features = displayFeatures.slice(0, 2);
186
+ return /* @__PURE__ */ jsxRuntime.jsx(themes.Card, { size: "1", children: /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", justify: "between", gap: "3", p: "3", children: [
187
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "3", children: [
188
+ /* @__PURE__ */ jsxRuntime.jsx(
189
+ themes.Box,
190
+ {
191
+ style: {
192
+ width: 40,
193
+ height: 40,
194
+ borderRadius: "var(--radius-2)",
195
+ background: `color-mix(in srgb, ${displayColor} 15%, transparent)`,
196
+ display: "flex",
197
+ alignItems: "center",
198
+ justifyContent: "center",
199
+ flexShrink: 0
200
+ },
201
+ dangerouslySetInnerHTML: { __html: displayIcon }
202
+ }
203
+ ),
204
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Box, { children: [
205
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", weight: "bold", mb: "1", children: displayTitle }),
206
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Flex, { gap: "1", wrap: "wrap", children: features.map((feature, i) => /* @__PURE__ */ jsxRuntime.jsxs(themes.Badge, { size: "1", variant: "soft", color: "gray", children: [
207
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 10, style: { marginRight: 2 } }),
208
+ feature
209
+ ] }, i)) })
210
+ ] })
211
+ ] }),
212
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "2", children: [
213
+ /* @__PURE__ */ jsxRuntime.jsx(
214
+ themes.Button,
215
+ {
216
+ size: "1",
217
+ style: { background: displayColor },
218
+ onClick: () => {
219
+ onCTAClick?.();
220
+ window.open(displayUrl, "_blank");
221
+ },
222
+ children: displayCta
223
+ }
224
+ ),
225
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Button, { variant: "ghost", size: "1", color: "gray", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 14 }) })
226
+ ] })
227
+ ] }) });
228
+ }
229
+ function GradientVariant({ campaign, onCTAClick, onClose }) {
230
+ const { displayTitle, displayTagline, displayCta, displayUrl, displayIcon, displayColor } = getDisplayValues$1(campaign);
231
+ return /* @__PURE__ */ jsxRuntime.jsx(
232
+ themes.Box,
233
+ {
234
+ style: {
235
+ background: `linear-gradient(135deg, ${displayColor} 0%, color-mix(in srgb, ${displayColor} 80%, black) 100%)`,
236
+ borderRadius: "var(--radius-3)",
237
+ padding: "var(--space-3)",
238
+ color: "white"
239
+ },
240
+ children: /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", justify: "between", gap: "3", children: [
241
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "3", children: [
242
+ /* @__PURE__ */ jsxRuntime.jsx(
243
+ themes.Box,
244
+ {
245
+ style: {
246
+ width: 40,
247
+ height: 40,
248
+ borderRadius: "var(--radius-2)",
249
+ background: "rgba(255, 255, 255, 0.2)",
250
+ display: "flex",
251
+ alignItems: "center",
252
+ justifyContent: "center",
253
+ flexShrink: 0
254
+ },
255
+ children: /* @__PURE__ */ jsxRuntime.jsx(
256
+ themes.Box,
257
+ {
258
+ dangerouslySetInnerHTML: { __html: displayIcon },
259
+ style: {
260
+ color: "white"
261
+ }
262
+ }
263
+ )
264
+ }
265
+ ),
266
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Box, { children: [
267
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", weight: "bold", style: { color: "white" }, children: displayTitle }),
268
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "1", style: { color: "rgba(255, 255, 255, 0.8)" }, children: displayTagline })
269
+ ] })
270
+ ] }),
271
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "2", children: [
272
+ /* @__PURE__ */ jsxRuntime.jsx(
273
+ themes.Button,
274
+ {
275
+ size: "1",
276
+ variant: "soft",
277
+ style: {
278
+ background: "white",
279
+ color: displayColor
280
+ },
281
+ onClick: () => {
282
+ onCTAClick?.();
283
+ window.open(displayUrl, "_blank");
284
+ },
285
+ children: displayCta
286
+ }
287
+ ),
288
+ /* @__PURE__ */ jsxRuntime.jsx(
289
+ themes.Button,
290
+ {
291
+ variant: "ghost",
292
+ size: "1",
293
+ onClick: onClose,
294
+ style: { color: "rgba(255, 255, 255, 0.8)" },
295
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 14 })
296
+ }
297
+ )
298
+ ] })
299
+ ] })
300
+ }
301
+ );
302
+ }
303
+ function CardVariant({ campaign, onCTAClick, onClose }) {
304
+ const { displayTitle, displayTagline, displayCta, displayUrl, displayIcon, displayColor } = getDisplayValues$1(campaign);
305
+ return /* @__PURE__ */ jsxRuntime.jsx(
306
+ themes.Card,
307
+ {
308
+ size: "2",
309
+ style: {
310
+ boxShadow: "0 4px 20px rgba(0, 0, 0, 0.1)",
311
+ transition: "all 0.2s ease",
312
+ border: `1px solid ${displayColor}20`
313
+ },
314
+ children: /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { direction: "column", gap: "3", p: "1", children: [
315
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", justify: "between", children: [
316
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "1", children: [
317
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { size: 14, color: displayColor }),
318
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "1", color: "gray", weight: "medium", children: "RECOMMENDED" })
319
+ ] }),
320
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Button, { variant: "ghost", size: "1", color: "gray", onClick: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 14 }) })
321
+ ] }),
322
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "3", children: [
323
+ /* @__PURE__ */ jsxRuntime.jsx(
324
+ themes.Box,
325
+ {
326
+ style: {
327
+ width: 48,
328
+ height: 48,
329
+ borderRadius: "var(--radius-3)",
330
+ background: `color-mix(in srgb, ${displayColor} 15%, transparent)`,
331
+ display: "flex",
332
+ alignItems: "center",
333
+ justifyContent: "center",
334
+ flexShrink: 0
335
+ },
336
+ dangerouslySetInnerHTML: { __html: displayIcon }
337
+ }
338
+ ),
339
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Box, { style: { flex: 1 }, children: [
340
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", weight: "bold", children: displayTitle }),
341
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "1", color: "gray", children: displayTagline })
342
+ ] })
343
+ ] }),
344
+ /* @__PURE__ */ jsxRuntime.jsxs(
345
+ themes.Button,
346
+ {
347
+ size: "2",
348
+ style: { background: displayColor, width: "100%" },
349
+ onClick: () => {
350
+ onCTAClick?.();
351
+ window.open(displayUrl, "_blank");
352
+ },
353
+ children: [
354
+ displayCta,
355
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { size: 14 })
356
+ ]
357
+ }
358
+ )
359
+ ] })
360
+ }
361
+ );
362
+ }
363
+ const SMALL_PANEL_VARIANTS = {
364
+ small_panel_1: MinimalVariant,
365
+ small_panel_2: TaglineVariant,
366
+ small_panel_3: FeaturesVariant,
367
+ small_panel_4: GradientVariant,
368
+ small_panel_5: CardVariant
369
+ };
370
+ function getSmallPanelVariant(variantName) {
371
+ return SMALL_PANEL_VARIANTS[variantName] || TaglineVariant;
372
+ }
373
+ function AdSlider({
374
+ placement = "footer_slider",
375
+ className,
376
+ style
377
+ }) {
378
+ const hasTrackedImpression = react.useRef(false);
379
+ const {
380
+ campaign,
381
+ loading,
382
+ recordImpression,
383
+ recordClick,
384
+ recordClose
385
+ } = useCampaigns.useCampaign({ placement });
386
+ react.useEffect(() => {
387
+ if (campaign && !hasTrackedImpression.current) {
388
+ hasTrackedImpression.current = true;
389
+ recordImpression(campaign);
390
+ }
391
+ }, [campaign, recordImpression]);
392
+ const handleCTAClick = react.useCallback(() => {
393
+ if (!campaign) return;
394
+ recordClick(campaign);
395
+ }, [campaign, recordClick]);
396
+ const handleClose = react.useCallback(() => {
397
+ if (!campaign) return;
398
+ recordClose(campaign);
399
+ }, [campaign, recordClose]);
400
+ if (loading || !campaign) {
401
+ return null;
402
+ }
403
+ const variantName = campaign.variant || "small_panel_2";
404
+ const VariantComponent = getSmallPanelVariant(variantName);
405
+ return /* @__PURE__ */ jsxRuntime.jsx(themes.Box, { className, style, children: /* @__PURE__ */ jsxRuntime.jsx(
406
+ VariantComponent,
407
+ {
408
+ campaign,
409
+ onCTAClick: handleCTAClick,
410
+ onClose: handleClose
411
+ }
412
+ ) });
413
+ }
414
+ function AdModal({
415
+ placement = "onetime_modal",
416
+ onClose,
417
+ welcomeTitle,
418
+ welcomeDescription
419
+ }) {
420
+ const [dontShowAgain, setDontShowAgain] = react.useState(false);
421
+ const hasTrackedImpression = react.useRef(false);
422
+ const config = analytics.getConfig();
423
+ const { shouldShow, markAsShown } = useCampaigns.useOneTimeAdModal();
424
+ const {
425
+ campaign,
426
+ loading,
427
+ recordImpression,
428
+ recordClick,
429
+ recordClose
430
+ } = useCampaigns.useCampaign({ placement });
431
+ react.useEffect(() => {
432
+ if (shouldShow && campaign && !hasTrackedImpression.current) {
433
+ hasTrackedImpression.current = true;
434
+ recordImpression(campaign);
435
+ }
436
+ }, [shouldShow, campaign, recordImpression]);
437
+ const handleCTAClick = react.useCallback(() => {
438
+ if (!campaign) return;
439
+ recordClick(campaign);
440
+ const targetUrl = campaign.customCtaUrl || campaign.product.url;
441
+ window.open(targetUrl, "_blank");
442
+ }, [campaign, recordClick]);
443
+ const handleClose = react.useCallback(() => {
444
+ if (campaign) {
445
+ recordClose(campaign);
446
+ }
447
+ markAsShown();
448
+ onClose?.();
449
+ }, [campaign, recordClose, markAsShown, onClose]);
450
+ if (!shouldShow || loading) {
451
+ return null;
452
+ }
453
+ if (!campaign) {
454
+ const defaultTitle = welcomeTitle || `Welcome to ${config.projectName}!`;
455
+ const defaultDesc = welcomeDescription || "Discover amazing features and tools at your fingertips.";
456
+ return /* @__PURE__ */ jsxRuntime.jsx(themes.Dialog.Root, { open: true, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(themes.Dialog.Content, { style: { maxWidth: 450 }, children: [
457
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Dialog.Title, { children: /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "2", children: [
458
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Gift, { size: 24 }),
459
+ defaultTitle
460
+ ] }) }),
461
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Dialog.Description, { size: "2", mb: "4", children: defaultDesc }),
462
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Flex, { gap: "3", mt: "4", justify: "end", children: /* @__PURE__ */ jsxRuntime.jsx(themes.Dialog.Close, { children: /* @__PURE__ */ jsxRuntime.jsx(themes.Button, { variant: "soft", color: "gray", children: "Start Exploring" }) }) })
463
+ ] }) });
464
+ }
465
+ const { product } = campaign;
466
+ const displayTitle = campaign.customTitle || product.name;
467
+ const displayTagline = campaign.customTagline || product.tagline;
468
+ const displayDescription = campaign.customDescription || product.description;
469
+ const displayCta = campaign.customCta || "Learn More";
470
+ const displayIcon = campaign.customIcon || product.icon128 || product.icon64 || "";
471
+ const displayColor = campaign.customProductColor || product.color || "#3B82F6";
472
+ const displayFeatures = campaign.customFeatures || product.features || [];
473
+ return /* @__PURE__ */ jsxRuntime.jsx(themes.Dialog.Root, { open: true, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(themes.Dialog.Content, { style: { maxWidth: 500 }, children: [
474
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Flex, { justify: "end", mb: "2", children: /* @__PURE__ */ jsxRuntime.jsx(themes.Dialog.Close, { children: /* @__PURE__ */ jsxRuntime.jsx(themes.Button, { variant: "ghost", size: "1", color: "gray", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 16 }) }) }) }),
475
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { direction: "column", align: "center", gap: "4", p: "4", style: { textAlign: "center" }, children: [
476
+ /* @__PURE__ */ jsxRuntime.jsx(
477
+ themes.Box,
478
+ {
479
+ style: {
480
+ width: 96,
481
+ height: 96,
482
+ borderRadius: "var(--radius-4)",
483
+ background: `color-mix(in srgb, ${displayColor} 15%, transparent)`,
484
+ display: "flex",
485
+ alignItems: "center",
486
+ justifyContent: "center"
487
+ },
488
+ dangerouslySetInnerHTML: { __html: displayIcon }
489
+ }
490
+ ),
491
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Box, { children: [
492
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Heading, { size: "5", weight: "bold", mb: "2", children: displayTitle }),
493
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "3", color: "gray", children: displayTagline })
494
+ ] }),
495
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", color: "gray", style: { maxWidth: 350, lineHeight: 1.6 }, children: displayDescription }),
496
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Flex, { wrap: "wrap", gap: "2", justify: "center", children: displayFeatures.slice(0, 4).map((feature, i) => /* @__PURE__ */ jsxRuntime.jsx(
497
+ themes.Box,
498
+ {
499
+ style: {
500
+ padding: "var(--space-1) var(--space-2)",
501
+ borderRadius: "var(--radius-2)",
502
+ background: "var(--gray-a3)",
503
+ fontSize: "var(--font-size-1)"
504
+ },
505
+ children: feature
506
+ },
507
+ i
508
+ )) }),
509
+ /* @__PURE__ */ jsxRuntime.jsxs(
510
+ themes.Button,
511
+ {
512
+ size: "3",
513
+ style: { background: displayColor, marginTop: "var(--space-2)" },
514
+ onClick: handleCTAClick,
515
+ children: [
516
+ displayCta,
517
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { size: 16 })
518
+ ]
519
+ }
520
+ ),
521
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "2", mt: "2", children: [
522
+ /* @__PURE__ */ jsxRuntime.jsx(
523
+ themes.Checkbox,
524
+ {
525
+ checked: dontShowAgain,
526
+ onCheckedChange: (checked) => setDontShowAgain(checked === true)
527
+ }
528
+ ),
529
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "1", color: "gray", children: "Don't show this again" })
530
+ ] })
531
+ ] })
532
+ ] }) });
533
+ }
534
+ function getDisplayValues(campaign) {
535
+ const isCustomProduct = !campaign.product.icon64 && campaign.customIcon;
536
+ return {
537
+ displayTitle: campaign.customTitle || campaign.product.name,
538
+ displayTagline: campaign.customTagline || campaign.product.tagline,
539
+ displayDescription: campaign.customDescription || campaign.product.description,
540
+ displayCta: campaign.customCta || "Learn More",
541
+ displayUrl: campaign.customCtaUrl || campaign.product.url,
542
+ displayIcon64: campaign.customIcon || campaign.product.icon64 || "",
543
+ displayIcon128: campaign.customIcon || campaign.product.icon128 || campaign.product.icon64 || "",
544
+ displayColor: campaign.customProductColor || campaign.product.color || "#3B82F6",
545
+ displayFeatures: campaign.customFeatures || campaign.product.features || [],
546
+ isCustomProduct
547
+ };
548
+ }
549
+ const DEFAULT_TESTIMONIALS = {
550
+ "video-controls-plus": '"Finally, I have complete control over video playback. The keyboard shortcuts save me so much time!"',
551
+ "ztools-web": '"300+ tools in one place. I use it daily for encoding, formatting, and data conversion tasks."',
552
+ "ztools-extension": '"Quick access to all my favorite tools right from the browser. Super convenient!"',
553
+ "pregnancy-pal-android": '"The weekly updates and kick counter are amazing. Best pregnancy tracking app!"',
554
+ "pregnancy-pal-web": '"Love being able to access my pregnancy data from any device. The sync is seamless."',
555
+ "lab-system-web": '"Streamlined our entire lab workflow. Sample tracking has never been easier."'
556
+ };
557
+ const DEFAULT_COMPARISONS = {
558
+ "video-controls-plus": {
559
+ before: ["Limited playback control", "No keyboard shortcuts", "Manual ad skipping", "No speed control"],
560
+ after: ["Full playback control", "Custom shortcuts", "Auto ad skip", "0.1x - 16x speed"]
561
+ },
562
+ "ztools-web": {
563
+ before: ["Multiple websites", "Scattered tools", "No offline access", "Ads everywhere"],
564
+ after: ["One destination", "300+ tools", "Works offline", "Ad-free experience"]
565
+ },
566
+ "ztools-extension": {
567
+ before: ["Open new tabs", "Search for tools", "Copy/paste repeatedly", "Time wasted"],
568
+ after: ["Instant access", "Quick search", "One-click actions", "Time saved"]
569
+ },
570
+ "pregnancy-pal-android": {
571
+ before: ["Paper tracking", "Forget updates", "Manual counting", "Scattered info"],
572
+ after: ["Digital diary", "Weekly reminders", "Auto tracking", "All in one app"]
573
+ },
574
+ "pregnancy-pal-web": {
575
+ before: ["Phone only", "No backup", "Limited access", "Data silos"],
576
+ after: ["Any device", "Cloud sync", "Always available", "Unified data"]
577
+ },
578
+ "lab-system-web": {
579
+ before: ["Paper records", "Manual tracking", "Error prone", "Slow reports"],
580
+ after: ["Digital records", "Auto tracking", "Accurate data", "Instant reports"]
581
+ }
582
+ };
583
+ function HeroVariant({
584
+ campaign,
585
+ onCTAClick,
586
+ showIndicator,
587
+ currentIndex,
588
+ totalCount
589
+ }) {
590
+ const { displayTitle, displayTagline, displayDescription, displayCta, displayUrl, displayIcon128, displayColor } = getDisplayValues(campaign);
591
+ return /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { direction: "column", align: "center", gap: "4", p: "5", style: { textAlign: "center" }, children: [
592
+ showIndicator && currentIndex !== void 0 && totalCount !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(themes.Text, { size: "1", color: "gray", style: { position: "absolute", top: 16, right: 16 }, children: [
593
+ currentIndex + 1,
594
+ " / ",
595
+ totalCount
596
+ ] }),
597
+ /* @__PURE__ */ jsxRuntime.jsx(
598
+ themes.Box,
599
+ {
600
+ style: {
601
+ width: 80,
602
+ height: 80,
603
+ borderRadius: "var(--radius-4)",
604
+ background: `color-mix(in srgb, ${displayColor} 15%, transparent)`,
605
+ display: "flex",
606
+ alignItems: "center",
607
+ justifyContent: "center"
608
+ },
609
+ dangerouslySetInnerHTML: { __html: displayIcon128 }
610
+ }
611
+ ),
612
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Heading, { size: "5", weight: "bold", children: displayTitle }),
613
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "3", color: "gray", children: displayTagline }),
614
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", color: "gray", style: { maxWidth: 300, lineHeight: 1.6 }, children: displayDescription }),
615
+ /* @__PURE__ */ jsxRuntime.jsxs(
616
+ themes.Button,
617
+ {
618
+ size: "3",
619
+ style: { background: displayColor, marginTop: "var(--space-2)" },
620
+ onClick: () => {
621
+ onCTAClick?.();
622
+ window.open(displayUrl, "_blank");
623
+ },
624
+ children: [
625
+ displayCta,
626
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { size: 16 })
627
+ ]
628
+ }
629
+ )
630
+ ] });
631
+ }
632
+ function FeatureGridVariant({
633
+ campaign,
634
+ onCTAClick,
635
+ showIndicator,
636
+ currentIndex,
637
+ totalCount
638
+ }) {
639
+ const { displayTitle, displayCta, displayUrl, displayIcon64, displayColor, displayFeatures } = getDisplayValues(campaign);
640
+ const features = displayFeatures.slice(0, 4);
641
+ return /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { direction: "column", gap: "4", p: "5", children: [
642
+ showIndicator && currentIndex !== void 0 && totalCount !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(themes.Text, { size: "1", color: "gray", style: { position: "absolute", top: 16, right: 16 }, children: [
643
+ currentIndex + 1,
644
+ " / ",
645
+ totalCount
646
+ ] }),
647
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "3", children: [
648
+ /* @__PURE__ */ jsxRuntime.jsx(
649
+ themes.Box,
650
+ {
651
+ style: {
652
+ width: 48,
653
+ height: 48,
654
+ borderRadius: "var(--radius-3)",
655
+ background: `color-mix(in srgb, ${displayColor} 15%, transparent)`,
656
+ display: "flex",
657
+ alignItems: "center",
658
+ justifyContent: "center",
659
+ flexShrink: 0
660
+ },
661
+ dangerouslySetInnerHTML: { __html: displayIcon64 }
662
+ }
663
+ ),
664
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Heading, { size: "4", weight: "bold", children: displayTitle })
665
+ ] }),
666
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Grid, { columns: "2", gap: "3", children: features.map((feature, i) => /* @__PURE__ */ jsxRuntime.jsx(themes.Card, { size: "1", style: { background: "var(--gray-a2)" }, children: /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "2", p: "2", children: [
667
+ /* @__PURE__ */ jsxRuntime.jsx(
668
+ themes.Flex,
669
+ {
670
+ align: "center",
671
+ justify: "center",
672
+ style: {
673
+ width: 24,
674
+ height: 24,
675
+ borderRadius: "50%",
676
+ background: displayColor,
677
+ color: "white",
678
+ fontSize: 12,
679
+ fontWeight: "bold",
680
+ flexShrink: 0
681
+ },
682
+ children: i + 1
683
+ }
684
+ ),
685
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", children: feature })
686
+ ] }) }, i)) }),
687
+ /* @__PURE__ */ jsxRuntime.jsxs(
688
+ themes.Button,
689
+ {
690
+ size: "3",
691
+ style: { background: displayColor, width: "100%" },
692
+ onClick: () => {
693
+ onCTAClick?.();
694
+ window.open(displayUrl, "_blank");
695
+ },
696
+ children: [
697
+ displayCta,
698
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { size: 16 })
699
+ ]
700
+ }
701
+ )
702
+ ] });
703
+ }
704
+ function TestimonialVariant({
705
+ campaign,
706
+ onCTAClick,
707
+ showIndicator,
708
+ currentIndex,
709
+ totalCount
710
+ }) {
711
+ const { product } = campaign;
712
+ const { displayTitle, displayTagline, displayCta, displayUrl, displayIcon64, displayColor } = getDisplayValues(campaign);
713
+ const quote = DEFAULT_TESTIMONIALS[product.id] || '"An amazing tool that makes my work easier every day."';
714
+ return /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { direction: "column", gap: "4", p: "5", style: { background: "var(--gray-a2)", borderRadius: "var(--radius-3)" }, children: [
715
+ showIndicator && currentIndex !== void 0 && totalCount !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(themes.Text, { size: "1", color: "gray", style: { position: "absolute", top: 16, right: 16 }, children: [
716
+ currentIndex + 1,
717
+ " / ",
718
+ totalCount
719
+ ] }),
720
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Box, { style: { position: "relative", padding: "var(--space-3)" }, children: [
721
+ /* @__PURE__ */ jsxRuntime.jsx(
722
+ lucideReact.Quote,
723
+ {
724
+ size: 32,
725
+ style: {
726
+ position: "absolute",
727
+ top: 0,
728
+ left: "50%",
729
+ transform: "translateX(-50%)",
730
+ opacity: 0.15,
731
+ color: displayColor
732
+ }
733
+ }
734
+ ),
735
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "3", style: { fontStyle: "italic", textAlign: "center", lineHeight: 1.6 }, children: quote }),
736
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", color: "gray", style: { textAlign: "center", marginTop: "var(--space-2)" }, children: "— Happy User" })
737
+ ] }),
738
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Card, { size: "1", children: /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "3", p: "3", children: [
739
+ /* @__PURE__ */ jsxRuntime.jsx(
740
+ themes.Box,
741
+ {
742
+ style: {
743
+ width: 48,
744
+ height: 48,
745
+ borderRadius: "var(--radius-3)",
746
+ background: `color-mix(in srgb, ${displayColor} 15%, transparent)`,
747
+ display: "flex",
748
+ alignItems: "center",
749
+ justifyContent: "center",
750
+ flexShrink: 0
751
+ },
752
+ dangerouslySetInnerHTML: { __html: displayIcon64 }
753
+ }
754
+ ),
755
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Box, { children: [
756
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", weight: "bold", children: displayTitle }),
757
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "1", color: "gray", children: displayTagline })
758
+ ] })
759
+ ] }) }),
760
+ /* @__PURE__ */ jsxRuntime.jsxs(
761
+ themes.Button,
762
+ {
763
+ size: "3",
764
+ style: { background: displayColor, width: "100%" },
765
+ onClick: () => {
766
+ onCTAClick?.();
767
+ window.open(displayUrl, "_blank");
768
+ },
769
+ children: [
770
+ displayCta,
771
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { size: 16 })
772
+ ]
773
+ }
774
+ )
775
+ ] });
776
+ }
777
+ function ComparisonVariant({
778
+ campaign,
779
+ onCTAClick,
780
+ showIndicator,
781
+ currentIndex,
782
+ totalCount
783
+ }) {
784
+ const { product } = campaign;
785
+ const { displayTitle, displayCta, displayUrl, displayIcon64, displayColor } = getDisplayValues(campaign);
786
+ const comparison = DEFAULT_COMPARISONS[product.id] || {
787
+ before: ["Old way", "Manual process", "Time consuming", "Limited features"],
788
+ after: ["Better way", "Automated", "Fast & easy", "Full features"]
789
+ };
790
+ return /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { direction: "column", gap: "4", p: "5", children: [
791
+ showIndicator && currentIndex !== void 0 && totalCount !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(themes.Text, { size: "1", color: "gray", style: { position: "absolute", top: 16, right: 16 }, children: [
792
+ currentIndex + 1,
793
+ " / ",
794
+ totalCount
795
+ ] }),
796
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "3", children: [
797
+ /* @__PURE__ */ jsxRuntime.jsx(
798
+ themes.Box,
799
+ {
800
+ style: {
801
+ width: 48,
802
+ height: 48,
803
+ borderRadius: "var(--radius-3)",
804
+ background: `color-mix(in srgb, ${displayColor} 15%, transparent)`,
805
+ display: "flex",
806
+ alignItems: "center",
807
+ justifyContent: "center",
808
+ flexShrink: 0
809
+ },
810
+ dangerouslySetInnerHTML: { __html: displayIcon64 }
811
+ }
812
+ ),
813
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Heading, { size: "4", weight: "bold", children: displayTitle })
814
+ ] }),
815
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { gap: "3", children: [
816
+ /* @__PURE__ */ jsxRuntime.jsxs(
817
+ themes.Box,
818
+ {
819
+ style: {
820
+ flex: 1,
821
+ padding: "var(--space-3)",
822
+ borderRadius: "var(--radius-2)",
823
+ background: "rgba(239, 68, 68, 0.1)"
824
+ },
825
+ children: [
826
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "1", weight: "bold", color: "red", mb: "2", style: { textTransform: "uppercase" }, children: "Before" }),
827
+ comparison.before.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "2", mb: "1", children: [
828
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 12, color: "var(--red-9)" }),
829
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "1", children: item })
830
+ ] }, i))
831
+ ]
832
+ }
833
+ ),
834
+ /* @__PURE__ */ jsxRuntime.jsxs(
835
+ themes.Box,
836
+ {
837
+ style: {
838
+ flex: 1,
839
+ padding: "var(--space-3)",
840
+ borderRadius: "var(--radius-2)",
841
+ background: "rgba(16, 185, 129, 0.1)"
842
+ },
843
+ children: [
844
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "1", weight: "bold", color: "green", mb: "2", style: { textTransform: "uppercase" }, children: "After" }),
845
+ comparison.after.map((item, i) => /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "2", mb: "1", children: [
846
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 12, color: "var(--green-9)" }),
847
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "1", children: item })
848
+ ] }, i))
849
+ ]
850
+ }
851
+ )
852
+ ] }),
853
+ /* @__PURE__ */ jsxRuntime.jsxs(
854
+ themes.Button,
855
+ {
856
+ size: "3",
857
+ style: { background: displayColor, width: "100%" },
858
+ onClick: () => {
859
+ onCTAClick?.();
860
+ window.open(displayUrl, "_blank");
861
+ },
862
+ children: [
863
+ displayCta,
864
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { size: 16 })
865
+ ]
866
+ }
867
+ )
868
+ ] });
869
+ }
870
+ function VideoVariant({
871
+ campaign,
872
+ onCTAClick,
873
+ showIndicator,
874
+ currentIndex,
875
+ totalCount
876
+ }) {
877
+ const { displayTitle, displayTagline, displayCta, displayUrl, displayIcon128, displayColor } = getDisplayValues(campaign);
878
+ return /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { direction: "column", align: "center", gap: "4", p: "5", style: { textAlign: "center" }, children: [
879
+ showIndicator && currentIndex !== void 0 && totalCount !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs(themes.Text, { size: "1", color: "gray", style: { position: "absolute", top: 16, right: 16 }, children: [
880
+ currentIndex + 1,
881
+ " / ",
882
+ totalCount
883
+ ] }),
884
+ /* @__PURE__ */ jsxRuntime.jsxs(
885
+ themes.Box,
886
+ {
887
+ style: {
888
+ position: "relative",
889
+ width: 140,
890
+ height: 140,
891
+ borderRadius: "var(--radius-4)",
892
+ background: `linear-gradient(135deg, color-mix(in srgb, ${displayColor} 20%, transparent), color-mix(in srgb, ${displayColor} 40%, transparent))`,
893
+ display: "flex",
894
+ alignItems: "center",
895
+ justifyContent: "center",
896
+ overflow: "hidden"
897
+ },
898
+ children: [
899
+ /* @__PURE__ */ jsxRuntime.jsx(
900
+ themes.Box,
901
+ {
902
+ style: {
903
+ animation: "shared-features-pulse 2s ease-in-out infinite"
904
+ },
905
+ dangerouslySetInnerHTML: { __html: displayIcon128 }
906
+ }
907
+ ),
908
+ /* @__PURE__ */ jsxRuntime.jsx(
909
+ themes.Flex,
910
+ {
911
+ align: "center",
912
+ justify: "center",
913
+ style: {
914
+ position: "absolute",
915
+ width: 56,
916
+ height: 56,
917
+ borderRadius: "50%",
918
+ background: "rgba(255, 255, 255, 0.95)",
919
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.2)",
920
+ cursor: "pointer",
921
+ transition: "transform 0.2s ease"
922
+ },
923
+ onClick: () => {
924
+ onCTAClick?.();
925
+ window.open(displayUrl, "_blank");
926
+ },
927
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Play, { size: 24, fill: displayColor, color: displayColor })
928
+ }
929
+ )
930
+ ]
931
+ }
932
+ ),
933
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Heading, { size: "5", weight: "bold", children: displayTitle }),
934
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", color: "gray", children: displayTagline }),
935
+ /* @__PURE__ */ jsxRuntime.jsxs(
936
+ themes.Button,
937
+ {
938
+ size: "3",
939
+ style: { background: displayColor, marginTop: "var(--space-2)" },
940
+ onClick: () => {
941
+ onCTAClick?.();
942
+ window.open(displayUrl, "_blank");
943
+ },
944
+ children: [
945
+ displayCta,
946
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { size: 16 })
947
+ ]
948
+ }
949
+ ),
950
+ /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
951
+ @keyframes shared-features-pulse {
952
+ 0%, 100% { transform: scale(1); }
953
+ 50% { transform: scale(1.1); }
954
+ }
955
+ ` })
956
+ ] });
957
+ }
958
+ const LARGE_PANEL_VARIANTS = {
959
+ large_slider_1: HeroVariant,
960
+ large_slider_2: FeatureGridVariant,
961
+ large_slider_3: TestimonialVariant,
962
+ large_slider_4: ComparisonVariant,
963
+ large_slider_5: VideoVariant
964
+ };
965
+ function getLargePanelVariant(variantName) {
966
+ return LARGE_PANEL_VARIANTS[variantName] || HeroVariant;
967
+ }
968
+ function AdUpdateModal({
969
+ placement = "update_modal",
970
+ maxCampaigns = 5,
971
+ autoAdvanceInterval = 5e3,
972
+ onClose
973
+ }) {
974
+ const [currentIndex, setCurrentIndex] = react.useState(0);
975
+ const autoAdvanceRef = react.useRef(null);
976
+ const trackedImpressions = react.useRef(/* @__PURE__ */ new Set());
977
+ const { shouldShow, currentVersion, markAsShown } = useCampaigns.useUpdateAdModal();
978
+ const {
979
+ campaigns,
980
+ loading,
981
+ recordImpression,
982
+ recordClick,
983
+ recordClose
984
+ } = useCampaigns.useCampaigns({ placement, maxCampaigns });
985
+ react.useEffect(() => {
986
+ if (shouldShow && campaigns.length > 0 && currentIndex < campaigns.length) {
987
+ const campaign = campaigns[currentIndex];
988
+ if (campaign && !trackedImpressions.current.has(campaign.id)) {
989
+ trackedImpressions.current.add(campaign.id);
990
+ recordImpression(campaign);
991
+ }
992
+ }
993
+ }, [shouldShow, campaigns, currentIndex, recordImpression]);
994
+ react.useEffect(() => {
995
+ if (!shouldShow || campaigns.length <= 1 || autoAdvanceInterval <= 0) return;
996
+ autoAdvanceRef.current = setInterval(() => {
997
+ setCurrentIndex((prev) => (prev + 1) % campaigns.length);
998
+ }, autoAdvanceInterval);
999
+ return () => {
1000
+ if (autoAdvanceRef.current) {
1001
+ clearInterval(autoAdvanceRef.current);
1002
+ }
1003
+ };
1004
+ }, [shouldShow, campaigns.length, autoAdvanceInterval]);
1005
+ const resetAutoAdvance = react.useCallback(() => {
1006
+ if (autoAdvanceRef.current) {
1007
+ clearInterval(autoAdvanceRef.current);
1008
+ }
1009
+ if (autoAdvanceInterval > 0 && campaigns.length > 1) {
1010
+ autoAdvanceRef.current = setInterval(() => {
1011
+ setCurrentIndex((prev) => (prev + 1) % campaigns.length);
1012
+ }, autoAdvanceInterval);
1013
+ }
1014
+ }, [autoAdvanceInterval, campaigns.length]);
1015
+ const goToPrevious = react.useCallback(() => {
1016
+ setCurrentIndex((prev) => (prev - 1 + campaigns.length) % campaigns.length);
1017
+ resetAutoAdvance();
1018
+ }, [campaigns.length, resetAutoAdvance]);
1019
+ const goToNext = react.useCallback(() => {
1020
+ setCurrentIndex((prev) => (prev + 1) % campaigns.length);
1021
+ resetAutoAdvance();
1022
+ }, [campaigns.length, resetAutoAdvance]);
1023
+ const goToSlide = react.useCallback(
1024
+ (index) => {
1025
+ setCurrentIndex(index);
1026
+ resetAutoAdvance();
1027
+ },
1028
+ [resetAutoAdvance]
1029
+ );
1030
+ react.useEffect(() => {
1031
+ if (!shouldShow) return;
1032
+ const handleKeyDown = (e) => {
1033
+ if (e.key === "ArrowLeft") {
1034
+ goToPrevious();
1035
+ } else if (e.key === "ArrowRight") {
1036
+ goToNext();
1037
+ } else if (e.key === "Escape") {
1038
+ handleClose();
1039
+ }
1040
+ };
1041
+ window.addEventListener("keydown", handleKeyDown);
1042
+ return () => window.removeEventListener("keydown", handleKeyDown);
1043
+ }, [shouldShow, goToPrevious, goToNext]);
1044
+ const handleCTAClick = react.useCallback(() => {
1045
+ const campaign = campaigns[currentIndex];
1046
+ if (!campaign) return;
1047
+ recordClick(campaign);
1048
+ }, [campaigns, currentIndex, recordClick]);
1049
+ const handleClose = react.useCallback(() => {
1050
+ campaigns.forEach((campaign) => {
1051
+ recordClose(campaign);
1052
+ });
1053
+ markAsShown();
1054
+ onClose?.();
1055
+ }, [campaigns, recordClose, markAsShown, onClose]);
1056
+ if (!shouldShow || loading || campaigns.length === 0) {
1057
+ return null;
1058
+ }
1059
+ const currentCampaign = campaigns[currentIndex];
1060
+ if (!currentCampaign) return null;
1061
+ const variantName = currentCampaign.variant || "large_slider_1";
1062
+ const VariantComponent = getLargePanelVariant(variantName);
1063
+ return /* @__PURE__ */ jsxRuntime.jsx(themes.Dialog.Root, { open: true, onOpenChange: (open) => !open && handleClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(
1064
+ themes.Dialog.Content,
1065
+ {
1066
+ style: {
1067
+ maxWidth: 550,
1068
+ padding: 0,
1069
+ overflow: "hidden"
1070
+ },
1071
+ children: [
1072
+ /* @__PURE__ */ jsxRuntime.jsxs(
1073
+ themes.Flex,
1074
+ {
1075
+ align: "center",
1076
+ justify: "between",
1077
+ p: "3",
1078
+ style: {
1079
+ borderBottom: "1px solid var(--gray-a5)"
1080
+ },
1081
+ children: [
1082
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Text, { size: "2", color: "gray", children: [
1083
+ "What's New in v",
1084
+ currentVersion
1085
+ ] }),
1086
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Dialog.Close, { children: /* @__PURE__ */ jsxRuntime.jsx(themes.IconButton, { variant: "ghost", size: "1", color: "gray", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { size: 16 }) }) })
1087
+ ]
1088
+ }
1089
+ ),
1090
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Box, { style: { position: "relative", minHeight: 350 }, children: [
1091
+ /* @__PURE__ */ jsxRuntime.jsx(
1092
+ VariantComponent,
1093
+ {
1094
+ campaign: currentCampaign,
1095
+ onCTAClick: handleCTAClick,
1096
+ showIndicator: campaigns.length > 1,
1097
+ currentIndex,
1098
+ totalCount: campaigns.length
1099
+ }
1100
+ ),
1101
+ campaigns.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1102
+ /* @__PURE__ */ jsxRuntime.jsx(
1103
+ themes.IconButton,
1104
+ {
1105
+ variant: "soft",
1106
+ size: "2",
1107
+ style: {
1108
+ position: "absolute",
1109
+ left: 8,
1110
+ top: "50%",
1111
+ transform: "translateY(-50%)",
1112
+ opacity: 0.8
1113
+ },
1114
+ onClick: goToPrevious,
1115
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLeft, { size: 20 })
1116
+ }
1117
+ ),
1118
+ /* @__PURE__ */ jsxRuntime.jsx(
1119
+ themes.IconButton,
1120
+ {
1121
+ variant: "soft",
1122
+ size: "2",
1123
+ style: {
1124
+ position: "absolute",
1125
+ right: 8,
1126
+ top: "50%",
1127
+ transform: "translateY(-50%)",
1128
+ opacity: 0.8
1129
+ },
1130
+ onClick: goToNext,
1131
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { size: 20 })
1132
+ }
1133
+ )
1134
+ ] })
1135
+ ] }),
1136
+ campaigns.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(
1137
+ themes.Flex,
1138
+ {
1139
+ align: "center",
1140
+ justify: "center",
1141
+ gap: "2",
1142
+ p: "3",
1143
+ style: {
1144
+ borderTop: "1px solid var(--gray-a5)"
1145
+ },
1146
+ children: campaigns.map((_, index) => /* @__PURE__ */ jsxRuntime.jsx(
1147
+ themes.Box,
1148
+ {
1149
+ onClick: () => goToSlide(index),
1150
+ style: {
1151
+ width: 8,
1152
+ height: 8,
1153
+ borderRadius: "50%",
1154
+ background: index === currentIndex ? "var(--accent-9)" : "var(--gray-a6)",
1155
+ cursor: "pointer",
1156
+ transition: "all 0.2s ease"
1157
+ }
1158
+ },
1159
+ index
1160
+ ))
1161
+ }
1162
+ ),
1163
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Flex, { justify: "center", pb: "3", children: /* @__PURE__ */ jsxRuntime.jsx(themes.Button, { variant: "ghost", size: "1", color: "gray", onClick: handleClose, children: "Skip All" }) })
1164
+ ]
1165
+ }
1166
+ ) });
1167
+ }
1168
+ function AdBanner({
1169
+ placement = "home_banner",
1170
+ rotationInterval = 1e4,
1171
+ maxCampaigns = 5,
1172
+ className,
1173
+ style
1174
+ }) {
1175
+ const [currentIndex, setCurrentIndex] = react.useState(0);
1176
+ const [isAnimating, setIsAnimating] = react.useState(false);
1177
+ const [progress, setProgress] = react.useState(0);
1178
+ const trackedImpressions = react.useRef(/* @__PURE__ */ new Set());
1179
+ const {
1180
+ campaigns,
1181
+ loading,
1182
+ recordImpression,
1183
+ recordClick
1184
+ } = useCampaigns.useCampaigns({ placement, maxCampaigns });
1185
+ react.useEffect(() => {
1186
+ if (campaigns.length === 0) return;
1187
+ const campaign2 = campaigns[currentIndex];
1188
+ if (!campaign2 || trackedImpressions.current.has(campaign2.id)) return;
1189
+ trackedImpressions.current.add(campaign2.id);
1190
+ recordImpression(campaign2);
1191
+ }, [currentIndex, campaigns, recordImpression]);
1192
+ react.useEffect(() => {
1193
+ if (campaigns.length <= 1) return;
1194
+ setProgress(0);
1195
+ const progressInterval = 50;
1196
+ const steps = rotationInterval / progressInterval;
1197
+ let currentStep = 0;
1198
+ const progressTimer = setInterval(() => {
1199
+ currentStep++;
1200
+ setProgress(currentStep / steps * 100);
1201
+ if (currentStep >= steps) {
1202
+ setIsAnimating(true);
1203
+ setTimeout(() => {
1204
+ setCurrentIndex((prev) => (prev + 1) % campaigns.length);
1205
+ setProgress(0);
1206
+ currentStep = 0;
1207
+ setTimeout(() => setIsAnimating(false), 50);
1208
+ }, 200);
1209
+ }
1210
+ }, progressInterval);
1211
+ return () => clearInterval(progressTimer);
1212
+ }, [campaigns.length, rotationInterval, currentIndex]);
1213
+ const handleClick = react.useCallback(
1214
+ (campaign2) => {
1215
+ recordClick(campaign2);
1216
+ const targetUrl = campaign2.customCtaUrl || campaign2.product.url;
1217
+ window.open(targetUrl, "_blank");
1218
+ },
1219
+ [recordClick]
1220
+ );
1221
+ const goToSlide = react.useCallback((index) => {
1222
+ if (index === currentIndex) return;
1223
+ setIsAnimating(true);
1224
+ setTimeout(() => {
1225
+ setCurrentIndex(index);
1226
+ setProgress(0);
1227
+ setTimeout(() => setIsAnimating(false), 50);
1228
+ }, 200);
1229
+ }, [currentIndex]);
1230
+ if (loading || campaigns.length === 0) return null;
1231
+ const campaign = campaigns[currentIndex];
1232
+ if (!campaign) return null;
1233
+ const { product } = campaign;
1234
+ const displayTitle = campaign.customTitle || product.name;
1235
+ const displayTagline = campaign.customTagline || product.tagline;
1236
+ const displayCta = campaign.customCta || "Learn More";
1237
+ const displayColor = campaign.customProductColor || product.color || "#3B82F6";
1238
+ const displayIcon = campaign.customIcon || product.icon64 || "";
1239
+ const displayFeatures = campaign.customFeatures || product.features || [];
1240
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1241
+ themes.Box,
1242
+ {
1243
+ className,
1244
+ style: {
1245
+ background: "var(--color-background)",
1246
+ borderBottom: "1px solid var(--gray-a4)",
1247
+ position: "relative",
1248
+ ...style
1249
+ },
1250
+ children: [
1251
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Box, { style: { height: 3, background: displayColor } }),
1252
+ /* @__PURE__ */ jsxRuntime.jsxs(
1253
+ themes.Box,
1254
+ {
1255
+ style: {
1256
+ background: `linear-gradient(90deg, ${displayColor}08 0%, ${displayColor}12 50%, ${displayColor}08 100%)`
1257
+ },
1258
+ children: [
1259
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", justify: "center", gap: "2", py: "2", children: [
1260
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { size: 12, color: displayColor }),
1261
+ /* @__PURE__ */ jsxRuntime.jsx(
1262
+ themes.Text,
1263
+ {
1264
+ size: "1",
1265
+ weight: "medium",
1266
+ style: {
1267
+ color: displayColor,
1268
+ fontSize: "11px",
1269
+ letterSpacing: "1.5px",
1270
+ textTransform: "uppercase"
1271
+ },
1272
+ children: "Discover Our Products"
1273
+ }
1274
+ ),
1275
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Sparkles, { size: 12, color: displayColor })
1276
+ ] }),
1277
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Box, { px: "4", py: "3", children: /* @__PURE__ */ jsxRuntime.jsxs(
1278
+ themes.Flex,
1279
+ {
1280
+ direction: { initial: "column", sm: "row" },
1281
+ align: "center",
1282
+ justify: "between",
1283
+ gap: { initial: "3", sm: "4" },
1284
+ style: {
1285
+ opacity: isAnimating ? 0 : 1,
1286
+ transform: isAnimating ? "translateX(-10px)" : "translateX(0)",
1287
+ transition: "all 0.2s ease-out"
1288
+ },
1289
+ children: [
1290
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "3", style: { flex: 1, minWidth: 0 }, children: [
1291
+ /* @__PURE__ */ jsxRuntime.jsx(
1292
+ themes.Box,
1293
+ {
1294
+ style: {
1295
+ width: 56,
1296
+ height: 56,
1297
+ borderRadius: 12,
1298
+ background: `${displayColor}15`,
1299
+ border: `1.5px solid ${displayColor}30`,
1300
+ display: "flex",
1301
+ alignItems: "center",
1302
+ justifyContent: "center",
1303
+ flexShrink: 0
1304
+ },
1305
+ dangerouslySetInnerHTML: { __html: displayIcon }
1306
+ }
1307
+ ),
1308
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { direction: "column", gap: "0", style: { minWidth: 0 }, children: [
1309
+ /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "2", children: [
1310
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "3", weight: "bold", children: displayTitle }),
1311
+ /* @__PURE__ */ jsxRuntime.jsx(
1312
+ themes.Badge,
1313
+ {
1314
+ size: "1",
1315
+ style: {
1316
+ background: `${displayColor}18`,
1317
+ color: displayColor,
1318
+ fontSize: "11px",
1319
+ fontWeight: 600,
1320
+ padding: "3px 8px"
1321
+ },
1322
+ children: product.type === "extension" ? "Extension" : product.type === "android" ? "App" : "Web"
1323
+ }
1324
+ )
1325
+ ] }),
1326
+ /* @__PURE__ */ jsxRuntime.jsx(
1327
+ themes.Text,
1328
+ {
1329
+ size: "2",
1330
+ color: "gray",
1331
+ style: {
1332
+ marginTop: 4,
1333
+ display: "-webkit-box",
1334
+ WebkitLineClamp: 1,
1335
+ WebkitBoxOrient: "vertical",
1336
+ overflow: "hidden"
1337
+ },
1338
+ children: displayTagline
1339
+ }
1340
+ ),
1341
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Flex, { gap: "4", mt: "2", display: { initial: "none", md: "flex" }, children: displayFeatures.slice(0, 3).map((feature, i) => /* @__PURE__ */ jsxRuntime.jsxs(themes.Flex, { align: "center", gap: "1", children: [
1342
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { size: 12, color: displayColor, strokeWidth: 3 }),
1343
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Text, { size: "2", style: { color: "var(--gray-10)" }, children: feature })
1344
+ ] }, i)) })
1345
+ ] })
1346
+ ] }),
1347
+ /* @__PURE__ */ jsxRuntime.jsx(themes.Flex, { align: "center", style: { flexShrink: 0 }, children: /* @__PURE__ */ jsxRuntime.jsxs(
1348
+ themes.Button,
1349
+ {
1350
+ size: "2",
1351
+ onClick: () => handleClick(campaign),
1352
+ style: {
1353
+ background: displayColor,
1354
+ color: "white",
1355
+ fontWeight: 600,
1356
+ fontSize: "14px",
1357
+ padding: "0 20px",
1358
+ height: 38,
1359
+ boxShadow: `0 2px 8px ${displayColor}40`
1360
+ },
1361
+ children: [
1362
+ displayCta,
1363
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { size: 14, style: { marginLeft: 6 } })
1364
+ ]
1365
+ }
1366
+ ) })
1367
+ ]
1368
+ }
1369
+ ) }),
1370
+ campaigns.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(themes.Flex, { justify: "center", align: "center", gap: "2", py: "3", children: campaigns.map((c, i) => /* @__PURE__ */ jsxRuntime.jsx(
1371
+ themes.Box,
1372
+ {
1373
+ onClick: () => goToSlide(i),
1374
+ style: {
1375
+ width: 40,
1376
+ height: 4,
1377
+ borderRadius: 2,
1378
+ background: "var(--gray-a4)",
1379
+ cursor: "pointer",
1380
+ overflow: "hidden",
1381
+ position: "relative"
1382
+ },
1383
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1384
+ themes.Box,
1385
+ {
1386
+ style: {
1387
+ position: "absolute",
1388
+ top: 0,
1389
+ left: 0,
1390
+ height: "100%",
1391
+ width: i === currentIndex ? `${progress}%` : i < currentIndex ? "100%" : "0%",
1392
+ background: c.product?.color || displayColor,
1393
+ borderRadius: 2,
1394
+ transition: i === currentIndex ? "none" : "width 0.3s ease"
1395
+ }
1396
+ }
1397
+ )
1398
+ },
1399
+ i
1400
+ )) })
1401
+ ]
1402
+ }
1403
+ )
1404
+ ]
1405
+ }
1406
+ );
1407
+ }
1408
+ exports.AdBanner = AdBanner;
1409
+ exports.AdModal = AdModal;
1410
+ exports.AdPanel = AdPanel;
1411
+ exports.AdSlider = AdSlider;
1412
+ exports.AdUpdateModal = AdUpdateModal;
1413
+ exports.CardVariant = CardVariant;
1414
+ exports.ComparisonVariant = ComparisonVariant;
1415
+ exports.FeatureGridVariant = FeatureGridVariant;
1416
+ exports.FeaturesVariant = FeaturesVariant;
1417
+ exports.GradientVariant = GradientVariant;
1418
+ exports.HeroVariant = HeroVariant;
1419
+ exports.LARGE_PANEL_VARIANTS = LARGE_PANEL_VARIANTS;
1420
+ exports.MinimalVariant = MinimalVariant;
1421
+ exports.SMALL_PANEL_VARIANTS = SMALL_PANEL_VARIANTS;
1422
+ exports.TaglineVariant = TaglineVariant;
1423
+ exports.TestimonialVariant = TestimonialVariant;
1424
+ exports.VideoVariant = VideoVariant;
1425
+ exports.getLargePanelVariant = getLargePanelVariant;
1426
+ exports.getSmallPanelVariant = getSmallPanelVariant;
1427
+ //# sourceMappingURL=AdBanner-B9918Vst.cjs.map