@tagadapay/headless-sdk 1.1.1 → 1.3.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 (64) hide show
  1. package/dist/core/client.d.ts +2 -5
  2. package/dist/core/client.d.ts.map +1 -1
  3. package/dist/core/client.js +1 -3
  4. package/dist/core/client.js.map +1 -1
  5. package/dist/core/helpers/autocomplete.d.ts +89 -0
  6. package/dist/core/helpers/autocomplete.d.ts.map +1 -0
  7. package/dist/core/helpers/autocomplete.js +186 -0
  8. package/dist/core/helpers/autocomplete.js.map +1 -0
  9. package/dist/core/helpers/countries.d.ts +45 -0
  10. package/dist/core/helpers/countries.d.ts.map +1 -0
  11. package/dist/core/helpers/countries.js +65 -0
  12. package/dist/core/helpers/countries.js.map +1 -0
  13. package/dist/core/helpers/currency.d.ts +26 -0
  14. package/dist/core/helpers/currency.d.ts.map +1 -0
  15. package/dist/core/helpers/currency.js +72 -0
  16. package/dist/core/helpers/currency.js.map +1 -0
  17. package/dist/core/helpers/index.d.ts +5 -0
  18. package/dist/core/helpers/index.d.ts.map +1 -0
  19. package/dist/core/helpers/index.js +5 -0
  20. package/dist/core/helpers/index.js.map +1 -0
  21. package/dist/core/helpers/iso3166.d.ts +28 -0
  22. package/dist/core/helpers/iso3166.d.ts.map +1 -0
  23. package/dist/core/helpers/iso3166.js +84 -0
  24. package/dist/core/helpers/iso3166.js.map +1 -0
  25. package/dist/core/index.d.ts +3 -2
  26. package/dist/core/index.d.ts.map +1 -1
  27. package/dist/core/index.js +2 -1
  28. package/dist/core/index.js.map +1 -1
  29. package/dist/core/modules/offers.d.ts +64 -23
  30. package/dist/core/modules/offers.d.ts.map +1 -1
  31. package/dist/core/modules/offers.js +70 -33
  32. package/dist/core/modules/offers.js.map +1 -1
  33. package/dist/core/types.d.ts +26 -16
  34. package/dist/core/types.d.ts.map +1 -1
  35. package/dist/react/hooks/useGoogleAutocomplete.d.ts +26 -0
  36. package/dist/react/hooks/useGoogleAutocomplete.d.ts.map +1 -0
  37. package/dist/react/hooks/useGoogleAutocomplete.js +70 -0
  38. package/dist/react/hooks/useGoogleAutocomplete.js.map +1 -0
  39. package/dist/react/hooks/useISOData.d.ts +23 -0
  40. package/dist/react/hooks/useISOData.d.ts.map +1 -0
  41. package/dist/react/hooks/useISOData.js +63 -0
  42. package/dist/react/hooks/useISOData.js.map +1 -0
  43. package/dist/react/hooks/useOffers.d.ts +63 -22
  44. package/dist/react/hooks/useOffers.d.ts.map +1 -1
  45. package/dist/react/hooks/useOffers.js +36 -52
  46. package/dist/react/hooks/useOffers.js.map +1 -1
  47. package/dist/react/index.d.ts +7 -3
  48. package/dist/react/index.d.ts.map +1 -1
  49. package/dist/react/index.js +4 -1
  50. package/dist/react/index.js.map +1 -1
  51. package/dist/tagada-headless-react.min.js +2 -2
  52. package/dist/tagada-headless-react.min.js.map +4 -4
  53. package/dist/tagada-headless.js +536 -292
  54. package/dist/tagada-headless.min.js +2 -2
  55. package/dist/tagada-headless.min.js.map +4 -4
  56. package/package.json +3 -3
  57. package/dist/core/modules/analytics.d.ts +0 -79
  58. package/dist/core/modules/analytics.d.ts.map +0 -1
  59. package/dist/core/modules/analytics.js +0 -265
  60. package/dist/core/modules/analytics.js.map +0 -1
  61. package/dist/react/hooks/useAnalytics.d.ts +0 -59
  62. package/dist/react/hooks/useAnalytics.d.ts.map +0 -1
  63. package/dist/react/hooks/useAnalytics.js +0 -49
  64. package/dist/react/hooks/useAnalytics.js.map +0 -1
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @tagadapay/headless-sdk v1.1.1
2
+ * @tagadapay/headless-sdk v1.3.0
3
3
  * Headless checkout, payments, analytics, and CRM
4
4
  * @license MIT
5
5
  */
