@appfunnel-dev/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,642 @@
1
+ import { createContext, useCallback, useSyncExternalStore, useMemo, useState, useRef, useEffect, useContext } from 'react';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { loadStripe } from '@stripe/stripe-js';
4
+ import { Elements, useStripe, useElements, PaymentElement } from '@stripe/react-stripe-js';
5
+
6
+ // src/config.ts
7
+ function defineConfig(config) {
8
+ return config;
9
+ }
10
+ function definePage(definition) {
11
+ return definition;
12
+ }
13
+ function registerIntegration(id, loader) {
14
+ }
15
+ var FunnelContext = createContext(null);
16
+ function useFunnelContext() {
17
+ const ctx = useContext(FunnelContext);
18
+ if (!ctx) {
19
+ throw new Error("useFunnelContext must be used within a <FunnelProvider>");
20
+ }
21
+ return ctx;
22
+ }
23
+
24
+ // src/hooks/useVariable.ts
25
+ function useVariable(id) {
26
+ const { variableStore } = useFunnelContext();
27
+ const subscribe = useCallback(
28
+ (callback) => variableStore.subscribe(callback),
29
+ [variableStore]
30
+ );
31
+ const getSnapshot = useCallback(
32
+ () => variableStore.get(id),
33
+ [variableStore, id]
34
+ );
35
+ const value = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
36
+ const setValue = useCallback(
37
+ (v) => variableStore.set(id, v),
38
+ [variableStore, id]
39
+ );
40
+ return [value, setValue];
41
+ }
42
+ function useVariables() {
43
+ const { variableStore } = useFunnelContext();
44
+ const subscribe = useCallback(
45
+ (callback) => variableStore.subscribe(callback),
46
+ [variableStore]
47
+ );
48
+ const getSnapshot = useCallback(
49
+ () => variableStore.getState(),
50
+ [variableStore]
51
+ );
52
+ return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
53
+ }
54
+ function useUser() {
55
+ const { variableStore, tracker } = useFunnelContext();
56
+ const subscribe = useCallback(
57
+ (cb) => variableStore.subscribe(cb),
58
+ [variableStore]
59
+ );
60
+ const getSnapshot = useCallback(
61
+ () => variableStore.getState(),
62
+ [variableStore]
63
+ );
64
+ const variables = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
65
+ return useMemo(() => ({
66
+ email: variables["user.email"] || "",
67
+ name: variables["user.name"] || "",
68
+ stripeCustomerId: variables["user.stripeCustomerId"] || "",
69
+ paddleCustomerId: variables["user.paddleCustomerId"] || "",
70
+ setEmail(email) {
71
+ variableStore.set("user.email", email);
72
+ tracker.identify(email);
73
+ },
74
+ setName(name) {
75
+ variableStore.set("user.name", name);
76
+ }
77
+ }), [variables, variableStore, tracker]);
78
+ }
79
+ function useUserVariable(field) {
80
+ const { variableStore } = useFunnelContext();
81
+ const key = `user.${field}`;
82
+ const subscribe = useCallback(
83
+ (cb) => variableStore.subscribe(cb),
84
+ [variableStore]
85
+ );
86
+ const getSnapshot = useCallback(
87
+ () => variableStore.get(key) || "",
88
+ [variableStore, key]
89
+ );
90
+ const value = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
91
+ const setValue = useCallback(
92
+ (v) => variableStore.set(key, v),
93
+ [variableStore, key]
94
+ );
95
+ return [value, setValue];
96
+ }
97
+ function useQueryParams() {
98
+ const { variableStore } = useFunnelContext();
99
+ const subscribe = useCallback(
100
+ (cb) => variableStore.subscribe(cb),
101
+ [variableStore]
102
+ );
103
+ const getSnapshot = useCallback(
104
+ () => variableStore.getState(),
105
+ [variableStore]
106
+ );
107
+ const variables = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
108
+ return useMemo(() => {
109
+ const params = {};
110
+ for (const [key, value] of Object.entries(variables)) {
111
+ if (key.startsWith("query.") && typeof value === "string") {
112
+ params[key.slice(6)] = value;
113
+ }
114
+ }
115
+ return params;
116
+ }, [variables]);
117
+ }
118
+ function useLocale() {
119
+ return useMemo(() => {
120
+ if (typeof navigator === "undefined") {
121
+ return {
122
+ locale: "en-US",
123
+ language: "en",
124
+ region: "US",
125
+ languages: ["en-US"],
126
+ timeZone: "UTC",
127
+ is24Hour: false
128
+ };
129
+ }
130
+ const locale = navigator.language || "en-US";
131
+ const [language, region] = locale.split("-");
132
+ const languages = [...navigator.languages || [locale]];
133
+ const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
134
+ const is24Hour = detect24Hour(locale);
135
+ return {
136
+ locale,
137
+ language: language || "en",
138
+ region: region?.toUpperCase() || "US",
139
+ languages,
140
+ timeZone,
141
+ is24Hour
142
+ };
143
+ }, []);
144
+ }
145
+ function detect24Hour(locale) {
146
+ try {
147
+ const formatted = new Intl.DateTimeFormat(locale, { hour: "numeric" }).format(/* @__PURE__ */ new Date());
148
+ return !formatted.match(/am|pm/i);
149
+ } catch {
150
+ return false;
151
+ }
152
+ }
153
+ function useTranslation() {
154
+ const { i18n } = useFunnelContext();
155
+ const subscribe = useCallback(
156
+ (cb) => i18n.subscribe(cb),
157
+ [i18n]
158
+ );
159
+ const getSnapshot = useCallback(
160
+ () => i18n.getLocale(),
161
+ [i18n]
162
+ );
163
+ const locale = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
164
+ const t = useCallback(
165
+ (key, params) => i18n.t(key, params),
166
+ [i18n, locale]
167
+ // eslint-disable-line react-hooks/exhaustive-deps
168
+ );
169
+ const setLocale = useCallback(
170
+ (l) => i18n.setLocale(l),
171
+ [i18n]
172
+ );
173
+ const availableLocales = i18n.getAvailableLocales();
174
+ return { t, locale, setLocale, availableLocales };
175
+ }
176
+ function useNavigation() {
177
+ const { router, variableStore, tracker } = useFunnelContext();
178
+ const subscribe = useCallback(
179
+ (cb) => variableStore.subscribe(cb),
180
+ [variableStore]
181
+ );
182
+ const getSnapshot = useCallback(
183
+ () => variableStore.getState(),
184
+ [variableStore]
185
+ );
186
+ const variables = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
187
+ const goToNextPage = useCallback(() => {
188
+ const previousPage = router.getCurrentPage();
189
+ if (previousPage) {
190
+ tracker.stopPageTracking();
191
+ }
192
+ const nextKey = router.goToNextPage(variables);
193
+ if (nextKey) {
194
+ const nextPage = router.getCurrentPage();
195
+ if (nextPage) {
196
+ tracker.track("page.view", {
197
+ pageId: nextPage.key,
198
+ pageKey: nextPage.key,
199
+ pageName: nextPage.name
200
+ });
201
+ tracker.startPageTracking(nextPage.key);
202
+ }
203
+ variableStore.setMany({
204
+ "page.currentId": nextKey,
205
+ "page.currentIndex": router.getPageHistory().length,
206
+ "page.current": router.getPageHistory().length + 1,
207
+ "page.startedAt": Date.now(),
208
+ "page.timeOnCurrent": 0
209
+ });
210
+ }
211
+ }, [router, variables, tracker, variableStore]);
212
+ const goBack = useCallback(() => {
213
+ tracker.stopPageTracking();
214
+ const prevKey = router.goBack();
215
+ if (prevKey) {
216
+ const page = router.getCurrentPage();
217
+ if (page) {
218
+ tracker.track("page.view", {
219
+ pageId: page.key,
220
+ pageKey: page.key,
221
+ pageName: page.name
222
+ });
223
+ tracker.startPageTracking(page.key);
224
+ }
225
+ variableStore.setMany({
226
+ "page.currentId": prevKey,
227
+ "page.currentIndex": router.getPageHistory().length,
228
+ "page.current": router.getPageHistory().length + 1,
229
+ "page.startedAt": Date.now(),
230
+ "page.timeOnCurrent": 0
231
+ });
232
+ }
233
+ }, [router, tracker, variableStore]);
234
+ const goToPage = useCallback((pageKey) => {
235
+ tracker.stopPageTracking();
236
+ const key = router.goToPage(pageKey);
237
+ if (key) {
238
+ const page = router.getCurrentPage();
239
+ if (page) {
240
+ tracker.track("page.view", {
241
+ pageId: page.key,
242
+ pageKey: page.key,
243
+ pageName: page.name
244
+ });
245
+ tracker.startPageTracking(page.key);
246
+ }
247
+ variableStore.setMany({
248
+ "page.currentId": key,
249
+ "page.currentIndex": router.getPageHistory().length,
250
+ "page.current": router.getPageHistory().length + 1,
251
+ "page.startedAt": Date.now(),
252
+ "page.timeOnCurrent": 0
253
+ });
254
+ }
255
+ }, [router, tracker, variableStore]);
256
+ return {
257
+ goToNextPage,
258
+ goBack,
259
+ goToPage,
260
+ currentPage: router.getCurrentPage(),
261
+ pageHistory: router.getPageHistory(),
262
+ progress: router.getProgress()
263
+ };
264
+ }
265
+ function useProducts() {
266
+ const { products, variableStore, selectProduct: ctxSelect } = useFunnelContext();
267
+ const subscribe = useCallback(
268
+ (cb) => variableStore.subscribe(cb),
269
+ [variableStore]
270
+ );
271
+ const getSnapshot = useCallback(
272
+ () => variableStore.get("products.selectedProductId"),
273
+ [variableStore]
274
+ );
275
+ const selectedId = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
276
+ const selected = products.find((p) => p.id === selectedId) || null;
277
+ const select = useCallback((productId) => {
278
+ ctxSelect(productId);
279
+ }, [ctxSelect]);
280
+ return { products, selected, select };
281
+ }
282
+ function useTracking() {
283
+ const { tracker } = useFunnelContext();
284
+ const track = useCallback(
285
+ (eventName, data) => {
286
+ tracker.track(eventName, data);
287
+ },
288
+ [tracker]
289
+ );
290
+ const identify = useCallback(
291
+ (email) => {
292
+ tracker.identify(email);
293
+ },
294
+ [tracker]
295
+ );
296
+ return { track, identify };
297
+ }
298
+ function usePayment() {
299
+ const { variableStore, tracker } = useFunnelContext();
300
+ const subscribe = useCallback(
301
+ (cb) => variableStore.subscribe(cb),
302
+ [variableStore]
303
+ );
304
+ const getSnapshot = useCallback(
305
+ () => variableStore.getState(),
306
+ [variableStore]
307
+ );
308
+ const variables = useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
309
+ return useMemo(() => {
310
+ const last4 = variables["card.last4"] || "";
311
+ const brand = variables["card.brand"] || "";
312
+ const expMonth = variables["card.expMonth"] || 0;
313
+ const expYear = variables["card.expYear"] || 0;
314
+ return {
315
+ customerId: tracker.getCustomerId(),
316
+ isAuthorized: !!last4,
317
+ loading: !!variables["payment.loading"],
318
+ error: variables["payment.error"] || null,
319
+ cardDetails: last4 ? { last4, brand, expMonth, expYear } : null
320
+ };
321
+ }, [variables, tracker]);
322
+ }
323
+
324
+ // src/hooks/useFunnel.ts
325
+ function useFunnel() {
326
+ const { funnelId, campaignId, tracker } = useFunnelContext();
327
+ return {
328
+ funnelId,
329
+ campaignId,
330
+ sessionId: tracker.getSessionId(),
331
+ variables: useVariables(),
332
+ user: useUser(),
333
+ queryParams: useQueryParams(),
334
+ navigation: useNavigation(),
335
+ products: useProducts(),
336
+ tracking: useTracking(),
337
+ payment: usePayment()
338
+ };
339
+ }
340
+ function InnerPaymentForm({
341
+ paymentMode,
342
+ validateOnly,
343
+ onSuccess,
344
+ onError
345
+ }) {
346
+ const stripe = useStripe();
347
+ const elements = useElements();
348
+ const [error, setError] = useState(null);
349
+ const { variableStore, campaignId, tracker, apiBaseUrl, products } = useFunnelContext();
350
+ const handleSubmit = useCallback(async () => {
351
+ if (!stripe || !elements) {
352
+ const msg = "Stripe not loaded";
353
+ setError(msg);
354
+ onError?.(msg);
355
+ return;
356
+ }
357
+ setError(null);
358
+ variableStore.set("payment.loading", true);
359
+ try {
360
+ const confirmFn = paymentMode === "setup" ? stripe.confirmSetup : stripe.confirmPayment;
361
+ const confirmResult = await confirmFn({
362
+ elements,
363
+ redirect: "if_required",
364
+ confirmParams: { return_url: window.location.href }
365
+ });
366
+ if (confirmResult.error) {
367
+ const msg = confirmResult.error.message || "Payment failed";
368
+ setError(msg);
369
+ variableStore.set("payment.error", msg);
370
+ onError?.(msg);
371
+ return;
372
+ }
373
+ tracker.track("checkout.payment_added");
374
+ if (validateOnly) {
375
+ const piId = "paymentIntent" in confirmResult ? confirmResult.paymentIntent : void 0;
376
+ if (!piId?.id) {
377
+ const msg = "PaymentIntent not found after confirmation";
378
+ setError(msg);
379
+ variableStore.set("payment.error", msg);
380
+ onError?.(msg);
381
+ return;
382
+ }
383
+ const response2 = await fetch(
384
+ `${apiBaseUrl}/campaign/${campaignId}/stripe/validate-card`,
385
+ {
386
+ method: "POST",
387
+ headers: { "Content-Type": "application/json" },
388
+ body: JSON.stringify({
389
+ campaignId,
390
+ sessionId: tracker.getSessionId(),
391
+ paymentIntentId: piId.id
392
+ })
393
+ }
394
+ );
395
+ const result2 = await response2.json();
396
+ if (!result2.success) {
397
+ const msg = result2.error || "Card validation failed";
398
+ setError(msg);
399
+ variableStore.set("payment.error", msg);
400
+ onError?.(msg);
401
+ return;
402
+ }
403
+ variableStore.setMany({
404
+ "card.last4": result2.card.last4,
405
+ "card.brand": result2.card.brand,
406
+ "card.expMonth": result2.card.expMonth,
407
+ "card.expYear": result2.card.expYear,
408
+ "card.funding": result2.card.funding,
409
+ "payment.error": ""
410
+ });
411
+ onSuccess?.();
412
+ return;
413
+ }
414
+ const paymentIntentId = "paymentIntent" in confirmResult ? confirmResult.paymentIntent?.id : void 0;
415
+ const selectedId = variableStore.get("products.selectedProductId");
416
+ const product = products.find((p) => p.id === selectedId);
417
+ if (!product?.stripePriceId) {
418
+ const msg = "No product selected or missing Stripe price";
419
+ setError(msg);
420
+ variableStore.set("payment.error", msg);
421
+ onError?.(msg);
422
+ return;
423
+ }
424
+ const variables = variableStore.getState();
425
+ await tracker.updateUserData(variables);
426
+ const response = await fetch(
427
+ `${apiBaseUrl}/campaign/${campaignId}/stripe/purchase`,
428
+ {
429
+ method: "POST",
430
+ headers: { "Content-Type": "application/json" },
431
+ body: JSON.stringify({
432
+ campaignId,
433
+ sessionId: tracker.getSessionId(),
434
+ stripePriceId: product.stripePriceId,
435
+ trialPeriodDays: product.hasTrial ? product.trialDays : void 0,
436
+ onSessionPiId: paymentMode === "payment" ? paymentIntentId : void 0
437
+ })
438
+ }
439
+ );
440
+ const result = await response.json();
441
+ if (result.success) {
442
+ variableStore.set("payment.error", "");
443
+ if (result.eventId || result.eventIds?.firstPeriod) {
444
+ tracker.track("purchase.complete", {
445
+ amount: product.rawPrice ? product.rawPrice / 100 : 0,
446
+ currency: product.currencyCode || "USD"
447
+ });
448
+ }
449
+ onSuccess?.();
450
+ } else {
451
+ const msg = result.error || "Failed to process payment";
452
+ setError(msg);
453
+ variableStore.set("payment.error", msg);
454
+ onError?.(msg);
455
+ }
456
+ } catch (err) {
457
+ const msg = err instanceof Error ? err.message : "An error occurred";
458
+ setError(msg);
459
+ variableStore.set("payment.error", msg);
460
+ onError?.(msg);
461
+ } finally {
462
+ variableStore.set("payment.loading", false);
463
+ }
464
+ }, [stripe, elements, paymentMode, validateOnly, variableStore, campaignId, tracker, apiBaseUrl, products, onSuccess, onError]);
465
+ useEffect(() => {
466
+ if (typeof window !== "undefined") {
467
+ window.__paymentElementSubmit = handleSubmit;
468
+ }
469
+ return () => {
470
+ if (typeof window !== "undefined") {
471
+ delete window.__paymentElementSubmit;
472
+ }
473
+ };
474
+ }, [handleSubmit]);
475
+ return /* @__PURE__ */ jsxs("div", { children: [
476
+ /* @__PURE__ */ jsx(PaymentElement, { options: { layout: "tabs" } }),
477
+ error && /* @__PURE__ */ jsx("div", { style: { color: "#ef4444", fontSize: "14px", marginTop: "12px" }, children: error })
478
+ ] });
479
+ }
480
+ function PaymentForm({
481
+ productId,
482
+ mode = "checkout",
483
+ onSuccess,
484
+ onError,
485
+ className,
486
+ appearance
487
+ }) {
488
+ const { campaignId, tracker, variableStore, apiBaseUrl, products } = useFunnelContext();
489
+ const [email] = useVariable("user.email");
490
+ const validateOnly = mode === "validate-only";
491
+ const product = useMemo(() => {
492
+ if (productId) return products.find((p) => p.id === productId) || null;
493
+ const selectedId = variableStore.get("products.selectedProductId");
494
+ return products.find((p) => p.id === selectedId) || null;
495
+ }, [productId, products, variableStore]);
496
+ const paymentMode = useMemo(() => {
497
+ if (validateOnly) return "payment";
498
+ if (product?.hasTrial && !product.paidTrial) return "setup";
499
+ return "payment";
500
+ }, [product, validateOnly]);
501
+ const [stripePromise, setStripePromise] = useState(null);
502
+ const [clientSecret, setClientSecret] = useState(null);
503
+ const [error, setError] = useState(null);
504
+ const [isLoading, setIsLoading] = useState(false);
505
+ const hasInitialized = useRef(false);
506
+ useEffect(() => {
507
+ if (!email || !campaignId || hasInitialized.current) return;
508
+ if (!product?.storePriceId) return;
509
+ hasInitialized.current = true;
510
+ setIsLoading(true);
511
+ variableStore.set("payment.loading", true);
512
+ const createIntent = async () => {
513
+ try {
514
+ const endpoint = paymentMode === "setup" ? `/campaign/${campaignId}/stripe/setup-intent` : `/campaign/${campaignId}/stripe/payment-intent`;
515
+ const body = {
516
+ campaignId,
517
+ sessionId: tracker.getSessionId(),
518
+ customerEmail: email,
519
+ priceId: product.storePriceId
520
+ };
521
+ if (validateOnly) body.validateOnly = true;
522
+ const response = await fetch(`${apiBaseUrl}${endpoint}`, {
523
+ method: "POST",
524
+ headers: { "Content-Type": "application/json" },
525
+ body: JSON.stringify(body)
526
+ });
527
+ const result = await response.json();
528
+ if (!result.success) {
529
+ throw new Error(result.error || "Failed to create intent");
530
+ }
531
+ setStripePromise(loadStripe(result.publishableKey));
532
+ setClientSecret(result.clientSecret);
533
+ variableStore.set("user.stripeCustomerId", result.customerId);
534
+ tracker.track("checkout.start", {
535
+ productId: product.id,
536
+ priceId: product.stripePriceId || product.storePriceId,
537
+ productName: product.displayName
538
+ });
539
+ } catch (err) {
540
+ const msg = err instanceof Error ? err.message : "Failed to initialize payment";
541
+ setError(msg);
542
+ variableStore.set("payment.error", msg);
543
+ } finally {
544
+ setIsLoading(false);
545
+ variableStore.set("payment.loading", false);
546
+ }
547
+ };
548
+ createIntent();
549
+ }, [email, campaignId, product, paymentMode, validateOnly, tracker, variableStore, apiBaseUrl]);
550
+ if (isLoading) {
551
+ return /* @__PURE__ */ jsx("div", { className, style: { padding: "20px", textAlign: "center", color: "#6b7280" }, children: "Loading payment form..." });
552
+ }
553
+ if (!email) {
554
+ return /* @__PURE__ */ jsx("div", { className, style: { padding: "20px", textAlign: "center", color: "#ef4444", fontSize: "14px" }, children: "Email is required to initialize payment" });
555
+ }
556
+ if (error) {
557
+ return /* @__PURE__ */ jsx("div", { className, style: { padding: "20px", textAlign: "center", color: "#ef4444", fontSize: "14px" }, children: error });
558
+ }
559
+ if (!stripePromise || !clientSecret) {
560
+ return /* @__PURE__ */ jsx("div", { className, style: { padding: "20px", textAlign: "center", color: "#6b7280" }, children: "Initializing payment..." });
561
+ }
562
+ const defaultAppearance = {
563
+ theme: "stripe",
564
+ variables: { colorPrimary: "#3b82f6", borderRadius: "8px" }
565
+ };
566
+ return /* @__PURE__ */ jsx("div", { className, children: /* @__PURE__ */ jsx(Elements, { stripe: stripePromise, options: { clientSecret, appearance: appearance || defaultAppearance }, children: /* @__PURE__ */ jsx(
567
+ InnerPaymentForm,
568
+ {
569
+ paymentMode,
570
+ validateOnly,
571
+ onSuccess,
572
+ onError
573
+ }
574
+ ) }) });
575
+ }
576
+ function PaddleCheckout({
577
+ productId,
578
+ mode = "overlay",
579
+ onSuccess,
580
+ onError,
581
+ className
582
+ }) {
583
+ const { variableStore, tracker, products } = useFunnelContext();
584
+ const containerRef = useRef(null);
585
+ const initializedRef = useRef(false);
586
+ const product = productId ? products.find((p) => p.id === productId) : products.find((p) => p.id === variableStore.get("products.selectedProductId"));
587
+ const handleCheckoutComplete = useCallback(() => {
588
+ tracker.track("purchase.complete", {
589
+ amount: product?.rawPrice ? product.rawPrice / 100 : 0,
590
+ currency: product?.currencyCode || "USD"
591
+ });
592
+ onSuccess?.();
593
+ }, [tracker, product, onSuccess]);
594
+ useEffect(() => {
595
+ if (initializedRef.current || !product?.paddlePriceId) return;
596
+ initializedRef.current = true;
597
+ if (!window.Paddle) {
598
+ onError?.("Paddle.js not loaded. Include the Paddle script in your HTML.");
599
+ return;
600
+ }
601
+ const email = variableStore.get("user.email") || "";
602
+ if (mode === "overlay") {
603
+ window.Paddle.Checkout.open({
604
+ items: [{ priceId: product.paddlePriceId, quantity: 1 }],
605
+ customer: email ? { email } : void 0,
606
+ successCallback: handleCheckoutComplete,
607
+ closeCallback: () => {
608
+ }
609
+ });
610
+ } else {
611
+ if (containerRef.current) {
612
+ window.Paddle.Checkout.open({
613
+ items: [{ priceId: product.paddlePriceId, quantity: 1 }],
614
+ customer: email ? { email } : void 0,
615
+ settings: {
616
+ displayMode: "inline",
617
+ frameTarget: containerRef.current.id || "paddle-checkout",
618
+ frameInitialHeight: 450,
619
+ frameStyle: "width: 100%; min-width: 312px; background-color: transparent; border: none;"
620
+ },
621
+ successCallback: handleCheckoutComplete
622
+ });
623
+ }
624
+ }
625
+ tracker.track("checkout.start", {
626
+ productId: product.id,
627
+ priceId: product.paddlePriceId,
628
+ productName: product.displayName
629
+ });
630
+ }, [product, mode, variableStore, tracker, handleCheckoutComplete, onError]);
631
+ if (!product) {
632
+ return /* @__PURE__ */ jsx("div", { className, style: { padding: "20px", textAlign: "center", color: "#ef4444", fontSize: "14px" }, children: "No product selected" });
633
+ }
634
+ if (mode === "inline") {
635
+ return /* @__PURE__ */ jsx("div", { ref: containerRef, id: "paddle-checkout", className });
636
+ }
637
+ return null;
638
+ }
639
+
640
+ export { PaddleCheckout, PaymentForm, defineConfig, definePage, registerIntegration, useFunnel, useLocale, useNavigation, usePayment, useProducts, useQueryParams, useTracking, useTranslation, useUser, useUserVariable, useVariable, useVariables };
641
+ //# sourceMappingURL=index.js.map
642
+ //# sourceMappingURL=index.js.map