@umituz/react-native-subscription 2.3.4 → 2.3.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-subscription",
3
- "version": "2.3.4",
3
+ "version": "2.3.6",
4
4
  "description": "Complete subscription management with RevenueCat, paywall UI, and credits system for React Native apps",
5
5
  "main": "./src/index.ts",
6
6
  "types": "./src/index.ts",
package/src/index.ts CHANGED
@@ -66,15 +66,9 @@ export {
66
66
  export {
67
67
  SubscriptionModal,
68
68
  type SubscriptionModalProps,
69
- type SubscriptionModalStyles,
70
69
  } from "./presentation/components/paywall/SubscriptionModal";
71
70
 
72
71
  export { SubscriptionModalHeader } from "./presentation/components/paywall/SubscriptionModalHeader";
73
- export {
74
- SubscriptionModalOverlay,
75
- type SubscriptionModalVariant,
76
- type ModalLayoutConfig,
77
- } from "./presentation/components/paywall/SubscriptionModalOverlay";
78
72
 
79
73
  export { SubscriptionPlanCard } from "./presentation/components/paywall/SubscriptionPlanCard";
80
74
  export { PaywallFeaturesList } from "./presentation/components/paywall/PaywallFeaturesList";
@@ -83,7 +77,6 @@ export { PaywallLegalFooter } from "./presentation/components/paywall/PaywallLeg
83
77
  export {
84
78
  PaywallModal,
85
79
  type PaywallModalProps,
86
- type PaywallModalStyles,
87
80
  } from "./presentation/components/paywall/PaywallModal";
88
81
 
89
82
  // =============================================================================
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * Paywall Modal Component
3
- * Single Responsibility: Display paywall with Credits and Subscription tabs
3
+ * Displays paywall with Credits and Subscription tabs
4
4
  */
5
5
 
6
6
  import React, { useEffect } from "react";
7
- import { View, Modal, StyleSheet, TouchableOpacity, Dimensions } from "react-native";
8
- import { useAppDesignTokens } from "@umituz/react-native-design-system";
7
+ import { View, StyleSheet } from "react-native";
8
+ import { useAppDesignTokens, BaseModal, useResponsive } from "@umituz/react-native-design-system";
9
9
  import { useLocalization } from "@umituz/react-native-localization";
10
10
  import type { PurchasesPackage } from "react-native-purchases";
11
11
  import { usePaywall } from "../../hooks/usePaywall";
@@ -13,33 +13,15 @@ import { PaywallHeader } from "./PaywallHeader";
13
13
  import { PaywallTabBar } from "./PaywallTabBar";
14
14
  import { CreditsTabContent } from "./CreditsTabContent";
15
15
  import { SubscriptionTabContent } from "./SubscriptionTabContent";
16
- import { ModalLayoutConfig } from "./SubscriptionModalOverlay";
17
16
  import type { PaywallTabType } from "../../../domain/entities/paywall/PaywallTab";
18
17
  import type { CreditsPackage } from "../../../domain/entities/paywall/CreditsPackage";
19
18
 
20
- const { height: SCREEN_HEIGHT } = Dimensions.get("window");
21
-
22
19
  export interface PaywallModalStyles {
23
20
  headerTopPadding?: number;
24
21
  contentHorizontalPadding?: number;
25
22
  contentBottomPadding?: number;
26
23
  }
27
24
 
28
- const DEFAULT_LAYOUT: ModalLayoutConfig = {
29
- maxWidth: 480,
30
- maxHeightPercent: 0.88,
31
- widthPercent: 0.92,
32
- borderRadius: 32,
33
- backdropOpacity: 0.85,
34
- horizontalPadding: 20,
35
- };
36
-
37
- const DEFAULT_STYLES: PaywallModalStyles = {
38
- headerTopPadding: 48,
39
- contentHorizontalPadding: 24,
40
- contentBottomPadding: 32,
41
- };
42
-
43
25
  export interface PaywallModalProps {
44
26
  visible: boolean;
45
27
  onClose: () => void;
@@ -60,167 +42,125 @@ export interface PaywallModalProps {
60
42
  privacyText?: string;
61
43
  termsOfServiceText?: string;
62
44
  restoreButtonText?: string;
63
- layoutConfig?: ModalLayoutConfig;
64
- styleConfig?: PaywallModalStyles;
65
45
  }
66
46
 
67
- export const PaywallModal: React.FC<PaywallModalProps> = React.memo(
68
- (props) => {
69
- const {
70
- visible,
71
- onClose,
72
- initialTab = "credits",
73
- creditsPackages,
74
- subscriptionPackages,
75
- currentCredits,
76
- requiredCredits,
77
- onCreditsPurchase,
78
- onSubscriptionPurchase,
79
- onRestore,
80
- subscriptionFeatures = [],
81
- isLoading = false,
82
- title,
83
- subtitle,
84
- privacyUrl,
85
- termsUrl,
86
- privacyText,
87
- termsOfServiceText,
88
- restoreButtonText,
89
- layoutConfig,
90
- styleConfig,
91
- } = props;
92
-
93
- const tokens = useAppDesignTokens();
94
- const { t } = useLocalization();
95
- const config = { ...DEFAULT_LAYOUT, ...layoutConfig };
96
- const styles_ = { ...DEFAULT_STYLES, ...styleConfig };
97
-
98
- const {
99
- activeTab,
100
- selectedCreditsPackageId,
101
- selectedSubscriptionPkg,
102
- handleTabChange,
103
- handleCreditsPackageSelect,
104
- handleSubscriptionPackageSelect,
105
- handleCreditsPurchase,
106
- handleSubscriptionPurchase,
107
- } = usePaywall({
108
- initialTab,
109
- onCreditsPurchase,
110
- onSubscriptionPurchase,
111
- });
112
-
113
- const displayTitle = title || t("paywall.title");
114
- const displaySubtitle = subtitle || t("paywall.subtitle");
115
-
116
- useEffect(() => {
117
- if (__DEV__) {
118
- console.log("[PaywallModal] Visibility changed:", visible);
119
- }
120
- }, [visible]);
121
-
122
- if (!visible) return null;
123
-
124
- return (
125
- <Modal
126
- visible={visible}
127
- transparent
128
- animationType="fade"
129
- onRequestClose={onClose}
130
- >
131
- <View style={[styles.overlay, { paddingHorizontal: config.horizontalPadding }]}>
132
- <TouchableOpacity
133
- style={[
134
- styles.backdrop,
135
- { backgroundColor: `rgba(0, 0, 0, ${config.backdropOpacity ?? 0.85})` }
136
- ]}
137
- activeOpacity={1}
138
- onPress={onClose}
139
- />
140
- <View
141
- style={[
142
- styles.content,
143
- {
144
- backgroundColor: tokens.colors.surface,
145
- borderRadius: config.borderRadius ?? 32,
146
- maxHeight: SCREEN_HEIGHT * (config.maxHeightPercent ?? 0.88),
147
- height: SCREEN_HEIGHT * (config.maxHeightPercent ?? 0.88), // Explicit height to prevent collapse
148
- width: `${(config.widthPercent ?? 0.92) * 100}%`,
149
- maxWidth: config.maxWidth ?? 480,
150
- }
151
- ]}
152
- >
153
- <View style={[styles.contentInner, { paddingTop: styles_.headerTopPadding }]}>
154
- <PaywallHeader
155
- title={displayTitle}
156
- subtitle={displaySubtitle}
157
- onClose={onClose}
158
- variant="fullscreen"
159
- />
160
-
161
- <PaywallTabBar
162
- activeTab={activeTab}
163
- onTabChange={handleTabChange}
164
- creditsLabel={t("paywall.tabs.credits")}
165
- subscriptionLabel={t("paywall.tabs.subscription")}
166
- />
167
-
168
- <View style={{ flex: 1 }}>
169
- {activeTab === "credits" ? (
170
- <CreditsTabContent
171
- packages={creditsPackages}
172
- selectedPackageId={selectedCreditsPackageId}
173
- onSelectPackage={handleCreditsPackageSelect}
174
- onPurchase={handleCreditsPurchase}
175
- currentCredits={currentCredits}
176
- requiredCredits={requiredCredits}
177
- isLoading={isLoading}
178
- purchaseButtonText={t("paywall.purchase")}
179
- />
180
- ) : (
181
- <SubscriptionTabContent
182
- packages={subscriptionPackages}
183
- selectedPackage={selectedSubscriptionPkg}
184
- onSelectPackage={handleSubscriptionPackageSelect}
185
- onPurchase={handleSubscriptionPurchase}
186
- features={subscriptionFeatures}
187
- isLoading={isLoading}
188
- purchaseButtonText={t("paywall.subscribe")}
189
- onRestore={onRestore}
190
- privacyUrl={privacyUrl}
191
- termsUrl={termsUrl}
192
- privacyText={privacyText}
193
- termsOfServiceText={termsOfServiceText}
194
- restoreButtonText={restoreButtonText}
195
- />
196
- )}
197
- </View>
198
- </View>
199
- </View>
47
+ export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
48
+ const {
49
+ visible,
50
+ onClose,
51
+ initialTab = "credits",
52
+ creditsPackages,
53
+ subscriptionPackages,
54
+ currentCredits,
55
+ requiredCredits,
56
+ onCreditsPurchase,
57
+ onSubscriptionPurchase,
58
+ onRestore,
59
+ subscriptionFeatures = [],
60
+ isLoading = false,
61
+ title,
62
+ subtitle,
63
+ privacyUrl,
64
+ termsUrl,
65
+ privacyText,
66
+ termsOfServiceText,
67
+ restoreButtonText,
68
+ } = props;
69
+
70
+ const tokens = useAppDesignTokens();
71
+ const { t } = useLocalization();
72
+ const { modalLayout } = useResponsive();
73
+
74
+ const {
75
+ activeTab,
76
+ selectedCreditsPackageId,
77
+ selectedSubscriptionPkg,
78
+ handleTabChange,
79
+ handleCreditsPackageSelect,
80
+ handleSubscriptionPackageSelect,
81
+ handleCreditsPurchase,
82
+ handleSubscriptionPurchase,
83
+ } = usePaywall({
84
+ initialTab,
85
+ onCreditsPurchase,
86
+ onSubscriptionPurchase,
87
+ });
88
+
89
+ const displayTitle = title || t("paywall.title");
90
+ const displaySubtitle = subtitle || t("paywall.subtitle");
91
+
92
+ useEffect(() => {
93
+ if (__DEV__) {
94
+ console.log("[PaywallModal] State:", {
95
+ visible,
96
+ activeTab,
97
+ modalLayout,
98
+ creditsPackagesCount: creditsPackages?.length ?? 0,
99
+ subscriptionPackagesCount: subscriptionPackages?.length ?? 0,
100
+ });
101
+ }
102
+ }, [visible, activeTab, modalLayout, creditsPackages?.length, subscriptionPackages?.length]);
103
+
104
+ return (
105
+ <BaseModal visible={visible} onClose={onClose}>
106
+ <View style={styles.container}>
107
+ <PaywallHeader
108
+ title={displayTitle}
109
+ subtitle={displaySubtitle}
110
+ onClose={onClose}
111
+ variant="fullscreen"
112
+ />
113
+
114
+ <PaywallTabBar
115
+ activeTab={activeTab}
116
+ onTabChange={handleTabChange}
117
+ creditsLabel={t("paywall.tabs.credits")}
118
+ subscriptionLabel={t("paywall.tabs.subscription")}
119
+ />
120
+
121
+ <View style={styles.tabContent}>
122
+ {activeTab === "credits" ? (
123
+ <CreditsTabContent
124
+ packages={creditsPackages}
125
+ selectedPackageId={selectedCreditsPackageId}
126
+ onSelectPackage={handleCreditsPackageSelect}
127
+ onPurchase={handleCreditsPurchase}
128
+ currentCredits={currentCredits}
129
+ requiredCredits={requiredCredits}
130
+ isLoading={isLoading}
131
+ purchaseButtonText={t("paywall.purchase")}
132
+ />
133
+ ) : (
134
+ <SubscriptionTabContent
135
+ packages={subscriptionPackages}
136
+ selectedPackage={selectedSubscriptionPkg}
137
+ onSelectPackage={handleSubscriptionPackageSelect}
138
+ onPurchase={handleSubscriptionPurchase}
139
+ features={subscriptionFeatures}
140
+ isLoading={isLoading}
141
+ purchaseButtonText={t("paywall.subscribe")}
142
+ onRestore={onRestore}
143
+ privacyUrl={privacyUrl}
144
+ termsUrl={termsUrl}
145
+ privacyText={privacyText}
146
+ termsOfServiceText={termsOfServiceText}
147
+ restoreButtonText={restoreButtonText}
148
+ />
149
+ )}
200
150
  </View>
201
- </Modal>
202
- );
203
- },
204
- );
151
+ </View>
152
+ </BaseModal>
153
+ );
154
+ });
205
155
 
