@tagadapay/headless-sdk 1.8.0-rc.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +216 -1
  2. package/dist/core/client.d.ts +68 -0
  3. package/dist/core/client.js +71 -0
  4. package/dist/core/errors.d.ts +46 -0
  5. package/dist/core/errors.js +57 -0
  6. package/dist/core/helpers/autocomplete.d.ts +89 -0
  7. package/dist/core/helpers/autocomplete.js +186 -0
  8. package/dist/core/helpers/countries.d.ts +45 -0
  9. package/dist/core/helpers/countries.js +65 -0
  10. package/dist/core/helpers/currency.d.ts +26 -0
  11. package/dist/core/helpers/currency.js +72 -0
  12. package/dist/core/helpers/index.d.ts +5 -0
  13. package/dist/core/helpers/index.js +5 -0
  14. package/dist/core/helpers/iso3166.d.ts +28 -0
  15. package/dist/core/helpers/iso3166.js +84 -0
  16. package/dist/core/http.d.ts +27 -0
  17. package/dist/core/http.js +116 -0
  18. package/dist/core/index.d.ts +15 -0
  19. package/dist/core/index.js +13 -0
  20. package/dist/core/modules/catalog.d.ts +27 -0
  21. package/dist/core/modules/catalog.js +38 -0
  22. package/dist/core/modules/checkout.d.ts +268 -0
  23. package/dist/core/modules/checkout.js +470 -0
  24. package/dist/core/modules/customer.d.ts +33 -0
  25. package/dist/core/modules/customer.js +53 -0
  26. package/dist/core/modules/funnel.d.ts +38 -0
  27. package/dist/core/modules/funnel.js +138 -0
  28. package/dist/core/modules/offers.d.ts +137 -0
  29. package/dist/core/modules/offers.js +141 -0
  30. package/dist/core/modules/payment.d.ts +298 -0
  31. package/dist/core/modules/payment.js +701 -0
  32. package/dist/core/modules/rx.d.ts +162 -0
  33. package/dist/core/modules/rx.js +46 -0
  34. package/dist/core/types.d.ts +505 -0
  35. package/dist/core/types.js +5 -0
  36. package/dist/react/hooks/useCatalog.d.ts +25 -0
  37. package/dist/react/hooks/useCatalog.js +58 -0
  38. package/dist/react/hooks/useCheckout.d.ts +58 -0
  39. package/dist/react/hooks/useCheckout.js +177 -0
  40. package/dist/react/hooks/useCustomer.d.ts +28 -0
  41. package/dist/react/hooks/useCustomer.js +77 -0
  42. package/dist/react/hooks/useGoogleAutocomplete.d.ts +26 -0
  43. package/dist/react/hooks/useGoogleAutocomplete.js +70 -0
  44. package/dist/react/hooks/useISOData.d.ts +23 -0
  45. package/dist/react/hooks/useISOData.js +63 -0
  46. package/dist/react/hooks/useOffers.d.ts +134 -0
  47. package/dist/react/hooks/useOffers.js +171 -0
  48. package/dist/react/hooks/usePayment.d.ts +108 -0
  49. package/dist/react/hooks/usePayment.js +233 -0
  50. package/dist/react/hooks/useRx.d.ts +64 -0
  51. package/dist/react/hooks/useRx.js +145 -0
  52. package/dist/react/index.d.ts +22 -0
  53. package/dist/react/index.js +12 -0
  54. package/dist/react/internal/redirectGuard.d.ts +9 -0
  55. package/dist/react/internal/redirectGuard.js +25 -0
  56. package/dist/react/provider.d.ts +31 -0
  57. package/dist/react/provider.js +32 -0
  58. package/dist/stripe/StripeExpressButton.d.ts +30 -0
  59. package/dist/stripe/StripeExpressButton.js +32 -0
  60. package/dist/stripe/StripeExpressCheckout.d.ts +98 -0
  61. package/dist/stripe/StripeExpressCheckout.js +198 -0
  62. package/dist/stripe/index.d.ts +8 -0
  63. package/dist/stripe/index.js +15 -0
  64. package/dist/stripe/useStripeExpress.d.ts +54 -0
  65. package/dist/stripe/useStripeExpress.js +126 -0
  66. package/package.json +2 -3
