@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.
- package/BillDogReactNative.podspec +30 -0
- package/LICENSE +21 -0
- package/README.md +330 -0
- package/android/build.gradle +99 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/kotlin/io/billdog/reactnative/BillDogABTestModule.kt +317 -0
- package/android/src/main/kotlin/io/billdog/reactnative/BillDogAnalyticsModule.kt +389 -0
- package/android/src/main/kotlin/io/billdog/reactnative/BillDogModule.kt +817 -0
- package/android/src/main/kotlin/io/billdog/reactnative/BillDogPaywallViewManager.kt +383 -0
- package/android/src/main/kotlin/io/billdog/reactnative/BillDogSurveyModule.kt +427 -0
- package/android/src/main/kotlin/io/billdog/reactnative/BillDogVirtualCurrencyModule.kt +407 -0
- package/android/src/main/kotlin/io/billdog/virtualcurrency/BillDogVirtualCurrencyPackage.kt +44 -0
- package/dist/AdvancedPaywallCache.d.ts +70 -0
- package/dist/AdvancedPaywallCache.js +344 -0
- package/dist/BillDog.d.ts +255 -0
- package/dist/BillDog.js +918 -0
- package/dist/BillDogConfiguration.d.ts +145 -0
- package/dist/BillDogConfiguration.js +229 -0
- package/dist/ComponentRenderer.d.ts +17 -0
- package/dist/ComponentRenderer.js +886 -0
- package/dist/LayoutEngine.d.ts +101 -0
- package/dist/LayoutEngine.js +394 -0
- package/dist/LocalizationResolver.d.ts +99 -0
- package/dist/LocalizationResolver.js +266 -0
- package/dist/NativePaywallView.d.ts +36 -0
- package/dist/NativePaywallView.js +59 -0
- package/dist/PaywallCache.d.ts +74 -0
- package/dist/PaywallCache.js +293 -0
- package/dist/PaywallStateManager.d.ts +62 -0
- package/dist/PaywallStateManager.js +147 -0
- package/dist/PaywallView.d.ts +42 -0
- package/dist/PaywallView.js +275 -0
- package/dist/ProductVariableProvider.d.ts +60 -0
- package/dist/ProductVariableProvider.js +239 -0
- package/dist/VariableResolver.d.ts +120 -0
- package/dist/VariableResolver.js +379 -0
- package/dist/WebViewPaywall.d.ts +75 -0
- package/dist/WebViewPaywall.js +360 -0
- package/dist/animations/presets.d.ts +49 -0
- package/dist/animations/presets.js +367 -0
- package/dist/components/AccoladeCpsComponent.d.ts +13 -0
- package/dist/components/AccoladeCpsComponent.js +248 -0
- package/dist/components/AccordionComponent.d.ts +10 -0
- package/dist/components/AccordionComponent.js +187 -0
- package/dist/components/AnimatedWrapper.d.ts +35 -0
- package/dist/components/AnimatedWrapper.js +277 -0
- package/dist/components/CarouselComponent.d.ts +23 -0
- package/dist/components/CarouselComponent.js +484 -0
- package/dist/components/ChartCurveComponent.d.ts +13 -0
- package/dist/components/ChartCurveComponent.js +333 -0
- package/dist/components/CheckboxComponent.d.ts +9 -0
- package/dist/components/CheckboxComponent.js +172 -0
- package/dist/components/ConfettiComponent.d.ts +9 -0
- package/dist/components/ConfettiComponent.js +172 -0
- package/dist/components/CountdownComponent.d.ts +16 -0
- package/dist/components/CountdownComponent.js +414 -0
- package/dist/components/DelayedXComponent.d.ts +12 -0
- package/dist/components/DelayedXComponent.js +240 -0
- package/dist/components/DrawerModalComponent.d.ts +20 -0
- package/dist/components/DrawerModalComponent.js +286 -0
- package/dist/components/GradientView.d.ts +38 -0
- package/dist/components/GradientView.js +126 -0
- package/dist/components/HapticFeedbackComponent.d.ts +16 -0
- package/dist/components/HapticFeedbackComponent.js +64 -0
- package/dist/components/HorizontalProductsComponent.d.ts +17 -0
- package/dist/components/HorizontalProductsComponent.js +284 -0
- package/dist/components/MultiChoiceGridComponent.d.ts +13 -0
- package/dist/components/MultiChoiceGridComponent.js +234 -0
- package/dist/components/NPSScaleComponent.d.ts +16 -0
- package/dist/components/NPSScaleComponent.js +260 -0
- package/dist/components/NavigationComponent.d.ts +26 -0
- package/dist/components/NavigationComponent.js +302 -0
- package/dist/components/OAuthButtonComponent.d.ts +20 -0
- package/dist/components/OAuthButtonComponent.js +237 -0
- package/dist/components/ProgressLoaderComponent.d.ts +13 -0
- package/dist/components/ProgressLoaderComponent.js +308 -0
- package/dist/components/ProgressStepperComponent.d.ts +18 -0
- package/dist/components/ProgressStepperComponent.js +228 -0
- package/dist/components/SegmentedPickerComponent.d.ts +10 -0
- package/dist/components/SegmentedPickerComponent.js +221 -0
- package/dist/components/ShareButtonsComponent.d.ts +21 -0
- package/dist/components/ShareButtonsComponent.js +265 -0
- package/dist/components/ShareCodeComponent.d.ts +16 -0
- package/dist/components/ShareCodeComponent.js +274 -0
- package/dist/components/SingleChoiceGridComponent.d.ts +13 -0
- package/dist/components/SingleChoiceGridComponent.js +210 -0
- package/dist/components/SliderComponent.d.ts +9 -0
- package/dist/components/SliderComponent.js +263 -0
- package/dist/components/StarRatingInputComponent.d.ts +20 -0
- package/dist/components/StarRatingInputComponent.js +198 -0
- package/dist/components/StickerCompositeComponent.d.ts +13 -0
- package/dist/components/StickerCompositeComponent.js +136 -0
- package/dist/components/TabsComponent.d.ts +19 -0
- package/dist/components/TabsComponent.js +431 -0
- package/dist/components/TextInputComponent.d.ts +18 -0
- package/dist/components/TextInputComponent.js +227 -0
- package/dist/components/TimelineComponent.d.ts +19 -0
- package/dist/components/TimelineComponent.js +104 -0
- package/dist/components/ToggleComponent.d.ts +14 -0
- package/dist/components/ToggleComponent.js +132 -0
- package/dist/components/VerticalProductsComponent.d.ts +17 -0
- package/dist/components/VerticalProductsComponent.js +311 -0
- package/dist/dynamicValues.d.ts +36 -0
- package/dist/dynamicValues.js +142 -0
- package/dist/filters/dateFilters.d.ts +50 -0
- package/dist/filters/dateFilters.js +390 -0
- package/dist/filters/index.d.ts +18 -0
- package/dist/filters/index.js +253 -0
- package/dist/hooks/useOfferings.d.ts +76 -0
- package/dist/hooks/useOfferings.js +99 -0
- package/dist/hooks/usePaywall.d.ts +27 -0
- package/dist/hooks/usePaywall.js +114 -0
- package/dist/hooks/usePlacement.d.ts +34 -0
- package/dist/hooks/usePlacement.js +89 -0
- package/dist/hooks/useSubscription.d.ts +40 -0
- package/dist/hooks/useSubscription.js +97 -0
- package/dist/index.d.ts +98 -0
- package/dist/index.js +198 -0
- package/dist/models/BillDogError.d.ts +40 -0
- package/dist/models/BillDogError.js +11 -0
- package/dist/models/CacheFetchPolicy.d.ts +8 -0
- package/dist/models/CacheFetchPolicy.js +4 -0
- package/dist/models/CustomProduct.d.ts +32 -0
- package/dist/models/CustomProduct.js +15 -0
- package/dist/models/CustomerInfo.d.ts +17 -0
- package/dist/models/CustomerInfo.js +11 -0
- package/dist/models/Delegate.d.ts +20 -0
- package/dist/models/Delegate.js +11 -0
- package/dist/models/EntitlementInfo.d.ts +19 -0
- package/dist/models/EntitlementInfo.js +2 -0
- package/dist/models/Placement.d.ts +54 -0
- package/dist/models/Placement.js +15 -0
- package/dist/models/PurchaseParams.d.ts +39 -0
- package/dist/models/PurchaseParams.js +60 -0
- package/dist/models/PurchaseResult.d.ts +30 -0
- package/dist/models/PurchaseResult.js +15 -0
- package/dist/models/RestoreResult.d.ts +30 -0
- package/dist/models/RestoreResult.js +22 -0
- package/dist/models/RestoredItem.d.ts +26 -0
- package/dist/models/RestoredItem.js +13 -0
- package/dist/modules/ABTest.d.ts +65 -0
- package/dist/modules/ABTest.js +113 -0
- package/dist/modules/Analytics.d.ts +91 -0
- package/dist/modules/Analytics.js +182 -0
- package/dist/modules/Survey.d.ts +65 -0
- package/dist/modules/Survey.js +82 -0
- package/dist/modules/VirtualCurrency.d.ts +63 -0
- package/dist/modules/VirtualCurrency.js +147 -0
- package/dist/murmur.d.ts +23 -0
- package/dist/murmur.js +104 -0
- package/dist/notifications/LiveActivitiesManager.d.ts +47 -0
- package/dist/notifications/LiveActivitiesManager.js +106 -0
- package/dist/notifications/NotificationScheduler.d.ts +55 -0
- package/dist/notifications/NotificationScheduler.js +199 -0
- package/dist/notifications/PurchaseNotificationHandler.d.ts +24 -0
- package/dist/notifications/PurchaseNotificationHandler.js +55 -0
- package/dist/notifications/useDeviceToken.d.ts +36 -0
- package/dist/notifications/useDeviceToken.js +97 -0
- package/dist/notifications/useLiveActivity.d.ts +39 -0
- package/dist/notifications/useLiveActivity.js +104 -0
- package/dist/review/ReviewAnalytics.d.ts +34 -0
- package/dist/review/ReviewAnalytics.js +73 -0
- package/dist/review/ReviewManager.d.ts +83 -0
- package/dist/review/ReviewManager.js +339 -0
- package/dist/review/ReviewTimingManager.d.ts +82 -0
- package/dist/review/ReviewTimingManager.js +224 -0
- package/dist/survey-core/types.d.ts +215 -0
- package/dist/survey-core/types.js +8 -0
- package/dist/types.d.ts +438 -0
- package/dist/types.js +158 -0
- package/dist/utils/ApiClient.d.ts +65 -0
- package/dist/utils/ApiClient.js +132 -0
- package/dist/utils/CSSConverter.d.ts +49 -0
- package/dist/utils/CSSConverter.js +470 -0
- package/dist/utils/animations.d.ts +41 -0
- package/dist/utils/animations.js +194 -0
- package/dist/utils/calendarIntegration.d.ts +36 -0
- package/dist/utils/calendarIntegration.js +89 -0
- package/dist/utils/configurationResolver.d.ts +23 -0
- package/dist/utils/configurationResolver.js +78 -0
- package/dist/utils/deviceDetection.d.ts +38 -0
- package/dist/utils/deviceDetection.js +59 -0
- package/dist/utils/hapticFeedback.d.ts +17 -0
- package/dist/utils/hapticFeedback.js +53 -0
- package/dist/utils/iconMapper.d.ts +26 -0
- package/dist/utils/iconMapper.js +113 -0
- package/dist/utils/notificationPermissions.d.ts +13 -0
- package/dist/utils/notificationPermissions.js +51 -0
- package/dist/utils/priceFormatting.d.ts +19 -0
- package/dist/utils/priceFormatting.js +99 -0
- package/dist/utils/shareSheet.d.ts +17 -0
- package/dist/utils/shareSheet.js +42 -0
- package/dist/utils/subscriptionUpgrade.d.ts +84 -0
- package/dist/utils/subscriptionUpgrade.js +100 -0
- package/dist/valueUtils.d.ts +48 -0
- package/dist/valueUtils.js +129 -0
- package/dist/xFlowTags.d.ts +18 -0
- package/dist/xFlowTags.js +385 -0
- package/ios/BillDogABTest.m +50 -0
- package/ios/BillDogABTest.swift +188 -0
- package/ios/BillDogAnalytics.m +105 -0
- package/ios/BillDogAnalytics.swift +324 -0
- package/ios/BillDogBridge.m +222 -0
- package/ios/BillDogBridge.swift +715 -0
- package/ios/BillDogLiveActivities.m +41 -0
- package/ios/BillDogLiveActivities.swift +104 -0
- package/ios/BillDogPaywallViewManager.m +39 -0
- package/ios/BillDogPaywallViewManager.swift +361 -0
- package/ios/BillDogSurvey.m +34 -0
- package/ios/BillDogSurvey.swift +257 -0
- package/ios/BillDogVirtualCurrencyBridge.m +63 -0
- package/ios/BillDogVirtualCurrencyBridge.swift +511 -0
- package/junit.xml +25 -0
- package/package.json +61 -0
- package/react-native.config.js +13 -0
- package/src/AdvancedPaywallCache.ts +433 -0
- package/src/BillDog.ts +983 -0
- package/src/BillDogConfiguration.ts +318 -0
- package/src/ComponentRenderer.tsx +1325 -0
- package/src/LayoutEngine.ts +459 -0
- package/src/LocalizationResolver.ts +311 -0
- package/src/NativePaywallView.tsx +132 -0
- package/src/PaywallCache.ts +358 -0
- package/src/PaywallStateManager.ts +154 -0
- package/src/PaywallView.tsx +328 -0
- package/src/ProductVariableProvider.ts +282 -0
- package/src/VariableResolver.ts +516 -0
- package/src/WebViewPaywall.tsx +454 -0
- package/src/animations/presets.ts +421 -0
- package/src/components/AccoladeCpsComponent.tsx +259 -0
- package/src/components/AccordionComponent.tsx +213 -0
- package/src/components/AnimatedWrapper.tsx +316 -0
- package/src/components/CarouselComponent.tsx +615 -0
- package/src/components/ChartCurveComponent.tsx +452 -0
- package/src/components/CheckboxComponent.tsx +185 -0
- package/src/components/ConfettiComponent.tsx +178 -0
- package/src/components/CountdownComponent.tsx +454 -0
- package/src/components/DelayedXComponent.tsx +266 -0
- package/src/components/DrawerModalComponent.tsx +324 -0
- package/src/components/GradientView.tsx +129 -0
- package/src/components/HapticFeedbackComponent.tsx +39 -0
- package/src/components/HorizontalProductsComponent.tsx +329 -0
- package/src/components/MultiChoiceGridComponent.tsx +265 -0
- package/src/components/NPSScaleComponent.tsx +294 -0
- package/src/components/NavigationComponent.tsx +329 -0
- package/src/components/OAuthButtonComponent.tsx +266 -0
- package/src/components/ProgressLoaderComponent.tsx +366 -0
- package/src/components/ProgressStepperComponent.tsx +250 -0
- package/src/components/SegmentedPickerComponent.tsx +245 -0
- package/src/components/ShareButtonsComponent.tsx +299 -0
- package/src/components/ShareCodeComponent.tsx +303 -0
- package/src/components/SingleChoiceGridComponent.tsx +229 -0
- package/src/components/SliderComponent.tsx +280 -0
- package/src/components/StarRatingInputComponent.tsx +223 -0
- package/src/components/StickerCompositeComponent.tsx +168 -0
- package/src/components/TabsComponent.tsx +496 -0
- package/src/components/TextInputComponent.tsx +258 -0
- package/src/components/TimelineComponent.tsx +129 -0
- package/src/components/ToggleComponent.tsx +142 -0
- package/src/components/VerticalProductsComponent.tsx +357 -0
- package/src/dynamicValues.ts +180 -0
- package/src/filters/dateFilters.ts +411 -0
- package/src/filters/index.ts +281 -0
- package/src/hooks/useOfferings.ts +192 -0
- package/src/hooks/usePaywall.ts +154 -0
- package/src/hooks/usePlacement.ts +143 -0
- package/src/hooks/useSubscription.ts +154 -0
- package/src/index.ts +245 -0
- package/src/models/BillDogError.ts +24 -0
- package/src/models/CacheFetchPolicy.ts +13 -0
- package/src/models/CustomProduct.ts +33 -0
- package/src/models/CustomerInfo.ts +26 -0
- package/src/models/Delegate.ts +22 -0
- package/src/models/EntitlementInfo.ts +27 -0
- package/src/models/Placement.ts +50 -0
- package/src/models/PurchaseParams.ts +81 -0
- package/src/models/PurchaseResult.ts +32 -0
- package/src/models/RestoreResult.ts +27 -0
- package/src/models/RestoredItem.ts +25 -0
- package/src/modules/ABTest.ts +131 -0
- package/src/modules/Analytics.ts +227 -0
- package/src/modules/Survey.ts +126 -0
- package/src/modules/VirtualCurrency.ts +223 -0
- package/src/murmur.ts +102 -0
- package/src/notifications/LiveActivitiesManager.ts +140 -0
- package/src/notifications/NotificationScheduler.ts +292 -0
- package/src/notifications/PurchaseNotificationHandler.ts +67 -0
- package/src/notifications/useDeviceToken.ts +116 -0
- package/src/notifications/useLiveActivity.ts +125 -0
- package/src/review/ReviewAnalytics.ts +89 -0
- package/src/review/ReviewManager.ts +355 -0
- package/src/review/ReviewTimingManager.ts +265 -0
- package/src/survey-core/types.ts +244 -0
- package/src/types/ambient.d.ts +9 -0
- package/src/types.ts +680 -0
- package/src/utils/ApiClient.ts +163 -0
- package/src/utils/CSSConverter.ts +552 -0
- package/src/utils/animations.ts +232 -0
- package/src/utils/calendarIntegration.ts +113 -0
- package/src/utils/configurationResolver.ts +106 -0
- package/src/utils/deviceDetection.ts +83 -0
- package/src/utils/hapticFeedback.ts +55 -0
- package/src/utils/iconMapper.ts +102 -0
- package/src/utils/notificationPermissions.ts +48 -0
- package/src/utils/priceFormatting.ts +119 -0
- package/src/utils/shareSheet.ts +55 -0
- package/src/utils/subscriptionUpgrade.ts +183 -0
- package/src/valueUtils.ts +108 -0
- 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
|
+
});
|