@tagadapay/plugin-sdk 2.1.0 โ†’ 2.1.3

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.
@@ -228,12 +228,7 @@ export interface CheckoutData {
228
228
  availablePromotions: Promotion[];
229
229
  }
230
230
  export interface UseCheckoutOptions {
231
- autoRefresh?: boolean;
232
- refreshInterval?: number;
233
- realTimeUpdates?: boolean;
234
- autoInitFromUrl?: boolean;
235
231
  checkoutToken?: string;
236
- fallbackToken?: string;
237
232
  autoLoadFromToken?: boolean;
238
233
  }
239
234
  export interface UseCheckoutResult {
@@ -1,27 +1,19 @@
1
1
  import { useCallback, useEffect, useRef, useState } from 'react';
2
2
  import { useCurrency } from '../hooks/useCurrency';
3
3
  import { useTagadaContext } from '../providers/TagadaProvider';
4
- import { getCheckoutToken } from '../utils/urlUtils';
5
4
  import { collectTrackingData } from '../utils/trackingUtils';
5
+ import { usePluginConfig } from './usePluginConfig';
6
6
  export function useCheckout(options = {}) {
7
- const { apiService, updateCheckoutDebugData, refreshCoordinator, store, currency } = useTagadaContext();
7
+ const { apiService, updateCheckoutDebugData, refreshCoordinator, currency } = useTagadaContext();
8
+ const { storeId } = usePluginConfig();
8
9
  const { code: currentCurrency } = useCurrency();
9
10
  const [checkout, setCheckout] = useState(null);
10
11
  const [isLoading, setIsLoading] = useState(false);
11
12
  const [error, setError] = useState(null);
12
13
  const [isInitialized, setIsInitialized] = useState(false);
13
- const { autoRefresh = false, refreshInterval = 30000, autoInitFromUrl = false, checkoutToken: providedToken, fallbackToken, autoLoadFromToken = true, } = options;
14
- const refreshTimeoutRef = useRef(null);
14
+ const { checkoutToken: providedToken, autoLoadFromToken = true, } = options;
15
15
  const currentCheckoutTokenRef = useRef(null);
16
16
  const hasAutoLoadedRef = useRef(false);
17
- // Clear refresh timeout on unmount
18
- useEffect(() => {
19
- return () => {
20
- if (refreshTimeoutRef.current) {
21
- clearTimeout(refreshTimeoutRef.current);
22
- }
23
- };
24
- }, []);
25
17
  // Update debug data whenever checkout state changes with comprehensive information
26
18
  useEffect(() => {
27
19
  const debugData = checkout
@@ -73,6 +65,7 @@ export function useCheckout(options = {}) {
73
65
  };
74
66
  const requestBody = {
75
67
  ...params,
68
+ storeId: params.storeId || storeId, // Use storeId from params or from usePluginConfig
76
69
  returnUrl: params.returnUrl || window.location.origin,
77
70
  customer: {
78
71
  ...params.customer,
@@ -111,7 +104,7 @@ export function useCheckout(options = {}) {
111
104
  finally {
112
105
  setIsLoading(false);
113
106
  }
114
- }, [apiService, currentCurrency, providedToken]);
107
+ }, [apiService, currentCurrency, providedToken, storeId]);
115
108
  const getCheckout = useCallback(async (checkoutToken) => {
116
109
  setIsLoading(true);
117
110
  setError(null);
@@ -425,7 +418,7 @@ export function useCheckout(options = {}) {
425
418
  method: 'POST',
426
419
  body: {
427
420
  lineItems,
428
- storeId: store?.id,
421
+ storeId,
429
422
  currency: currency.code,
430
423
  promotionIds: promotionIds ?? [],
431
424
  },
@@ -436,41 +429,31 @@ export function useCheckout(options = {}) {
436
429
  const error = err instanceof Error ? err : new Error('Failed to preview checkout session');
437
430
  throw error;
438
431
  }
439
- }, [apiService, checkout?.checkoutSession.storeId, checkout?.summary?.currency]);
432
+ }, [apiService, storeId, currency.code]);
440
433
  const clear = useCallback(() => {
441
434
  setCheckout(null);
442
435
  setError(null);
443
436
  setIsInitialized(false);
444
437
  currentCheckoutTokenRef.current = null;
445
438
  hasAutoLoadedRef.current = false;
446
- if (refreshTimeoutRef.current) {
447
- clearTimeout(refreshTimeoutRef.current);
448
- }
449
439
  }, []);
450
- // Auto-load existing checkout session from provided token or URL token
440
+ // Auto-load existing checkout session from provided token
451
441
  useEffect(() => {
452
- if (!autoLoadFromToken || hasAutoLoadedRef.current || isInitialized) {
442
+ if (!autoLoadFromToken || hasAutoLoadedRef.current || isInitialized || !providedToken) {
453
443
  return;
454
444
  }
455
- // Prioritize provided checkoutToken, then URL token, then fallback
456
- const token = providedToken ||
457
- getCheckoutToken({
458
- currentUrl: true,
459
- fallbackToken,
460
- });
461
- if (token && !isLoading) {
462
- console.debug('[Checkout] Auto-loading from token:', {
463
- source: providedToken ? 'provided' : 'url/fallback',
464
- tokenPreview: token.substring(0, 8) + '...',
445
+ if (!isLoading) {
446
+ console.debug('[Checkout] Auto-loading from provided token:', {
447
+ tokenPreview: providedToken.substring(0, 8) + '...',
465
448
  });
466
449
  hasAutoLoadedRef.current = true;
467
- getCheckout(token).catch((err) => {
450
+ getCheckout(providedToken).catch((err) => {
468
451
  console.error('Auto-load failed:', err);
469
452
  setError(err instanceof Error ? err : new Error('Auto-load failed'));
470
453
  hasAutoLoadedRef.current = false; // Reset to allow retry
471
454
  });
472
455
  }
473
- }, [autoLoadFromToken, providedToken, fallbackToken, isInitialized, isLoading, getCheckout]);
456
+ }, [autoLoadFromToken, providedToken, isInitialized, isLoading, getCheckout]);
474
457
  return {
475
458
  checkout,
476
459
  isLoading,
@@ -1,7 +1,4 @@
1
- import { useMemo } from 'react';
2
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
3
- // @ts-ignore - iso3166-2-db doesn't have TypeScript definitions
4
- import { getDataSet, reduce } from 'iso3166-2-db';
1
+ import { useMemo, useState, useEffect } from 'react';
5
2
  /**
6
3
  * React hook for accessing ISO3166 countries and regions data
7
4
  * @param language - Language code (en, fr, de, es, etc.)
@@ -9,8 +6,43 @@ import { getDataSet, reduce } from 'iso3166-2-db';
9
6
  * @returns Object with countries data and helper functions
10
7
  */
11
8
  export function useISOData(language = 'en', disputeSetting = 'UN') {
9
+ const [isoModule, setIsoModule] = useState(null);
10
+ const [isLoading, setIsLoading] = useState(true);
11
+ useEffect(() => {
12
+ let isMounted = true;
13
+ const loadModule = async () => {
14
+ try {
15
+ // Try dynamic import first (ES modules)
16
+ const isoModule = await import('iso3166-2-db');
17
+ if (isMounted) {
18
+ setIsoModule(isoModule);
19
+ setIsLoading(false);
20
+ }
21
+ }
22
+ catch (importError) {
23
+ console.error(`Failed to load ISO data module:`, importError);
24
+ if (isMounted) {
25
+ setIsoModule(null);
26
+ setIsLoading(false);
27
+ }
28
+ }
29
+ };
30
+ void loadModule();
31
+ return () => {
32
+ isMounted = false;
33
+ };
34
+ }, []);
12
35
  const data = useMemo(() => {
36
+ if (isLoading || !isoModule) {
37
+ return {
38
+ countries: {},
39
+ getRegions: () => [],
40
+ findRegion: () => null,
41
+ mapGoogleToISO: () => null,
42
+ };
43
+ }
13
44
  try {
45
+ const { getDataSet, reduce } = isoModule;
14
46
  // Get the dataset using the iso3166-2-db library
15
47
  const worldDatabase = reduce(getDataSet(), language);
16
48
  // Transform to our expected format
@@ -85,7 +117,7 @@ export function useISOData(language = 'en', disputeSetting = 'UN') {
85
117
  mapGoogleToISO: () => null,
86
118
  };
87
119
  }
88
- }, [language, disputeSetting]);
120
+ }, [isoModule, isLoading, language, disputeSetting]);
89
121
  return data;
90
122
  }
91
123
  /**
@@ -1,14 +1,15 @@
1
1
  import { useCallback, useState } from 'react';
2
2
  import { useTagadaContext } from '../providers/TagadaProvider';
3
+ import { usePluginConfig } from './usePluginConfig';
3
4
  import { setClientToken } from '../utils/tokenStorage';
4
5
  export function useLogin() {
5
6
  const [isLoading, setIsLoading] = useState(false);
6
7
  const [error, setError] = useState(null);
7
8
  const { apiService } = useTagadaContext();
9
+ const { storeId } = usePluginConfig();
8
10
  const requestCode = useCallback(async (email) => {
9
11
  setIsLoading(true);
10
12
  try {
11
- const storeId = apiService.getStoredStoreId();
12
13
  if (!storeId) {
13
14
  throw new Error('Store ID not found. Make sure the TagadaProvider is properly configured.');
14
15
  }
@@ -33,11 +34,10 @@ export function useLogin() {
33
34
  finally {
34
35
  setIsLoading(false);
35
36
  }
36
- }, [apiService]);
37
+ }, [apiService, storeId]);
37
38
  const verifyCode = useCallback(async (email, code) => {
38
39
  setIsLoading(true);
39
40
  try {
40
- const storeId = apiService.getStoredStoreId();
41
41
  if (!storeId) {
42
42
  throw new Error('Store ID not found. Make sure the TagadaProvider is properly configured.');
43
43
  }
@@ -65,7 +65,7 @@ export function useLogin() {
65
65
  finally {
66
66
  setIsLoading(false);
67
67
  }
68
- }, [apiService]);
68
+ }, [apiService, storeId]);
69
69
  return {
70
70
  error,
71
71
  isLoading,
@@ -1,7 +1,9 @@
1
1
  import { useCallback, useEffect, useState } from 'react';
2
2
  import { useTagadaContext } from '../providers/TagadaProvider';
3
+ import { usePluginConfig } from './usePluginConfig';
3
4
  export function useOffers(options) {
4
5
  const { apiService, environment } = useTagadaContext();
6
+ const { storeId } = usePluginConfig();
5
7
  const [offers, setOffers] = useState([]);
6
8
  const [isLoading, setIsLoading] = useState(false);
7
9
  const [error, setError] = useState(null);
@@ -12,7 +14,10 @@ export function useOffers(options) {
12
14
  setIsLoading(true);
13
15
  setError(null);
14
16
  try {
15
- const responseData = await apiService.fetch(`/api/v1/stores/${apiService.getStoredStoreId()}/offers`, {
17
+ if (!storeId) {
18
+ throw new Error('Store ID not found. Make sure the TagadaProvider is properly configured.');
19
+ }
20
+ const responseData = await apiService.fetch(`/api/v1/stores/${storeId}/offers`, {
16
21
  method: 'GET',
17
22
  headers: {
18
23
  'Content-Type': 'application/json',
@@ -31,7 +36,7 @@ export function useOffers(options) {
31
36
  finally {
32
37
  setIsLoading(false);
33
38
  }
34
- }, [apiService, environment.apiConfig.baseUrl, offerIds, enabled]);
39
+ }, [apiService, storeId, environment.apiConfig.baseUrl, offerIds, enabled]);
35
40
  const initCheckoutSession = useCallback(async (offerId, orderId) => {
36
41
  const response = await apiService.fetch(`/api/v1/checkout/offer/init`, {
37
42
  method: 'POST',
@@ -1,7 +1,9 @@
1
1
  import { useState, useCallback, useEffect, useMemo } from 'react';
2
2
  import { useTagadaContext } from '../providers/TagadaProvider';
3
+ import { usePluginConfig } from './usePluginConfig';
3
4
  export function useProducts(options = {}) {
4
5
  const { apiService } = useTagadaContext();
6
+ const { storeId } = usePluginConfig();
5
7
  const [products, setProducts] = useState([]);
6
8
  const [isLoading, setIsLoading] = useState(false);
7
9
  const [error, setError] = useState(null);
@@ -27,7 +29,6 @@ export function useProducts(options = {}) {
27
29
  setIsLoading(true);
28
30
  setError(null);
29
31
  try {
30
- const storeId = apiService.getStoredStoreId();
31
32
  if (!storeId) {
32
33
  throw new Error('Store ID not found. Make sure the TagadaProvider is properly configured.');
33
34
  }
@@ -67,7 +68,7 @@ export function useProducts(options = {}) {
67
68
  finally {
68
69
  setIsLoading(false);
69
70
  }
70
- }, [apiService, productIds, enabled, includeVariants, includePrices]);
71
+ }, [apiService, storeId, productIds, enabled, includeVariants, includePrices]);
71
72
  const getProduct = useCallback((productId) => {
72
73
  return products.find((product) => product.id === productId);
73
74
  }, [products]);
@@ -2,12 +2,12 @@
2
2
  * React SDK exports
3
3
  */
4
4
  export { TagadaProvider } from './providers/TagadaProvider';
5
- export { useAddress } from './hooks/useAddress';
6
5
  export { useAuth } from './hooks/useAuth';
7
6
  export { useCheckout } from './hooks/useCheckout';
8
7
  export { useCurrency } from './hooks/useCurrency';
9
8
  export { useCustomer } from './hooks/useCustomer';
10
9
  export { useEnvironment } from './hooks/useEnvironment';
10
+ export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
11
11
  export { useLocale } from './hooks/useLocale';
12
12
  export { useLogin } from './hooks/useLogin';
13
13
  export { useOffers } from './hooks/useOffers';
@@ -15,12 +15,12 @@ export { useOrderBump } from './hooks/useOrderBump';
15
15
  export { usePostPurchases } from './hooks/usePostPurchases';
16
16
  export { useProducts } from './hooks/useProducts';
17
17
  export { useSession } from './hooks/useSession';
18
+ export { useTagadaContext } from './providers/TagadaProvider';
18
19
  export { usePluginConfig, useBasePath, getPluginConfig, clearPluginConfigCache, debugPluginConfig } from './hooks/usePluginConfig';
19
20
  export type { PluginConfig } from './hooks/usePluginConfig';
20
- export { useGoogleAutocomplete, useGoogleMapsLoaded } from './hooks/useGoogleAutocomplete';
21
- export type { GooglePrediction, GoogleAddressComponent, GooglePlaceDetails, ExtractedAddress, UseGoogleAutocompleteOptions, UseGoogleAutocompleteResult } from './hooks/useGoogleAutocomplete';
22
21
  export { useISOData, useCountryOptions, useRegionOptions, getAvailableLanguages } from './hooks/useISOData';
23
22
  export type { ISOCountry, ISORegion, UseISODataResult } from './hooks/useISOData';
23
+ export type { GooglePrediction, GoogleAddressComponent, GooglePlaceDetails, ExtractedAddress, UseGoogleAutocompleteOptions, UseGoogleAutocompleteResult } from './hooks/useGoogleAutocomplete';
24
24
  export { useOrder } from './hooks/useOrder';
25
25
  export type { UseOrderOptions, UseOrderResult } from './hooks/useOrder';
26
26
  export { usePayment } from './hooks/usePayment';
@@ -28,10 +28,9 @@ export { usePaymentPolling } from './hooks/usePaymentPolling';
28
28
  export { useThreeds } from './hooks/useThreeds';
29
29
  export { useThreedsModal } from './hooks/useThreedsModal';
30
30
  export type { AuthState, Currency, Customer, Environment, EnvironmentConfig, Locale, Order, OrderAddress, OrderItem, OrderSummary, PickupPoint, Session, Store, } from './types';
31
- export type { CheckoutData, CheckoutInitParams, CheckoutLineItem, CheckoutSession, Promotion, UseCheckoutOptions, UseCheckoutResult, } from './hooks/useCheckout';
31
+ export type { CheckoutSessionPreview, CheckoutData, CheckoutInitParams, CheckoutLineItem, CheckoutSession, Promotion, UseCheckoutOptions, UseCheckoutResult, } from './hooks/useCheckout';
32
32
  export type { OrderBumpPreview, UseOrderBumpOptions, UseOrderBumpResult } from './hooks/useOrderBump';
33
33
  export type { PostPurchaseOffer, PostPurchaseOfferItem, PostPurchaseOfferLineItem, PostPurchaseOfferSummary, UsePostPurchasesOptions, UsePostPurchasesResult, } from './hooks/usePostPurchases';
34
- export type { AddressData, AddressField, Country, State, UseAddressOptions, UseAddressResult, } from './hooks/useAddress';
35
34
  export type { Payment, PaymentPollingHook, PollingOptions } from './hooks/usePaymentPolling';
36
35
  export type { PaymentInstrument, ThreedsChallenge, ThreedsHook, ThreedsOptions, ThreedsProvider, ThreedsSession, } from './hooks/useThreeds';
37
36
  export type { ApplePayToken, CardPaymentMethod, PaymentHook, PaymentInstrumentResponse, PaymentOptions, PaymentResponse, } from './hooks/usePayment';
@@ -5,12 +5,12 @@
5
5
  // Provider exports
6
6
  export { TagadaProvider } from './providers/TagadaProvider';
7
7
  // Hook exports
8
- export { useAddress } from './hooks/useAddress';
9
8
  export { useAuth } from './hooks/useAuth';
10
9
  export { useCheckout } from './hooks/useCheckout';
11
10
  export { useCurrency } from './hooks/useCurrency';
12
11
  export { useCustomer } from './hooks/useCustomer';
13
12
  export { useEnvironment } from './hooks/useEnvironment';
13
+ export { useGoogleAutocomplete } from './hooks/useGoogleAutocomplete';
14
14
  export { useLocale } from './hooks/useLocale';
15
15
  export { useLogin } from './hooks/useLogin';
16
16
  export { useOffers } from './hooks/useOffers';
@@ -18,10 +18,9 @@ export { useOrderBump } from './hooks/useOrderBump';
18
18
  export { usePostPurchases } from './hooks/usePostPurchases';
19
19
  export { useProducts } from './hooks/useProducts';
20
20
  export { useSession } from './hooks/useSession';
21
+ export { useTagadaContext } from './providers/TagadaProvider';
21
22
  // Plugin configuration hooks
22
23
  export { usePluginConfig, useBasePath, getPluginConfig, clearPluginConfigCache, debugPluginConfig } from './hooks/usePluginConfig';
23
- // Google Places hooks
24
- export { useGoogleAutocomplete, useGoogleMapsLoaded } from './hooks/useGoogleAutocomplete';
25
24
  // ISO Data hooks
26
25
  export { useISOData, useCountryOptions, useRegionOptions, getAvailableLanguages } from './hooks/useISOData';
27
26
  // Order hook exports
@@ -51,11 +51,9 @@ interface TagadaProviderProps {
51
51
  environment?: Environment;
52
52
  customApiConfig?: Partial<EnvironmentConfig>;
53
53
  debugMode?: boolean;
54
- storeId?: string;
55
- accountId?: string;
56
54
  localConfig?: string;
57
55
  }
58
56
  export declare function TagadaProvider({ children, environment, customApiConfig, debugMode, // Remove default, will be set based on environment
59
- storeId: propStoreId, accountId: propAccountId, localConfig, }: TagadaProviderProps): import("react/jsx-runtime").JSX.Element;
57
+ localConfig, }: TagadaProviderProps): import("react/jsx-runtime").JSX.Element;
60
58
  export declare function useTagadaContext(): TagadaContextValue;
61
59
  export {};
@@ -1,9 +1,9 @@
1
1
  'use client';
2
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
3
  /**
4
4
  * TagadaProvider - Main provider component for the Tagada Pay React SDK
5
5
  */
6
- import { createContext, useContext, useState, useEffect, useRef, useCallback } from 'react';
6
+ import { createContext, useContext, useState, useEffect, useRef, useCallback, useMemo, } from 'react';
7
7
  import { getEnvironmentConfig, detectEnvironment } from '../config/environment';
8
8
  import { ApiService } from '../services/apiService';
9
9
  import { setClientToken, getClientToken, clearClientToken } from '../utils/tokenStorage';
@@ -12,39 +12,58 @@ import { collectDeviceInfo, getBrowserLocale, getUrlParams } from '../utils/devi
12
12
  import DebugDrawer from '../components/DebugDrawer';
13
13
  import { loadPluginConfig } from '../hooks/usePluginConfig';
14
14
  import { formatMoney, getCurrencyInfo, moneyStringOrNumberToMinorUnits, minorUnitsToMajorUnits, formatMoneyWithoutSymbol, convertCurrency, formatSimpleMoney, } from '../utils/money';
15
- // Subtle loading component for initialization
16
- const InitializationLoader = () => (_jsx("div", { style: {
15
+ // Professional, subtle loading component for initialization
16
+ const InitializationLoader = () => (_jsxs("div", { style: {
17
17
  position: 'fixed',
18
- top: 0,
19
- left: 0,
20
- right: 0,
21
- height: '2px',
22
- background: 'linear-gradient(90deg, #3b82f6 0%, #8b5cf6 50%, #3b82f6 100%)',
23
- backgroundSize: '200% 100%',
24
- animation: 'tagada-loading 1.5s ease-in-out infinite',
25
- zIndex: 9999,
26
- }, children: _jsx("style", { children: `
27
- @keyframes tagada-loading {
28
- 0% { background-position: 200% 0; }
29
- 100% { background-position: -200% 0; }
18
+ top: '24px',
19
+ right: '24px',
20
+ display: 'flex',
21
+ alignItems: 'center',
22
+ gap: '8px',
23
+ padding: '8px 12px',
24
+ backgroundColor: 'rgba(255, 255, 255, 0.9)',
25
+ border: '1px solid rgba(229, 231, 235, 0.8)',
26
+ borderRadius: '8px',
27
+ boxShadow: '0 2px 8px rgba(0, 0, 0, 0.04)',
28
+ backdropFilter: 'blur(8px)',
29
+ zIndex: 999999,
30
+ fontSize: '13px',
31
+ color: '#6b7280',
32
+ fontFamily: 'system-ui, -apple-system, sans-serif',
33
+ fontWeight: '500',
34
+ }, children: [_jsx("div", { style: {
35
+ width: '12px',
36
+ height: '12px',
37
+ border: '1.5px solid #e5e7eb',
38
+ borderTop: '1.5px solid #9ca3af',
39
+ borderRadius: '50%',
40
+ animation: 'tagada-spin 1s linear infinite',
41
+ } }), _jsx("span", { children: "Loading..." }), _jsx("style", { children: `
42
+ @keyframes tagada-spin {
43
+ 0% { transform: rotate(0deg); }
44
+ 100% { transform: rotate(360deg); }
30
45
  }
31
- ` }) }));
46
+ ` })] }));
32
47
  const TagadaContext = createContext(null);
33
48
  export function TagadaProvider({ children, environment, customApiConfig, debugMode, // Remove default, will be set based on environment
34
- storeId: propStoreId, accountId: propAccountId, localConfig, }) {
49
+ localConfig, }) {
35
50
  // LOCAL DEV ONLY: Use localConfig override if in local development, otherwise use default
36
51
  const isLocalDev = typeof window !== 'undefined' &&
37
52
  (window.location.hostname === 'localhost' ||
38
53
  window.location.hostname.includes('.localhost') ||
39
54
  window.location.hostname.includes('127.0.0.1'));
40
55
  const configVariant = isLocalDev ? localConfig || 'default' : 'default';
41
- // Debug logging
42
- console.log('๐Ÿ” TagadaProvider Config Debug:', {
43
- hostname: typeof window !== 'undefined' ? window.location.hostname : 'SSR',
44
- isLocalDev,
45
- localConfig,
46
- configVariant,
47
- });
56
+ // Debug logging (only log once during initial render)
57
+ const hasLoggedRef = useRef(false);
58
+ if (!hasLoggedRef.current) {
59
+ console.log('๐Ÿ” TagadaProvider Config Debug:', {
60
+ hostname: typeof window !== 'undefined' ? window.location.hostname : 'SSR',
61
+ isLocalDev,
62
+ localConfig,
63
+ configVariant,
64
+ });
65
+ hasLoggedRef.current = true;
66
+ }
48
67
  // Load plugin configuration directly (not using hook to avoid circular dependency)
49
68
  const [pluginConfig, setPluginConfig] = useState({ basePath: '/', config: {} });
50
69
  const [configLoading, setConfigLoading] = useState(true);
@@ -53,10 +72,20 @@ storeId: propStoreId, accountId: propAccountId, localConfig, }) {
53
72
  const loadConfig = async () => {
54
73
  try {
55
74
  const config = await loadPluginConfig(configVariant);
75
+ // Ensure we have required store ID before proceeding
76
+ if (!config.storeId) {
77
+ console.warn('โš ๏ธ No store ID found in plugin config. This may cause hooks to fail.');
78
+ }
56
79
  setPluginConfig(config);
80
+ console.log('โœ… Plugin config loaded:', {
81
+ storeId: config.storeId,
82
+ accountId: config.accountId,
83
+ basePath: config.basePath,
84
+ hasConfig: !!config.config,
85
+ });
57
86
  }
58
87
  catch (error) {
59
- console.warn('Failed to load plugin config in TagadaProvider:', error);
88
+ console.error('โŒ Failed to load plugin config in TagadaProvider:', error);
60
89
  setPluginConfig({ basePath: '/', config: {} });
61
90
  }
62
91
  finally {
@@ -65,12 +94,9 @@ storeId: propStoreId, accountId: propAccountId, localConfig, }) {
65
94
  };
66
95
  void loadConfig();
67
96
  }, [configVariant]);
68
- // Extract store/account IDs from plugin config
69
- const configStoreId = pluginConfig.storeId;
70
- const configAccountId = pluginConfig.accountId;
71
- // Use props if provided, otherwise use config from hook
72
- const storeId = propStoreId || configStoreId;
73
- const accountId = propAccountId || configAccountId;
97
+ // Extract store/account IDs from plugin config (only source now)
98
+ const storeId = pluginConfig.storeId;
99
+ const accountId = pluginConfig.accountId;
74
100
  const [isLoading, setIsLoading] = useState(true);
75
101
  const [isInitialized, setIsInitialized] = useState(false);
76
102
  const [token, setToken] = useState(null);
@@ -117,10 +143,9 @@ storeId: propStoreId, accountId: propAccountId, localConfig, }) {
117
143
  clearClientToken();
118
144
  },
119
145
  });