@@ -0,0 +1,5 @@
1
+ // ---------------------------------------------------------------------------
2
+ // Configuration
3
+ // ---------------------------------------------------------------------------
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,25 @@
1
+ import type { CatalogProduct } from '../../core/types.js';
2
+ export interface UseCatalogReturn {
3
+ products: CatalogProduct[];
4
+ isLoading: boolean;
5
+ error: Error | null;
6
+ /** Fetch all products for the store. */
7
+ loadProducts: (opts?: {
8
+ productIds?: string[];
9
+ variantIds?: string[];
10
+ }) => Promise<CatalogProduct[]>;
11
+ /** Fetch a single product by ID. */
12
+ loadProduct: (productId: string) => Promise<CatalogProduct | null>;
13
+ }
14
+ /**
15
+ * React hook for browsing the store's product catalog.
16
+ *
17
+ * @example
18
+ * ```tsx
19
+ * const { products, isLoading, loadProducts } = useCatalog();
20
+ *
21
+ * useEffect(() => { loadProducts(); }, []);
22
+ * ```
23
+ */
24
+ export declare function useCatalog(): UseCatalogReturn;
25
+ //# sourceMappingURL=useCatalog.d.ts.map
@@ -0,0 +1,58 @@
1
+ import { useState, useCallback } from 'react';
2
+ import { useHeadlessClient } from '../provider.js';
3
+ /**
4
+ * React hook for browsing the store's product catalog.
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * const { products, isLoading, loadProducts } = useCatalog();
9
+ *
10
+ * useEffect(() => { loadProducts(); }, []);
11
+ * ```
12
+ */
13
+ export function useCatalog() {
14
+ const client = useHeadlessClient();
15
+ const [products, setProducts] = useState([]);
16
+ const [isLoading, setIsLoading] = useState(false);
17
+ const [error, setError] = useState(null);
18
+ const loadProducts = useCallback(async (opts) => {
19
+ setIsLoading(true);
20
+ setError(null);
21
+ try {
22
+ const items = await client.catalog.getProducts(opts);
23
+ setProducts(items);
24
+ return items;
25
+ }
26
+ catch (err) {
27
+ const e = err instanceof Error ? err : new Error(String(err));
28
+ setError(e);
29
+ throw e;
30
+ }
31
+ finally {
32
+ setIsLoading(false);
33
+ }
34
+ }, [client]);
35
+ const loadProduct = useCallback(async (productId) => {
36
+ setIsLoading(true);
37
+ setError(null);
38
+ try {
39
+ return await client.catalog.getProduct(productId);
40
+ }
41
+ catch (err) {
42
+ const e = err instanceof Error ? err : new Error(String(err));
43
+ setError(e);
44
+ throw e;
45
+ }
46
+ finally {
47
+ setIsLoading(false);
48
+ }
49
+ }, [client]);
50
+ return {
51
+ products,
52
+ isLoading,
53
+ error,
54
+ loadProducts,
55
+ loadProduct,
56
+ };
57
+ }
58
+ //# sourceMappingURL=useCatalog.js.map
@@ -0,0 +1,58 @@
1
+ import type { CheckoutSession, LineItem, ShippingRate, Address, CheckoutCustomer } from '../../core/types.js';
2
+ export interface UseCheckoutReturn {
3
+ session: CheckoutSession | null;
4
+ isLoading: boolean;
5
+ error: Error | null;
6
+ /** Reload the session from the server. */
7
+ refresh: () => Promise<void>;
8
+ /** Create a new checkout session (auto-loads it after creation). */
9
+ createSession: (opts: {
10
+ items: LineItem[];
11
+ currency?: string;
12
+ returnUrl?: string;
13
+ customerEmail?: string;
14
+ }) => Promise<void>;
15
+ /** Replace cart items. */
16
+ updateCart: (items: LineItem[]) => Promise<void>;
17
+ /** Update customer info on the session. */
18
+ updateCustomer: (customer: Partial<CheckoutCustomer>) => Promise<void>;
19
+ /** Update address on the session. */
20
+ updateAddress: (addresses: {
21
+ shippingAddress?: Address;
22
+ billingAddress?: Address;
23
+ }) => Promise<void>;
24
+ /**
25
+ * Update customer info AND address in a single call. Prefer this over
26
+ * calling `updateCustomer` then `updateAddress` separately — the
27
+ * underlying server action is destructive on partial saves
28
+ * (`customers.firstName = shippingAddress.firstName ?? null`), so
29
+ * sending the address without the customer name will silently wipe
30
+ * `customer.firstName` / `customer.lastName` from the session.
31
+ */
32
+ updateCustomerAndAddress: (data: {
33
+ customer: Partial<CheckoutCustomer>;
34
+ shippingAddress?: Address;
35
+ billingAddress?: Address;
36
+ }) => Promise<void>;
37
+ /** Apply a promo code. */
38
+ applyPromo: (code: string) => Promise<void>;
39
+ /** Remove the applied promo code. */
40
+ removePromo: (promotionId?: string) => Promise<void>;
41
+ /** Fetch shipping rates. */
42
+ getShippingRates: () => Promise<ShippingRate[]>;
43
+ /** Select a shipping rate. */
44
+ selectShippingRate: (rateId: string) => Promise<void>;
45
+ }
46
+ /**
47
+ * React hook for checkout session management.
48
+ *
49
+ * @param checkoutToken - The checkout token from the URL (e.g. `?checkoutToken=xxx`).
50
+ * @param sessionToken - Optional JWT session token (from URL param `token`).
51
+ *
52
+ * @example
53
+ * ```tsx
54
+ * const { session, isLoading, applyPromo, createSession } = useCheckout(checkoutToken, sessionToken);
55
+ * ```
56
+ */
57
+ export declare function useCheckout(checkoutToken: string | null | undefined, sessionToken?: string): UseCheckoutReturn;
58
+ //# sourceMappingURL=useCheckout.d.ts.map
@@ -0,0 +1,177 @@
1
+ import { useState, useEffect, useCallback } from 'react';
2
+ import { useHeadlessClient } from '../provider.js';
3
+ /**
4
+ * React hook for checkout session management.
5
+ *
6
+ * @param checkoutToken - The checkout token from the URL (e.g. `?checkoutToken=xxx`).
7
+ * @param sessionToken - Optional JWT session token (from URL param `token`).
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * const { session, isLoading, applyPromo, createSession } = useCheckout(checkoutToken, sessionToken);
12
+ * ```
13
+ */
14
+ export function useCheckout(checkoutToken, sessionToken) {
15
+ const client = useHeadlessClient();
16
+ const [session, setSession] = useState(null);
17
+ const [isLoading, setIsLoading] = useState(false);
18
+ const [error, setError] = useState(null);
19
+ const loadSession = useCallback(async () => {
20
+ if (!checkoutToken)
21
+ return;
22
+ setIsLoading(true);
23
+ setError(null);
24
+ try {
25
+ const s = await client.checkout.loadSession(checkoutToken, sessionToken);
26
+ setSession(s);
27
+ }
28
+ catch (err) {
29
+ setError(err instanceof Error ? err : new Error(String(err)));
30
+ }
31
+ finally {
32
+ setIsLoading(false);
33
+ }
34
+ }, [client, checkoutToken, sessionToken]);
35
+ useEffect(() => {
36
+ loadSession();
37
+ }, [loadSession]);
38
+ const createSession = useCallback(async (opts) => {
39
+ setIsLoading(true);
40
+ setError(null);
41
+ try {
42
+ const result = await client.checkout.createSession(opts);
43
+ const newUrl = new URL(window.location.href);
44
+ newUrl.searchParams.set('checkoutToken', result.checkoutToken);
45
+ newUrl.searchParams.set('token', result.sessionToken);
46
+ window.history.replaceState({}, '', newUrl.toString());
47
+ const s = await client.checkout.loadSession(result.checkoutToken, result.sessionToken);
48
+ setSession(s);
49
+ }
50
+ catch (err) {
51
+ setError(err instanceof Error ? err : new Error(String(err)));
52
+ }
53
+ finally {
54
+ setIsLoading(false);
55
+ }
56
+ }, [client]);
57
+ const updateCart = useCallback(async (items) => {
58
+ if (!session)
59
+ return;
60
+ // `updateCart` returns mutation stats (counts), not a CheckoutSession.
61
+ // We previously assigned that result into `setSession`, which silently
62
+ // replaced the session with `{ success, updated, created, total }`.
63
+ // Mirror the same pattern as `updateAddress`: mutate, then reload.
64
+ setIsLoading(true);
65
+ try {
66
+ await client.checkout.updateCart(session.id, items);
67
+ await loadSession();
68
+ }
69
+ catch (err) {
70
+ setError(err instanceof Error ? err : new Error(String(err)));
71
+ }
72
+ finally {
73
+ setIsLoading(false);
74
+ }
75
+ }, [client, session, loadSession]);
76
+ const updateCustomer = useCallback(async (customer) => {
77
+ if (!session)
78
+ return;
79
+ await client.checkout.updateCustomer(session.id, customer);
80
+ }, [client, session]);
81
+ const updateAddress = useCallback(async (addresses) => {
82
+ if (!session)
83
+ return;
84
+ setIsLoading(true);
85
+ try {
86
+ await client.checkout.updateAddress(session.id, addresses);
87
+ await loadSession();
88
+ }
89
+ catch (err) {
90
+ setError(err instanceof Error ? err : new Error(String(err)));
91
+ }
92
+ finally {
93
+ setIsLoading(false);
94
+ }
95
+ }, [client, session, loadSession]);
96
+ const updateCustomerAndAddress = useCallback(async (data) => {
97
+ if (!session)
98
+ return;
99
+ setIsLoading(true);
100
+ try {
101
+ await client.checkout.updateCustomerAndAddress(session.id, data);
102
+ await loadSession();
103
+ }
104
+ catch (err) {
105
+ setError(err instanceof Error ? err : new Error(String(err)));
106
+ }
107
+ finally {
108
+ setIsLoading(false);
109
+ }
110
+ }, [client, session, loadSession]);
111
+ const applyPromo = useCallback(async (code) => {
112
+ if (!session)
113
+ return;
114
+ setIsLoading(true);
115
+ try {
116
+ await client.checkout.applyPromoCode(session.id, code);
117
+ await loadSession();
118
+ }
119
+ catch (err) {
120
+ setError(err instanceof Error ? err : new Error(String(err)));
121
+ }
122
+ finally {
123
+ setIsLoading(false);
124
+ }
125
+ }, [client, session, loadSession]);
126
+ const removePromo = useCallback(async (promotionId) => {
127
+ if (!session)
128
+ return;
129
+ setIsLoading(true);
130
+ try {
131
+ await client.checkout.removePromoCode(session.id, promotionId);
132
+ await loadSession();
133
+ }
134
+ catch (err) {
135
+ setError(err instanceof Error ? err : new Error(String(err)));
136
+ }
137
+ finally {
138
+ setIsLoading(false);
139
+ }
140
+ }, [client, session, loadSession]);
141
+ const getShippingRates = useCallback(async () => {
142
+ if (!session)
143
+ return [];
144
+ return client.checkout.getShippingRates(session.id);
145
+ }, [client, session]);
146
+ const selectShippingRate = useCallback(async (rateId) => {
147
+ if (!session)
148
+ return;
149
+ setIsLoading(true);
150
+ try {
151
+ await client.checkout.selectShippingRate(session.id, rateId);
152
+ await loadSession();
153
+ }
154
+ catch (err) {
155
+ setError(err instanceof Error ? err : new Error(String(err)));
156
+ }
157
+ finally {
158
+ setIsLoading(false);
159
+ }
160
+ }, [client, session, loadSession]);
161
+ return {
162
+ session,
163
+ isLoading,
164
+ error,
165
+ refresh: loadSession,
166
+ createSession,
167
+ updateCart,
168
+ updateCustomer,
169
+ updateAddress,
170
+ updateCustomerAndAddress,
171
+ applyPromo,
172
+ removePromo,
173
+ getShippingRates,
174
+ selectShippingRate,
175
+ };
176
+ }
177
+ //# sourceMappingURL=useCheckout.js.map
@@ -0,0 +1,28 @@
1
+ import type { Customer, Order, Subscription } from '../../core/types.js';
2
+ export interface UseCustomerReturn {
3
+ customer: Customer | null;
4
+ orders: Order[];
5
+ subscriptions: Subscription[];
6
+ isLoading: boolean;
7
+ error: Error | null;
8
+ /** Load customer profile by ID. */
9
+ loadCustomer: (customerId: string) => Promise<void>;
10
+ /** Load customer orders. */
11
+ loadOrders: (customerId: string) => Promise<void>;
12
+ /** Load customer subscriptions. */
13
+ loadSubscriptions: (customerId: string) => Promise<void>;
14
+ /** Update customer profile. */
15
+ updateProfile: (customerId: string, data: Partial<Pick<Customer, 'email' | 'firstName' | 'lastName' | 'phone'>>) => Promise<void>;
16
+ }
17
+ /**
18
+ * React hook for customer data -- profile, orders, subscriptions.
19
+ *
20
+ * @param customerId - Auto-loads the customer profile when provided.
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * const { customer, orders, loadOrders } = useCustomer(session?.customer?.id);
25
+ * ```
26
+ */
27
+ export declare function useCustomer(customerId?: string | null): UseCustomerReturn;
28
+ //# sourceMappingURL=useCustomer.d.ts.map
@@ -0,0 +1,77 @@
1
+ import { useState, useEffect, useCallback } from 'react';
2
+ import { useHeadlessClient } from '../provider.js';
3
+ /**
4
+ * React hook for customer data -- profile, orders, subscriptions.
5
+ *
6
+ * @param customerId - Auto-loads the customer profile when provided.
7
+ *
8
+ * @example
9
+ * ```tsx
10
+ * const { customer, orders, loadOrders } = useCustomer(session?.customer?.id);
11
+ * ```
12
+ */
13
+ export function useCustomer(customerId) {
14
+ const client = useHeadlessClient();
15
+ const [customer, setCustomer] = useState(null);
16
+ const [orders, setOrders] = useState([]);
17
+ const [subscriptions, setSubscriptions] = useState([]);
18
+ const [isLoading, setIsLoading] = useState(false);
19
+ const [error, setError] = useState(null);
20
+ const loadCustomer = useCallback(async (id) => {
21
+ setIsLoading(true);
22
+ setError(null);
23
+ try {
24
+ const c = await client.customer.getProfile(id);
25
+ setCustomer(c);
26
+ }
27
+ catch (err) {
28
+ setError(err instanceof Error ? err : new Error(String(err)));
29
+ }
30
+ finally {
31
+ setIsLoading(false);
32
+ }
33
+ }, [client]);
34
+ const loadOrders = useCallback(async (id) => {
35
+ try {
36
+ const res = await client.customer.getOrders(id);
37
+ setOrders(res.orders);
38
+ }
39
+ catch (err) {
40
+ setError(err instanceof Error ? err : new Error(String(err)));
41
+ }
42
+ }, [client]);
43
+ const loadSubscriptions = useCallback(async (id) => {
44
+ try {
45
+ const subs = await client.customer.getSubscriptions(id);
46
+ setSubscriptions(subs);
47
+ }
48
+ catch (err) {
49
+ setError(err instanceof Error ? err : new Error(String(err)));
50
+ }
51
+ }, [client]);
52
+ const updateProfile = useCallback(async (id, data) => {
53
+ try {
54
+ const updated = await client.customer.updateProfile(id, data);
55
+ setCustomer(updated);
56
+ }
57
+ catch (err) {
58
+ setError(err instanceof Error ? err : new Error(String(err)));
59
+ }
60
+ }, [client]);
61
+ useEffect(() => {
62
+ if (customerId)
63
+ loadCustomer(customerId);
64
+ }, [customerId, loadCustomer]);
65
+ return {
66
+ customer,
67
+ orders,
68
+ subscriptions,
69
+ isLoading,
70
+ error,
71
+ loadCustomer,
72
+ loadOrders,
73
+ loadSubscriptions,
74
+ updateProfile,
75
+ };
76
+ }
77
+ //# sourceMappingURL=useCustomer.js.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * React hook for Google Places Autocomplete — handles script injection,
3
+ * debounced prediction search, place detail fetching, and address extraction.
4
+ */
5
+ import { type GooglePrediction, type GooglePlaceDetails, type ExtractedAddress, type FormattedAddress } from '../../core/helpers/autocomplete.js';
6
+ export type { GooglePrediction, GooglePlaceDetails, ExtractedAddress, FormattedAddress };
7
+ export interface UseGoogleAutocompleteOptions {
8
+ apiKey: string;
9
+ language?: string;
10
+ region?: string;
11
+ version?: string;
12
+ /** Defer script loading until searchPlaces() is first called. Default: false. */
13
+ defer?: boolean;
14
+ }
15
+ export interface UseGoogleAutocompleteReturn {
16
+ predictions: GooglePrediction[];
17
+ isLoading: boolean;
18
+ isScriptLoaded: boolean;
19
+ searchPlaces: (input: string, countryRestriction?: string) => void;
20
+ getPlaceDetails: (placeId: string) => Promise<GooglePlaceDetails | null>;
21
+ extractAddressComponents: (place: GooglePlaceDetails) => ExtractedAddress;
22
+ extractFormattedAddress: (place: GooglePlaceDetails) => FormattedAddress;
23
+ clearPredictions: () => void;
24
+ }
25
+ export declare function useGoogleAutocomplete(options: UseGoogleAutocompleteOptions): UseGoogleAutocompleteReturn;
26
+ //# sourceMappingURL=useGoogleAutocomplete.d.ts.map
@@ -0,0 +1,70 @@
1
+ /**
2
+ * React hook for Google Places Autocomplete — handles script injection,
3
+ * debounced prediction search, place detail fetching, and address extraction.
4
+ */
5
+ import { useCallback, useEffect, useRef, useState } from 'react';
6
+ import { GoogleAutocompleteCore, loadGoogleMapsScript, } from '../../core/helpers/autocomplete.js';
7
+ export function useGoogleAutocomplete(options) {
8
+ const { apiKey, language, region, version, defer = false } = options;
9
+ const [predictions, setPredictions] = useState([]);
10
+ const [isLoading, setIsLoading] = useState(false);
11
+ const [isScriptLoaded, setIsScriptLoaded] = useState(false);
12
+ const debounceRef = useRef(null);
13
+ const pendingRef = useRef(null);
14
+ const inject = useCallback(() => {
15
+ loadGoogleMapsScript(apiKey, { language, region, version }).then(() => setIsScriptLoaded(true));
16
+ }, [apiKey, language, region, version]);
17
+ // Eager load unless defer
18
+ useEffect(() => {
19
+ if (!apiKey || defer)
20
+ return;
21
+ inject();
22
+ }, [apiKey, defer, inject]);
23
+ // Replay pending search after deferred load
24
+ useEffect(() => {
25
+ if (isScriptLoaded && pendingRef.current) {
26
+ const { input, country } = pendingRef.current;
27
+ pendingRef.current = null;
28
+ doSearch(input, country);
29
+ }
30
+ // eslint-disable-next-line react-hooks/exhaustive-deps
31
+ }, [isScriptLoaded]);
32
+ const doSearch = useCallback((input, countryRestriction) => {
33
+ if (!isScriptLoaded) {
34
+ if (defer) {
35
+ pendingRef.current = { input, country: countryRestriction };
36
+ inject();
37
+ }
38
+ return;
39
+ }
40
+ if (input.length < 3) {
41
+ setPredictions([]);
42
+ return;
43
+ }
44
+ if (debounceRef.current)
45
+ clearTimeout(debounceRef.current);
46
+ debounceRef.current = setTimeout(async () => {
47
+ setIsLoading(true);
48
+ const results = await GoogleAutocompleteCore.searchPlaces(input, {
49
+ componentRestrictions: countryRestriction ? { country: countryRestriction.toLowerCase() } : undefined,
50
+ });
51
+ setPredictions(results);
52
+ setIsLoading(false);
53
+ }, 300);
54
+ }, [isScriptLoaded, defer, inject]);
55
+ const getPlaceDetails = useCallback((placeId) => GoogleAutocompleteCore.getPlaceDetails(placeId), []);
56
+ const extractAddressComponents = useCallback((place) => GoogleAutocompleteCore.extractAddressComponents(place), []);
57
+ const extractFormattedAddress = useCallback((place) => GoogleAutocompleteCore.extractFormattedAddress(place), []);
58
+ const clearPredictions = useCallback(() => setPredictions([]), []);
59
+ return {
60
+ predictions,
61
+ isLoading,
62
+ isScriptLoaded,
63
+ searchPlaces: doSearch,
64
+ getPlaceDetails,
65
+ extractAddressComponents,
66
+ extractFormattedAddress,
67
+ clearPredictions,
68
+ };
69
+ }
70
+ //# sourceMappingURL=useGoogleAutocomplete.js.map
@@ -0,0 +1,23 @@
1
+ /**
2
+ * React hooks for ISO country/region data — CDN-backed,
3
+ * with Google Places → ISO region mapping.
4
+ */
5
+ import { type ISOCountry, type ISORegion, type SupportedLanguage } from '../../core/helpers/countries.js';
6
+ export type { ISOCountry, ISORegion, SupportedLanguage };
7
+ export interface UseISODataReturn {
8
+ countries: Record<string, ISOCountry>;
9
+ getRegions: (countryCode: string) => ISORegion[];
10
+ findRegion: (countryCode: string, regionCode: string) => ISORegion | null;
11
+ mapGoogleToISO: (googleState: string, googleStateLong: string, countryCode: string) => ISORegion | null;
12
+ isLoaded: boolean;
13
+ }
14
+ export declare function useISOData(language?: SupportedLanguage): UseISODataReturn;
15
+ export declare function useCountryOptions(language?: SupportedLanguage): Array<{
16
+ value: string;
17
+ label: string;
18
+ }>;
19
+ export declare function useRegionOptions(countryCode: string, language?: SupportedLanguage): Array<{
20
+ value: string;
21
+ label: string;
22
+ }>;
23
+ //# sourceMappingURL=useISOData.d.ts.map
@@ -0,0 +1,63 @@
1
+ /**
2
+ * React hooks for ISO country/region data — CDN-backed,
3
+ * with Google Places → ISO region mapping.
4
+ */
5
+ import { useEffect, useMemo, useState } from 'react';
6
+ import { ISODataCore, } from '../../core/helpers/countries.js';
7
+ import { ensureGeoDataLoaded, isLanguageLoaded } from '../../core/helpers/iso3166.js';
8
+ export function useISOData(language = 'en') {
9
+ const [isLoaded, setIsLoaded] = useState(isLanguageLoaded(language));
10
+ useEffect(() => {
11
+ let cancelled = false;
12
+ ensureGeoDataLoaded(language)
13
+ .then(() => { if (!cancelled)
14
+ setIsLoaded(true); })
15
+ .catch((err) => console.error('[headless-sdk] Failed to load geodata:', err));
16
+ return () => { cancelled = true; };
17
+ }, [language]);
18
+ return useMemo(() => {
19
+ if (!isLoaded) {
20
+ return {
21
+ countries: {},
22
+ getRegions: () => [],
23
+ findRegion: () => null,
24
+ mapGoogleToISO: () => null,
25
+ isLoaded: false,
26
+ };
27
+ }
28
+ return {
29
+ countries: ISODataCore.getCountries(language),
30
+ getRegions: (cc) => ISODataCore.getRegions(cc, language),
31
+ findRegion: (cc, rc) => ISODataCore.findRegion(cc, rc, language),
32
+ mapGoogleToISO: (gs, gsl, cc) => ISODataCore.mapGoogleToISO(gs, gsl, cc, language),
33
+ isLoaded: true,
34
+ };
35
+ }, [language, isLoaded]);
36
+ }
37
+ // ---------------------------------------------------------------------------
38
+ // useCountryOptions — countries as select options
39
+ // ---------------------------------------------------------------------------
40
+ export function useCountryOptions(language = 'en') {
41
+ const { countries, isLoaded } = useISOData(language);
42
+ return useMemo(() => {
43
+ if (!isLoaded)
44
+ return [];
45
+ return Object.values(countries)
46
+ .map((c) => ({ value: c.iso, label: c.name }))
47
+ .sort((a, b) => a.label.localeCompare(b.label));
48
+ }, [countries, isLoaded]);
49
+ }
50
+ // ---------------------------------------------------------------------------
51
+ // useRegionOptions — regions/states for a country as select options
52
+ // ---------------------------------------------------------------------------
53
+ export function useRegionOptions(countryCode, language = 'en') {
54
+ const { getRegions, isLoaded } = useISOData(language);
55
+ return useMemo(() => {
56
+ if (!isLoaded || !countryCode)
57
+ return [];
58
+ return getRegions(countryCode)
59
+ .map((r) => ({ value: r.iso, label: r.name }))
60
+ .sort((a, b) => a.label.localeCompare(b.label));
61
+ }, [countryCode, getRegions, isLoaded]);
62
+ }
63
+ //# sourceMappingURL=useISOData.js.map