@tagadapay/plugin-sdk 3.0.3 → 3.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/build-cdn.js +113 -0
  2. package/dist/config/basisTheory.d.ts +26 -0
  3. package/dist/config/basisTheory.js +29 -0
  4. package/dist/external-tracker.js +5072 -0
  5. package/dist/external-tracker.min.js +11 -0
  6. package/dist/external-tracker.min.js.map +7 -0
  7. package/dist/react/config/payment.d.ts +8 -8
  8. package/dist/react/config/payment.js +17 -21
  9. package/dist/react/hooks/useApplePay.js +1 -1
  10. package/dist/react/hooks/usePayment.js +1 -3
  11. package/dist/react/hooks/useThreeds.js +2 -2
  12. package/dist/v2/core/client.d.ts +30 -3
  13. package/dist/v2/core/client.js +326 -8
  14. package/dist/v2/core/config/environment.d.ts +16 -3
  15. package/dist/v2/core/config/environment.js +72 -3
  16. package/dist/v2/core/funnelClient.d.ts +4 -0
  17. package/dist/v2/core/funnelClient.js +106 -4
  18. package/dist/v2/core/resources/funnel.d.ts +22 -0
  19. package/dist/v2/core/resources/offers.d.ts +64 -3
  20. package/dist/v2/core/resources/offers.js +112 -10
  21. package/dist/v2/core/resources/postPurchases.js +4 -1
  22. package/dist/v2/core/utils/configHotReload.d.ts +39 -0
  23. package/dist/v2/core/utils/configHotReload.js +75 -0
  24. package/dist/v2/core/utils/eventBus.d.ts +11 -0
  25. package/dist/v2/core/utils/eventBus.js +34 -0
  26. package/dist/v2/core/utils/pluginConfig.d.ts +14 -5
  27. package/dist/v2/core/utils/pluginConfig.js +74 -59
  28. package/dist/v2/core/utils/previewMode.d.ts +114 -0
  29. package/dist/v2/core/utils/previewMode.js +379 -0
  30. package/dist/v2/core/utils/sessionStorage.d.ts +5 -0
  31. package/dist/v2/core/utils/sessionStorage.js +22 -0
  32. package/dist/v2/index.d.ts +4 -1
  33. package/dist/v2/index.js +3 -1
  34. package/dist/v2/react/components/DebugDrawer.js +68 -46
  35. package/dist/v2/react/hooks/useOfferQuery.js +50 -17
  36. package/dist/v2/react/hooks/usePaymentQuery.js +1 -3
  37. package/dist/v2/react/hooks/usePreviewOffer.d.ts +84 -0
  38. package/dist/v2/react/hooks/usePreviewOffer.js +290 -0
  39. package/dist/v2/react/hooks/useThreeds.js +2 -2
  40. package/dist/v2/react/index.d.ts +2 -0
  41. package/dist/v2/react/index.js +1 -0
  42. package/dist/v2/react/providers/TagadaProvider.js +49 -32
  43. package/dist/v2/standalone/external-tracker.d.ts +119 -0
  44. package/dist/v2/standalone/external-tracker.js +260 -0
  45. package/dist/v2/standalone/index.d.ts +2 -0
  46. package/dist/v2/standalone/index.js +6 -0
  47. package/package.json +11 -3
  48. package/dist/v2/react/hooks/useOffersQuery.d.ts +0 -12
  49. package/dist/v2/react/hooks/useOffersQuery.js +0 -404
