@tagadapay/plugin-sdk 2.8.8 → 2.8.10

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 (43) hide show
  1. package/dist/react/config/environment.d.ts +1 -22
  2. package/dist/react/config/environment.js +1 -132
  3. package/dist/react/utils/deviceInfo.d.ts +1 -39
  4. package/dist/react/utils/deviceInfo.js +1 -163
  5. package/dist/react/utils/jwtDecoder.d.ts +1 -14
  6. package/dist/react/utils/jwtDecoder.js +1 -86
  7. package/dist/react/utils/tokenStorage.d.ts +1 -16
  8. package/dist/react/utils/tokenStorage.js +1 -53
  9. package/dist/v2/core/client.d.ts +96 -0
  10. package/dist/v2/core/client.js +430 -0
  11. package/dist/v2/core/config/environment.d.ts +36 -0
  12. package/dist/v2/core/config/environment.js +155 -0
  13. package/dist/v2/core/pathRemapping.js +61 -3
  14. package/dist/v2/core/resources/apiClient.d.ts +13 -0
  15. package/dist/v2/core/resources/apiClient.js +77 -9
  16. package/dist/v2/core/resources/funnel.d.ts +21 -0
  17. package/dist/v2/core/resources/payments.d.ts +23 -0
  18. package/dist/v2/core/types.d.ts +271 -0
  19. package/dist/v2/core/types.js +4 -0
  20. package/dist/v2/core/utils/deviceInfo.d.ts +39 -0
  21. package/dist/v2/core/utils/deviceInfo.js +162 -0
  22. package/dist/v2/core/utils/eventDispatcher.d.ts +10 -0
  23. package/dist/v2/core/utils/eventDispatcher.js +24 -0
  24. package/dist/v2/core/utils/jwtDecoder.d.ts +14 -0
  25. package/dist/v2/core/utils/jwtDecoder.js +85 -0
  26. package/dist/v2/core/utils/pluginConfig.d.ts +1 -0
  27. package/dist/v2/core/utils/pluginConfig.js +64 -8
  28. package/dist/v2/core/utils/tokenStorage.d.ts +19 -0
  29. package/dist/v2/core/utils/tokenStorage.js +52 -0
  30. package/dist/v2/react/components/ApplePayButton.js +1 -1
  31. package/dist/v2/react/components/DebugDrawer.js +90 -1
  32. package/dist/v2/react/hooks/__examples__/FunnelContextExample.d.ts +12 -0
  33. package/dist/v2/react/hooks/__examples__/FunnelContextExample.js +54 -0
  34. package/dist/v2/react/hooks/useFunnel.d.ts +2 -1
  35. package/dist/v2/react/hooks/useFunnel.js +245 -69
  36. package/dist/v2/react/hooks/useGoogleAutocomplete.js +26 -18
  37. package/dist/v2/react/hooks/useISOData.js +4 -2
  38. package/dist/v2/react/hooks/useOffersQuery.d.ts +42 -29
  39. package/dist/v2/react/hooks/useOffersQuery.js +266 -204
  40. package/dist/v2/react/hooks/usePaymentQuery.js +99 -6
  41. package/dist/v2/react/providers/TagadaProvider.d.ts +13 -21
  42. package/dist/v2/react/providers/TagadaProvider.js +79 -673
  43. package/package.json +1 -1