206
156
  PaywallModal.displayName = "PaywallModal";
207
157
 
208
158
  const styles = StyleSheet.create({
209
- overlay: {
159
+ container: {
210
160
  flex: 1,
211
- justifyContent: "center",
212
- alignItems: "center",
213
- },
214
- backdrop: {
215
- ...StyleSheet.absoluteFillObject,
216
- },
217
- content: {
218
- overflow: "hidden",
219
- borderWidth: 1,
220
- borderColor: "rgba(255, 255, 255, 0.08)",
161
+ width: "100%",
221
162
  },
222
- contentInner: {
163
+ tabContent: {
223
164
  flex: 1,
224
- paddingBottom: 20,
225
165
  },
226
166
  });
@@ -1,30 +1,19 @@
1
1
  /**
2
2
  * Subscription Modal Component
3
- * Orchestrates subscription flow using decomposed components
3
+ * Fullscreen subscription flow using BaseModal from design system
4
4
  */
5
5
 
6
6
  import React from "react";
7
7
  import { View, StyleSheet, ScrollView } from "react-native";
8
- import { useAppDesignTokens } from "@umituz/react-native-design-system";
8
+ import { useAppDesignTokens, BaseModal, useResponsive } from "@umituz/react-native-design-system";
9
9
  import type { PurchasesPackage } from "react-native-purchases";
10
10
 
11
11
  import { SubscriptionModalHeader } from "./SubscriptionModalHeader";
12
- import {
13
- SubscriptionModalOverlay,
14
- SubscriptionModalVariant,
15
- ModalLayoutConfig,
16
- } from "./SubscriptionModalOverlay";
17
12
  import { PaywallFeaturesList } from "./PaywallFeaturesList";
18
13
  import { SubscriptionPackageList } from "./SubscriptionPackageList";
19
14
  import { SubscriptionFooter } from "./SubscriptionFooter";
20
15
  import { useSubscriptionModal } from "../../hooks/useSubscriptionModal";
21
16
 
22
- export interface SubscriptionModalStyles {
23
- headerTopPadding?: number;
24
- contentHorizontalPadding?: number;
25
- contentBottomPadding?: number;
26
- }
27
-
28
17
  export interface SubscriptionModalProps {
29
18
  visible: boolean;
30
19
  onClose: () => void;
@@ -45,17 +34,8 @@ export interface SubscriptionModalProps {
45
34
  privacyText?: string;
46
35
  termsOfServiceText?: string;
47
36
  showRestoreButton?: boolean;
48
- variant?: SubscriptionModalVariant;
49
- layoutConfig?: ModalLayoutConfig;
50
- styleConfig?: SubscriptionModalStyles;
51
37
  }
52
38
 
53
- const DEFAULT_STYLES: SubscriptionModalStyles = {
54
- headerTopPadding: 48,
55
- contentHorizontalPadding: 24,
56
- contentBottomPadding: 32,
57
- };
58
-
59
39
  export const SubscriptionModal: React.FC<SubscriptionModalProps> = React.memo((props) => {
60
40
  const {
61
41
  visible,
@@ -77,13 +57,10 @@ export const SubscriptionModal: React.FC<SubscriptionModalProps> = React.memo((p
77
57
  privacyText,
78
58
  termsOfServiceText,
79
59
  showRestoreButton = true,
80
- variant = "bottom-sheet",
81
- layoutConfig,
82
- styleConfig,
83
60
  } = props;
84
61
 
85
62
  const tokens = useAppDesignTokens();
86
- const styles_ = { ...DEFAULT_STYLES, ...styleConfig };
63
+ const { modalLayout } = useResponsive();
87
64
 
88
65
  const {
89
66
  selectedPkg,
@@ -97,55 +74,32 @@ export const SubscriptionModal: React.FC<SubscriptionModalProps> = React.memo((p
97
74
  onClose,
98
75
  });
99
76
 
100
- // Debug logging in development
101
77
  if (__DEV__) {
102
78
  console.log("[SubscriptionModal] State:", {
103
79
  visible,
104
- variant,
105
80
  isLoading,
106
81
  packagesCount: packages?.length ?? 0,
107
- packagesData: packages?.map(p => ({
108
- id: p?.identifier,
109
- price: p?.product?.priceString,
110
- title: p?.product?.title,
111
- })),
112
- featuresCount: features?.length ?? 0,
113
- title,
114
- subtitle: subtitle?.substring(0, 50),
115
- hasTokens: !!tokens,
82
+ modalLayout,
116
83
  selectedPkg: selectedPkg?.identifier ?? null,
117
84
  isProcessing,
118
85
  });
119
86
  }
120
87
 
121
- if (!visible) return null;
122
-
123
- const isFullscreen = variant === "fullscreen";
124
- const containerPaddingTop = isFullscreen ? styles_.headerTopPadding : 0;
125
-
126
88
  return (
127
- <SubscriptionModalOverlay
128
- visible={visible}
129
- onClose={onClose}
130
- variant={variant}
131
- layoutConfig={layoutConfig}
132
- >
133
- <View style={[styles.container, { paddingTop: containerPaddingTop }]}>
89
+ <BaseModal visible={visible} onClose={onClose}>
90
+ <View style={styles.container}>
134
91
  <SubscriptionModalHeader
135
92
  title={title}
136
93
  subtitle={subtitle}
137
94
  onClose={onClose}
138
- variant={variant}
95
+ variant="fullscreen"
139
96
  />
140
97
 
141
98
  <ScrollView
142
99
  style={styles.scrollView}
143
100
  contentContainerStyle={[
144
101
  styles.scrollContent,
145
- {
146
- paddingHorizontal: styles_.contentHorizontalPadding,
147
- paddingBottom: styles_.contentBottomPadding,
148
- }
102
+ { paddingHorizontal: modalLayout.horizontalPadding }
149
103
  ]}
150
104
  showsVerticalScrollIndicator={false}
151
105
  bounces={false}
@@ -160,7 +114,15 @@ export const SubscriptionModal: React.FC<SubscriptionModalProps> = React.memo((p
160
114
  />
161
115
 
162
116
  {features.length > 0 && (
163
- <View style={[styles.featuresSection, { backgroundColor: tokens.colors.surfaceSecondary }]}>
117
+ <View
118
+ style={[
119
+ styles.featuresSection,
120
+ {
121
+ backgroundColor: tokens.colors.surfaceSecondary,
122
+ borderColor: tokens.colors.border
123
+ }
124
+ ]}
125
+ >
164
126
  <PaywallFeaturesList features={features} gap={12} />
165
127
  </View>
166
128
  )}
@@ -183,7 +145,7 @@ export const SubscriptionModal: React.FC<SubscriptionModalProps> = React.memo((p
183
145
  onRestore={handleRestore}
184
146
  />
185
147
  </View>
186
- </SubscriptionModalOverlay>
148
+ </BaseModal>
187
149
  );
188
150
  });
189
151
 
@@ -196,16 +158,15 @@ const styles = StyleSheet.create({
196
158
  },
197
159
  scrollView: {
198
160
  flex: 1,
199
- width: "100%",
200
161
  },
201
162
  scrollContent: {
202
163
  flexGrow: 1,
164
+ paddingBottom: 32,
203
165
  },
204
166
  featuresSection: {
205
167
  borderRadius: 24,
206
168
  padding: 24,
207
169
  marginTop: 12,
208
170
  borderWidth: 1,
209
- borderColor: "rgba(255, 255, 255, 0.05)",
210
171
  },
211
172
  });
@@ -1,179 +0,0 @@
1
- /**
2
- * Subscription Modal Overlay Component
3
- * Handles the Modal wrapper and backdrop logic for different variants
4
- */
5
-
6
- import React from "react";
7
- import {
8
- View,
9
- Modal,
10
- StyleSheet,
11
- TouchableOpacity,
12
- Dimensions,
13
- ViewStyle,
14
- } from "react-native";
15
- import { useAppDesignTokens } from "@umituz/react-native-design-system";
16
-
17
- const { height: SCREEN_HEIGHT, width: SCREEN_WIDTH } = Dimensions.get("window");
18
-
19
- export type SubscriptionModalVariant = "bottom-sheet" | "fullscreen" | "dialog";
20
-
21
- export interface ModalLayoutConfig {
22
- maxWidth?: number;
23
- maxHeightPercent?: number;
24
- widthPercent?: number;
25
- borderRadius?: number;
26
- backdropOpacity?: number;
27
- horizontalPadding?: number;
28
- }
29
-
30
- const DEFAULT_LAYOUT: ModalLayoutConfig = {
31
- maxWidth: 480,
32
- maxHeightPercent: 0.88,
33
- widthPercent: 0.92,
34
- borderRadius: 32,
35
- backdropOpacity: 0.85,
36
- horizontalPadding: 20,
37
- };
38
-
39
- interface SubscriptionModalOverlayProps {
40
- visible: boolean;
41
- onClose: () => void;
42
- children: React.ReactNode;
43
- variant: SubscriptionModalVariant;
44
- layoutConfig?: ModalLayoutConfig;
45
- }
46
-
47
- export const SubscriptionModalOverlay: React.FC<SubscriptionModalOverlayProps> = ({
48
- visible,
49
- onClose,
50
- children,
51
- variant,
52
- layoutConfig,
53
- }) => {
54
- const tokens = useAppDesignTokens();
55
- const config = { ...DEFAULT_LAYOUT, ...layoutConfig };
56
-
57
- // Debug logging in development
58
- if (__DEV__) {
59
- console.log("[SubscriptionModalOverlay] State:", {
60
- visible,
61
- variant,
62
- config,
63
- screenWidth: SCREEN_WIDTH,
64
- screenHeight: SCREEN_HEIGHT,
65
- backgroundColor: tokens?.colors?.backgroundPrimary ?? "NO_TOKEN",
66
- hasChildren: !!children,
67
- });
68
- }
69
-
70
- const isFullScreen = variant === "fullscreen";
71
-
72
- const getFullscreenContentStyle = (): ViewStyle => {
73
- const width = Math.min(SCREEN_WIDTH * (config.widthPercent ?? 0.92), config.maxWidth ?? 480);
74
- const height = SCREEN_HEIGHT * (config.maxHeightPercent ?? 0.88);
75
-
76
- if (__DEV__) {
77
- console.log("[SubscriptionModalOverlay] Content dimensions:", { width, height });
78
- }
79
-
80
- return {
81
- width,
82
- height, // Changed from maxHeight to height - this is critical!
83
- borderRadius: config.borderRadius ?? 32,
84
- overflow: "hidden",
85
- borderWidth: 2,
86
- borderColor: "rgba(255, 255, 255, 0.15)",
87
- backgroundColor: tokens.colors.backgroundPrimary,
88
- };
89
- };
90
-
91
- if (isFullScreen) {
92
- return (
93
- <Modal
94
- visible={visible}
95
- transparent
96
- animationType="fade"
97
- onRequestClose={onClose}
98
- >
99
- <View style={[styles.fullscreenOverlay, { paddingHorizontal: config.horizontalPadding }]}>
100
- <TouchableOpacity
101
- style={[
102
- styles.fullscreenBackdrop,
103
- { backgroundColor: `rgba(0, 0, 0, ${config.backdropOpacity ?? 0.85})` }
104
- ]}
105
- activeOpacity={1}
106
- onPress={onClose}
107
- />
108
- <View style={getFullscreenContentStyle()}>
109
- {children}
110
- </View>
111
- </View>
112
- </Modal>
113
- );
114
- }
115
-
116
- return (
117
- <Modal
118
- visible={visible}
119
- transparent
120
- animationType="fade"
121
- onRequestClose={onClose}
122
- >
123
- <View style={[styles.overlay, variant === "dialog" && styles.overlayCentered]}>
124
- <TouchableOpacity
125
- style={styles.backdrop}
126
- activeOpacity={1}
127
- onPress={onClose}
128
- />
129
- <View
130
- style={[
131
- variant === "bottom-sheet" ? styles.bottomSheet : styles.dialog,
132
- { backgroundColor: tokens.colors.surface }
133
- ]}
134
- >
135
- {children}
136
- </View>
137
- </View>
138
- </Modal>
139
- );
140
- };
141
-
142
- const styles = StyleSheet.create({
143
- overlay: {
144
- flex: 1,
145
- justifyContent: "flex-end",
146
- },
147
- overlayCentered: {
148
- justifyContent: "center",
149
- paddingHorizontal: 20,
150
- },
151
- backdrop: {
152
- ...StyleSheet.absoluteFillObject,
153
- backgroundColor: "rgba(0, 0, 0, 0.6)",
154
- },
155
- fullscreenOverlay: {
156
- flex: 1,
157
- justifyContent: "center",
158
- alignItems: "center",
159
- },
160
- fullscreenBackdrop: {
161
- ...StyleSheet.absoluteFillObject,
162
- },
163
- bottomSheet: {
164
- borderTopLeftRadius: 32,
165
- borderTopRightRadius: 32,
166
- maxHeight: SCREEN_HEIGHT * 0.9,
167
- minHeight: 400,
168
- width: "100%",
169
- },
170
- dialog: {
171
- alignSelf: "center",
172
- width: Math.min(SCREEN_WIDTH * 0.94, 500),
173
- maxHeight: SCREEN_HEIGHT * 0.85,
174
- borderRadius: 32,
175
- overflow: "hidden",
176
- borderWidth: 1,
177
- borderColor: "rgba(255, 255, 255, 0.1)",
178
- },
179
- });