120
- // Store the provided store ID immediately if available
146
+ // Store ID is managed by plugin configuration system
121
147
  if (storeId) {
122
- console.log(`[SDK] Using provided store ID: ${storeId}`);
123
- service.storeStoreId(storeId);
148
+ console.log(`[SDK] Using store ID from config: ${storeId}`);
124
149
  }
125
150
  return service;
126
151
  });
@@ -319,8 +344,8 @@ storeId: propStoreId, accountId: propAccountId, localConfig, }) {
319
344
  if (isInitializing.current) {
320
345
  return;
321
346
  }
322
- // Wait for plugin config to load before initializing
323
- if (configLoading) {
347
+ // Wait for plugin config to load AND ensure we have a store ID before initializing
348
+ if (configLoading || !storeId) {
324
349
  return;
325
350
  }
326
351
  isInitializing.current = true;
@@ -388,7 +413,7 @@ storeId: propStoreId, accountId: propAccountId, localConfig, }) {
388
413
  // Refresh coordinator for bidirectional hook communication
389
414
  const checkoutRefreshRef = useRef(null);
390
415
  const orderBumpRefreshRef = useRef(null);
391
- const refreshCoordinator = {
416
+ const refreshCoordinator = useMemo(() => ({
392
417
  registerCheckoutRefresh: (refreshFn) => {
393
418
  checkoutRefreshRef.current = refreshFn;
394
419
  console.log('๐Ÿ”„ [RefreshCoordinator] Checkout refresh function registered');
@@ -429,8 +454,9 @@ storeId: propStoreId, accountId: propAccountId, localConfig, }) {
429
454
  orderBumpRefreshRef.current = null;
430
455
  console.log('๐Ÿงน [RefreshCoordinator] Order bump refresh function unregistered');
431
456
  },
432
- };
433
- const contextValue = {
457
+ }), []);
458
+ // Memoize the context value to prevent unnecessary re-renders
459
+ const contextValue = useMemo(() => ({
434
460
  auth,
435
461
  session,
436
462
  customer,
@@ -464,8 +490,28 @@ storeId: propStoreId, accountId: propAccountId, localConfig, }) {
464
490
  convertCurrency,
465
491
  formatSimpleMoney,
466
492
  },
467
- };
468
- return (_jsxs(TagadaContext.Provider, { value: contextValue, children: [isLoading && !isInitialized && _jsx(InitializationLoader, {}), finalDebugMode && isInitialized && (_jsxs(_Fragment, { children: [_jsx("button", { onClick: () => setIsDebugDrawerOpen(true), style: {
493
+ }), [
494
+ auth,
495
+ session,
496
+ customer,
497
+ locale,
498
+ currency,
499
+ store,
500
+ environmentConfig,
501
+ apiService,
502
+ isLoading,
503
+ isInitialized,
504
+ finalDebugMode,
505
+ pluginConfig,
506
+ configLoading,
507
+ debugCheckout,
508
+ refreshCoordinator,
509
+ ]);
510
+ // Determine if we should show loading
511
+ // Show loading if: config is loading OR (config loaded but no store ID and session not initialized)
512
+ const shouldShowLoading = configLoading || (!storeId && !isInitialized);
513
+ const canRenderChildren = !configLoading && storeId && isInitialized;
514
+ return (_jsxs(TagadaContext.Provider, { value: contextValue, children: [shouldShowLoading && _jsx(InitializationLoader, {}), finalDebugMode && canRenderChildren && (_jsxs(_Fragment, { children: [_jsx("button", { onClick: () => setIsDebugDrawerOpen(true), style: {
469
515
  position: 'fixed',
470
516
  bottom: '16px',
471
517
  right: '16px',
@@ -486,7 +532,7 @@ storeId: propStoreId, accountId: propAccountId, localConfig, }) {
486
532
  }, onMouseLeave: (e) => {
487
533
  e.currentTarget.style.backgroundColor = '#f97316';
488
534
  e.currentTarget.style.transform = 'scale(1)';
489
- }, title: "Open TagadaPay SDK Debug Panel", children: "\uD83D\uDC1B" }), _jsx(DebugDrawer, { isOpen: isDebugDrawerOpen, onClose: () => setIsDebugDrawerOpen(false) })] })), isInitialized && children] }));
535
+ }, title: "Open TagadaPay SDK Debug Panel", children: "\uD83D\uDC1B" }), _jsx(DebugDrawer, { isOpen: isDebugDrawerOpen, onClose: () => setIsDebugDrawerOpen(false) })] })), canRenderChildren && children] }));
490
536
  }