@@ -0,0 +1,162 @@
1
+ /**
2
+ * Get basic browser information from user agent
3
+ */
4
+ function getBrowserInfo() {
5
+ const userAgent = navigator.userAgent;
6
+ // Chrome
7
+ if (userAgent.includes('Chrome')) {
8
+ const match = /Chrome\/(\d+)/.exec(userAgent);
9
+ return { name: 'Chrome', version: match ? match[1] : 'unknown' };
10
+ }
11
+ // Firefox
12
+ if (userAgent.includes('Firefox')) {
13
+ const match = /Firefox\/(\d+)/.exec(userAgent);
14
+ return { name: 'Firefox', version: match ? match[1] : 'unknown' };
15
+ }
16
+ // Safari
17
+ if (userAgent.includes('Safari') && !userAgent.includes('Chrome')) {
18
+ const match = /Version\/(\d+)/.exec(userAgent);
19
+ return { name: 'Safari', version: match ? match[1] : 'unknown' };
20
+ }
21
+ // Edge
22
+ if (userAgent.includes('Edge')) {
23
+ const match = /Edge\/(\d+)/.exec(userAgent);
24
+ return { name: 'Edge', version: match ? match[1] : 'unknown' };
25
+ }
26
+ return { name: 'unknown', version: 'unknown' };
27
+ }
28
+ /**
29
+ * Get basic OS information from user agent
30
+ */
31
+ function getOSInfo() {
32
+ const userAgent = navigator.userAgent;
33
+ // Windows
34
+ if (userAgent.includes('Windows')) {
35
+ if (userAgent.includes('Windows NT 10.0'))
36
+ return { name: 'Windows', version: '10' };
37
+ if (userAgent.includes('Windows NT 6.3'))
38
+ return { name: 'Windows', version: '8.1' };
39
+ if (userAgent.includes('Windows NT 6.2'))
40
+ return { name: 'Windows', version: '8' };
41
+ if (userAgent.includes('Windows NT 6.1'))
42
+ return { name: 'Windows', version: '7' };
43
+ return { name: 'Windows', version: 'unknown' };
44
+ }
45
+ // macOS
46
+ if (userAgent.includes('Mac OS X')) {
47
+ const match = /Mac OS X (\d+[._]\d+)/.exec(userAgent);
48
+ return { name: 'macOS', version: match ? match[1].replace('_', '.') : 'unknown' };
49
+ }
50
+ // iOS
51
+ if (userAgent.includes('iPhone') || userAgent.includes('iPad')) {
52
+ const match = /OS (\d+[._]\d+)/.exec(userAgent);
53
+ return { name: 'iOS', version: match ? match[1].replace('_', '.') : 'unknown' };
54
+ }
55
+ // Android
56
+ if (userAgent.includes('Android')) {
57
+ const match = /Android (\d+[.\d]*)/.exec(userAgent);
58
+ return { name: 'Android', version: match ? match[1] : 'unknown' };
59
+ }
60
+ // Linux
61
+ if (userAgent.includes('Linux')) {
62
+ return { name: 'Linux', version: 'unknown' };
63
+ }
64
+ return { name: 'unknown', version: 'unknown' };
65
+ }
66
+ /**
67
+ * Get device information
68
+ */
69
+ function getDeviceInfo() {
70
+ const userAgent = navigator.userAgent;
71
+ // Mobile devices
72
+ if (userAgent.includes('iPhone')) {
73
+ return { type: 'mobile', model: 'iPhone' };
74
+ }
75
+ if (userAgent.includes('iPad')) {
76
+ return { type: 'tablet', model: 'iPad' };
77
+ }
78
+ if (userAgent.includes('Android')) {
79
+ if (userAgent.includes('Mobile')) {
80
+ return { type: 'mobile', model: 'Android' };
81
+ }
82
+ else {
83
+ return { type: 'tablet', model: 'Android' };
84
+ }
85
+ }
86
+ // Desktop (no specific device info)
87
+ return undefined;
88
+ }
89
+ /**
90
+ * Get screen resolution
91
+ */
92
+ function getScreenResolution() {
93
+ return {
94
+ width: window.screen.width,
95
+ height: window.screen.height,
96
+ };
97
+ }
98
+ /**
99
+ * Get timezone
100
+ */
101
+ function getTimeZone() {
102
+ try {
103
+ return Intl.DateTimeFormat().resolvedOptions().timeZone;
104
+ }
105
+ catch (error) {
106
+ console.error('Failed to get timezone:', error);
107
+ return 'UTC';
108
+ }
109
+ }
110
+ /**
111
+ * Get browser locale
112
+ */
113
+ export function getBrowserLocale() {
114
+ try {
115
+ return navigator.language || 'en-US';
116
+ }
117
+ catch (error) {
118
+ console.error('Failed to get browser locale:', error);
119
+ return 'en-US';
120
+ }
121
+ }
122
+ /**
123
+ * Collect all device information
124
+ */
125
+ export function collectDeviceInfo() {
126
+ if (typeof window === 'undefined') {
127
+ // Server-side fallback
128
+ return {
129
+ userAgent: {
130
+ browser: { name: 'unknown', version: 'unknown' },
131
+ os: { name: 'unknown', version: 'unknown' },
132
+ },
133
+ screenResolution: { width: 0, height: 0 },
134
+ timeZone: 'UTC',
135
+ };
136
+ }
137
+ return {
138
+ userAgent: {
139
+ browser: getBrowserInfo(),
140
+ os: getOSInfo(),
141
+ device: getDeviceInfo(),
142
+ },
143
+ screenResolution: getScreenResolution(),
144
+ timeZone: getTimeZone(),
145
+ };
146
+ }
147
+ /**
148
+ * Get URL parameters for session initialization
149
+ */
150
+ export function getUrlParams() {
151
+ if (typeof window === 'undefined') {
152
+ return {};
153
+ }
154
+ const params = new URLSearchParams(window.location.search);
155
+ return {
156
+ locale: params.get('locale') || undefined,
157
+ currency: params.get('currency') || undefined,
158
+ utmSource: params.get('utm_source') || undefined,
159
+ utmMedium: params.get('utm_medium') || undefined,
160
+ utmCampaign: params.get('utm_campaign') || undefined,
161
+ };
162
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Simple event dispatcher for handling state changes in the SDK
3
+ */
4
+ export type Listener<T> = (data: T) => void;
5
+ export declare class EventDispatcher<T> {
6
+ private listeners;
7
+ subscribe(listener: Listener<T>): () => void;
8
+ notify(data: T): void;
9
+ clear(): void;
10
+ }
@@ -0,0 +1,24 @@
1
+ export class EventDispatcher {
2
+ constructor() {
3
+ this.listeners = new Set();
4
+ }
5
+ subscribe(listener) {
6
+ this.listeners.add(listener);
7
+ return () => {
8
+ this.listeners.delete(listener);
9
+ };
10
+ }
11
+ notify(data) {
12
+ this.listeners.forEach((listener) => {
13
+ try {
14
+ listener(data);
15
+ }
16
+ catch (error) {
17
+ console.error('Error in event listener:', error);
18
+ }
19
+ });
20
+ }
21
+ clear() {
22
+ this.listeners.clear();
23
+ }
24
+ }
@@ -0,0 +1,14 @@
1
+ import { Session } from '../types';
2
+ /**
3
+ * Decode a JWT token to extract session information
4
+ * This is a simple client-side decoder - do not use for security validation
5
+ */
6
+ export declare function decodeJWTClient(token: string): Session | null;
7
+ /**
8
+ * Check if a JWT token is expired
9
+ */
10
+ export declare function isTokenExpired(token: string): boolean;
11
+ /**
12
+ * Get token expiration time
13
+ */
14
+ export declare function getTokenExpiration(token: string): Date | null;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * Decode a JWT token to extract session information
3
+ * This is a simple client-side decoder - do not use for security validation
4
+ */
5
+ export function decodeJWTClient(token) {
6
+ try {
7
+ // Split the token into parts
8
+ const parts = token.split('.');
9
+ if (parts.length !== 3) {
10
+ console.error('Invalid JWT token format');
11
+ return null;
12
+ }
13
+ // Decode the payload (second part)
14
+ const payload = parts[1];
15
+ // Add padding if needed
16
+ const paddedPayload = payload + '='.repeat((4 - (payload.length % 4)) % 4);
17
+ // Decode base64
18
+ const decoded = atob(paddedPayload);
19
+ // Parse JSON
20
+ const parsedPayload = JSON.parse(decoded);
21
+ // Check if token is expired
22
+ if (parsedPayload.exp && Date.now() >= parsedPayload.exp * 1000) {
23
+ console.warn('JWT token is expired');
24
+ return null;
25
+ }
26
+ // Return session data
27
+ return {
28
+ sessionId: parsedPayload.sessionId,
29
+ storeId: parsedPayload.storeId,
30
+ accountId: parsedPayload.accountId,
31
+ customerId: parsedPayload.customerId,
32
+ role: parsedPayload.role,
33
+ isValid: true,
34
+ isLoading: false,
35
+ };
36
+ }
37
+ catch (error) {
38
+ console.error('Failed to decode JWT token:', error);
39
+ return null;
40
+ }
41
+ }
42
+ /**
43
+ * Check if a JWT token is expired
44
+ */
45
+ export function isTokenExpired(token) {
46
+ try {
47
+ const parts = token.split('.');
48
+ if (parts.length !== 3)
49
+ return true;
50
+ const payload = parts[1];
51
+ const paddedPayload = payload + '='.repeat((4 - (payload.length % 4)) % 4);
52
+ const decoded = atob(paddedPayload);
53
+ const parsedPayload = JSON.parse(decoded);
54
+ if (parsedPayload.exp) {
55
+ return Date.now() >= parsedPayload.exp * 1000;
56
+ }
57
+ return false;
58
+ }
59
+ catch (error) {
60
+ console.error('Failed to check token expiration:', error);
61
+ return true;
62
+ }
63
+ }
64
+ /**
65
+ * Get token expiration time
66
+ */
67
+ export function getTokenExpiration(token) {
68
+ try {
69
+ const parts = token.split('.');
70
+ if (parts.length !== 3)
71
+ return null;
72
+ const payload = parts[1];
73
+ const paddedPayload = payload + '='.repeat((4 - (payload.length % 4)) % 4);
74
+ const decoded = atob(paddedPayload);
75
+ const parsedPayload = JSON.parse(decoded);
76
+ if (parsedPayload.exp) {
77
+ return new Date(parsedPayload.exp * 1000);
78
+ }
79
+ return null;
80
+ }
81
+ catch (error) {
82
+ console.error('Failed to get token expiration:', error);
83
+ return null;
84
+ }
85
+ }
@@ -7,6 +7,7 @@ export type PluginConfig<TConfig = Record<string, any>> = {
7
7
  accountId?: string;
8
8
  basePath?: string;
9
9
  config?: any;
10
+ staticResources?: Record<string, any>;
10
11
  productId?: string;
11
12
  variants?: Record<string, string>;
12
13
  prices?: Record<string, any>;
@@ -8,13 +8,19 @@ import { resolveEnvValue } from './env';
8
8
  */
9
9
  const loadLocalDevConfig = async (configVariant = 'default') => {
10
10
  try {
11
- // Only try to load local config in development
12
- // Use hostname-based detection for better Vite compatibility
11
+ // Check for explicit environment override
12
+ const env = resolveEnvValue('TAGADA_ENV') || resolveEnvValue('TAGADA_ENVIRONMENT');
13
+ if (env === 'production') {
14
+ // Skip local config loading if explicitly in production mode
15
+ return null;
16
+ }
17
+ // Only try to load local config in TRUE local development (not deployed CDN instances)
18
+ // Exclude CDN subdomains (e.g., instance-id.cdn.localhost) by checking for 'cdn.' prefix
13
19
  const isLocalDev = typeof window !== 'undefined' &&
14
20
  (window.location.hostname === 'localhost' ||
15
- window.location.hostname.includes('ngrok-free.app') ||
16
- window.location.hostname.includes('.localhost') ||
17
- window.location.hostname.includes('127.0.0.1'));
21
+ window.location.hostname === '127.0.0.1' ||
22
+ window.location.hostname.includes('ngrok-free.app')) &&
23
+ !window.location.hostname.includes('.cdn.');
18
24
  if (!isLocalDev) {
19
25
  return null;
20
26
  }
@@ -81,6 +87,43 @@ const loadLocalDevConfig = async (configVariant = 'default') => {
81
87
  return null;
82
88
  }
83
89
  };
90
+ /**
91
+ * Load static resources for local development
92
+ * Loads /config/resources.static.json
93
+ */
94
+ const loadStaticResources = async () => {
95
+ try {
96
+ // Check for explicit environment override
97
+ const env = resolveEnvValue('TAGADA_ENV') || resolveEnvValue('TAGADA_ENVIRONMENT');
98
+ if (env === 'production') {
99
+ return null;
100
+ }
101
+ // Only try to load in TRUE local development (not deployed CDN instances)
102
+ // Exclude CDN subdomains (e.g., instance-id.cdn.localhost) by checking for 'cdn.' prefix
103
+ const isLocalDev = typeof window !== 'undefined' &&
104
+ (window.location.hostname === 'localhost' ||
105
+ window.location.hostname === '127.0.0.1' ||
106
+ window.location.hostname.includes('ngrok-free.app')) &&
107
+ !window.location.hostname.includes('.cdn.');
108
+ if (!isLocalDev) {
109
+ return null;
110
+ }
111
+ // Load static resources file
112
+ console.log('🛠️ Attempting to load /config/resources.static.json...');
113
+ const response = await fetch('/config/resources.static.json');
114
+ if (!response.ok) {
115
+ console.log('🛠️ resources.static.json not found or failed to load');
116
+ return null;
117
+ }
118
+ const staticResources = await response.json();
119
+ console.log('🛠️ ✅ Loaded local static resources:', staticResources);
120
+ return staticResources;
121
+ }
122
+ catch (error) {
123
+ console.error('🛠️ ❌ Error loading static resources:', error);
124
+ return null;
125
+ }
126
+ };
84
127
  /**
85
128
  * Helper to get content from meta tag
86
129
  */
@@ -137,6 +180,8 @@ const loadProductionConfig = async () => {
137
180
  * Handles local dev, production, and raw config
138
181
  */
139
182
  export const loadPluginConfig = async (configVariant = 'default', rawConfig) => {
183
+ // Load static resources first (only in local dev)
184
+ const staticResources = await loadStaticResources();
140
185
  // If raw config is provided, use it directly
141
186
  if (rawConfig) {
142
187
  return {
@@ -144,21 +189,32 @@ export const loadPluginConfig = async (configVariant = 'default', rawConfig) =>
144
189
  accountId: rawConfig.accountId,
145
190
  basePath: rawConfig.basePath ?? '/',
146
191
  config: rawConfig.config ?? {},
192
+ staticResources: staticResources ?? undefined,
147
193
  };
148
194
  }
149
195
  else {
150
196
  const rawConfig = await createRawPluginConfig();
151
197
  if (rawConfig) {
152
- return rawConfig;
198
+ return {
199
+ ...rawConfig,
200
+ staticResources: staticResources ?? undefined,
201
+ };
153
202
  }
154
203
  }
155
204
  // Try local development config
156
205
  const localConfig = await loadLocalDevConfig(configVariant);
157
206
  if (localConfig) {
158
- return localConfig;
207
+ return {
208
+ ...localConfig,
209
+ staticResources: staticResources ?? undefined,
210
+ };
159
211
  }
160
212
  // Fall back to production config
161
- return loadProductionConfig();
213
+ const productionConfig = await loadProductionConfig();
214
+ return {
215
+ ...productionConfig,
216
+ staticResources: staticResources ?? undefined,
217
+ };
162
218
  };
163
219
  /**
164
220
  * Helper to load local config file for development (from /config directory)
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Client-side token storage utilities
3
+ */
4
+ /**
5
+ * Set the CMS token in localStorage
6
+ */
7
+ export declare function setClientToken(token: string): void;
8
+ /**
9
+ * Get the CMS token from localStorage
10
+ */
11
+ export declare function getClientToken(): string | null;
12
+ /**
13
+ * Clear the CMS token from localStorage
14
+ */
15
+ export declare function clearClientToken(): void;
16
+ /**
17
+ * Check if a token exists in localStorage
18
+ */
19
+ export declare function hasClientToken(): boolean;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Client-side token storage utilities
3
+ */
4
+ const TOKEN_KEY = 'cms_token';
5
+ /**
6
+ * Set the CMS token in localStorage
7
+ */
8
+ export function setClientToken(token) {
9
+ if (typeof window !== 'undefined') {
10
+ try {
11
+ localStorage.setItem(TOKEN_KEY, token);
12
+ window.dispatchEvent(new Event('storage'));
13
+ }
14
+ catch (error) {
15
+ console.error('Failed to save token to localStorage:', error);
16
+ }
17
+ }
18
+ }
19
+ /**
20
+ * Get the CMS token from localStorage
21
+ */
22
+ export function getClientToken() {
23
+ if (typeof window !== 'undefined') {
24
+ try {
25
+ return localStorage.getItem(TOKEN_KEY);
26
+ }
27
+ catch (error) {
28
+ console.error('Failed to get token from localStorage:', error);
29
+ return null;
30
+ }
31
+ }
32
+ return null;
33
+ }
34
+ /**
35
+ * Clear the CMS token from localStorage
36
+ */
37
+ export function clearClientToken() {
38
+ if (typeof window !== 'undefined') {
39
+ try {
40
+ localStorage.removeItem(TOKEN_KEY);
41
+ }
42
+ catch (error) {
43
+ console.error('Failed to clear token from localStorage:', error);
44
+ }
45
+ }
46
+ }
47
+ /**
48
+ * Check if a token exists in localStorage
49
+ */
50
+ export function hasClientToken() {
51
+ return !!getClientToken();
52
+ }
@@ -5,7 +5,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
5
5
  */
6
6
  import { useCallback, useEffect, useState } from 'react';
7
7
  import { useExpressPaymentMethods } from '../hooks/useExpressPaymentMethods';
8
- export const ApplePayButton = ({ className = '', disabled = false, onSuccess, onError, onCancel, storeName, currencyCode = 'USD', variant = 'outline', size = 'lg', checkout, }) => {
8
+ export const ApplePayButton = ({ className = '', disabled = false, onSuccess, onError, onCancel, storeName, currencyCode = 'USD', variant = 'default', size = 'lg', checkout, }) => {
9
9
  const { applePayPaymentMethod, shippingMethods, lineItems, handleAddExpressId, updateCheckoutSessionValues, updateCustomerEmail, reComputeOrderSummary, setError: setContextError, } = useExpressPaymentMethods();
10
10
  const [processingPayment, setProcessingPayment] = useState(false);
11
11
  const [isApplePayAvailable, setIsApplePayAvailable] = useState(false);
@@ -582,7 +582,96 @@ export const DebugDrawer = ({ isOpen, onClose }) => {
582
582
  color: isCurrent ? '#d1fae5' : '#9ca3af',
583
583
  marginLeft: '8px',
584
584
  }, children: ["\u2022 ", cond.type, " \u2192 ", cond.nextStepId] }, condIdx)))] }))] }, step.id));
