@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,275 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* PaywallView - Main React Native component for rendering paywalls
|
|
4
|
+
*
|
|
5
|
+
* Credentials and API base URL are resolved from BillDogConfiguration.
|
|
6
|
+
* Pass an `apiKey` prop only for backward compatibility.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.PaywallView = void 0;
|
|
43
|
+
const react_1 = __importStar(require("react"));
|
|
44
|
+
const react_native_1 = require("react-native");
|
|
45
|
+
const ComponentRenderer_1 = require("./ComponentRenderer");
|
|
46
|
+
const PaywallStateManager_1 = require("./PaywallStateManager");
|
|
47
|
+
const usePaywall_1 = require("./hooks/usePaywall");
|
|
48
|
+
const deviceDetection_1 = require("./utils/deviceDetection");
|
|
49
|
+
const LayoutEngine_1 = require("./LayoutEngine");
|
|
50
|
+
const LocalizationResolver_1 = require("./LocalizationResolver");
|
|
51
|
+
const PaywallView = ({ paywallIdentifier, configuration: providedConfiguration, apiKey, onButtonPress, onDismiss, LoadingComponent, ErrorComponent, }) => {
|
|
52
|
+
var _a, _b;
|
|
53
|
+
const [deviceCategory, setDeviceCategory] = (0, react_1.useState)((0, deviceDetection_1.detectDeviceCategory)());
|
|
54
|
+
// ── ELEMENT STATE ────────────────────────────────────────────────────────────
|
|
55
|
+
// Components have always called a `stateManager` prop (updateState /
|
|
56
|
+
// subscribeToState / getState / setState) but nothing ever supplied one, and every
|
|
57
|
+
// call site optional-chains — so the whole cross-component state protocol was a
|
|
58
|
+
// silent no-op. Supplying the shared manager here activates it for the tree.
|
|
59
|
+
//
|
|
60
|
+
// Reset DURING FIRST RENDER, not in an effect: React runs child effects BEFORE
|
|
61
|
+
// parent effects, so clearing on mount would wipe the subscriptions the children
|
|
62
|
+
// just registered and leave every component permanently deaf. (Inverted from the
|
|
63
|
+
// native SDKs, where the parent clears first and children subscribe after.) The ref
|
|
64
|
+
// guard keeps it once-per-presentation and StrictMode-safe.
|
|
65
|
+
const stateResetRef = (0, react_1.useRef)(false);
|
|
66
|
+
if (!stateResetRef.current) {
|
|
67
|
+
PaywallStateManager_1.paywallStateManager.clearAll();
|
|
68
|
+
stateResetRef.current = true;
|
|
69
|
+
}
|
|
70
|
+
(0, react_1.useEffect)(() => () => PaywallStateManager_1.paywallStateManager.clearAll(), []);
|
|
71
|
+
// Fetch paywall if identifier is provided
|
|
72
|
+
const { configuration, loading, error, refetch } = (0, usePaywall_1.usePaywall)({
|
|
73
|
+
paywallIdentifier,
|
|
74
|
+
apiKey,
|
|
75
|
+
skipFetch: !!providedConfiguration,
|
|
76
|
+
});
|
|
77
|
+
// Listen for orientation changes
|
|
78
|
+
(0, react_1.useEffect)(() => {
|
|
79
|
+
const subscription = react_native_1.Dimensions.addEventListener('change', () => {
|
|
80
|
+
const newCategory = (0, deviceDetection_1.detectDeviceCategory)();
|
|
81
|
+
if (newCategory !== deviceCategory) {
|
|
82
|
+
setDeviceCategory(newCategory);
|
|
83
|
+
if (!providedConfiguration) {
|
|
84
|
+
refetch();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return () => subscription === null || subscription === void 0 ? void 0 : subscription.remove();
|
|
89
|
+
}, [deviceCategory, providedConfiguration]);
|
|
90
|
+
// Use provided configuration or fetched configuration
|
|
91
|
+
const activeConfiguration = providedConfiguration || configuration;
|
|
92
|
+
/**
|
|
93
|
+
* Unwrap nested configuration structure
|
|
94
|
+
*/
|
|
95
|
+
const unwrappedConfig = (0, react_1.useMemo)(() => {
|
|
96
|
+
var _a, _b, _c;
|
|
97
|
+
if (!activeConfiguration)
|
|
98
|
+
return null;
|
|
99
|
+
const config = activeConfiguration;
|
|
100
|
+
if (config.configuration && typeof config.configuration === 'object') {
|
|
101
|
+
const deviceConfig = config.configuration[deviceCategory] ||
|
|
102
|
+
config.configuration['phone_portrait'] ||
|
|
103
|
+
Object.values(config.configuration)[0];
|
|
104
|
+
if (deviceConfig && typeof deviceConfig === 'object') {
|
|
105
|
+
return {
|
|
106
|
+
...deviceConfig,
|
|
107
|
+
wallConfigTheme: (_a = config.wallConfig) === null || _a === void 0 ? void 0 : _a.themeConfig,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (((_b = config[deviceCategory]) === null || _b === void 0 ? void 0 : _b.theme) || ((_c = config[deviceCategory]) === null || _c === void 0 ? void 0 : _c.components)) {
|
|
112
|
+
return config[deviceCategory];
|
|
113
|
+
}
|
|
114
|
+
return config;
|
|
115
|
+
}, [activeConfiguration, deviceCategory]);
|
|
116
|
+
/**
|
|
117
|
+
* Comprehensive theme resolution
|
|
118
|
+
*/
|
|
119
|
+
const resolvedTheme = (0, react_1.useMemo)(() => {
|
|
120
|
+
var _a, _b, _c, _d;
|
|
121
|
+
if (!unwrappedConfig)
|
|
122
|
+
return undefined;
|
|
123
|
+
const config = unwrappedConfig;
|
|
124
|
+
if ((_a = config.theme) === null || _a === void 0 ? void 0 : _a.resolvedColors) {
|
|
125
|
+
return {
|
|
126
|
+
...config.theme,
|
|
127
|
+
themingMode: config.theme.themingMode || 'full',
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
if ((_b = config.wallConfigTheme) === null || _b === void 0 ? void 0 : _b.resolvedColors) {
|
|
131
|
+
return config.wallConfigTheme;
|
|
132
|
+
}
|
|
133
|
+
if ((_c = config.structured) === null || _c === void 0 ? void 0 : _c.themes) {
|
|
134
|
+
const structuredTheme = config.structured.themes[deviceCategory] ||
|
|
135
|
+
config.structured.themes['phone_portrait'];
|
|
136
|
+
if (structuredTheme === null || structuredTheme === void 0 ? void 0 : structuredTheme.resolvedColors) {
|
|
137
|
+
return structuredTheme;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if ((_d = config.theme) === null || _d === void 0 ? void 0 : _d.colors) {
|
|
141
|
+
return {
|
|
142
|
+
primaryColor: config.theme.colors.primary,
|
|
143
|
+
secondaryColor: config.theme.colors.secondary,
|
|
144
|
+
backgroundColor: config.theme.colors.background,
|
|
145
|
+
textColor: config.theme.colors.foreground || config.theme.colors.text,
|
|
146
|
+
cardColor: config.theme.colors.card,
|
|
147
|
+
mutedColor: config.theme.colors.muted,
|
|
148
|
+
borderColor: config.theme.colors.border,
|
|
149
|
+
accentColor: config.theme.colors.accent,
|
|
150
|
+
resolvedColors: config.theme.colors,
|
|
151
|
+
themingMode: config.theme.themingMode || 'full',
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
return config.theme;
|
|
155
|
+
}, [unwrappedConfig, deviceCategory]);
|
|
156
|
+
// Initialize ThemeColorResolver with resolved theme colors
|
|
157
|
+
(0, react_1.useEffect)(() => {
|
|
158
|
+
if (resolvedTheme) {
|
|
159
|
+
const themeForResolver = {};
|
|
160
|
+
if (resolvedTheme.primaryColor)
|
|
161
|
+
themeForResolver.primaryColor = resolvedTheme.primaryColor;
|
|
162
|
+
if (resolvedTheme.secondaryColor)
|
|
163
|
+
themeForResolver.secondaryColor = resolvedTheme.secondaryColor;
|
|
164
|
+
if (resolvedTheme.backgroundColor)
|
|
165
|
+
themeForResolver.backgroundColor = resolvedTheme.backgroundColor;
|
|
166
|
+
if (resolvedTheme.textColor)
|
|
167
|
+
themeForResolver.textColor = resolvedTheme.textColor;
|
|
168
|
+
if (resolvedTheme.cardColor)
|
|
169
|
+
themeForResolver.cardColor = resolvedTheme.cardColor;
|
|
170
|
+
if (resolvedTheme.mutedColor)
|
|
171
|
+
themeForResolver.mutedColor = resolvedTheme.mutedColor;
|
|
172
|
+
if (resolvedTheme.borderColor)
|
|
173
|
+
themeForResolver.borderColor = resolvedTheme.borderColor;
|
|
174
|
+
if (resolvedTheme.accentColor)
|
|
175
|
+
themeForResolver.accentColor = resolvedTheme.accentColor;
|
|
176
|
+
if (resolvedTheme.resolvedColors) {
|
|
177
|
+
Object.entries(resolvedTheme.resolvedColors).forEach(([key, value]) => {
|
|
178
|
+
if (typeof value === 'string') {
|
|
179
|
+
themeForResolver[key] = value;
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
LayoutEngine_1.ThemeColorResolver.setTheme(themeForResolver);
|
|
184
|
+
console.log('[PaywallView] Theme initialized:', themeForResolver);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
LayoutEngine_1.ThemeColorResolver.setTheme(null);
|
|
188
|
+
}
|
|
189
|
+
}, [resolvedTheme]);
|
|
190
|
+
if (loading && !activeConfiguration) {
|
|
191
|
+
if (LoadingComponent) {
|
|
192
|
+
return <LoadingComponent />;
|
|
193
|
+
}
|
|
194
|
+
return (<react_native_1.View style={styles.centered}>
|
|
195
|
+
<react_native_1.ActivityIndicator size="large" color="#007AFF"/>
|
|
196
|
+
</react_native_1.View>);
|
|
197
|
+
}
|
|
198
|
+
if (error && !activeConfiguration) {
|
|
199
|
+
if (ErrorComponent) {
|
|
200
|
+
return <ErrorComponent error={error}/>;
|
|
201
|
+
}
|
|
202
|
+
return <react_native_1.View style={styles.centered}/>;
|
|
203
|
+
}
|
|
204
|
+
if (!activeConfiguration) {
|
|
205
|
+
return null;
|
|
206
|
+
}
|
|
207
|
+
const backgroundColor = (resolvedTheme === null || resolvedTheme === void 0 ? void 0 : resolvedTheme.backgroundColor) ||
|
|
208
|
+
((_a = resolvedTheme === null || resolvedTheme === void 0 ? void 0 : resolvedTheme.resolvedColors) === null || _a === void 0 ? void 0 : _a.background) ||
|
|
209
|
+
'#FFFFFF';
|
|
210
|
+
// Layout direction — RTL when the dashboard set an explicit
|
|
211
|
+
// `theme.direction: 'rtl'` override, or when the effective locale's
|
|
212
|
+
// language is right-to-left. Mirrors Android `PaywallScreen.kt:431-458`.
|
|
213
|
+
// Applied as a Yoga `direction` style so flex layout mirrors for the
|
|
214
|
+
// whole component tree (row reverses, start/end flip).
|
|
215
|
+
const layoutDirection = (() => {
|
|
216
|
+
var _a, _b;
|
|
217
|
+
const explicit = (_b = (_a = unwrappedConfig === null || unwrappedConfig === void 0 ? void 0 : unwrappedConfig.theme) === null || _a === void 0 ? void 0 : _a.direction) !== null && _b !== void 0 ? _b : resolvedTheme === null || resolvedTheme === void 0 ? void 0 : resolvedTheme.direction;
|
|
218
|
+
if (explicit === 'rtl')
|
|
219
|
+
return 'rtl';
|
|
220
|
+
if (explicit === 'ltr')
|
|
221
|
+
return 'ltr';
|
|
222
|
+
const baseLocale = activeConfiguration === null || activeConfiguration === void 0 ? void 0 : activeConfiguration.baseLocale;
|
|
223
|
+
const effectiveLocale = LocalizationResolver_1.LocalizationResolver.getEffectiveLocale();
|
|
224
|
+
// A non-base effective locale wins; otherwise fall back to baseLocale.
|
|
225
|
+
const localeForDirection = effectiveLocale && effectiveLocale !== baseLocale
|
|
226
|
+
? effectiveLocale
|
|
227
|
+
: (baseLocale || effectiveLocale);
|
|
228
|
+
return LocalizationResolver_1.LocalizationResolver.isRtlLocale(localeForDirection) ? 'rtl' : 'ltr';
|
|
229
|
+
})();
|
|
230
|
+
const components = (unwrappedConfig === null || unwrappedConfig === void 0 ? void 0 : unwrappedConfig.components) || (activeConfiguration === null || activeConfiguration === void 0 ? void 0 : activeConfiguration.components) || [];
|
|
231
|
+
const absoluteComponents = components.filter((c) => c.absolutePosition);
|
|
232
|
+
const relativeComponents = components.filter((c) => !c.absolutePosition);
|
|
233
|
+
const screenLayout = (_b = unwrappedConfig === null || unwrappedConfig === void 0 ? void 0 : unwrappedConfig.theme) === null || _b === void 0 ? void 0 : _b.screenLayout;
|
|
234
|
+
const contentPadding = (screenLayout === null || screenLayout === void 0 ? void 0 : screenLayout.padding) || { top: 16, right: 16, bottom: 16, left: 16 };
|
|
235
|
+
return (<react_native_1.View style={[styles.container, { backgroundColor, direction: layoutDirection }]}>
|
|
236
|
+
<react_native_1.ScrollView style={styles.scrollView} contentContainerStyle={[
|
|
237
|
+
styles.content,
|
|
238
|
+
{
|
|
239
|
+
paddingTop: contentPadding.top,
|
|
240
|
+
paddingRight: contentPadding.right,
|
|
241
|
+
paddingBottom: contentPadding.bottom,
|
|
242
|
+
paddingLeft: contentPadding.left,
|
|
243
|
+
gap: (screenLayout === null || screenLayout === void 0 ? void 0 : screenLayout.gap) || 16,
|
|
244
|
+
}
|
|
245
|
+
]}>
|
|
246
|
+
{relativeComponents.map((component) => (<ComponentRenderer_1.ComponentRenderer key={component.id} stateManager={PaywallStateManager_1.paywallStateManager} component={component} configuration={activeConfiguration} theme={resolvedTheme} onButtonPress={onButtonPress}/>))}
|
|
247
|
+
</react_native_1.ScrollView>
|
|
248
|
+
|
|
249
|
+
{absoluteComponents.length > 0 && (<react_native_1.View style={styles.absoluteContainer} pointerEvents="box-none">
|
|
250
|
+
{absoluteComponents.map((component) => (<ComponentRenderer_1.ComponentRenderer key={component.id} stateManager={PaywallStateManager_1.paywallStateManager} component={component} configuration={activeConfiguration} theme={resolvedTheme} onButtonPress={onButtonPress}/>))}
|
|
251
|
+
</react_native_1.View>)}
|
|
252
|
+
</react_native_1.View>);
|
|
253
|
+
};
|
|
254
|
+
exports.PaywallView = PaywallView;
|
|
255
|
+
const styles = react_native_1.StyleSheet.create({
|
|
256
|
+
container: {
|
|
257
|
+
flex: 1,
|
|
258
|
+
position: 'relative',
|
|
259
|
+
},
|
|
260
|
+
scrollView: {
|
|
261
|
+
flex: 1,
|
|
262
|
+
},
|
|
263
|
+
content: {
|
|
264
|
+
flexGrow: 1,
|
|
265
|
+
},
|
|
266
|
+
centered: {
|
|
267
|
+
flex: 1,
|
|
268
|
+
justifyContent: 'center',
|
|
269
|
+
alignItems: 'center',
|
|
270
|
+
},
|
|
271
|
+
absoluteContainer: {
|
|
272
|
+
...react_native_1.StyleSheet.absoluteFillObject,
|
|
273
|
+
zIndex: 10,
|
|
274
|
+
},
|
|
275
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product Variable Provider for BillDog React Native SDK
|
|
3
|
+
*
|
|
4
|
+
* Generates variable maps from packages for use in VariableResolver.
|
|
5
|
+
* Enables {{product.price}}, {{product.period}}, {{selectedProduct.*}}, etc.
|
|
6
|
+
*
|
|
7
|
+
* Port of Android's ProductVariableProvider.kt with 1:1 variable key parity.
|
|
8
|
+
*/
|
|
9
|
+
export interface PackageInput {
|
|
10
|
+
identifier: string;
|
|
11
|
+
packageType?: string;
|
|
12
|
+
productId?: string;
|
|
13
|
+
price?: string;
|
|
14
|
+
rawPrice?: number;
|
|
15
|
+
currencyCode?: string;
|
|
16
|
+
title?: string;
|
|
17
|
+
description?: string;
|
|
18
|
+
subscriptionPeriod?: {
|
|
19
|
+
value: number;
|
|
20
|
+
unit: string;
|
|
21
|
+
} | null;
|
|
22
|
+
freeTrialPeriod?: {
|
|
23
|
+
value: number;
|
|
24
|
+
unit: string;
|
|
25
|
+
} | null;
|
|
26
|
+
introductoryPrice?: {
|
|
27
|
+
price: number;
|
|
28
|
+
priceString: string;
|
|
29
|
+
period?: {
|
|
30
|
+
value: number;
|
|
31
|
+
unit: string;
|
|
32
|
+
};
|
|
33
|
+
} | null;
|
|
34
|
+
isSubscription?: boolean;
|
|
35
|
+
[key: string]: any;
|
|
36
|
+
}
|
|
37
|
+
export interface TrialEligibilityInput {
|
|
38
|
+
isEligible: boolean;
|
|
39
|
+
hasUsedTrial?: boolean;
|
|
40
|
+
[key: string]: any;
|
|
41
|
+
}
|
|
42
|
+
export declare class ProductVariableProvider {
|
|
43
|
+
private packages;
|
|
44
|
+
private trialEligibility?;
|
|
45
|
+
constructor(packages: PackageInput[], trialEligibility?: Record<string, TrialEligibilityInput>);
|
|
46
|
+
/** Generate variable map for a specific product index */
|
|
47
|
+
getVariablesForProduct(index: number): Record<string, any>;
|
|
48
|
+
/** Generate variable map for a specific package (40+ keys) */
|
|
49
|
+
getVariablesForPackage(pkg: PackageInput): Record<string, any>;
|
|
50
|
+
/** Generate variables for selected product with "selectedProduct." prefix */
|
|
51
|
+
getSelectedProductVariables(selectedIndex: number): Record<string, any>;
|
|
52
|
+
/** Generate all product variables with index prefix (products.0.*, products.1.*, etc.) */
|
|
53
|
+
getAllProductVariables(): Record<string, any>;
|
|
54
|
+
/** Generate convenience aliases (primary, secondary, monthly, annual, etc.) */
|
|
55
|
+
getConvenienceVariables(): Record<string, any>;
|
|
56
|
+
/** Create provider from an offering */
|
|
57
|
+
static fromOffering(offering: {
|
|
58
|
+
packages: PackageInput[];
|
|
59
|
+
}, trialEligibility?: Record<string, TrialEligibilityInput>): ProductVariableProvider;
|
|
60
|
+
}
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Product Variable Provider for BillDog React Native SDK
|
|
4
|
+
*
|
|
5
|
+
* Generates variable maps from packages for use in VariableResolver.
|
|
6
|
+
* Enables {{product.price}}, {{product.period}}, {{selectedProduct.*}}, etc.
|
|
7
|
+
*
|
|
8
|
+
* Port of Android's ProductVariableProvider.kt with 1:1 variable key parity.
|
|
9
|
+
*/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.ProductVariableProvider = void 0;
|
|
12
|
+
class ProductVariableProvider {
|
|
13
|
+
constructor(packages, trialEligibility) {
|
|
14
|
+
this.packages = packages;
|
|
15
|
+
this.trialEligibility = trialEligibility;
|
|
16
|
+
}
|
|
17
|
+
/** Generate variable map for a specific product index */
|
|
18
|
+
getVariablesForProduct(index) {
|
|
19
|
+
const pkg = this.packages[index];
|
|
20
|
+
if (!pkg)
|
|
21
|
+
return {};
|
|
22
|
+
return this.getVariablesForPackage(pkg);
|
|
23
|
+
}
|
|
24
|
+
/** Generate variable map for a specific package (40+ keys) */
|
|
25
|
+
getVariablesForPackage(pkg) {
|
|
26
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
27
|
+
const eligibility = (_a = this.trialEligibility) === null || _a === void 0 ? void 0 : _a[(_b = pkg.productId) !== null && _b !== void 0 ? _b : pkg.identifier];
|
|
28
|
+
const vars = {};
|
|
29
|
+
// Basic
|
|
30
|
+
vars['product.identifier'] = pkg.identifier;
|
|
31
|
+
vars['product.packageType'] = (_c = pkg.packageType) !== null && _c !== void 0 ? _c : 'custom';
|
|
32
|
+
const hasProduct = pkg.price !== undefined || pkg.rawPrice !== undefined;
|
|
33
|
+
if (hasProduct) {
|
|
34
|
+
vars['product.price'] = (_d = pkg.price) !== null && _d !== void 0 ? _d : '';
|
|
35
|
+
vars['product.rawPrice'] = (_e = pkg.rawPrice) !== null && _e !== void 0 ? _e : 0;
|
|
36
|
+
vars['product.currencyCode'] = (_f = pkg.currencyCode) !== null && _f !== void 0 ? _f : 'USD';
|
|
37
|
+
vars['product.currencySymbol'] = getCurrencySymbol((_g = pkg.currencyCode) !== null && _g !== void 0 ? _g : 'USD');
|
|
38
|
+
vars['product.title'] = (_h = pkg.title) !== null && _h !== void 0 ? _h : '';
|
|
39
|
+
vars['product.description'] = (_j = pkg.description) !== null && _j !== void 0 ? _j : '';
|
|
40
|
+
// Period
|
|
41
|
+
const period = pkg.subscriptionPeriod;
|
|
42
|
+
if (period) {
|
|
43
|
+
vars['product.period'] = toDisplayString(period);
|
|
44
|
+
vars['product.periodShort'] = toShortString(period);
|
|
45
|
+
vars['product.periodDays'] = totalDays(period);
|
|
46
|
+
vars['product.periodUnit'] = period.unit;
|
|
47
|
+
vars['product.periodValue'] = period.value;
|
|
48
|
+
}
|
|
49
|
+
// Calculated prices
|
|
50
|
+
const raw = (_k = pkg.rawPrice) !== null && _k !== void 0 ? _k : 0;
|
|
51
|
+
const days = period ? totalDays(period) : 0;
|
|
52
|
+
const daily = days > 0 ? raw / days : raw;
|
|
53
|
+
const weekly = days > 0 ? (raw / days) * 7 : raw;
|
|
54
|
+
const monthly = days > 0 ? raw / (days / 30) : raw;
|
|
55
|
+
const yearly = days > 0 ? (raw / days) * 365 : raw;
|
|
56
|
+
const cc = (_l = pkg.currencyCode) !== null && _l !== void 0 ? _l : 'USD';
|
|
57
|
+
vars['product.dailyPrice'] = formatPrice(daily, cc);
|
|
58
|
+
vars['product.weeklyPrice'] = formatPrice(weekly, cc);
|
|
59
|
+
vars['product.monthlyPrice'] = formatPrice(monthly, cc);
|
|
60
|
+
vars['product.yearlyPrice'] = formatPrice(yearly, cc);
|
|
61
|
+
vars['product.rawDailyPrice'] = daily;
|
|
62
|
+
vars['product.rawWeeklyPrice'] = weekly;
|
|
63
|
+
vars['product.rawMonthlyPrice'] = monthly;
|
|
64
|
+
vars['product.rawYearlyPrice'] = yearly;
|
|
65
|
+
// Trial
|
|
66
|
+
const trial = pkg.freeTrialPeriod;
|
|
67
|
+
vars['product.hasFreeTrial'] = trial != null;
|
|
68
|
+
if (trial) {
|
|
69
|
+
vars['product.trialPeriod'] = toDisplayString(trial);
|
|
70
|
+
vars['product.trialPeriodDays'] = totalDays(trial);
|
|
71
|
+
vars['product.trialPeriodText'] = formatTrialPeriod(trial);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
vars['product.trialPeriod'] = '';
|
|
75
|
+
vars['product.trialPeriodDays'] = 0;
|
|
76
|
+
vars['product.trialPeriodText'] = '';
|
|
77
|
+
}
|
|
78
|
+
vars['product.isTrialEligible'] = (_m = eligibility === null || eligibility === void 0 ? void 0 : eligibility.isEligible) !== null && _m !== void 0 ? _m : (trial != null);
|
|
79
|
+
// Intro offer
|
|
80
|
+
const intro = pkg.introductoryPrice;
|
|
81
|
+
vars['product.hasIntroOffer'] = intro != null;
|
|
82
|
+
if (intro) {
|
|
83
|
+
vars['product.introPrice'] = intro.priceString;
|
|
84
|
+
vars['product.introPriceRaw'] = intro.price;
|
|
85
|
+
vars['product.introPeriod'] = intro.period ? toDisplayString(intro.period) : '';
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
vars['product.introPrice'] = '';
|
|
89
|
+
vars['product.introPriceRaw'] = 0;
|
|
90
|
+
vars['product.introPeriod'] = '';
|
|
91
|
+
}
|
|
92
|
+
// User eligibility
|
|
93
|
+
const isEligibleForIntro = (_o = eligibility === null || eligibility === void 0 ? void 0 : eligibility.isEligible) !== null && _o !== void 0 ? _o : (trial != null || intro != null);
|
|
94
|
+
const hasUsedTrial = (_p = eligibility === null || eligibility === void 0 ? void 0 : eligibility.hasUsedTrial) !== null && _p !== void 0 ? _p : false;
|
|
95
|
+
vars['user.isEligibleForIntro'] = isEligibleForIntro;
|
|
96
|
+
vars['user.hasUsedTrial'] = hasUsedTrial;
|
|
97
|
+
vars['user.isEligibleForPromo'] = false;
|
|
98
|
+
// Offer summary
|
|
99
|
+
const hasAnyOffer = trial != null || intro != null;
|
|
100
|
+
vars['offer.hasAnyOffer'] = hasAnyOffer;
|
|
101
|
+
vars['offer.type'] = trial ? 'free_trial' : intro ? 'intro' : 'none';
|
|
102
|
+
vars['product.isSubscription'] = (_q = pkg.isSubscription) !== null && _q !== void 0 ? _q : (period != null);
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
// Fallback values
|
|
106
|
+
vars['product.price'] = '';
|
|
107
|
+
vars['product.rawPrice'] = 0;
|
|
108
|
+
vars['product.currencyCode'] = 'USD';
|
|
109
|
+
vars['product.currencySymbol'] = '$';
|
|
110
|
+
vars['product.title'] = '';
|
|
111
|
+
vars['product.description'] = '';
|
|
112
|
+
vars['product.period'] = '';
|
|
113
|
+
vars['product.periodShort'] = '';
|
|
114
|
+
vars['product.periodDays'] = 0;
|
|
115
|
+
vars['product.hasFreeTrial'] = false;
|
|
116
|
+
vars['product.isTrialEligible'] = false;
|
|
117
|
+
vars['product.hasIntroOffer'] = false;
|
|
118
|
+
vars['product.isSubscription'] = false;
|
|
119
|
+
}
|
|
120
|
+
return vars;
|
|
121
|
+
}
|
|
122
|
+
/** Generate variables for selected product with "selectedProduct." prefix */
|
|
123
|
+
getSelectedProductVariables(selectedIndex) {
|
|
124
|
+
const productVars = this.getVariablesForProduct(selectedIndex);
|
|
125
|
+
const result = {};
|
|
126
|
+
for (const [key, value] of Object.entries(productVars)) {
|
|
127
|
+
result[key.replace('product.', 'selectedProduct.')] = value;
|
|
128
|
+
}
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
/** Generate all product variables with index prefix (products.0.*, products.1.*, etc.) */
|
|
132
|
+
getAllProductVariables() {
|
|
133
|
+
const vars = {};
|
|
134
|
+
this.packages.forEach((pkg, index) => {
|
|
135
|
+
const pkgVars = this.getVariablesForPackage(pkg);
|
|
136
|
+
for (const [key, value] of Object.entries(pkgVars)) {
|
|
137
|
+
const productKey = key.startsWith('product.') ? key.slice(8) : key;
|
|
138
|
+
vars[`products.${index}.${productKey}`] = value;
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
return vars;
|
|
142
|
+
}
|
|
143
|
+
/** Generate convenience aliases (primary, secondary, monthly, annual, etc.) */
|
|
144
|
+
getConvenienceVariables() {
|
|
145
|
+
var _a;
|
|
146
|
+
const vars = {};
|
|
147
|
+
// Primary = first package
|
|
148
|
+
if (this.packages[0]) {
|
|
149
|
+
for (const [key, value] of Object.entries(this.getVariablesForPackage(this.packages[0]))) {
|
|
150
|
+
const k = key.startsWith('product.') ? key.slice(8) : key;
|
|
151
|
+
vars[`primary.${k}`] = value;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Secondary = second package
|
|
155
|
+
if (this.packages[1]) {
|
|
156
|
+
for (const [key, value] of Object.entries(this.getVariablesForPackage(this.packages[1]))) {
|
|
157
|
+
const k = key.startsWith('product.') ? key.slice(8) : key;
|
|
158
|
+
vars[`secondary.${k}`] = value;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Named packages by type
|
|
162
|
+
for (const pkg of this.packages) {
|
|
163
|
+
const typeKey = (_a = pkg.packageType) !== null && _a !== void 0 ? _a : 'custom';
|
|
164
|
+
for (const [key, value] of Object.entries(this.getVariablesForPackage(pkg))) {
|
|
165
|
+
const k = key.startsWith('product.') ? key.slice(8) : key;
|
|
166
|
+
vars[`${typeKey}.${k}`] = value;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return vars;
|
|
170
|
+
}
|
|
171
|
+
/** Create provider from an offering */
|
|
172
|
+
static fromOffering(offering, trialEligibility) {
|
|
173
|
+
return new ProductVariableProvider(offering.packages, trialEligibility);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
exports.ProductVariableProvider = ProductVariableProvider;
|
|
177
|
+
// Helpers
|
|
178
|
+
function getCurrencySymbol(currencyCode) {
|
|
179
|
+
try {
|
|
180
|
+
return (0).toLocaleString(undefined, {
|
|
181
|
+
style: 'currency', currency: currencyCode, minimumFractionDigits: 0, maximumFractionDigits: 0,
|
|
182
|
+
}).replace(/\d/g, '').trim() || '$';
|
|
183
|
+
}
|
|
184
|
+
catch {
|
|
185
|
+
return '$';
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function formatPrice(price, currencyCode) {
|
|
189
|
+
try {
|
|
190
|
+
return new Intl.NumberFormat(undefined, { style: 'currency', currency: currencyCode }).format(price);
|
|
191
|
+
}
|
|
192
|
+
catch {
|
|
193
|
+
return `$${price.toFixed(2)}`;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
function totalDays(period) {
|
|
197
|
+
switch (period.unit) {
|
|
198
|
+
case 'day': return period.value;
|
|
199
|
+
case 'week': return period.value * 7;
|
|
200
|
+
case 'month': return period.value * 30;
|
|
201
|
+
case 'year': return period.value * 365;
|
|
202
|
+
default: return period.value;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function toDisplayString(period) {
|
|
206
|
+
const u = period.unit;
|
|
207
|
+
const v = period.value;
|
|
208
|
+
const unitStr = v === 1
|
|
209
|
+
? (u === 'day' ? 'day' : u === 'week' ? 'week' : u === 'month' ? 'month' : 'year')
|
|
210
|
+
: (u === 'day' ? 'days' : u === 'week' ? 'weeks' : u === 'month' ? 'months' : 'years');
|
|
211
|
+
return `${v} ${unitStr}`;
|
|
212
|
+
}
|
|
213
|
+
function toShortString(period) {
|
|
214
|
+
switch (period.unit) {
|
|
215
|
+
case 'day': return '/day';
|
|
216
|
+
case 'week': return '/wk';
|
|
217
|
+
case 'month': return '/mo';
|
|
218
|
+
case 'year': return '/yr';
|
|
219
|
+
default: return `/${period.unit}`;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
function formatTrialPeriod(period) {
|
|
223
|
+
const days = totalDays(period);
|
|
224
|
+
if (days === 1)
|
|
225
|
+
return '1-day free trial';
|
|
226
|
+
if (days === 7)
|
|
227
|
+
return '7-day free trial';
|
|
228
|
+
if (days === 14)
|
|
229
|
+
return '2-week free trial';
|
|
230
|
+
if (days === 30 || days === 31)
|
|
231
|
+
return '1-month free trial';
|
|
232
|
+
if (days < 7)
|
|
233
|
+
return `${days}-day free trial`;
|
|
234
|
+
if (days % 7 === 0)
|
|
235
|
+
return `${days / 7}-week free trial`;
|
|
236
|
+
if (days % 30 === 0)
|
|
237
|
+
return `${days / 30}-month free trial`;
|
|
238
|
+
return `${days}-day free trial`;
|
|
239
|
+
}
|