@@ -0,0 +1,379 @@
1
+ /**
2
+ * SDK Override Parameters
3
+ *
4
+ * Centralized parameter management for SDK behavior overrides.
5
+ * Parameters can come from URL query params, localStorage, or cookies.
6
+ *
7
+ * Key concepts:
8
+ * - forceReset: Clears all stored state (localStorage, cookies) - simulates hard refresh
9
+ * - draft: Marks customers/sessions as draft (for staging/preview/testing)
10
+ * - funnelTracking: Controls whether funnel events are tracked
11
+ * - tagadaClientEnv: Forces specific environment (production/development/local) - overrides auto-detection
12
+ * - tagadaClientBaseUrl: Forces custom API base URL - overrides environment-based URL
13
+ * - token: Authentication token (URL > localStorage)
14
+ * - funnelSessionId: Active funnel session (URL > cookie)
15
+ *
16
+ * Usage examples:
17
+ * - Force production API: ?tagadaClientEnv=production
18
+ * - Force development API: ?tagadaClientEnv=development
19
+ * - Force local API: ?tagadaClientEnv=local
20
+ * - Custom API URL: ?tagadaClientBaseUrl=https://tagada.loclx.io
21
+ * - Combined: ?tagadaClientEnv=local&tagadaClientBaseUrl=https://tagada.loclx.io
22
+ * - Hard reset + production: ?forceReset=true&tagadaClientEnv=production
23
+ */
24
+ import { clearClientToken, setClientToken, getClientToken } from './tokenStorage';
25
+ import { clearFunnelSessionCookie } from './sessionStorage';
26
+ // Storage keys for SDK override params
27
+ const STORAGE_KEYS = {
28
+ DRAFT: 'tgd_draft',
29
+ FUNNEL_TRACKING: 'tgd_funnel_tracking',
30
+ FORCE_RESET: 'tgd_force_reset',
31
+ CLIENT_ENV: 'tgd_client_env',
32
+ CLIENT_BASE_URL: 'tgd_client_base_url',
33
+ };
34
+ /**
35
+ * Check if force reset is active (simulates hard refresh)
36
+ */
37
+ export function isForceReset() {
38
+ if (typeof window === 'undefined')
39
+ return false;
40
+ const params = new URLSearchParams(window.location.search);
41
+ return params.get('forceReset') === 'true';
42
+ }
43
+ /**
44
+ * Get value from localStorage with fallback
45
+ */
46
+ function getFromStorage(key) {
47
+ if (typeof window === 'undefined')
48
+ return null;
49
+ try {
50
+ return localStorage.getItem(key);
51
+ }
52
+ catch {
53
+ return null;
54
+ }
55
+ }
56
+ /**
57
+ * Set value in localStorage
58
+ */
59
+ function setInStorage(key, value) {
60
+ if (typeof window === 'undefined')
61
+ return;
62
+ try {
63
+ localStorage.setItem(key, value);
64
+ }
65
+ catch {
66
+ // Storage not available
67
+ }
68
+ }
69
+ /**
70
+ * Get value from cookie
71
+ */
72
+ function getFromCookie(key) {
73
+ if (typeof document === 'undefined')
74
+ return null;
75
+ const cookies = document.cookie.split(';');
76
+ const cookie = cookies.find(c => c.trim().startsWith(`${key}=`));
77
+ return cookie ? cookie.split('=')[1]?.trim() : null;
78
+ }
79
+ /**
80
+ * Set value in cookie
81
+ */
82
+ function setInCookie(key, value, maxAge = 86400) {
83
+ if (typeof document === 'undefined')
84
+ return;
85
+ document.cookie = `${key}=${value}; path=/; max-age=${maxAge}`;
86
+ }
87
+ /**
88
+ * Clear value from cookie
89
+ */
90
+ function clearFromCookie(key) {
91
+ if (typeof document === 'undefined')
92
+ return;
93
+ document.cookie = `${key}=; path=/; max-age=0`;
94
+ }
95
+ /**
96
+ * Get SDK override parameters from all sources (URL, localStorage, cookies)
97
+ * Priority: URL > localStorage > Cookie
98
+ */
99
+ export function getSDKParams() {
100
+ if (typeof window === 'undefined') {
101
+ return {};
102
+ }
103
+ const urlParams = new URLSearchParams(window.location.search);
104
+ // Get draft mode (URL > localStorage > cookie)
105
+ let draft;
106
+ const urlDraft = urlParams.get('draft');
107
+ if (urlDraft !== null) {
108
+ draft = urlDraft === 'true';
109
+ }
110
+ else {
111
+ const storageDraft = getFromStorage(STORAGE_KEYS.DRAFT) || getFromCookie(STORAGE_KEYS.DRAFT);
112
+ if (storageDraft !== null) {
113
+ draft = storageDraft === 'true';
114
+ }
115
+ }
116
+ // Get funnel tracking (URL > localStorage > cookie, default true)
117
+ let funnelTracking;
118
+ const urlTracking = urlParams.get('funnelTracking');
119
+ if (urlTracking !== null) {
120
+ funnelTracking = urlTracking !== 'false';
121
+ }
122
+ else {
123
+ const storageTracking = getFromStorage(STORAGE_KEYS.FUNNEL_TRACKING) || getFromCookie(STORAGE_KEYS.FUNNEL_TRACKING);
124
+ if (storageTracking !== null) {
125
+ funnelTracking = storageTracking !== 'false';
126
+ }
127
+ }
128
+ // Get token (URL > localStorage)
129
+ const token = urlParams.get('token') || getClientToken() || null;
130
+ // Get funnel session ID (URL only, cookie handled elsewhere)
131
+ const funnelSessionId = urlParams.get('funnelSessionId') || null;
132
+ // Get funnel ID (URL only)
133
+ const funnelId = urlParams.get('funnelId') || null;
134
+ // Force reset is URL-only (not persisted)
135
+ const forceReset = urlParams.get('forceReset') === 'true';
136
+ // Get client environment override (URL > localStorage > cookie)
137
+ let tagadaClientEnv;
138
+ const urlEnv = urlParams.get('tagadaClientEnv');
139
+ if (urlEnv && (urlEnv === 'production' || urlEnv === 'development' || urlEnv === 'local')) {
140
+ tagadaClientEnv = urlEnv;
141
+ }
142
+ else {
143
+ const storageEnv = getFromStorage(STORAGE_KEYS.CLIENT_ENV) || getFromCookie(STORAGE_KEYS.CLIENT_ENV);
144
+ if (storageEnv && (storageEnv === 'production' || storageEnv === 'development' || storageEnv === 'local')) {
145
+ tagadaClientEnv = storageEnv;
146
+ }
147
+ }
148
+ // Get custom API base URL override (URL > localStorage > cookie)
149
+ let tagadaClientBaseUrl;
150
+ const urlBaseUrl = urlParams.get('tagadaClientBaseUrl');
151
+ if (urlBaseUrl) {
152
+ tagadaClientBaseUrl = urlBaseUrl;
153
+ }
154
+ else {
155
+ const storageBaseUrl = getFromStorage(STORAGE_KEYS.CLIENT_BASE_URL) || getFromCookie(STORAGE_KEYS.CLIENT_BASE_URL);
156
+ if (storageBaseUrl) {
157
+ tagadaClientBaseUrl = storageBaseUrl;
158
+ }
159
+ }
160
+ return {
161
+ forceReset,
162
+ token,
163
+ funnelSessionId,
164
+ funnelId,
165
+ draft,
166
+ funnelTracking,
167
+ tagadaClientEnv,
168
+ tagadaClientBaseUrl,
169
+ };
170
+ }
171
+ /**
172
+ * Legacy alias for backward compatibility
173
+ * @deprecated Use getSDKParams() instead
174
+ */
175
+ export function getPreviewParams() {
176
+ return getSDKParams();
177
+ }
178
+ /**
179
+ * Check if draft mode is active
180
+ * Uses centralized getSDKParams()
181
+ */
182
+ export function isDraftMode() {
183
+ const params = getSDKParams();
184
+ return params.draft ?? false;
185
+ }
186
+ /**
187
+ * Set draft mode in storage for persistence
188
+ */
189
+ export function setDraftMode(draft) {
190
+ if (typeof window === 'undefined')
191
+ return;
192
+ if (draft) {
193
+ setInStorage(STORAGE_KEYS.DRAFT, 'true');
194
+ setInCookie(STORAGE_KEYS.DRAFT, 'true', 86400); // 24 hours
195
+ }
196
+ else {
197
+ setInStorage(STORAGE_KEYS.DRAFT, 'false');
198
+ clearFromCookie(STORAGE_KEYS.DRAFT);
199
+ }
200
+ }
201
+ /**
202
+ * Initialize SDK with override parameters
203
+ *
204
+ * This function handles SDK initialization based on override params:
205
+ * 1. If forceReset flag is set: Clear all stored state (simulates hard refresh)
206
+ * 2. If token in URL: Use it (override localStorage)
207
+ * 3. If draft in URL: Persist it to storage
208
+ * 4. If funnelTracking in URL: Persist it to storage
209
+ *
210
+ * @returns True if force reset was activated and state was cleared
211
+ */
212
+ export function handlePreviewMode(debugMode = false) {
213
+ const params = getSDKParams();
214
+ const shouldReset = params.forceReset || false;
215
+ if (!shouldReset && !params.token) {
216
+ // Not forcing reset and no explicit token override
217
+ // But still persist draft/tracking if in URL
218
+ persistSDKParamsFromURL();
219
+ return false;
220
+ }
221
+ if (debugMode) {
222
+ console.log('[SDK] Detected params:', params);
223
+ }
224
+ // CASE 1: Force reset - clear all state (simulates hard refresh)
225
+ if (shouldReset) {
226
+ if (debugMode) {
227
+ console.log('[SDK] Force reset: Clearing all stored state');
228
+ }
229
+ clearClientToken();
230
+ clearFunnelSessionCookie();
231
+ // Clear all tagadapay-related localStorage keys
232
+ if (typeof window !== 'undefined' && window.localStorage) {
233
+ const keys = Object.keys(localStorage);
234
+ keys.forEach(key => {
235
+ if (key.startsWith('tagadapay_') || key.startsWith('tgd_')) {
236
+ if (debugMode) {
237
+ console.log(`[SDK] Clearing localStorage: ${key}`);
238
+ }
239
+ localStorage.removeItem(key);
240
+ }
241
+ });
242
+ }
243
+ }
244
+ // CASE 2: Token in URL - override stored token
245
+ if (params.token !== null && params.token !== undefined) {
246
+ if (debugMode) {
247
+ console.log('[SDK] Using token from URL:', params.token.substring(0, 20) + '...');
248
+ }
249
+ if (params.token === '' || params.token === 'null') {
250
+ // Explicitly cleared token
251
+ clearClientToken();
252
+ }
253
+ else {
254
+ // Set token from URL
255
+ setClientToken(params.token);
256
+ }
257
+ }
258
+ else if (shouldReset) {
259
+ // Force reset but no token = clear stored token
260
+ if (debugMode) {
261
+ console.log('[SDK] Force reset mode (no token)');
262
+ }
263
+ clearClientToken();
264
+ }
265
+ // CASE 3: Persist URL params to storage
266
+ persistSDKParamsFromURL();
267
+ // CASE 4: Funnel session ID in URL - will be used by FunnelClient
268
+ if (params.funnelSessionId && debugMode) {
269
+ console.log('[SDK] Using funnelSessionId from URL:', params.funnelSessionId);
270
+ }
271
+ return shouldReset;
272
+ }
273
+ /**
274
+ * Persist SDK parameters from URL to storage
275
+ * This ensures params survive page navigation
276
+ */
277
+ function persistSDKParamsFromURL() {
278
+ if (typeof window === 'undefined')
279
+ return;
280
+ const urlParams = new URLSearchParams(window.location.search);
281
+ // Persist draft mode if in URL
282
+ const urlDraft = urlParams.get('draft');
283
+ if (urlDraft !== null) {
284
+ setDraftMode(urlDraft === 'true');
285
+ }
286
+ // Persist funnel tracking if in URL
287
+ const urlTracking = urlParams.get('funnelTracking');
288
+ if (urlTracking !== null) {
289
+ setFunnelTracking(urlTracking !== 'false');
290
+ }
291
+ // Persist client environment if in URL
292
+ const urlEnv = urlParams.get('tagadaClientEnv');
293
+ if (urlEnv && (urlEnv === 'production' || urlEnv === 'development' || urlEnv === 'local')) {
294
+ setClientEnvironment(urlEnv);
295
+ }
296
+ // Persist custom base URL if in URL
297
+ const urlBaseUrl = urlParams.get('tagadaClientBaseUrl');
298
+ if (urlBaseUrl) {
299
+ setClientBaseUrl(urlBaseUrl);
300
+ }
301
+ }
302
+ /**
303
+ * Set funnel tracking mode in storage for persistence
304
+ */
305
+ export function setFunnelTracking(enabled) {
306
+ if (typeof window === 'undefined')
307
+ return;
308
+ const value = enabled ? 'true' : 'false';
309
+ setInStorage(STORAGE_KEYS.FUNNEL_TRACKING, value);
310
+ setInCookie(STORAGE_KEYS.FUNNEL_TRACKING, value, 86400); // 24 hours
311
+ }
312
+ /**
313
+ * Set client environment override in storage for persistence
314
+ */
315
+ export function setClientEnvironment(env) {
316
+ if (typeof window === 'undefined')
317
+ return;
318
+ setInStorage(STORAGE_KEYS.CLIENT_ENV, env);
319
+ setInCookie(STORAGE_KEYS.CLIENT_ENV, env, 86400); // 24 hours
320
+ }
321
+ /**
322
+ * Clear client environment override
323
+ */
324
+ export function clearClientEnvironment() {
325
+ if (typeof window === 'undefined')
326
+ return;
327
+ try {
328
+ localStorage.removeItem(STORAGE_KEYS.CLIENT_ENV);
329
+ clearFromCookie(STORAGE_KEYS.CLIENT_ENV);
330
+ }
331
+ catch {
332
+ // Storage not available
333
+ }
334
+ }
335
+ /**
336
+ * Set custom API base URL override in storage for persistence
337
+ */
338
+ export function setClientBaseUrl(baseUrl) {
339
+ if (typeof window === 'undefined')
340
+ return;
341
+ setInStorage(STORAGE_KEYS.CLIENT_BASE_URL, baseUrl);
342
+ setInCookie(STORAGE_KEYS.CLIENT_BASE_URL, baseUrl, 86400); // 24 hours
343
+ }
344
+ /**
345
+ * Clear custom API base URL override
346
+ */
347
+ export function clearClientBaseUrl() {
348
+ if (typeof window === 'undefined')
349
+ return;
350
+ try {
351
+ localStorage.removeItem(STORAGE_KEYS.CLIENT_BASE_URL);
352
+ clearFromCookie(STORAGE_KEYS.CLIENT_BASE_URL);
353
+ }
354
+ catch {
355
+ // Storage not available
356
+ }
357
+ }
358
+ /**
359
+ * Check if we should use URL params over stored values
360
+ *
361
+ * Returns true if:
362
+ * - Force reset is active, OR
363
+ * - Explicit token/sessionId in URL (indicating intentional override)
364
+ */
365
+ export function shouldUseUrlParams() {
366
+ const params = getSDKParams();
367
+ return !!(params.forceReset ||
368
+ params.token !== null ||
369
+ params.funnelSessionId !== null);
370
+ }
371
+ /**
372
+ * Check if funnel tracking is enabled
373
+ * Uses centralized getSDKParams()
374
+ * Default is true for normal operations
375
+ */
376
+ export function isFunnelTrackingEnabled() {
377
+ const params = getSDKParams();
378
+ return params.funnelTracking ?? true; // Default true
379
+ }
@@ -18,3 +18,8 @@ export declare function clearFunnelSessionCookie(): void;
18
18
  * Check if a funnel session cookie exists
