@virex-tech/paywallo-sdk 2.5.3 → 2.6.2

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.
package/dist/index.js CHANGED
@@ -491,7 +491,7 @@ async function readAnonIdDurably(storage) {
491
491
  if (secure) return secure;
492
492
  return nativeStorage.get(ANON_ID_FALLBACK_KEY);
493
493
  }
494
- var DEVICE_ID_KEY, ANON_ID_FALLBACK_KEY, ANON_ID_KEY, USER_EMAIL_KEY, USER_PROPERTIES_KEY, USER_DISTINCT_ID_KEY, USER_NAME_KEY, USER_COUNTRY_KEY, USER_LOCALE_KEY, USER_PHONE_KEY, USER_FIRST_NAME_KEY, USER_LAST_NAME_KEY, USER_DOB_KEY, USER_GENDER_KEY, LEGACY_USER_PHONE_KEY, LEGACY_USER_FIRST_NAME_KEY, LEGACY_USER_LAST_NAME_KEY, LEGACY_USER_DOB_KEY, LEGACY_USER_GENDER_KEY, LEGACY_DEVICE_ID_KEY, LEGACY_ANON_ID_KEY, LEGACY_EMAIL_KEY, LEGACY_PROPERTIES_KEY, LEGACY_DISTINCT_ID_KEY, LEGACY_NAME_KEY, LEGACY_COUNTRY_KEY, LEGACY_LOCALE_KEY, ANON_ID_SET_RETRIES, ANON_ID_RETRY_DELAY_MS;
494
+ var DEVICE_ID_KEY, ANON_ID_FALLBACK_KEY, ANON_ID_KEY, USER_EMAIL_KEY, USER_PROPERTIES_KEY, USER_DISTINCT_ID_KEY, USER_NAME_KEY, USER_COUNTRY_KEY, USER_LOCALE_KEY, USER_PHONE_KEY, USER_FIRST_NAME_KEY, USER_LAST_NAME_KEY, USER_DOB_KEY, USER_GENDER_KEY, USER_ZIP_KEY, LEGACY_USER_PHONE_KEY, LEGACY_USER_FIRST_NAME_KEY, LEGACY_USER_LAST_NAME_KEY, LEGACY_USER_DOB_KEY, LEGACY_USER_GENDER_KEY, LEGACY_DEVICE_ID_KEY, LEGACY_ANON_ID_KEY, LEGACY_EMAIL_KEY, LEGACY_PROPERTIES_KEY, LEGACY_DISTINCT_ID_KEY, LEGACY_NAME_KEY, LEGACY_COUNTRY_KEY, LEGACY_LOCALE_KEY, ANON_ID_SET_RETRIES, ANON_ID_RETRY_DELAY_MS;
495
495
  var init_IdentityStorage = __esm({
496
496
  "src/domains/identity/IdentityStorage.ts"() {
497
497
  "use strict";
@@ -510,6 +510,7 @@ var init_IdentityStorage = __esm({
510
510
  USER_LAST_NAME_KEY = "@paywallo:user_last_name";
511
511
  USER_DOB_KEY = "@paywallo:user_dob";
512
512
  USER_GENDER_KEY = "@paywallo:user_gender";
513
+ USER_ZIP_KEY = "@paywallo:user_zip";
513
514
  LEGACY_USER_PHONE_KEY = "@panel:user_phone";
514
515
  LEGACY_USER_FIRST_NAME_KEY = "@panel:user_first_name";
515
516
  LEGACY_USER_LAST_NAME_KEY = "@panel:user_last_name";
@@ -560,6 +561,7 @@ var init_IdentityManager = __esm({
560
561
  this.lastName = null;
561
562
  this.dateOfBirth = null;
562
563
  this.gender = null;
564
+ this.zipCode = null;
563
565
  this.apiClient = null;
564
566
  this.secureStorage = null;
565
567
  this.debug = false;
@@ -614,7 +616,7 @@ var init_IdentityManager = __esm({
614
616
  let email;
615
617
  let properties;
616
618
  if (options) {
617
- if ("email" in options || "properties" in options || "phone" in options || "firstName" in options || "lastName" in options || "dateOfBirth" in options || "gender" in options) {
619
+ if ("email" in options || "properties" in options || "phone" in options || "firstName" in options || "lastName" in options || "dateOfBirth" in options || "gender" in options || "zipCode" in options) {
618
620
  email = options.email;
619
621
  properties = options.properties;
620
622
  } else {
@@ -655,6 +657,10 @@ var init_IdentityManager = __esm({
655
657
  this.gender = opts.gender;
656
658
  await this.secureStorage.set(USER_GENDER_KEY, this.gender);
657
659
  }
660
+ if (opts?.zipCode) {
661
+ this.zipCode = opts.zipCode;
662
+ await this.secureStorage.set(USER_ZIP_KEY, this.zipCode);
663
+ }
658
664
  if (this.apiClient && this.anonId) {
659
665
  try {
660
666
  await this.apiClient.identify(this.anonId, properties, email, this.deviceId ?? void 0, {
@@ -662,11 +668,15 @@ var init_IdentityManager = __esm({
662
668
  firstName: this.firstName ?? void 0,
663
669
  lastName: this.lastName ?? void 0,
664
670
  dateOfBirth: this.dateOfBirth ?? void 0,
665
- gender: this.gender ?? void 0
671
+ gender: this.gender ?? void 0,
672
+ zipCode: this.zipCode ?? void 0
666
673
  });
674
+ if (this.debug) console.log("[Paywallo] identify confirmed", this.anonId.slice(0, 8));
667
675
  } catch (err) {
668
- if (this.debug) console.log("[Paywallo] identify dispatch error", err);
676
+ if (this.debug) console.log("[Paywallo] identify failed:", err);
669
677
  }
678
+ } else {
679
+ if (this.debug) console.log("[Paywallo] identify skipped \u2014 anonId not ready");
670
680
  }
671
681
  }
672
682
  getDistinctId() {
@@ -709,6 +719,7 @@ var init_IdentityManager = __esm({
709
719
  this.lastName = null;
710
720
  this.dateOfBirth = null;
711
721
  this.gender = null;
722
+ this.zipCode = null;
712
723
  await Promise.all([
713
724
  this.secureStorage?.set(ANON_ID_KEY, newAnonId) ?? Promise.resolve(false),
714
725
  this.secureStorage?.remove(USER_EMAIL_KEY) ?? Promise.resolve(false),
@@ -717,7 +728,8 @@ var init_IdentityManager = __esm({
717
728
  this.secureStorage?.remove(USER_FIRST_NAME_KEY) ?? Promise.resolve(false),
718
729
  this.secureStorage?.remove(USER_LAST_NAME_KEY) ?? Promise.resolve(false),
719
730
  this.secureStorage?.remove(USER_DOB_KEY) ?? Promise.resolve(false),
720
- this.secureStorage?.remove(USER_GENDER_KEY) ?? Promise.resolve(false)
731
+ this.secureStorage?.remove(USER_GENDER_KEY) ?? Promise.resolve(false),
732
+ this.secureStorage?.remove(USER_ZIP_KEY) ?? Promise.resolve(false)
721
733
  ]);
722
734
  }
723
735
  getState() {
@@ -729,7 +741,8 @@ var init_IdentityManager = __esm({
729
741
  firstName: this.firstName,
730
742
  lastName: this.lastName,
731
743
  dateOfBirth: this.dateOfBirth,
732
- gender: this.gender
744
+ gender: this.gender,
745
+ zipCode: this.zipCode
733
746
  };
734
747
  }
735
748
  isSecureStorageAvailable() {
@@ -947,17 +960,39 @@ var init_campaign = __esm({
947
960
  }
948
961
  });
949
962
 
963
+ // src/domains/identity/NativeAdvertisingId.ts
964
+ var import_react_native3, nativeModule, nativeAdvertisingId;
965
+ var init_NativeAdvertisingId = __esm({
966
+ "src/domains/identity/NativeAdvertisingId.ts"() {
967
+ "use strict";
968
+ import_react_native3 = require("react-native");
969
+ nativeModule = import_react_native3.NativeModules.PaywalloAdvertisingId ?? null;
970
+ nativeAdvertisingId = {
971
+ async getAdvertisingId() {
972
+ try {
973
+ return await nativeModule?.getAdvertisingId?.() ?? null;
974
+ } catch {
975
+ return null;
976
+ }
977
+ }
978
+ };
979
+ }
980
+ });
981
+
950
982
  // src/domains/identity/AdvertisingIdManager.ts
951
- var import_react_native3, ZERO_IDFA, AdvertisingIdManager, advertisingIdManager;
983
+ var import_react_native4, ZERO_IDFA, ATT_PROMPT_TIMEOUT_MS, AdvertisingIdManager, advertisingIdManager;
952
984
  var init_AdvertisingIdManager = __esm({
953
985
  "src/domains/identity/AdvertisingIdManager.ts"() {
954
986
  "use strict";
955
- import_react_native3 = require("react-native");
987
+ import_react_native4 = require("react-native");
956
988
  init_NativeDeviceInfo();
989
+ init_NativeAdvertisingId();
957
990
  ZERO_IDFA = "00000000-0000-0000-0000-000000000000";
991
+ ATT_PROMPT_TIMEOUT_MS = 4e3;
958
992
  AdvertisingIdManager = class {
959
- constructor() {
993
+ constructor(debug = false) {
960
994
  this.cached = null;
995
+ this.debug = debug;
961
996
  }
962
997
  /**
963
998
  * Synchronous accessor for the cached collect() result. Returns null until
@@ -972,9 +1007,12 @@ var init_AdvertisingIdManager = __esm({
972
1007
  return this.cached;
973
1008
  }
974
1009
  const fallback = { idfv: null, idfa: null, gaid: null, attStatus: "unavailable" };
1010
+ if (import_react_native4.Platform.OS === "android") {
1011
+ return this.collectAndroid();
1012
+ }
975
1013
  try {
976
1014
  const tracking = await import("expo-tracking-transparency");
977
- if (import_react_native3.Platform.OS === "ios") {
1015
+ if (import_react_native4.Platform.OS === "ios") {
978
1016
  if (!tracking.isAvailable()) {
979
1017
  const idfv2 = await this.collectIdfv();
980
1018
  const result2 = { ...fallback, idfv: idfv2 };
@@ -985,9 +1023,20 @@ var init_AdvertisingIdManager = __esm({
985
1023
  let status = current.status;
986
1024
  let granted = current.granted;
987
1025
  if (status === "undetermined" && requestATT) {
988
- const result2 = await tracking.requestTrackingPermissionsAsync();
989
- status = result2.status;
990
- granted = result2.granted;
1026
+ const result2 = await Promise.race([
1027
+ tracking.requestTrackingPermissionsAsync(),
1028
+ new Promise((r) => setTimeout(() => r(null), ATT_PROMPT_TIMEOUT_MS))
1029
+ ]);
1030
+ if (result2 === null) {
1031
+ if (this.debug) {
1032
+ console.log(`[Paywallo] ATT prompt timed out after ${ATT_PROMPT_TIMEOUT_MS}ms \u2014 treating as undetermined`);
1033
+ }
1034
+ status = "undetermined";
1035
+ granted = false;
1036
+ } else {
1037
+ status = result2.status;
1038
+ granted = result2.granted;
1039
+ }
991
1040
  }
992
1041
  const idfv = await this.collectIdfv();
993
1042
  const idfa = granted ? this.sanitizeId(tracking.getAdvertisingId()) : null;
@@ -995,12 +1044,6 @@ var init_AdvertisingIdManager = __esm({
995
1044
  if (idfv !== null) this.cached = result;
996
1045
  return result;
997
1046
  }
998
- if (import_react_native3.Platform.OS === "android") {
999
- const rawGaid = tracking.getAdvertisingId();
1000
- const gaid = this.sanitizeId(rawGaid);
1001
- this.cached = { idfv: null, idfa: null, gaid, attStatus: "unavailable" };
1002
- return this.cached;
1003
- }
1004
1047
  this.cached = fallback;
1005
1048
  return this.cached;
1006
1049
  } catch {
@@ -1008,6 +1051,27 @@ var init_AdvertisingIdManager = __esm({
1008
1051
  return this.cached;
1009
1052
  }
1010
1053
  }
1054
+ async collectAndroid() {
1055
+ const nativeGaid = this.sanitizeId(
1056
+ await Promise.race([
1057
+ nativeAdvertisingId.getAdvertisingId(),
1058
+ new Promise((r) => setTimeout(() => r(null), 1500))
1059
+ ])
1060
+ );
1061
+ if (nativeGaid !== null) {
1062
+ this.cached = { idfv: null, idfa: null, gaid: nativeGaid, attStatus: "unavailable" };
1063
+ return this.cached;
1064
+ }
1065
+ try {
1066
+ const tracking = await import("expo-tracking-transparency");
1067
+ const gaid = this.sanitizeId(tracking.getAdvertisingId());
1068
+ this.cached = { idfv: null, idfa: null, gaid, attStatus: "unavailable" };
1069
+ return this.cached;
1070
+ } catch {
1071
+ this.cached = { idfv: null, idfa: null, gaid: null, attStatus: "unavailable" };
1072
+ return this.cached;
1073
+ }
1074
+ }
1011
1075
  async collectIdfv() {
1012
1076
  const RETRY_DELAY_MS = 80;
1013
1077
  const MAX_ATTEMPTS = 3;
@@ -1151,11 +1215,11 @@ var init_sessionTracking = __esm({
1151
1215
  });
1152
1216
 
1153
1217
  // src/domains/session/SessionManager.ts
1154
- var import_react_native4, SESSION_ID_KEY, SESSION_START_KEY, LEGACY_SESSION_ID_KEY, LEGACY_SESSION_START_KEY, SESSION_TIMEOUT_MS, SessionManager, sessionManager;
1218
+ var import_react_native5, SESSION_ID_KEY, SESSION_START_KEY, LEGACY_SESSION_ID_KEY, LEGACY_SESSION_START_KEY, SESSION_TIMEOUT_MS, SessionManager, sessionManager;
1155
1219
  var init_SessionManager = __esm({
1156
1220
  "src/domains/session/SessionManager.ts"() {
1157
1221
  "use strict";
1158
- import_react_native4 = require("react-native");
1222
+ import_react_native5 = require("react-native");
1159
1223
  init_SecureStorage();
1160
1224
  init_uuid();
1161
1225
  init_distinctIdGuard();
@@ -1311,7 +1375,7 @@ var init_SessionManager = __esm({
1311
1375
  if (this.appStateSubscription) {
1312
1376
  this.appStateSubscription.remove();
1313
1377
  }
1314
- this.appStateSubscription = import_react_native4.AppState.addEventListener("change", this.handleAppStateChange);
1378
+ this.appStateSubscription = import_react_native5.AppState.addEventListener("change", this.handleAppStateChange);
1315
1379
  }
1316
1380
  async handleForeground() {
1317
1381
  const elapsed = this.backgroundTimestamp ? Date.now() - this.backgroundTimestamp : null;
@@ -1614,13 +1678,13 @@ var init_deferredAppLink = __esm({
1614
1678
  });
1615
1679
 
1616
1680
  // src/domains/identity/MetaBridge.ts
1617
- var import_react_native5, TIMEOUT_MS, NativeBridge, MetaBridge, metaBridge;
1681
+ var import_react_native6, TIMEOUT_MS, NativeBridge, MetaBridge, metaBridge;
1618
1682
  var init_MetaBridge = __esm({
1619
1683
  "src/domains/identity/MetaBridge.ts"() {
1620
1684
  "use strict";
1621
- import_react_native5 = require("react-native");
1685
+ import_react_native6 = require("react-native");
1622
1686
  TIMEOUT_MS = 2e3;
1623
- NativeBridge = import_react_native5.NativeModules.PaywalloFBBridge ?? null;
1687
+ NativeBridge = import_react_native6.NativeModules.PaywalloFBBridge ?? null;
1624
1688
  MetaBridge = class {
1625
1689
  constructor() {
1626
1690
  this.cachedAnonId = null;
@@ -1712,18 +1776,18 @@ var init_MetaBridge = __esm({
1712
1776
  });
1713
1777
 
1714
1778
  // src/domains/identity/InstallReferrerManager.ts
1715
- var import_react_native6, REFERRER_TIMEOUT_MS, InstallReferrerManager, installReferrerManager;
1779
+ var import_react_native7, REFERRER_TIMEOUT_MS, InstallReferrerManager, installReferrerManager;
1716
1780
  var init_InstallReferrerManager = __esm({
1717
1781
  "src/domains/identity/InstallReferrerManager.ts"() {
1718
1782
  "use strict";
1719
- import_react_native6 = require("react-native");
1783
+ import_react_native7 = require("react-native");
1720
1784
  init_NativeDeviceInfo();
1721
1785
  init_deferredAppLink();
1722
1786
  init_MetaBridge();
1723
1787
  REFERRER_TIMEOUT_MS = 5e3;
1724
1788
  InstallReferrerManager = class {
1725
1789
  async getReferrer() {
1726
- if (import_react_native6.Platform.OS !== "android") {
1790
+ if (import_react_native7.Platform.OS !== "android") {
1727
1791
  return this.fetchDeferredReferrer();
1728
1792
  }
1729
1793
  let timerId;
@@ -1829,11 +1893,11 @@ function extractDeferredAttribution(raw) {
1829
1893
  }
1830
1894
  return Object.keys(out).length > 0 ? out : null;
1831
1895
  }
1832
- var import_react_native7, InstallTracker, DEFERRED_ATTRIBUTION_FIELDS;
1896
+ var import_react_native8, InstallTracker, DEFERRED_ATTRIBUTION_FIELDS;
1833
1897
  var init_InstallTracker = __esm({
1834
1898
  "src/domains/identity/InstallTracker.ts"() {
1835
1899
  "use strict";
1836
- import_react_native7 = require("react-native");
1900
+ import_react_native8 = require("react-native");
1837
1901
  init_SecureStorage();
1838
1902
  init_NativeDeviceInfo();
1839
1903
  init_distinctIdGuard();
@@ -1889,10 +1953,10 @@ var init_InstallTracker = __esm({
1889
1953
  }
1890
1954
  let deviceData = {};
1891
1955
  try {
1892
- const screen = import_react_native7.Dimensions.get("screen");
1956
+ const screen = import_react_native8.Dimensions.get("screen");
1893
1957
  const screenWidth = Math.round(screen.width ?? 0);
1894
1958
  const screenHeight = Math.round(screen.height ?? 0);
1895
- const screenDensity = import_react_native7.PixelRatio.get();
1959
+ const screenDensity = import_react_native8.PixelRatio.get();
1896
1960
  const locale = Intl.DateTimeFormat().resolvedOptions().locale ?? "unknown";
1897
1961
  const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone ?? "unknown";
1898
1962
  const info = await nativeDeviceInfo.getDeviceInfo();
@@ -1953,13 +2017,14 @@ var init_InstallTracker = __esm({
1953
2017
  } else {
1954
2018
  const { generateUUID: generateUUID2 } = await Promise.resolve().then(() => (init_uuid(), uuid_exports));
1955
2019
  effectiveAnonId = `PW_${generateUUID2()}`;
2020
+ if (this.debug) console.log("[Paywallo] fb_anon_id: gerado PW_ local (Facebook Android SDK ausente no host? _fbp real indispon\xEDvel \u2014 Meta n\xE3o reconhece PW_)");
1956
2021
  await storage.set(INSTALL_KEYS.ANON_ID, effectiveAnonId).catch(() => {
1957
2022
  });
1958
2023
  }
1959
2024
  }
1960
2025
  await apiClient.trackEvent("$app_installed", distinctId, {
1961
2026
  installedAt,
1962
- platform: import_react_native7.Platform.OS,
2027
+ platform: import_react_native8.Platform.OS,
1963
2028
  installEventId,
1964
2029
  ...sessionId && { sessionId },
1965
2030
  ...deviceData,
@@ -1981,11 +2046,11 @@ var init_InstallTracker = __esm({
1981
2046
  ...adIds.gaid && { gaid: adIds.gaid },
1982
2047
  attStatus: adIds.attStatus
1983
2048
  }, void 0, { priority: "critical" });
1984
- void this.callDeferredMatch(apiClient, deviceData, adIds, effectiveAnonId, installedAt).catch(() => {
2049
+ void this.callDeferredMatch(apiClient, distinctId, deviceData, adIds, effectiveAnonId, installedAt).catch(() => {
1985
2050
  });
1986
2051
  await markInstallTracked(storage, installedAt);
1987
2052
  }
1988
- async callDeferredMatch(apiClient, deviceData, adIds, anonId, installedAt) {
2053
+ async callDeferredMatch(apiClient, distinctId, deviceData, adIds, anonId, installedAt) {
1989
2054
  const storage = new SecureStorage(this.debug);
1990
2055
  const alreadyMatched = await storage.get(INSTALL_KEYS.DEFERRED_MATCH_DONE);
1991
2056
  if (alreadyMatched) return;
@@ -1999,7 +2064,11 @@ var init_InstallTracker = __esm({
1999
2064
  method: "POST",
2000
2065
  headers: { "Content-Type": "application/json", "X-App-Key": appKey },
2001
2066
  body: JSON.stringify({
2002
- platform: import_react_native7.Platform.OS,
2067
+ platform: import_react_native8.Platform.OS,
2068
+ // Sem isto o servidor não tem identificador no Android (não há IDFV) e grava a
2069
+ // attribution com distinct_id vazio — o reader junta por
2070
+ // install_attributions.distinct_id = app_users.external_id e nunca casa.
2071
+ distinctId,
2003
2072
  ...adIds.idfv && { idfv: adIds.idfv },
2004
2073
  ...adIds.gaid && { gaid: adIds.gaid },
2005
2074
  ...referrer.rawReferrer && { installReferrer: referrer.rawReferrer },
@@ -2094,11 +2163,11 @@ function parseAttributionFromUrl(url) {
2094
2163
  return {};
2095
2164
  }
2096
2165
  }
2097
- var import_react_native8, DeepLinkAttributionCapture, deepLinkAttributionCapture;
2166
+ var import_react_native9, DeepLinkAttributionCapture, deepLinkAttributionCapture;
2098
2167
  var init_DeepLinkAttributionCapture = __esm({
2099
2168
  "src/domains/identity/DeepLinkAttributionCapture.ts"() {
2100
2169
  "use strict";
2101
- import_react_native8 = require("react-native");
2170
+ import_react_native9 = require("react-native");
2102
2171
  init_InstallTracker();
2103
2172
  DeepLinkAttributionCapture = class {
2104
2173
  constructor(debug = false) {
@@ -2107,7 +2176,7 @@ var init_DeepLinkAttributionCapture = __esm({
2107
2176
  }
2108
2177
  async start() {
2109
2178
  try {
2110
- const initialUrl = await import_react_native8.Linking.getInitialURL();
2179
+ const initialUrl = await import_react_native9.Linking.getInitialURL();
2111
2180
  const parsed = parseAttributionFromUrl(initialUrl);
2112
2181
  await attributionTracker.capture(parsed).catch(() => {
2113
2182
  });
@@ -2120,13 +2189,13 @@ var init_DeepLinkAttributionCapture = __esm({
2120
2189
  void attributionTracker.capture(parsed).catch(() => {
2121
2190
  });
2122
2191
  };
2123
- const maybeSub = import_react_native8.Linking.addEventListener("url", handler);
2192
+ const maybeSub = import_react_native9.Linking.addEventListener("url", handler);
2124
2193
  if (maybeSub && typeof maybeSub.remove === "function") {
2125
2194
  this.subscription = maybeSub;
2126
2195
  } else {
2127
2196
  this.subscription = {
2128
2197
  remove: () => {
2129
- const legacy = import_react_native8.Linking;
2198
+ const legacy = import_react_native9.Linking;
2130
2199
  legacy.removeEventListener?.("url", handler);
2131
2200
  }
2132
2201
  };
@@ -2161,10 +2230,10 @@ var init_identity = __esm({
2161
2230
 
2162
2231
  // src/domains/notifications/bridges/NativePushBridge.ts
2163
2232
  function getPaywalloNotifications() {
2164
- return import_react_native9.NativeModules.PaywalloNotifications ?? null;
2233
+ return import_react_native10.NativeModules.PaywalloNotifications ?? null;
2165
2234
  }
2166
2235
  function isNativePushAvailable() {
2167
- return !!import_react_native9.NativeModules.PaywalloNotifications;
2236
+ return !!import_react_native10.NativeModules.PaywalloNotifications;
2168
2237
  }
2169
2238
  function mapStatusToNumber(status) {
2170
2239
  switch (status) {
@@ -2186,16 +2255,16 @@ function mapStatusToNumber(status) {
2186
2255
  }
2187
2256
  function getEmitter() {
2188
2257
  if (_emitter) return _emitter;
2189
- const nativeMod = import_react_native9.NativeModules.PaywalloNotifications;
2258
+ const nativeMod = import_react_native10.NativeModules.PaywalloNotifications;
2190
2259
  if (!nativeMod) return null;
2191
- _emitter = new import_react_native9.NativeEventEmitter(nativeMod);
2260
+ _emitter = new import_react_native10.NativeEventEmitter(nativeMod);
2192
2261
  return _emitter;
2193
2262
  }
2194
- var import_react_native9, _emitter, NativePushBridge;
2263
+ var import_react_native10, _emitter, NativePushBridge;
2195
2264
  var init_NativePushBridge = __esm({
2196
2265
  "src/domains/notifications/bridges/NativePushBridge.ts"() {
2197
2266
  "use strict";
2198
- import_react_native9 = require("react-native");
2267
+ import_react_native10 = require("react-native");
2199
2268
  _emitter = null;
2200
2269
  NativePushBridge = class {
2201
2270
  async getToken() {
@@ -2208,7 +2277,7 @@ var init_NativePushBridge = __esm({
2208
2277
  }
2209
2278
  }
2210
2279
  async getAPNSToken() {
2211
- if (import_react_native9.Platform.OS !== "ios") return null;
2280
+ if (import_react_native10.Platform.OS !== "ios") return null;
2212
2281
  return this.getToken();
2213
2282
  }
2214
2283
  async requestPermission(options) {
@@ -2301,18 +2370,15 @@ var init_constants = __esm({
2301
2370
  });
2302
2371
 
2303
2372
  // src/domains/notifications/config.ts
2304
- function resolveApiBaseUrl(config) {
2305
- if (config.apiBaseUrl) return config.apiBaseUrl;
2306
- if (config.environment === "sandbox") return SANDBOX_API_BASE_URL;
2373
+ function resolveApiBaseUrl() {
2307
2374
  return DEFAULT_API_BASE_URL;
2308
2375
  }
2309
- var DEFAULT_API_BASE_URL, SANDBOX_API_BASE_URL;
2376
+ var DEFAULT_API_BASE_URL;
2310
2377
  var init_config = __esm({
2311
2378
  "src/domains/notifications/config.ts"() {
2312
2379
  "use strict";
2313
2380
  init_constants();
2314
2381
  DEFAULT_API_BASE_URL = DEFAULT_API_URL;
2315
- SANDBOX_API_BASE_URL = DEFAULT_API_URL;
2316
2382
  }
2317
2383
  });
2318
2384
 
@@ -2450,13 +2516,13 @@ function getTimezone() {
2450
2516
  }
2451
2517
  }
2452
2518
  function detectPlatform() {
2453
- return import_react_native10.Platform.OS === "ios" ? "ios" : "android";
2519
+ return import_react_native11.Platform.OS === "ios" ? "ios" : "android";
2454
2520
  }
2455
- var import_react_native10, SEEN_MESSAGES_KEY, LEGACY_SEEN_MESSAGES_KEY, SEEN_TTL_MS, MAX_SEEN_SIZE, NOTIFICATION_TYPE_TO_FAMILY, NotificationEventTracker;
2521
+ var import_react_native11, SEEN_MESSAGES_KEY, LEGACY_SEEN_MESSAGES_KEY, SEEN_TTL_MS, MAX_SEEN_SIZE, NOTIFICATION_TYPE_TO_FAMILY, NotificationEventTracker;
2456
2522
  var init_NotificationEventTracker = __esm({
2457
2523
  "src/domains/notifications/NotificationEventTracker.ts"() {
2458
2524
  "use strict";
2459
- import_react_native10 = require("react-native");
2525
+ import_react_native11 = require("react-native");
2460
2526
  SEEN_MESSAGES_KEY = "@paywallo:seen_messages";
2461
2527
  LEGACY_SEEN_MESSAGES_KEY = "seen_messages";
2462
2528
  SEEN_TTL_MS = 60 * 60 * 1e3;
@@ -2627,8 +2693,8 @@ var init_NotificationHandlerSetup = __esm({
2627
2693
  // src/core/version.ts
2628
2694
  function resolveVersion() {
2629
2695
  try {
2630
- if ("2.5.3") {
2631
- return "2.5.3";
2696
+ if ("2.6.2") {
2697
+ return "2.6.2";
2632
2698
  }
2633
2699
  } catch {
2634
2700
  }
@@ -2698,7 +2764,7 @@ function mapPermissionStatus(status) {
2698
2764
  }
2699
2765
  }
2700
2766
  function detectPlatform2() {
2701
- return import_react_native11.Platform.OS === "ios" ? "ios" : "android";
2767
+ return import_react_native12.Platform.OS === "ios" ? "ios" : "android";
2702
2768
  }
2703
2769
  async function getAppVersion() {
2704
2770
  try {
@@ -2709,11 +2775,11 @@ async function getAppVersion() {
2709
2775
  return "unknown";
2710
2776
  }
2711
2777
  }
2712
- var import_react_native11, AUTH_STATUS, LOCALE_WHITELIST;
2778
+ var import_react_native12, AUTH_STATUS, LOCALE_WHITELIST;
2713
2779
  var init_utils = __esm({
2714
2780
  "src/domains/notifications/utils.ts"() {
2715
2781
  "use strict";
2716
- import_react_native11 = require("react-native");
2782
+ import_react_native12 = require("react-native");
2717
2783
  init_NotificationsError();
2718
2784
  AUTH_STATUS = {
2719
2785
  NOT_DETERMINED: -1,
@@ -2889,18 +2955,18 @@ function mapPermissionStatus2(status) {
2889
2955
  }
2890
2956
  }
2891
2957
  function getPlatform() {
2892
- return import_react_native12.Platform;
2958
+ return import_react_native13.Platform;
2893
2959
  }
2894
2960
  function needsAndroidRuntimePermission(platform) {
2895
2961
  if (platform.OS !== "android") return false;
2896
2962
  const v = typeof platform.Version === "string" ? parseInt(platform.Version, 10) : platform.Version ?? 0;
2897
2963
  return Number.isFinite(v) && v >= ANDROID_TIRAMISU_API;
2898
2964
  }
2899
- var import_react_native12, AUTH_STATUS2, ANDROID_TIRAMISU_API, PermissionManager;
2965
+ var import_react_native13, AUTH_STATUS2, ANDROID_TIRAMISU_API, PermissionManager;
2900
2966
  var init_PermissionManager = __esm({
2901
2967
  "src/domains/notifications/PermissionManager.ts"() {
2902
2968
  "use strict";
2903
- import_react_native12 = require("react-native");
2969
+ import_react_native13 = require("react-native");
2904
2970
  AUTH_STATUS2 = {
2905
2971
  NOT_DETERMINED: -1,
2906
2972
  DENIED: 0,
@@ -3082,10 +3148,7 @@ var init_NotificationsManager = __esm({
3082
3148
  }
3083
3149
  applyConfig(config) {
3084
3150
  this.appKey = config.appKey;
3085
- this.apiBaseUrl = resolveApiBaseUrl({
3086
- apiBaseUrl: config.apiBaseUrl,
3087
- environment: config.environment
3088
- });
3151
+ this.apiBaseUrl = resolveApiBaseUrl();
3089
3152
  this.debug = config.debug ?? false;
3090
3153
  this.permissionManager.setDebug(this.debug);
3091
3154
  }
@@ -3261,7 +3324,8 @@ var init_OnboardingError = __esm({
3261
3324
  };
3262
3325
  ONBOARDING_ERROR_CODES = {
3263
3326
  NOT_INITIALIZED: "ONBOARDING_NOT_INITIALIZED",
3264
- INVALID_STEP_NAME: "ONBOARDING_INVALID_STEP_NAME"
3327
+ INVALID_STEP_NAME: "ONBOARDING_INVALID_STEP_NAME",
3328
+ INVALID_ORDER: "ONBOARDING_INVALID_ORDER"
3265
3329
  };
3266
3330
  }
3267
3331
  });
@@ -3291,16 +3355,20 @@ var init_OnboardingManager = __esm({
3291
3355
  * Saves the step name internally for implicit drop detection on the backend.
3292
3356
  *
3293
3357
  * @param stepName - Unique name for this onboarding step.
3294
- * @param order - Optional explicit display order (accepts decimals, e.g. 2.1 for A/B variants).
3358
+ * @param order - Ordem de exibição do step. Obrigatório. Aceita decimais (ex: 2.1 para variantes A/B).
3359
+ * Deve ser um número finito e não-negativo. O servidor faz o floor — não arredondar aqui.
3295
3360
  */
3296
- async step(stepName, order) {
3361
+ async step(stepName, order, options) {
3297
3362
  this.assertConfig();
3298
3363
  this.validateStepName(stepName, "step");
3364
+ this.validateOrder(order);
3299
3365
  this.lastStep = stepName;
3300
- const stepPayload = { step_name: stepName };
3301
- if (order !== void 0 && Number.isFinite(order) && order >= 0) {
3302
- stepPayload.order = order;
3303
- }
3366
+ const stepPayload = {
3367
+ step_name: stepName,
3368
+ order,
3369
+ ...options?.variantKey !== void 0 ? { variant_key: options.variantKey } : {},
3370
+ ...options?.timeOnPrevS !== void 0 ? { time_on_prev_s: options.timeOnPrevS } : {}
3371
+ };
3304
3372
  const payload = {
3305
3373
  family: "onboarding",
3306
3374
  type: "step",
@@ -3312,33 +3380,21 @@ var init_OnboardingManager = __esm({
3312
3380
  * Tracks successful completion of the onboarding flow.
3313
3381
  * Marks the flow as finished.
3314
3382
  */
3315
- async complete() {
3316
- this.assertConfig();
3317
- this.finished = true;
3318
- return this.emit("onboarding", { family: "onboarding", type: "complete" }, "complete");
3319
- }
3320
- /**
3321
- * Tracks an explicit drop (abandonment) at the given step.
3322
- * Marks the flow as finished.
3323
- *
3324
- * @param stepName - The step name where the user dropped off.
3325
- */
3326
- async drop(stepName) {
3383
+ async complete(options) {
3327
3384
  this.assertConfig();
3328
- this.validateStepName(stepName, "drop");
3329
3385
  this.finished = true;
3330
3386
  const payload = {
3331
3387
  family: "onboarding",
3332
- type: "drop",
3333
- ...{ step_name: stepName }
3388
+ type: "complete",
3389
+ ...options?.variantKey !== void 0 ? { variant_key: options.variantKey } : {}
3334
3390
  };
3335
- return this.emit("onboarding", payload, "drop");
3391
+ return this.emit("onboarding", payload, "complete");
3336
3392
  }
3337
3393
  /** Returns the last step name seen, or null if no step was tracked yet. */
3338
3394
  getLastStep() {
3339
3395
  return this.lastStep;
3340
3396
  }
3341
- /** Returns whether the flow has been marked as finished (complete or drop). */
3397
+ /** Returns whether the flow has been marked as finished (complete). */
3342
3398
  isFinished() {
3343
3399
  return this.finished;
3344
3400
  }
@@ -3370,6 +3426,14 @@ var init_OnboardingManager = __esm({
3370
3426
  );
3371
3427
  }
3372
3428
  }
3429
+ validateOrder(order) {
3430
+ if (order === void 0 || order === null || !Number.isFinite(order) || order < 0) {
3431
+ throw new OnboardingError(
3432
+ ONBOARDING_ERROR_CODES.INVALID_ORDER,
3433
+ "OnboardingManager.step(): order deve ser um n\xFAmero finito e n\xE3o-negativo."
3434
+ );
3435
+ }
3436
+ }
3373
3437
  };
3374
3438
  onboardingManager = new OnboardingManager();
3375
3439
  }
@@ -3647,11 +3711,11 @@ function getLocalizedString(text) {
3647
3711
  }
3648
3712
  function detectDeviceLanguage() {
3649
3713
  try {
3650
- if (import_react_native13.Platform.OS === "ios") {
3651
- const settings = import_react_native13.NativeModules.SettingsManager?.settings;
3714
+ if (import_react_native14.Platform.OS === "ios") {
3715
+ const settings = import_react_native14.NativeModules.SettingsManager?.settings;
3652
3716
  return settings?.AppleLocale ?? settings?.AppleLanguages?.[0] ?? "en-US";
3653
3717
  }
3654
- return import_react_native13.NativeModules.I18nManager?.localeIdentifier ?? "en-US";
3718
+ return import_react_native14.NativeModules.I18nManager?.localeIdentifier ?? "en-US";
3655
3719
  } catch {
3656
3720
  return "en-US";
3657
3721
  }
@@ -3673,11 +3737,11 @@ function initLocalization(options) {
3673
3737
  currentLanguage = deviceLanguage;
3674
3738
  }
3675
3739
  }
3676
- var import_react_native13, currentLanguage, defaultLanguage, SDK_STRINGS;
3740
+ var import_react_native14, currentLanguage, defaultLanguage, SDK_STRINGS;
3677
3741
  var init_localization = __esm({
3678
3742
  "src/utils/localization.ts"() {
3679
3743
  "use strict";
3680
- import_react_native13 = require("react-native");
3744
+ import_react_native14 = require("react-native");
3681
3745
  currentLanguage = "pt-BR";
3682
3746
  defaultLanguage = "pt-BR";
3683
3747
  SDK_STRINGS = {
@@ -3714,48 +3778,48 @@ var init_localization = __esm({
3714
3778
 
3715
3779
  // src/domains/paywall/PaywallSkeleton.tsx
3716
3780
  function SkeletonBlock({ style, color, opacity }) {
3717
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native14.Animated.View, { style: [style, { backgroundColor: color, opacity }] });
3781
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native15.Animated.View, { style: [style, { backgroundColor: color, opacity }] });
3718
3782
  }
3719
3783
  function PaywallSkeleton({ backgroundColor = "#FFFFFF" }) {
3720
- const pulse = (0, import_react3.useRef)(new import_react_native14.Animated.Value(0.4)).current;
3784
+ const pulse = (0, import_react3.useRef)(new import_react_native15.Animated.Value(0.4)).current;
3721
3785
  (0, import_react3.useEffect)(() => {
3722
- const loop = import_react_native14.Animated.loop(
3723
- import_react_native14.Animated.sequence([
3724
- import_react_native14.Animated.timing(pulse, { toValue: 1, duration: 700, useNativeDriver: true }),
3725
- import_react_native14.Animated.timing(pulse, { toValue: 0.4, duration: 700, useNativeDriver: true })
3786
+ const loop = import_react_native15.Animated.loop(
3787
+ import_react_native15.Animated.sequence([
3788
+ import_react_native15.Animated.timing(pulse, { toValue: 1, duration: 700, useNativeDriver: true }),
3789
+ import_react_native15.Animated.timing(pulse, { toValue: 0.4, duration: 700, useNativeDriver: true })
3726
3790
  ])
3727
3791
  );
3728
3792
  loop.start();
3729
3793
  return () => loop.stop();
3730
3794
  }, [pulse]);
3731
3795
  const placeholder = isColorDark(backgroundColor) ? "rgba(255,255,255,0.13)" : "rgba(0,0,0,0.07)";
3732
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native14.View, { style: [styles.container, { backgroundColor }], pointerEvents: "none", children: [
3733
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native14.View, { style: styles.header, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.logo, color: placeholder, opacity: pulse }) }),
3796
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native15.View, { style: [styles.container, { backgroundColor }], pointerEvents: "none", children: [
3797
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react_native15.View, { style: styles.header, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.logo, color: placeholder, opacity: pulse }) }),
3734
3798
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.hero, color: placeholder, opacity: pulse }),
3735
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native14.View, { style: styles.titleGroup, children: [
3799
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native15.View, { style: styles.titleGroup, children: [
3736
3800
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.titleLine, color: placeholder, opacity: pulse }),
3737
3801
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.titleLineShort, color: placeholder, opacity: pulse })
3738
3802
  ] }),
3739
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native14.View, { style: styles.cardsRow, children: [
3803
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native15.View, { style: styles.cardsRow, children: [
3740
3804
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.card, color: placeholder, opacity: pulse }),
3741
3805
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.card, color: placeholder, opacity: pulse })
3742
3806
  ] }),
3743
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native14.View, { style: styles.footerGroup, children: [
3807
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_react_native15.View, { style: styles.footerGroup, children: [
3744
3808
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.cta, color: placeholder, opacity: pulse }),
3745
3809
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SkeletonBlock, { style: styles.footer, color: placeholder, opacity: pulse })
3746
3810
  ] })
3747
3811
  ] });
3748
3812
  }
3749
- var import_react3, import_react_native14, import_jsx_runtime, RADIUS, styles;
3813
+ var import_react3, import_react_native15, import_jsx_runtime, RADIUS, styles;
3750
3814
  var init_PaywallSkeleton = __esm({
3751
3815
  "src/domains/paywall/PaywallSkeleton.tsx"() {
3752
3816
  "use strict";
3753
3817
  import_react3 = require("react");
3754
- import_react_native14 = require("react-native");
3818
+ import_react_native15 = require("react-native");
3755
3819
  init_extractFirstPageBackground();
3756
3820
  import_jsx_runtime = require("react/jsx-runtime");
3757
3821
  RADIUS = 14;
3758
- styles = import_react_native14.StyleSheet.create({
3822
+ styles = import_react_native15.StyleSheet.create({
3759
3823
  card: { borderRadius: RADIUS, flex: 1, height: 120 },
3760
3824
  cardsRow: { flexDirection: "row", gap: 12, marginTop: "auto", paddingHorizontal: 24 },
3761
3825
  container: { flex: 1, paddingBottom: 40, paddingTop: 64 },
@@ -3821,7 +3885,7 @@ function getNativeWebView() {
3821
3885
  if (NativeWebViewComponent) return NativeWebViewComponent;
3822
3886
  if (nativeWebViewLookupFailed) return null;
3823
3887
  try {
3824
- NativeWebViewComponent = (0, import_react_native15.requireNativeComponent)("PaywalloWebView");
3888
+ NativeWebViewComponent = (0, import_react_native16.requireNativeComponent)("PaywalloWebView");
3825
3889
  return NativeWebViewComponent;
3826
3890
  } catch {
3827
3891
  nativeWebViewLookupFailed = true;
@@ -3830,9 +3894,9 @@ function getNativeWebView() {
3830
3894
  }
3831
3895
  function getWebViewEmitter() {
3832
3896
  if (webViewEmitter) return webViewEmitter;
3833
- const mod = import_react_native15.NativeModules.PaywalloWebViewModule;
3897
+ const mod = import_react_native16.NativeModules.PaywalloWebViewModule;
3834
3898
  if (!mod) return null;
3835
- webViewEmitter = new import_react_native15.NativeEventEmitter(mod);
3899
+ webViewEmitter = new import_react_native16.NativeEventEmitter(mod);
3836
3900
  return webViewEmitter;
3837
3901
  }
3838
3902
  async function triggerNativeHaptic(style) {
@@ -3923,10 +3987,10 @@ function PaywallWebView({
3923
3987
  }
3924
3988
  }, []);
3925
3989
  const injectScript = (0, import_react4.useCallback)((script) => {
3926
- if (import_react_native15.Platform.OS === "android") {
3927
- const handle = (0, import_react_native15.findNodeHandle)(webViewRef.current);
3990
+ if (import_react_native16.Platform.OS === "android") {
3991
+ const handle = (0, import_react_native16.findNodeHandle)(webViewRef.current);
3928
3992
  if (handle == null) return;
3929
- import_react_native15.UIManager.dispatchViewManagerCommand(handle, "injectJavaScript", [script]);
3993
+ import_react_native16.UIManager.dispatchViewManagerCommand(handle, "injectJavaScript", [script]);
3930
3994
  return;
3931
3995
  }
3932
3996
  setScriptToInject(script);
@@ -3986,7 +4050,7 @@ function PaywallWebView({
3986
4050
  if (message.payload?.url) {
3987
4051
  const url = message.payload.url;
3988
4052
  if (/^https?:\/\//i.test(url) || /^mailto:/i.test(url) || /^itms-apps:/i.test(url) || /^market:/i.test(url)) {
3989
- void import_react_native15.Linking.openURL(url);
4053
+ void import_react_native16.Linking.openURL(url);
3990
4054
  }
3991
4055
  }
3992
4056
  break;
@@ -4067,18 +4131,18 @@ function PaywallWebView({
4067
4131
  injectScript(buildPurchaseStateScript(isPurchasing));
4068
4132
  }, [isPurchasing, injectScript]);
4069
4133
  (0, import_react4.useEffect)(() => {
4070
- if (import_react_native15.Platform.OS !== "android") return;
4134
+ if (import_react_native16.Platform.OS !== "android") return;
4071
4135
  const onBackPress = () => {
4072
4136
  if (!paywallDataSent.current) return false;
4073
4137
  injectScript(buildBackButtonScript());
4074
4138
  return true;
4075
4139
  };
4076
- const subscription = import_react_native15.BackHandler.addEventListener("hardwareBackPress", onBackPress);
4140
+ const subscription = import_react_native16.BackHandler.addEventListener("hardwareBackPress", onBackPress);
4077
4141
  return () => subscription.remove();
4078
4142
  }, [injectScript]);
4079
4143
  if (!resolvedWebUrl || !NativeWebView) return null;
4080
4144
  const paywallUrl = `${resolvedWebUrl}/paywall/${paywallId}`;
4081
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native15.View, { style: styles2.container, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4145
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_native16.View, { style: styles2.container, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
4082
4146
  NativeWebView,
4083
4147
  {
4084
4148
  ref: webViewRef,
@@ -4091,12 +4155,12 @@ function PaywallWebView({
4091
4155
  }
4092
4156
  ) });
4093
4157
  }
4094
- var import_react4, import_react_native15, import_jsx_runtime2, NativeWebViewComponent, nativeWebViewLookupFailed, webViewEmitter, styles2;
4158
+ var import_react4, import_react_native16, import_jsx_runtime2, NativeWebViewComponent, nativeWebViewLookupFailed, webViewEmitter, styles2;
4095
4159
  var init_PaywallWebView = __esm({
4096
4160
  "src/domains/paywall/PaywallWebView.tsx"() {
4097
4161
  "use strict";
4098
4162
  import_react4 = require("react");
4099
- import_react_native15 = require("react-native");
4163
+ import_react_native16 = require("react-native");
4100
4164
  init_PaywalloClient();
4101
4165
  init_parseWebViewMessage();
4102
4166
  init_paywallScripts();
@@ -4104,7 +4168,7 @@ var init_PaywallWebView = __esm({
4104
4168
  NativeWebViewComponent = null;
4105
4169
  nativeWebViewLookupFailed = false;
4106
4170
  webViewEmitter = null;
4107
- styles2 = import_react_native15.StyleSheet.create({
4171
+ styles2 = import_react_native16.StyleSheet.create({
4108
4172
  container: { flex: 1 },
4109
4173
  webview: { flex: 1, backgroundColor: "transparent" }
4110
4174
  });
@@ -4239,7 +4303,7 @@ function mapNativePurchase(native) {
4239
4303
  transactionId: native.transactionId,
4240
4304
  transactionDate: native.transactionDate,
4241
4305
  receipt: native.receipt,
4242
- platform: import_react_native16.Platform.OS
4306
+ platform: import_react_native17.Platform.OS
4243
4307
  };
4244
4308
  }
4245
4309
  function normalizeTransactionUpdate(raw) {
@@ -4259,17 +4323,17 @@ function normalizeTransactionUpdate(raw) {
4259
4323
  if (typeof r.currency === "string") update.currency = r.currency;
4260
4324
  return update;
4261
4325
  }
4262
- var import_react_native16, TRANSACTION_UPDATE_EVENT, PaywalloStoreKitNative, nativeStoreKit, NativeStoreKit;
4326
+ var import_react_native17, TRANSACTION_UPDATE_EVENT, PaywalloStoreKitNative, nativeStoreKit, NativeStoreKit;
4263
4327
  var init_NativeStoreKit = __esm({
4264
4328
  "src/domains/iap/NativeStoreKit.ts"() {
4265
4329
  "use strict";
4266
- import_react_native16 = require("react-native");
4330
+ import_react_native17 = require("react-native");
4267
4331
  init_PaywalloClient();
4268
4332
  init_uuid();
4269
4333
  init_IdentityManager();
4270
4334
  init_PurchaseError();
4271
4335
  TRANSACTION_UPDATE_EVENT = "PaywalloTransactionUpdate";
4272
- PaywalloStoreKitNative = import_react_native16.NativeModules.PaywalloStoreKit ?? null;
4336
+ PaywalloStoreKitNative = import_react_native17.NativeModules.PaywalloStoreKit ?? null;
4273
4337
  nativeStoreKit = {
4274
4338
  isAvailable: isAvailable3,
4275
4339
  async getProducts(productIds) {
@@ -4338,7 +4402,7 @@ var init_NativeStoreKit = __esm({
4338
4402
  subscribeToTransactionUpdates(listener) {
4339
4403
  if (!PaywalloStoreKitNative) return null;
4340
4404
  try {
4341
- const EmitterCtor = import_react_native16.NativeEventEmitter;
4405
+ const EmitterCtor = import_react_native17.NativeEventEmitter;
4342
4406
  const emitter = new EmitterCtor(PaywalloStoreKitNative);
4343
4407
  const sub = emitter.addListener(TRANSACTION_UPDATE_EVENT, (payload) => {
4344
4408
  const update = normalizeTransactionUpdate(payload);
@@ -4971,11 +5035,11 @@ var init_types2 = __esm({
4971
5035
  });
4972
5036
 
4973
5037
  // src/core/network/NetworkMonitor.ts
4974
- var import_react_native17, NetworkMonitorClass, networkMonitor;
5038
+ var import_react_native18, NetworkMonitorClass, networkMonitor;
4975
5039
  var init_NetworkMonitor = __esm({
4976
5040
  "src/core/network/NetworkMonitor.ts"() {
4977
5041
  "use strict";
4978
- import_react_native17 = require("react-native");
5042
+ import_react_native18 = require("react-native");
4979
5043
  init_types2();
4980
5044
  NetworkMonitorClass = class {
4981
5045
  constructor() {
@@ -5004,7 +5068,7 @@ var init_NetworkMonitor = __esm({
5004
5068
  }, this.config.checkInterval);
5005
5069
  }
5006
5070
  setupAppStateListener() {
5007
- this.appStateSubscription = import_react_native17.AppState.addEventListener("change", (state) => {
5071
+ this.appStateSubscription = import_react_native18.AppState.addEventListener("change", (state) => {
5008
5072
  if (state === "active") {
5009
5073
  if (!this.checkIntervalId) {
5010
5074
  this.checkIntervalId = setInterval(() => {
@@ -5226,7 +5290,7 @@ var init_QueueProcessor = __esm({
5226
5290
  for (const item of batch) {
5227
5291
  retryIds.add(item.id);
5228
5292
  }
5229
- console.error("[Paywallo:QUEUE] event batch network error \u2014 items will retry", { size: batch.length, error: error instanceof Error ? error.message : String(error) });
5293
+ if (this.config.debug) console.log("[Paywallo:QUEUE] event batch network error \u2014 items will retry", { size: batch.length, error: error instanceof Error ? error.message : String(error) });
5230
5294
  this.log("Event batch threw network error - will retry", {
5231
5295
  size: batch.length,
5232
5296
  error: error instanceof Error ? error.message : String(error)
@@ -5239,7 +5303,7 @@ var init_QueueProcessor = __esm({
5239
5303
  processed++;
5240
5304
  }
5241
5305
  this.log("Event batch processed successfully", { size: batch.length });
5242
- } else if (response.status >= 400 && response.status < 500) {
5306
+ } else if (response.status >= 400 && response.status < 500 && response.status !== 429) {
5243
5307
  for (const item of batch) {
5244
5308
  await offlineQueue.removeItem(item.id);
5245
5309
  failed++;
@@ -5251,7 +5315,7 @@ var init_QueueProcessor = __esm({
5251
5315
  console.log("[Paywallo:QUEUE] event batch deduplicated by server \u2014 items dropped (benign)", { status: response.status, size: batch.length, error: responseError });
5252
5316
  }
5253
5317
  } else {
5254
- console.error("[Paywallo:QUEUE] event batch failed PERMANENTLY (4xx) \u2014 items dropped", { status: response.status, size: batch.length, responseBody: typeof response.data === "string" ? response.data.slice(0, 1e3) : JSON.stringify(response.data).slice(0, 1e3), firstItemBody: typeof batch[0].body === "string" ? batch[0].body.slice(0, 1e3) : JSON.stringify(batch[0].body).slice(0, 1e3) });
5318
+ if (this.config.debug) console.log("[Paywallo:QUEUE] event batch failed PERMANENTLY (4xx) \u2014 items dropped", { status: response.status, size: batch.length, responseBody: typeof response.data === "string" ? response.data.slice(0, 1e3) : JSON.stringify(response.data).slice(0, 1e3), firstItemBody: typeof batch[0].body === "string" ? batch[0].body.slice(0, 1e3) : JSON.stringify(batch[0].body).slice(0, 1e3) });
5255
5319
  }
5256
5320
  this.log("Event batch failed permanently (4xx) - removing from queue", {
5257
5321
  status: response.status,
@@ -5262,7 +5326,7 @@ var init_QueueProcessor = __esm({
5262
5326
  for (const item of batch) {
5263
5327
  retryIds.add(item.id);
5264
5328
  }
5265
- console.error("[Paywallo:QUEUE] event batch server error (5xx) \u2014 will retry", { status: response.status, size: batch.length });
5329
+ if (this.config.debug) console.log("[Paywallo:QUEUE] event batch server error (5xx) \u2014 will retry", { status: response.status, size: batch.length });
5266
5330
  this.log("Event batch failed with server error - will retry", {
5267
5331
  status: response.status,
5268
5332
  size: batch.length
@@ -5292,7 +5356,7 @@ var init_QueueProcessor = __esm({
5292
5356
  skipRetry: false
5293
5357
  });
5294
5358
  } catch (error) {
5295
- console.error("[Paywallo:QUEUE] individual item network error \u2014 will retry", { id: item.id, url: item.url, error: error instanceof Error ? error.message : String(error) });
5359
+ if (this.config.debug) console.log("[Paywallo:QUEUE] individual item network error \u2014 will retry", { id: item.id, url: item.url, error: error instanceof Error ? error.message : String(error) });
5296
5360
  this.log("Request threw network error - will retry", {
5297
5361
  id: item.id,
5298
5362
  error: error instanceof Error ? error.message : String(error)
@@ -5303,7 +5367,7 @@ var init_QueueProcessor = __esm({
5303
5367
  this.log("Queue item processed successfully", { id: item.id });
5304
5368
  return { success: true, permanent: false };
5305
5369
  }
5306
- if (response.status >= 400 && response.status < 500) {
5370
+ if (response.status >= 400 && response.status < 500 && response.status !== 429) {
5307
5371
  this.log("Request failed with permanent client error - removing from queue", {
5308
5372
  id: item.id,
5309
5373
  url: item.url,
@@ -5373,11 +5437,11 @@ var init_queue = __esm({
5373
5437
  });
5374
5438
 
5375
5439
  // src/domains/iap/IAPValidator.ts
5376
- var import_react_native18, IAPValidator;
5440
+ var import_react_native19, IAPValidator;
5377
5441
  var init_IAPValidator = __esm({
5378
5442
  "src/domains/iap/IAPValidator.ts"() {
5379
5443
  "use strict";
5380
- import_react_native18 = require("react-native");
5444
+ import_react_native19 = require("react-native");
5381
5445
  init_PaywalloClient();
5382
5446
  init_queue();
5383
5447
  init_PurchaseError();
@@ -5403,7 +5467,7 @@ var init_IAPValidator = __esm({
5403
5467
  async validateWithServer(purchase, productId, options) {
5404
5468
  const apiClient = this.getApiClientFn();
5405
5469
  const product = this.getProductFromCache(productId);
5406
- const platform = import_react_native18.Platform.OS;
5470
+ const platform = import_react_native19.Platform.OS;
5407
5471
  const distinctId = PaywalloClient.getDistinctId();
5408
5472
  return this.validateWithRetry(
5409
5473
  () => apiClient.validatePurchase(
@@ -5438,7 +5502,7 @@ var init_IAPValidator = __esm({
5438
5502
  try {
5439
5503
  const apiClient = this.getApiClientFn();
5440
5504
  const product = this.getProductFromCache(productId);
5441
- const platform = import_react_native18.Platform.OS;
5505
+ const platform = import_react_native19.Platform.OS;
5442
5506
  const distinctId = PaywalloClient.getDistinctId();
5443
5507
  const appKey = apiClient.getAppKey();
5444
5508
  const body = {
@@ -5478,11 +5542,11 @@ function getIAPService() {
5478
5542
  }
5479
5543
  return _instance;
5480
5544
  }
5481
- var import_react_native19, IAPService, _instance;
5545
+ var import_react_native20, IAPService, _instance;
5482
5546
  var init_IAPService = __esm({
5483
5547
  "src/domains/iap/IAPService.ts"() {
5484
5548
  "use strict";
5485
- import_react_native19 = require("react-native");
5549
+ import_react_native20 = require("react-native");
5486
5550
  init_PaywalloClient();
5487
5551
  init_IAPTransactionEmitter();
5488
5552
  init_IAPValidator();
@@ -5632,7 +5696,7 @@ var init_IAPService = __esm({
5632
5696
  const transactions = await nativeStoreKit.getActiveTransactions();
5633
5697
  const apiClient = this.getApiClient();
5634
5698
  const distinctId = PaywalloClient.getDistinctId();
5635
- const platform = import_react_native19.Platform.OS;
5699
+ const platform = import_react_native20.Platform.OS;
5636
5700
  const results = await Promise.allSettled(
5637
5701
  transactions.map((tx) => {
5638
5702
  const product = this.productsCache.get(tx.productId);
@@ -5727,7 +5791,7 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
5727
5791
  const [isPurchasing, setIsPurchasing] = (0, import_react6.useState)(false);
5728
5792
  const isPurchasingRef = (0, import_react6.useRef)(false);
5729
5793
  const [isClosing, setIsClosing] = (0, import_react6.useState)(false);
5730
- const slideAnim = (0, import_react6.useRef)(new import_react_native20.Animated.Value(0)).current;
5794
+ const slideAnim = (0, import_react6.useRef)(new import_react_native21.Animated.Value(0)).current;
5731
5795
  const presentedAtRef = (0, import_react6.useRef)(Date.now());
5732
5796
  const closedRef = (0, import_react6.useRef)(false);
5733
5797
  const { trackDismissed, trackProductSelected, trackPurchased } = usePaywallTracking();
@@ -5735,8 +5799,8 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
5735
5799
  if (closedRef.current) return;
5736
5800
  closedRef.current = true;
5737
5801
  const animTarget = openAnim ?? slideAnim;
5738
- import_react_native20.Animated.timing(animTarget, {
5739
- toValue: import_react_native20.Dimensions.get("window").height,
5802
+ import_react_native21.Animated.timing(animTarget, {
5803
+ toValue: import_react_native21.Dimensions.get("window").height,
5740
5804
  duration: 350,
5741
5805
  useNativeDriver: true
5742
5806
  }).start(() => {
@@ -5756,7 +5820,7 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
5756
5820
  closeWithReason("dismissed");
5757
5821
  }, [isClosing, closeWithReason]);
5758
5822
  (0, import_react6.useEffect)(() => {
5759
- const sub = import_react_native20.AppState.addEventListener("change", (nextState) => {
5823
+ const sub = import_react_native21.AppState.addEventListener("change", (nextState) => {
5760
5824
  if (isPurchasingRef.current) return;
5761
5825
  if (nextState === "background" || nextState === "inactive") {
5762
5826
  closeWithReason("backgrounded");
@@ -5824,12 +5888,12 @@ function usePaywallActions(placement, paywallConfig, onResult, variantKey, campa
5824
5888
  }, [isPurchasing, onResult, paywallConfig, placement, trackDismissed, variantKey, campaignId, variantId]);
5825
5889
  return { isPurchasing, slideAnim, handleClose, handlePurchase, handleRestore };
5826
5890
  }
5827
- var import_react6, import_react_native20, PAYWALL_TIMEOUT_MS;
5891
+ var import_react6, import_react_native21, PAYWALL_TIMEOUT_MS;
5828
5892
  var init_usePaywallActions = __esm({
5829
5893
  "src/domains/paywall/usePaywallActions.ts"() {
5830
5894
  "use strict";
5831
5895
  import_react6 = require("react");
5832
- import_react_native20 = require("react-native");
5896
+ import_react_native21 = require("react-native");
5833
5897
  init_IAPService();
5834
5898
  init_usePaywallTracking();
5835
5899
  PAYWALL_TIMEOUT_MS = 30 * 60 * 1e3;
@@ -5950,11 +6014,11 @@ function ErrorFallback({ description, onRetry, onClose }) {
5950
6014
  const title = overrides?.title ?? getSdkString("paywallErrorTitle");
5951
6015
  const retryLabel = overrides?.retry ?? getSdkString("paywallRetryButton");
5952
6016
  const closeLabel = overrides?.close ?? getSdkString("paywallCloseButton");
5953
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.View, { style: styles3.fallbackContainer, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native21.View, { style: styles3.fallbackCard, children: [
5954
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Text, { style: styles3.fallbackTitle, children: title }),
5955
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Text, { style: styles3.fallbackDescription, children: description }),
5956
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Pressable, { style: styles3.retryButton, onPress: onRetry, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Text, { style: styles3.retryButtonText, children: retryLabel }) }),
5957
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Pressable, { style: styles3.closeButton, onPress: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Text, { style: styles3.closeButtonText, children: closeLabel }) })
6017
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native22.View, { style: styles3.fallbackContainer, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native22.View, { style: styles3.fallbackCard, children: [
6018
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native22.Text, { style: styles3.fallbackTitle, children: title }),
6019
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native22.Text, { style: styles3.fallbackDescription, children: description }),
6020
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native22.Pressable, { style: styles3.retryButton, onPress: onRetry, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native22.Text, { style: styles3.retryButtonText, children: retryLabel }) }),
6021
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native22.Pressable, { style: styles3.closeButton, onPress: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native22.Text, { style: styles3.closeButtonText, children: closeLabel }) })
5958
6022
  ] }) });
5959
6023
  }
5960
6024
  function PaywallModal({
@@ -5976,8 +6040,8 @@ function PaywallModal({
5976
6040
  campaignId,
5977
6041
  variantId
5978
6042
  );
5979
- const screenHeight = import_react_native21.Dimensions.get("window").height;
5980
- const openAnim = (0, import_react8.useRef)(new import_react_native21.Animated.Value(screenHeight)).current;
6043
+ const screenHeight = import_react_native22.Dimensions.get("window").height;
6044
+ const openAnim = (0, import_react8.useRef)(new import_react_native22.Animated.Value(screenHeight)).current;
5981
6045
  const [modalVisible, setModalVisible] = (0, import_react8.useState)(false);
5982
6046
  const handleResult = (0, import_react8.useCallback)((result) => {
5983
6047
  setModalVisible(false);
@@ -5987,7 +6051,7 @@ function PaywallModal({
5987
6051
  const [webViewError, setWebViewError] = (0, import_react8.useState)(null);
5988
6052
  const [retryCount, setRetryCount] = (0, import_react8.useState)(0);
5989
6053
  const [showSkeleton, setShowSkeleton] = (0, import_react8.useState)(true);
5990
- const skeletonOpacity = (0, import_react8.useRef)(new import_react_native21.Animated.Value(1)).current;
6054
+ const skeletonOpacity = (0, import_react8.useRef)(new import_react_native22.Animated.Value(1)).current;
5991
6055
  const retryCountRef = (0, import_react8.useRef)(0);
5992
6056
  const handleWebViewError = (0, import_react8.useCallback)(
5993
6057
  (err) => {
@@ -6008,10 +6072,10 @@ function PaywallModal({
6008
6072
  skeletonOpacity.setValue(1);
6009
6073
  }, [skeletonOpacity]);
6010
6074
  const handleWebViewReady = (0, import_react8.useCallback)(() => {
6011
- import_react_native21.Animated.timing(skeletonOpacity, {
6075
+ import_react_native22.Animated.timing(skeletonOpacity, {
6012
6076
  toValue: 0,
6013
6077
  duration: 250,
6014
- easing: import_react_native21.Easing.out(import_react_native21.Easing.cubic),
6078
+ easing: import_react_native22.Easing.out(import_react_native22.Easing.cubic),
6015
6079
  useNativeDriver: true
6016
6080
  }).start(() => setShowSkeleton(false));
6017
6081
  }, [skeletonOpacity]);
@@ -6025,11 +6089,11 @@ function PaywallModal({
6025
6089
  setModalVisible(true);
6026
6090
  setShowSkeleton(true);
6027
6091
  skeletonOpacity.setValue(1);
6028
- openAnim.setValue(import_react_native21.Dimensions.get("window").height);
6029
- import_react_native21.Animated.timing(openAnim, {
6092
+ openAnim.setValue(import_react_native22.Dimensions.get("window").height);
6093
+ import_react_native22.Animated.timing(openAnim, {
6030
6094
  toValue: 0,
6031
6095
  duration: 550,
6032
- easing: import_react_native21.Easing.out(import_react_native21.Easing.cubic),
6096
+ easing: import_react_native22.Easing.out(import_react_native22.Easing.cubic),
6033
6097
  useNativeDriver: true
6034
6098
  }).start();
6035
6099
  }
@@ -6037,7 +6101,7 @@ function PaywallModal({
6037
6101
  if (!modalVisible && !visible) return null;
6038
6102
  const skeletonBackground = paywallConfig && "craftData" in paywallConfig.config ? extractFirstPageBackground(paywallConfig.config.craftData) : "#FFFFFF";
6039
6103
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
6040
- import_react_native21.Modal,
6104
+ import_react_native22.Modal,
6041
6105
  {
6042
6106
  visible: modalVisible,
6043
6107
  animationType: "none",
@@ -6045,8 +6109,8 @@ function PaywallModal({
6045
6109
  onRequestClose: handleClose,
6046
6110
  transparent: true,
6047
6111
  statusBarTranslucent: true,
6048
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.View, { style: styles3.overlay, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Animated.View, { style: [styles3.animatedContainer, { transform: [{ translateY: openAnim }] }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native21.View, { style: styles3.container, children: [
6049
- error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.View, { style: styles3.errorContainer, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native21.Text, { style: styles3.errorText, children: error.message }) }),
6112
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native22.View, { style: styles3.overlay, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native22.Animated.View, { style: [styles3.animatedContainer, { transform: [{ translateY: openAnim }] }], children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_react_native22.View, { style: styles3.container, children: [
6113
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native22.View, { style: styles3.errorContainer, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react_native22.Text, { style: styles3.errorText, children: error.message }) }),
6050
6114
  !error && paywallConfig && "craftData" in paywallConfig.config && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: webViewError ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
6051
6115
  ErrorFallback,
6052
6116
  {
@@ -6073,9 +6137,9 @@ function PaywallModal({
6073
6137
  retryCount
6074
6138
  ) }),
6075
6139
  showSkeleton && !error && !webViewError && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
6076
- import_react_native21.Animated.View,
6140
+ import_react_native22.Animated.View,
6077
6141
  {
6078
- style: [import_react_native21.StyleSheet.absoluteFill, { opacity: skeletonOpacity }],
6142
+ style: [import_react_native22.StyleSheet.absoluteFill, { opacity: skeletonOpacity }],
6079
6143
  pointerEvents: "none",
6080
6144
  children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PaywallSkeleton, { backgroundColor: skeletonBackground })
6081
6145
  }
@@ -6084,12 +6148,12 @@ function PaywallModal({
6084
6148
  }
6085
6149
  );
6086
6150
  }
6087
- var import_react8, import_react_native21, import_jsx_runtime3, styles3;
6151
+ var import_react8, import_react_native22, import_jsx_runtime3, styles3;
6088
6152
  var init_PaywallModal = __esm({
6089
6153
  "src/domains/paywall/PaywallModal.tsx"() {
6090
6154
  "use strict";
6091
6155
  import_react8 = require("react");
6092
- import_react_native21 = require("react-native");
6156
+ import_react_native22 = require("react-native");
6093
6157
  init_PaywalloClient();
6094
6158
  init_localization();
6095
6159
  init_extractFirstPageBackground();
@@ -6098,7 +6162,7 @@ var init_PaywallModal = __esm({
6098
6162
  init_usePaywallActions();
6099
6163
  init_usePaywallLoader();
6100
6164
  import_jsx_runtime3 = require("react/jsx-runtime");
6101
- styles3 = import_react_native21.StyleSheet.create({
6165
+ styles3 = import_react_native22.StyleSheet.create({
6102
6166
  overlay: { flex: 1, backgroundColor: "rgba(0,0,0,0.3)" },
6103
6167
  animatedContainer: { flex: 1, backgroundColor: "#fff" },
6104
6168
  container: { flex: 1, backgroundColor: "#fff" },
@@ -6268,7 +6332,7 @@ function getNativeWebView2() {
6268
6332
  if (NativeWebViewComponent2) return NativeWebViewComponent2;
6269
6333
  if (nativeLookupFailed) return null;
6270
6334
  try {
6271
- NativeWebViewComponent2 = (0, import_react_native22.requireNativeComponent)("PaywalloWebView");
6335
+ NativeWebViewComponent2 = (0, import_react_native23.requireNativeComponent)("PaywalloWebView");
6272
6336
  return NativeWebViewComponent2;
6273
6337
  } catch {
6274
6338
  nativeLookupFailed = true;
@@ -6291,20 +6355,20 @@ function PaywallWebViewPrewarmer({
6291
6355
  if (PaywalloClient.getConfig()?.debug) {
6292
6356
  console.log(`[Paywallo PREWARM] mounting hidden WebView: ${preheatUrl}`);
6293
6357
  }
6294
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native22.View, { pointerEvents: "none", style: styles4.hidden, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NativeWebView, { sourceUrl: preheatUrl, style: styles4.fill }) });
6358
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_react_native23.View, { pointerEvents: "none", style: styles4.hidden, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NativeWebView, { sourceUrl: preheatUrl, style: styles4.fill }) });
6295
6359
  }
6296
- var import_react9, import_react_native22, import_jsx_runtime4, NativeWebViewComponent2, nativeLookupFailed, DEFAULT_DURATION_MS, styles4;
6360
+ var import_react9, import_react_native23, import_jsx_runtime4, NativeWebViewComponent2, nativeLookupFailed, DEFAULT_DURATION_MS, styles4;
6297
6361
  var init_PaywallWebViewPrewarmer = __esm({
6298
6362
  "src/domains/paywall/PaywallWebViewPrewarmer.tsx"() {
6299
6363
  "use strict";
6300
6364
  import_react9 = require("react");
6301
- import_react_native22 = require("react-native");
6365
+ import_react_native23 = require("react-native");
6302
6366
  init_PaywalloClient();
6303
6367
  import_jsx_runtime4 = require("react/jsx-runtime");
6304
6368
  NativeWebViewComponent2 = null;
6305
6369
  nativeLookupFailed = false;
6306
6370
  DEFAULT_DURATION_MS = 60 * 1e3;
6307
- styles4 = import_react_native22.StyleSheet.create({
6371
+ styles4 = import_react_native23.StyleSheet.create({
6308
6372
  hidden: {
6309
6373
  height: 1,
6310
6374
  left: -9999,
@@ -6821,8 +6885,9 @@ var init_schemas = __esm({
6821
6885
  path: ["transaction_id"]
6822
6886
  });
6823
6887
  onboardingEventSchema = import_zod.z.object({
6824
- type: import_zod.z.enum(["step", "complete", "drop"]),
6825
- step_index: import_zod.z.number().int().nonnegative().optional(),
6888
+ type: import_zod.z.enum(["step", "complete"]),
6889
+ family: import_zod.z.literal("onboarding").optional(),
6890
+ order: import_zod.z.number().nonnegative().optional(),
6826
6891
  step_name: import_zod.z.string().optional(),
6827
6892
  variant_key: import_zod.z.string().optional(),
6828
6893
  time_on_prev_s: import_zod.z.number().nonnegative().optional()
@@ -6919,7 +6984,7 @@ function isValidEventName(name) {
6919
6984
  async function trackEvent(apiClient, state, eventName, options) {
6920
6985
  const distinctId = identityManager.getDistinctId();
6921
6986
  if (!distinctId) {
6922
- console.error("[Paywallo:DROP] event dropped \u2014 no distinctId available yet", { eventName });
6987
+ if (state.config?.debug) console.log("[Paywallo:DROP] event dropped \u2014 no distinctId available yet", { eventName });
6923
6988
  return;
6924
6989
  }
6925
6990
  if (!isValidEventName(eventName)) {
@@ -7341,12 +7406,12 @@ async function detectEnvironment() {
7341
7406
  cached = "sandbox";
7342
7407
  return cached;
7343
7408
  }
7344
- if (!nativeModule) {
7409
+ if (!nativeModule2) {
7345
7410
  cached = "production";
7346
7411
  return cached;
7347
7412
  }
7348
7413
  try {
7349
- const result = await nativeModule.detect();
7414
+ const result = await nativeModule2.detect();
7350
7415
  cached = result === "sandbox" ? "sandbox" : "production";
7351
7416
  return cached;
7352
7417
  } catch {
@@ -7354,12 +7419,12 @@ async function detectEnvironment() {
7354
7419
  return cached;
7355
7420
  }
7356
7421
  }
7357
- var import_react_native23, nativeModule, cached;
7422
+ var import_react_native24, nativeModule2, cached;
7358
7423
  var init_detectEnvironment = __esm({
7359
7424
  "src/utils/detectEnvironment.ts"() {
7360
7425
  "use strict";
7361
- import_react_native23 = require("react-native");
7362
- nativeModule = import_react_native23.NativeModules.PaywalloEnv ?? null;
7426
+ import_react_native24 = require("react-native");
7427
+ nativeModule2 = import_react_native24.NativeModules.PaywalloEnv ?? null;
7363
7428
  cached = null;
7364
7429
  }
7365
7430
  });
@@ -7427,6 +7492,32 @@ var init_apiPurchaseMethods = __esm({
7427
7492
  }
7428
7493
  });
7429
7494
 
7495
+ // src/utils/userAgent.ts
7496
+ function buildUserAgent(sdkVersion) {
7497
+ const clean = (v) => v.replace(/[^\x20-\x7E]/g, "").replace(/[();]/g, "").trim();
7498
+ const info = typeof nativeDeviceInfo.getCachedDeviceInfo === "function" ? nativeDeviceInfo.getCachedDeviceInfo() : null;
7499
+ if (!info) {
7500
+ return `PaywalloSDK/${sdkVersion} (${clean(import_react_native25.Platform.OS)})`;
7501
+ }
7502
+ const isValid = (v) => {
7503
+ if (typeof v !== "string") return false;
7504
+ const c = clean(v);
7505
+ return c.length > 0 && c !== "unknown";
7506
+ };
7507
+ const parts = [clean(info.osName)];
7508
+ if (isValid(info.systemVersion)) parts.push(clean(info.systemVersion));
7509
+ const detail = isValid(info.model) ? `; ${clean(info.model)}` : "";
7510
+ return `PaywalloSDK/${sdkVersion} (${parts.join(" ")}${detail})`;
7511
+ }
7512
+ var import_react_native25;
7513
+ var init_userAgent = __esm({
7514
+ "src/utils/userAgent.ts"() {
7515
+ "use strict";
7516
+ import_react_native25 = require("react-native");
7517
+ init_NativeDeviceInfo();
7518
+ }
7519
+ });
7520
+
7430
7521
  // src/core/ApiCache.ts
7431
7522
  var ApiCache;
7432
7523
  var init_ApiCache = __esm({
@@ -7654,6 +7745,11 @@ function isServerError(res) {
7654
7745
  const r = res;
7655
7746
  return r.ok === false && typeof r.status === "number" && r.status >= 500;
7656
7747
  }
7748
+ function isRateLimitError(res) {
7749
+ if (typeof res !== "object" || res === null) return false;
7750
+ const r = res;
7751
+ return r.ok === false && r.status === 429;
7752
+ }
7657
7753
  async function postWithQueue(deps, url, payload, label, priority) {
7658
7754
  const enqueue = async () => {
7659
7755
  await offlineQueue.enqueue(
@@ -7665,6 +7761,11 @@ async function postWithQueue(deps, url, payload, label, priority) {
7665
7761
  priority
7666
7762
  );
7667
7763
  };
7764
+ if (priority === "critical" && deps.isOfflineQueueEnabled()) {
7765
+ await enqueue();
7766
+ if (deps.isDebug()) console.log("[Paywallo:ApiClient] Critical event queued (write-ahead):", label);
7767
+ return;
7768
+ }
7668
7769
  if (deps.isOfflineQueueEnabled() && !networkMonitor.isOnline()) {
7669
7770
  await enqueue();
7670
7771
  if (deps.isDebug()) console.log("[Paywallo:ApiClient] Queued for offline:", label, priority ?? "normal");
@@ -7675,6 +7776,9 @@ async function postWithQueue(deps, url, payload, label, priority) {
7675
7776
  if (isServerError(res) && deps.isOfflineQueueEnabled()) {
7676
7777
  if (deps.isDebug()) console.log("[Paywallo:ApiClient] Server error, queued for retry:", label, priority ?? "normal");
7677
7778
  await enqueue();
7779
+ } else if (isRateLimitError(res) && deps.isOfflineQueueEnabled()) {
7780
+ if (deps.isDebug()) console.log("[Paywallo:ApiClient] Rate limited (429), queued for retry:", label, priority ?? "normal");
7781
+ await enqueue();
7678
7782
  }
7679
7783
  } catch (error) {
7680
7784
  if (deps.isDebug()) console.log("[Paywallo:ApiClient] Request failed:", label, error);
@@ -7719,7 +7823,7 @@ function buildV2Envelope(events, providerContext) {
7719
7823
  return { id, ts: event.timestamp, name: family, payload };
7720
7824
  });
7721
7825
  if (context.sdk_version === void 0) context.sdk_version = SDK_VERSION;
7722
- if (context.platform === void 0) context.platform = import_react_native24.Platform.OS;
7826
+ if (context.platform === void 0) context.platform = import_react_native26.Platform.OS;
7723
7827
  if (context.distinct_id === void 0 && events.length > 0) {
7724
7828
  context.distinct_id = events[0].distinctId;
7725
7829
  }
@@ -7777,11 +7881,11 @@ function splitPayloadAndContext(properties) {
7777
7881
  }
7778
7882
  return { payload, promoted };
7779
7883
  }
7780
- var import_react_native24, import_zod2, v2EventSchema, v2ContextSchema, v2EnvelopeSchema, IDS_PROMO_ALIASES, CONTEXT_KEY_ALIASES;
7884
+ var import_react_native26, import_zod2, v2EventSchema, v2ContextSchema, v2EnvelopeSchema, IDS_PROMO_ALIASES, CONTEXT_KEY_ALIASES;
7781
7885
  var init_eventEnvelopeV2 = __esm({
7782
7886
  "src/core/eventEnvelopeV2.ts"() {
7783
7887
  "use strict";
7784
- import_react_native24 = require("react-native");
7888
+ import_react_native26 = require("react-native");
7785
7889
  import_zod2 = require("zod");
7786
7890
  init_uuid();
7787
7891
  init_eventFamilies();
@@ -7859,11 +7963,11 @@ var init_events = __esm({
7859
7963
  });
7860
7964
 
7861
7965
  // src/core/EventBatcher.ts
7862
- var import_react_native25, BATCH_MAX_SIZE, BATCH_FLUSH_MS, EVENT_NAME_REGEX, V2_BATCH_ENDPOINT, EventBatcher;
7966
+ var import_react_native27, BATCH_MAX_SIZE, BATCH_FLUSH_MS, EVENT_NAME_REGEX, V2_BATCH_ENDPOINT, EventBatcher;
7863
7967
  var init_EventBatcher = __esm({
7864
7968
  "src/core/EventBatcher.ts"() {
7865
7969
  "use strict";
7866
- import_react_native25 = require("react-native");
7970
+ import_react_native27 = require("react-native");
7867
7971
  init_eventEnvelopeV2();
7868
7972
  init_events();
7869
7973
  BATCH_MAX_SIZE = 25;
@@ -7872,10 +7976,8 @@ var init_EventBatcher = __esm({
7872
7976
  V2_BATCH_ENDPOINT = "/sdk/ingest/batch";
7873
7977
  EventBatcher = class {
7874
7978
  constructor(post, debug = false, contextProvider = null) {
7875
- this.criticalQueue = [];
7876
7979
  this.normalQueue = [];
7877
7980
  this.normalTimer = null;
7878
- this.criticalScheduled = false;
7879
7981
  this.post = post;
7880
7982
  this.debug = debug;
7881
7983
  this.contextProvider = contextProvider;
@@ -7912,14 +8014,17 @@ var init_EventBatcher = __esm({
7912
8014
  const event = {
7913
8015
  eventName,
7914
8016
  distinctId,
7915
- properties: { ...properties, platform: import_react_native25.Platform.OS },
8017
+ properties: { ...properties, platform: import_react_native27.Platform.OS },
7916
8018
  timestamp: timestamp ?? Date.now(),
7917
8019
  environment: environment.toLowerCase()
7918
8020
  };
7919
8021
  const priority = options?.priority ?? "normal";
7920
8022
  if (priority === "critical") {
7921
- this.criticalQueue.push(event);
7922
- this.scheduleCriticalFlush();
8023
+ try {
8024
+ await this.postBatch([event], `event_critical:${event.eventName}`, "critical");
8025
+ } catch (err) {
8026
+ if (this.debug) console.log("[Paywallo:CRITICAL] critical event post failed", { eventName: event.eventName, error: err instanceof Error ? err.message : String(err) });
8027
+ }
7923
8028
  return;
7924
8029
  }
7925
8030
  this.normalQueue.push(event);
@@ -7940,9 +8045,10 @@ var init_EventBatcher = __esm({
7940
8045
  }
7941
8046
  /**
7942
8047
  * Force flush of the normal queue. Critical events are never held in the
7943
- * normal queue, so this does not affect them (they flush on their own
7944
- * microtask). Exposed so callers (e.g. `AppState=background` listener in
7945
- * phase 2.4) can drain pending events before the app is suspended.
8048
+ * normal queue, so this does not affect them they are posted (and
8049
+ * awaited) synchronously inside `track()`. Exposed so callers (e.g.
8050
+ * `AppState=background` listener in phase 2.4) can drain pending events
8051
+ * before the app is suspended.
7946
8052
  */
7947
8053
  async flush() {
7948
8054
  await this.flushNormal();
@@ -7952,28 +8058,7 @@ var init_EventBatcher = __esm({
7952
8058
  clearTimeout(this.normalTimer);
7953
8059
  this.normalTimer = null;
7954
8060
  }
7955
- this.criticalQueue = [];
7956
8061
  this.normalQueue = [];
7957
- this.criticalScheduled = false;
7958
- }
7959
- scheduleCriticalFlush() {
7960
- if (this.criticalScheduled) return;
7961
- this.criticalScheduled = true;
7962
- queueMicrotask(() => {
7963
- this.criticalScheduled = false;
7964
- void this.flushCritical();
7965
- });
7966
- }
7967
- async flushCritical() {
7968
- if (this.criticalQueue.length === 0) return;
7969
- const drained = this.criticalQueue.splice(0, this.criticalQueue.length);
7970
- for (const event of drained) {
7971
- try {
7972
- await this.postBatch([event], `event_critical:${event.eventName}`, "critical");
7973
- } catch (err) {
7974
- console.error("[Paywallo:CRITICAL] critical event post failed", { eventName: event.eventName, error: err instanceof Error ? err.message : String(err) });
7975
- }
7976
- }
7977
8062
  }
7978
8063
  async flushNormal() {
7979
8064
  if (this.normalQueue.length === 0) return;
@@ -7985,7 +8070,7 @@ var init_EventBatcher = __esm({
7985
8070
  try {
7986
8071
  await this.postBatch(batch, `event_batch:${batch.length}`);
7987
8072
  } catch (err) {
7988
- console.error("[Paywallo:NORMAL] batch post failed \u2014 relying on OfflineQueue", { batchSize: batch.length, error: err instanceof Error ? err.message : String(err) });
8073
+ if (this.debug) console.log("[Paywallo:NORMAL] batch post failed \u2014 relying on OfflineQueue", { batchSize: batch.length, error: err instanceof Error ? err.message : String(err) });
7989
8074
  }
7990
8075
  }
7991
8076
  async postBatch(events, label, priority = "normal") {
@@ -8000,7 +8085,7 @@ var init_EventBatcher = __esm({
8000
8085
  const parsed = v2EnvelopeSchema.safeParse(envelope);
8001
8086
  if (!parsed.success) {
8002
8087
  if (this.debug) console.log("[Paywallo EVENTS] V2 envelope schema validation failed:", parsed.error.issues);
8003
- console.error("[Paywallo:CRITICAL] V2 envelope schema validation failed", { issues: parsed.error.issues, eventCount: events.length, firstEventName: events[0]?.eventName, context: providerContext });
8088
+ if (this.debug) console.log("[Paywallo:CRITICAL] V2 envelope schema validation failed", { issues: parsed.error.issues, eventCount: events.length, firstEventName: events[0]?.eventName, context: providerContext });
8004
8089
  throw parsed.error;
8005
8090
  }
8006
8091
  await this.post(V2_BATCH_ENDPOINT, parsed.data, label, priority);
@@ -8258,6 +8343,7 @@ function buildPiiPayload(pii) {
8258
8343
  if (dob) result.dateOfBirth = dob;
8259
8344
  const g = normalizeGender(pii.gender);
8260
8345
  if (g) result.gender = g;
8346
+ if (pii.zipCode) result.zipCode = pii.zipCode.trim();
8261
8347
  return result;
8262
8348
  }
8263
8349
  function normalizeGender(raw) {
@@ -8267,12 +8353,13 @@ function normalizeGender(raw) {
8267
8353
  if (lower === "f" || lower === "female") return "f";
8268
8354
  return void 0;
8269
8355
  }
8270
- var import_react_native26, DATE_OF_BIRTH_RE, ApiClient;
8356
+ var import_react_native28, DATE_OF_BIRTH_RE, ApiClient;
8271
8357
  var init_ApiClient = __esm({
8272
8358
  "src/core/ApiClient.ts"() {
8273
8359
  "use strict";
8274
- import_react_native26 = require("react-native");
8360
+ import_react_native28 = require("react-native");
8275
8361
  init_apiPurchaseMethods();
8362
+ init_userAgent();
8276
8363
  init_ApiCache();
8277
8364
  init_ApiClientFlags();
8278
8365
  init_ApiClientQueue();
@@ -8372,10 +8459,13 @@ var init_ApiClient = __esm({
8372
8459
  * should carry. Keep this tiny — it runs once per ApiClient instance.
8373
8460
  */
8374
8461
  buildSdkHeaders() {
8462
+ const ua = buildUserAgent(SDK_VERSION);
8375
8463
  return {
8376
8464
  "x-sdk-version": SDK_VERSION,
8377
- "x-sdk-platform": import_react_native26.Platform.OS,
8378
- "x-sdk-environment": this.environment
8465
+ "x-sdk-platform": import_react_native28.Platform.OS,
8466
+ "x-sdk-environment": this.environment,
8467
+ "User-Agent": ua,
8468
+ "x-sdk-user-agent": ua
8379
8469
  };
8380
8470
  }
8381
8471
  async clearQueue() {
@@ -8404,7 +8494,7 @@ var init_ApiClient = __esm({
8404
8494
  message,
8405
8495
  context,
8406
8496
  sdkVersion: SDK_VERSION,
8407
- platform: import_react_native26.Platform.OS
8497
+ platform: import_react_native28.Platform.OS
8408
8498
  }, true);
8409
8499
  } catch (err) {
8410
8500
  if (this.debug) console.log("[Paywallo:ApiClient] reportError failed", err);
@@ -8422,7 +8512,7 @@ var init_ApiClient = __esm({
8422
8512
  async identify(distinctId, properties, email, deviceId, pii) {
8423
8513
  const rawTraits = {
8424
8514
  email: email || void 0,
8425
- platform: import_react_native26.Platform.OS,
8515
+ platform: import_react_native28.Platform.OS,
8426
8516
  name: properties?.name,
8427
8517
  country: properties?.country,
8428
8518
  locale: properties?.locale,
@@ -8618,7 +8708,6 @@ function setupNotifications(apiClient, config, environment, eventPipeline) {
8618
8708
  notificationsManager.setupHandlers({ eventBatcher: eventPipeline });
8619
8709
  notificationsManager.initialize({
8620
8710
  appKey: config.appKey,
8621
- apiBaseUrl: DEFAULT_API_URL,
8622
8711
  debug: config.debug,
8623
8712
  environment: environment === "Sandbox" ? "sandbox" : "production"
8624
8713
  }).catch((err) => {
@@ -8660,7 +8749,6 @@ var init_PaywalloInitHelpers = __esm({
8660
8749
  init_identity();
8661
8750
  init_notifications();
8662
8751
  init_NativePushBridge();
8663
- init_constants();
8664
8752
  init_SecureStorage();
8665
8753
  }
8666
8754
  });
@@ -8750,7 +8838,7 @@ function reportInitFailure(state, config, error, reason) {
8750
8838
  error: error instanceof Error ? error.message : String(error)
8751
8839
  });
8752
8840
  } catch (err) {
8753
- console.error("[Paywallo] reportInitFailure error", err);
8841
+ if (config.debug) console.log("[Paywallo] reportInitFailure error", err);
8754
8842
  }
8755
8843
  }
8756
8844
  function reportInitSuccess(state, config, attempts) {
@@ -8759,7 +8847,7 @@ function reportInitSuccess(state, config, attempts) {
8759
8847
  void state.apiClient.reportError("INIT_RECOVERED", `Succeeded after ${attempts} retries`, { attempts });
8760
8848
  }
8761
8849
  } catch (err) {
8762
- console.error("[Paywallo] reportInitSuccess error", err);
8850
+ if (config.debug) console.log("[Paywallo] reportInitSuccess error", err);
8763
8851
  }
8764
8852
  }
8765
8853
  async function resolveSessionFlags(state, keys, apiClient, distinctId) {
@@ -8835,9 +8923,14 @@ async function doInit(state, config) {
8835
8923
  } catch (err) {
8836
8924
  if (config.debug) console.log("[Paywallo ATTR] start error", err);
8837
8925
  }
8838
- void nativeDeviceInfo.getDeviceInfo().catch(() => null);
8839
- void advertisingIdManager.collect(false).catch(() => null);
8840
- void metaBridge.getAnonymousID().catch(() => null);
8926
+ await Promise.race([
8927
+ Promise.all([
8928
+ nativeDeviceInfo.getDeviceInfo().catch(() => null),
8929
+ advertisingIdManager.collect(false).catch(() => null),
8930
+ metaBridge.getAnonymousID().catch(() => null)
8931
+ ]),
8932
+ new Promise((resolve) => setTimeout(resolve, 350))
8933
+ ]);
8841
8934
  apiClient.setEventContextProvider(() => {
8842
8935
  const attr = attributionTracker.get();
8843
8936
  const attrEntries = attr ? [
@@ -8874,10 +8967,10 @@ async function doInit(state, config) {
8874
8967
  let screenHeight;
8875
8968
  let screenDensity;
8876
8969
  try {
8877
- const screen = import_react_native27.Dimensions.get("screen");
8970
+ const screen = import_react_native29.Dimensions.get("screen");
8878
8971
  screenWidth = Math.round(screen.width) || void 0;
8879
8972
  screenHeight = Math.round(screen.height) || void 0;
8880
- screenDensity = import_react_native27.PixelRatio.get() || void 0;
8973
+ screenDensity = import_react_native29.PixelRatio.get() || void 0;
8881
8974
  } catch {
8882
8975
  }
8883
8976
  return {
@@ -8913,12 +9006,15 @@ async function doInit(state, config) {
8913
9006
  setupNotifications(apiClient, config, environment, eventPipeline);
8914
9007
  if (config.autoStartSession !== false) {
8915
9008
  sessionManager.startSession().catch((err) => {
8916
- console.error("[Paywallo INIT] autoStart session error", err);
9009
+ if (config.debug) console.log("[Paywallo INIT] autoStart session error", err);
8917
9010
  });
8918
9011
  }
8919
9012
  new InstallTracker(config.debug, {
8920
9013
  distinctIdProvider: () => identityManager.getDistinctId()
8921
- }).trackIfNeeded(apiClient, config.requestATT === true).catch(() => {
9014
+ }).trackIfNeeded(apiClient, config.requestATT === true).then(() => {
9015
+ if (config.debug) console.log("[Paywallo INSTALL] $app_installed sent");
9016
+ }).catch(() => {
9017
+ if (config.debug) console.log("[Paywallo INSTALL] $app_installed failed \u2014 will retry on next launch");
8922
9018
  });
8923
9019
  if (config.sessionFlags && config.sessionFlags.length > 0) {
8924
9020
  await resolveSessionFlags(state, config.sessionFlags, apiClient, distinctId);
@@ -8944,11 +9040,11 @@ async function doInit(state, config) {
8944
9040
  setupAutoPreload(state, apiClient, config, distinctId);
8945
9041
  startBatchPreload(apiClient, config.debug);
8946
9042
  }
8947
- var import_react_native27;
9043
+ var import_react_native29;
8948
9044
  var init_PaywalloInitializer = __esm({
8949
9045
  "src/core/PaywalloInitializer.ts"() {
8950
9046
  "use strict";
8951
- import_react_native27 = require("react-native");
9047
+ import_react_native29 = require("react-native");
8952
9048
  init_identity();
8953
9049
  init_AdvertisingIdManager();
8954
9050
  init_DeepLinkAttributionCapture();
@@ -9155,6 +9251,7 @@ var init_PaywalloClient = __esm({
9155
9251
  }
9156
9252
  if (this.state.config?.debug) console.log("[Paywallo IDENTIFY]", options ? { hasEmail: "email" in options && !!options.email, hasProperties: "properties" in options } : void 0);
9157
9253
  await identityManager.identify(options);
9254
+ if (this.state.config?.debug) console.log("[Paywallo IDENTIFY] done");
9158
9255
  }
9159
9256
  async track(eventName, options) {
9160
9257
  return trackEvent(this.getApiClientOrThrow(), this.state, eventName, options);
@@ -9389,7 +9486,7 @@ __export(OfferingService_exports, {
9389
9486
  offeringService: () => offeringService
9390
9487
  });
9391
9488
  function resolveProductId(raw) {
9392
- const isIos = import_react_native28.Platform.OS === "ios";
9489
+ const isIos = import_react_native30.Platform.OS === "ios";
9393
9490
  const productId = isIos ? raw.apple_product_id : raw.google_product_id;
9394
9491
  return productId ?? "";
9395
9492
  }
@@ -9408,7 +9505,7 @@ function mapProduct2(raw) {
9408
9505
  };
9409
9506
  }
9410
9507
  function pickPlatformProduct(products) {
9411
- const isIos = import_react_native28.Platform.OS === "ios";
9508
+ const isIos = import_react_native30.Platform.OS === "ios";
9412
9509
  const match = products.find((p) => isIos ? p.apple_product_id : p.google_product_id);
9413
9510
  return match ?? products[0] ?? null;
9414
9511
  }
@@ -9424,11 +9521,11 @@ function mapOffering(raw) {
9424
9521
  product: mapProduct2(rawProduct)
9425
9522
  };
9426
9523
  }
9427
- var import_react_native28, OFFERINGS_CACHE_KEY, DEFAULT_TTL3, OfferingService, offeringService;
9524
+ var import_react_native30, OFFERINGS_CACHE_KEY, DEFAULT_TTL3, OfferingService, offeringService;
9428
9525
  var init_OfferingService = __esm({
9429
9526
  "src/domains/offering/OfferingService.ts"() {
9430
9527
  "use strict";
9431
- import_react_native28 = require("react-native");
9528
+ import_react_native30 = require("react-native");
9432
9529
  init_SecureStorage();
9433
9530
  OFFERINGS_CACHE_KEY = "@paywallo:offerings_cache";
9434
9531
  DEFAULT_TTL3 = 5 * 60 * 1e3;
@@ -9715,18 +9812,14 @@ var import_react15 = require("react");
9715
9812
  init_onboarding();
9716
9813
  function useOnboarding() {
9717
9814
  const step = (0, import_react15.useCallback)(
9718
- (stepName, order) => onboardingManager.step(stepName, order),
9815
+ (stepName, order, options) => onboardingManager.step(stepName, order, options),
9719
9816
  []
9720
9817
  );
9721
9818
  const complete = (0, import_react15.useCallback)(
9722
- () => onboardingManager.complete(),
9723
- []
9724
- );
9725
- const drop = (0, import_react15.useCallback)(
9726
- (stepName) => onboardingManager.drop(stepName),
9819
+ (options) => onboardingManager.complete(options),
9727
9820
  []
9728
9821
  );
9729
- return { step, complete, drop };
9822
+ return { step, complete };
9730
9823
  }
9731
9824
 
9732
9825
  // src/hooks/usePaywallo.ts
@@ -10094,7 +10187,7 @@ function useSubscription() {
10094
10187
 
10095
10188
  // src/PaywalloProvider.tsx
10096
10189
  var import_react28 = require("react");
10097
- var import_react_native29 = require("react-native");
10190
+ var import_react_native31 = require("react-native");
10098
10191
  init_PaywalloClient();
10099
10192
  init_NativeStorage();
10100
10193
  init_SecureStorage();
@@ -10986,8 +11079,8 @@ function PaywalloProvider({ children, config }) {
10986
11079
  });
10987
11080
  }, []);
10988
11081
  const { showingPreloadedWebView, presentPreloadedWebView, resolvePreloadedPaywall, handlePreloadedWebViewReady: baseHandlePreloadedWebViewReady, handlePreloadedClose: baseHandlePreloadedClose, setShowingPreloadedWebView, presentedAtRef } = usePaywallPresenter(preloadedWebView, setPreloadedWebView);
10989
- const SCREEN_HEIGHT = (0, import_react28.useMemo)(() => import_react_native29.Dimensions.get("window").height, []);
10990
- const slideAnim = (0, import_react28.useRef)(new import_react_native29.Animated.Value(SCREEN_HEIGHT)).current;
11082
+ const SCREEN_HEIGHT = (0, import_react28.useMemo)(() => import_react_native31.Dimensions.get("window").height, []);
11083
+ const slideAnim = (0, import_react28.useRef)(new import_react_native31.Animated.Value(SCREEN_HEIGHT)).current;
10991
11084
  const handlePreloadedWebViewReady = (0, import_react28.useCallback)(() => {
10992
11085
  if (PaywalloClient.getConfig()?.debug) {
10993
11086
  console.log(`[Paywallo WEBVIEW] loaded \u2014 placement: ${preloadedWebView?.placement}`);
@@ -10996,7 +11089,7 @@ function PaywalloProvider({ children, config }) {
10996
11089
  }, [preloadedWebView?.placement, baseHandlePreloadedWebViewReady]);
10997
11090
  const handlePreloadedClose = (0, import_react28.useCallback)(() => {
10998
11091
  const placement = preloadedWebView?.placement;
10999
- import_react_native29.Animated.timing(slideAnim, { toValue: SCREEN_HEIGHT, duration: 200, easing: import_react_native29.Easing.in(import_react_native29.Easing.cubic), useNativeDriver: true }).start(() => {
11092
+ import_react_native31.Animated.timing(slideAnim, { toValue: SCREEN_HEIGHT, duration: 200, easing: import_react_native31.Easing.in(import_react_native31.Easing.cubic), useNativeDriver: true }).start(() => {
11000
11093
  baseHandlePreloadedClose();
11001
11094
  if (placement) triggerRepreload(placement);
11002
11095
  });
@@ -11040,6 +11133,7 @@ function PaywalloProvider({ children, config }) {
11040
11133
  void pushAttributionToSuperwall(configRef.current.debug);
11041
11134
  setDistinctId(PaywalloClient.getDistinctId());
11042
11135
  setIsInitialized(true);
11136
+ if (configRef.current.debug) console.log("[Paywallo] SDK ready", PaywalloClient.getDistinctId()?.slice(0, 8));
11043
11137
  if (!autoPreloadTriggeredRef.current) {
11044
11138
  autoPreloadTriggeredRef.current = true;
11045
11139
  const placement = await PaywalloClient.waitForAutoPreloadedPlacement();
@@ -11280,7 +11374,7 @@ function PaywalloProvider({ children, config }) {
11280
11374
  (0, import_react28.useLayoutEffect)(() => {
11281
11375
  if (showingPreloadedWebView) {
11282
11376
  slideAnim.setValue(SCREEN_HEIGHT);
11283
- import_react_native29.Animated.timing(slideAnim, { toValue: 0, duration: 200, easing: import_react_native29.Easing.out(import_react_native29.Easing.cubic), useNativeDriver: true }).start();
11377
+ import_react_native31.Animated.timing(slideAnim, { toValue: 0, duration: 200, easing: import_react_native31.Easing.out(import_react_native31.Easing.cubic), useNativeDriver: true }).start();
11284
11378
  }
11285
11379
  }, [showingPreloadedWebView, slideAnim, SCREEN_HEIGHT]);
11286
11380
  const preloadStyle = [
@@ -11290,7 +11384,7 @@ function PaywalloProvider({ children, config }) {
11290
11384
  ];
11291
11385
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(PaywalloContext.Provider, { value: contextValue, children: [
11292
11386
  children,
11293
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PaywallErrorBoundary, { children: !!preloadedWebView?.craftData && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native29.Animated.View, { style: preloadStyle, pointerEvents: showingPreloadedWebView ? "auto" : "none", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11387
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PaywallErrorBoundary, { children: !!preloadedWebView?.craftData && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_react_native31.Animated.View, { style: preloadStyle, pointerEvents: showingPreloadedWebView ? "auto" : "none", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11294
11388
  PaywallWebView,
11295
11389
  {
11296
11390
  paywallId: preloadedWebView.paywallId,
@@ -11322,7 +11416,7 @@ function PaywalloProvider({ children, config }) {
11322
11416
  isInitialized && (config.preloadPaywalls?.length ?? 0) > 0 && PaywalloClient.getWebUrl() !== null && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PaywallWebViewPrewarmer, { webUrl: PaywalloClient.getWebUrl() })
11323
11417
  ] });
11324
11418
  }
11325
- var styles5 = import_react_native29.StyleSheet.create({
11419
+ var styles5 = import_react_native31.StyleSheet.create({
11326
11420
  preloadOverlay: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0, backgroundColor: "#ffffff" },
11327
11421
  hidden: { zIndex: -1, opacity: 0, width: 1, height: 1, overflow: "hidden" },
11328
11422
  visible: { zIndex: 9999, opacity: 1 }