@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,459 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layout Engine - Converts JSON layout to React Native StyleSheet
|
|
3
|
+
*
|
|
4
|
+
* PHASE 5 SIMPLIFIED: All colors are now pre-resolved to hex by the web exporter.
|
|
5
|
+
* Removed ThemeColorResolver, CSS variable resolution, and HSL parsing.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { ViewStyle, TextStyle, ImageStyle } from 'react-native';
|
|
9
|
+
import { Layout, Appearance, Size, SizeValue, BorderConfig, Shadow, BorderSide } from './types';
|
|
10
|
+
import { convertCSSToReactNative, validateCSSForNative } from './utils/CSSConverter';
|
|
11
|
+
|
|
12
|
+
export interface CustomCSSConfig {
|
|
13
|
+
styles?: string;
|
|
14
|
+
transitions?: string;
|
|
15
|
+
animations?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Normalize a size value from any format to { type, value }
|
|
20
|
+
*/
|
|
21
|
+
function normalizeSizeValue(size: any): { type: string; value?: number } {
|
|
22
|
+
// Already normalized format
|
|
23
|
+
if (size && typeof size === 'object' && 'type' in size) {
|
|
24
|
+
// Migrate 'hug' to 'fit' for consistency
|
|
25
|
+
const type = size.type === 'hug' ? 'fit' : size.type;
|
|
26
|
+
return { type, value: size.value };
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Number value = fixed
|
|
30
|
+
if (typeof size === 'number') {
|
|
31
|
+
return { type: 'fixed', value: size };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// String value
|
|
35
|
+
if (typeof size === 'string') {
|
|
36
|
+
const lower = size.toLowerCase();
|
|
37
|
+
if (lower === 'fill' || lower === '100%') return { type: 'fill' };
|
|
38
|
+
if (lower === 'fit' || lower === 'auto' || lower === 'hug') return { type: 'fit' };
|
|
39
|
+
|
|
40
|
+
// Try to parse as number
|
|
41
|
+
const num = parseFloat(size);
|
|
42
|
+
if (!isNaN(num)) return { type: 'fixed', value: num };
|
|
43
|
+
|
|
44
|
+
return { type: 'fit' };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Default
|
|
48
|
+
return { type: 'fit' };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export class LayoutEngine {
|
|
52
|
+
/**
|
|
53
|
+
* Normalize size value (exported for external use)
|
|
54
|
+
*/
|
|
55
|
+
static normalizeSizeValue = normalizeSizeValue;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Convert JSON layout and size to React Native flex layout
|
|
59
|
+
*/
|
|
60
|
+
static getFlexLayout(layout: Layout, size?: Size): ViewStyle {
|
|
61
|
+
const style: ViewStyle = {};
|
|
62
|
+
|
|
63
|
+
// Normalize size values
|
|
64
|
+
const normalizedWidth = size?.width ? normalizeSizeValue(size.width) : { type: 'fit' };
|
|
65
|
+
const normalizedHeight = size?.height ? normalizeSizeValue(size.height) : { type: 'fit' };
|
|
66
|
+
|
|
67
|
+
// Width handling
|
|
68
|
+
switch (normalizedWidth.type) {
|
|
69
|
+
case 'fill':
|
|
70
|
+
style.alignSelf = 'stretch';
|
|
71
|
+
style.width = '100%';
|
|
72
|
+
break;
|
|
73
|
+
case 'fixed':
|
|
74
|
+
if (normalizedWidth.value && normalizedWidth.value > 0) {
|
|
75
|
+
style.width = normalizedWidth.value;
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
case 'fit':
|
|
79
|
+
default:
|
|
80
|
+
break;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Height handling
|
|
84
|
+
switch (normalizedHeight.type) {
|
|
85
|
+
case 'fill':
|
|
86
|
+
style.flex = 1;
|
|
87
|
+
break;
|
|
88
|
+
case 'fixed':
|
|
89
|
+
if (normalizedHeight.value && normalizedHeight.value > 0) {
|
|
90
|
+
style.height = normalizedHeight.value;
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
case 'fit':
|
|
94
|
+
default:
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Padding
|
|
99
|
+
if (layout.padding) {
|
|
100
|
+
if (layout.padding.top !== undefined) style.paddingTop = layout.padding.top;
|
|
101
|
+
if (layout.padding.right !== undefined) style.paddingRight = layout.padding.right;
|
|
102
|
+
if (layout.padding.bottom !== undefined) style.paddingBottom = layout.padding.bottom;
|
|
103
|
+
if (layout.padding.left !== undefined) style.paddingLeft = layout.padding.left;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Margin
|
|
107
|
+
if (layout.margin) {
|
|
108
|
+
if (layout.margin.top !== undefined) style.marginTop = layout.margin.top;
|
|
109
|
+
if (layout.margin.right !== undefined) style.marginRight = layout.margin.right;
|
|
110
|
+
if (layout.margin.bottom !== undefined) style.marginBottom = layout.margin.bottom;
|
|
111
|
+
if (layout.margin.left !== undefined) style.marginLeft = layout.margin.left;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return style;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Convert size to React Native dimensions
|
|
119
|
+
* @deprecated Use getFlexLayout with size parameter instead
|
|
120
|
+
*/
|
|
121
|
+
static getSize(size: Size, layout: Layout): ViewStyle {
|
|
122
|
+
const style: ViewStyle = {};
|
|
123
|
+
|
|
124
|
+
const normalizedWidth = normalizeSizeValue(size.width);
|
|
125
|
+
const normalizedHeight = normalizeSizeValue(size.height);
|
|
126
|
+
|
|
127
|
+
// Width
|
|
128
|
+
if (normalizedWidth.type === 'fixed' && normalizedWidth.value) {
|
|
129
|
+
style.width = normalizedWidth.value;
|
|
130
|
+
} else if (normalizedWidth.type === 'fill') {
|
|
131
|
+
style.width = '100%';
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Height
|
|
135
|
+
if (normalizedHeight.type === 'fixed' && normalizedHeight.value) {
|
|
136
|
+
style.height = normalizedHeight.value;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return style;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Parse a color value - PHASE 5 SIMPLIFIED
|
|
144
|
+
* All colors are now pre-resolved to hex by the web exporter
|
|
145
|
+
*/
|
|
146
|
+
private static parseColorValue(color: any): string | undefined {
|
|
147
|
+
if (!color) return undefined;
|
|
148
|
+
|
|
149
|
+
if (typeof color === 'string') {
|
|
150
|
+
// Handle 8-character hex colors (#RRGGBBAA format)
|
|
151
|
+
if (color.length === 9 && color.startsWith('#')) {
|
|
152
|
+
// Convert RRGGBBAA to rgba for React Native
|
|
153
|
+
const r = parseInt(color.substring(1, 3), 16);
|
|
154
|
+
const g = parseInt(color.substring(3, 5), 16);
|
|
155
|
+
const b = parseInt(color.substring(5, 7), 16);
|
|
156
|
+
const a = parseInt(color.substring(7, 9), 16) / 255;
|
|
157
|
+
return `rgba(${r}, ${g}, ${b}, ${a.toFixed(2)})`;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return color;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Handle object format { type: 'color'|'gradient', color?: string, gradient?: {...} }
|
|
164
|
+
if (typeof color === 'object') {
|
|
165
|
+
// Check resolvedColor first (pre-computed hex from web exporter)
|
|
166
|
+
if (color.resolvedColor) return this.parseColorValue(color.resolvedColor);
|
|
167
|
+
|
|
168
|
+
// Direct color type with nested color
|
|
169
|
+
if (color.type === 'color' && color.color) {
|
|
170
|
+
return this.parseColorValue(color.color);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Gradient type - fallback to first stop color
|
|
174
|
+
if (color.type === 'gradient' && color.gradient?.stops?.length) {
|
|
175
|
+
const firstStop = color.gradient.stops[0];
|
|
176
|
+
if (firstStop?.color) {
|
|
177
|
+
return this.parseColorValue(firstStop.color);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Fallback fields
|
|
182
|
+
if (color.color && typeof color.color === 'string') return this.parseColorValue(color.color);
|
|
183
|
+
if (color.hex) return color.hex;
|
|
184
|
+
if (color.value) return color.value;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
return undefined;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Convert JSON appearance to React Native ViewStyle
|
|
192
|
+
*/
|
|
193
|
+
static getAppearanceStyle(appearance: Appearance): ViewStyle {
|
|
194
|
+
const style: ViewStyle = {};
|
|
195
|
+
|
|
196
|
+
// Background color - check resolvedColor first.
|
|
197
|
+
// `fill` may be a plain color string or a structured fill object; only the
|
|
198
|
+
// object branch carries resolvedColor/color, so narrow before accessing.
|
|
199
|
+
const fillObj = typeof appearance.fill === 'object' ? appearance.fill : undefined;
|
|
200
|
+
const bgColor = this.parseColorValue(fillObj?.resolvedColor)
|
|
201
|
+
|| this.parseColorValue(fillObj?.color)
|
|
202
|
+
|| this.parseColorValue(typeof appearance.fill === 'string' ? appearance.fill : undefined)
|
|
203
|
+
|| this.parseColorValue(appearance.backgroundColor);
|
|
204
|
+
|
|
205
|
+
if (bgColor) {
|
|
206
|
+
style.backgroundColor = bgColor;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Border radius
|
|
210
|
+
const borderRadius = appearance.cornerRadius ?? appearance.borderRadius;
|
|
211
|
+
if (borderRadius !== undefined && borderRadius > 0) {
|
|
212
|
+
style.borderRadius = borderRadius;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Opacity
|
|
216
|
+
if (appearance.opacity !== undefined) {
|
|
217
|
+
style.opacity = appearance.opacity;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Border
|
|
221
|
+
if (appearance.borderWidth !== undefined && appearance.borderWidth > 0) {
|
|
222
|
+
style.borderWidth = appearance.borderWidth;
|
|
223
|
+
|
|
224
|
+
const borderColor = this.parseColorValue(appearance.borderColorResolved)
|
|
225
|
+
|| this.parseColorValue(appearance.borderColor);
|
|
226
|
+
if (borderColor) {
|
|
227
|
+
style.borderColor = borderColor;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return style;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Get appearance style with border config support
|
|
236
|
+
*/
|
|
237
|
+
static getAppearanceStyleWithBorder(appearance: Appearance, border?: BorderConfig): ViewStyle {
|
|
238
|
+
const style = this.getAppearanceStyle(appearance);
|
|
239
|
+
|
|
240
|
+
if (border) {
|
|
241
|
+
if (border.width !== undefined && border.width > 0) {
|
|
242
|
+
style.borderWidth = border.width;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Use resolvedColor first (pre-computed hex)
|
|
246
|
+
const borderColor = border.resolvedColor || border.color;
|
|
247
|
+
if (borderColor) {
|
|
248
|
+
style.borderColor = this.parseColorValue(borderColor);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (border.radius?.uniform !== undefined) {
|
|
252
|
+
style.borderRadius = border.radius.uniform;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return style;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Apply shadow to style
|
|
261
|
+
*/
|
|
262
|
+
static applyShadow(style: ViewStyle, shadow: Shadow): ViewStyle {
|
|
263
|
+
const result = { ...style };
|
|
264
|
+
|
|
265
|
+
const shadowColor = this.parseColorValue(shadow.color);
|
|
266
|
+
if (shadowColor) {
|
|
267
|
+
result.shadowColor = shadowColor;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
result.shadowOffset = {
|
|
271
|
+
width: shadow.x ?? 0,
|
|
272
|
+
height: shadow.y ?? 0,
|
|
273
|
+
};
|
|
274
|
+
result.shadowOpacity = 1;
|
|
275
|
+
result.shadowRadius = shadow.blur ?? 0;
|
|
276
|
+
|
|
277
|
+
// Android elevation
|
|
278
|
+
(result as any).elevation = Math.max(shadow.blur ?? 0, 1);
|
|
279
|
+
|
|
280
|
+
return result;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
/**
|
|
284
|
+
* Apply border sides (top, right, bottom, left individual borders)
|
|
285
|
+
*/
|
|
286
|
+
static applyBorderSides(style: ViewStyle, appearance: Appearance): ViewStyle {
|
|
287
|
+
const result = { ...style };
|
|
288
|
+
|
|
289
|
+
const applyBorderSide = (side: BorderSide | undefined, prefix: 'Top' | 'Right' | 'Bottom' | 'Left') => {
|
|
290
|
+
if (!side) return;
|
|
291
|
+
|
|
292
|
+
if (side.width !== undefined && side.width > 0) {
|
|
293
|
+
(result as any)[`border${prefix}Width`] = side.width;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const color = side.resolvedColor || side.color;
|
|
297
|
+
if (color) {
|
|
298
|
+
(result as any)[`border${prefix}Color`] = this.parseColorValue(color);
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
applyBorderSide(appearance.borderTop, 'Top');
|
|
303
|
+
applyBorderSide(appearance.borderRight, 'Right');
|
|
304
|
+
applyBorderSide(appearance.borderBottom, 'Bottom');
|
|
305
|
+
applyBorderSide(appearance.borderLeft, 'Left');
|
|
306
|
+
|
|
307
|
+
return result;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Apply custom CSS styles (for native rendering)
|
|
312
|
+
*/
|
|
313
|
+
static applyCustomCSS(style: ViewStyle, customCSS?: CustomCSSConfig): { style: ViewStyle; warnings: string[] } {
|
|
314
|
+
if (!customCSS?.styles) {
|
|
315
|
+
return { style, warnings: [] };
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const result = convertCSSToReactNative(customCSS.styles);
|
|
319
|
+
|
|
320
|
+
return {
|
|
321
|
+
style: { ...style, ...result.style },
|
|
322
|
+
warnings: result.warnings,
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Validate if custom CSS can be rendered natively
|
|
328
|
+
*/
|
|
329
|
+
static validateCustomCSSForNative(customCSS?: CustomCSSConfig): { isValid: boolean; warnings: string[] } {
|
|
330
|
+
if (!customCSS?.styles) {
|
|
331
|
+
return { isValid: true, warnings: [] };
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
const warnings = validateCSSForNative(customCSS.styles);
|
|
335
|
+
return { isValid: warnings.length === 0, warnings };
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Get container style for stack/group components
|
|
340
|
+
*/
|
|
341
|
+
static getContainerStyle(
|
|
342
|
+
layout: Layout,
|
|
343
|
+
size: Size,
|
|
344
|
+
appearance: Appearance,
|
|
345
|
+
containerLayout?: { direction?: string; distribution?: string; alignment?: string; gap?: number }
|
|
346
|
+
): ViewStyle {
|
|
347
|
+
const style: ViewStyle = {
|
|
348
|
+
...this.getFlexLayout(layout, size),
|
|
349
|
+
...this.getAppearanceStyle(appearance),
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
if (containerLayout) {
|
|
353
|
+
// Flex direction - uses canonical 'direction' property
|
|
354
|
+
style.flexDirection = containerLayout.direction === 'horizontal' ? 'row' : 'column';
|
|
355
|
+
|
|
356
|
+
// Distribution (justify-content)
|
|
357
|
+
switch (containerLayout.distribution) {
|
|
358
|
+
case 'start':
|
|
359
|
+
style.justifyContent = 'flex-start';
|
|
360
|
+
break;
|
|
361
|
+
case 'center':
|
|
362
|
+
style.justifyContent = 'center';
|
|
363
|
+
break;
|
|
364
|
+
case 'end':
|
|
365
|
+
style.justifyContent = 'flex-end';
|
|
366
|
+
break;
|
|
367
|
+
case 'space-between':
|
|
368
|
+
style.justifyContent = 'space-between';
|
|
369
|
+
break;
|
|
370
|
+
case 'space-around':
|
|
371
|
+
style.justifyContent = 'space-around';
|
|
372
|
+
break;
|
|
373
|
+
case 'space-evenly':
|
|
374
|
+
style.justifyContent = 'space-evenly';
|
|
375
|
+
break;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Alignment (align-items)
|
|
379
|
+
switch (containerLayout.alignment) {
|
|
380
|
+
case 'start':
|
|
381
|
+
style.alignItems = 'flex-start';
|
|
382
|
+
break;
|
|
383
|
+
case 'center':
|
|
384
|
+
style.alignItems = 'center';
|
|
385
|
+
break;
|
|
386
|
+
case 'end':
|
|
387
|
+
style.alignItems = 'flex-end';
|
|
388
|
+
break;
|
|
389
|
+
case 'stretch':
|
|
390
|
+
style.alignItems = 'stretch';
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Gap
|
|
395
|
+
if (containerLayout.gap !== undefined) {
|
|
396
|
+
style.gap = containerLayout.gap;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return style;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
/**
|
|
404
|
+
* Build a combined ViewStyle for a single rendered component.
|
|
405
|
+
*
|
|
406
|
+
* Composes flex layout + appearance + optional custom CSS, then layers on
|
|
407
|
+
* absolute positioning and z-index when present. This delegates to the
|
|
408
|
+
* existing helpers so runtime behavior matches the per-helper output the
|
|
409
|
+
* renderer previously relied on.
|
|
410
|
+
*/
|
|
411
|
+
static getComponentStyle(
|
|
412
|
+
layout: Layout,
|
|
413
|
+
appearance: Appearance,
|
|
414
|
+
size: Size,
|
|
415
|
+
_type?: string,
|
|
416
|
+
_properties?: Record<string, any>,
|
|
417
|
+
absolutePosition?: { x: number; y: number },
|
|
418
|
+
zIndex?: number,
|
|
419
|
+
customCSS?: CustomCSSConfig
|
|
420
|
+
): ViewStyle {
|
|
421
|
+
let style: ViewStyle = {
|
|
422
|
+
...this.getFlexLayout(layout, size),
|
|
423
|
+
...this.getAppearanceStyle(appearance),
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
if (customCSS) {
|
|
427
|
+
style = this.applyCustomCSS(style, customCSS).style;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
if (absolutePosition) {
|
|
431
|
+
style.position = 'absolute';
|
|
432
|
+
style.left = absolutePosition.x;
|
|
433
|
+
style.top = absolutePosition.y;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (zIndex !== undefined) {
|
|
437
|
+
style.zIndex = zIndex;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
return style;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Export for backward compatibility
|
|
445
|
+
export const ThemeColorResolver = {
|
|
446
|
+
setTheme: (_config: any) => {
|
|
447
|
+
console.log('[ThemeColorResolver] Phase 5: Colors pre-resolved, theme setup skipped');
|
|
448
|
+
},
|
|
449
|
+
setResolvedColors: (_colors: any) => {},
|
|
450
|
+
clearTheme: () => {},
|
|
451
|
+
isThemingEnabled: () => false,
|
|
452
|
+
getThemingMode: () => 'disabled' as const,
|
|
453
|
+
// Phase 5: colors are pre-resolved upstream, so this runtime stub performs no
|
|
454
|
+
// variable resolution. resolveVariable returns undefined (caller falls through
|
|
455
|
+
// to its own fallback) and getDefaultVariableColor returns a neutral
|
|
456
|
+
// transparent default to keep the renderer's string-typed color pipeline valid.
|
|
457
|
+
resolveVariable: (_name: string): string | undefined => undefined,
|
|
458
|
+
getDefaultVariableColor: (_name: string): string => 'transparent',
|
|
459
|
+
};
|