@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,886 @@
1
+ "use strict";
2
+ /**
3
+ * Component Renderer - Maps PaywallComponent types to React Native components
4
+ * Enhanced with CSS-first rendering, gradient support, and theme-aware color resolution
5
+ * UPDATED: Comprehensive theme support and fixed stack alignment
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.ComponentRenderer = void 0;
42
+ const react_1 = __importStar(require("react"));
43
+ const react_native_1 = require("react-native");
44
+ const VariableResolver_1 = require("./VariableResolver");
45
+ const LayoutEngine_1 = require("./LayoutEngine");
46
+ const dynamicValues_1 = require("./dynamicValues");
47
+ const PaywallStateManager_1 = require("./PaywallStateManager");
48
+ const BillDog_1 = require("./BillDog");
49
+ const deviceDetection_1 = require("./utils/deviceDetection");
50
+ const CountdownComponent_1 = require("./components/CountdownComponent");
51
+ const CarouselComponent_1 = require("./components/CarouselComponent");
52
+ const AccordionComponent_1 = require("./components/AccordionComponent");
53
+ const SliderComponent_1 = require("./components/SliderComponent");
54
+ const ToggleComponent_1 = require("./components/ToggleComponent");
55
+ const CheckboxComponent_1 = require("./components/CheckboxComponent");
56
+ const SegmentedPickerComponent_1 = require("./components/SegmentedPickerComponent");
57
+ const ConfettiComponent_1 = require("./components/ConfettiComponent");
58
+ const HapticFeedbackComponent_1 = require("./components/HapticFeedbackComponent");
59
+ const DelayedXComponent_1 = require("./components/DelayedXComponent");
60
+ const ProgressLoaderComponent_1 = require("./components/ProgressLoaderComponent");
61
+ const ChartCurveComponent_1 = require("./components/ChartCurveComponent");
62
+ const SingleChoiceGridComponent_1 = require("./components/SingleChoiceGridComponent");
63
+ const MultiChoiceGridComponent_1 = require("./components/MultiChoiceGridComponent");
64
+ const DrawerModalComponent_1 = require("./components/DrawerModalComponent");
65
+ const TimelineComponent_1 = require("./components/TimelineComponent");
66
+ const TextInputComponent_1 = require("./components/TextInputComponent");
67
+ const StarRatingInputComponent_1 = require("./components/StarRatingInputComponent");
68
+ const NPSScaleComponent_1 = require("./components/NPSScaleComponent");
69
+ const OAuthButtonComponent_1 = require("./components/OAuthButtonComponent");
70
+ const ProgressStepperComponent_1 = require("./components/ProgressStepperComponent");
71
+ const ShareCodeComponent_1 = require("./components/ShareCodeComponent");
72
+ const ShareButtonsComponent_1 = require("./components/ShareButtonsComponent");
73
+ const VerticalProductsComponent_1 = require("./components/VerticalProductsComponent");
74
+ const HorizontalProductsComponent_1 = require("./components/HorizontalProductsComponent");
75
+ const AccoladeCpsComponent_1 = require("./components/AccoladeCpsComponent");
76
+ const StickerCompositeComponent_1 = require("./components/StickerCompositeComponent");
77
+ const AnimatedWrapper_1 = require("./components/AnimatedWrapper");
78
+ const NavigationComponent_1 = require("./components/NavigationComponent");
79
+ const TabsComponent_1 = require("./components/TabsComponent");
80
+ const GradientView_1 = require("./components/GradientView");
81
+ const ComponentRenderer = ({ component, configuration, theme, onButtonPress, stateManager, isPreviewMode = true, }) => {
82
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
83
+ // Process full component to evaluate dynamic values across ALL property bags.
84
+ //
85
+ // Device variables MUST be merged in. iOS (WallManager) and Android (PaywallManager) both enrich the
86
+ // bag with `buildDeviceVariables` before resolving dynamic values; React Native was the only native SDK
87
+ // that did not, so every `device.*` condition (device.osName, device.platform, …) silently resolved to
88
+ // its default here. buildDeviceVariables emits the canonical flat keys (`device.osName`) the audience
89
+ // authors target; explicit `configuration.variables` win on any collision.
90
+ // Live product selection (Phase 2b). Seeded from the store, then kept current via a
91
+ // subscription, so `products.selectedIndex` / `selectedProduct.*` conditions resolve
92
+ // against what the user actually picked instead of being pinned to the first package.
93
+ // Falls back to 0 whenever no state manager is supplied (e.g. standalone renders),
94
+ // which is exactly the previous behaviour.
95
+ const [liveSelectedIndex, setLiveSelectedIndex] = (0, react_1.useState)(0);
96
+ (0, react_1.useEffect)(() => {
97
+ var _a, _b;
98
+ if (!stateManager)
99
+ return;
100
+ const key = PaywallStateManager_1.PaywallStateManager.SELECTED_INDEX_KEY;
101
+ const initial = (_a = stateManager.getState) === null || _a === void 0 ? void 0 : _a.call(stateManager, key);
102
+ if (initial !== undefined && initial !== null)
103
+ setLiveSelectedIndex(Number(initial) || 0);
104
+ return (_b = stateManager.subscribeToState) === null || _b === void 0 ? void 0 : _b.call(stateManager, key, (value) => {
105
+ setLiveSelectedIndex(Number(value) || 0);
106
+ });
107
+ }, [stateManager]);
108
+ const [customerInfo, setCustomerInfo] = (0, react_1.useState)(() => BillDog_1.BillDog.customerInfoEmitter.latest);
109
+ (0, react_1.useEffect)(() => {
110
+ const sub = BillDog_1.BillDog.customerInfoEmitter.addListener((info) => {
111
+ setCustomerInfo(info);
112
+ });
113
+ return () => {
114
+ sub.remove();
115
+ };
116
+ }, []);
117
+ const resolvedComponent = (0, react_1.useMemo)(() => {
118
+ // Full offering-aware render bag (device + product/offer/user + user.seed/
119
+ // subscription) — parity with iOS/Android Phase 2. Was device + config.variables
120
+ // only, so every product/user DV condition silently resolved to `default`.
121
+ // appUserId + customerInfo are read here (sync) and threaded in to avoid an
122
+ // import cycle.
123
+ const bag = VariableResolver_1.VariableResolver.buildRenderVariables(configuration, (0, deviceDetection_1.getDeviceInfo)(), {
124
+ selectedIndex: liveSelectedIndex,
125
+ appUserId: BillDog_1.BillDog.getAppUserId(),
126
+ customerInfo: customerInfo,
127
+ });
128
+ const allVariables = { ...bag, ...(configuration.variables || {}) };
129
+ return (0, dynamicValues_1.processFullComponent)(component, allVariables);
130
+ }, [component, configuration.variables, configuration.packages, liveSelectedIndex, customerInfo]);
131
+ // Create a VariableResolver with full localization support (must be before early returns)
132
+ const variableResolver = (0, react_1.useMemo)(() => {
133
+ return VariableResolver_1.VariableResolver.withLocalization(configuration);
134
+ }, [configuration]);
135
+ // Resolve variables in text using the full resolver (must be before early returns)
136
+ const resolveVariable = (0, react_1.useCallback)((text) => {
137
+ if (!text)
138
+ return '';
139
+ return variableResolver.resolve(text);
140
+ }, [variableResolver]);
141
+ const processedProperties = resolvedComponent.properties || {};
142
+ // Don't render if not visible (resolved from dynamic values)
143
+ if (resolvedComponent.visible === false || processedProperties.visible === false) {
144
+ return null;
145
+ }
146
+ // Get combined style with absolute position support and custom CSS
147
+ const style = LayoutEngine_1.LayoutEngine.getComponentStyle(resolvedComponent.layout, resolvedComponent.appearance, resolvedComponent.size, resolvedComponent.type, processedProperties, resolvedComponent.absolutePosition, resolvedComponent.zIndex, processedProperties.customCSS);
148
+ /**
149
+ * Theme-aware color resolution
150
+ * Resolves CSS variables and color objects using the provided theme
151
+ */
152
+ const resolveColor = (color, fallback) => {
153
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
154
+ if (!color)
155
+ return fallback || 'transparent';
156
+ if (typeof color === 'string') {
157
+ // Handle CSS variable references
158
+ if (color.includes('var(--')) {
159
+ return resolveCSSVariable(color) || fallback || 'transparent';
160
+ }
161
+ return color;
162
+ }
163
+ // Handle object format
164
+ if (typeof color === 'object') {
165
+ // Check for resolvedColor first (pre-computed by web builder)
166
+ if (color.resolvedColor) {
167
+ return resolveColor(color.resolvedColor, fallback);
168
+ }
169
+ if (color.type === 'color' && color.color) {
170
+ return resolveColor(color.color, fallback);
171
+ }
172
+ if (color.type === 'gradient' && ((_b = (_a = color.gradient) === null || _a === void 0 ? void 0 : _a.stops) === null || _b === void 0 ? void 0 : _b.length)) {
173
+ const firstStop = color.gradient.stops[0];
174
+ if (firstStop === null || firstStop === void 0 ? void 0 : firstStop.color) {
175
+ return resolveColor(firstStop.color, fallback);
176
+ }
177
+ }
178
+ // HSL format
179
+ if (color.type === 'hsl' || (color.h !== undefined && color.s !== undefined && color.l !== undefined)) {
180
+ const h = (_c = color.h) !== null && _c !== void 0 ? _c : 0;
181
+ const s = (_d = color.s) !== null && _d !== void 0 ? _d : 0;
182
+ const l = (_e = color.l) !== null && _e !== void 0 ? _e : 0;
183
+ const a = (_g = (_f = color.a) !== null && _f !== void 0 ? _f : color.opacity) !== null && _g !== void 0 ? _g : 1;
184
+ if (a < 1) {
185
+ return `hsla(${h}, ${s}%, ${l}%, ${a})`;
186
+ }
187
+ return `hsl(${h}, ${s}%, ${l}%)`;
188
+ }
189
+ // RGBA format
190
+ if (color.type === 'rgba' || (color.r !== undefined && color.g !== undefined && color.b !== undefined)) {
191
+ const r = (_h = color.r) !== null && _h !== void 0 ? _h : 0;
192
+ const g = (_j = color.g) !== null && _j !== void 0 ? _j : 0;
193
+ const b = (_k = color.b) !== null && _k !== void 0 ? _k : 0;
194
+ const a = (_m = (_l = color.a) !== null && _l !== void 0 ? _l : color.opacity) !== null && _m !== void 0 ? _m : 1;
195
+ return `rgba(${r}, ${g}, ${b}, ${a})`;
196
+ }
197
+ if (color.hex)
198
+ return color.hex;
199
+ if (color.value)
200
+ return color.value;
201
+ if (color.color && typeof color.color === 'string')
202
+ return color.color;
203
+ }
204
+ return fallback || 'transparent';
205
+ };
206
+ /**
207
+ * Resolve CSS variable to actual color value using theme
208
+ * UPDATED: Handle themingMode disabled
209
+ */
210
+ const resolveCSSVariable = (cssVar) => {
211
+ var _a;
212
+ const varMatch = cssVar.match(/var\(--([a-zA-Z-]+)\)/);
213
+ if (!varMatch)
214
+ return cssVar;
215
+ const varName = varMatch[1];
216
+ // Extract opacity if present
217
+ const opacityMatch = cssVar.match(/\/\s*([\d.]+)\s*\)?$/);
218
+ const opacity = opacityMatch ? parseFloat(opacityMatch[1]) : 1;
219
+ // If theming is disabled, use default colors only
220
+ if ((theme === null || theme === void 0 ? void 0 : theme.themingMode) === 'disabled') {
221
+ const defaultColor = LayoutEngine_1.ThemeColorResolver.getDefaultVariableColor(varName);
222
+ return opacity < 1 ? applyOpacity(defaultColor, opacity) : defaultColor;
223
+ }
224
+ // First try theme's resolvedColors (direct lookup)
225
+ if ((_a = theme === null || theme === void 0 ? void 0 : theme.resolvedColors) === null || _a === void 0 ? void 0 : _a[varName]) {
226
+ const color = parseHexColor(theme.resolvedColors[varName]);
227
+ return opacity < 1 ? applyOpacity(color, opacity) : color;
228
+ }
229
+ // Then try ThemeColorResolver (which was initialized with theme)
230
+ const resolved = LayoutEngine_1.ThemeColorResolver.resolveVariable(varName);
231
+ if (resolved) {
232
+ const parsedResolved = parseHexColor(resolved);
233
+ return opacity < 1 ? applyOpacity(parsedResolved, opacity) : parsedResolved;
234
+ }
235
+ // Fallback to defaults
236
+ const defaultColor = LayoutEngine_1.ThemeColorResolver.getDefaultVariableColor(varName);
237
+ return opacity < 1 ? applyOpacity(defaultColor, opacity) : defaultColor;
238
+ };
239
+ /**
240
+ * Parse 8-character hex colors (#AARRGGBB format) to rgba
241
+ */
242
+ const parseHexColor = (hex) => {
243
+ if (!hex || typeof hex !== 'string')
244
+ return hex;
245
+ // Handle 8-character hex with alpha prefix (#AARRGGBB format)
246
+ if (hex.length === 9 && hex.startsWith('#')) {
247
+ const alpha = parseInt(hex.substring(1, 3), 16) / 255;
248
+ const r = parseInt(hex.substring(3, 5), 16);
249
+ const g = parseInt(hex.substring(5, 7), 16);
250
+ const b = parseInt(hex.substring(7, 9), 16);
251
+ return `rgba(${r}, ${g}, ${b}, ${alpha.toFixed(2)})`;
252
+ }
253
+ return hex;
254
+ };
255
+ /**
256
+ * Apply opacity to a color
257
+ */
258
+ const applyOpacity = (color, opacity) => {
259
+ if (color.startsWith('#')) {
260
+ const cleanHex = color.replace('#', '');
261
+ if (cleanHex.length >= 6) {
262
+ const r = parseInt(cleanHex.substring(0, 2), 16);
263
+ const g = parseInt(cleanHex.substring(2, 4), 16);
264
+ const b = parseInt(cleanHex.substring(4, 6), 16);
265
+ return `rgba(${r}, ${g}, ${b}, ${opacity})`;
266
+ }
267
+ }
268
+ if (color.startsWith('hsl(')) {
269
+ const match = color.match(/hsl\(\s*([\d.]+)\s*,?\s*([\d.]+)%?\s*,?\s*([\d.]+)%?\s*\)/);
270
+ if (match) {
271
+ return `hsla(${match[1]}, ${match[2]}%, ${match[3]}%, ${opacity})`;
272
+ }
273
+ }
274
+ return color;
275
+ };
276
+ /**
277
+ * Universal children rendering function for composite components
278
+ * Renders children in a stack layout (horizontal, vertical, or layered)
279
+ */
280
+ const renderWithChildren = (component) => {
281
+ var _a;
282
+ if (!((_a = component.children) === null || _a === void 0 ? void 0 : _a.length)) {
283
+ return <react_native_1.View />;
284
+ }
285
+ // Build container style from component's containerLayout - uses canonical 'direction'
286
+ const containerLayout = component.containerLayout || { direction: 'vertical' };
287
+ const containerStyle = {
288
+ flexDirection: containerLayout.direction === 'horizontal' ? 'row' : 'column',
289
+ };
290
+ // Add gap (React Native doesn't support gap directly, use margin on children)
291
+ if (containerLayout.gap) {
292
+ // Will need to add margin to children instead
293
+ }
294
+ // Add alignment
295
+ if (containerLayout.verticalAlignment) {
296
+ containerStyle.alignItems = containerLayout.verticalAlignment === 'center' ? 'center'
297
+ : containerLayout.verticalAlignment === 'end' ? 'flex-end'
298
+ : 'flex-start';
299
+ }
300
+ if (containerLayout.horizontalAlignment) {
301
+ containerStyle.justifyContent = containerLayout.horizontalAlignment === 'center' ? 'center'
302
+ : containerLayout.horizontalAlignment === 'end' ? 'flex-end'
303
+ : containerLayout.horizontalAlignment === 'space-between' ? 'space-between'
304
+ : 'flex-start';
305
+ }
306
+ return (<react_native_1.View style={[containerStyle, style]}>
307
+ {component.children.map((child) => (<exports.ComponentRenderer key={child.id} component={child} configuration={configuration} theme={theme} onButtonPress={onButtonPress} stateManager={stateManager} isPreviewMode={isPreviewMode}/>))}
308
+ </react_native_1.View>);
309
+ };
310
+ // Render child component helper for accordion etc.
311
+ const renderChild = (child) => (<exports.ComponentRenderer key={child.id} component={child} configuration={configuration} theme={theme} onButtonPress={onButtonPress} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
312
+ // Animation wrapper helper
313
+ const wrapWithAnimation = (content) => {
314
+ const animationMode = processedProperties.animationMode;
315
+ const animationPreset = processedProperties.animationPreset;
316
+ if (animationMode === 'none' || !animationPreset) {
317
+ return content;
318
+ }
319
+ return (<AnimatedWrapper_1.AnimatedWrapper preset={animationPreset} trigger={animationMode === 'loop' ? 'loop' : 'enter'} duration={processedProperties.animationDuration} delay={processedProperties.animationDelay} easing={processedProperties.animationEasing}>
320
+ {content}
321
+ </AnimatedWrapper_1.AnimatedWrapper>);
322
+ };
323
+ /**
324
+ * Helper to map alignment strings to flex values
325
+ * FIXED: Proper mapping for both axes
326
+ */
327
+ const mapAlignment = (align) => {
328
+ switch (align) {
329
+ case 'start': return 'flex-start';
330
+ case 'center': return 'center';
331
+ case 'end': return 'flex-end';
332
+ case 'stretch': return 'stretch';
333
+ case 'space-between': return 'space-between';
334
+ default: return 'flex-start';
335
+ }
336
+ };
337
+ // Helper to get gap value from containerLayout
338
+ const getGapValue = (gap) => {
339
+ if (typeof gap === 'number')
340
+ return gap;
341
+ if (gap && typeof gap === 'object' && 'value' in gap)
342
+ return gap.value;
343
+ return 8;
344
+ };
345
+ // Helper to parse color values (HSL, hex, rgba, gradient, or object format)
346
+ const parseColorValue = (color) => {
347
+ return resolveColor(color, 'transparent');
348
+ };
349
+ // Helper to parse size values (number or { value, unit } format)
350
+ const parseSizeValue = (size) => {
351
+ if (typeof size === 'number')
352
+ return size;
353
+ if (size && typeof size === 'object' && 'value' in size)
354
+ return size.value;
355
+ return undefined;
356
+ };
357
+ // Helper to extract gradient config from backgroundColor
358
+ const extractGradientConfig = (backgroundColor) => {
359
+ if (!backgroundColor || typeof backgroundColor !== 'object')
360
+ return null;
361
+ if (backgroundColor.type === 'gradient' && backgroundColor.gradient) {
362
+ const gradient = backgroundColor.gradient;
363
+ return {
364
+ type: gradient.type || 'linear',
365
+ angle: gradient.angle,
366
+ stops: (gradient.stops || []).map((stop) => {
367
+ const rawPos = stop.position !== undefined ? stop.position : stop.offset;
368
+ let posD = 0;
369
+ if (typeof rawPos === 'number') {
370
+ posD = rawPos;
371
+ }
372
+ else if (typeof rawPos === 'string') {
373
+ const trimmed = rawPos.trim();
374
+ if (trimmed.endsWith('%')) {
375
+ const val = parseFloat(trimmed.slice(0, -1));
376
+ posD = isNaN(val) ? 0 : val / 100;
377
+ }
378
+ else {
379
+ const val = parseFloat(trimmed);
380
+ posD = isNaN(val) ? 0 : val;
381
+ }
382
+ }
383
+ const position = posD <= 1 ? posD : posD / 100;
384
+ return {
385
+ color: parseColorValue(stop.color),
386
+ position,
387
+ };
388
+ }),
389
+ };
390
+ }
391
+ return null;
392
+ };
393
+ /**
394
+ * Get text color from properties or theme
395
+ * Falls back to theme's text color if not specified
396
+ */
397
+ const getTextColor = () => {
398
+ var _a;
399
+ // Check component properties first
400
+ if (processedProperties.color) {
401
+ return resolveColor(processedProperties.color);
402
+ }
403
+ if (processedProperties.textColor) {
404
+ return resolveColor(processedProperties.textColor);
405
+ }
406
+ // Fall back to theme text color
407
+ if (theme === null || theme === void 0 ? void 0 : theme.textColor) {
408
+ return theme.textColor;
409
+ }
410
+ if ((_a = theme === null || theme === void 0 ? void 0 : theme.resolvedColors) === null || _a === void 0 ? void 0 : _a.foreground) {
411
+ return theme.resolvedColors.foreground;
412
+ }
413
+ // Default fallback
414
+ return '#1A1A2E';
415
+ };
416
+ // Render based on component type
417
+ switch (component.type) {
418
+ case 'text':
419
+ const textColor = getTextColor();
420
+ return (<react_native_1.Text style={[styles.text, style, { color: textColor }]}>
421
+ {resolveVariable(processedProperties.text || '')}
422
+ </react_native_1.Text>);
423
+ case 'image': {
424
+ const imgUrl = processedProperties.imageUrl
425
+ || processedProperties.src
426
+ || processedProperties.source
427
+ || '';
428
+ const imgObjectFit = processedProperties.objectFit || 'cover';
429
+ const imgAlt = processedProperties.altText || processedProperties.alt || '';
430
+ if (imgUrl) {
431
+ return (<react_native_1.Image source={{ uri: imgUrl }}
432
+ // `style` is a shared ViewStyle whose `overflow: 'scroll'` is not valid
433
+ // for ImageStyle; cast to ImageStyle (RN ignores the extra value).
434
+ style={[styles.image, style]} resizeMode={imgObjectFit} accessibilityLabel={imgAlt}/>);
435
+ }
436
+ return (<react_native_1.View style={[styles.mediaPlaceholder, style]}>
437
+ <react_native_1.Text style={styles.placeholderIcon}>🖼</react_native_1.Text>
438
+ <react_native_1.Text style={styles.placeholderText}>No image</react_native_1.Text>
439
+ </react_native_1.View>);
440
+ }
441
+ case 'stack': {
442
+ // Enhanced stack rendering with containerLayout support
443
+ // Uses canonical 'direction' property
444
+ const containerLayout = component.containerLayout || {};
445
+ const direction = containerLayout.direction || 'vertical';
446
+ const gap = getGapValue(containerLayout.gap);
447
+ const isHorizontal = direction === 'horizontal';
448
+ // Layered mode (similar to CSS Grid stacking)
449
+ if (direction === 'layered') {
450
+ return (<react_native_1.View style={[style, { position: 'relative' }]}>
451
+ {(_a = component.children) === null || _a === void 0 ? void 0 : _a.map((child, index) => {
452
+ var _a, _b;
453
+ // Size-based inference: fill+fill = non-measuring background layer
454
+ const childSize = child.size;
455
+ const isBackground = ((_a = childSize === null || childSize === void 0 ? void 0 : childSize.width) === null || _a === void 0 ? void 0 : _a.type) === 'fill' && ((_b = childSize === null || childSize === void 0 ? void 0 : childSize.height) === null || _b === void 0 ? void 0 : _b.type) === 'fill';
456
+ return (<react_native_1.View key={child.id}
457
+ // mapAlignment can yield 'space-between' which is valid for
458
+ // justifyContent but not the narrower alignItems FlexAlignType;
459
+ // cast to ViewStyle (RN ignores an out-of-range alignItems).
460
+ style={{
461
+ position: isBackground ? 'absolute' : 'relative',
462
+ top: isBackground ? 0 : undefined,
463
+ left: isBackground ? 0 : undefined,
464
+ right: isBackground ? 0 : undefined,
465
+ bottom: isBackground ? 0 : undefined,
466
+ zIndex: isBackground ? 0 : index + 1,
467
+ alignItems: mapAlignment(containerLayout.horizontalAlignment),
468
+ justifyContent: mapAlignment(containerLayout.verticalAlignment),
469
+ }}>
470
+ <exports.ComponentRenderer key={child.id} component={child} configuration={configuration} theme={theme} onButtonPress={onButtonPress} stateManager={stateManager} isPreviewMode={isPreviewMode}/>
471
+ </react_native_1.View>);
472
+ })}
473
+ </react_native_1.View>);
474
+ }
475
+ /**
476
+ * Direction-aware alignment mapping
477
+ * For horizontal direction (row):
478
+ * - horizontalAlignment controls justifyContent (main axis)
479
+ * - verticalAlignment controls alignItems (cross axis)
480
+ * For vertical direction (column):
481
+ * - verticalAlignment controls justifyContent (main axis)
482
+ * - horizontalAlignment controls alignItems (cross axis)
483
+ */
484
+ const justifyContent = isHorizontal
485
+ ? mapAlignment(containerLayout.horizontalAlignment)
486
+ : mapAlignment(containerLayout.verticalAlignment);
487
+ const alignItems = isHorizontal
488
+ ? mapAlignment(containerLayout.verticalAlignment)
489
+ : mapAlignment(containerLayout.horizontalAlignment);
490
+ return (<react_native_1.View style={[styles.stack, style, {
491
+ flexDirection: isHorizontal ? 'row' : 'column',
492
+ gap: gap,
493
+ // justifyContent/alignItems come from mapAlignment whose 'stretch' value
494
+ // is valid for alignItems but not justifyContent; cast (RN ignores it).
495
+ justifyContent,
496
+ alignItems,
497
+ }]}>
498
+ {(_b = component.children) === null || _b === void 0 ? void 0 : _b.map((child) => (<exports.ComponentRenderer key={child.id} component={child} configuration={configuration} theme={theme} onButtonPress={onButtonPress} stateManager={stateManager} isPreviewMode={isPreviewMode}/>))}
499
+ </react_native_1.View>);
500
+ }
501
+ case 'divider':
502
+ // Use theme border color for divider
503
+ const dividerColor = resolveColor((_c = resolvedComponent.appearance) === null || _c === void 0 ? void 0 : _c.backgroundColor, (theme === null || theme === void 0 ? void 0 : theme.borderColor) || ((_d = theme === null || theme === void 0 ? void 0 : theme.resolvedColors) === null || _d === void 0 ? void 0 : _d.border) || '#E5E7EB');
504
+ return (<react_native_1.View style={[
505
+ styles.divider,
506
+ style,
507
+ {
508
+ backgroundColor: dividerColor,
509
+ height: processedProperties.orientation === 'vertical' ? '100%' : 1,
510
+ width: processedProperties.orientation === 'vertical' ? 1 : '100%',
511
+ },
512
+ ]}/>);
513
+ case 'spacer':
514
+ return (<react_native_1.View style={[
515
+ style,
516
+ {
517
+ width: processedProperties.size || 16,
518
+ height: processedProperties.size || 16,
519
+ },
520
+ ]}/>);
521
+ // Interactive components (keep dedicated handlers)
522
+ case 'checkbox':
523
+ return (<CheckboxComponent_1.CheckboxComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
524
+ case 'toggle':
525
+ return (<ToggleComponent_1.ToggleComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
526
+ case 'segmented-picker':
527
+ return (<SegmentedPickerComponent_1.SegmentedPickerComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
528
+ case 'price':
529
+ const priceColor = getTextColor();
530
+ return (<react_native_1.View style={[styles.priceContainer, style]}>
531
+ <react_native_1.Text style={[styles.priceText, { color: priceColor }]}>
532
+ {processedProperties.currency || '$'}
533
+ {processedProperties.amount || '0.00'}
534
+ </react_native_1.Text>
535
+ {processedProperties.period && (<react_native_1.Text style={[styles.pricePeriod, { color: applyOpacity(priceColor, 0.6) }]}>
536
+ /{processedProperties.period}
537
+ </react_native_1.Text>)}
538
+ </react_native_1.View>);
539
+ case 'countdown':
540
+ return (<CountdownComponent_1.CountdownComponent component={resolvedComponent} configuration={configuration} style={style}/>);
541
+ case 'carousel':
542
+ return (<CarouselComponent_1.CarouselComponent component={resolvedComponent} configuration={configuration} style={style} onButtonPress={onButtonPress} stateManager={stateManager}/>);
543
+ case 'accordion':
544
+ return (<AccordionComponent_1.AccordionComponent component={resolvedComponent} renderChild={renderChild} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
545
+ case 'slider':
546
+ return (<SliderComponent_1.SliderComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
547
+ case 'tabs':
548
+ return (<TabsComponent_1.TabsComponent component={resolvedComponent} children={component.children || []} renderChild={renderChild} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
549
+ case 'navigation':
550
+ return (<NavigationComponent_1.NavigationComponent component={resolvedComponent} children={component.children || []} renderChild={renderChild} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
551
+ case 'confetti':
552
+ return (<ConfettiComponent_1.ConfettiComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
553
+ case 'delayed-x':
554
+ return (<DelayedXComponent_1.DelayedXComponent component={resolvedComponent} configuration={configuration} renderChild={renderChild} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
555
+ case 'haptic-feedback':
556
+ return (<HapticFeedbackComponent_1.HapticFeedbackComponent component={resolvedComponent} isPreviewMode={isPreviewMode}/>);
557
+ case 'button': {
558
+ // Theme-aware button rendering
559
+ const buttonBgColor = resolveColor((_e = resolvedComponent.appearance) === null || _e === void 0 ? void 0 : _e.backgroundColor, (theme === null || theme === void 0 ? void 0 : theme.primaryColor) || ((_f = theme === null || theme === void 0 ? void 0 : theme.resolvedColors) === null || _f === void 0 ? void 0 : _f.primary) || '#007AFF');
560
+ const buttonTextColor = processedProperties.textColor
561
+ ? resolveColor(processedProperties.textColor)
562
+ : '#FFFFFF';
563
+ return (<react_native_1.TouchableOpacity style={[styles.button, style, { backgroundColor: buttonBgColor }]} onPress={() => onButtonPress === null || onButtonPress === void 0 ? void 0 : onButtonPress(component.id, processedProperties.action || 'tap')}>
564
+ <react_native_1.Text style={[styles.buttonText, { color: buttonTextColor }]}>
565
+ {resolveVariable(processedProperties.text || processedProperties.label || 'Button')}
566
+ </react_native_1.Text>
567
+ </react_native_1.TouchableOpacity>);
568
+ }
569
+ case 'badge': {
570
+ const badgeBgColor = resolveColor((_g = resolvedComponent.appearance) === null || _g === void 0 ? void 0 : _g.backgroundColor, (theme === null || theme === void 0 ? void 0 : theme.primaryColor) || '#FF3B30');
571
+ const badgeTextColor = processedProperties.textColor
572
+ ? resolveColor(processedProperties.textColor)
573
+ : '#FFFFFF';
574
+ return (<react_native_1.View style={[styles.badge, style, { backgroundColor: badgeBgColor }]}>
575
+ <react_native_1.Text style={[styles.badgeText, { color: badgeTextColor }]}>
576
+ {resolveVariable(processedProperties.text || '')}
577
+ </react_native_1.Text>
578
+ </react_native_1.View>);
579
+ }
580
+ case 'feature-list': {
581
+ const features = processedProperties.features || [];
582
+ const checkColor = (theme === null || theme === void 0 ? void 0 : theme.primaryColor) || ((_h = theme === null || theme === void 0 ? void 0 : theme.resolvedColors) === null || _h === void 0 ? void 0 : _h.primary) || '#34C759';
583
+ const textColor = getTextColor();
584
+ return (<react_native_1.View style={[styles.featureList, style]}>
585
+ {features.map((feature, index) => (<react_native_1.View key={index} style={styles.featureItem}>
586
+ <react_native_1.Text style={[styles.featureIcon, { color: checkColor }]}>✓</react_native_1.Text>
587
+ <react_native_1.Text style={[styles.featureText, { color: textColor }]}>
588
+ {resolveVariable(feature)}
589
+ </react_native_1.Text>
590
+ </react_native_1.View>))}
591
+ </react_native_1.View>);
592
+ }
593
+ case 'shape': {
594
+ // Render shape primitives (rectangles, circles, etc.)
595
+ const shapeType = processedProperties.shapeType || 'rectangle';
596
+ const cornerRadius = ((_j = resolvedComponent.appearance) === null || _j === void 0 ? void 0 : _j.cornerRadius) || 0;
597
+ const backgroundColor = (_k = resolvedComponent.appearance) === null || _k === void 0 ? void 0 : _k.backgroundColor;
598
+ const borderWidth = ((_l = resolvedComponent.appearance) === null || _l === void 0 ? void 0 : _l.borderWidth) || 0;
599
+ const borderColor = (_m = resolvedComponent.appearance) === null || _m === void 0 ? void 0 : _m.borderColor;
600
+ // backgroundColor may be a plain color string or a structured object;
601
+ // only the object branch carries an opacity field.
602
+ const opacity = (_o = (typeof backgroundColor === 'object' ? backgroundColor === null || backgroundColor === void 0 ? void 0 : backgroundColor.opacity : undefined)) !== null && _o !== void 0 ? _o : 1;
603
+ // Check for gradient background
604
+ const gradientConfig = extractGradientConfig(backgroundColor);
605
+ const effectiveBorderRadius = shapeType === 'circle' ? 9999 : cornerRadius;
606
+ // If gradient is detected and supported, use GradientView
607
+ if (gradientConfig && (0, GradientView_1.isGradientSupported)()) {
608
+ return (<GradientView_1.GradientView gradient={gradientConfig} fallbackColor={parseColorValue(backgroundColor)} style={[style, { opacity }]} borderRadius={effectiveBorderRadius} borderWidth={borderWidth} borderColor={parseColorValue(borderColor)}/>);
609
+ }
610
+ // Fallback to solid color (uses first stop color for gradients)
611
+ const bgColor = parseColorValue(backgroundColor);
612
+ return (<react_native_1.View style={[
613
+ style,
614
+ {
615
+ backgroundColor: bgColor,
616
+ borderRadius: effectiveBorderRadius,
617
+ borderWidth,
618
+ borderColor: parseColorValue(borderColor),
619
+ opacity,
620
+ }
621
+ ]}/>);
622
+ }
623
+ case 'icon': {
624
+ // Render icon primitives using Lucide icons (same as web editor)
625
+ const rawIcon = processedProperties.iconName;
626
+ let iconName = 'Circle';
627
+ const { Platform } = require('react-native');
628
+ if (rawIcon && typeof rawIcon === 'object' && 'iconName' in rawIcon) {
629
+ if (Platform.OS === 'ios' && rawIcon.iconNameIos) {
630
+ iconName = rawIcon.iconNameIos;
631
+ }
632
+ else if (Platform.OS === 'android' && rawIcon.iconNameAndroid) {
633
+ iconName = rawIcon.iconNameAndroid;
634
+ }
635
+ else {
636
+ iconName = rawIcon.iconName || 'Circle';
637
+ }
638
+ }
639
+ else if (typeof rawIcon === 'string') {
640
+ if (Platform.OS === 'ios' && processedProperties.iconNameIos) {
641
+ iconName = processedProperties.iconNameIos;
642
+ }
643
+ else if (Platform.OS === 'android' && processedProperties.iconNameAndroid) {
644
+ iconName = processedProperties.iconNameAndroid;
645
+ }
646
+ else {
647
+ iconName = rawIcon;
648
+ }
649
+ }
650
+ else {
651
+ iconName = processedProperties.name || 'Circle';
652
+ }
653
+ const iconSize = parseSizeValue(processedProperties.iconSize) || parseSizeValue(processedProperties.size) || 24;
654
+ const iconColor = resolveColor(processedProperties.iconColor || processedProperties.color, getTextColor());
655
+ const strokeWidth = typeof processedProperties.strokeWidth === 'number'
656
+ ? processedProperties.strokeWidth
657
+ : 2;
658
+ // Use getLucideIcon for SVG icon parity with web editor
659
+ const { getLucideIcon } = require('./utils/iconMapper');
660
+ const { component: IconComp, fallback } = getLucideIcon(iconName);
661
+ if (IconComp) {
662
+ return (<react_native_1.View style={[style, { alignItems: 'center', justifyContent: 'center' }]}>
663
+ <IconComp size={iconSize} color={iconColor} strokeWidth={strokeWidth}/>
664
+ </react_native_1.View>);
665
+ }
666
+ // Emoji fallback for unmapped icons
667
+ const fallbackEmoji = {
668
+ 'check': '✓', 'x': '✕', 'plus': '+', 'minus': '−',
669
+ 'star': '☆', 'heart': '♡', 'circle': '○',
670
+ };
671
+ const emojiChar = fallbackEmoji[iconName.toLowerCase()] || '○';
672
+ return (<react_native_1.View style={[style, { width: iconSize, height: iconSize, alignItems: 'center', justifyContent: 'center' }]}>
673
+ <react_native_1.Text style={{ fontSize: iconSize * 0.8, color: iconColor, lineHeight: iconSize }}>
674
+ {emojiChar}
675
+ </react_native_1.Text>
676
+ </react_native_1.View>);
677
+ }
678
+ case 'webp':
679
+ case 'gif': {
680
+ // Render animated/static images — same property chain as 'image'
681
+ const mediaUrl = processedProperties.imageUrl
682
+ || processedProperties.src
683
+ || processedProperties.source
684
+ || '';
685
+ const mediaObjectFit = processedProperties.objectFit || 'cover';
686
+ const mediaAlt = processedProperties.altText || processedProperties.alt || '';
687
+ return mediaUrl ? (<react_native_1.Image source={{ uri: mediaUrl }}
688
+ // See note above: cast shared ViewStyle to ImageStyle for Image.
689
+ style={[styles.image, style]} resizeMode={mediaObjectFit} accessibilityLabel={mediaAlt}/>) : (<react_native_1.View style={[styles.mediaPlaceholder, style]}>
690
+ <react_native_1.Text style={styles.placeholderIcon}>🖼</react_native_1.Text>
691
+ <react_native_1.Text style={styles.placeholderText}>{component.type.toUpperCase()}</react_native_1.Text>
692
+ </react_native_1.View>);
693
+ }
694
+ case 'video': {
695
+ // Video placeholder - in production, use expo-av or react-native-video
696
+ return (<react_native_1.View style={[styles.mediaPlaceholder, style]}>
697
+ <react_native_1.Text style={styles.placeholderIcon}>🎬</react_native_1.Text>
698
+ <react_native_1.Text style={styles.placeholderText}>Video</react_native_1.Text>
699
+ {processedProperties.source && (<react_native_1.Text style={styles.placeholderHint}>Source: {processedProperties.source}</react_native_1.Text>)}
700
+ </react_native_1.View>);
701
+ }
702
+ case 'lottie': {
703
+ // Lottie animation placeholder - in production, use lottie-react-native
704
+ return (<react_native_1.View style={[styles.mediaPlaceholder, style]}>
705
+ <react_native_1.Text style={styles.placeholderIcon}>✨</react_native_1.Text>
706
+ <react_native_1.Text style={styles.placeholderText}>Lottie Animation</react_native_1.Text>
707
+ {processedProperties.source && (<react_native_1.Text style={styles.placeholderHint}>Source: {processedProperties.source}</react_native_1.Text>)}
708
+ </react_native_1.View>);
709
+ }
710
+ case 'progress-loader':
711
+ return (<ProgressLoaderComponent_1.ProgressLoaderComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
712
+ case 'chart-curve':
713
+ return (<ChartCurveComponent_1.ChartCurveComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
714
+ case 'single-choice-grid':
715
+ return (<SingleChoiceGridComponent_1.SingleChoiceGridComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
716
+ case 'multi-choice-grid':
717
+ return (<MultiChoiceGridComponent_1.MultiChoiceGridComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
718
+ case 'drawer-modal':
719
+ return (<DrawerModalComponent_1.DrawerModalComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode} renderComponent={renderChild}/>);
720
+ case 'timeline':
721
+ return (<TimelineComponent_1.TimelineComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode} renderComponent={renderChild}/>);
722
+ case 'text-input':
723
+ return (<TextInputComponent_1.TextInputComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
724
+ case 'star-rating-input':
725
+ return (<StarRatingInputComponent_1.StarRatingInputComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
726
+ case 'nps-scale':
727
+ return (<NPSScaleComponent_1.NPSScaleComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
728
+ case 'oauth-button':
729
+ return (<OAuthButtonComponent_1.OAuthButtonComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
730
+ case 'progress-stepper':
731
+ return (<ProgressStepperComponent_1.ProgressStepperComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
732
+ case 'share-code':
733
+ return (<ShareCodeComponent_1.ShareCodeComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
734
+ case 'share-buttons':
735
+ return (<ShareButtonsComponent_1.ShareButtonsComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode} renderChild={(child, index) => (<exports.ComponentRenderer key={child.id} component={child} configuration={configuration} theme={theme} onButtonPress={onButtonPress} stateManager={stateManager} isPreviewMode={isPreviewMode}/>)}/>);
736
+ case 'vertical-products':
737
+ return (<VerticalProductsComponent_1.VerticalProductsComponent component={resolvedComponent} configuration={configuration} renderChild={(child) => (<exports.ComponentRenderer key={child.id} component={child} configuration={configuration} theme={theme} onButtonPress={onButtonPress} stateManager={stateManager} isPreviewMode={isPreviewMode}/>)} stateManager={stateManager} onAction={onButtonPress}/>);
738
+ case 'horizontal-products':
739
+ return (<HorizontalProductsComponent_1.HorizontalProductsComponent component={resolvedComponent} configuration={configuration} renderChild={(child) => (<exports.ComponentRenderer key={child.id} component={child} configuration={configuration} theme={theme} onButtonPress={onButtonPress} stateManager={stateManager} isPreviewMode={isPreviewMode}/>)} stateManager={stateManager} onAction={onButtonPress}/>);
740
+ case 'accolade-cps':
741
+ return (<AccoladeCpsComponent_1.AccoladeCpsComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
742
+ case 'sticker-composite':
743
+ return (<StickerCompositeComponent_1.StickerCompositeComponent component={resolvedComponent} stateManager={stateManager} isPreviewMode={isPreviewMode}/>);
744
+ default:
745
+ // Fallback for unknown component types - render children if available (composite handling)
746
+ if ((_p = component.children) === null || _p === void 0 ? void 0 : _p.length) {
747
+ return renderWithChildren(component);
748
+ }
749
+ return <react_native_1.View style={[styles.fallback, style]}/>;
750
+ }
751
+ };
752
+ exports.ComponentRenderer = ComponentRenderer;
753
+ /**
754
+ * StyleSheet with minimal defaults
755
+ * Colors should come from theme, not hardcoded here
756
+ */
757
+ const styles = react_native_1.StyleSheet.create({
758
+ text: {
759
+ fontSize: 16,
760
+ // Color set dynamically from theme
761
+ },
762
+ image: {
763
+ width: 100,
764
+ height: 100,
765
+ },
766
+ button: {
767
+ paddingVertical: 12,
768
+ paddingHorizontal: 24,
769
+ borderRadius: 8,
770
+ alignItems: 'center',
771
+ justifyContent: 'center',
772
+ },
773
+ buttonText: {
774
+ fontSize: 16,
775
+ fontWeight: '600',
776
+ },
777
+ stack: {
778
+ flexDirection: 'column',
779
+ },
780
+ divider: {
781
+ // backgroundColor set dynamically from theme
782
+ },
783
+ badge: {
784
+ paddingVertical: 4,
785
+ paddingHorizontal: 8,
786
+ borderRadius: 4,
787
+ },
788
+ badgeText: {
789
+ fontSize: 12,
790
+ fontWeight: '600',
791
+ },
792
+ featureList: {
793
+ gap: 8,
794
+ },
795
+ featureItem: {
796
+ flexDirection: 'row',
797
+ alignItems: 'center',
798
+ gap: 8,
799
+ },
800
+ featureIcon: {
801
+ fontSize: 16,
802
+ fontWeight: 'bold',
803
+ },
804
+ featureText: {
805
+ fontSize: 14,
806
+ },
807
+ priceContainer: {
808
+ flexDirection: 'row',
809
+ alignItems: 'baseline',
810
+ },
811
+ priceText: {
812
+ fontSize: 32,
813
+ fontWeight: 'bold',
814
+ },
815
+ pricePeriod: {
816
+ fontSize: 16,
817
+ marginLeft: 4,
818
+ },
819
+ package: {
820
+ padding: 16,
821
+ borderRadius: 12,
822
+ borderWidth: 2,
823
+ },
824
+ packageTitle: {
825
+ fontSize: 18,
826
+ fontWeight: '600',
827
+ },
828
+ packageSubtitle: {
829
+ fontSize: 14,
830
+ marginTop: 4,
831
+ },
832
+ fallback: {
833
+ padding: 8,
834
+ },
835
+ advancedWarning: {
836
+ backgroundColor: '#FFF3CD',
837
+ padding: 16,
838
+ borderRadius: 12,
839
+ borderWidth: 1,
840
+ borderColor: '#FFE69C',
841
+ alignItems: 'center',
842
+ },
843
+ warningIcon: {
844
+ fontSize: 32,
845
+ marginBottom: 8,
846
+ },
847
+ warningTitle: {
848
+ fontSize: 16,
849
+ fontWeight: '600',
850
+ color: '#000000',
851
+ marginBottom: 4,
852
+ },
853
+ warningText: {
854
+ fontSize: 13,
855
+ color: '#856404',
856
+ textAlign: 'center',
857
+ marginBottom: 4,
858
+ },
859
+ warningHint: {
860
+ fontSize: 11,
861
+ color: '#0056B3',
862
+ textAlign: 'center',
863
+ },
864
+ mediaPlaceholder: {
865
+ backgroundColor: '#F0F0F0',
866
+ padding: 16,
867
+ borderRadius: 8,
868
+ alignItems: 'center',
869
+ justifyContent: 'center',
870
+ minHeight: 60,
871
+ },
872
+ placeholderIcon: {
873
+ fontSize: 24,
874
+ marginBottom: 4,
875
+ },
876
+ placeholderText: {
877
+ fontSize: 12,
878
+ fontWeight: '600',
879
+ color: '#666666',
880
+ },
881
+ placeholderHint: {
882
+ fontSize: 10,
883
+ color: '#999999',
884
+ marginTop: 4,
885
+ },
886
+ });