19
19
  */
20
20
  export declare function hasFunnelSessionCookie(): boolean;
21
+ /**
22
+ * Retrieve funnel variant ID from sticky session (for A/B tracking)
23
+ * The variant ID is stored in the sticky session metadata by plugin-routing
24
+ */
25
+ export declare function getFunnelVariantId(): string | undefined;
@@ -3,6 +3,7 @@
3
3
  * Handles session persistence using browser cookies
4
4
  */
5
5
  const FUNNEL_SESSION_COOKIE_NAME = 'tgd-funnel-session-id';
6
+ const STICKY_SESSION_COOKIE_NAME = 'tgd-session-id';
6
7
  const SESSION_MAX_AGE = 30 * 24 * 60 * 60; // 30 days
7
8
  /**
8
9
  * Save funnel session ID to browser cookie
@@ -37,3 +38,24 @@ export function clearFunnelSessionCookie() {
37
38
  export function hasFunnelSessionCookie() {
38
39
  return !!getFunnelSessionCookie();
39
40
  }
41
+ /**
42
+ * Retrieve funnel variant ID from sticky session (for A/B tracking)
43
+ * The variant ID is stored in the sticky session metadata by plugin-routing
44
+ */
45
+ export function getFunnelVariantId() {
46
+ if (typeof document === 'undefined')
47
+ return undefined;
48
+ try {
49
+ const cookie = document.cookie
50
+ .split('; ')
51
+ .find((row) => row.startsWith(`${STICKY_SESSION_COOKIE_NAME}=`));
52
+ if (!cookie)
53
+ return undefined;
54
+ const sessionData = JSON.parse(decodeURIComponent(cookie.split('=')[1]));
55
+ return sessionData?.metadata?.funnelVariantId;
56
+ }
57
+ catch (error) {
58
+ console.warn('Failed to parse sticky session for variant ID:', error);
59
+ return undefined;
60
+ }
61
+ }
@@ -10,6 +10,8 @@ export * from './core/isoData';
10
10
  export * from './core/utils/currency';
