@tagadapay/plugin-sdk 2.4.39 → 2.5.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.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/react/hooks/useCheckout.js +19 -2
- package/dist/react/hooks/useCheckoutSession.d.ts +19 -0
- package/dist/react/hooks/useCheckoutSession.js +108 -0
- package/dist/react/hooks/useCheckoutToken.d.ts +17 -0
- package/dist/react/hooks/useCheckoutToken.js +80 -0
- package/dist/react/hooks/useOrderBump.js +92 -13
- package/dist/react/hooks/useOrderBumpV2.d.ts +17 -0
- package/dist/react/hooks/useOrderBumpV2.js +95 -0
- package/dist/react/hooks/useOrderBumpV3.d.ts +23 -0
- package/dist/react/hooks/useOrderBumpV3.js +109 -0
- package/dist/react/hooks/usePostPurchases.js +11 -5
- package/dist/react/index.d.ts +8 -0
- package/dist/react/index.js +4 -0
- package/dist/react/services/apiService.d.ts +1 -0
- package/dist/react/services/apiService.js +3 -0
- package/dist/v2/core/googleAutocomplete.d.ts +65 -0
- package/dist/v2/core/googleAutocomplete.js +94 -0
- package/dist/v2/core/index.d.ts +8 -0
- package/dist/v2/core/index.js +11 -0
- package/dist/v2/core/isoData.d.ts +50 -0
- package/dist/v2/core/isoData.js +103 -0
- package/dist/v2/core/resources/apiClient.d.ts +25 -0
- package/dist/v2/core/resources/apiClient.js +95 -0
- package/dist/v2/core/resources/checkout.d.ts +189 -0
- package/dist/v2/core/resources/checkout.js +119 -0
- package/dist/v2/core/resources/index.d.ts +13 -0
- package/dist/v2/core/resources/index.js +13 -0
- package/dist/v2/core/resources/offers.d.ts +98 -0
- package/dist/v2/core/resources/offers.js +115 -0
- package/dist/v2/core/resources/orders.d.ts +40 -0
- package/dist/v2/core/resources/orders.js +59 -0
- package/dist/v2/core/resources/payments.d.ts +140 -0
- package/dist/v2/core/resources/payments.js +126 -0
- package/dist/v2/core/resources/postPurchases.d.ts +182 -0
- package/dist/v2/core/resources/postPurchases.js +116 -0
- package/dist/v2/core/resources/products.d.ts +29 -0
- package/dist/v2/core/resources/products.js +49 -0
- package/dist/v2/core/resources/promotions.d.ts +45 -0
- package/dist/v2/core/resources/promotions.js +87 -0
- package/dist/v2/core/resources/threeds.d.ts +23 -0
- package/dist/v2/core/resources/threeds.js +15 -0
- package/dist/v2/core/utils/checkout.d.ts +24 -0
- package/dist/v2/core/utils/checkout.js +30 -0
- package/dist/v2/core/utils/currency.d.ts +28 -0
- package/dist/v2/core/utils/currency.js +272 -0
- package/dist/v2/core/utils/index.d.ts +12 -0
- package/dist/v2/core/utils/index.js +12 -0
- package/dist/v2/core/utils/order.d.ts +159 -0
- package/dist/v2/core/utils/order.js +42 -0
- package/dist/v2/core/utils/orderBump.d.ts +40 -0
- package/dist/v2/core/utils/orderBump.js +47 -0
- package/dist/v2/core/utils/pluginConfig.d.ts +43 -0
- package/dist/v2/core/utils/pluginConfig.js +155 -0
- package/dist/v2/core/utils/postPurchases.d.ts +32 -0
- package/dist/v2/core/utils/postPurchases.js +42 -0
- package/dist/v2/core/utils/products.d.ts +58 -0
- package/dist/v2/core/utils/products.js +64 -0
- package/dist/v2/core/utils/promotions.d.ts +24 -0
- package/dist/v2/core/utils/promotions.js +30 -0
- package/dist/v2/index.d.ts +19 -0
- package/dist/v2/index.js +15 -0
- package/dist/v2/react/components/DebugDrawer.d.ts +7 -0
- package/dist/v2/react/components/DebugDrawer.js +383 -0
- package/dist/v2/react/hooks/useApiQuery.d.ts +28 -0
- package/dist/v2/react/hooks/useApiQuery.js +84 -0
- package/dist/v2/react/hooks/useCheckoutQuery.d.ts +39 -0
- package/dist/v2/react/hooks/useCheckoutQuery.js +208 -0
- package/dist/v2/react/hooks/useCheckoutToken.d.ts +17 -0
- package/dist/v2/react/hooks/useCheckoutToken.js +80 -0
- package/dist/v2/react/hooks/useCurrency.d.ts +9 -0
- package/dist/v2/react/hooks/useCurrency.js +21 -0
- package/dist/v2/react/hooks/useGeoLocation.d.ts +138 -0
- package/dist/v2/react/hooks/useGeoLocation.js +126 -0
- package/dist/v2/react/hooks/useGoogleAutocomplete.d.ts +74 -0
- package/dist/v2/react/hooks/useGoogleAutocomplete.js +207 -0
- package/dist/v2/react/hooks/useISOData.d.ts +61 -0
- package/dist/v2/react/hooks/useISOData.js +176 -0
- package/dist/v2/react/hooks/useOffersQuery.d.ts +65 -0
- package/dist/v2/react/hooks/useOffersQuery.js +353 -0
- package/dist/v2/react/hooks/useOrderBumpQuery.d.ts +20 -0
- package/dist/v2/react/hooks/useOrderBumpQuery.js +88 -0
- package/dist/v2/react/hooks/useOrderQuery.d.ts +29 -0
- package/dist/v2/react/hooks/useOrderQuery.js +98 -0
- package/dist/v2/react/hooks/usePaymentPolling.d.ts +45 -0
- package/dist/v2/react/hooks/usePaymentPolling.js +153 -0
- package/dist/v2/react/hooks/usePaymentQuery.d.ts +19 -0
- package/dist/v2/react/hooks/usePaymentQuery.js +283 -0
- package/dist/v2/react/hooks/usePluginConfig.d.ts +16 -0
- package/dist/v2/react/hooks/usePluginConfig.js +36 -0
- package/dist/v2/react/hooks/usePostPurchasesQuery.d.ts +63 -0
- package/dist/v2/react/hooks/usePostPurchasesQuery.js +365 -0
- package/dist/v2/react/hooks/useProductsQuery.d.ts +31 -0
- package/dist/v2/react/hooks/useProductsQuery.js +102 -0
- package/dist/v2/react/hooks/usePromotionsQuery.d.ts +28 -0
- package/dist/v2/react/hooks/usePromotionsQuery.js +97 -0
- package/dist/v2/react/hooks/useThreeds.d.ts +36 -0
- package/dist/v2/react/hooks/useThreeds.js +166 -0
- package/dist/v2/react/hooks/useThreedsModal.d.ts +13 -0
- package/dist/v2/react/hooks/useThreedsModal.js +343 -0
- package/dist/v2/react/index.d.ts +38 -0
- package/dist/v2/react/index.js +27 -0
- package/dist/v2/react/providers/TagadaProvider.d.ts +63 -0
- package/dist/v2/react/providers/TagadaProvider.js +680 -0
- package/package.json +10 -3
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { useState, useCallback, useEffect, useMemo } from 'react';
|
|
2
|
+
import { getBasisTheoryApiKey } from '../../../react/config/payment';
|
|
3
|
+
import { ThreedsResource } from '../../core/resources/threeds';
|
|
4
|
+
import { useThreedsModal } from './useThreedsModal';
|
|
5
|
+
import { getGlobalApiClient } from './useApiQuery';
|
|
6
|
+
export function useThreeds(options = {}) {
|
|
7
|
+
const { defaultProvider = 'basis_theory' } = options;
|
|
8
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
9
|
+
const [error, setError] = useState(null);
|
|
10
|
+
const { createThreedsModal, closeThreedsModal } = useThreedsModal();
|
|
11
|
+
const [basisTheory3ds, setBasisTheory3ds] = useState(null);
|
|
12
|
+
const [_currentChallenge, _setCurrentChallenge] = useState(null);
|
|
13
|
+
// Create threeds resource client
|
|
14
|
+
const threedsResource = useMemo(() => {
|
|
15
|
+
try {
|
|
16
|
+
return new ThreedsResource(getGlobalApiClient());
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
throw new Error('Failed to initialize threeds resource: ' + (error instanceof Error ? error.message : 'Unknown error'));
|
|
20
|
+
}
|
|
21
|
+
}, []);
|
|
22
|
+
// Dynamically import BasisTheory3ds on the client side only
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
let isMounted = true;
|
|
25
|
+
const loadBasisTheory = async () => {
|
|
26
|
+
try {
|
|
27
|
+
// Dynamically import the library only on the client side
|
|
28
|
+
const { BasisTheory3ds } = await import('@basis-theory/web-threeds');
|
|
29
|
+
if (isMounted) {
|
|
30
|
+
setBasisTheory3ds(() => BasisTheory3ds);
|
|
31
|
+
console.log('✅ BasisTheory3ds initialized successfully');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
console.error('Failed to load BasisTheory3ds:', err);
|
|
36
|
+
if (isMounted) {
|
|
37
|
+
setError(err instanceof Error ? err : new Error('Failed to load 3DS library'));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
void loadBasisTheory();
|
|
42
|
+
return () => {
|
|
43
|
+
isMounted = false;
|
|
44
|
+
};
|
|
45
|
+
}, []);
|
|
46
|
+
// Create a 3DS session with BasisTheory
|
|
47
|
+
const createBasisTheorySession = useCallback(async (paymentInstrument) => {
|
|
48
|
+
try {
|
|
49
|
+
if (!basisTheory3ds) {
|
|
50
|
+
throw new Error('BasisTheory3ds not loaded yet');
|
|
51
|
+
}
|
|
52
|
+
// Use the same API key approach as the working CMS version
|
|
53
|
+
const apiKey = getBasisTheoryApiKey('production'); // Use production config for now
|
|
54
|
+
const bt3ds = basisTheory3ds(apiKey);
|
|
55
|
+
console.log('paymentInstrument paymentInstrument', paymentInstrument?.token);
|
|
56
|
+
const session = await bt3ds.createSession({
|
|
57
|
+
tokenId: paymentInstrument.token,
|
|
58
|
+
});
|
|
59
|
+
// Create session through our API
|
|
60
|
+
const threedsSession = await threedsResource.createSession({
|
|
61
|
+
provider: 'basis_theory',
|
|
62
|
+
sessionData: session,
|
|
63
|
+
paymentInstrumentId: paymentInstrument.id,
|
|
64
|
+
});
|
|
65
|
+
return threedsSession;
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error('Error creating BasisTheory 3DS session:', error);
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
}, [threedsResource, basisTheory3ds]);
|
|
72
|
+
// Generic createSession method that supports multiple providers
|
|
73
|
+
const createSession = useCallback(async (paymentInstrument, options) => {
|
|
74
|
+
const provider = options?.provider || defaultProvider;
|
|
75
|
+
setIsLoading(true);
|
|
76
|
+
setError(null);
|
|
77
|
+
try {
|
|
78
|
+
let session;
|
|
79
|
+
if (provider === 'basis_theory') {
|
|
80
|
+
session = await createBasisTheorySession(paymentInstrument);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
throw new Error(`Unsupported 3DS provider: ${String(provider)}`);
|
|
84
|
+
}
|
|
85
|
+
return session;
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
const error = err instanceof Error ? err : new Error('Failed to create 3DS session');
|
|
89
|
+
setError(error);
|
|
90
|
+
throw error;
|
|
91
|
+
}
|
|
92
|
+
finally {
|
|
93
|
+
setIsLoading(false);
|
|
94
|
+
}
|
|
95
|
+
}, [defaultProvider, createBasisTheorySession]);
|
|
96
|
+
// Start a 3DS challenge with BasisTheory
|
|
97
|
+
const startBasisTheoryChallenge = useCallback(async (sessionId, acsChallengeUrl, acsTransactionId, threeDSVersion) => {
|
|
98
|
+
try {
|
|
99
|
+
if (!basisTheory3ds) {
|
|
100
|
+
throw new Error('BasisTheory3ds not loaded yet');
|
|
101
|
+
}
|
|
102
|
+
// Use the same API key approach as the working CMS version
|
|
103
|
+
const apiKey = getBasisTheoryApiKey('production'); // Use production config for now
|
|
104
|
+
if (!apiKey) {
|
|
105
|
+
throw new Error('BasisTheory API key is not set');
|
|
106
|
+
}
|
|
107
|
+
const modal = createThreedsModal({
|
|
108
|
+
onClose: () => {
|
|
109
|
+
// Throw error when user closes the modal
|
|
110
|
+
throw new Error('Authentication was cancelled by the user');
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
const bt3ds = basisTheory3ds(apiKey);
|
|
114
|
+
console.log('bt3ds starting challenge with params', {
|
|
115
|
+
sessionId,
|
|
116
|
+
acsChallengeUrl,
|
|
117
|
+
acsTransactionId,
|
|
118
|
+
threeDSVersion,
|
|
119
|
+
});
|
|
120
|
+
const challengeCompletion = await bt3ds.startChallenge({
|
|
121
|
+
sessionId,
|
|
122
|
+
acsChallengeUrl,
|
|
123
|
+
acsTransactionId,
|
|
124
|
+
threeDSVersion: threeDSVersion,
|
|
125
|
+
containerId: modal.containerId + '-content',
|
|
126
|
+
mode: 'iframe',
|
|
127
|
+
timeout: 60000 * 3,
|
|
128
|
+
});
|
|
129
|
+
closeThreedsModal();
|
|
130
|
+
return challengeCompletion;
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
console.error('Error starting BasisTheory 3DS challenge:', error);
|
|
134
|
+
closeThreedsModal();
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
}, [basisTheory3ds, createThreedsModal, closeThreedsModal]);
|
|
138
|
+
// Generic startChallenge method that supports multiple providers
|
|
139
|
+
const startChallenge = useCallback(async (challengeData, options) => {
|
|
140
|
+
const provider = options?.provider || defaultProvider;
|
|
141
|
+
setIsLoading(true);
|
|
142
|
+
setError(null);
|
|
143
|
+
try {
|
|
144
|
+
if (provider === 'basis_theory') {
|
|
145
|
+
return await startBasisTheoryChallenge(challengeData.sessionId, challengeData.acsChallengeUrl, challengeData.acsTransactionId, challengeData.threeDSVersion);
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
throw new Error(`Unsupported 3DS provider: ${String(provider)}`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
const error = err instanceof Error ? err : new Error('Failed to start 3DS challenge');
|
|
153
|
+
setError(error);
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
finally {
|
|
157
|
+
setIsLoading(false);
|
|
158
|
+
}
|
|
159
|
+
}, [defaultProvider, startBasisTheoryChallenge]);
|
|
160
|
+
return {
|
|
161
|
+
createSession,
|
|
162
|
+
startChallenge,
|
|
163
|
+
isLoading,
|
|
164
|
+
error,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function useThreedsModal(): {
|
|
2
|
+
createThreedsModal: (options?: {
|
|
3
|
+
containerId?: string;
|
|
4
|
+
mode?: "fixed" | "auto-fit";
|
|
5
|
+
onClose?: () => void;
|
|
6
|
+
}) => {
|
|
7
|
+
containerId: string;
|
|
8
|
+
getContentElement: () => HTMLElement | null;
|
|
9
|
+
updateModalSize: () => void;
|
|
10
|
+
cleanup: () => void;
|
|
11
|
+
};
|
|
12
|
+
closeThreedsModal: (containerId?: string) => void;
|
|
13
|
+
};
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
export function useThreedsModal() {
|
|
4
|
+
// Close the 3DS modal
|
|
5
|
+
const closeThreedsModal = useCallback((containerId = 'threedscontainer') => {
|
|
6
|
+
const container = document.getElementById(containerId);
|
|
7
|
+
const backdrop = document.getElementById(`${containerId}-backdrop`);
|
|
8
|
+
if (container && backdrop) {
|
|
9
|
+
// Animate out
|
|
10
|
+
container.style.transform = 'scale(0.95)';
|
|
11
|
+
container.style.opacity = '0';
|
|
12
|
+
backdrop.style.opacity = '0';
|
|
13
|
+
setTimeout(() => {
|
|
14
|
+
if (backdrop && document.body.contains(backdrop)) {
|
|
15
|
+
document.body.removeChild(backdrop);
|
|
16
|
+
}
|
|
17
|
+
// Remove escape key listener
|
|
18
|
+
document.removeEventListener('keydown', (e) => {
|
|
19
|
+
if (e.key === 'Escape')
|
|
20
|
+
closeThreedsModal(containerId);
|
|
21
|
+
});
|
|
22
|
+
}, 300);
|
|
23
|
+
}
|
|
24
|
+
}, []);
|
|
25
|
+
// Create and open a modal for 3DS authentication
|
|
26
|
+
const createThreedsModal = useCallback((options = {}) => {
|
|
27
|
+
const { containerId = 'threedscontainer', mode = 'auto-fit', onClose } = options;
|
|
28
|
+
// Remove any existing modal first
|
|
29
|
+
const existingContainer = document.getElementById(containerId);
|
|
30
|
+
const existingBackdrop = document.getElementById(`${containerId}-backdrop`);
|
|
31
|
+
if (existingContainer)
|
|
32
|
+
document.body.removeChild(existingContainer);
|
|
33
|
+
if (existingBackdrop)
|
|
34
|
+
document.body.removeChild(existingBackdrop);
|
|
35
|
+
// Create backdrop
|
|
36
|
+
const backdrop = document.createElement('div');
|
|
37
|
+
backdrop.id = `${containerId}-backdrop`;
|
|
38
|
+
Object.assign(backdrop.style, {
|
|
39
|
+
position: 'fixed',
|
|
40
|
+
top: '0',
|
|
41
|
+
left: '0',
|
|
42
|
+
width: '100%',
|
|
43
|
+
height: '100%',
|
|
44
|
+
backgroundColor: 'rgba(0, 0, 0, 0.6)',
|
|
45
|
+
zIndex: '9998',
|
|
46
|
+
display: 'flex',
|
|
47
|
+
justifyContent: 'center',
|
|
48
|
+
alignItems: 'center', // Default to center alignment
|
|
49
|
+
transition: 'opacity 0.3s ease',
|
|
50
|
+
opacity: '0', // Start transparent
|
|
51
|
+
});
|
|
52
|
+
// Create modal container
|
|
53
|
+
const container = document.createElement('div');
|
|
54
|
+
container.id = containerId;
|
|
55
|
+
// Check if mobile initially
|
|
56
|
+
let isMobile = window.innerWidth < 768;
|
|
57
|
+
// Base styles for both modes
|
|
58
|
+
const baseStyles = {
|
|
59
|
+
position: 'relative',
|
|
60
|
+
backgroundColor: 'white',
|
|
61
|
+
borderRadius: '12px', // Default border radius
|
|
62
|
+
boxShadow: '0 10px 25px rgba(0, 0, 0, 0.2)',
|
|
63
|
+
maxWidth: '100%',
|
|
64
|
+
overflow: 'hidden',
|
|
65
|
+
zIndex: '9999',
|
|
66
|
+
transition: 'transform 0.3s ease, opacity 0.3s ease, width 0.3s ease, height 0.3s ease',
|
|
67
|
+
transform: 'scale(0.95)',
|
|
68
|
+
opacity: '0',
|
|
69
|
+
};
|
|
70
|
+
// Function to apply styles based on screen size and mode
|
|
71
|
+
const applyResponsiveStyles = () => {
|
|
72
|
+
isMobile = window.innerWidth < 768;
|
|
73
|
+
// Always ensure backdrop is properly centered
|
|
74
|
+
backdrop.style.alignItems = 'center';
|
|
75
|
+
backdrop.style.justifyContent = 'center';
|
|
76
|
+
if (mode === 'fixed') {
|
|
77
|
+
if (isMobile) {
|
|
78
|
+
// Full screen modal for mobile
|
|
79
|
+
Object.assign(container.style, {
|
|
80
|
+
...baseStyles,
|
|
81
|
+
position: 'fixed',
|
|
82
|
+
top: '0',
|
|
83
|
+
left: '0',
|
|
84
|
+
right: '0',
|
|
85
|
+
bottom: '0',
|
|
86
|
+
width: '100%',
|
|
87
|
+
height: '100%',
|
|
88
|
+
borderRadius: '0', // No border radius for full screen
|
|
89
|
+
margin: '0',
|
|
90
|
+
backgroundColor: 'white',
|
|
91
|
+
transform: 'scale(0.95)',
|
|
92
|
+
opacity: '0',
|
|
93
|
+
maxHeight: '100%',
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
// Desktop styles
|
|
98
|
+
Object.assign(container.style, {
|
|
99
|
+
...baseStyles,
|
|
100
|
+
width: '550px',
|
|
101
|
+
height: '600px',
|
|
102
|
+
maxHeight: '85vh',
|
|
103
|
+
position: 'relative',
|
|
104
|
+
borderRadius: '12px',
|
|
105
|
+
margin: 'auto',
|
|
106
|
+
backgroundColor: 'white',
|
|
107
|
+
transform: 'scale(0.95)',
|
|
108
|
+
opacity: '0',
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
// auto-fit mode
|
|
114
|
+
if (isMobile) {
|
|
115
|
+
// Full screen modal for mobile
|
|
116
|
+
Object.assign(container.style, {
|
|
117
|
+
...baseStyles,
|
|
118
|
+
position: 'fixed',
|
|
119
|
+
top: '0',
|
|
120
|
+
left: '0',
|
|
121
|
+
right: '0',
|
|
122
|
+
bottom: '0',
|
|
123
|
+
width: '100%',
|
|
124
|
+
height: '100%',
|
|
125
|
+
borderRadius: '0', // No border radius for full screen
|
|
126
|
+
margin: '0',
|
|
127
|
+
backgroundColor: 'white',
|
|
128
|
+
transform: 'scale(0.95)',
|
|
129
|
+
opacity: '0',
|
|
130
|
+
maxHeight: '100%',
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
// Desktop styles
|
|
135
|
+
Object.assign(container.style, {
|
|
136
|
+
...baseStyles,
|
|
137
|
+
width: '550px',
|
|
138
|
+
maxHeight: '85vh',
|
|
139
|
+
height: 'auto',
|
|
140
|
+
minHeight: '250px',
|
|
141
|
+
position: 'relative',
|
|
142
|
+
borderRadius: '12px',
|
|
143
|
+
margin: 'auto',
|
|
144
|
+
backgroundColor: 'white',
|
|
145
|
+
transform: 'scale(0.95)',
|
|
146
|
+
opacity: '0',
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
// Apply initial styles
|
|
152
|
+
applyResponsiveStyles();
|
|
153
|
+
// Create header
|
|
154
|
+
const header = document.createElement('div');
|
|
155
|
+
Object.assign(header.style, {
|
|
156
|
+
padding: '16px 20px',
|
|
157
|
+
borderBottom: '1px solid #eaeaea',
|
|
158
|
+
display: 'flex',
|
|
159
|
+
justifyContent: 'space-between',
|
|
160
|
+
alignItems: 'center',
|
|
161
|
+
backgroundColor: 'white',
|
|
162
|
+
});
|
|
163
|
+
// Add title
|
|
164
|
+
const title = document.createElement('h3');
|
|
165
|
+
title.textContent = 'Secure Authentication';
|
|
166
|
+
Object.assign(title.style, {
|
|
167
|
+
margin: '0',
|
|
168
|
+
fontSize: '18px',
|
|
169
|
+
fontWeight: '600',
|
|
170
|
+
color: '#333',
|
|
171
|
+
});
|
|
172
|
+
// Add close button
|
|
173
|
+
const closeButton = document.createElement('button');
|
|
174
|
+
closeButton.innerHTML = '×';
|
|
175
|
+
Object.assign(closeButton.style, {
|
|
176
|
+
background: 'none',
|
|
177
|
+
border: 'none',
|
|
178
|
+
fontSize: '24px',
|
|
179
|
+
cursor: 'pointer',
|
|
180
|
+
color: '#666',
|
|
181
|
+
padding: '0 5px',
|
|
182
|
+
lineHeight: '1',
|
|
183
|
+
});
|
|
184
|
+
// Create content area
|
|
185
|
+
const content = document.createElement('div');
|
|
186
|
+
content.id = `${containerId}-content`;
|
|
187
|
+
// Function to update content styles based on mode and screen size
|
|
188
|
+
const updateContentStyles = () => {
|
|
189
|
+
if (mode === 'fixed') {
|
|
190
|
+
Object.assign(content.style, {
|
|
191
|
+
height: isMobile ? 'calc(100% - 60px)' : 'calc(100% - 60px)',
|
|
192
|
+
width: '100%',
|
|
193
|
+
overflow: 'hidden',
|
|
194
|
+
backgroundColor: 'white',
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
// auto-fit mode
|
|
199
|
+
if (isMobile) {
|
|
200
|
+
Object.assign(content.style, {
|
|
201
|
+
width: '100%',
|
|
202
|
+
height: 'calc(100% - 60px)',
|
|
203
|
+
overflow: 'auto',
|
|
204
|
+
padding: '16px',
|
|
205
|
+
backgroundColor: 'white',
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
Object.assign(content.style, {
|
|
210
|
+
width: '100%',
|
|
211
|
+
overflow: 'auto',
|
|
212
|
+
padding: '20px',
|
|
213
|
+
maxHeight: 'calc(85vh - 60px)',
|
|
214
|
+
backgroundColor: 'white',
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
// Apply initial content styles
|
|
220
|
+
updateContentStyles();
|
|
221
|
+
// Update close handlers to call onClose callback
|
|
222
|
+
const handleClose = () => {
|
|
223
|
+
onClose?.();
|
|
224
|
+
closeThreedsModal(containerId);
|
|
225
|
+
};
|
|
226
|
+
// Update event listeners
|
|
227
|
+
closeButton.onclick = handleClose;
|
|
228
|
+
backdrop.onclick = (e) => {
|
|
229
|
+
if (e.target === backdrop) {
|
|
230
|
+
handleClose();
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
// Update escape key listener
|
|
234
|
+
const escKeyHandler = (e) => {
|
|
235
|
+
if (e.key === 'Escape') {
|
|
236
|
+
handleClose();
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
document.addEventListener('keydown', escKeyHandler);
|
|
240
|
+
// Assemble the modal
|
|
241
|
+
header.appendChild(title);
|
|
242
|
+
header.appendChild(closeButton);
|
|
243
|
+
container.appendChild(header);
|
|
244
|
+
container.appendChild(content);
|
|
245
|
+
backdrop.appendChild(container);
|
|
246
|
+
document.body.appendChild(backdrop);
|
|
247
|
+
// Animate in with a slight delay to ensure proper rendering
|
|
248
|
+
setTimeout(() => {
|
|
249
|
+
backdrop.style.opacity = '1';
|
|
250
|
+
container.style.transform = 'scale(1)';
|
|
251
|
+
container.style.opacity = '1';
|
|
252
|
+
}, 50);
|
|
253
|
+
// Function to adjust height in auto-fit mode
|
|
254
|
+
const adjustAutoFitHeight = () => {
|
|
255
|
+
if (!content)
|
|
256
|
+
return;
|
|
257
|
+
if (isMobile) {
|
|
258
|
+
// On mobile, we're using full screen so just ensure content scrolls
|
|
259
|
+
content.style.height = 'calc(100% - 60px)';
|
|
260
|
+
content.style.overflowY = 'auto';
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
const viewportHeight = window.innerHeight;
|
|
264
|
+
const contentHeight = content.scrollHeight;
|
|
265
|
+
const headerHeight = header.offsetHeight;
|
|
266
|
+
const maxModalHeight = viewportHeight * 0.85;
|
|
267
|
+
if (contentHeight + headerHeight < maxModalHeight) {
|
|
268
|
+
// Content fits, let it determine the height
|
|
269
|
+
container.style.height = 'auto';
|
|
270
|
+
content.style.overflowY = 'visible';
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
// Content is too large, cap the height
|
|
274
|
+
container.style.height = `${maxModalHeight}px`;
|
|
275
|
+
content.style.height = `${maxModalHeight - headerHeight}px`;
|
|
276
|
+
content.style.overflowY = 'auto';
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
};
|
|
280
|
+
// Handle window resize
|
|
281
|
+
const handleResize = () => {
|
|
282
|
+
// Store current opacity values before applying new styles
|
|
283
|
+
const currentOpacity = container.style.opacity;
|
|
284
|
+
const currentTransform = container.style.transform;
|
|
285
|
+
applyResponsiveStyles();
|
|
286
|
+
updateContentStyles();
|
|
287
|
+
// Restore opacity and transform to maintain visibility
|
|
288
|
+
container.style.opacity = currentOpacity;
|
|
289
|
+
container.style.transform = currentTransform;
|
|
290
|
+
// For auto-fit mode, also adjust the height
|
|
291
|
+
if (mode === 'auto-fit') {
|
|
292
|
+
adjustAutoFitHeight();
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
// Set up mutation observer to detect content changes
|
|
296
|
+
const contentObserver = new MutationObserver((mutations) => {
|
|
297
|
+
// When content changes, adjust the height
|
|
298
|
+
if (mode === 'auto-fit') {
|
|
299
|
+
// Small delay to ensure content has rendered
|
|
300
|
+
setTimeout(adjustAutoFitHeight, 50);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
// Configure and start the mutation observer
|
|
304
|
+
contentObserver.observe(content, {
|
|
305
|
+
childList: true, // Watch for changes to child elements
|
|
306
|
+
subtree: true, // Watch the entire subtree
|
|
307
|
+
characterData: true, // Watch for changes to text content
|
|
308
|
+
attributes: true, // Watch for changes to attributes
|
|
309
|
+
});
|
|
310
|
+
// For auto-fit mode, set up resize observer for content element
|
|
311
|
+
let resizeObserver = null;
|
|
312
|
+
if (mode === 'auto-fit') {
|
|
313
|
+
resizeObserver = new ResizeObserver(() => {
|
|
314
|
+
adjustAutoFitHeight();
|
|
315
|
+
});
|
|
316
|
+
resizeObserver.observe(content);
|
|
317
|
+
}
|
|
318
|
+
// Add window resize listener
|
|
319
|
+
window.addEventListener('resize', handleResize);
|
|
320
|
+
// Create a function to manually trigger height adjustment
|
|
321
|
+
const updateModalSize = () => {
|
|
322
|
+
if (mode === 'auto-fit') {
|
|
323
|
+
adjustAutoFitHeight();
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
return {
|
|
327
|
+
containerId,
|
|
328
|
+
getContentElement: () => document.getElementById(`${containerId}-content`),
|
|
329
|
+
updateModalSize, // Expose function to manually update size
|
|
330
|
+
cleanup: () => {
|
|
331
|
+
window.removeEventListener('resize', handleResize);
|
|
332
|
+
if (resizeObserver) {
|
|
333
|
+
resizeObserver.disconnect();
|
|
334
|
+
}
|
|
335
|
+
contentObserver.disconnect();
|
|
336
|
+
},
|
|
337
|
+
};
|
|
338
|
+
}, [closeThreedsModal]);
|
|
339
|
+
return {
|
|
340
|
+
createThreedsModal,
|
|
341
|
+
closeThreedsModal,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hooks and components for TagadaPay Plugin SDK v2
|
|
3
|
+
* Uses core functions for business logic
|
|
4
|
+
*/
|
|
5
|
+
export { TagadaProvider, useTagadaContext } from './providers/TagadaProvider';
|
|
6
|
+
export { useCheckoutToken } from './hooks/useCheckoutToken';
|
|
7
|
+
export { usePluginConfig } from './hooks/usePluginConfig';
|
|
8
|
+
export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
|
|
9
|
+
export { useGeoLocation } from './hooks/useGeoLocation';
|
|
10
|
+
export { useISOData, getAvailableLanguages, useLanguageImport, useCountryOptions, useRegionOptions } from './hooks/useISOData';
|
|
11
|
+
export { useCheckoutQuery as useCheckout } from './hooks/useCheckoutQuery';
|
|
12
|
+
export { useOrderBumpQuery as useOrderBump } from './hooks/useOrderBumpQuery';
|
|
13
|
+
export { usePromotionsQuery as usePromotions } from './hooks/usePromotionsQuery';
|
|
14
|
+
export { useProductsQuery as useProducts } from './hooks/useProductsQuery';
|
|
15
|
+
export { useOrderQuery as useOrder } from './hooks/useOrderQuery';
|
|
16
|
+
export { usePostPurchasesQuery as usePostPurchases } from './hooks/usePostPurchasesQuery';
|
|
17
|
+
export { useOffersQuery as useOffers } from './hooks/useOffersQuery';
|
|
18
|
+
export { usePaymentQuery as usePayment } from './hooks/usePaymentQuery';
|
|
19
|
+
export { useThreeds } from './hooks/useThreeds';
|
|
20
|
+
export { useThreedsModal } from './hooks/useThreedsModal';
|
|
21
|
+
export { useCurrency } from './hooks/useCurrency';
|
|
22
|
+
export { useApiQuery, useApiMutation, useInvalidateQuery, usePreloadQuery, queryKeys } from './hooks/useApiQuery';
|
|
23
|
+
export type { UseCheckoutTokenOptions, UseCheckoutTokenResult } from './hooks/useCheckoutToken';
|
|
24
|
+
export type { UsePluginConfigOptions, UsePluginConfigResult } from './hooks/usePluginConfig';
|
|
25
|
+
export type { UseGoogleAutocompleteOptions, UseGoogleAutocompleteResult, GooglePrediction, GooglePlaceDetails, ExtractedAddress } from './hooks/useGoogleAutocomplete';
|
|
26
|
+
export type { UseGeoLocationOptions, UseGeoLocationReturn, GeoLocationData } from './hooks/useGeoLocation';
|
|
27
|
+
export type { UseISODataResult, ISOCountry, ISORegion } from './hooks/useISOData';
|
|
28
|
+
export type { UseCheckoutQueryOptions as UseCheckoutOptions, UseCheckoutQueryResult as UseCheckoutResult } from './hooks/useCheckoutQuery';
|
|
29
|
+
export type { UseOrderBumpQueryOptions as UseOrderBumpOptions, UseOrderBumpQueryResult as UseOrderBumpResult } from './hooks/useOrderBumpQuery';
|
|
30
|
+
export type { UsePromotionsQueryOptions as UsePromotionsOptions, UsePromotionsQueryResult as UsePromotionsResult } from './hooks/usePromotionsQuery';
|
|
31
|
+
export type { UseProductsQueryOptions as UseProductsOptions, UseProductsQueryResult as UseProductsResult } from './hooks/useProductsQuery';
|
|
32
|
+
export type { UseOrderQueryOptions as UseOrderOptions, UseOrderQueryResult as UseOrderResult } from './hooks/useOrderQuery';
|
|
33
|
+
export type { UsePostPurchasesQueryOptions as UsePostPurchasesOptions, UsePostPurchasesQueryResult as UsePostPurchasesResult } from './hooks/usePostPurchasesQuery';
|
|
34
|
+
export type { UseOffersQueryOptions as UseOffersOptions, UseOffersQueryResult as UseOffersResult } from './hooks/useOffersQuery';
|
|
35
|
+
export type { PaymentHook as UsePaymentResult } from './hooks/usePaymentQuery';
|
|
36
|
+
export type { ThreedsProvider, PaymentInstrument, ThreedsSession, ThreedsChallenge, ThreedsOptions, ThreedsHook } from './hooks/useThreeds';
|
|
37
|
+
export { formatMoney } from '../../react/utils/money';
|
|
38
|
+
export type OrderItem = import('../core/utils/order').OrderLineItem;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React hooks and components for TagadaPay Plugin SDK v2
|
|
3
|
+
* Uses core functions for business logic
|
|
4
|
+
*/
|
|
5
|
+
// Provider
|
|
6
|
+
export { TagadaProvider, useTagadaContext } from './providers/TagadaProvider';
|
|
7
|
+
// Hooks
|
|
8
|
+
export { useCheckoutToken } from './hooks/useCheckoutToken';
|
|
9
|
+
export { usePluginConfig } from './hooks/usePluginConfig';
|
|
10
|
+
export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
|
|
11
|
+
export { useGeoLocation } from './hooks/useGeoLocation';
|
|
12
|
+
export { useISOData, getAvailableLanguages, useLanguageImport, useCountryOptions, useRegionOptions } from './hooks/useISOData';
|
|
13
|
+
// TanStack Query hooks (recommended)
|
|
14
|
+
export { useCheckoutQuery as useCheckout } from './hooks/useCheckoutQuery';
|
|
15
|
+
export { useOrderBumpQuery as useOrderBump } from './hooks/useOrderBumpQuery';
|
|
16
|
+
export { usePromotionsQuery as usePromotions } from './hooks/usePromotionsQuery';
|
|
17
|
+
export { useProductsQuery as useProducts } from './hooks/useProductsQuery';
|
|
18
|
+
export { useOrderQuery as useOrder } from './hooks/useOrderQuery';
|
|
19
|
+
export { usePostPurchasesQuery as usePostPurchases } from './hooks/usePostPurchasesQuery';
|
|
20
|
+
export { useOffersQuery as useOffers } from './hooks/useOffersQuery';
|
|
21
|
+
export { usePaymentQuery as usePayment } from './hooks/usePaymentQuery';
|
|
22
|
+
export { useThreeds } from './hooks/useThreeds';
|
|
23
|
+
export { useThreedsModal } from './hooks/useThreedsModal';
|
|
24
|
+
export { useCurrency } from './hooks/useCurrency';
|
|
25
|
+
export { useApiQuery, useApiMutation, useInvalidateQuery, usePreloadQuery, queryKeys } from './hooks/useApiQuery';
|
|
26
|
+
// Re-export utilities from main react
|
|
27
|
+
export { formatMoney } from '../../react/utils/money';
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TagadaProvider - Main provider component for the Tagada Pay React SDK
|
|
3
|
+
*/
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
import { PluginConfig, RawPluginConfig } from '../../../react/hooks/usePluginConfig';
|
|
6
|
+
import { ApiService } from '../../../react/services/apiService';
|
|
7
|
+
import { AuthState, Currency, Customer, Environment, EnvironmentConfig, Locale, Session, Store } from '../../../react/types';
|
|
8
|
+
import { convertCurrency, formatMoney, formatMoneyWithoutSymbol, formatSimpleMoney, getCurrencyInfo, minorUnitsToMajorUnits, moneyStringOrNumberToMinorUnits } from '../../../react/utils/money';
|
|
9
|
+
interface TagadaContextValue {
|
|
10
|
+
auth: AuthState;
|
|
11
|
+
session: Session | null;
|
|
12
|
+
customer: Customer | null;
|
|
13
|
+
locale: Locale;
|
|
14
|
+
currency: Currency;
|
|
15
|
+
store: Store | null;
|
|
16
|
+
environment: EnvironmentConfig;
|
|
17
|
+
apiService: ApiService;
|
|
18
|
+
isLoading: boolean;
|
|
19
|
+
isInitialized: boolean;
|
|
20
|
+
isSessionInitialized: boolean;
|
|
21
|
+
debugMode: boolean;
|
|
22
|
+
pluginConfig: PluginConfig;
|
|
23
|
+
pluginConfigLoading: boolean;
|
|
24
|
+
debugCheckout: {
|
|
25
|
+
isActive: boolean;
|
|
26
|
+
data: any;
|
|
27
|
+
error: Error | null;
|
|
28
|
+
isLoading: boolean;
|
|
29
|
+
lastUpdated: Date | null;
|
|
30
|
+
};
|
|
31
|
+
updateCheckoutDebugData: (data: any, error?: Error | null, isLoading?: boolean) => void;
|
|
32
|
+
refreshCoordinator: {
|
|
33
|
+
registerCheckoutRefresh: (refreshFn: () => Promise<void>, name?: string) => void;
|
|
34
|
+
registerOrderBumpRefresh: (refreshFn: () => Promise<void>) => void;
|
|
35
|
+
notifyCheckoutChanged: () => Promise<void>;
|
|
36
|
+
notifyOrderBumpChanged: () => Promise<void>;
|
|
37
|
+
unregisterCheckoutRefresh: (refreshFn?: () => Promise<void>) => void;
|
|
38
|
+
unregisterOrderBumpRefresh: () => void;
|
|
39
|
+
};
|
|
40
|
+
money: {
|
|
41
|
+
formatMoney: typeof formatMoney;
|
|
42
|
+
getCurrencyInfo: typeof getCurrencyInfo;
|
|
43
|
+
moneyStringOrNumberToMinorUnits: typeof moneyStringOrNumberToMinorUnits;
|
|
44
|
+
minorUnitsToMajorUnits: typeof minorUnitsToMajorUnits;
|
|
45
|
+
formatMoneyWithoutSymbol: typeof formatMoneyWithoutSymbol;
|
|
46
|
+
convertCurrency: typeof convertCurrency;
|
|
47
|
+
formatSimpleMoney: typeof formatSimpleMoney;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
interface TagadaProviderProps {
|
|
51
|
+
children: ReactNode;
|
|
52
|
+
environment?: Environment;
|
|
53
|
+
customApiConfig?: Partial<EnvironmentConfig>;
|
|
54
|
+
debugMode?: boolean;
|
|
55
|
+
localConfig?: string;
|
|
56
|
+
blockUntilSessionReady?: boolean;
|
|
57
|
+
rawPluginConfig?: RawPluginConfig;
|
|
58
|
+
}
|
|
59
|
+
export declare function TagadaProvider({ children, environment, customApiConfig, debugMode, // Remove default, will be set based on environment
|
|
60
|
+
localConfig, blockUntilSessionReady, // Default to new non-blocking behavior
|
|
61
|
+
rawPluginConfig, }: TagadaProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
62
|
+
export declare function useTagadaContext(): TagadaContextValue;
|
|
63
|
+
export {};
|