@umituz/react-native-subscription 2.39.6 → 2.39.8

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.39.6",
3
+ "version": "2.39.8",
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",
@@ -41,7 +41,8 @@ export const paywallScreenStyles = StyleSheet.create({
41
41
  right: 0,
42
42
  paddingHorizontal: 16,
43
43
  paddingTop: 12,
44
- backgroundColor: "#000",
44
+ borderTopWidth: 1,
45
+ borderTopColor: "rgba(255, 255, 255, 0.1)",
45
46
  },
46
47
  cta: {
47
48
  borderRadius: 14,
@@ -6,10 +6,11 @@
6
6
  */
7
7
 
8
8
  import React, { useCallback, useEffect } from "react";
9
- import { View, ScrollView, TouchableOpacity, Linking, StyleSheet } from "react-native";
9
+ import { View, TouchableOpacity, Linking, StyleSheet } from "react-native";
10
10
  import { AtomicText, AtomicIcon, AtomicSpinner } from "@umituz/react-native-design-system/atoms";
11
11
  import { useSafeAreaInsets } from "@umituz/react-native-design-system/safe-area";
12
12
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
13
+ import { ScreenLayout } from "@umituz/react-native-design-system/layouts";
13
14
  import { Image } from "expo-image";
14
15
  import { PlanCard } from "./PlanCard";
15
16
  import { paywallScreenStyles as styles } from "./PaywallScreen.styles";
@@ -77,21 +78,23 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
77
78
  }, []);
78
79
 
79
80
  return (
80
- <View style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}>
81
- {/* Close button */}
82
- <TouchableOpacity
83
- onPress={onClose}
84
- style={[screenStyles.closeBtn, { backgroundColor: tokens.colors.surfaceSecondary, top: Math.max(insets.top, 12) }]}
85
- hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
86
- >
87
- <AtomicIcon name="close-outline" size="md" customColor={tokens.colors.textPrimary} />
88
- </TouchableOpacity>
81
+ <View style={[screenStyles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}>
82
+ {/* Close button - positioned absolutely at top */}
83
+ <View style={[screenStyles.headerContainer, { paddingTop: insets.top }]}>
84
+ <TouchableOpacity
85
+ onPress={onClose}
86
+ style={[screenStyles.closeBtn, { backgroundColor: tokens.colors.surfaceSecondary }]}
87
+ hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
88
+ >
89
+ <AtomicIcon name="close-outline" size="md" customColor={tokens.colors.textPrimary} />
90
+ </TouchableOpacity>
91
+ </View>
89
92
 
90
93
  {/* Scrollable content */}
91
- <ScrollView
92
- style={screenStyles.scrollContainer}
93
- contentContainerStyle={screenStyles.scroll}
94
- showsVerticalScrollIndicator={false}
94
+ <ScreenLayout
95
+ scrollable={true}
96
+ backgroundColor="transparent"
97
+ contentContainerStyle={{ ...screenStyles.contentContainer, paddingBottom: 120 }}
95
98
  >
96
99
  {/* Hero Image */}
97
100
  {heroImage && (
@@ -171,28 +174,32 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
171
174
  })
172
175
  )}
173
176
  </View>
174
-
175
- {/* Sticky footer — always visible, never hidden behind scroll content */}
176
- <View style={[styles.stickyFooter, { paddingBottom: Math.max(insets.bottom, 16) }]}>
177
- <TouchableOpacity
178
- onPress={handlePurchase}
179
- disabled={isProcessing || isLoadingPackages || !selectedPlanId}
180
- style={[styles.cta, { backgroundColor: tokens.colors.primary }, (isProcessing || isLoadingPackages || !selectedPlanId) && styles.ctaDisabled]}
181
- activeOpacity={0.75}
182
- >
183
- <AtomicText type="titleLarge" style={[styles.ctaText, { color: tokens.colors.onPrimary }]}>
184
- {isProcessing ? translations.processingText : translations.purchaseButtonText}
185
- </AtomicText>
186
- </TouchableOpacity>
187
- <PaywallFooter
188
- translations={translations}
189
- legalUrls={legalUrls}
190
- isProcessing={isProcessing}
191
- onRestore={onRestore ? handleRestore : undefined}
192
- onLegalClick={handleLegalUrl}
193
- />
194
- </View>
195
- </ScrollView>
177
+ </ScreenLayout>
178
+
179
+ {/* Fixed footer overlay - always visible at bottom */}
180
+ <View style={[styles.stickyFooter, { backgroundColor: tokens.colors.backgroundPrimary, paddingBottom: Math.max(insets.bottom, 16) }]}>
181
+ <TouchableOpacity
182
+ onPress={handlePurchase}
183
+ disabled={isProcessing || isLoadingPackages || !selectedPlanId}
184
+ style={[
185
+ styles.cta,
186
+ { backgroundColor: tokens.colors.primary },
187
+ (isProcessing || isLoadingPackages || !selectedPlanId) && styles.ctaDisabled
188
+ ]}
189
+ activeOpacity={0.75}
190
+ >
191
+ <AtomicText type="titleLarge" style={[styles.ctaText, { color: tokens.colors.onPrimary }]}>
192
+ {isProcessing ? translations.processingText : translations.purchaseButtonText}
193
+ </AtomicText>
194
+ </TouchableOpacity>
195
+ <PaywallFooter
196
+ translations={translations}
197
+ legalUrls={legalUrls}
198
+ isProcessing={isProcessing}
199
+ onRestore={onRestore ? handleRestore : undefined}
200
+ onLegalClick={handleLegalUrl}
201
+ />
202
+ </View>
196
203
  </View>
197
204
  );
198
205
  });
@@ -203,21 +210,24 @@ const screenStyles = StyleSheet.create({
203
210
  container: {
204
211
  flex: 1,
205
212
  },
206
- closeBtn: {
213
+ headerContainer: {
207
214
  position: 'absolute',
208
- top: 12,
209
- right: 12,
215
+ top: 0,
216
+ left: 0,
217
+ right: 0,
218
+ zIndex: 1000,
219
+ paddingHorizontal: 12,
220
+ paddingTop: 12,
221
+ },
222
+ closeBtn: {
210
223
  width: 36,
211
224
  height: 36,
212
225
  borderRadius: 18,
213
- zIndex: 1000,
214
226
  justifyContent: 'center',
215
227
  alignItems: 'center',
228
+ alignSelf: 'flex-end',
216
229
  },
217
- scrollContainer: {
218
- flex: 1,
219
- },
220
- scroll: {
221
- paddingBottom: 100,
230
+ contentContainer: {
231
+ paddingTop: 60, // Space for close button
222
232
  },
223
233
  });
@@ -139,7 +139,13 @@ export const PaywallFeedbackScreen: React.FC<PaywallFeedbackScreenProps> = React
139
139
 
140
140
  PaywallFeedbackScreen.displayName = "PaywallFeedbackScreen";
141
141
 
142
- const createScreenStyles = (tokens: any, _insets: any) => ({
142
+ const createScreenStyles = (
143
+ tokens: {
144
+ colors: { backgroundPrimary: string; border: string };
145
+ spacing: { xl: number; sm: number; md: number };
146
+ },
147
+ _insets: { top: number; bottom: number }
148
+ ) => ({
143
149
  container: {
144
150
  flex: 1,
145
151
  },