@@ -43,12 +43,15 @@ var TagadaHeadlessBundle = (() => {
43
43
  // src/core/index.ts
44
44
  var core_exports = {};
45
45
  __export(core_exports, {
46
- AnalyticsModule: () => AnalyticsModule,
46
+ AVAILABLE_LANGUAGES: () => AVAILABLE_LANGUAGES,
47
47
  CatalogModule: () => CatalogModule,
48
48
  CheckoutModule: () => CheckoutModule,
49
+ CurrencyUtils: () => CurrencyUtils,
49
50
  CustomerModule: () => CustomerModule,
51
+ GoogleAutocompleteCore: () => GoogleAutocompleteCore,
50
52
  HeadlessClient: () => HeadlessClient,
51
53
  HttpClient: () => HttpClient,
54
+ ISODataCore: () => ISODataCore,
52
55
  OffersModule: () => OffersModule,
53
56
  PaymentModule: () => PaymentModule,
54
57
  TagadaAuthError: () => TagadaAuthError,
@@ -58,7 +61,13 @@ var TagadaHeadlessBundle = (() => {
58
61
  TagadaPaymentError: () => TagadaPaymentError,
59
62
  TagadaRateLimitError: () => TagadaRateLimitError,
60
63
  TagadaValidationError: () => TagadaValidationError,
61
- createHeadlessClient: () => createHeadlessClient
64
+ createHeadlessClient: () => createHeadlessClient,
65
+ ensureGeoDataLoaded: () => ensureGeoDataLoaded,
66
+ formatMoney: () => formatMoney,
67
+ getCountries: () => getCountries,
68
+ getStatesForCountry: () => getStatesForCountry,
69
+ isLanguageLoaded: () => isLanguageLoaded,
70
+ loadGoogleMapsScript: () => loadGoogleMapsScript
62
71
  });
63
72
 
64
73
  // src/core/errors.ts
@@ -717,315 +726,93 @@ var TagadaHeadlessBundle = (() => {
717
726
  }
718
727
  };
719
728
 
720
- // src/core/modules/analytics.ts
721
- var AnalyticsModule = class {
729
+ // src/core/modules/offers.ts
730
+ var OffersModule = class {
722
731
  constructor(http, storeId) {
723
732
  this.http = http;
724
733
  this.storeId = storeId;
725
- this.pixels = { loaded: false };
726
- this.eventQueue = [];
727
- this.dedupeSet = /* @__PURE__ */ new Set();
728
- }
729
- /**
730
- * Initialize analytics by loading pixel configuration from the store.
731
- * Call this once on page load. Events fired before init completes are queued.
732
- */
733
- async init(opts) {
734
- if (this.pixels.loaded)
735
- return;
736
- let config = opts == null ? void 0 : opts.pixelConfig;
737
- if (!config) {
738
- try {
739
- const res = await this.http.get(
740
- "/api/v1/checkout/config",
741
- { params: { storeId: this.storeId } }
742
- );
743
- config = res.pixels;
744
- } catch {
745
- }
746
- }
747
- this.pixels = { loaded: true, config };
748
- if (typeof window !== "undefined" && config) {
749
- this.loadPixelScripts(config);
750
- }
751
- this.flushQueue();
752
734
  }
753
735
  // ---------------------------------------------------------------------------
754
- // Standard e-commerce events
736
+ // Offer loading
755
737
  // ---------------------------------------------------------------------------
756
- trackPageView(page) {
757
- this.fireEvent("PageView", { page: page ?? this.getCurrentPath() });
758
- }
759
- trackViewContent(data) {
760
- this.fireEvent("ViewContent", data);
761
- }
762
- trackAddToCart(data) {
763
- this.fireEvent("AddToCart", data);
738
+ /** Get a single offer by ID. */
739
+ async getOffer(offerId) {
740
+ return this.http.get(`/api/v1/offers/${offerId}`);
764
741
  }
765
- trackInitiateCheckout(data) {
766
- this.fireEvent("InitiateCheckout", data ?? {});
767
- }
768
- trackAddPaymentInfo(data) {
769
- this.fireEvent("AddPaymentInfo", data ?? {});
770
- }
771
- trackPurchase(data) {
772
- this.fireEvent("Purchase", data, true);
773
- }
774
- trackCustomEvent(event, data) {
775
- this.fireEvent(event, data ?? {});
776
- }
777
- /** Track a funnel step (maps to Tagada's funnel tracking endpoint). */
778
- trackStep(data) {
779
- this.fireEvent("FunnelStep", data);
780
- this.http.post("/api/v1/funnel-tracking/step", {
781
- storeId: this.storeId,
782
- ...data
783
- }).catch(() => {
784
- });
785
- }
786
- trackConversion(data) {
787
- this.fireEvent("Conversion", data, true);
788
- }
789
- // ---------------------------------------------------------------------------
790
- // Internals
791
- // ---------------------------------------------------------------------------
792
- fireEvent(event, data, dedupe = false) {
793
- if (dedupe) {
794
- const key = `${event}:${JSON.stringify(data)}`;
795
- if (this.dedupeSet.has(key))
796
- return;
797
- this.dedupeSet.add(key);
798
- }
799
- if (!this.pixels.loaded) {
800
- this.eventQueue.push({ event, data });
801
- return;
802
- }
803
- this.sendToMeta(event, data);
804
- this.sendToTikTok(event, data);
805
- this.sendToSnapchat(event, data);
806
- this.sendToGTM(event, data);
807
- this.sendToGA(event, data);
808
- }
809
- flushQueue() {
810
- const queue = [...this.eventQueue];
811
- this.eventQueue = [];
812
- for (const { event, data } of queue) {
813
- this.fireEvent(event, data);
742
+ /** List offers for the current store. Optionally filter by type or a set of IDs. */
743
+ async listOffers(opts) {
744
+ var _a;
745
+ let url = `/api/v1/stores/${this.storeId}/offers`;
746
+ const queryParts = [];
747
+ if (opts == null ? void 0 : opts.type)
748
+ queryParts.push(`type=${encodeURIComponent(opts.type)}`);
749
+ if ((_a = opts == null ? void 0 : opts.ids) == null ? void 0 : _a.length) {
750
+ for (const id of opts.ids)
751
+ queryParts.push(`ids=${encodeURIComponent(id)}`);
814
752
  }
815
- }
816
- getCurrentPath() {
817
- return typeof window !== "undefined" ? window.location.pathname : "/";
818
- }
819
- // ---------------------------------------------------------------------------
820
- // Pixel script loaders
821
- // ---------------------------------------------------------------------------
822
- loadPixelScripts(config) {
823
- if (config.metaPixelId)
824
- this.loadMetaPixel(config.metaPixelId);
825
- if (config.tiktokPixelId)
826
- this.loadTikTokPixel(config.tiktokPixelId);
827
- if (config.snapchatPixelId)
828
- this.loadSnapchatPixel(config.snapchatPixelId);
829
- if (config.gtmId)
830
- this.loadGTM(config.gtmId);
831
- if (config.gaId)
832
- this.loadGA(config.gaId);
833
- }
834
- loadMetaPixel(pixelId) {
835
- if (typeof window === "undefined")
836
- return;
837
- const w = window;
838
- if (w.fbq)
839
- return;
840
- const n = w.fbq = function(...args) {
841
- n.callMethod ? n.callMethod(...args) : n.queue.push(args);
842
- };
843
- n.queue = [];
844
- n.loaded = true;
845
- n.version = "2.0";
846
- this.injectScript("https://connect.facebook.net/en_US/fbevents.js");
847
- w.fbq("init", pixelId);
848
- }
849
- loadTikTokPixel(pixelId) {
850
- if (typeof window === "undefined")
851
- return;
852
- const w = window;
853
- if (w.ttq)
854
- return;
855
- const ttq = {};
856
- ttq.methods = ["page", "track", "identify", "instances", "debug", "on", "off", "once", "ready", "alias", "group", "enableCookie", "disableCookie"];
857
- ttq.setAndDefer = function(t, e) {
858
- t[e] = function(...args) {
859
- t.push([e, ...args]);
860
- };
861
- };
862
- w.ttq = ttq;
863
- this.injectScript("https://analytics.tiktok.com/i18n/pixel/events.js?sdkid=" + pixelId);
864
- }
865
- loadSnapchatPixel(pixelId) {
866
- if (typeof window === "undefined")
867
- return;
868
- const w = window;
869
- if (w.snaptr)
870
- return;
871
- w.snaptr = function(...args) {
872
- w.snaptr.handleRequest ? w.snaptr.handleRequest(...args) : w.snaptr.queue.push(args);
873
- };
874
- w.snaptr.queue = [];
875
- this.injectScript("https://sc-static.net/scevent.min.js");
876
- w.snaptr("init", pixelId);
877
- }
878
- loadGTM(gtmId) {
879
- if (typeof window === "undefined")
880
- return;
881
- const w = window;
882
- w.dataLayer = w.dataLayer ?? [];
883
- w.dataLayer.push({ "gtm.start": Date.now(), event: "gtm.js" });
884
- this.injectScript(`https://www.googletagmanager.com/gtm.js?id=${gtmId}`);
885
- }
886
- loadGA(gaId) {
887
- if (typeof window === "undefined")
888
- return;
889
- this.injectScript(`https://www.googletagmanager.com/gtag/js?id=${gaId}`);
890
- const w = window;
891
- w.dataLayer = w.dataLayer ?? [];
892
- w.gtag = function(...args) {
893
- w.dataLayer.push(args);
894
- };
895
- w.gtag("js", /* @__PURE__ */ new Date());
896
- w.gtag("config", gaId);
897
- }
898
- injectScript(src) {
899
- if (typeof document === "undefined")
900
- return;
901
- const s = document.createElement("script");
902
- s.async = true;
903
- s.src = src;
904
- document.head.appendChild(s);
753
+ if (queryParts.length)
754
+ url += `?${queryParts.join("&")}`;
755
+ const res = await this.http.get(url);
756
+ return res.offers ?? [];
905
757
  }
906
758
  // ---------------------------------------------------------------------------
907
- // Event dispatchers per pixel
759
+ // Preview & pay (one-click upsell flow from plugin-sdk)
908
760
  // ---------------------------------------------------------------------------
909
- sendToMeta(event, data) {
910
- const w = typeof window !== "undefined" ? window : null;
911
- const fbq = w == null ? void 0 : w.fbq;
912
- if (!fbq)
913
- return;
914
- const metaEventMap = {
915
- PageView: "PageView",
916
- ViewContent: "ViewContent",
917
- AddToCart: "AddToCart",
918
- InitiateCheckout: "InitiateCheckout",
919
- AddPaymentInfo: "AddPaymentInfo",
920
- Purchase: "Purchase"
921
- };
922
- const mapped = metaEventMap[event];
923
- if (mapped) {
924
- fbq("track", mapped, data);
925
- } else {
926
- fbq("trackCustom", event, data);
927
- }
928
- }
929
- sendToTikTok(event, data) {
930
- var _a, _b;
931
- const w = typeof window !== "undefined" ? window : null;
932
- const ttq = w == null ? void 0 : w.ttq;
933
- if (!ttq)
934
- return;
935
- if (event === "PageView") {
936
- (_a = ttq.page) == null ? void 0 : _a.call(ttq);
937
- } else {
938
- (_b = ttq.track) == null ? void 0 : _b.call(ttq, event, data);
939
- }
940
- }
941
- sendToSnapchat(event, data) {
942
- const w = typeof window !== "undefined" ? window : null;
943
- const snaptr = w == null ? void 0 : w.snaptr;
944
- if (!snaptr)
945
- return;
946
- const snapEventMap = {
947
- PageView: "PAGE_VIEW",
948
- ViewContent: "VIEW_CONTENT",
949
- AddToCart: "ADD_CART",
950
- InitiateCheckout: "START_CHECKOUT",
951
- Purchase: "PURCHASE"
952
- };
953
- const mapped = snapEventMap[event];
954
- if (mapped)
955
- snaptr("track", mapped, data);
956
- }
957
- sendToGTM(event, data) {
958
- const w = typeof window !== "undefined" ? window : null;
959
- const dataLayer = w == null ? void 0 : w.dataLayer;
960
- if (!dataLayer)
961
- return;
962
- dataLayer.push({ event, ...data });
963
- }
964
- sendToGA(event, data) {
965
- const w = typeof window !== "undefined" ? window : null;
966
- const gtag = w == null ? void 0 : w.gtag;
967
- if (!gtag)
968
- return;
969
- gtag("event", event, data);
970
- }
971
- };
972
-
973
- // src/core/modules/offers.ts
974
- var OffersModule = class {
975
- constructor(http, storeId) {
976
- this.http = http;
977
- this.storeId = storeId;
978
- }
979
- /** Load offer details by ID. */
980
- async loadOffer(offerId) {
981
- const res = await this.http.get(
982
- `/api/v1/checkout-offers/${offerId}`,
983
- { params: { storeId: this.storeId } }
984
- );
985
- return res.offer;
986
- }
987
- /** List all offers for the store. */
988
- async listOffers(opts) {
989
- const res = await this.http.get(
990
- "/api/v1/checkout-offers",
991
- { params: { storeId: this.storeId, type: opts == null ? void 0 : opts.type } }
992
- );
993
- return res.offers;
761
+ /** Preview offer pricing. Returns line items with amounts and totals. */
762
+ async previewOffer(opts) {
763
+ return this.http.post(`/api/v1/offers/${opts.offerId}/preview`, {
764
+ offerId: opts.offerId,
765
+ currency: opts.currency ?? "",
766
+ lineItems: opts.lineItems
767
+ });
994
768
  }
995
769
  /**
996
- * Accept an offer (one-click upsell).
997
- * Charges the stored payment instrument from the main checkout order.
770
+ * Pay a previously previewed offer (one-click charge).
771
+ * Used after a main order so the stored payment instrument is reused.
998
772
  */
999
- async acceptOffer(opts) {
1000
- return this.http.post("/api/v1/checkout-offers/accept", {
773
+ async payPreviewedOffer(opts) {
774
+ return this.http.post(`/api/v1/offers/${opts.offerId}/pay-preview`, {
1001
775
  offerId: opts.offerId,
1002
- checkoutSessionId: opts.checkoutSessionId,
1003
- storeId: this.storeId,
776
+ currency: opts.currency ?? "",
777
+ lineItems: opts.lineItems,
778
+ returnUrl: opts.returnUrl ?? (typeof window !== "undefined" ? window.location.href : ""),
779
+ mainOrderId: opts.mainOrderId,
1004
780
  paymentInstrumentId: opts.paymentInstrumentId
1005
781
  });
1006
782
  }
1007
- /** Decline an offer. Advances the funnel to the next step. */
1008
- async declineOffer(opts) {
1009
- return this.http.post("/api/v1/checkout-offers/decline", {
1010
- offerId: opts.offerId,
1011
- checkoutSessionId: opts.checkoutSessionId,
1012
- storeId: this.storeId
1013
- });
783
+ // ---------------------------------------------------------------------------
784
+ // Order bumps (checkout-session scoped)
785
+ // ---------------------------------------------------------------------------
786
+ /** Toggle an order bump on/off within a checkout session. */
787
+ async toggleOrderBump(opts) {
788
+ return this.http.post(
789
+ `/api/v1/checkout-sessions/${opts.checkoutSessionId}/toggle-order-bump`,
790
+ {
791
+ orderBumpOfferId: opts.orderBumpOfferId,
792
+ selected: opts.selected
793
+ }
794
+ );
1014
795
  }
1015
- /** List order bumps available for a checkout session (shown on the checkout page). */
1016
- async listOrderBumps(checkoutSessionId) {
1017
- const res = await this.http.get(
1018
- "/api/v1/checkout-offers",
1019
- { params: { storeId: this.storeId, checkoutSessionId, type: "orderbump" } }
796
+ // ---------------------------------------------------------------------------
797
+ // Post-purchase offers (order-scoped)
798
+ // ---------------------------------------------------------------------------
799
+ /** List post-purchase offers for an order. */
800
+ async listPostPurchaseOffers(orderId) {
801
+ const res = await this.http.get(`/api/v1/post-purchase/${orderId}/offers`);
802
+ return Array.isArray(res) ? res : [];
803
+ }
804
+ /** Accept a post-purchase offer. */
805
+ async acceptPostPurchaseOffer(opts) {
806
+ return this.http.post(
807
+ `/api/v1/orders/${opts.orderId}/post-purchase-offers/${opts.offerId}/accept`,
808
+ { items: opts.items ?? [] }
1020
809
  );
1021
- return res.offers;
1022
810
  }
1023
- /** Toggle an order bump on/off for a checkout session. */
1024
- async toggleOrderBump(opts) {
1025
- await this.http.post(`/api/v1/checkout-sessions/${opts.checkoutSessionId}/order-bumps`, {
1026
- offerId: opts.offerId,
1027
- selected: opts.selected
1028
- });
811
+ /** Decline a post-purchase offer. */
812
+ async declinePostPurchaseOffer(opts) {
813
+ return this.http.post(
814
+ `/api/v1/orders/${opts.orderId}/post-purchase-offers/${opts.offerId}/decline`
815
+ );
1029
816
  }
1030
817
  };
1031
818
 
@@ -1155,7 +942,6 @@ var TagadaHeadlessBundle = (() => {
1155
942
  };
1156
943
  this.checkout = new CheckoutModule(this.http, this.config.storeId, setToken);
1157
944
  this.payment = new PaymentModule(this.http, this.config.storeId, environment);
1158
- this.analytics = new AnalyticsModule(this.http, this.config.storeId);
1159
945
  this.offers = new OffersModule(this.http, this.config.storeId);
1160
946
  this.customer = new CustomerModule(this.http, this.config.storeId);
1161
947
  this.catalog = new CatalogModule(this.http, this.config.storeId);
@@ -1168,6 +954,464 @@ var TagadaHeadlessBundle = (() => {
1168
954
  function createHeadlessClient(config) {
1169
955
  return new HeadlessClient(config);
1170
956
  }
957
+
958
+ // src/core/helpers/autocomplete.ts
959
+ var scriptInjected = false;
960
+ var scriptReady = false;
961
+ var readyCallbacks = [];
962
+ function onScriptReady() {
963
+ scriptReady = true;
964
+ for (const cb of readyCallbacks)
965
+ cb();
966
+ readyCallbacks.length = 0;
967
+ }
968
+ function loadGoogleMapsScript(apiKey, opts = {}) {
969
+ var _a, _b;
970
+ if (scriptReady || ((_b = (_a = window.google) == null ? void 0 : _a.maps) == null ? void 0 : _b.places)) {
971
+ onScriptReady();
972
+ return Promise.resolve();
973
+ }
974
+ if (scriptInjected) {
975
+ return new Promise((resolve) => readyCallbacks.push(resolve));
976
+ }
977
+ scriptInjected = true;
978
+ return new Promise((resolve, reject) => {
979
+ readyCallbacks.push(resolve);
980
+ const existing = document.querySelector('script[src*="maps.googleapis.com"]');
981
+ if (existing) {
982
+ const poll = () => {
983
+ var _a2, _b2;
984
+ if ((_b2 = (_a2 = window.google) == null ? void 0 : _a2.maps) == null ? void 0 : _b2.places) {
985
+ onScriptReady();
986
+ } else {
987
+ setTimeout(poll, 100);
988
+ }
989
+ };
990
+ poll();
991
+ return;
992
+ }
993
+ const params = new URLSearchParams({
994
+ key: apiKey,
995
+ libraries: "places",
996
+ v: opts.version ?? "weekly"
997
+ });
998
+ if (opts.language)
999
+ params.set("language", opts.language);
1000
+ if (opts.region)
1001
+ params.set("region", opts.region);
1002
+ const script = document.createElement("script");
1003
+ script.src = `https://maps.googleapis.com/maps/api/js?${params}`;
1004
+ script.async = true;
1005
+ script.defer = true;
1006
+ script.onload = () => onScriptReady();
1007
+ script.onerror = () => reject(new Error("Failed to load Google Maps script"));
1008
+ document.head.appendChild(script);
1009
+ });
1010
+ }
1011
+ var GoogleAutocompleteCore = class _GoogleAutocompleteCore {
1012
+ /** Search for address predictions. */
1013
+ static async searchPlaces(input, options = {}) {
1014
+ var _a, _b;
1015
+ if (!((_b = (_a = window.google) == null ? void 0 : _a.maps) == null ? void 0 : _b.places) || !input.trim())
1016
+ return [];
1017
+ const service = new window.google.maps.places.AutocompleteService();
1018
+ return new Promise((resolve) => {
1019
+ service.getPlacePredictions(
1020
+ { input, types: options.types ?? ["address"], componentRestrictions: options.componentRestrictions },
1021
+ (predictions, status) => {
1022
+ var _a2, _b2, _c;
1023
+ resolve(status === ((_c = (_b2 = (_a2 = window.google) == null ? void 0 : _a2.maps) == null ? void 0 : _b2.places) == null ? void 0 : _c.PlacesServiceStatus.OK) && predictions ? predictions : []);
1024
+ }
1025
+ );
1026
+ });
1027
+ }
1028
+ /** Get full place details by place_id. */
1029
+ static async getPlaceDetails(placeId) {
1030
+ var _a, _b;
1031
+ if (!((_b = (_a = window.google) == null ? void 0 : _a.maps) == null ? void 0 : _b.places))
1032
+ return null;
1033
+ const svc = new window.google.maps.places.PlacesService(document.createElement("div"));
1034
+ return new Promise((resolve) => {
1035
+ svc.getDetails(
1036
+ { placeId, fields: ["place_id", "formatted_address", "address_components", "geometry"] },
1037
+ (place, status) => {
1038
+ var _a2, _b2, _c;
1039
+ resolve(status === ((_c = (_b2 = (_a2 = window.google) == null ? void 0 : _a2.maps) == null ? void 0 : _b2.places) == null ? void 0 : _c.PlacesServiceStatus.OK) && place ? place : null);
1040
+ }
1041
+ );
1042
+ });
1043
+ }
1044
+ /** Extract structured address fields from a Google PlaceDetails result. */
1045
+ static extractAddressComponents(place) {
1046
+ const out = {
1047
+ subpremise: "",
1048
+ streetNumber: "",
1049
+ route: "",
1050
+ locality: "",
1051
+ administrativeAreaLevel1: "",
1052
+ administrativeAreaLevel1Long: "",
1053
+ administrativeAreaLevel2: "",
1054
+ administrativeAreaLevel2Long: "",
1055
+ country: "",
1056
+ postalCode: "",
1057
+ fullStreetAddress: ""
1058
+ };
1059
+ let premise = "";
1060
+ let neighborhood = "";
1061
+ let sublocality5 = "", sublocality4 = "", sublocality3 = "", sublocality2 = "", sublocality1 = "";
1062
+ let postalTown = "";
1063
+ for (const c of place.address_components ?? []) {
1064
+ const t = c.types;
1065
+ if (t.includes("subpremise"))
1066
+ out.subpremise = c.long_name;
1067
+ if (t.includes("street_number"))
1068
+ out.streetNumber = c.long_name;
1069
+ if (t.includes("premise"))
1070
+ premise = c.long_name;
1071
+ if (t.includes("route"))
1072
+ out.route = c.long_name;
1073
+ if (t.includes("neighborhood"))
1074
+ neighborhood = c.long_name;
1075
+ if (t.includes("sublocality_level_5"))
1076
+ sublocality5 = c.long_name;
1077
+ if (t.includes("sublocality_level_4"))
1078
+ sublocality4 = c.long_name;
1079
+ if (t.includes("sublocality_level_3"))
1080
+ sublocality3 = c.long_name;
1081
+ if (t.includes("sublocality_level_2"))
1082
+ sublocality2 = c.long_name;
1083
+ if (t.includes("sublocality_level_1"))
1084
+ sublocality1 = c.long_name;
1085
+ if (t.includes("locality"))
1086
+ out.locality = c.long_name;
1087
+ if (t.includes("postal_town"))
1088
+ postalTown = c.long_name;
1089
+ if (t.includes("administrative_area_level_2")) {
1090
+ out.administrativeAreaLevel2 = c.short_name;
1091
+ out.administrativeAreaLevel2Long = c.long_name;
1092
+ }
1093
+ if (t.includes("administrative_area_level_1")) {
1094
+ out.administrativeAreaLevel1 = c.short_name;
1095
+ out.administrativeAreaLevel1Long = c.long_name;
1096
+ }
1097
+ if (t.includes("country"))
1098
+ out.country = c.short_name;
1099
+ if (t.includes("postal_code"))
1100
+ out.postalCode = c.long_name;
1101
+ }
1102
+ if (!out.locality)
1103
+ out.locality = postalTown || sublocality2 || sublocality1 || "";
1104
+ if (!out.administrativeAreaLevel1 && out.administrativeAreaLevel2) {
1105
+ out.administrativeAreaLevel1 = out.administrativeAreaLevel2Long || out.administrativeAreaLevel2;
1106
+ out.administrativeAreaLevel1Long = out.administrativeAreaLevel2Long;
1107
+ }
1108
+ const buildingNumber = out.streetNumber || premise;
1109
+ const streetName = out.route || sublocality5 || sublocality4 || sublocality3 || neighborhood;
1110
+ if (out.subpremise && buildingNumber && streetName) {
1111
+ out.fullStreetAddress = `${out.subpremise}/${buildingNumber} ${streetName}`;
1112
+ } else if (buildingNumber && streetName) {
1113
+ if (premise && sublocality4 && sublocality3) {
1114
+ let addr = `${sublocality3}-${sublocality4}-${premise}`;
1115
+ if (sublocality2)
1116
+ addr = `${addr} ${sublocality2}`;
1117
+ out.fullStreetAddress = addr;
1118
+ } else {
1119
+ out.fullStreetAddress = `${buildingNumber} ${streetName}`;
1120
+ }
1121
+ } else if (streetName) {
1122
+ out.fullStreetAddress = streetName;
1123
+ } else if (buildingNumber) {
1124
+ out.fullStreetAddress = buildingNumber;
1125
+ }
1126
+ out.fullStreetAddress = out.fullStreetAddress.trim();
1127
+ return out;
1128
+ }
1129
+ /** Shorthand: extract into the flat shape used by address forms. */
1130
+ static extractFormattedAddress(place) {
1131
+ const a = _GoogleAutocompleteCore.extractAddressComponents(place);
1132
+ return {
1133
+ address1: a.fullStreetAddress,
1134
+ city: a.locality,
1135
+ country: a.country,
1136
+ state: a.administrativeAreaLevel1,
1137
+ postal: a.postalCode
1138
+ };
1139
+ }
1140
+ };
1141
+
1142
+ // src/core/helpers/iso3166.ts
1143
+ var GEODATA_CDN_BASE = "https://cvwnizdbugpz6jwk.public.blob.vercel-storage.com/geodata/v1";
1144
+ var AVAILABLE_LANGUAGES = ["en", "ru", "de", "da", "fr", "es", "zh", "hi", "pt", "ja", "ar", "it", "he"];
1145
+ var countriesCache = /* @__PURE__ */ new Map();
1146
+ var regionsCache = /* @__PURE__ */ new Map();
1147
+ var inflightCountries = /* @__PURE__ */ new Map();
1148
+ var inflightRegions = /* @__PURE__ */ new Map();
1149
+ async function fetchCountriesRaw(language) {
1150
+ const cached = countriesCache.get(language);
1151
+ if (cached)
1152
+ return cached;
1153
+ let inflight = inflightCountries.get(language);
1154
+ if (inflight)
1155
+ return inflight;
1156
+ inflight = (async () => {
1157
+ const url = `${GEODATA_CDN_BASE}/${language}/countries.json`;
1158
+ const res = await fetch(url);
1159
+ if (!res.ok)
1160
+ throw new Error(`Geodata fetch failed: ${url} (${res.status})`);
1161
+ const data = await res.json();
1162
+ countriesCache.set(language, data);
1163
+ inflightCountries.delete(language);
1164
+ return data;
1165
+ })();
1166
+ inflightCountries.set(language, inflight);
1167
+ return inflight;
1168
+ }
1169
+ async function fetchRegionsRaw(language) {
1170
+ const cached = regionsCache.get(language);
1171
+ if (cached)
1172
+ return cached;
1173
+ let inflight = inflightRegions.get(language);
1174
+ if (inflight)
1175
+ return inflight;
1176
+ inflight = (async () => {
1177
+ const url = `${GEODATA_CDN_BASE}/${language}/regions.json`;
1178
+ const res = await fetch(url);
1179
+ if (!res.ok)
1180
+ throw new Error(`Geodata fetch failed: ${url} (${res.status})`);
1181
+ const data = await res.json();
1182
+ regionsCache.set(language, data);
1183
+ inflightRegions.delete(language);
1184
+ return data;
1185
+ })();
1186
+ inflightRegions.set(language, inflight);
1187
+ return inflight;
1188
+ }
1189
+ function getCountriesCached(language) {
1190
+ return countriesCache.get(language) || countriesCache.get("en") || {};
1191
+ }
1192
+ function getRegionsCached(language) {
1193
+ return regionsCache.get(language) || regionsCache.get("en") || {};
1194
+ }
1195
+ async function ensureGeoDataLoaded(language = "en") {
1196
+ await Promise.all([fetchCountriesRaw(language), fetchRegionsRaw(language)]);
1197
+ }
1198
+ var getCountries = (language = "en") => {
1199
+ const raw = getCountriesCached(language);
1200
+ return Object.entries(raw).map(([code, c]) => ({ code, name: c.n, iso3: c.i3, numeric: c.nu })).sort((a, b) => a.name.localeCompare(b.name));
1201
+ };
1202
+ var getStatesForCountry = (countryCode, language = "en") => {
1203
+ const raw = getRegionsCached(language);
1204
+ const tuples = raw[countryCode];
1205
+ if (!tuples)
1206
+ return [];
1207
+ return tuples.map(([iso, name]) => ({ code: iso, name, countryCode })).sort((a, b) => a.name.localeCompare(b.name));
1208
+ };
1209
+ function isLanguageLoaded(language) {
1210
+ return countriesCache.has(language);
1211
+ }
1212
+
1213
+ // src/core/helpers/countries.ts
1214
+ var ISODataCore = class _ISODataCore {
1215
+ /** Fetch countries + regions from CDN for a language. Call before sync getters. */
1216
+ static ensureLoaded(language = "en") {
1217
+ return ensureGeoDataLoaded(language);
1218
+ }
1219
+ /** Get all countries as a Record keyed by ISO code. */
1220
+ static getCountries(language = "en") {
1221
+ const arr = getCountries(language);
1222
+ const result = {};
1223
+ for (const c of arr) {
1224
+ result[c.code] = { iso: c.code, iso3: c.iso3 ?? "", numeric: c.numeric ?? 0, name: c.name };
1225
+ }
1226
+ return result;
1227
+ }
1228
+ /** Get all countries as a sorted array of { value, label } for select inputs. */
1229
+ static getCountryOptions(language = "en") {
1230
+ return getCountries(language).map((c) => ({ value: c.code, label: c.name }));
1231
+ }
1232
+ /** Get regions/states for a country. */
1233
+ static getRegions(countryCode, language = "en") {
1234
+ return getStatesForCountry(countryCode, language).map((s) => ({ iso: s.code, name: s.name }));
1235
+ }
1236
+ /** Get regions as a sorted array of { value, label } for select inputs. */
1237
+ static getRegionOptions(countryCode, language = "en") {
1238
+ return _ISODataCore.getRegions(countryCode, language).map((r) => ({ value: r.iso, label: r.name }));
1239
+ }
1240
+ /** Find a specific region by ISO code. */
1241
+ static findRegion(countryCode, regionCode, language = "en") {
1242
+ return _ISODataCore.getRegions(countryCode, language).find((r) => r.iso === regionCode) ?? null;
1243
+ }
1244
+ /**
1245
+ * Map a Google Places administrative_area to an ISO region.
1246
+ * Tries exact ISO match, then name match, then partial match.
1247
+ */
1248
+ static mapGoogleToISO(googleState, googleStateLong, countryCode, language = "en") {
1249
+ const regions = _ISODataCore.getRegions(countryCode, language);
1250
+ if (regions.length === 0)
1251
+ return null;
1252
+ let match = regions.find((r) => r.iso === googleState);
1253
+ if (match)
1254
+ return match;
1255
+ match = regions.find((r) => r.name.toLowerCase() === googleState.toLowerCase());
1256
+ if (match)
1257
+ return match;
1258
+ match = regions.find((r) => r.name.toLowerCase() === googleStateLong.toLowerCase());
1259
+ if (match)
1260
+ return match;
1261
+ match = regions.find(
1262
+ (r) => r.name.toLowerCase().includes(googleStateLong.toLowerCase()) || googleStateLong.toLowerCase().includes(r.name.toLowerCase())
1263
+ );
1264
+ return match ?? null;
1265
+ }
1266
+ static isLanguageLoaded(language) {
1267
+ return isLanguageLoaded(language);
1268
+ }
1269
+ static getAvailableLanguages() {
1270
+ return AVAILABLE_LANGUAGES;
1271
+ }
1272
+ };
1273
+
1274
+ // src/core/helpers/currency.ts
1275
+ var SYMBOLS = {
1276
+ USD: "$",
1277
+ EUR: "\u20AC",
1278
+ GBP: "\xA3",
1279
+ JPY: "\xA5",
1280
+ CAD: "C$",
1281
+ AUD: "A$",
1282
+ CHF: "CHF",
1283
+ CNY: "\xA5",
1284
+ SEK: "kr",
1285
+ NOK: "kr",
1286
+ DKK: "kr",
1287
+ PLN: "z\u0142",
1288
+ CZK: "K\u010D",
1289
+ HUF: "Ft",
1290
+ RON: "lei",
1291
+ BGN: "\u043B\u0432",
1292
+ HRK: "kn",
1293
+ RUB: "\u20BD",
1294
+ UAH: "\u20B4",
1295
+ TRY: "\u20BA",
1296
+ BRL: "R$",
1297
+ MXN: "$",
1298
+ ZAR: "R",
1299
+ INR: "\u20B9",
1300
+ KRW: "\u20A9",
1301
+ THB: "\u0E3F",
1302
+ VND: "\u20AB",
1303
+ IDR: "Rp",
1304
+ MYR: "RM",
1305
+ SGD: "S$",
1306
+ PHP: "\u20B1",
1307
+ TWD: "NT$",
1308
+ HKD: "HK$",
1309
+ ILS: "\u20AA",
1310
+ AED: "\u062F.\u0625",
1311
+ SAR: "\u0631.\u0633",
1312
+ QAR: "\u0631.\u0642",
1313
+ KWD: "\u062F.\u0643",
1314
+ BHD: "\u062F.\u0628",
1315
+ OMR: "\u0631.\u0639.",
1316
+ EGP: "\xA3",
1317
+ NGN: "\u20A6",
1318
+ KES: "KSh",
1319
+ GHS: "\u20B5",
1320
+ COP: "$",
1321
+ ARS: "$",
1322
+ CLP: "$",
1323
+ PEN: "S/",
1324
+ CRC: "\u20A1",
1325
+ DOP: "RD$",
1326
+ JMD: "J$",
1327
+ BOB: "Bs",
1328
+ PYG: "\u20B2",
1329
+ GTQ: "Q",
1330
+ NIO: "C$",
1331
+ PAB: "B/.",
1332
+ PKR: "\u20A8",
1333
+ BDT: "\u09F3",
1334
+ LKR: "\u20A8",
1335
+ NPR: "\u20A8",
1336
+ GEL: "\u20BE",
1337
+ AMD: "\u058F",
1338
+ AZN: "\u20BC",
1339
+ KZT: "\u20B8"
1340
+ };
1341
+ var NAMES = {
1342
+ USD: "US Dollar",
1343
+ EUR: "Euro",
1344
+ GBP: "British Pound",
1345
+ JPY: "Japanese Yen",
1346
+ CAD: "Canadian Dollar",
1347
+ AUD: "Australian Dollar",
1348
+ CHF: "Swiss Franc",
1349
+ CNY: "Chinese Yuan",
1350
+ SEK: "Swedish Krona",
1351
+ NOK: "Norwegian Krone",
1352
+ DKK: "Danish Krone",
1353
+ PLN: "Polish Zloty",
1354
+ CZK: "Czech Koruna",
1355
+ HUF: "Hungarian Forint",
1356
+ BRL: "Brazilian Real",
1357
+ MXN: "Mexican Peso",
1358
+ INR: "Indian Rupee",
1359
+ KRW: "South Korean Won",
1360
+ THB: "Thai Baht",
1361
+ SGD: "Singapore Dollar",
1362
+ HKD: "Hong Kong Dollar",
1363
+ TWD: "Taiwan Dollar",
1364
+ ILS: "Israeli Shekel",
1365
+ AED: "UAE Dirham",
1366
+ SAR: "Saudi Riyal",
1367
+ ZAR: "South African Rand",
1368
+ TRY: "Turkish Lira",
1369
+ RUB: "Russian Ruble",
1370
+ NGN: "Nigerian Naira"
1371
+ };
1372
+ var ZERO_DECIMAL = /* @__PURE__ */ new Set([
1373
+ "JPY",
1374
+ "KRW",
1375
+ "VND",
1376
+ "IDR",
1377
+ "LAK",
1378
+ "KHR",
1379
+ "MMK",
1380
+ "PYG"
1381
+ ]);
1382
+ var CurrencyUtils = class _CurrencyUtils {
1383
+ static getSymbol(code) {
1384
+ return SYMBOLS[code] ?? code;
1385
+ }
1386
+ static getName(code) {
1387
+ return NAMES[code] ?? code;
1388
+ }
1389
+ static getDecimalPlaces(code) {
1390
+ return ZERO_DECIMAL.has(code) ? 0 : 2;
1391
+ }
1392
+ static getCurrency(code) {
1393
+ return {
1394
+ code,
1395
+ symbol: _CurrencyUtils.getSymbol(code),
1396
+ name: _CurrencyUtils.getName(code),
1397
+ decimalPlaces: _CurrencyUtils.getDecimalPlaces(code)
1398
+ };
1399
+ }
1400
+ };
1401
+ function formatMoney(amountMinorUnits, currencyCode = "USD", locale = "en-US") {
1402
+ const decimals = CurrencyUtils.getDecimalPlaces(currencyCode);
1403
+ const value = amountMinorUnits / (decimals === 0 ? 100 : Math.pow(10, decimals));
1404
+ try {
1405
+ return new Intl.NumberFormat(locale, {
1406
+ style: "currency",
1407
+ currency: currencyCode,
1408
+ minimumFractionDigits: decimals,
1409
+ maximumFractionDigits: decimals
1410
+ }).format(value);
1411
+ } catch {
1412
+ return `${CurrencyUtils.getSymbol(currencyCode)}${value.toFixed(decimals)}`;
1413
+ }
1414
+ }
1171
1415
  return __toCommonJS(core_exports);
1172
1416
  })();
1173
1417
  if(typeof window!=="undefined"&&TagadaHeadlessBundle){ window.TagadaHeadless=TagadaHeadlessBundle; window.TagadaHeadless.create=TagadaHeadlessBundle.createHeadlessClient;}