11
11
  export * from './core/utils/pluginConfig';
12
12
  export * from './core/utils/products';
13
+ export * from './core/utils/previewMode';
14
+ export * from './core/utils/configHotReload';
13
15
  export * from './core/pathRemapping';
14
16
  export type { CheckoutData, CheckoutInitParams, CheckoutLineItem, CheckoutSession, CheckoutSessionPreview, Promotion } from './core/resources/checkout';
15
17
  export type { Order, OrderLineItem } from './core/utils/order';
@@ -23,7 +25,7 @@ export type { ToggleOrderBumpResponse, VipOffer, VipPreviewResponse } from './co
23
25
  export type { StoreConfig } from './core/resources/storeConfig';
24
26
  export { FunnelActionType } from './core/resources/funnel';
25
27
  export type { BackNavigationActionData, CartUpdatedActionData, DirectNavigationActionData, FormSubmitActionData, FunnelContextUpdateRequest, FunnelContextUpdateResponse, FunnelAction as FunnelEvent, FunnelInitializeRequest, FunnelInitializeResponse, FunnelNavigateRequest, FunnelNavigateResponse, FunnelNavigationAction, FunnelNavigationResult, NextAction, OfferAcceptedActionData, OfferDeclinedActionData, PaymentFailedActionData, PaymentSuccessActionData, SimpleFunnelContext } from './core/resources/funnel';
