@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,431 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TabsComponent - Interactive tabs for React Native
|
|
4
|
+
* Uses element:{id}.currentIndex for state tracking (Superwall pattern)
|
|
5
|
+
* Full property support matching web schema for cross-platform consistency
|
|
6
|
+
* Phase 2 Enhanced: icon support, alignment, sizing, disabled state, animation duration, overflow
|
|
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.TabsComponent = void 0;
|
|
43
|
+
const react_1 = __importStar(require("react"));
|
|
44
|
+
const react_native_1 = require("react-native");
|
|
45
|
+
// Enable LayoutAnimation on Android
|
|
46
|
+
if (react_native_1.Platform.OS === 'android' && react_native_1.UIManager.setLayoutAnimationEnabledExperimental) {
|
|
47
|
+
react_native_1.UIManager.setLayoutAnimationEnabledExperimental(true);
|
|
48
|
+
}
|
|
49
|
+
// Icon mapping for React Native (using basic Unicode symbols as fallback)
|
|
50
|
+
const ICON_MAP = {
|
|
51
|
+
home: '🏠',
|
|
52
|
+
star: '⭐',
|
|
53
|
+
settings: '⚙️',
|
|
54
|
+
person: '👤',
|
|
55
|
+
favorite: '❤️',
|
|
56
|
+
heart: '❤️',
|
|
57
|
+
search: '🔍',
|
|
58
|
+
check: '✓',
|
|
59
|
+
close: '✕',
|
|
60
|
+
add: '+',
|
|
61
|
+
remove: '-',
|
|
62
|
+
edit: '✏️',
|
|
63
|
+
delete: '🗑️',
|
|
64
|
+
share: '↗️',
|
|
65
|
+
download: '⬇️',
|
|
66
|
+
upload: '⬆️',
|
|
67
|
+
refresh: '🔄',
|
|
68
|
+
info: 'ℹ️',
|
|
69
|
+
help: '❓',
|
|
70
|
+
warning: '⚠️',
|
|
71
|
+
error: '❌',
|
|
72
|
+
lock: '🔒',
|
|
73
|
+
unlock: '🔓',
|
|
74
|
+
notification: '🔔',
|
|
75
|
+
email: '✉️',
|
|
76
|
+
phone: '📞',
|
|
77
|
+
location: '📍',
|
|
78
|
+
calendar: '📅',
|
|
79
|
+
time: '⏰',
|
|
80
|
+
camera: '📷',
|
|
81
|
+
photo: '🖼️',
|
|
82
|
+
video: '🎥',
|
|
83
|
+
music: '🎵',
|
|
84
|
+
play: '▶️',
|
|
85
|
+
pause: '⏸️',
|
|
86
|
+
stop: '⏹️',
|
|
87
|
+
crown: '👑',
|
|
88
|
+
premium: '👑',
|
|
89
|
+
diamond: '💎',
|
|
90
|
+
gift: '🎁',
|
|
91
|
+
cart: '🛒',
|
|
92
|
+
wallet: '💰',
|
|
93
|
+
rocket: '🚀',
|
|
94
|
+
trophy: '🏆',
|
|
95
|
+
medal: '🏅',
|
|
96
|
+
badge: '📛',
|
|
97
|
+
verified: '✅',
|
|
98
|
+
shield: '🛡️',
|
|
99
|
+
bolt: '⚡',
|
|
100
|
+
fire: '🔥',
|
|
101
|
+
sparkle: '✨',
|
|
102
|
+
magic: '🪄',
|
|
103
|
+
};
|
|
104
|
+
const TabsComponent = ({ component, renderChild, stateManager, isPreviewMode = false, onTabChange, }) => {
|
|
105
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1;
|
|
106
|
+
const props = component.properties || {};
|
|
107
|
+
// Core Properties
|
|
108
|
+
const tabCount = (_a = props.tabCount) !== null && _a !== void 0 ? _a : 3;
|
|
109
|
+
const defaultTab = (_b = props.defaultTab) !== null && _b !== void 0 ? _b : 0;
|
|
110
|
+
const animated = (_c = props.animated) !== null && _c !== void 0 ? _c : true;
|
|
111
|
+
const variant = (_d = props.variant) !== null && _d !== void 0 ? _d : 'pills';
|
|
112
|
+
// Phase 2: New Properties
|
|
113
|
+
const tabAlignment = (_e = props.tabAlignment) !== null && _e !== void 0 ? _e : 'stretch';
|
|
114
|
+
const tabSizing = (_f = props.tabSizing) !== null && _f !== void 0 ? _f : 'equal';
|
|
115
|
+
const fixedTabWidth = props.fixedTabWidth;
|
|
116
|
+
const animationDuration = (_g = props.animationDuration) !== null && _g !== void 0 ? _g : 200;
|
|
117
|
+
const overflowBehavior = (_h = props.overflowBehavior) !== null && _h !== void 0 ? _h : 'scroll';
|
|
118
|
+
const tabIconPosition = (_j = props.tabIconPosition) !== null && _j !== void 0 ? _j : 'left';
|
|
119
|
+
// Styling Properties (matching web schema)
|
|
120
|
+
const activeTabColor = (_k = props.activeTabColor) !== null && _k !== void 0 ? _k : '#FFFFFF';
|
|
121
|
+
const inactiveTabColor = (_l = props.inactiveTabColor) !== null && _l !== void 0 ? _l : 'transparent';
|
|
122
|
+
const activeTextColor = (_m = props.activeTextColor) !== null && _m !== void 0 ? _m : '#000000';
|
|
123
|
+
const inactiveTextColor = (_o = props.inactiveTextColor) !== null && _o !== void 0 ? _o : '#666666';
|
|
124
|
+
const tabListBackgroundColor = (_p = props.tabListBackgroundColor) !== null && _p !== void 0 ? _p : '#F5F5F5';
|
|
125
|
+
const tabFontSize = (_q = props.tabFontSize) !== null && _q !== void 0 ? _q : 14;
|
|
126
|
+
const tabFontWeight = (_r = props.tabFontWeight) !== null && _r !== void 0 ? _r : '600';
|
|
127
|
+
const tabBorderRadius = (_s = props.tabBorderRadius) !== null && _s !== void 0 ? _s : 8;
|
|
128
|
+
const tabListBorderRadius = (_t = props.tabListBorderRadius) !== null && _t !== void 0 ? _t : 10;
|
|
129
|
+
const tabGap = (_u = props.tabGap) !== null && _u !== void 0 ? _u : 4;
|
|
130
|
+
const tabPaddingX = (_v = props.tabPaddingX) !== null && _v !== void 0 ? _v : 16;
|
|
131
|
+
const tabPaddingY = (_w = props.tabPaddingY) !== null && _w !== void 0 ? _w : 10;
|
|
132
|
+
// Phase 2: Disabled state colors
|
|
133
|
+
const disabledTextColor = (_x = props.disabledTextColor) !== null && _x !== void 0 ? _x : '#AAAAAA';
|
|
134
|
+
const disabledTabFill = (_y = props.disabledTabFill) !== null && _y !== void 0 ? _y : '#F0F0F0';
|
|
135
|
+
const [currentIndex, setCurrentIndex] = (0, react_1.useState)(defaultTab);
|
|
136
|
+
// Resolve tab children by role (canonical pattern matching all other renderers)
|
|
137
|
+
const tabChildren = (0, react_1.useMemo)(() => {
|
|
138
|
+
return (component.children || [])
|
|
139
|
+
.filter(child => /^tab-\d+$/.test(child.role || ''))
|
|
140
|
+
.sort((a, b) => {
|
|
141
|
+
var _a, _b;
|
|
142
|
+
const aNum = parseInt(((_a = a.role) === null || _a === void 0 ? void 0 : _a.replace('tab-', '')) || '0');
|
|
143
|
+
const bNum = parseInt(((_b = b.role) === null || _b === void 0 ? void 0 : _b.replace('tab-', '')) || '0');
|
|
144
|
+
return aNum - bNum;
|
|
145
|
+
});
|
|
146
|
+
}, [component.children]);
|
|
147
|
+
// Get tab label from child properties (canonical: label → text → name)
|
|
148
|
+
const getTabLabel = (0, react_1.useCallback)((index) => {
|
|
149
|
+
var _a, _b, _c, _d, _e;
|
|
150
|
+
const child = tabChildren[index];
|
|
151
|
+
if (!child)
|
|
152
|
+
return `Tab ${index + 1}`;
|
|
153
|
+
return (_e = (_d = (_b = (_a = child.properties) === null || _a === void 0 ? void 0 : _a.label) !== null && _b !== void 0 ? _b : (_c = child.properties) === null || _c === void 0 ? void 0 : _c.text) !== null && _d !== void 0 ? _d : child.name) !== null && _e !== void 0 ? _e : `Tab ${index + 1}`;
|
|
154
|
+
}, [tabChildren]);
|
|
155
|
+
// Get tab icon from child properties
|
|
156
|
+
const getTabIcon = (0, react_1.useCallback)((index) => {
|
|
157
|
+
var _a;
|
|
158
|
+
const child = tabChildren[index];
|
|
159
|
+
const iconName = (_a = child === null || child === void 0 ? void 0 : child.properties) === null || _a === void 0 ? void 0 : _a.icon;
|
|
160
|
+
if (iconName && ICON_MAP[iconName.toLowerCase()]) {
|
|
161
|
+
return ICON_MAP[iconName.toLowerCase()];
|
|
162
|
+
}
|
|
163
|
+
return undefined;
|
|
164
|
+
}, [tabChildren]);
|
|
165
|
+
// Check if tab is disabled from child properties
|
|
166
|
+
const isTabDisabled = (0, react_1.useCallback)((index) => {
|
|
167
|
+
var _a, _b;
|
|
168
|
+
const child = tabChildren[index];
|
|
169
|
+
return (_b = (_a = child === null || child === void 0 ? void 0 : child.properties) === null || _a === void 0 ? void 0 : _a.disabled) !== null && _b !== void 0 ? _b : false;
|
|
170
|
+
}, [tabChildren]);
|
|
171
|
+
// Parse children to find content panels - filter by content-panel-X role and sort
|
|
172
|
+
const contentPanels = (0, react_1.useMemo)(() => {
|
|
173
|
+
const children = component.children || [];
|
|
174
|
+
return children
|
|
175
|
+
.filter(child => /^content-panel-\d+$/.test(child.role || ''))
|
|
176
|
+
.sort((a, b) => {
|
|
177
|
+
var _a, _b;
|
|
178
|
+
const aNum = parseInt(((_a = a.role) === null || _a === void 0 ? void 0 : _a.replace('content-panel-', '')) || '0');
|
|
179
|
+
const bNum = parseInt(((_b = b.role) === null || _b === void 0 ? void 0 : _b.replace('content-panel-', '')) || '0');
|
|
180
|
+
return aNum - bNum;
|
|
181
|
+
});
|
|
182
|
+
}, [component.children]);
|
|
183
|
+
// Update state manager
|
|
184
|
+
(0, react_1.useEffect)(() => {
|
|
185
|
+
if (stateManager) {
|
|
186
|
+
stateManager.updateState(`element:${component.id}.currentIndex`, currentIndex);
|
|
187
|
+
}
|
|
188
|
+
}, [component.id, currentIndex, stateManager]);
|
|
189
|
+
// Listen for external state changes
|
|
190
|
+
(0, react_1.useEffect)(() => {
|
|
191
|
+
if (!stateManager)
|
|
192
|
+
return;
|
|
193
|
+
const unsubscribe = stateManager.subscribeToState(`element:${component.id}.currentIndex`, (value) => {
|
|
194
|
+
if (typeof value === 'number' && value !== currentIndex) {
|
|
195
|
+
selectTab(value);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
return unsubscribe;
|
|
199
|
+
}, [component.id, currentIndex, stateManager]);
|
|
200
|
+
const selectTab = (0, react_1.useCallback)((index) => {
|
|
201
|
+
if (index < 0 || index >= tabCount)
|
|
202
|
+
return;
|
|
203
|
+
// Phase 2: Check if tab is disabled
|
|
204
|
+
if (isTabDisabled(index))
|
|
205
|
+
return;
|
|
206
|
+
const previousIndex = currentIndex;
|
|
207
|
+
const tabLabel = getTabLabel(index);
|
|
208
|
+
if (animated) {
|
|
209
|
+
react_native_1.LayoutAnimation.configureNext({
|
|
210
|
+
duration: animationDuration,
|
|
211
|
+
update: { type: react_native_1.LayoutAnimation.Types.easeInEaseOut },
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
setCurrentIndex(index);
|
|
215
|
+
// Phase 2: Fire tab change callback
|
|
216
|
+
onTabChange === null || onTabChange === void 0 ? void 0 : onTabChange(component.id, previousIndex, index, tabLabel);
|
|
217
|
+
}, [animated, animationDuration, tabCount, currentIndex, isTabDisabled, getTabLabel, onTabChange, component.id]);
|
|
218
|
+
// Content gap from containerLayout (matching web schema)
|
|
219
|
+
const contentGap = (_0 = (_z = component.containerLayout) === null || _z === void 0 ? void 0 : _z.gap) !== null && _0 !== void 0 ? _0 : 12;
|
|
220
|
+
// Phase 2: Get flex justification based on alignment
|
|
221
|
+
const getJustifyContent = () => {
|
|
222
|
+
switch (tabAlignment) {
|
|
223
|
+
case 'start': return 'flex-start';
|
|
224
|
+
case 'center': return 'center';
|
|
225
|
+
case 'end': return 'flex-end';
|
|
226
|
+
case 'stretch':
|
|
227
|
+
default: return 'flex-start';
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
// Variant-specific styles
|
|
231
|
+
const getTabListStyle = () => {
|
|
232
|
+
const baseStyle = {
|
|
233
|
+
backgroundColor: tabListBackgroundColor,
|
|
234
|
+
flexDirection: 'row',
|
|
235
|
+
padding: 4,
|
|
236
|
+
marginBottom: contentGap,
|
|
237
|
+
justifyContent: getJustifyContent(),
|
|
238
|
+
};
|
|
239
|
+
switch (variant) {
|
|
240
|
+
case 'underline':
|
|
241
|
+
return {
|
|
242
|
+
...baseStyle,
|
|
243
|
+
backgroundColor: 'transparent',
|
|
244
|
+
borderBottomWidth: 1,
|
|
245
|
+
borderBottomColor: '#e5e5e5',
|
|
246
|
+
padding: 0,
|
|
247
|
+
};
|
|
248
|
+
case 'boxed':
|
|
249
|
+
return {
|
|
250
|
+
...baseStyle,
|
|
251
|
+
borderRadius: tabBorderRadius,
|
|
252
|
+
borderWidth: 1,
|
|
253
|
+
borderColor: '#e5e5e5',
|
|
254
|
+
padding: 0,
|
|
255
|
+
};
|
|
256
|
+
default: // pills
|
|
257
|
+
return {
|
|
258
|
+
...baseStyle,
|
|
259
|
+
borderRadius: tabListBorderRadius,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
const getTabButtonStyle = (isActive, isDisabled) => {
|
|
264
|
+
// Phase 2: Determine width based on sizing mode
|
|
265
|
+
let widthStyle = {};
|
|
266
|
+
if (tabSizing === 'equal' && tabAlignment === 'stretch') {
|
|
267
|
+
widthStyle = { flex: 1 };
|
|
268
|
+
}
|
|
269
|
+
else if (tabSizing === 'fixed' && fixedTabWidth) {
|
|
270
|
+
widthStyle = { width: fixedTabWidth };
|
|
271
|
+
}
|
|
272
|
+
// Phase 2: Determine background color
|
|
273
|
+
const bgColor = isDisabled
|
|
274
|
+
? disabledTabFill
|
|
275
|
+
: (isActive ? activeTabColor : inactiveTabColor);
|
|
276
|
+
const baseStyle = {
|
|
277
|
+
...widthStyle,
|
|
278
|
+
paddingVertical: tabPaddingY,
|
|
279
|
+
paddingHorizontal: tabPaddingX,
|
|
280
|
+
alignItems: 'center',
|
|
281
|
+
justifyContent: 'center',
|
|
282
|
+
marginHorizontal: tabGap / 2,
|
|
283
|
+
opacity: isDisabled ? 0.5 : 1,
|
|
284
|
+
};
|
|
285
|
+
switch (variant) {
|
|
286
|
+
case 'underline':
|
|
287
|
+
return {
|
|
288
|
+
...baseStyle,
|
|
289
|
+
marginHorizontal: 0,
|
|
290
|
+
borderBottomWidth: isActive ? 2 : 0,
|
|
291
|
+
borderBottomColor: isActive ? activeTextColor : 'transparent',
|
|
292
|
+
};
|
|
293
|
+
case 'boxed':
|
|
294
|
+
return {
|
|
295
|
+
...baseStyle,
|
|
296
|
+
marginHorizontal: 0,
|
|
297
|
+
backgroundColor: bgColor,
|
|
298
|
+
};
|
|
299
|
+
default: // pills
|
|
300
|
+
return {
|
|
301
|
+
...baseStyle,
|
|
302
|
+
backgroundColor: bgColor,
|
|
303
|
+
borderRadius: tabBorderRadius,
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
const getTabTextStyle = (isActive, isDisabled) => {
|
|
308
|
+
const textColor = isDisabled
|
|
309
|
+
? disabledTextColor
|
|
310
|
+
: (isActive ? activeTextColor : inactiveTextColor);
|
|
311
|
+
return {
|
|
312
|
+
fontSize: tabFontSize,
|
|
313
|
+
fontWeight: isActive ? tabFontWeight : '500',
|
|
314
|
+
color: textColor,
|
|
315
|
+
};
|
|
316
|
+
};
|
|
317
|
+
// Phase 2: Render tab content with icon
|
|
318
|
+
const renderTabContent = (index, isActive, isDisabled) => {
|
|
319
|
+
const label = getTabLabel(index);
|
|
320
|
+
const icon = getTabIcon(index);
|
|
321
|
+
const textStyle = getTabTextStyle(isActive, isDisabled);
|
|
322
|
+
if (!icon || tabIconPosition === 'only') {
|
|
323
|
+
if (icon && tabIconPosition === 'only') {
|
|
324
|
+
return <react_native_1.Text style={[textStyle, { fontSize: tabFontSize + 4 }]}>{icon}</react_native_1.Text>;
|
|
325
|
+
}
|
|
326
|
+
return <react_native_1.Text style={textStyle}>{label}</react_native_1.Text>;
|
|
327
|
+
}
|
|
328
|
+
const iconElement = <react_native_1.Text style={[textStyle, { fontSize: tabFontSize + 2, marginHorizontal: 4 }]}>{icon}</react_native_1.Text>;
|
|
329
|
+
const labelElement = <react_native_1.Text style={textStyle}>{label}</react_native_1.Text>;
|
|
330
|
+
switch (tabIconPosition) {
|
|
331
|
+
case 'right':
|
|
332
|
+
return (<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
|
333
|
+
{labelElement}
|
|
334
|
+
{iconElement}
|
|
335
|
+
</react_native_1.View>);
|
|
336
|
+
case 'top':
|
|
337
|
+
return (<react_native_1.View style={{ alignItems: 'center' }}>
|
|
338
|
+
{iconElement}
|
|
339
|
+
{labelElement}
|
|
340
|
+
</react_native_1.View>);
|
|
341
|
+
case 'left':
|
|
342
|
+
default:
|
|
343
|
+
return (<react_native_1.View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
|
344
|
+
{iconElement}
|
|
345
|
+
{labelElement}
|
|
346
|
+
</react_native_1.View>);
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
// Render tab list
|
|
350
|
+
const renderTabList = () => {
|
|
351
|
+
const actualTabCount = tabChildren.length || tabCount;
|
|
352
|
+
const tabButtons = Array.from({ length: actualTabCount }, (_, index) => {
|
|
353
|
+
const isActive = index === currentIndex;
|
|
354
|
+
const disabled = isTabDisabled(index);
|
|
355
|
+
return (<react_1.default.Fragment key={index}>
|
|
356
|
+
<react_native_1.TouchableOpacity style={getTabButtonStyle(isActive, disabled)} onPress={() => selectTab(index)} activeOpacity={disabled ? 1 : 0.7} disabled={disabled}>
|
|
357
|
+
{renderTabContent(index, isActive, disabled)}
|
|
358
|
+
</react_native_1.TouchableOpacity>
|
|
359
|
+
{variant === 'boxed' && index < actualTabCount - 1 && (<react_native_1.View style={styles.boxedDivider}/>)}
|
|
360
|
+
</react_1.default.Fragment>);
|
|
361
|
+
});
|
|
362
|
+
const tabListStyle = getTabListStyle();
|
|
363
|
+
// Phase 2: Handle overflow behavior
|
|
364
|
+
if (overflowBehavior === 'scroll') {
|
|
365
|
+
return (<react_native_1.ScrollView horizontal showsHorizontalScrollIndicator={false} contentContainerStyle={tabListStyle}>
|
|
366
|
+
{tabButtons}
|
|
367
|
+
</react_native_1.ScrollView>);
|
|
368
|
+
}
|
|
369
|
+
return (<react_native_1.View style={tabListStyle}>
|
|
370
|
+
{tabButtons}
|
|
371
|
+
</react_native_1.View>);
|
|
372
|
+
};
|
|
373
|
+
// Render content panel - no fallback to first panel
|
|
374
|
+
const renderContentPanel = () => {
|
|
375
|
+
const panel = contentPanels[currentIndex];
|
|
376
|
+
if (!panel) {
|
|
377
|
+
// Empty placeholder matching web style
|
|
378
|
+
return (<react_native_1.View style={styles.emptyPlaceholder}>
|
|
379
|
+
<react_native_1.Text style={styles.emptyPlaceholderText}>
|
|
380
|
+
No content panel for Tab {currentIndex + 1}
|
|
381
|
+
</react_native_1.Text>
|
|
382
|
+
</react_native_1.View>);
|
|
383
|
+
}
|
|
384
|
+
return (<react_native_1.View style={styles.contentPanel}>
|
|
385
|
+
{renderChild(panel, currentIndex)}
|
|
386
|
+
</react_native_1.View>);
|
|
387
|
+
};
|
|
388
|
+
if (!((_1 = component.children) === null || _1 === void 0 ? void 0 : _1.length)) {
|
|
389
|
+
return (<react_native_1.View style={styles.emptyContainer}>
|
|
390
|
+
<react_native_1.Text style={styles.emptyText}>Add tabs to the component</react_native_1.Text>
|
|
391
|
+
</react_native_1.View>);
|
|
392
|
+
}
|
|
393
|
+
return (<react_native_1.View style={styles.container}>
|
|
394
|
+
{renderTabList()}
|
|
395
|
+
{renderContentPanel()}
|
|
396
|
+
</react_native_1.View>);
|
|
397
|
+
};
|
|
398
|
+
exports.TabsComponent = TabsComponent;
|
|
399
|
+
const styles = react_native_1.StyleSheet.create({
|
|
400
|
+
container: {
|
|
401
|
+
flex: 1,
|
|
402
|
+
},
|
|
403
|
+
contentPanel: {
|
|
404
|
+
flex: 1,
|
|
405
|
+
},
|
|
406
|
+
boxedDivider: {
|
|
407
|
+
width: 1,
|
|
408
|
+
backgroundColor: '#e5e5e5',
|
|
409
|
+
},
|
|
410
|
+
emptyContainer: {
|
|
411
|
+
padding: 32,
|
|
412
|
+
alignItems: 'center',
|
|
413
|
+
justifyContent: 'center',
|
|
414
|
+
},
|
|
415
|
+
emptyText: {
|
|
416
|
+
color: '#999',
|
|
417
|
+
fontSize: 14,
|
|
418
|
+
},
|
|
419
|
+
emptyPlaceholder: {
|
|
420
|
+
minHeight: 100,
|
|
421
|
+
backgroundColor: 'rgba(128, 128, 128, 0.1)',
|
|
422
|
+
borderRadius: 8,
|
|
423
|
+
padding: 16,
|
|
424
|
+
alignItems: 'center',
|
|
425
|
+
justifyContent: 'center',
|
|
426
|
+
},
|
|
427
|
+
emptyPlaceholderText: {
|
|
428
|
+
color: 'rgba(128, 128, 128, 0.6)',
|
|
429
|
+
fontSize: 14,
|
|
430
|
+
},
|
|
431
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TextInputComponent - React Native
|
|
3
|
+
*
|
|
4
|
+
* Form field for text/email/password input with validation.
|
|
5
|
+
* Features:
|
|
6
|
+
* - Multiple field types (text, email, password, phone, number)
|
|
7
|
+
* - Real-time validation
|
|
8
|
+
* - State manager integration for form data collection
|
|
9
|
+
*/
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import { PaywallComponent } from '../types';
|
|
12
|
+
interface TextInputComponentProps {
|
|
13
|
+
component: PaywallComponent;
|
|
14
|
+
stateManager?: any;
|
|
15
|
+
isPreviewMode?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare const TextInputComponent: React.FC<TextInputComponentProps>;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* TextInputComponent - React Native
|
|
4
|
+
*
|
|
5
|
+
* Form field for text/email/password input with validation.
|
|
6
|
+
* Features:
|
|
7
|
+
* - Multiple field types (text, email, password, phone, number)
|
|
8
|
+
* - Real-time validation
|
|
9
|
+
* - State manager integration for form data collection
|
|
10
|
+
*/
|
|
11
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
12
|
+
if (k2 === undefined) k2 = k;
|
|
13
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
14
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
15
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
16
|
+
}
|
|
17
|
+
Object.defineProperty(o, k2, desc);
|
|
18
|
+
}) : (function(o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
}));
|
|
22
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
23
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
24
|
+
}) : function(o, v) {
|
|
25
|
+
o["default"] = v;
|
|
26
|
+
});
|
|
27
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
28
|
+
var ownKeys = function(o) {
|
|
29
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
30
|
+
var ar = [];
|
|
31
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
32
|
+
return ar;
|
|
33
|
+
};
|
|
34
|
+
return ownKeys(o);
|
|
35
|
+
};
|
|
36
|
+
return function (mod) {
|
|
37
|
+
if (mod && mod.__esModule) return mod;
|
|
38
|
+
var result = {};
|
|
39
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
40
|
+
__setModuleDefault(result, mod);
|
|
41
|
+
return result;
|
|
42
|
+
};
|
|
43
|
+
})();
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.TextInputComponent = void 0;
|
|
46
|
+
const react_1 = __importStar(require("react"));
|
|
47
|
+
const react_native_1 = require("react-native");
|
|
48
|
+
// Validation patterns
|
|
49
|
+
const VALIDATION_PATTERNS = {
|
|
50
|
+
email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
|
|
51
|
+
phone: /^[\d\s\-+()]{7,20}$/,
|
|
52
|
+
url: /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/,
|
|
53
|
+
};
|
|
54
|
+
const TextInputComponent = ({ component, stateManager, isPreviewMode = false, }) => {
|
|
55
|
+
var _a;
|
|
56
|
+
const props = component.properties;
|
|
57
|
+
const componentId = component.id;
|
|
58
|
+
// Extract props
|
|
59
|
+
const fieldType = props.fieldType || 'text';
|
|
60
|
+
const placeholder = props.placeholder || 'Enter text...';
|
|
61
|
+
const label = props.label;
|
|
62
|
+
const helperText = props.helperText;
|
|
63
|
+
const defaultValue = props.defaultValue || '';
|
|
64
|
+
const required = props.required || false;
|
|
65
|
+
const minLength = props.minLength || 0;
|
|
66
|
+
const maxLength = props.maxLength || 255;
|
|
67
|
+
const fontSize = props.fontSize || 16;
|
|
68
|
+
const textColor = props.textColor || '#000000';
|
|
69
|
+
const placeholderColor = props.placeholderColor || '#9CA3AF';
|
|
70
|
+
const labelColor = props.labelColor || '#374151';
|
|
71
|
+
const errorColor = props.errorColor || '#EF4444';
|
|
72
|
+
const backgroundColor = ((_a = props.backgroundColor) === null || _a === void 0 ? void 0 : _a.color) || '#FFFFFF';
|
|
73
|
+
const borderColor = props.borderColor || '#D1D5DB';
|
|
74
|
+
const focusBorderColor = props.focusBorderColor || '#3B82F6';
|
|
75
|
+
const errorBorderColor = props.errorBorderColor || '#EF4444';
|
|
76
|
+
const borderRadius = props.borderRadius || 8;
|
|
77
|
+
const borderWidth = props.borderWidth || 1;
|
|
78
|
+
const inputHeight = props.inputHeight || 48;
|
|
79
|
+
const [value, setValue] = (0, react_1.useState)(defaultValue);
|
|
80
|
+
const [isFocused, setIsFocused] = (0, react_1.useState)(false);
|
|
81
|
+
const [showPassword, setShowPassword] = (0, react_1.useState)(false);
|
|
82
|
+
const [errors, setErrors] = (0, react_1.useState)([]);
|
|
83
|
+
const [touched, setTouched] = (0, react_1.useState)(false);
|
|
84
|
+
// Validate value
|
|
85
|
+
const validate = (0, react_1.useCallback)((val) => {
|
|
86
|
+
const validationErrors = [];
|
|
87
|
+
if (required && !val.trim()) {
|
|
88
|
+
validationErrors.push('This field is required');
|
|
89
|
+
}
|
|
90
|
+
if (val.length > 0 && minLength > 0 && val.length < minLength) {
|
|
91
|
+
validationErrors.push(`Must be at least ${minLength} characters`);
|
|
92
|
+
}
|
|
93
|
+
if (val.length > maxLength) {
|
|
94
|
+
validationErrors.push(`Must be less than ${maxLength} characters`);
|
|
95
|
+
}
|
|
96
|
+
if (fieldType === 'email' && val && !VALIDATION_PATTERNS.email.test(val)) {
|
|
97
|
+
validationErrors.push('Please enter a valid email address');
|
|
98
|
+
}
|
|
99
|
+
if (fieldType === 'phone' && val && !VALIDATION_PATTERNS.phone.test(val)) {
|
|
100
|
+
validationErrors.push('Please enter a valid phone number');
|
|
101
|
+
}
|
|
102
|
+
return validationErrors;
|
|
103
|
+
}, [required, minLength, maxLength, fieldType]);
|
|
104
|
+
// Update state manager when value changes
|
|
105
|
+
(0, react_1.useEffect)(() => {
|
|
106
|
+
if (stateManager) {
|
|
107
|
+
const validationErrors = validate(value);
|
|
108
|
+
const isValid = validationErrors.length === 0;
|
|
109
|
+
stateManager.updateState(`element:${componentId}.value`, value);
|
|
110
|
+
stateManager.updateState(`element:${componentId}.isValid`, isValid);
|
|
111
|
+
stateManager.updateState(`element:${componentId}.fieldData`, {
|
|
112
|
+
fieldId: componentId,
|
|
113
|
+
fieldType,
|
|
114
|
+
value,
|
|
115
|
+
isValid,
|
|
116
|
+
validationErrors,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}, [value, componentId, fieldType, stateManager, validate]);
|
|
120
|
+
// Subscribe to external state changes
|
|
121
|
+
(0, react_1.useEffect)(() => {
|
|
122
|
+
if (stateManager) {
|
|
123
|
+
return stateManager.subscribeToState(`element:${componentId}.value`, (newValue) => {
|
|
124
|
+
if (newValue !== value) {
|
|
125
|
+
setValue(newValue);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}, [componentId, stateManager, value]);
|
|
130
|
+
// Handle input change
|
|
131
|
+
const handleChange = (0, react_1.useCallback)((text) => {
|
|
132
|
+
setValue(text);
|
|
133
|
+
if (touched) {
|
|
134
|
+
setErrors(validate(text));
|
|
135
|
+
}
|
|
136
|
+
}, [touched, validate]);
|
|
137
|
+
// Handle blur
|
|
138
|
+
const handleBlur = (0, react_1.useCallback)(() => {
|
|
139
|
+
setIsFocused(false);
|
|
140
|
+
setTouched(true);
|
|
141
|
+
setErrors(validate(value));
|
|
142
|
+
}, [value, validate]);
|
|
143
|
+
// Determine keyboard type
|
|
144
|
+
const keyboardType = (0, react_1.useMemo)(() => {
|
|
145
|
+
switch (fieldType) {
|
|
146
|
+
case 'email': return 'email-address';
|
|
147
|
+
case 'phone': return 'phone-pad';
|
|
148
|
+
case 'number': return 'numeric';
|
|
149
|
+
default: return 'default';
|
|
150
|
+
}
|
|
151
|
+
}, [fieldType]);
|
|
152
|
+
// Current border color
|
|
153
|
+
const currentBorderColor = errors.length > 0 && touched
|
|
154
|
+
? errorBorderColor
|
|
155
|
+
: isFocused
|
|
156
|
+
? focusBorderColor
|
|
157
|
+
: borderColor;
|
|
158
|
+
const hasError = errors.length > 0 && touched;
|
|
159
|
+
return (<react_native_1.View style={styles.container}>
|
|
160
|
+
{/* Label */}
|
|
161
|
+
{label && (<react_native_1.Text style={[styles.label, { fontSize: fontSize - 2, color: labelColor }]}>
|
|
162
|
+
{label}
|
|
163
|
+
{required && <react_native_1.Text style={{ color: errorColor }}> *</react_native_1.Text>}
|
|
164
|
+
</react_native_1.Text>)}
|
|
165
|
+
|
|
166
|
+
{/* Input Container */}
|
|
167
|
+
<react_native_1.View style={styles.inputContainer}>
|
|
168
|
+
<react_native_1.TextInput value={value} onChangeText={handleChange} onFocus={() => setIsFocused(true)} onBlur={handleBlur} placeholder={placeholder} placeholderTextColor={placeholderColor} maxLength={maxLength} keyboardType={keyboardType} secureTextEntry={fieldType === 'password' && !showPassword} autoCapitalize={fieldType === 'email' ? 'none' : 'sentences'} autoCorrect={fieldType !== 'email' && fieldType !== 'password'} style={[
|
|
169
|
+
styles.input,
|
|
170
|
+
{
|
|
171
|
+
height: inputHeight,
|
|
172
|
+
fontSize,
|
|
173
|
+
color: textColor,
|
|
174
|
+
backgroundColor,
|
|
175
|
+
borderColor: currentBorderColor,
|
|
176
|
+
borderRadius,
|
|
177
|
+
borderWidth,
|
|
178
|
+
paddingRight: fieldType === 'password' ? 48 : 16,
|
|
179
|
+
},
|
|
180
|
+
]}/>
|
|
181
|
+
|
|
182
|
+
{/* Password Toggle */}
|
|
183
|
+
{fieldType === 'password' && (<react_native_1.TouchableOpacity style={styles.passwordToggle} onPress={() => setShowPassword(!showPassword)}>
|
|
184
|
+
<react_native_1.Text style={{ color: placeholderColor, fontSize: 12 }}>
|
|
185
|
+
{showPassword ? 'HIDE' : 'SHOW'}
|
|
186
|
+
</react_native_1.Text>
|
|
187
|
+
</react_native_1.TouchableOpacity>)}
|
|
188
|
+
</react_native_1.View>
|
|
189
|
+
|
|
190
|
+
{/* Helper Text / Error */}
|
|
191
|
+
{(helperText || hasError) && (<react_native_1.Text style={[
|
|
192
|
+
styles.helperText,
|
|
193
|
+
{
|
|
194
|
+
fontSize: fontSize - 4,
|
|
195
|
+
color: hasError ? errorColor : placeholderColor,
|
|
196
|
+
},
|
|
197
|
+
]}>
|
|
198
|
+
{hasError ? errors[0] : helperText}
|
|
199
|
+
</react_native_1.Text>)}
|
|
200
|
+
</react_native_1.View>);
|
|
201
|
+
};
|
|
202
|
+
exports.TextInputComponent = TextInputComponent;
|
|
203
|
+
const styles = react_native_1.StyleSheet.create({
|
|
204
|
+
container: {
|
|
205
|
+
width: '100%',
|
|
206
|
+
},
|
|
207
|
+
label: {
|
|
208
|
+
fontWeight: '500',
|
|
209
|
+
marginBottom: 6,
|
|
210
|
+
},
|
|
211
|
+
inputContainer: {
|
|
212
|
+
position: 'relative',
|
|
213
|
+
},
|
|
214
|
+
input: {
|
|
215
|
+
paddingHorizontal: 16,
|
|
216
|
+
},
|
|
217
|
+
passwordToggle: {
|
|
218
|
+
position: 'absolute',
|
|
219
|
+
right: 16,
|
|
220
|
+
top: 0,
|
|
221
|
+
bottom: 0,
|
|
222
|
+
justifyContent: 'center',
|
|
223
|
+
},
|
|
224
|
+
helperText: {
|
|
225
|
+
marginTop: 4,
|
|
226
|
+
},
|
|
227
|
+
});
|