@tagadapay/plugin-sdk 3.1.11 → 3.1.22
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/README.md +1129 -1129
- package/build-cdn.js +231 -228
- package/dist/data/iso3166.d.ts +23 -33
- package/dist/data/iso3166.js +134 -198
- package/dist/data/languages.d.ts +5 -64
- package/dist/data/languages.js +23 -143
- package/dist/external-tracker.js +968 -102
- package/dist/external-tracker.min.js +2 -2
- package/dist/external-tracker.min.js.map +4 -4
- package/dist/react/hooks/useISOData.js +1 -1
- package/dist/react/hooks/usePaymentPolling.d.ts +3 -3
- package/dist/react/hooks/useShippingRates.d.ts +6 -0
- package/dist/react/hooks/useShippingRates.js +38 -0
- package/dist/react/providers/TagadaProvider.js +5 -5
- package/dist/react/services/apiService.d.ts +21 -0
- package/dist/react/services/apiService.js +10 -0
- package/dist/tagada-sdk.js +2079 -179
- package/dist/tagada-sdk.min.js +4 -2
- package/dist/tagada-sdk.min.js.map +4 -4
- package/dist/v2/core/client.d.ts +4 -2
- package/dist/v2/core/client.js +4 -3
- package/dist/v2/core/errors.d.ts +75 -0
- package/dist/v2/core/errors.js +104 -0
- package/dist/v2/core/funnelClient.d.ts +16 -15
- package/dist/v2/core/funnelClient.js +1 -1
- package/dist/v2/core/index.d.ts +1 -0
- package/dist/v2/core/index.js +2 -0
- package/dist/v2/core/pixelMapping.d.ts +49 -0
- package/dist/v2/core/pixelMapping.js +325 -0
- package/dist/v2/core/resources/apiClient.d.ts +2 -0
- package/dist/v2/core/resources/apiClient.js +52 -9
- package/dist/v2/core/resources/checkout.d.ts +89 -30
- package/dist/v2/core/resources/checkout.js +8 -0
- package/dist/v2/core/resources/customer.d.ts +20 -19
- package/dist/v2/core/resources/funnel.d.ts +17 -17
- package/dist/v2/core/resources/payments.d.ts +84 -13
- package/dist/v2/core/resources/payments.js +26 -9
- package/dist/v2/core/resources/shippingRates.d.ts +15 -0
- package/dist/v2/core/resources/shippingRates.js +11 -0
- package/dist/v2/core/types.d.ts +50 -12
- package/dist/v2/core/types.js +0 -3
- package/dist/v2/core/utils/checkout.d.ts +2 -2
- package/dist/v2/core/utils/checkout.js +7 -2
- package/dist/v2/core/utils/order.d.ts +11 -9
- package/dist/v2/core/utils/previewModeIndicator.js +101 -101
- package/dist/v2/index.d.ts +4 -2
- package/dist/v2/index.js +1 -1
- package/dist/v2/react/components/ApplePayButton.js +13 -4
- package/dist/v2/react/components/FunnelScriptInjector.js +51 -30
- package/dist/v2/react/components/WhopCheckout.d.ts +24 -0
- package/dist/v2/react/components/WhopCheckout.js +231 -0
- package/dist/v2/react/hooks/__examples__/FunnelContextExample.js +1 -1
- package/dist/v2/react/hooks/payment-actions/useAirwallexRadarAction.d.ts +14 -0
- package/dist/v2/react/hooks/payment-actions/useAirwallexRadarAction.js +181 -0
- package/dist/v2/react/hooks/payment-actions/useErrorAction.d.ts +9 -0
- package/dist/v2/react/hooks/payment-actions/useErrorAction.js +21 -0
- package/dist/v2/react/hooks/payment-actions/useFinixRadarAction.d.ts +14 -0
- package/dist/v2/react/hooks/payment-actions/useFinixRadarAction.js +187 -0
- package/dist/v2/react/hooks/payment-actions/useKessPayAction.d.ts +11 -0
- package/dist/v2/react/hooks/payment-actions/useKessPayAction.js +91 -0
- package/dist/v2/react/hooks/payment-actions/useMasterCardAction.d.ts +24 -0
- package/dist/v2/react/hooks/payment-actions/useMasterCardAction.js +221 -0
- package/dist/v2/react/hooks/payment-actions/usePaymentActionHandler.d.ts +15 -0
- package/dist/v2/react/hooks/payment-actions/usePaymentActionHandler.js +142 -0
- package/dist/v2/react/hooks/payment-actions/useProcessorAuthAction.d.ts +3 -0
- package/dist/v2/react/hooks/payment-actions/useProcessorAuthAction.js +13 -0
- package/dist/v2/react/hooks/payment-actions/useRedirectAction.d.ts +10 -0
- package/dist/v2/react/hooks/payment-actions/useRedirectAction.js +35 -0
- package/dist/v2/react/hooks/payment-actions/useStripeRadarAction.d.ts +14 -0
- package/dist/v2/react/hooks/payment-actions/useStripeRadarAction.js +192 -0
- package/dist/v2/react/hooks/payment-actions/useThreedsAuthAction.d.ts +14 -0
- package/dist/v2/react/hooks/payment-actions/useThreedsAuthAction.js +81 -0
- package/dist/v2/react/hooks/payment-actions/useTrustFlowAction.d.ts +11 -0
- package/dist/v2/react/hooks/payment-actions/useTrustFlowAction.js +84 -0
- package/dist/v2/react/hooks/payment-processing/usePaymentInstruments.d.ts +14 -0
- package/dist/v2/react/hooks/payment-processing/usePaymentInstruments.js +36 -0
- package/dist/v2/react/hooks/payment-processing/usePaymentProcessors.d.ts +31 -0
- package/dist/v2/react/hooks/payment-processing/usePaymentProcessors.js +212 -0
- package/dist/v2/react/hooks/payment-redirect/useAirwallex3dsReturn.d.ts +14 -0
- package/dist/v2/react/hooks/payment-redirect/useAirwallex3dsReturn.js +207 -0
- package/dist/v2/react/hooks/payment-redirect/useGenericPaymentReturn.d.ts +12 -0
- package/dist/v2/react/hooks/payment-redirect/useGenericPaymentReturn.js +101 -0
- package/dist/v2/react/hooks/useCheckoutQuery.d.ts +6 -0
- package/dist/v2/react/hooks/useCheckoutQuery.js +45 -0
- package/dist/v2/react/hooks/useFunnel.d.ts +1 -2
- package/dist/v2/react/hooks/useGeoLocation.d.ts +2 -1
- package/dist/v2/react/hooks/useGeoLocation.js +4 -2
- package/dist/v2/react/hooks/useGoogleAutocomplete.js +82 -33
- package/dist/v2/react/hooks/useISOData.js +1 -1
- package/dist/v2/react/hooks/usePaymentPolling.d.ts +3 -3
- package/dist/v2/react/hooks/usePaymentQuery.d.ts +18 -5
- package/dist/v2/react/hooks/usePaymentQuery.js +63 -1015
- package/dist/v2/react/hooks/usePaymentRetrieve.d.ts +3 -2
- package/dist/v2/react/hooks/usePaymentRetrieve.js +3 -1
- package/dist/v2/react/hooks/usePixelTracking.d.ts +5 -43
- package/dist/v2/react/hooks/usePixelTracking.js +213 -407
- package/dist/v2/react/hooks/useShippingRatesQuery.d.ts +6 -0
- package/dist/v2/react/hooks/useShippingRatesQuery.js +47 -4
- package/dist/v2/react/hooks/useStepConfig.d.ts +2 -8
- package/dist/v2/react/hooks/useStepConfig.js +1 -1
- package/dist/v2/react/hooks/useWhopPaymentPolling.d.ts +30 -0
- package/dist/v2/react/hooks/useWhopPaymentPolling.js +61 -0
- package/dist/v2/react/index.d.ts +7 -0
- package/dist/v2/react/index.js +4 -0
- package/dist/v2/react/providers/ExpressPaymentMethodsProvider.d.ts +2 -1
- package/dist/v2/react/providers/ExpressPaymentMethodsProvider.js +3 -1
- package/dist/v2/react/providers/TagadaProvider.js +76 -7
- package/dist/v2/standalone/external-tracker.d.ts +52 -46
- package/dist/v2/standalone/external-tracker.js +205 -98
- package/dist/v2/standalone/index.d.ts +22 -0
- package/dist/v2/standalone/index.js +125 -0
- package/package.json +112 -112
- package/dist/react/utils/__tests__/urlUtils.test.d.ts +0 -1
- package/dist/react/utils/__tests__/urlUtils.test.js +0 -189
- package/dist/v2/core/__tests__/pathRemapping.test.d.ts +0 -11
- package/dist/v2/core/__tests__/pathRemapping.test.js +0 -776
|
@@ -18,5 +18,11 @@ export interface UseShippingRatesQueryResult {
|
|
|
18
18
|
error: Error | null;
|
|
19
19
|
clearError: () => void;
|
|
20
20
|
refetch: () => Promise<void>;
|
|
21
|
+
/** Preview shipping rates for a country without updating session */
|
|
22
|
+
previewRates: (countryCode: string, stateCode?: string) => Promise<ShippingRate[]>;
|
|
23
|
+
/** Rates from the last previewRates call */
|
|
24
|
+
previewedRates: ShippingRate[] | undefined;
|
|
25
|
+
/** Loading state for previewRates */
|
|
26
|
+
isPreviewLoading: boolean;
|
|
21
27
|
}
|
|
22
28
|
export declare function useShippingRatesQuery(options?: UseShippingRatesQueryOptions): UseShippingRatesQueryResult;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Simplified shipping rates management with automatic cache invalidation
|
|
4
4
|
*/
|
|
5
5
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
6
|
-
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
6
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
7
7
|
import { ShippingRatesResource } from '../../core/resources/shippingRates';
|
|
8
8
|
import { getGlobalApiClient } from './useApiQuery';
|
|
9
9
|
export function useShippingRatesQuery(options = {}) {
|
|
@@ -23,10 +23,17 @@ export function useShippingRatesQuery(options = {}) {
|
|
|
23
23
|
const effectiveSessionId = sessionId || checkout?.checkoutSession?.id;
|
|
24
24
|
// Track if we've synced the initial selection from checkout
|
|
25
25
|
const hasSyncedInitialSelectionRef = useRef(false);
|
|
26
|
+
// Preview rates state
|
|
27
|
+
const [previewedRates, setPreviewedRates] = useState();
|
|
28
|
+
const [isPreviewLoading, setIsPreviewLoading] = useState(false);
|
|
26
29
|
// Main shipping rates query
|
|
27
30
|
const { data: shippingRatesData, isLoading: isFetching, error: fetchError, refetch: refetchRates, } = useQuery({
|
|
28
31
|
queryKey: ['shipping-rates', effectiveSessionId],
|
|
29
|
-
queryFn: () =>
|
|
32
|
+
queryFn: () => {
|
|
33
|
+
if (!enabled)
|
|
34
|
+
return Promise.resolve({ rates: [] });
|
|
35
|
+
return shippingRatesResource.getShippingRates(effectiveSessionId);
|
|
36
|
+
},
|
|
30
37
|
enabled: enabled && !!effectiveSessionId,
|
|
31
38
|
staleTime: 30000, // 30 seconds
|
|
32
39
|
refetchOnWindowFocus: false,
|
|
@@ -73,8 +80,10 @@ export function useShippingRatesQuery(options = {}) {
|
|
|
73
80
|
});
|
|
74
81
|
// Select rate function
|
|
75
82
|
const selectRate = useCallback(async (rateId) => {
|
|
83
|
+
if (!enabled)
|
|
84
|
+
return;
|
|
76
85
|
await setShippingRateMutation.mutateAsync({ rateId });
|
|
77
|
-
}, [setShippingRateMutation]);
|
|
86
|
+
}, [enabled, setShippingRateMutation]);
|
|
78
87
|
// Auto-select cheapest rate when:
|
|
79
88
|
// 1. Rates are loaded
|
|
80
89
|
// 2. No rate is currently selected in checkout
|
|
@@ -114,14 +123,45 @@ export function useShippingRatesQuery(options = {}) {
|
|
|
114
123
|
}, [shippingRates, checkoutSelectedRateId]);
|
|
115
124
|
// Refetch function
|
|
116
125
|
const refetch = useCallback(async () => {
|
|
126
|
+
if (!enabled)
|
|
127
|
+
return;
|
|
117
128
|
await refetchRates();
|
|
118
|
-
}, [refetchRates]);
|
|
129
|
+
}, [enabled, refetchRates]);
|
|
119
130
|
// Clear error function
|
|
120
131
|
const clearError = useCallback(() => {
|
|
121
132
|
// TanStack Query doesn't provide a direct way to clear errors
|
|
122
133
|
// We can trigger a refetch which will clear the error
|
|
123
134
|
void refetch();
|
|
124
135
|
}, [refetch]);
|
|
136
|
+
// Preview shipping rates for a country without updating session
|
|
137
|
+
const previewRates = useCallback(async (countryCode, stateCode) => {
|
|
138
|
+
if (!enabled || !effectiveSessionId)
|
|
139
|
+
return [];
|
|
140
|
+
try {
|
|
141
|
+
setIsPreviewLoading(true);
|
|
142
|
+
const response = await shippingRatesResource.previewShippingRates(effectiveSessionId, {
|
|
143
|
+
countryCode,
|
|
144
|
+
stateCode,
|
|
145
|
+
});
|
|
146
|
+
// Sort rates: free first, then by ascending amount
|
|
147
|
+
const sortedRates = [...response.rates].sort((a, b) => {
|
|
148
|
+
if (a.isFree && !b.isFree)
|
|
149
|
+
return -1;
|
|
150
|
+
if (!a.isFree && b.isFree)
|
|
151
|
+
return 1;
|
|
152
|
+
return (a.amount ?? 0) - (b.amount ?? 0);
|
|
153
|
+
});
|
|
154
|
+
setPreviewedRates(sortedRates);
|
|
155
|
+
return sortedRates;
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
console.error('[useShippingRatesQuery] Error previewing shipping rates:', error);
|
|
159
|
+
return [];
|
|
160
|
+
}
|
|
161
|
+
finally {
|
|
162
|
+
setIsPreviewLoading(false);
|
|
163
|
+
}
|
|
164
|
+
}, [enabled, effectiveSessionId, shippingRatesResource]);
|
|
125
165
|
return {
|
|
126
166
|
shippingRates,
|
|
127
167
|
selectedRate,
|
|
@@ -130,5 +170,8 @@ export function useShippingRatesQuery(options = {}) {
|
|
|
130
170
|
error: (fetchError || setShippingRateMutation.error),
|
|
131
171
|
clearError,
|
|
132
172
|
refetch,
|
|
173
|
+
previewRates,
|
|
174
|
+
previewedRates,
|
|
175
|
+
isPreviewLoading,
|
|
133
176
|
};
|
|
134
177
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* const offerId = staticResources?.offer;
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
|
-
import {
|
|
24
|
+
import { PixelsConfig, RuntimeStepConfig } from '../../core/funnelClient';
|
|
25
25
|
export interface UseStepConfigResult {
|
|
26
26
|
/**
|
|
27
27
|
* Full step configuration object
|
|
@@ -45,13 +45,7 @@ export interface UseStepConfigResult {
|
|
|
45
45
|
* @param position - Where the scripts should be injected
|
|
46
46
|
*/
|
|
47
47
|
getScripts: (position?: 'head-start' | 'head-end' | 'body-start' | 'body-end') => RuntimeStepConfig['scripts'];
|
|
48
|
-
pixels:
|
|
49
|
-
[TrackingProvider.FACEBOOK]?: PixelTrackingConfig[];
|
|
50
|
-
[TrackingProvider.TIKTOK]?: PixelTrackingConfig[];
|
|
51
|
-
[TrackingProvider.SNAPCHAT]?: SnapchatTrackingConfig[];
|
|
52
|
-
[TrackingProvider.META_CONVERSION]?: MetaConversionTrackingConfig[];
|
|
53
|
-
[TrackingProvider.GTM]?: GTMTrackingConfig[];
|
|
54
|
-
} | undefined;
|
|
48
|
+
pixels: PixelsConfig | undefined;
|
|
55
49
|
}
|
|
56
50
|
/**
|
|
57
51
|
* Hook to access runtime step configuration injected via HTML
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
import { useMemo } from 'react';
|
|
25
|
-
import { getAssignedPaymentFlowId, getAssignedPixels, getAssignedScripts, getAssignedStaticResources, getAssignedStepConfig,
|
|
25
|
+
import { getAssignedPaymentFlowId, getAssignedPixels, getAssignedScripts, getAssignedStaticResources, getAssignedStepConfig, } from '../../core/funnelClient';
|
|
26
26
|
/**
|
|
27
27
|
* Hook to access runtime step configuration injected via HTML
|
|
28
28
|
*
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface WhopPayment {
|
|
2
|
+
id: string;
|
|
3
|
+
status: 'succeeded' | 'declined' | 'pending';
|
|
4
|
+
requireAction: 'none' | 'redirect' | 'error';
|
|
5
|
+
orderId: string;
|
|
6
|
+
amount: number;
|
|
7
|
+
currency: string;
|
|
8
|
+
order?: {
|
|
9
|
+
id: string;
|
|
10
|
+
amount: number;
|
|
11
|
+
currency: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export interface UseWhopPaymentPollingOptions {
|
|
15
|
+
apiService: {
|
|
16
|
+
fetch: <T>(url: string, options: any) => Promise<T>;
|
|
17
|
+
};
|
|
18
|
+
checkoutSessionId: string;
|
|
19
|
+
maxAttempts?: number;
|
|
20
|
+
intervalMs?: number;
|
|
21
|
+
onSuccess?: (payment: WhopPayment) => void;
|
|
22
|
+
onMaxAttemptsReached?: () => void;
|
|
23
|
+
onError?: (error: Error) => void;
|
|
24
|
+
}
|
|
25
|
+
export interface UseWhopPaymentPollingReturn {
|
|
26
|
+
startPolling: (receiptId: string, orderId: string) => void;
|
|
27
|
+
stopPolling: () => void;
|
|
28
|
+
isPolling: boolean;
|
|
29
|
+
}
|
|
30
|
+
export declare const useWhopPaymentPolling: ({ apiService, checkoutSessionId, maxAttempts, intervalMs, onSuccess, onMaxAttemptsReached, onError, }: UseWhopPaymentPollingOptions) => UseWhopPaymentPollingReturn;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
export const useWhopPaymentPolling = ({ apiService, checkoutSessionId, maxAttempts = 60, intervalMs = 2000, onSuccess, onMaxAttemptsReached, onError, }) => {
|
|
3
|
+
const pollIntervalRef = useRef(null);
|
|
4
|
+
const attemptsRef = useRef(0);
|
|
5
|
+
const currentParamsRef = useRef(null);
|
|
6
|
+
const [isPolling, setIsPolling] = useState(false);
|
|
7
|
+
const stopPolling = useCallback(() => {
|
|
8
|
+
if (pollIntervalRef.current) {
|
|
9
|
+
clearInterval(pollIntervalRef.current);
|
|
10
|
+
pollIntervalRef.current = null;
|
|
11
|
+
}
|
|
12
|
+
setIsPolling(false);
|
|
13
|
+
attemptsRef.current = 0;
|
|
14
|
+
currentParamsRef.current = null;
|
|
15
|
+
}, []);
|
|
16
|
+
const startPolling = useCallback((receiptId, orderId) => {
|
|
17
|
+
stopPolling();
|
|
18
|
+
attemptsRef.current = 0;
|
|
19
|
+
currentParamsRef.current = { receiptId, orderId };
|
|
20
|
+
setIsPolling(true);
|
|
21
|
+
pollIntervalRef.current = setInterval(async () => {
|
|
22
|
+
if (!currentParamsRef.current)
|
|
23
|
+
return;
|
|
24
|
+
try {
|
|
25
|
+
attemptsRef.current++;
|
|
26
|
+
console.log(`Whop payment polling attempt ${attemptsRef.current}/${maxAttempts}...`);
|
|
27
|
+
const data = await apiService.fetch(`/api/v1/checkout-sessions/${checkoutSessionId}/whop-payment-status`, {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
body: JSON.stringify(currentParamsRef.current),
|
|
30
|
+
headers: { 'Content-Type': 'application/json' },
|
|
31
|
+
});
|
|
32
|
+
if (data && (data.status === 'succeeded' || data.status === 'declined')) {
|
|
33
|
+
stopPolling();
|
|
34
|
+
onSuccess?.(data);
|
|
35
|
+
}
|
|
36
|
+
else if (attemptsRef.current >= maxAttempts) {
|
|
37
|
+
stopPolling();
|
|
38
|
+
onMaxAttemptsReached?.();
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
console.warn(`Whop polling attempt ${attemptsRef.current} failed:`, error);
|
|
43
|
+
if (attemptsRef.current >= maxAttempts) {
|
|
44
|
+
stopPolling();
|
|
45
|
+
onError?.(error instanceof Error ? error : new Error(String(error)));
|
|
46
|
+
}
|
|
47
|
+
// Otherwise keep polling through transient errors
|
|
48
|
+
}
|
|
49
|
+
}, intervalMs);
|
|
50
|
+
}, [apiService, checkoutSessionId, maxAttempts, intervalMs, onSuccess, onMaxAttemptsReached, onError, stopPolling]);
|
|
51
|
+
useEffect(() => {
|
|
52
|
+
return () => {
|
|
53
|
+
stopPolling();
|
|
54
|
+
};
|
|
55
|
+
}, [stopPolling]);
|
|
56
|
+
return {
|
|
57
|
+
startPolling,
|
|
58
|
+
stopPolling,
|
|
59
|
+
isPolling,
|
|
60
|
+
};
|
|
61
|
+
};
|
package/dist/v2/react/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export type { DebugScript } from './providers/TagadaProvider';
|
|
|
8
8
|
export { ApplePayButton } from './components/ApplePayButton';
|
|
9
9
|
export { GooglePayButton } from './components/GooglePayButton';
|
|
10
10
|
export { PreviewModeIndicator } from './components/PreviewModeIndicator';
|
|
11
|
+
export { WhopCheckout } from './components/WhopCheckout';
|
|
11
12
|
export { useApplePayCheckout } from './hooks/useApplePayCheckout';
|
|
12
13
|
export { useAuth } from './hooks/useAuth';
|
|
13
14
|
export { useCheckoutToken } from './hooks/useCheckoutToken';
|
|
@@ -46,6 +47,7 @@ export { useThreeds } from './hooks/useThreeds';
|
|
|
46
47
|
export { useThreedsModal } from './hooks/useThreedsModal';
|
|
47
48
|
export { useTranslation } from './hooks/useTranslation';
|
|
48
49
|
export { useVipOffersQuery as useVipOffers } from './hooks/useVipOffersQuery';
|
|
50
|
+
export { useWhopPaymentPolling } from './hooks/useWhopPaymentPolling';
|
|
49
51
|
export { useFunnel } from './hooks/useFunnel';
|
|
50
52
|
export { useStepConfig } from './hooks/useStepConfig';
|
|
51
53
|
export { useFunnel as useFunnelLegacy, useSimpleFunnel } from './hooks/useFunnelLegacy';
|
|
@@ -63,6 +65,8 @@ export type { UseLoginOptions, UseLoginResult } from './hooks/useLogin';
|
|
|
63
65
|
export type { ApplePayButtonProps } from './components/ApplePayButton';
|
|
64
66
|
export type { GooglePayButtonProps } from './components/GooglePayButton';
|
|
65
67
|
export type { PreviewModeIndicatorProps } from './components/PreviewModeIndicator';
|
|
68
|
+
export type { WhopCheckoutHandle, WhopCheckoutProps } from './components/WhopCheckout';
|
|
69
|
+
export type { WhopPayment, UseWhopPaymentPollingOptions, UseWhopPaymentPollingReturn } from './hooks/useWhopPaymentPolling';
|
|
66
70
|
export type { GeoLocationData, UseGeoLocationOptions, UseGeoLocationReturn } from './hooks/useGeoLocation';
|
|
67
71
|
export type { ExtractedAddress, GooglePlaceDetails, GooglePrediction, UseGoogleAutocompleteOptions, UseGoogleAutocompleteResult } from './hooks/useGoogleAutocomplete';
|
|
68
72
|
export type { ISOCountry, ISORegion, UseISODataResult } from './hooks/useISOData';
|
|
@@ -89,4 +93,7 @@ export type { UseStoreConfigQueryOptions as UseStoreConfigOptions, UseStoreConfi
|
|
|
89
93
|
export type { PaymentInstrument, ThreedsChallenge, ThreedsHook, ThreedsOptions, ThreedsProvider, ThreedsSession } from './hooks/useThreeds';
|
|
90
94
|
export type { UseVipOffersQueryOptions as UseVipOffersOptions, UseVipOffersQueryResult as UseVipOffersResult } from './hooks/useVipOffersQuery';
|
|
91
95
|
export { formatMoney } from '../../react/utils/money';
|
|
96
|
+
export { TagadaError, TagadaApiError, TagadaNetworkError, TagadaAuthError, TagadaValidationError, TagadaCircuitBreakerError, TagadaErrorCode, } from '../core/errors';
|
|
97
|
+
export type { TagadaErrorOptions, TagadaErrorCodeValue } from '../core/errors';
|
|
98
|
+
export type { Order, OrderItem as CoreOrderItem, OrderAddress, OrderSummary, OrderWithRelations, PaymentSummary, PromotionSummary, Subscription, DeviceInfo, PromotionCode, Customer, Store, PickupPoint, } from '../core/types';
|
|
92
99
|
export type OrderItem = import('../core/utils/order').OrderLineItem;
|
package/dist/v2/react/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export { TagadaProvider, useTagadaContext } from './providers/TagadaProvider';
|
|
|
9
9
|
export { ApplePayButton } from './components/ApplePayButton';
|
|
10
10
|
export { GooglePayButton } from './components/GooglePayButton';
|
|
11
11
|
export { PreviewModeIndicator } from './components/PreviewModeIndicator';
|
|
12
|
+
export { WhopCheckout } from './components/WhopCheckout';
|
|
12
13
|
// Hooks
|
|
13
14
|
export { useApplePayCheckout } from './hooks/useApplePayCheckout';
|
|
14
15
|
export { useAuth } from './hooks/useAuth';
|
|
@@ -48,6 +49,7 @@ export { useThreeds } from './hooks/useThreeds';
|
|
|
48
49
|
export { useThreedsModal } from './hooks/useThreedsModal';
|
|
49
50
|
export { useTranslation } from './hooks/useTranslation';
|
|
50
51
|
export { useVipOffersQuery as useVipOffers } from './hooks/useVipOffersQuery';
|
|
52
|
+
export { useWhopPaymentPolling } from './hooks/useWhopPaymentPolling';
|
|
51
53
|
// Funnel hooks
|
|
52
54
|
export { useFunnel } from './hooks/useFunnel';
|
|
53
55
|
// Step config hook (access runtime configuration from HTML injection)
|
|
@@ -58,3 +60,5 @@ export { useFunnel as useFunnelLegacy, useSimpleFunnel } from './hooks/useFunnel
|
|
|
58
60
|
export { FunnelActionType } from '../core/resources/funnel';
|
|
59
61
|
// Re-export utilities from main react
|
|
60
62
|
export { formatMoney } from '../../react/utils/money';
|
|
63
|
+
// Error types
|
|
64
|
+
export { TagadaError, TagadaApiError, TagadaNetworkError, TagadaAuthError, TagadaValidationError, TagadaCircuitBreakerError, TagadaErrorCode, } from '../core/errors';
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Manages express payment methods (Apple Pay, Google Pay, PayPal, Klarna)
|
|
4
4
|
*/
|
|
5
5
|
import React, { ReactNode } from 'react';
|
|
6
|
+
import { TagadaError } from '../../core/errors';
|
|
6
7
|
import { CheckoutData } from '../../core/resources/checkout';
|
|
7
8
|
import { Address, PaymentMethod } from '../../core/resources/expressPaymentMethods';
|
|
8
9
|
type ExpressOrderLineItem = {
|
|
@@ -47,7 +48,7 @@ interface ExpressPaymentMethodsContextType {
|
|
|
47
48
|
};
|
|
48
49
|
}) => Promise<void>;
|
|
49
50
|
loading?: boolean;
|
|
50
|
-
error:
|
|
51
|
+
error: TagadaError | null;
|
|
51
52
|
setError: (error: string | null) => void;
|
|
52
53
|
}
|
|
53
54
|
interface ExpressPaymentMethodsProviderProps {
|
|
@@ -5,6 +5,7 @@ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
|
5
5
|
*/
|
|
6
6
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
7
7
|
import { createContext, useCallback, useMemo, useState } from 'react';
|
|
8
|
+
import { TagadaError, TagadaErrorCode } from '../../core/errors';
|
|
8
9
|
import { ExpressPaymentMethodsResource, } from '../../core/resources/expressPaymentMethods';
|
|
9
10
|
import { getGlobalApiClient } from '../hooks/useApiQuery';
|
|
10
11
|
import { useShippingRatesQuery } from '../hooks/useShippingRatesQuery';
|
|
@@ -170,6 +171,7 @@ export const ExpressPaymentMethodsProvider = ({ children, customerId, checkout,
|
|
|
170
171
|
const paypalPaymentMethod = useMemo(() => paymentMethods?.find((p) => p.type === 'paypal'), [paymentMethods]);
|
|
171
172
|
const klarnaPaymentMethod = useMemo(() => paymentMethods?.find((p) => p.type === 'klarna'), [paymentMethods]);
|
|
172
173
|
const loading = !paymentMethods || isLoadingPaymentMethods;
|
|
174
|
+
const tagadaError = useMemo(() => error ? new TagadaError(error, { code: TagadaErrorCode.PAYMENT_FAILED }) : null, [error]);
|
|
173
175
|
const contextValue = {
|
|
174
176
|
paymentMethods,
|
|
175
177
|
availableExpressPaymentMethodIds,
|
|
@@ -185,7 +187,7 @@ export const ExpressPaymentMethodsProvider = ({ children, customerId, checkout,
|
|
|
185
187
|
handleAddExpressId,
|
|
186
188
|
updateCheckoutSessionValues,
|
|
187
189
|
updateCustomerEmail,
|
|
188
|
-
error,
|
|
190
|
+
error: tagadaError,
|
|
189
191
|
setError,
|
|
190
192
|
};
|
|
191
193
|
const hasAnyEnabled = Boolean(applePayPaymentMethod || googlePayPaymentMethod || paypalPaymentMethod || klarnaPaymentMethod);
|
|
@@ -4,7 +4,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
4
4
|
* TagadaProvider - Main provider component for the Tagada Pay React SDK
|
|
5
5
|
*/
|
|
6
6
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
7
|
-
import { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
|
7
|
+
import { Suspense, createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
|
8
8
|
import { ApiService } from '../../../react/services/apiService';
|
|
9
9
|
import { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits, } from '../../../react/utils/money';
|
|
10
10
|
import { TagadaClient } from '../../core/client';
|
|
@@ -38,11 +38,11 @@ const InitializationLoader = () => (_jsxs("div", { style: {
|
|
|
38
38
|
borderTop: '1.5px solid #9ca3af',
|
|
39
39
|
borderRadius: '50%',
|
|
40
40
|
animation: 'tagada-spin 1s linear infinite',
|
|
41
|
-
} }), _jsx("span", { children: "Loading..." }), _jsx("style", { children: `
|
|
42
|
-
@keyframes tagada-spin {
|
|
43
|
-
0% { transform: rotate(0deg); }
|
|
44
|
-
100% { transform: rotate(360deg); }
|
|
45
|
-
}
|
|
41
|
+
} }), _jsx("span", { children: "Loading..." }), _jsx("style", { children: `
|
|
42
|
+
@keyframes tagada-spin {
|
|
43
|
+
0% { transform: rotate(0deg); }
|
|
44
|
+
100% { transform: rotate(360deg); }
|
|
45
|
+
}
|
|
46
46
|
` })] }));
|
|
47
47
|
const TagadaContext = createContext(null);
|
|
48
48
|
export function TagadaProvider({ children, environment, customApiConfig, debugMode, localConfig, blockUntilSessionReady = false, rawPluginConfig, features, funnelId, autoInitializeFunnel = true, onNavigate, onFunnelError, debugScripts = [], }) {
|
|
@@ -213,6 +213,75 @@ export function TagadaProvider({ children, environment, customApiConfig, debugMo
|
|
|
213
213
|
formatSimpleMoney,
|
|
214
214
|
}), []);
|
|
215
215
|
const [isDebugDrawerOpen, setIsDebugDrawerOpen] = useState(false);
|
|
216
|
+
// Track last injected script to prevent duplicate execution
|
|
217
|
+
/**
|
|
218
|
+
* Editor Element Click Bridge (Iframe → Parent)
|
|
219
|
+
*
|
|
220
|
+
* When running inside the CRM config editor iframe, elements can declare an `editor-id`
|
|
221
|
+
* attribute (e.g. <h1 editor-id="config.texts.checkoutTitle">Title</h1>).
|
|
222
|
+
*
|
|
223
|
+
* This effect sets up a delegated click listener on `document` that:
|
|
224
|
+
* - Finds the closest ancestor with an `editor-id`
|
|
225
|
+
* - Sends a `postMessage` to `window.parent` with the editorId and text content
|
|
226
|
+
*
|
|
227
|
+
* The parent (ConfigEditor) can then map this back to the corresponding config field.
|
|
228
|
+
*/
|
|
229
|
+
useEffect(() => {
|
|
230
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
231
|
+
return;
|
|
232
|
+
}
|
|
233
|
+
const handleClick = (event) => {
|
|
234
|
+
if (!(event.target instanceof Element))
|
|
235
|
+
return;
|
|
236
|
+
const targetWithEditorId = event.target.closest('[editor-id]');
|
|
237
|
+
if (!targetWithEditorId)
|
|
238
|
+
return;
|
|
239
|
+
const editorId = targetWithEditorId.getAttribute('editor-id');
|
|
240
|
+
if (!editorId)
|
|
241
|
+
return;
|
|
242
|
+
const textContent = targetWithEditorId.textContent ?? '';
|
|
243
|
+
// Only attempt cross-window messaging when inside an iframe
|
|
244
|
+
const isInIframe = window.parent && window.parent !== window;
|
|
245
|
+
if (!isInIframe) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const message = {
|
|
249
|
+
type: 'TAGADAPAY_EDITOR_ELEMENT_CLICK',
|
|
250
|
+
editorId,
|
|
251
|
+
textContent,
|
|
252
|
+
};
|
|
253
|
+
try {
|
|
254
|
+
// Derive parent origin from document.referrer when possible; fall back to '*'
|
|
255
|
+
// This avoids postMessage origin mismatch errors in dev (e.g. 3001 ↔ 5173)
|
|
256
|
+
let targetOrigin = '*';
|
|
257
|
+
try {
|
|
258
|
+
if (typeof document !== 'undefined' && document.referrer) {
|
|
259
|
+
const url = new URL(document.referrer);
|
|
260
|
+
targetOrigin = url.origin;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
// Fallback to '*'
|
|
265
|
+
targetOrigin = '*';
|
|
266
|
+
}
|
|
267
|
+
window.parent.postMessage(message, targetOrigin);
|
|
268
|
+
if (state.debugMode) {
|
|
269
|
+
// eslint-disable-next-line no-console
|
|
270
|
+
console.log('[TagadaProvider] Sent editor element click to parent:', message);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
if (state.debugMode) {
|
|
275
|
+
// eslint-disable-next-line no-console
|
|
276
|
+
console.error('[TagadaProvider] Failed to post editor element click message:', error);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
document.addEventListener('click', handleClick, true);
|
|
281
|
+
return () => {
|
|
282
|
+
document.removeEventListener('click', handleClick, true);
|
|
283
|
+
};
|
|
284
|
+
}, [state.debugMode]);
|
|
216
285
|
// Funnel Methods
|
|
217
286
|
const funnelMethods = useMemo(() => {
|
|
218
287
|
if (!client.funnel) {
|
|
@@ -335,7 +404,7 @@ export function TagadaProvider({ children, environment, customApiConfig, debugMo
|
|
|
335
404
|
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
|
|
336
405
|
zIndex: 999997,
|
|
337
406
|
transition: 'all 0.2s ease',
|
|
338
|
-
}, title: "Open TagadaPay SDK Debug Panel", children: "\uD83D\uDC1B" }), _jsx(DebugDrawer, { isOpen: isDebugDrawerOpen, onClose: () => setIsDebugDrawerOpen(false) })] })), canRenderChildren && children] }) }) }));
|
|
407
|
+
}, title: "Open TagadaPay SDK Debug Panel", children: "\uD83D\uDC1B" }), _jsx(Suspense, { fallback: null, children: _jsx(DebugDrawer, { isOpen: isDebugDrawerOpen, onClose: () => setIsDebugDrawerOpen(false) }) })] })), canRenderChildren && children] }) }) }));
|
|
339
408
|
}
|
|
340
409
|
export function useTagadaContext() {
|
|
341
410
|
const context = useContext(TagadaContext);
|
|
@@ -1,59 +1,48 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* TagadaPay External Page Tracker
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Standalone script for tracking users on external pages that are part of a
|
|
5
|
+
* TagadaPay funnel but not hosted on the TagadaPay platform.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* Use cases:
|
|
8
|
+
* - WooCommerce / WordPress storefronts
|
|
9
|
+
* - Custom landing pages
|
|
10
|
+
* - Any external page that is a funnel step
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* @example CDN usage
|
|
13
|
+
* ```html
|
|
13
14
|
* <script src="https://cdn.jsdelivr.net/npm/@tagadapay/plugin-sdk/dist/external-tracker.min.js"></script>
|
|
14
15
|
* <script>
|
|
15
16
|
* TagadaTracker.init({
|
|
16
17
|
* storeId: 'store_xxx',
|
|
17
18
|
* accountId: 'acc_xxx',
|
|
18
|
-
* funnelId: 'funnel_xxx', // Optional: detected from URL
|
|
19
19
|
* stepId: 'step_xxx',
|
|
20
|
-
* stepName: 'External Offer Page',
|
|
21
|
-
* stepType: 'external'
|
|
22
|
-
* });
|
|
23
|
-
*
|
|
24
|
-
* // Navigate to next step (tracking automatic)
|
|
25
|
-
* TagadaTracker.navigate({
|
|
26
|
-
* eventType: 'form.submitted',
|
|
27
|
-
* eventData: { email: 'user@example.com' }
|
|
28
20
|
* });
|
|
29
21
|
* </script>
|
|
22
|
+
* ```
|
|
30
23
|
*/
|
|
31
24
|
import type { TagadaClient } from '../core/client';
|
|
25
|
+
export declare const TRACKER_VERSION = "1.0.0";
|
|
32
26
|
export interface TagadaTrackerConfig {
|
|
33
27
|
/** Store ID (required) */
|
|
34
28
|
storeId: string;
|
|
35
|
-
/** Account ID (required
|
|
36
|
-
accountId
|
|
37
|
-
/** Funnel ID (optional
|
|
29
|
+
/** Account ID (required — session init will fail without it) */
|
|
30
|
+
accountId: string;
|
|
31
|
+
/** Funnel ID (optional — can be extracted from URL param) */
|
|
38
32
|
funnelId?: string;
|
|
39
|
-
/**
|
|
40
|
-
* Step ID (REQUIRED for external pages)
|
|
41
|
-
*
|
|
42
|
-
* External URLs cannot be mapped to steps via URL matching (only works for Tagadapay-hosted pages).
|
|
43
|
-
* You must explicitly specify which step this external page represents.
|
|
44
|
-
*/
|
|
33
|
+
/** Step ID (required for external pages — URL-to-step mapping only works for TagadaPay-hosted pages) */
|
|
45
34
|
stepId: string;
|
|
46
|
-
/** Step name (optional
|
|
35
|
+
/** Step name (optional — for analytics/debugging) */
|
|
47
36
|
stepName?: string;
|
|
48
|
-
/** Step type (optional
|
|
37
|
+
/** Step type (optional — e.g., 'landing', 'offer', 'external') */
|
|
49
38
|
stepType?: string;
|
|
50
|
-
/** API base URL (defaults to
|
|
39
|
+
/** API base URL (defaults to https://app.tagadapay.com) */
|
|
51
40
|
apiBaseUrl?: string;
|
|
52
41
|
/** Enable debug logging */
|
|
53
42
|
debug?: boolean;
|
|
54
43
|
/** Callback when session is ready */
|
|
55
44
|
onReady?: (session: ExternalTrackerSession) => void;
|
|
56
|
-
/** Callback on error */
|
|
45
|
+
/** Callback on error — when provided, init() will NOT throw */
|
|
57
46
|
onError?: (error: Error) => void;
|
|
58
47
|
}
|
|
59
48
|
export interface ExternalTrackerSession {
|
|
@@ -71,49 +60,66 @@ export interface NavigateOptions {
|
|
|
71
60
|
eventData?: Record<string, unknown>;
|
|
72
61
|
/** Override return URL */
|
|
73
62
|
returnUrl?: string;
|
|
74
|
-
/**
|
|
63
|
+
/** Whether to auto-redirect after navigation (default: true) */
|
|
75
64
|
autoRedirect?: boolean;
|
|
76
65
|
}
|
|
66
|
+
export interface TrackEventOptions {
|
|
67
|
+
/** Event name (e.g., 'button_click', 'scroll_depth', 'video_play') */
|
|
68
|
+
name: string;
|
|
69
|
+
/** Arbitrary event data */
|
|
70
|
+
data?: Record<string, unknown>;
|
|
71
|
+
}
|
|
77
72
|
declare class TagadaExternalTracker {
|
|
78
73
|
private config;
|
|
79
74
|
private client;
|
|
80
75
|
private initialized;
|
|
81
76
|
private initializing;
|
|
77
|
+
private unsubscribe;
|
|
78
|
+
/** Tracker version */
|
|
79
|
+
readonly version = "1.0.0";
|
|
82
80
|
/**
|
|
83
|
-
* Initialize the tracker
|
|
81
|
+
* Initialize the tracker.
|
|
82
|
+
* When `onError` is provided, errors are passed to the callback and init()
|
|
83
|
+
* resolves to `null` instead of throwing.
|
|
84
84
|
*/
|
|
85
85
|
init(config: TagadaTrackerConfig): Promise<ExternalTrackerSession | null>;
|
|
86
|
-
/**
|
|
87
|
-
* Get current session from SDK state
|
|
88
|
-
*/
|
|
86
|
+
/** Get current session data. */
|
|
89
87
|
getSession(): ExternalTrackerSession | null;
|
|
90
|
-
/**
|
|
91
|
-
* Check if tracker is ready
|
|
92
|
-
*/
|
|
88
|
+
/** Whether the tracker is fully initialized and ready. */
|
|
93
89
|
isReady(): boolean;
|
|
94
90
|
/**
|
|
95
|
-
* Navigate to next step in
|
|
91
|
+
* Navigate to the next step in the funnel.
|
|
92
|
+
* By default, auto-redirects the browser window.
|
|
96
93
|
*/
|
|
97
94
|
navigate(options: NavigateOptions): Promise<{
|
|
98
95
|
url: string;
|
|
99
96
|
} | null>;
|
|
100
97
|
/**
|
|
101
|
-
*
|
|
98
|
+
* Track a custom event (e.g., button click, scroll depth, video play).
|
|
99
|
+
* Events are sent through the funnel orchestrator for unified analytics.
|
|
102
100
|
*/
|
|
101
|
+
trackEvent(options: TrackEventOptions): Promise<void>;
|
|
102
|
+
/** Get customer ID. */
|
|
103
103
|
getCustomerId(): string | null;
|
|
104
|
-
/**
|
|
105
|
-
* Get funnel session ID
|
|
106
|
-
*/
|
|
104
|
+
/** Get funnel session ID. */
|
|
107
105
|
getFunnelSessionId(): string | null;
|
|
108
106
|
/**
|
|
109
|
-
* Build a URL
|
|
110
|
-
*
|
|
107
|
+
* Build a URL that preserves funnel session context.
|
|
108
|
+
* Use this to link to other external pages within the same funnel.
|
|
111
109
|
*/
|
|
112
110
|
buildUrl(baseUrl: string, additionalParams?: Record<string, string>): string;
|
|
111
|
+
/** Get the underlying SDK client (advanced usage). */
|
|
112
|
+
getClient(): TagadaClient | null;
|
|
113
113
|
/**
|
|
114
|
-
*
|
|
114
|
+
* Reset the tracker to a new step without re-creating the session.
|
|
115
|
+
* Useful for SPAs that navigate between funnel steps client-side.
|
|
115
116
|
*/
|
|
116
|
-
|
|
117
|
+
reset(newStepId: string): Promise<ExternalTrackerSession | null>;
|
|
118
|
+
/**
|
|
119
|
+
* Destroy the tracker, clean up event listeners and state.
|
|
120
|
+
* Call this when the tracker is no longer needed (e.g., SPA teardown).
|
|
121
|
+
*/
|
|
122
|
+
destroy(): void;
|
|
117
123
|
private waitForClientReady;
|
|
118
124
|
private initializeFunnel;
|
|
119
125
|
}
|