26
- export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCredits, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useFunnelLegacy, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useLogin, useOffer, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';
28
+ export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCredits, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useFunnelLegacy, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useLogin, useOffer, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, usePreviewOffer, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';
27
29
  export type { DebugScript } from './react';
28
30
  export type { TranslateFunction, TranslationText, UseTranslationOptions, UseTranslationResult } from './react/hooks/useTranslation';
29
31
  export type { FunnelContextValue } from './react/hooks/useFunnel';
@@ -36,3 +38,4 @@ export type { UseCustomerInfosOptions, UseCustomerInfosResult } from './react/ho
36
38
  export type { UseCustomerOrdersOptions, UseCustomerOrdersResult } from './react/hooks/useCustomerOrders';
37
39
  export type { UseCustomerSubscriptionsOptions, UseCustomerSubscriptionsResult } from './react/hooks/useCustomerSubscriptions';
38
40
  export type { UseShippingRatesQueryOptions, UseShippingRatesQueryResult } from './react/hooks/useShippingRatesQuery';
41
+ export type { PreviewOfferSummary, UsePreviewOfferOptions, UsePreviewOfferResult } from './react/hooks/usePreviewOffer';
package/dist/v2/index.js CHANGED
@@ -11,8 +11,10 @@ export * from './core/isoData';
11
11
  export * from './core/utils/currency';