491
537
  export function useTagadaContext() {
492
538
  const context = useContext(TagadaContext);
@@ -51,11 +51,13 @@ export declare class ApiService {
51
51
  updateToken(token: string | null): void;
52
52
  updateConfig(config: EnvironmentConfig): void;
53
53
  /**
54
- * Store the store ID in localStorage
54
+ * Store the store ID in localStorage (deprecated - use usePluginConfig instead)
55
+ * @deprecated Use usePluginConfig hook to get storeId
55
56
  */
56
57
  storeStoreId(storeId: string): void;
57
58
  /**
58
- * Get the store ID from localStorage
59
+ * Get the store ID from localStorage (deprecated - use usePluginConfig instead)
60
+ * @deprecated Use usePluginConfig hook to get storeId
59
61
  */
60
62
  getStoredStoreId(): string | null;
61
63
  /**
@@ -14,9 +14,11 @@ export class ApiService {
14
14
  this.config = config;
15
15
  }
16
16
  /**
17
- * Store the store ID in localStorage
17
+ * Store the store ID in localStorage (deprecated - use usePluginConfig instead)
18
+ * @deprecated Use usePluginConfig hook to get storeId
18
19
  */
19
20
  storeStoreId(storeId) {
21
+ console.warn('[SDK] storeStoreId is deprecated. Use usePluginConfig hook to get storeId.');
20
22
  try {
21
23
  if (typeof window !== 'undefined' && window.localStorage) {
22
24
  window.localStorage.setItem('tagada_store_id', storeId);
@@ -27,9 +29,11 @@ export class ApiService {
27
29
  }
28
30
  }
29
31
  /**
30
- * Get the store ID from localStorage
32
+ * Get the store ID from localStorage (deprecated - use usePluginConfig instead)
33
+ * @deprecated Use usePluginConfig hook to get storeId
31
34
  */
32
35
  getStoredStoreId() {
36
+ console.warn('[SDK] getStoredStoreId is deprecated. Use usePluginConfig hook to get storeId.');
33
37
  try {
34
38
  if (typeof window !== 'undefined' && window.localStorage) {
35
39
  return window.localStorage.getItem('tagada_store_id');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tagadapay/plugin-sdk",
3
- "version": "2.1.0",
3
+ "version": "2.1.3",
4
4
  "description": "Modern React SDK for building Tagada Pay plugins",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -51,7 +51,6 @@
51
51
  "@basis-theory/web-threeds": "^1.0.1",
52
52
  "axios": "^1.6.0",
53
53
  "iso3166-2-db": "^2.3.11",
54
- "react-google-autocomplete": "^2.7.3",
55
54
  "react-intl": "^7.1.11"
56
55
  },
57
56
  "devDependencies": {
@@ -1 +0,0 @@
1
- export declare const AddressFormExample: () => import("react/jsx-runtime").JSX.Element;