@umituz/react-native-subscription 2.2.18 → 2.2.20
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.2.
|
|
3
|
+
"version": "2.2.20",
|
|
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",
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
StyleSheet,
|
|
11
11
|
TouchableOpacity,
|
|
12
12
|
ScrollView,
|
|
13
|
+
Dimensions,
|
|
13
14
|
} from "react-native";
|
|
14
15
|
import { SafeAreaView } from "react-native-safe-area-context";
|
|
15
16
|
import type { PurchasesPackage } from "react-native-purchases";
|
|
@@ -19,6 +20,8 @@ import { PaywallFeaturesList } from "./PaywallFeaturesList";
|
|
|
19
20
|
import { SubscriptionPackageList } from "./SubscriptionPackageList";
|
|
20
21
|
import { SubscriptionFooter } from "./SubscriptionFooter";
|
|
21
22
|
|
|
23
|
+
const { height: SCREEN_HEIGHT } = Dimensions.get("window");
|
|
24
|
+
|
|
22
25
|
export interface SubscriptionModalProps {
|
|
23
26
|
visible: boolean;
|
|
24
27
|
onClose: () => void;
|
|
@@ -97,93 +100,108 @@ export const SubscriptionModal: React.FC<SubscriptionModalProps> = React.memo(
|
|
|
97
100
|
|
|
98
101
|
const isFullScreen = variant === "fullscreen";
|
|
99
102
|
|
|
103
|
+
// Fullscreen variant uses SafeAreaView, bottom-sheet uses regular View
|
|
100
104
|
const ContentWrapper = isFullScreen ? SafeAreaView : View;
|
|
101
105
|
const wrapperProps = isFullScreen ? { edges: ["top", "bottom"] as const } : {};
|
|
102
106
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
style={
|
|
107
|
+
// Scrollable content (packages + features)
|
|
108
|
+
const ScrollContent = (
|
|
109
|
+
<ScrollView
|
|
110
|
+
style={styles.scrollView}
|
|
111
|
+
contentContainerStyle={styles.scrollContent}
|
|
112
|
+
showsVerticalScrollIndicator={false}
|
|
113
|
+
bounces={false}
|
|
107
114
|
>
|
|
108
|
-
<
|
|
109
|
-
|
|
110
|
-
<AtomicText style={[styles.closeIcon, { color: tokens.colors.textSecondary }]}>
|
|
111
|
-
×
|
|
112
|
-
</AtomicText>
|
|
113
|
-
</TouchableOpacity>
|
|
114
|
-
<AtomicText
|
|
115
|
-
type="headlineMedium"
|
|
116
|
-
style={[styles.title, { color: tokens.colors.textPrimary }]}
|
|
117
|
-
>
|
|
118
|
-
{title}
|
|
119
|
-
</AtomicText>
|
|
120
|
-
{subtitle && (
|
|
121
|
-
<AtomicText
|
|
122
|
-
type="bodyMedium"
|
|
123
|
-
style={[styles.subtitle, { color: tokens.colors.textSecondary }]}
|
|
124
|
-
>
|
|
125
|
-
{subtitle}
|
|
126
|
-
</AtomicText>
|
|
127
|
-
)}
|
|
128
|
-
</View>
|
|
129
|
-
|
|
130
|
-
<ScrollView
|
|
131
|
-
style={isFullScreen ? styles.scrollViewFullScreen : styles.scrollViewBottomSheet}
|
|
132
|
-
contentContainerStyle={styles.scrollContent}
|
|
133
|
-
>
|
|
134
|
-
<SubscriptionPackageList
|
|
135
|
-
packages={packages}
|
|
136
|
-
isLoading={isLoading}
|
|
137
|
-
selectedPkg={selectedPkg}
|
|
138
|
-
onSelect={setSelectedPkg}
|
|
139
|
-
loadingText={loadingText}
|
|
140
|
-
emptyText={emptyText}
|
|
141
|
-
/>
|
|
142
|
-
{features.length > 0 && (
|
|
143
|
-
<View style={[styles.featuresSection, { backgroundColor: tokens.colors.surfaceSecondary }]}>
|
|
144
|
-
<PaywallFeaturesList features={features} gap={12} />
|
|
145
|
-
</View>
|
|
146
|
-
)}
|
|
147
|
-
</ScrollView>
|
|
148
|
-
|
|
149
|
-
<SubscriptionFooter
|
|
150
|
-
isProcessing={isProcessing}
|
|
115
|
+
<SubscriptionPackageList
|
|
116
|
+
packages={packages}
|
|
151
117
|
isLoading={isLoading}
|
|
152
|
-
processingText={processingText}
|
|
153
|
-
purchaseButtonText={purchaseButtonText}
|
|
154
|
-
hasPackages={packages.length > 0}
|
|
155
118
|
selectedPkg={selectedPkg}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
termsUrl={termsUrl}
|
|
160
|
-
privacyText={privacyText}
|
|
161
|
-
termsOfServiceText={termsOfServiceText}
|
|
162
|
-
onPurchase={handlePurchase}
|
|
163
|
-
onRestore={handleRestore}
|
|
119
|
+
onSelect={setSelectedPkg}
|
|
120
|
+
loadingText={loadingText}
|
|
121
|
+
emptyText={emptyText}
|
|
164
122
|
/>
|
|
165
|
-
|
|
123
|
+
{features.length > 0 && (
|
|
124
|
+
<View style={[styles.featuresSection, { backgroundColor: tokens.colors.surfaceSecondary }]}>
|
|
125
|
+
<PaywallFeaturesList features={features} gap={12} />
|
|
126
|
+
</View>
|
|
127
|
+
)}
|
|
128
|
+
</ScrollView>
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
// Footer with buttons and legal links
|
|
132
|
+
const Footer = (
|
|
133
|
+
<SubscriptionFooter
|
|
134
|
+
isProcessing={isProcessing}
|
|
135
|
+
isLoading={isLoading}
|
|
136
|
+
processingText={processingText}
|
|
137
|
+
purchaseButtonText={purchaseButtonText}
|
|
138
|
+
hasPackages={packages.length > 0}
|
|
139
|
+
selectedPkg={selectedPkg}
|
|
140
|
+
restoreButtonText={restoreButtonText}
|
|
141
|
+
showRestoreButton={showRestoreButton}
|
|
142
|
+
privacyUrl={privacyUrl}
|
|
143
|
+
termsUrl={termsUrl}
|
|
144
|
+
privacyText={privacyText}
|
|
145
|
+
termsOfServiceText={termsOfServiceText}
|
|
146
|
+
onPurchase={handlePurchase}
|
|
147
|
+
onRestore={handleRestore}
|
|
148
|
+
/>
|
|
166
149
|
);
|
|
167
150
|
|
|
168
|
-
|
|
151
|
+
// Header with title and close button
|
|
152
|
+
const Header = (
|
|
153
|
+
<View style={styles.header}>
|
|
154
|
+
<TouchableOpacity style={styles.closeButton} onPress={onClose}>
|
|
155
|
+
<AtomicText style={[styles.closeIcon, { color: tokens.colors.textSecondary }]}>
|
|
156
|
+
×
|
|
157
|
+
</AtomicText>
|
|
158
|
+
</TouchableOpacity>
|
|
159
|
+
<AtomicText
|
|
160
|
+
type="headlineMedium"
|
|
161
|
+
style={[styles.title, { color: tokens.colors.textPrimary }]}
|
|
162
|
+
>
|
|
163
|
+
{title}
|
|
164
|
+
</AtomicText>
|
|
165
|
+
{subtitle && (
|
|
166
|
+
<AtomicText
|
|
167
|
+
type="bodyMedium"
|
|
168
|
+
style={[styles.subtitle, { color: tokens.colors.textSecondary }]}
|
|
169
|
+
>
|
|
170
|
+
{subtitle}
|
|
171
|
+
</AtomicText>
|
|
172
|
+
)}
|
|
173
|
+
</View>
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
// FULLSCREEN VARIANT
|
|
177
|
+
if (isFullScreen) {
|
|
169
178
|
const Wrapper = BackgroundComponent || View;
|
|
170
|
-
const wrapperStyle = !BackgroundComponent
|
|
179
|
+
const wrapperStyle = !BackgroundComponent
|
|
180
|
+
? { flex: 1, backgroundColor: tokens.colors.backgroundPrimary }
|
|
181
|
+
: { flex: 1 };
|
|
171
182
|
|
|
172
183
|
return (
|
|
173
184
|
<Modal visible={visible} transparent={false} animationType="slide" onRequestClose={onClose}>
|
|
174
185
|
<Wrapper style={wrapperStyle}>
|
|
175
|
-
{
|
|
186
|
+
<ContentWrapper {...wrapperProps} style={styles.fullscreenContainer}>
|
|
187
|
+
{Header}
|
|
188
|
+
{ScrollContent}
|
|
189
|
+
{Footer}
|
|
190
|
+
</ContentWrapper>
|
|
176
191
|
</Wrapper>
|
|
177
192
|
</Modal>
|
|
178
193
|
);
|
|
179
194
|
}
|
|
180
195
|
|
|
196
|
+
// BOTTOM-SHEET VARIANT
|
|
181
197
|
return (
|
|
182
198
|
<Modal visible={visible} transparent animationType="slide" onRequestClose={onClose}>
|
|
183
199
|
<View style={styles.overlay}>
|
|
184
200
|
<TouchableOpacity style={styles.backdrop} activeOpacity={1} onPress={onClose} />
|
|
185
|
-
<View style={[styles.
|
|
186
|
-
{
|
|
201
|
+
<View style={[styles.bottomSheetContainer, { backgroundColor: tokens.colors.surface }]}>
|
|
202
|
+
{Header}
|
|
203
|
+
{ScrollContent}
|
|
204
|
+
{Footer}
|
|
187
205
|
</View>
|
|
188
206
|
</View>
|
|
189
207
|
</Modal>
|
|
@@ -194,22 +212,71 @@ export const SubscriptionModal: React.FC<SubscriptionModalProps> = React.memo(
|
|
|
194
212
|
SubscriptionModal.displayName = "SubscriptionModal";
|
|
195
213
|
|
|
196
214
|
const styles = StyleSheet.create({
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
215
|
+
// Overlay and backdrop for bottom-sheet
|
|
216
|
+
overlay: {
|
|
217
|
+
flex: 1,
|
|
218
|
+
justifyContent: "flex-end",
|
|
219
|
+
},
|
|
220
|
+
backdrop: {
|
|
221
|
+
...StyleSheet.absoluteFillObject,
|
|
222
|
+
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
223
|
+
},
|
|
224
|
+
|
|
225
|
+
// Bottom-sheet container - KEY FIX: explicit max height calculation
|
|
226
|
+
bottomSheetContainer: {
|
|
227
|
+
borderTopLeftRadius: 24,
|
|
228
|
+
borderTopRightRadius: 24,
|
|
229
|
+
maxHeight: SCREEN_HEIGHT * 0.85,
|
|
230
|
+
paddingTop: 16,
|
|
231
|
+
paddingBottom: 24,
|
|
232
|
+
},
|
|
200
233
|
|
|
201
|
-
|
|
202
|
-
|
|
234
|
+
// Fullscreen container
|
|
235
|
+
fullscreenContainer: {
|
|
236
|
+
flex: 1,
|
|
237
|
+
paddingTop: 16,
|
|
238
|
+
},
|
|
203
239
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
240
|
+
// Header
|
|
241
|
+
header: {
|
|
242
|
+
alignItems: "center",
|
|
243
|
+
paddingHorizontal: 24,
|
|
244
|
+
paddingBottom: 16,
|
|
245
|
+
},
|
|
246
|
+
closeButton: {
|
|
247
|
+
position: "absolute",
|
|
248
|
+
top: 0,
|
|
249
|
+
right: 16,
|
|
250
|
+
padding: 8,
|
|
251
|
+
zIndex: 1,
|
|
252
|
+
},
|
|
253
|
+
closeIcon: {
|
|
254
|
+
fontSize: 28,
|
|
255
|
+
fontWeight: "300",
|
|
256
|
+
},
|
|
257
|
+
title: {
|
|
258
|
+
marginBottom: 8,
|
|
259
|
+
textAlign: "center",
|
|
260
|
+
},
|
|
261
|
+
subtitle: {
|
|
262
|
+
textAlign: "center",
|
|
263
|
+
},
|
|
209
264
|
|
|
210
|
-
|
|
211
|
-
|
|
265
|
+
// ScrollView - expands to fill available space, shrinks if needed
|
|
266
|
+
scrollView: {
|
|
267
|
+
flex: 1,
|
|
268
|
+
minHeight: 100,
|
|
269
|
+
},
|
|
270
|
+
scrollContent: {
|
|
271
|
+
paddingHorizontal: 24,
|
|
272
|
+
paddingBottom: 16,
|
|
273
|
+
flexGrow: 1,
|
|
274
|
+
},
|
|
212
275
|
|
|
213
|
-
|
|
214
|
-
featuresSection: {
|
|
276
|
+
// Features section
|
|
277
|
+
featuresSection: {
|
|
278
|
+
borderRadius: 16,
|
|
279
|
+
padding: 16,
|
|
280
|
+
marginTop: 16,
|
|
281
|
+
},
|
|
215
282
|
});
|