585
- }) })] })), _jsxs("div", { style: { marginTop: '12px' }, children: [_jsx("h4", { style: { margin: '0 0 8px 0', color: '#60a5fa', fontSize: '13px' }, children: "\uD83D\uDD0D Raw Data" }), _jsx("div", { style: { fontSize: '11px' }, children: _jsx(TreeView, { data: context.debugFunnel.data, name: "funnelData" }) })] })] })) : (_jsx("p", { style: { color: '#6b7280' }, children: "No funnel hook active" }))] })), activeTab === 'checkout' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Checkout Debug" }), context.debugCheckout.isActive ? (_jsxs("div", { children: [_jsxs("div", { style: { marginBottom: '20px' }, children: [_jsx("h4", { style: { margin: '0 0 12px 0', color: '#60a5fa' }, children: "Status" }), _jsxs("div", { style: { display: 'grid', gap: '8px' }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Hook Active:" }), _jsx("span", { style: { color: '#10b981' }, children: "\u2705 Yes" })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Loading:" }), _jsx("span", { style: { color: context.debugCheckout.isLoading ? '#f59e0b' : '#10b981' }, children: context.debugCheckout.isLoading ? '⏳ Yes' : '✅ No' })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Has Error:" }), _jsx("span", { style: { color: context.debugCheckout.error ? '#ef4444' : '#10b981' }, children: context.debugCheckout.error ? '❌ Yes' : '✅ No' })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Last Updated:" }), _jsx("span", { style: { color: '#9ca3af', fontSize: '12px' }, children: context.debugCheckout.lastUpdated?.toLocaleTimeString() || 'Never' })] })] })] }), context.debugCheckout.error && (_jsxs("div", { style: { marginBottom: '20px' }, children: [_jsx("h4", { style: { margin: '0 0 12px 0', color: '#ef4444' }, children: "Error Details" }), _jsxs("div", { style: {
585
+ }) })] })), context.debugFunnel.data?.session && (_jsxs("div", { style: { marginBottom: '16px' }, children: [_jsx("h4", { style: { margin: '0 0 8px 0', color: '#60a5fa', fontSize: '13px' }, children: "\uD83D\uDCE6 Resources & Context" }), context.debugFunnel.data.session.resources &&
586
+ Object.keys(context.debugFunnel.data.session.resources).length > 0 && (_jsxs("div", { style: { marginBottom: '12px' }, children: [_jsxs("div", { style: {
587
+ fontSize: '11px',
588
+ color: '#10b981',
589
+ fontWeight: 'bold',
590
+ marginBottom: '6px',
591
+ }, children: ["\uD83C\uDFAF Available Resources (", Object.keys(context.debugFunnel.data.session.resources).length, ")"] }), _jsx("div", { style: { display: 'grid', gap: '8px' }, children: Object.entries(context.debugFunnel.data.session.resources).map(([key, value]) => {
592
+ // Skip undefined/null resources
593
+ if (value === undefined || value === null)
594
+ return null;
595
+ // Check if it's an array or single resource
596
+ const isArray = Array.isArray(value);
597
+ const resourceCount = isArray ? value.length : 1;
598
+ return (_jsxs("div", { style: {
599
+ border: '1px solid #374151',
600
+ borderRadius: '6px',
601
+ padding: '10px',
602
+ backgroundColor: '#111827',
603
+ }, children: [_jsxs("div", { style: {
604
+ display: 'flex',
605
+ justifyContent: 'space-between',
606
+ alignItems: 'center',
607
+ marginBottom: '8px',
608
+ }, children: [_jsxs("div", { style: { display: 'flex', alignItems: 'center', gap: '6px' }, children: [_jsx("span", { style: { color: '#10b981', fontSize: '14px' }, children: key === 'order' || key === 'mainOrder'
609
+ ? '🛒'
610
+ : key === 'customer'
611
+ ? '👤'
612
+ : key === 'checkout'
613
+ ? '💳'
614
+ : key === 'offer'
615
+ ? '🎁'
616
+ : key === 'subscription'
617
+ ? '🔄'
618
+ : '📄' }), _jsx("span", { style: {
619
+ color: '#f9fafb',
620
+ fontWeight: 'bold',
621
+ fontSize: '12px',
622
+ }, children: key }), isArray && (_jsxs("span", { style: {
623
+ fontSize: '10px',
624
+ backgroundColor: '#3b82f6',
625
+ color: '#fff',
626
+ padding: '2px 6px',
627
+ borderRadius: '3px',
628
+ }, children: [resourceCount, " items"] }))] }), !isArray && value && typeof value === 'object' && (_jsx("div", { style: { fontSize: '10px', color: '#9ca3af' }, children: value.id && (_jsx("span", { style: { fontFamily: 'monospace' }, children: value.id })) }))] }), !isArray && value && typeof value === 'object' && (_jsxs("div", { style: {
629
+ display: 'grid',
630
+ gridTemplateColumns: '1fr 1fr',
631
+ gap: '6px',
632
+ fontSize: '11px',
633
+ marginBottom: '8px',
634
+ }, children: [value.amount !== undefined && (_jsxs("div", { children: [_jsx("span", { style: { color: '#6b7280' }, children: "Amount: " }), _jsx("span", { style: { color: '#10b981', fontWeight: 'bold' }, children: (() => {
635
+ try {
636
+ return context.money.formatMoney(Number(value.amount) || 0, String(value.currency) || 'USD', context.locale.locale);
637
+ }
638
+ catch {
639
+ return `${value.amount} ${value.currency || ''}`;
640
+ }
641
+ })() })] })), value.email !== undefined && (_jsxs("div", { children: [_jsx("span", { style: { color: '#6b7280' }, children: "Email: " }), _jsx("span", { style: { color: '#60a5fa' }, children: value.email })] })), value.status !== undefined && (_jsxs("div", { children: [_jsx("span", { style: { color: '#6b7280' }, children: "Status: " }), _jsx("span", { style: { color: '#f59e0b' }, children: value.status })] })), value.currency !== undefined && (_jsxs("div", { children: [_jsx("span", { style: { color: '#6b7280' }, children: "Currency: " }), _jsx("span", { style: { color: '#8b5cf6' }, children: value.currency })] }))] })), _jsxs("details", { style: { marginTop: '6px' }, children: [_jsx("summary", { style: {
642
+ cursor: 'pointer',
643
+ fontSize: '10px',
644
+ color: '#60a5fa',
645
+ fontWeight: 'bold',
646
+ }, children: "Show Full Data" }), _jsx("div", { style: { marginTop: '6px', fontSize: '10px' }, children: _jsx(TreeView, { data: value, name: key, maxLevel: 3 }) })] })] }, key));
647
+ }) })] })), context.debugFunnel.data.session.metadata &&
648
+ Object.keys(context.debugFunnel.data.session.metadata).length > 0 && (_jsxs("div", { style: { marginBottom: '12px' }, children: [_jsxs("div", { style: {
649
+ fontSize: '11px',
650
+ color: '#8b5cf6',
651
+ fontWeight: 'bold',
652
+ marginBottom: '6px',
653
+ }, children: ["\uD83D\uDCDD Session Metadata (", Object.keys(context.debugFunnel.data.session.metadata).length, ")"] }), _jsx("div", { style: {
654
+ border: '1px solid #374151',
655
+ borderRadius: '6px',
656
+ padding: '10px',
657
+ backgroundColor: '#111827',
658
+ }, children: _jsx(TreeView, { data: context.debugFunnel.data.session.metadata, name: "metadata", maxLevel: 2 }) })] })), _jsxs("div", { style: { marginBottom: '12px' }, children: [_jsx("div", { style: {
659
+ fontSize: '11px',
660
+ color: '#f59e0b',
661
+ fontWeight: 'bold',
662
+ marginBottom: '6px',
663
+ }, children: "\u2139\uFE0F Session Context" }), _jsx("div", { style: {
664
+ border: '1px solid #374151',
665
+ borderRadius: '6px',
666
+ padding: '10px',
667
+ backgroundColor: '#111827',
668
+ }, children: _jsxs("div", { style: { display: 'grid', gap: '6px', fontSize: '11px' }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { style: { color: '#6b7280' }, children: "Customer ID:" }), _jsx("span", { style: { color: '#60a5fa', fontFamily: 'monospace', fontSize: '10px' }, children: context.debugFunnel.data.session.customerId })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { style: { color: '#6b7280' }, children: "Store ID:" }), _jsx("span", { style: { color: '#60a5fa', fontFamily: 'monospace', fontSize: '10px' }, children: context.debugFunnel.data.session.storeId })] }), context.debugFunnel.data.session.environment && (_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { style: { color: '#6b7280' }, children: "Environment:" }), _jsx("span", { style: { color: '#10b981' }, children: context.debugFunnel.data.session.environment })] })), context.debugFunnel.data.session.startedAt && (_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { style: { color: '#6b7280' }, children: "Started At:" }), _jsx("span", { style: { color: '#9ca3af', fontSize: '10px' }, children: new Date(context.debugFunnel.data.session.startedAt).toLocaleString() })] })), context.debugFunnel.data.session.lastActivityAt && (_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { style: { color: '#6b7280' }, children: "Last Activity:" }), _jsx("span", { style: { color: '#9ca3af', fontSize: '10px' }, children: new Date(context.debugFunnel.data.session.lastActivityAt).toLocaleString() })] }))] }) })] })] })), _jsxs("details", { style: { marginTop: '12px' }, children: [_jsx("summary", { style: {
669
+ cursor: 'pointer',
670
+ fontWeight: 'bold',
671
+ fontSize: '13px',
672
+ color: '#60a5fa',
673
+ marginBottom: '8px',
674
+ }, children: "\uD83D\uDD0D Raw Funnel Data (Debug)" }), _jsx("div", { style: { fontSize: '11px', marginTop: '8px' }, children: _jsx(TreeView, { data: context.debugFunnel.data, name: "funnelData", maxLevel: 4 }) })] })] })) : (_jsx("p", { style: { color: '#6b7280' }, children: "No funnel hook active" }))] })), activeTab === 'checkout' && (_jsxs("div", { children: [_jsx("h3", { style: { margin: '0 0 16px 0', color: '#60a5fa' }, children: "Checkout Debug" }), context.debugCheckout.isActive ? (_jsxs("div", { children: [_jsxs("div", { style: { marginBottom: '20px' }, children: [_jsx("h4", { style: { margin: '0 0 12px 0', color: '#60a5fa' }, children: "Status" }), _jsxs("div", { style: { display: 'grid', gap: '8px' }, children: [_jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Hook Active:" }), _jsx("span", { style: { color: '#10b981' }, children: "\u2705 Yes" })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Loading:" }), _jsx("span", { style: { color: context.debugCheckout.isLoading ? '#f59e0b' : '#10b981' }, children: context.debugCheckout.isLoading ? '⏳ Yes' : '✅ No' })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Has Error:" }), _jsx("span", { style: { color: context.debugCheckout.error ? '#ef4444' : '#10b981' }, children: context.debugCheckout.error ? '❌ Yes' : '✅ No' })] }), _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between' }, children: [_jsx("span", { children: "Last Updated:" }), _jsx("span", { style: { color: '#9ca3af', fontSize: '12px' }, children: context.debugCheckout.lastUpdated?.toLocaleTimeString() || 'Never' })] })] })] }), context.debugCheckout.error && (_jsxs("div", { style: { marginBottom: '20px' }, children: [_jsx("h4", { style: { margin: '0 0 12px 0', color: '#ef4444' }, children: "Error Details" }), _jsxs("div", { style: {
586
675
  backgroundColor: '#372c2c',
587
676
  padding: '12px',
588
677
  borderRadius: '4px',
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Example: Accessing Funnel Context & Resources
3
+ *
4
+ * This example demonstrates how to access data from previous steps
5
+ * using the funnel context, including order, customer, and other resources.
6
+ */
7
+ export declare function FunnelContextExample(): import("react/jsx-runtime").JSX.Element;
8
+ /**
9
+ * Simple example for documentation
10
+ * This can now be called with or without options
11
+ */
12
+ export declare function SimpleContextExample(): import("react/jsx-runtime").JSX.Element;