12
12
  export * from './core/utils/pluginConfig';
13
13
  export * from './core/utils/products';
14
+ export * from './core/utils/previewMode';
15
+ export * from './core/utils/configHotReload';
14
16
  // Path remapping helpers (framework-agnostic)
15
17
  export * from './core/pathRemapping';
16
18
  export { FunnelActionType } from './core/resources/funnel';
17
19
  // React exports (hooks and components only, types are exported above)
18
- export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCredits, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useFunnelLegacy, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useLogin, useOffer, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';
20
+ export { ApplePayButton, ExpressPaymentMethodsProvider, formatMoney, getAvailableLanguages, GooglePayButton, queryKeys, TagadaProvider, useApiMutation, useApiQuery, useAuth, useCheckout, useCheckoutToken, useClubOffers, useCountryOptions, useCredits, useCurrency, useCustomer, useCustomerInfos, useCustomerOrders, useCustomerSubscriptions, useDiscounts, useExpressPaymentMethods, useFunnel, useFunnelLegacy, useGeoLocation, useGoogleAutocomplete, useInvalidateQuery, useISOData, useLanguageImport, useLogin, useOffer, useOrder, useOrderBump, usePayment, usePluginConfig, usePostPurchases, usePreloadQuery, usePreviewOffer, useProducts, usePromotions, useRegionOptions, useRemappableParams, useShippingRates, useSimpleFunnel, useStoreConfig, useTagadaContext, useThreeds, useThreedsModal, useTranslation, useVipOffers } from './react';
@@ -79,6 +79,7 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
79
79
  const [activeTab, setActiveTab] = useState('overview');
