@billdog.io/react-native 1.0.0-beta.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.
Files changed (309) hide show
  1. package/BillDogReactNative.podspec +30 -0
  2. package/LICENSE +21 -0
  3. package/README.md +330 -0
  4. package/android/build.gradle +99 -0
  5. package/android/src/main/AndroidManifest.xml +1 -0
  6. package/android/src/main/kotlin/io/billdog/reactnative/BillDogABTestModule.kt +317 -0
  7. package/android/src/main/kotlin/io/billdog/reactnative/BillDogAnalyticsModule.kt +389 -0
  8. package/android/src/main/kotlin/io/billdog/reactnative/BillDogModule.kt +817 -0
  9. package/android/src/main/kotlin/io/billdog/reactnative/BillDogPaywallViewManager.kt +383 -0
  10. package/android/src/main/kotlin/io/billdog/reactnative/BillDogSurveyModule.kt +427 -0
  11. package/android/src/main/kotlin/io/billdog/reactnative/BillDogVirtualCurrencyModule.kt +407 -0
  12. package/android/src/main/kotlin/io/billdog/virtualcurrency/BillDogVirtualCurrencyPackage.kt +44 -0
  13. package/dist/AdvancedPaywallCache.d.ts +70 -0
  14. package/dist/AdvancedPaywallCache.js +344 -0
  15. package/dist/BillDog.d.ts +255 -0
  16. package/dist/BillDog.js +918 -0
  17. package/dist/BillDogConfiguration.d.ts +145 -0
  18. package/dist/BillDogConfiguration.js +229 -0
  19. package/dist/ComponentRenderer.d.ts +17 -0
  20. package/dist/ComponentRenderer.js +886 -0
  21. package/dist/LayoutEngine.d.ts +101 -0
  22. package/dist/LayoutEngine.js +394 -0
  23. package/dist/LocalizationResolver.d.ts +99 -0
  24. package/dist/LocalizationResolver.js +266 -0
  25. package/dist/NativePaywallView.d.ts +36 -0
  26. package/dist/NativePaywallView.js +59 -0
  27. package/dist/PaywallCache.d.ts +74 -0
  28. package/dist/PaywallCache.js +293 -0
  29. package/dist/PaywallStateManager.d.ts +62 -0
  30. package/dist/PaywallStateManager.js +147 -0
  31. package/dist/PaywallView.d.ts +42 -0
  32. package/dist/PaywallView.js +275 -0
  33. package/dist/ProductVariableProvider.d.ts +60 -0
  34. package/dist/ProductVariableProvider.js +239 -0
  35. package/dist/VariableResolver.d.ts +120 -0
  36. package/dist/VariableResolver.js +379 -0
  37. package/dist/WebViewPaywall.d.ts +75 -0
  38. package/dist/WebViewPaywall.js +360 -0
  39. package/dist/animations/presets.d.ts +49 -0
  40. package/dist/animations/presets.js +367 -0
  41. package/dist/components/AccoladeCpsComponent.d.ts +13 -0
  42. package/dist/components/AccoladeCpsComponent.js +248 -0
  43. package/dist/components/AccordionComponent.d.ts +10 -0
  44. package/dist/components/AccordionComponent.js +187 -0
  45. package/dist/components/AnimatedWrapper.d.ts +35 -0
  46. package/dist/components/AnimatedWrapper.js +277 -0
  47. package/dist/components/CarouselComponent.d.ts +23 -0
  48. package/dist/components/CarouselComponent.js +484 -0
  49. package/dist/components/ChartCurveComponent.d.ts +13 -0
  50. package/dist/components/ChartCurveComponent.js +333 -0
  51. package/dist/components/CheckboxComponent.d.ts +9 -0
  52. package/dist/components/CheckboxComponent.js +172 -0
  53. package/dist/components/ConfettiComponent.d.ts +9 -0
  54. package/dist/components/ConfettiComponent.js +172 -0
  55. package/dist/components/CountdownComponent.d.ts +16 -0
  56. package/dist/components/CountdownComponent.js +414 -0
  57. package/dist/components/DelayedXComponent.d.ts +12 -0
  58. package/dist/components/DelayedXComponent.js +240 -0
  59. package/dist/components/DrawerModalComponent.d.ts +20 -0
  60. package/dist/components/DrawerModalComponent.js +286 -0
  61. package/dist/components/GradientView.d.ts +38 -0
  62. package/dist/components/GradientView.js +126 -0
  63. package/dist/components/HapticFeedbackComponent.d.ts +16 -0
  64. package/dist/components/HapticFeedbackComponent.js +64 -0
  65. package/dist/components/HorizontalProductsComponent.d.ts +17 -0
  66. package/dist/components/HorizontalProductsComponent.js +284 -0
  67. package/dist/components/MultiChoiceGridComponent.d.ts +13 -0
  68. package/dist/components/MultiChoiceGridComponent.js +234 -0
  69. package/dist/components/NPSScaleComponent.d.ts +16 -0
  70. package/dist/components/NPSScaleComponent.js +260 -0
  71. package/dist/components/NavigationComponent.d.ts +26 -0
  72. package/dist/components/NavigationComponent.js +302 -0
  73. package/dist/components/OAuthButtonComponent.d.ts +20 -0
  74. package/dist/components/OAuthButtonComponent.js +237 -0
  75. package/dist/components/ProgressLoaderComponent.d.ts +13 -0
  76. package/dist/components/ProgressLoaderComponent.js +308 -0
  77. package/dist/components/ProgressStepperComponent.d.ts +18 -0
  78. package/dist/components/ProgressStepperComponent.js +228 -0
  79. package/dist/components/SegmentedPickerComponent.d.ts +10 -0
  80. package/dist/components/SegmentedPickerComponent.js +221 -0
  81. package/dist/components/ShareButtonsComponent.d.ts +21 -0
  82. package/dist/components/ShareButtonsComponent.js +265 -0
  83. package/dist/components/ShareCodeComponent.d.ts +16 -0
  84. package/dist/components/ShareCodeComponent.js +274 -0
  85. package/dist/components/SingleChoiceGridComponent.d.ts +13 -0
  86. package/dist/components/SingleChoiceGridComponent.js +210 -0
  87. package/dist/components/SliderComponent.d.ts +9 -0
  88. package/dist/components/SliderComponent.js +263 -0
  89. package/dist/components/StarRatingInputComponent.d.ts +20 -0
  90. package/dist/components/StarRatingInputComponent.js +198 -0
  91. package/dist/components/StickerCompositeComponent.d.ts +13 -0
  92. package/dist/components/StickerCompositeComponent.js +136 -0
  93. package/dist/components/TabsComponent.d.ts +19 -0
  94. package/dist/components/TabsComponent.js +431 -0
  95. package/dist/components/TextInputComponent.d.ts +18 -0
  96. package/dist/components/TextInputComponent.js +227 -0
  97. package/dist/components/TimelineComponent.d.ts +19 -0
  98. package/dist/components/TimelineComponent.js +104 -0
  99. package/dist/components/ToggleComponent.d.ts +14 -0
  100. package/dist/components/ToggleComponent.js +132 -0
  101. package/dist/components/VerticalProductsComponent.d.ts +17 -0
  102. package/dist/components/VerticalProductsComponent.js +311 -0
  103. package/dist/dynamicValues.d.ts +36 -0
  104. package/dist/dynamicValues.js +142 -0
  105. package/dist/filters/dateFilters.d.ts +50 -0
  106. package/dist/filters/dateFilters.js +390 -0
  107. package/dist/filters/index.d.ts +18 -0
  108. package/dist/filters/index.js +253 -0
  109. package/dist/hooks/useOfferings.d.ts +76 -0
  110. package/dist/hooks/useOfferings.js +99 -0
  111. package/dist/hooks/usePaywall.d.ts +27 -0
  112. package/dist/hooks/usePaywall.js +114 -0
  113. package/dist/hooks/usePlacement.d.ts +34 -0
  114. package/dist/hooks/usePlacement.js +89 -0
  115. package/dist/hooks/useSubscription.d.ts +40 -0
  116. package/dist/hooks/useSubscription.js +97 -0
  117. package/dist/index.d.ts +98 -0
  118. package/dist/index.js +198 -0
  119. package/dist/models/BillDogError.d.ts +40 -0
  120. package/dist/models/BillDogError.js +11 -0
  121. package/dist/models/CacheFetchPolicy.d.ts +8 -0
  122. package/dist/models/CacheFetchPolicy.js +4 -0
  123. package/dist/models/CustomProduct.d.ts +32 -0
  124. package/dist/models/CustomProduct.js +15 -0
  125. package/dist/models/CustomerInfo.d.ts +17 -0
  126. package/dist/models/CustomerInfo.js +11 -0
  127. package/dist/models/Delegate.d.ts +20 -0
  128. package/dist/models/Delegate.js +11 -0
  129. package/dist/models/EntitlementInfo.d.ts +19 -0
  130. package/dist/models/EntitlementInfo.js +2 -0
  131. package/dist/models/Placement.d.ts +54 -0
  132. package/dist/models/Placement.js +15 -0
  133. package/dist/models/PurchaseParams.d.ts +39 -0
  134. package/dist/models/PurchaseParams.js +60 -0
  135. package/dist/models/PurchaseResult.d.ts +30 -0
  136. package/dist/models/PurchaseResult.js +15 -0
  137. package/dist/models/RestoreResult.d.ts +30 -0
  138. package/dist/models/RestoreResult.js +22 -0
  139. package/dist/models/RestoredItem.d.ts +26 -0
  140. package/dist/models/RestoredItem.js +13 -0
  141. package/dist/modules/ABTest.d.ts +65 -0
  142. package/dist/modules/ABTest.js +113 -0
  143. package/dist/modules/Analytics.d.ts +91 -0
  144. package/dist/modules/Analytics.js +182 -0
  145. package/dist/modules/Survey.d.ts +65 -0
  146. package/dist/modules/Survey.js +82 -0
  147. package/dist/modules/VirtualCurrency.d.ts +63 -0
  148. package/dist/modules/VirtualCurrency.js +147 -0
  149. package/dist/murmur.d.ts +23 -0
  150. package/dist/murmur.js +104 -0
  151. package/dist/notifications/LiveActivitiesManager.d.ts +47 -0
  152. package/dist/notifications/LiveActivitiesManager.js +106 -0
  153. package/dist/notifications/NotificationScheduler.d.ts +55 -0
  154. package/dist/notifications/NotificationScheduler.js +199 -0
  155. package/dist/notifications/PurchaseNotificationHandler.d.ts +24 -0
  156. package/dist/notifications/PurchaseNotificationHandler.js +55 -0
  157. package/dist/notifications/useDeviceToken.d.ts +36 -0
  158. package/dist/notifications/useDeviceToken.js +97 -0
  159. package/dist/notifications/useLiveActivity.d.ts +39 -0
  160. package/dist/notifications/useLiveActivity.js +104 -0
  161. package/dist/review/ReviewAnalytics.d.ts +34 -0
  162. package/dist/review/ReviewAnalytics.js +73 -0
  163. package/dist/review/ReviewManager.d.ts +83 -0
  164. package/dist/review/ReviewManager.js +339 -0
  165. package/dist/review/ReviewTimingManager.d.ts +82 -0
  166. package/dist/review/ReviewTimingManager.js +224 -0
  167. package/dist/survey-core/types.d.ts +215 -0
  168. package/dist/survey-core/types.js +8 -0
  169. package/dist/types.d.ts +438 -0
  170. package/dist/types.js +158 -0
  171. package/dist/utils/ApiClient.d.ts +65 -0
  172. package/dist/utils/ApiClient.js +132 -0
  173. package/dist/utils/CSSConverter.d.ts +49 -0
  174. package/dist/utils/CSSConverter.js +470 -0
  175. package/dist/utils/animations.d.ts +41 -0
  176. package/dist/utils/animations.js +194 -0
  177. package/dist/utils/calendarIntegration.d.ts +36 -0
  178. package/dist/utils/calendarIntegration.js +89 -0
  179. package/dist/utils/configurationResolver.d.ts +23 -0
  180. package/dist/utils/configurationResolver.js +78 -0
  181. package/dist/utils/deviceDetection.d.ts +38 -0
  182. package/dist/utils/deviceDetection.js +59 -0
  183. package/dist/utils/hapticFeedback.d.ts +17 -0
  184. package/dist/utils/hapticFeedback.js +53 -0
  185. package/dist/utils/iconMapper.d.ts +26 -0
  186. package/dist/utils/iconMapper.js +113 -0
  187. package/dist/utils/notificationPermissions.d.ts +13 -0
  188. package/dist/utils/notificationPermissions.js +51 -0
  189. package/dist/utils/priceFormatting.d.ts +19 -0
  190. package/dist/utils/priceFormatting.js +99 -0
  191. package/dist/utils/shareSheet.d.ts +17 -0
  192. package/dist/utils/shareSheet.js +42 -0
  193. package/dist/utils/subscriptionUpgrade.d.ts +84 -0
  194. package/dist/utils/subscriptionUpgrade.js +100 -0
  195. package/dist/valueUtils.d.ts +48 -0
  196. package/dist/valueUtils.js +129 -0
  197. package/dist/xFlowTags.d.ts +18 -0
  198. package/dist/xFlowTags.js +385 -0
  199. package/ios/BillDogABTest.m +50 -0
  200. package/ios/BillDogABTest.swift +188 -0
  201. package/ios/BillDogAnalytics.m +105 -0
  202. package/ios/BillDogAnalytics.swift +324 -0
  203. package/ios/BillDogBridge.m +222 -0
  204. package/ios/BillDogBridge.swift +715 -0
  205. package/ios/BillDogLiveActivities.m +41 -0
  206. package/ios/BillDogLiveActivities.swift +104 -0
  207. package/ios/BillDogPaywallViewManager.m +39 -0
  208. package/ios/BillDogPaywallViewManager.swift +361 -0
  209. package/ios/BillDogSurvey.m +34 -0
  210. package/ios/BillDogSurvey.swift +257 -0
  211. package/ios/BillDogVirtualCurrencyBridge.m +63 -0
  212. package/ios/BillDogVirtualCurrencyBridge.swift +511 -0
  213. package/junit.xml +25 -0
  214. package/package.json +61 -0
  215. package/react-native.config.js +13 -0
  216. package/src/AdvancedPaywallCache.ts +433 -0
  217. package/src/BillDog.ts +983 -0
  218. package/src/BillDogConfiguration.ts +318 -0
  219. package/src/ComponentRenderer.tsx +1325 -0
  220. package/src/LayoutEngine.ts +459 -0
  221. package/src/LocalizationResolver.ts +311 -0
  222. package/src/NativePaywallView.tsx +132 -0
  223. package/src/PaywallCache.ts +358 -0
  224. package/src/PaywallStateManager.ts +154 -0
  225. package/src/PaywallView.tsx +328 -0
  226. package/src/ProductVariableProvider.ts +282 -0
  227. package/src/VariableResolver.ts +516 -0
  228. package/src/WebViewPaywall.tsx +454 -0
  229. package/src/animations/presets.ts +421 -0
  230. package/src/components/AccoladeCpsComponent.tsx +259 -0
  231. package/src/components/AccordionComponent.tsx +213 -0
  232. package/src/components/AnimatedWrapper.tsx +316 -0
  233. package/src/components/CarouselComponent.tsx +615 -0
  234. package/src/components/ChartCurveComponent.tsx +452 -0
  235. package/src/components/CheckboxComponent.tsx +185 -0
  236. package/src/components/ConfettiComponent.tsx +178 -0
  237. package/src/components/CountdownComponent.tsx +454 -0
  238. package/src/components/DelayedXComponent.tsx +266 -0
  239. package/src/components/DrawerModalComponent.tsx +324 -0
  240. package/src/components/GradientView.tsx +129 -0
  241. package/src/components/HapticFeedbackComponent.tsx +39 -0
  242. package/src/components/HorizontalProductsComponent.tsx +329 -0
  243. package/src/components/MultiChoiceGridComponent.tsx +265 -0
  244. package/src/components/NPSScaleComponent.tsx +294 -0
  245. package/src/components/NavigationComponent.tsx +329 -0
  246. package/src/components/OAuthButtonComponent.tsx +266 -0
  247. package/src/components/ProgressLoaderComponent.tsx +366 -0
  248. package/src/components/ProgressStepperComponent.tsx +250 -0
  249. package/src/components/SegmentedPickerComponent.tsx +245 -0
  250. package/src/components/ShareButtonsComponent.tsx +299 -0
  251. package/src/components/ShareCodeComponent.tsx +303 -0
  252. package/src/components/SingleChoiceGridComponent.tsx +229 -0
  253. package/src/components/SliderComponent.tsx +280 -0
  254. package/src/components/StarRatingInputComponent.tsx +223 -0
  255. package/src/components/StickerCompositeComponent.tsx +168 -0
  256. package/src/components/TabsComponent.tsx +496 -0
  257. package/src/components/TextInputComponent.tsx +258 -0
  258. package/src/components/TimelineComponent.tsx +129 -0
  259. package/src/components/ToggleComponent.tsx +142 -0
  260. package/src/components/VerticalProductsComponent.tsx +357 -0
  261. package/src/dynamicValues.ts +180 -0
  262. package/src/filters/dateFilters.ts +411 -0
  263. package/src/filters/index.ts +281 -0
  264. package/src/hooks/useOfferings.ts +192 -0
  265. package/src/hooks/usePaywall.ts +154 -0
  266. package/src/hooks/usePlacement.ts +143 -0
  267. package/src/hooks/useSubscription.ts +154 -0
  268. package/src/index.ts +245 -0
  269. package/src/models/BillDogError.ts +24 -0
  270. package/src/models/CacheFetchPolicy.ts +13 -0
  271. package/src/models/CustomProduct.ts +33 -0
  272. package/src/models/CustomerInfo.ts +26 -0
  273. package/src/models/Delegate.ts +22 -0
  274. package/src/models/EntitlementInfo.ts +27 -0
  275. package/src/models/Placement.ts +50 -0
  276. package/src/models/PurchaseParams.ts +81 -0
  277. package/src/models/PurchaseResult.ts +32 -0
  278. package/src/models/RestoreResult.ts +27 -0
  279. package/src/models/RestoredItem.ts +25 -0
  280. package/src/modules/ABTest.ts +131 -0
  281. package/src/modules/Analytics.ts +227 -0
  282. package/src/modules/Survey.ts +126 -0
  283. package/src/modules/VirtualCurrency.ts +223 -0
  284. package/src/murmur.ts +102 -0
  285. package/src/notifications/LiveActivitiesManager.ts +140 -0
  286. package/src/notifications/NotificationScheduler.ts +292 -0
  287. package/src/notifications/PurchaseNotificationHandler.ts +67 -0
  288. package/src/notifications/useDeviceToken.ts +116 -0
  289. package/src/notifications/useLiveActivity.ts +125 -0
  290. package/src/review/ReviewAnalytics.ts +89 -0
  291. package/src/review/ReviewManager.ts +355 -0
  292. package/src/review/ReviewTimingManager.ts +265 -0
  293. package/src/survey-core/types.ts +244 -0
  294. package/src/types/ambient.d.ts +9 -0
  295. package/src/types.ts +680 -0
  296. package/src/utils/ApiClient.ts +163 -0
  297. package/src/utils/CSSConverter.ts +552 -0
  298. package/src/utils/animations.ts +232 -0
  299. package/src/utils/calendarIntegration.ts +113 -0
  300. package/src/utils/configurationResolver.ts +106 -0
  301. package/src/utils/deviceDetection.ts +83 -0
  302. package/src/utils/hapticFeedback.ts +55 -0
  303. package/src/utils/iconMapper.ts +102 -0
  304. package/src/utils/notificationPermissions.ts +48 -0
  305. package/src/utils/priceFormatting.ts +119 -0
  306. package/src/utils/shareSheet.ts +55 -0
  307. package/src/utils/subscriptionUpgrade.ts +183 -0
  308. package/src/valueUtils.ts +108 -0
  309. package/src/xFlowTags.ts +463 -0
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+ /**
3
+ * Filter Registry and Chain Processor — React Native SDK.
4
+ *
5
+ * Verbatim mirror of src/lib/filters/index.ts (pure TypeScript, no web
6
+ * dependencies). Handles xFlow filter syntax: {{ variable | filter: arg }}
7
+ * and {% assign x = value | filter %}. Kept in lockstep with the web file;
8
+ * the shared conformance corpus enforces parity.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.DATE_FILTERS = exports.ALL_FILTERS = void 0;
12
+ exports.applyFilterChain = applyFilterChain;
13
+ exports.replaceVariablesWithFilters = replaceVariablesWithFilters;
14
+ const dateFilters_1 = require("./dateFilters");
15
+ // ============= String Filters =============
16
+ const STRING_FILTERS = {
17
+ upcase: (value) => String(value).toUpperCase(),
18
+ downcase: (value) => String(value).toLowerCase(),
19
+ capitalize: (value) => {
20
+ const str = String(value);
21
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
22
+ },
23
+ titlecase: (value) => String(value).replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.slice(1).toLowerCase()),
24
+ strip: (value) => String(value).trim(),
25
+ lstrip: (value) => String(value).trimStart(),
26
+ rstrip: (value) => String(value).trimEnd(),
27
+ truncate: (value, length = 50, ellipsis = '...') => {
28
+ const str = String(value);
29
+ if (str.length <= length)
30
+ return str;
31
+ return str.slice(0, length - ellipsis.length) + ellipsis;
32
+ },
33
+ truncatewords: (value, words = 15, ellipsis = '...') => {
34
+ const wordArray = String(value).split(/\s+/);
35
+ if (wordArray.length <= words)
36
+ return value;
37
+ return wordArray.slice(0, words).join(' ') + ellipsis;
38
+ },
39
+ append: (value, suffix) => String(value) + suffix,
40
+ prepend: (value, prefix) => prefix + String(value),
41
+ replace: (value, search, replacement = '') => String(value).replace(new RegExp(search, 'g'), replacement),
42
+ replace_first: (value, search, replacement = '') => String(value).replace(search, replacement),
43
+ remove: (value, toRemove) => String(value).replace(new RegExp(toRemove, 'g'), ''),
44
+ remove_first: (value, toRemove) => String(value).replace(toRemove, ''),
45
+ size: (value) => (Array.isArray(value) ? value.length : String(value).length),
46
+ escape: (value) => String(value)
47
+ .replace(/&/g, '&amp;')
48
+ .replace(/</g, '&lt;')
49
+ .replace(/>/g, '&gt;')
50
+ .replace(/"/g, '&quot;')
51
+ .replace(/'/g, '&#39;'),
52
+ url_encode: (value) => encodeURIComponent(String(value)),
53
+ url_decode: (value) => decodeURIComponent(String(value)),
54
+ };
55
+ // ============= Number Filters =============
56
+ const NUMBER_FILTERS = {
57
+ plus: (value, addend) => Number(value) + Number(addend),
58
+ minus: (value, subtrahend) => Number(value) - Number(subtrahend),
59
+ times: (value, multiplier) => Number(value) * Number(multiplier),
60
+ divided_by: (value, divisor) => Number(value) / Number(divisor),
61
+ modulo: (value, divisor) => Number(value) % Number(divisor),
62
+ round: (value, decimals = 0) => {
63
+ const factor = Math.pow(10, decimals);
64
+ return Math.round(Number(value) * factor) / factor;
65
+ },
66
+ floor: (value) => Math.floor(Number(value)),
67
+ ceil: (value) => Math.ceil(Number(value)),
68
+ abs: (value) => Math.abs(Number(value)),
69
+ number_with_delimiter: (value, delimiter = ',') => Number(value).toLocaleString('en-US').replace(/,/g, delimiter),
70
+ currency: (value, symbol = '$', decimals = 2) => `${symbol}${Number(value).toFixed(decimals)}`,
71
+ percentage: (value, decimals = 0) => `${(Number(value) * 100).toFixed(decimals)}%`,
72
+ at_least: (value, min) => Math.max(Number(value), Number(min)),
73
+ at_most: (value, max) => Math.min(Number(value), Number(max)),
74
+ };
75
+ // ============= Array Filters =============
76
+ const ARRAY_FILTERS = {
77
+ first: (value) => (Array.isArray(value) ? value[0] : value),
78
+ last: (value) => (Array.isArray(value) ? value[value.length - 1] : value),
79
+ join: (value, separator = ', ') => Array.isArray(value) ? value.join(separator) : String(value),
80
+ reverse: (value) => (Array.isArray(value) ? [...value].reverse() : value),
81
+ sort: (value) => (Array.isArray(value) ? [...value].sort() : value),
82
+ uniq: (value) => (Array.isArray(value) ? [...new Set(value)] : value),
83
+ compact: (value) => (Array.isArray(value) ? value.filter((v) => v != null) : value),
84
+ };
85
+ // ============= Default/Fallback Filters =============
86
+ const UTILITY_FILTERS = {
87
+ default: (value, defaultValue) => value == null || value === '' || value === false ? defaultValue : value,
88
+ default_if_none: (value, defaultValue) => (value == null ? defaultValue : value),
89
+ };
90
+ // ============= All Filters Combined =============
91
+ exports.ALL_FILTERS = {
92
+ ...STRING_FILTERS,
93
+ ...NUMBER_FILTERS,
94
+ ...ARRAY_FILTERS,
95
+ ...UTILITY_FILTERS,
96
+ date: (value, format, locale) => (0, dateFilters_1.formatDate)(value, format, locale),
97
+ date_add: (value, amount, unit) => (0, dateFilters_1.dateAdd)(value, amount, unit),
98
+ date_subtract: (value, amount, unit) => (0, dateFilters_1.dateSubtract)(value, amount, unit),
99
+ countdown_from: (endDate, startDate, format, maxUnit) => (0, dateFilters_1.countdownFrom)(endDate, startDate, format, maxUnit),
100
+ countdown_days_total: (start, end) => (0, dateFilters_1.countdownDaysTotal)(start, end),
101
+ countdown_hours_total: (start, end) => (0, dateFilters_1.countdownHoursTotal)(start, end),
102
+ countdown_minutes_total: (start, end) => (0, dateFilters_1.countdownMinutesTotal)(start, end),
103
+ countdown_seconds_total: (start, end) => (0, dateFilters_1.countdownSecondsTotal)(start, end),
104
+ to_ordinal: (value) => (0, dateFilters_1.toOrdinal)(value),
105
+ to_month_name: (value, format, locale) => (0, dateFilters_1.toMonthName)(value, format, locale),
106
+ to_day_name: (value, format, locale) => (0, dateFilters_1.toDayName)(value, format, locale),
107
+ relative_time: (value, locale) => (0, dateFilters_1.relativeTime)(value, locale),
108
+ };
109
+ // ============= Filter Argument Parser =============
110
+ function parseFilterArgs(argsString) {
111
+ if (!(argsString === null || argsString === void 0 ? void 0 : argsString.trim()))
112
+ return [];
113
+ const args = [];
114
+ let current = '';
115
+ let inQuote = false;
116
+ let quoteChar = '';
117
+ let depth = 0;
118
+ for (let i = 0; i < argsString.length; i++) {
119
+ const char = argsString[i];
120
+ if ((char === '"' || char === "'") && argsString[i - 1] !== '\\') {
121
+ if (!inQuote) {
122
+ inQuote = true;
123
+ quoteChar = char;
124
+ }
125
+ else if (char === quoteChar) {
126
+ inQuote = false;
127
+ }
128
+ current += char;
129
+ }
130
+ else if (char === '[' || char === '{') {
131
+ depth++;
132
+ current += char;
133
+ }
134
+ else if (char === ']' || char === '}') {
135
+ depth--;
136
+ current += char;
137
+ }
138
+ else if (char === ',' && !inQuote && depth === 0) {
139
+ args.push(parseArgValue(current.trim()));
140
+ current = '';
141
+ }
142
+ else {
143
+ current += char;
144
+ }
145
+ }
146
+ if (current.trim())
147
+ args.push(parseArgValue(current.trim()));
148
+ return args;
149
+ }
150
+ function parseArgValue(value) {
151
+ if ((value.startsWith('"') && value.endsWith('"')) ||
152
+ (value.startsWith("'") && value.endsWith("'"))) {
153
+ return value.slice(1, -1);
154
+ }
155
+ if (value === 'true')
156
+ return true;
157
+ if (value === 'false')
158
+ return false;
159
+ if (value === 'null' || value === 'nil')
160
+ return null;
161
+ const num = Number(value);
162
+ if (!isNaN(num) && value !== '')
163
+ return num;
164
+ try {
165
+ return JSON.parse(value);
166
+ }
167
+ catch {
168
+ return value;
169
+ }
170
+ }
171
+ function parseFilterChain(filterChain) {
172
+ const filters = [];
173
+ const parts = [];
174
+ let current = '';
175
+ let inQuote = false;
176
+ let quoteChar = '';
177
+ for (let i = 0; i < filterChain.length; i++) {
178
+ const char = filterChain[i];
179
+ if ((char === '"' || char === "'") && filterChain[i - 1] !== '\\') {
180
+ if (!inQuote) {
181
+ inQuote = true;
182
+ quoteChar = char;
183
+ }
184
+ else if (char === quoteChar) {
185
+ inQuote = false;
186
+ }
187
+ current += char;
188
+ }
189
+ else if (char === '|' && !inQuote) {
190
+ if (current.trim())
191
+ parts.push(current.trim());
192
+ current = '';
193
+ }
194
+ else {
195
+ current += char;
196
+ }
197
+ }
198
+ if (current.trim())
199
+ parts.push(current.trim());
200
+ for (const part of parts) {
201
+ const colonIndex = part.indexOf(':');
202
+ if (colonIndex === -1) {
203
+ filters.push({ name: part.trim(), args: [] });
204
+ }
205
+ else {
206
+ const name = part.slice(0, colonIndex).trim();
207
+ const argsString = part.slice(colonIndex + 1).trim();
208
+ filters.push({ name, args: parseFilterArgs(argsString) });
209
+ }
210
+ }
211
+ return filters;
212
+ }
213
+ function applyFilterChain(value, filterChain) {
214
+ const filters = parseFilterChain(filterChain);
215
+ let result = value;
216
+ for (const filter of filters) {
217
+ const filterFn = exports.ALL_FILTERS[filter.name];
218
+ if (filterFn) {
219
+ try {
220
+ result = filterFn(result, ...filter.args);
221
+ }
222
+ catch (error) {
223
+ console.warn(`Filter "${filter.name}" failed:`, error);
224
+ }
225
+ }
226
+ else {
227
+ console.warn(`Unknown filter: "${filter.name}"`);
228
+ }
229
+ }
230
+ return result;
231
+ }
232
+ /**
233
+ * Replace {{ variable }} and {{ variable | filter: arg }} occurrences in text.
234
+ * Mirror of the web replaceVariablesWithFilters — unresolved variables are
235
+ * left untouched.
236
+ */
237
+ function replaceVariablesWithFilters(text, variables) {
238
+ if (!text)
239
+ return text;
240
+ return text.replace(/\{\{\s*([\w.]+)(?:\s*\|\s*(.+?))?\s*\}\}/g, (match, varPath, filterChain) => {
241
+ let value = varPath
242
+ .split('.')
243
+ .reduce((obj, key) => obj === null || obj === void 0 ? void 0 : obj[key], variables);
244
+ if (value === undefined)
245
+ return match;
246
+ if (filterChain) {
247
+ value = applyFilterChain(value, filterChain);
248
+ }
249
+ return value !== undefined ? String(value) : match;
250
+ });
251
+ }
252
+ var dateFilters_2 = require("./dateFilters");
253
+ Object.defineProperty(exports, "DATE_FILTERS", { enumerable: true, get: function () { return dateFilters_2.DATE_FILTERS; } });
@@ -0,0 +1,76 @@
1
+ /**
2
+ * useOfferings Hook - Fetches offerings list with filtering and pagination
3
+ */
4
+ interface Package {
5
+ id: string;
6
+ package_identifier: string;
7
+ position: number;
8
+ metadata?: Record<string, any>;
9
+ product_id?: string;
10
+ product?: {
11
+ id: string;
12
+ product_identifier: string;
13
+ display_name: string;
14
+ description?: string;
15
+ type: string;
16
+ platform: string;
17
+ price_usd?: number;
18
+ currency?: string;
19
+ };
20
+ }
21
+ interface PaywallOffering {
22
+ is_primary: boolean;
23
+ paywall: {
24
+ id: string;
25
+ identifier: string;
26
+ name: string;
27
+ configuration: any;
28
+ version: number;
29
+ };
30
+ }
31
+ interface Offering {
32
+ id: string;
33
+ identifier: string;
34
+ display_name: string;
35
+ description?: string;
36
+ notes?: string;
37
+ is_current: boolean;
38
+ is_default: boolean;
39
+ metadata?: Record<string, any>;
40
+ created_at: string;
41
+ updated_at: string;
42
+ offering_packages?: Package[];
43
+ paywall_offerings?: PaywallOffering[];
44
+ }
45
+ export interface UseOfferingsOptions {
46
+ /** @deprecated Use BillDogConfiguration.configure({ apiKey }) instead */
47
+ apiKey?: string;
48
+ skipFetch?: boolean;
49
+ limit?: number;
50
+ offset?: number;
51
+ is_current?: boolean;
52
+ is_default?: boolean;
53
+ identifier?: string;
54
+ expand?: 'packages' | 'products' | 'paywall' | string;
55
+ sort_by?: 'created_at' | 'display_name' | 'identifier';
56
+ sort_order?: 'asc' | 'desc';
57
+ }
58
+ interface Pagination {
59
+ total: number;
60
+ limit: number;
61
+ offset: number;
62
+ has_more: boolean;
63
+ }
64
+ export interface UseOfferingsResult {
65
+ offerings: Offering[];
66
+ currentOffering: Offering | null;
67
+ allOfferings: Record<string, Offering> | null;
68
+ pagination: Pagination | null;
69
+ loading: boolean;
70
+ error: Error | null;
71
+ refetch: () => Promise<void>;
72
+ fetchCurrentOffering: () => Promise<Offering | null>;
73
+ fetchOfferingForPlacement: (placementIdentifier: string, userContext?: Record<string, any>) => Promise<any>;
74
+ }
75
+ export declare const useOfferings: ({ apiKey: apiKeyOverride, skipFetch, limit, offset, is_current, is_default, identifier, expand, sort_by, sort_order, }: UseOfferingsOptions) => UseOfferingsResult;
76
+ export {};
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+ /**
3
+ * useOfferings Hook - Fetches offerings list with filtering and pagination
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.useOfferings = void 0;
7
+ const react_1 = require("react");
8
+ const ApiClient_1 = require("../utils/ApiClient");
9
+ const useOfferings = ({ apiKey: apiKeyOverride, skipFetch = false, limit = 20, offset = 0, is_current, is_default, identifier, expand, sort_by = 'created_at', sort_order = 'desc', }) => {
10
+ const [offerings, setOfferings] = (0, react_1.useState)([]);
11
+ const [currentOffering, setCurrentOffering] = (0, react_1.useState)(null);
12
+ const [allOfferings, setAllOfferings] = (0, react_1.useState)(null);
13
+ const [pagination, setPagination] = (0, react_1.useState)(null);
14
+ const [loading, setLoading] = (0, react_1.useState)(false);
15
+ const [error, setError] = (0, react_1.useState)(null);
16
+ const resolvedApiKey = ApiClient_1.ApiClient.resolveApiKey(apiKeyOverride);
17
+ const deprecatedOptions = { apiKey: apiKeyOverride };
18
+ const fetchOfferings = async () => {
19
+ if (skipFetch || !resolvedApiKey) {
20
+ return;
21
+ }
22
+ setLoading(true);
23
+ setError(null);
24
+ try {
25
+ const body = {
26
+ limit,
27
+ offset,
28
+ sort_by,
29
+ sort_order,
30
+ };
31
+ if (is_current !== undefined)
32
+ body.is_current = is_current;
33
+ if (is_default !== undefined)
34
+ body.is_default = is_default;
35
+ if (identifier)
36
+ body.identifier = identifier;
37
+ if (expand)
38
+ body.expand = expand;
39
+ const json = await ApiClient_1.ApiClient.post('list-offerings', body, deprecatedOptions);
40
+ // Phase M4: Extract from wrapped envelope { success, data, meta }
41
+ const data = json.data;
42
+ setOfferings(data.offerings || []);
43
+ setCurrentOffering(data.current_offering || null);
44
+ setAllOfferings(data.all_offerings || null);
45
+ setPagination(data.pagination || null);
46
+ }
47
+ catch (err) {
48
+ setError(err instanceof Error ? err : new Error('Unknown error'));
49
+ }
50
+ finally {
51
+ setLoading(false);
52
+ }
53
+ };
54
+ (0, react_1.useEffect)(() => {
55
+ fetchOfferings();
56
+ }, [resolvedApiKey, skipFetch, limit, offset, is_current, is_default, identifier, expand, sort_by, sort_order]);
57
+ const fetchCurrentOffering = (0, react_1.useCallback)(async () => {
58
+ if (!resolvedApiKey)
59
+ return null;
60
+ try {
61
+ const json = await ApiClient_1.ApiClient.post('fetch-offering', {
62
+ is_current: true,
63
+ }, deprecatedOptions);
64
+ const data = json.data;
65
+ return data.current_offering || null;
66
+ }
67
+ catch (err) {
68
+ console.error('Error fetching current offering:', err);
69
+ return null;
70
+ }
71
+ }, [resolvedApiKey, apiKeyOverride]);
72
+ const fetchOfferingForPlacement = (0, react_1.useCallback)(async (placementIdentifier, userContext) => {
73
+ if (!resolvedApiKey)
74
+ return null;
75
+ try {
76
+ const json = await ApiClient_1.ApiClient.post('fetch-offerings-for-placement', {
77
+ placement_identifier: placementIdentifier,
78
+ ...userContext,
79
+ }, deprecatedOptions);
80
+ return json.data;
81
+ }
82
+ catch (err) {
83
+ console.error('Error fetching offering for placement:', err);
84
+ return null;
85
+ }
86
+ }, [resolvedApiKey, apiKeyOverride]);
87
+ return {
88
+ offerings,
89
+ currentOffering,
90
+ allOfferings,
91
+ pagination,
92
+ loading,
93
+ error,
94
+ refetch: fetchOfferings,
95
+ fetchCurrentOffering,
96
+ fetchOfferingForPlacement,
97
+ };
98
+ };
99
+ exports.useOfferings = useOfferings;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * usePaywall Hook - Fetches paywall configuration from API
3
+ */
4
+ import { PaywallConfiguration } from '../types';
5
+ import { AdvancedCacheConfig } from '../AdvancedPaywallCache';
6
+ export interface UsePaywallOptions {
7
+ paywallIdentifier?: string;
8
+ /** @deprecated Use BillDogConfiguration.configure({ apiKey }) instead */
9
+ apiKey?: string;
10
+ skipFetch?: boolean;
11
+ cacheConfig?: Partial<AdvancedCacheConfig>;
12
+ userContext?: {
13
+ app_user_id?: string;
14
+ country?: string;
15
+ app_version?: string;
16
+ platform?: string;
17
+ sdk_version?: string;
18
+ custom_attributes?: Record<string, string>;
19
+ };
20
+ }
21
+ export interface UsePaywallResult {
22
+ configuration: PaywallConfiguration | null;
23
+ loading: boolean;
24
+ error: Error | null;
25
+ refetch: () => Promise<void>;
26
+ }
27
+ export declare const usePaywall: ({ paywallIdentifier, apiKey: apiKeyOverride, skipFetch, cacheConfig, userContext, }: UsePaywallOptions) => UsePaywallResult;
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ /**
3
+ * usePaywall Hook - Fetches paywall configuration from API
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.usePaywall = void 0;
7
+ const react_1 = require("react");
8
+ const AdvancedPaywallCache_1 = require("../AdvancedPaywallCache");
9
+ const deviceDetection_1 = require("../utils/deviceDetection");
10
+ const configurationResolver_1 = require("../utils/configurationResolver");
11
+ const ApiClient_1 = require("../utils/ApiClient");
12
+ const usePaywall = ({ paywallIdentifier, apiKey: apiKeyOverride, skipFetch = false, cacheConfig, userContext, }) => {
13
+ const [configuration, setConfiguration] = (0, react_1.useState)(null);
14
+ const [loading, setLoading] = (0, react_1.useState)(false);
15
+ const [error, setError] = (0, react_1.useState)(null);
16
+ const [cache] = (0, react_1.useState)(() => (cacheConfig === null || cacheConfig === void 0 ? void 0 : cacheConfig.enabled) !== false ? new AdvancedPaywallCache_1.AdvancedPaywallCache(cacheConfig || {}) : null);
17
+ const resolvedApiKey = ApiClient_1.ApiClient.resolveApiKey(apiKeyOverride);
18
+ const fetchPaywall = async () => {
19
+ if (skipFetch || !paywallIdentifier || !resolvedApiKey) {
20
+ return;
21
+ }
22
+ // Try cache first if enabled
23
+ if (cache) {
24
+ const cached = await cache.get(paywallIdentifier);
25
+ if (cached && Date.now() < cached.expiresAt) {
26
+ console.log(`[usePaywall] Cache HIT for ${paywallIdentifier}`);
27
+ setConfiguration(cached.paywall.configuration);
28
+ setLoading(false);
29
+ // Check for updates in background
30
+ checkAndUpdateInBackground(paywallIdentifier, cached.version);
31
+ return;
32
+ }
33
+ }
34
+ setLoading(true);
35
+ setError(null);
36
+ try {
37
+ const json = await ApiClient_1.ApiClient.post('fetch-paywall', {
38
+ paywall_identifier: paywallIdentifier,
39
+ ...userContext,
40
+ }, {
41
+ apiKey: apiKeyOverride,
42
+ });
43
+ // Phase M4: Extract from wrapped envelope { success, data, meta }
44
+ const data = json.data;
45
+ if (data.paywall) {
46
+ // Detect device category
47
+ const deviceCategory = (0, deviceDetection_1.detectDeviceCategory)();
48
+ // Check if we have multi-config or single config
49
+ let resolvedConfig = null;
50
+ if (data.paywall.configurations) {
51
+ // Multi-config mode
52
+ const multiConfig = {
53
+ mode: data.paywall.configuration_mode || 'single',
54
+ ...data.paywall.configurations,
55
+ };
56
+ resolvedConfig = (0, configurationResolver_1.resolveConfiguration)(multiConfig, deviceCategory);
57
+ }
58
+ else if (data.paywall.configuration) {
59
+ // Single config mode (legacy)
60
+ resolvedConfig = data.paywall.configuration;
61
+ }
62
+ if (!resolvedConfig) {
63
+ throw new Error('No configuration available for current device');
64
+ }
65
+ setConfiguration(resolvedConfig);
66
+ // Cache the result
67
+ if (cache) {
68
+ await cache.set(paywallIdentifier, {
69
+ paywall: data.paywall,
70
+ version: data.paywall.version || 1,
71
+ cachedAt: Date.now(),
72
+ expiresAt: Date.now() + ((cacheConfig === null || cacheConfig === void 0 ? void 0 : cacheConfig.maxCacheAge) || 604800000),
73
+ });
74
+ }
75
+ }
76
+ else {
77
+ throw new Error('Invalid paywall data');
78
+ }
79
+ }
80
+ catch (err) {
81
+ setError(err instanceof Error ? err : new Error('Unknown error'));
82
+ }
83
+ finally {
84
+ setLoading(false);
85
+ }
86
+ };
87
+ const checkAndUpdateInBackground = async (identifier, currentVersion) => {
88
+ try {
89
+ const versionInfo = await ApiClient_1.ApiClient.post('check-paywall-version', {
90
+ paywall_identifier: identifier,
91
+ current_version: currentVersion,
92
+ }, {
93
+ apiKey: apiKeyOverride,
94
+ });
95
+ if (versionInfo.has_update) {
96
+ console.log(`[usePaywall] New version available for ${identifier}`);
97
+ await fetchPaywall();
98
+ }
99
+ }
100
+ catch (err) {
101
+ console.error('[usePaywall] Background update failed:', err);
102
+ }
103
+ };
104
+ (0, react_1.useEffect)(() => {
105
+ fetchPaywall();
106
+ }, [paywallIdentifier, resolvedApiKey, skipFetch]);
107
+ return {
108
+ configuration,
109
+ loading,
110
+ error,
111
+ refetch: fetchPaywall,
112
+ };
113
+ };
114
+ exports.usePaywall = usePaywall;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * usePlacement Hook — placement registration with a feature-callback model
3
+ * (API_Calls_Migration P4, Track D).
4
+ *
5
+ * Mirrors the iOS `register` / Android `registerFeature` feature gate:
6
+ * - **non-gated** placement → `onFeatureUnlocked` runs immediately;
7
+ * - **gated** placement → the paywall is presented (via the native bridge)
8
+ * and `onFeatureUnlocked` runs only on an entitlement-granting outcome
9
+ * (already-entitled / purchased / restored). A dismissed/errored outcome
10
+ * does NOT run it.
11
+ *
12
+ * Gating is resolved in JS through the unified `get-wall-for-placement`
13
+ * endpoint (an unknown placement is auto-created server-side — P4 hybrid
14
+ * auto-create). `usePaywall` + `useOfferings` remain the escape-hatch hooks.
15
+ */
16
+ import type { PlacementResult, PaywallPresentationHandler } from '../models/Placement';
17
+ export interface UsePlacementResult {
18
+ /**
19
+ * Result-handler variant — register a placement and get the
20
+ * `PlacementResult`. The paywall (if any) is presented via the native bridge.
21
+ */
22
+ register: (placementId: string, params?: Record<string, unknown>, handler?: PaywallPresentationHandler) => Promise<PlacementResult>;
23
+ /**
24
+ * Feature-closure variant — Superwall's `register("feature") { unlock() }`.
25
+ * Non-gated → `onFeatureUnlocked` runs immediately; gated → it runs only
26
+ * when the placement yields entitlement (entitled / purchased / restored).
27
+ */
28
+ registerFeature: (placementId: string, onFeatureUnlocked: () => void, params?: Record<string, unknown>) => Promise<PlacementResult>;
29
+ /** True while a registration is in flight. */
30
+ loading: boolean;
31
+ /** The most recent `PlacementResult`, or null. */
32
+ lastResult: PlacementResult | null;
33
+ }
34
+ export declare const usePlacement: () => UsePlacementResult;