80
80
  const [runningScripts, setRunningScripts] = useState(new Set());
81
81
  const [scriptResults, setScriptResults] = useState({});
82
+ const [expandedScriptCategories, setExpandedScriptCategories] = useState({});
82
83
  // Handler to jump to a specific step using direct_navigation
83
84
  const handleJumpToStep = async (stepId, stepName) => {
84
85
  // Try to get sessionId from debug data or context
@@ -187,8 +188,9 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
187
188
  const script = context.debugScripts?.find((s) => s.id === scriptId);
188
189
  if (!script)
189
190
  return;
191
+ // Clear previous script results so only the current script shows a status
192
+ setScriptResults({});
190
193
  setRunningScripts((prev) => new Set(prev).add(scriptId));
191
- setScriptResults((prev) => ({ ...prev, [scriptId]: undefined }));
192
194
  try {
193
195
  await script.run(context);
194
196
  setScriptResults((prev) => ({
@@ -733,51 +735,71 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
733
735
  acc[category].push(script);
734
736
  return acc;
735
737
  }, {});
736
- return Object.entries(grouped).map(([category, scripts]) => (_jsxs("div", { children: [_jsx("div", { style: {
737
- fontSize: '11px',
738
- color: '#9ca3af',
739
- fontWeight: 'bold',
740
- marginBottom: '8px',
741
- textTransform: 'uppercase',
742
- letterSpacing: '0.5px',
743
- }, children: category }), _jsx("div", { style: { display: 'grid', gap: '8px' }, children: scripts.map((script) => {
744
- const isRunning = runningScripts.has(script.id);
745
- const result = scriptResults[script.id];
746
- return (_jsxs("div", { style: {
747
- border: '1px solid #374151',
748
- borderRadius: '6px',
749
- padding: '10px 12px',
750
- backgroundColor: '#111827',
751
- }, children: [_jsxs("div", { style: {
752
- display: 'flex',
753
- justifyContent: 'space-between',
754
- alignItems: 'flex-start',
755
- gap: '12px',
756
- }, children: [_jsxs("div", { style: { flex: 1 }, children: [_jsx("div", { style: {
757
- color: '#f9fafb',
758
- fontWeight: 'bold',
759
- fontSize: '12px',
760
- marginBottom: '4px',
761
- }, children: script.name }), script.description && (_jsx("div", { style: { fontSize: '11px', color: '#9ca3af' }, children: script.description }))] }), _jsx("button", { onClick: () => handleRunScript(script.id), disabled: isRunning, style: {
762
- backgroundColor: isRunning ? '#374151' : '#3b82f6',
763
- color: '#fff',
764
- border: 'none',
765
- borderRadius: '4px',
766
- padding: '6px 12px',
767
- fontSize: '11px',
768
- fontWeight: 'bold',
769
- cursor: isRunning ? 'not-allowed' : 'pointer',
770
- transition: 'background-color 0.2s',
771
- minWidth: '60px',
772
- }, children: isRunning ? '' : '▶ Run' })] }), result && (_jsxs("div", { style: {
773
- marginTop: '8px',
774
- padding: '6px 8px',
775
- borderRadius: '4px',
776
- fontSize: '10px',
777
- backgroundColor: result.success ? '#065f46' : '#7f1d1d',
778
- color: result.success ? '#6ee7b7' : '#fca5a5',
779
- }, children: [result.success ? '' : '❌', " ", result.message] }))] }, script.id));
780
- }) })] }, category)));
738
+ return Object.entries(grouped).map(([category, scripts]) => {
739
+ const isExpanded = expandedScriptCategories[category] ?? false;
740
+ const toggleCategory = () => {
741
+ setExpandedScriptCategories((prev) => ({
742
+ ...prev,
743
+ [category]: !(prev[category] ?? false),
744
+ }));
745
+ };
746
+ return (_jsxs("div", { children: [_jsx("button", { type: "button", onClick: toggleCategory, style: {
747
+ display: 'flex',
748
+ alignItems: 'center',
749
+ justifyContent: 'space-between',
750
+ width: '100%',
751
+ background: 'none',
752
+ border: 'none',
753
+ padding: '6px 0',
754
+ cursor: 'pointer',
755
+ }, children: _jsxs("div", { style: {
756
+ display: 'flex',
757
+ alignItems: 'center',
758
+ gap: '6px',
759
+ fontSize: '11px',
760
+ fontWeight: 'bold',
761
+ textTransform: 'uppercase',
762
+ letterSpacing: '0.5px',
763
+ color: '#9ca3af',
764
+ }, children: [_jsx("span", { style: { fontSize: '10px' }, children: isExpanded ? '' : '▶' }), _jsx("span", { children: category }), _jsxs("span", { style: { fontSize: '10px', color: '#6b7280' }, children: ["(", scripts.length, ")"] })] }) }), isExpanded && (_jsx("div", { style: { display: 'grid', gap: '8px', marginTop: '4px' }, children: scripts.map((script) => {
765
+ const isRunning = runningScripts.has(script.id);
766
+ const result = scriptResults[script.id];
767
+ return (_jsxs("div", { style: {
768
+ border: '1px solid #374151',
769
+ borderRadius: '6px',
770
+ padding: '10px 12px',
771
+ backgroundColor: '#111827',
772
+ }, children: [_jsxs("div", { style: {
773
+ display: 'flex',
774
+ justifyContent: 'space-between',
775
+ alignItems: 'flex-start',
776
+ gap: '12px',
777
+ }, children: [_jsxs("div", { style: { flex: 1 }, children: [_jsx("div", { style: {
778
+ color: '#f9fafb',
779
+ fontWeight: 'bold',
780
+ fontSize: '12px',
781
+ marginBottom: '4px',
782
+ }, children: script.name }), script.description && (_jsx("div", { style: { fontSize: '11px', color: '#9ca3af' }, children: script.description }))] }), _jsx("button", { onClick: () => handleRunScript(script.id), disabled: isRunning, style: {
783
+ backgroundColor: isRunning ? '#374151' : '#3b82f6',
784
+ color: '#fff',
785
+ border: 'none',
786
+ borderRadius: '4px',
787
+ padding: '6px 12px',
788
+ fontSize: '11px',
789
+ fontWeight: 'bold',
790
+ cursor: isRunning ? 'not-allowed' : 'pointer',
791
+ transition: 'background-color 0.2s',
792
+ minWidth: '60px',
793
+ }, children: isRunning ? '⏳' : '▶ Run' })] }), result && (_jsxs("div", { style: {
794
+ marginTop: '8px',
795
+ padding: '6px 8px',
796
+ borderRadius: '4px',
797
+ fontSize: '10px',
798
+ backgroundColor: result.success ? '#065f46' : '#7f1d1d',
799
+ color: result.success ? '#6ee7b7' : '#fca5a5',
800
+ }, children: [result.success ? '✅' : '❌', " ", result.message] }))] }, script.id));
801
+ }) }))] }, category));
802
+ });
781
803
  })() })) : (_jsx("p", { style: { color: '#6b7280' }, children: "No debug scripts available" }))] })), activeTab === 'raw' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Raw Context Data" }), _jsx("div", { style: { fontSize: '12px' }, children: _jsx(TreeView, { data: context, name: "tagadaContext", maxLevel: 4 }) })] }))] })] })] }));
782
804
  };
783
805
  export default DebugDrawer;