@umituz/react-native-subscription 3.1.27 → 3.1.28

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": "3.1.27",
3
+ "version": "3.1.28",
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",
@@ -2,6 +2,7 @@ import React from "react";
2
2
  import { View, TouchableOpacity, StyleSheet } from "react-native";
3
3
  import { AtomicText, AtomicSpinner } from "@umituz/react-native-design-system/atoms";
4
4
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
5
+ import { useResponsive } from "@umituz/react-native-design-system/responsive";
5
6
  import type { PaywallTranslations, PaywallLegalUrls } from "../entities/types";
6
7
 
7
8
  interface PaywallFooterProps {
@@ -12,8 +13,6 @@ interface PaywallFooterProps {
12
13
  onRestore?: () => Promise<void | boolean>;
13
14
  onLegalClick: (url: string | undefined) => void;
14
15
  purchaseButtonText?: string;
15
- isTablet?: boolean;
16
- isSmallDevice?: boolean;
17
16
  }
18
17
 
19
18
  export const PaywallFooter: React.FC<PaywallFooterProps> = React.memo(({
@@ -24,33 +23,45 @@ export const PaywallFooter: React.FC<PaywallFooterProps> = React.memo(({
24
23
  onRestore,
25
24
  onLegalClick,
26
25
  purchaseButtonText,
27
- isTablet = false,
28
- isSmallDevice = false,
29
26
  }) => {
30
27
  const tokens = useAppDesignTokens();
28
+ const responsive = useResponsive();
31
29
 
32
- // Device-based sizing
33
- const buttonHeight = React.useMemo(() => {
34
- if (isTablet) return 64; // Larger button on tablet
35
- if (isSmallDevice) return 52; // Slightly smaller on small phones
36
- return 56; // Standard size
37
- }, [isTablet, isSmallDevice]);
30
+ // Base values that will be scaled by spacingMultiplier
31
+ const BASE_BUTTON_HEIGHT = 56;
32
+ const BASE_FONT_SIZE = 17;
33
+ const BASE_PADDING_VERTICAL = 16;
34
+ const BASE_SPACING = 12;
38
35
 
39
- const fontSize = React.useMemo(() => {
40
- if (isTablet) return 19;
41
- if (isSmallDevice) return 16;
42
- return 17;
43
- }, [isTablet, isSmallDevice]);
36
+ // Responsive values using spacingMultiplier
37
+ const buttonHeight = React.useMemo(
38
+ () => Math.round(BASE_BUTTON_HEIGHT * responsive.spacingMultiplier),
39
+ [responsive, BASE_BUTTON_HEIGHT]
40
+ );
41
+
42
+ const fontSize = React.useMemo(
43
+ () => responsive.getFontSize(BASE_FONT_SIZE),
44
+ [responsive, BASE_FONT_SIZE]
45
+ );
46
+
47
+ const paddingVertical = React.useMemo(
48
+ () => Math.round(BASE_PADDING_VERTICAL * responsive.spacingMultiplier),
49
+ [responsive, BASE_PADDING_VERTICAL]
50
+ );
51
+
52
+ const spacing = React.useMemo(
53
+ () => Math.round(BASE_SPACING * responsive.spacingMultiplier),
54
+ [responsive, BASE_SPACING]
55
+ );
44
56
 
45
- const paddingVertical = React.useMemo(() => {
46
- if (isTablet) return 20;
47
- if (isSmallDevice) return 12;
48
- return 16;
49
- }, [isTablet, isSmallDevice]);
57
+ const paddingHorizontal = React.useMemo(
58
+ () => responsive.horizontalPadding,
59
+ [responsive]
60
+ );
50
61
 
51
62
  return (
52
- <View style={footerStyles.container}>
53
- {/* Purchase Button - Device-responsive */}
63
+ <View style={[footerStyles.container, { paddingHorizontal, paddingVertical: spacing, gap: spacing }]}>
64
+ {/* Purchase Button - Responsive sizing */}
54
65
  {onPurchase && (
55
66
  <TouchableOpacity
56
67
  onPress={onPurchase}
@@ -78,13 +89,13 @@ export const PaywallFooter: React.FC<PaywallFooterProps> = React.memo(({
78
89
  </TouchableOpacity>
79
90
  )}
80
91
 
81
- {/* Restore Link - Device-spaced */}
92
+ {/* Restore Link - Responsive spacing */}
82
93
  {onRestore && (
83
94
  <TouchableOpacity
84
95
  onPress={onRestore}
85
96
  disabled={isProcessing}
86
97
  activeOpacity={0.6}
87
- style={[footerStyles.restoreButton, { marginTop: isTablet ? 16 : 8 }]}
98
+ style={[footerStyles.restoreButton, { marginTop: spacing / 2 }]}
88
99
  >
89
100
  <AtomicText style={[footerStyles.restoreText, { color: tokens.colors.textSecondary }]}>
90
101
  {translations.restoreButtonText}
@@ -126,9 +137,6 @@ export const PaywallFooter: React.FC<PaywallFooterProps> = React.memo(({
126
137
  const footerStyles = StyleSheet.create({
127
138
  container: {
128
139
  width: '100%',
129
- paddingHorizontal: 20,
130
- paddingVertical: 16,
131
- gap: 12,
132
140
  },
133
141
  purchaseButton: {
134
142
  width: '100%',
@@ -8,6 +8,7 @@ import { View } from "react-native";
8
8
  import type { ImageSourcePropType } from "react-native";
9
9
  import { AtomicText, AtomicIcon } from "@umituz/react-native-design-system/atoms";
10
10
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
11
+ import { useResponsive } from "@umituz/react-native-design-system/responsive";
11
12
  import { Image } from "expo-image";
12
13
  import { PlanCard } from "./PlanCard";
13
14
  import type { PaywallListItem } from "../utils/paywallLayoutUtils";
@@ -36,6 +37,25 @@ export const PaywallRenderItem: React.FC<PaywallRenderItemProps> = React.memo(({
36
37
  onSelectPlan,
37
38
  }) => {
38
39
  const tokens = useAppDesignTokens();
40
+ const responsive = useResponsive();
41
+
42
+ // Responsive spacing
43
+ const spacing = React.useMemo(
44
+ () => Math.round(16 * responsive.spacingMultiplier),
45
+ [responsive]
46
+ );
47
+
48
+ // Responsive feature icon size
49
+ const featureIconSize = React.useMemo(
50
+ () => responsive.getIconSize(30),
51
+ [responsive]
52
+ );
53
+
54
+ // Responsive hero image size
55
+ const heroImageSize = React.useMemo(
56
+ () => responsive.getIconSize(120),
57
+ [responsive]
58
+ );
39
59
 
40
60
  if (!translations) return null;
41
61
 
@@ -43,10 +63,15 @@ export const PaywallRenderItem: React.FC<PaywallRenderItemProps> = React.memo(({
43
63
  case 'HEADER':
44
64
  return (
45
65
  <View key="header">
46
- {/* Hero Image */}
66
+ {/* Hero Image - Responsive sizing */}
47
67
  {heroImage && (
48
68
  <View style={styles.heroContainer}>
49
- <Image source={heroImage} style={styles.heroImage} contentFit="cover" transition={200} />
69
+ <Image
70
+ source={heroImage}
71
+ style={[styles.heroImage, { width: heroImageSize, height: heroImageSize, borderRadius: heroImageSize * 0.25 }]}
72
+ contentFit="cover"
73
+ transition={200}
74
+ />
50
75
  </View>
51
76
  )}
52
77
 
@@ -66,7 +91,7 @@ export const PaywallRenderItem: React.FC<PaywallRenderItemProps> = React.memo(({
66
91
 
67
92
  case 'FEATURE_HEADER':
68
93
  return (
69
- <View key="feat-header" style={styles.sectionHeader}>
94
+ <View key="feat-header" style={[styles.sectionHeader, { marginTop: spacing * 1.5 }]}>
70
95
  <AtomicText type="labelLarge" style={[styles.sectionTitle, { color: tokens.colors.textSecondary }]}>
71
96
  {translations.featuresTitle || "WHAT'S INCLUDED"}
72
97
  </AtomicText>
@@ -75,9 +100,13 @@ export const PaywallRenderItem: React.FC<PaywallRenderItemProps> = React.memo(({
75
100
 
76
101
  case 'FEATURE':
77
102
  return (
78
- <View key={`feat-${item.feature.text}`} style={styles.featureRow}>
79
- <View style={[styles.featureIcon, { backgroundColor: tokens.colors.primary }]}>
80
- <AtomicIcon name={item.feature.icon} customSize={16} customColor={tokens.colors.onPrimary} />
103
+ <View key={`feat-${item.feature.text}`} style={[styles.featureRow, { marginBottom: spacing }]}>
104
+ <View style={[styles.featureIcon, { width: featureIconSize, height: featureIconSize, backgroundColor: tokens.colors.primary }]}>
105
+ <AtomicIcon
106
+ name={item.feature.icon}
107
+ customSize={responsive.getFontSize(16)}
108
+ customColor={tokens.colors.onPrimary}
109
+ />
81
110
  </View>
82
111
  <AtomicText type="bodyMedium" style={[styles.featureText, { color: tokens.colors.textPrimary }]}>
83
112
  {item.feature.text}
@@ -87,7 +116,7 @@ export const PaywallRenderItem: React.FC<PaywallRenderItemProps> = React.memo(({
87
116
 
88
117
  case 'PLAN_HEADER':
89
118
  return (
90
- <View key="plan-header" style={styles.sectionHeader}>
119
+ <View key="plan-header" style={[styles.sectionHeader, { marginTop: spacing * 1.5 }]}>
91
120
  <AtomicText type="labelLarge" style={[styles.sectionTitle, { color: tokens.colors.textSecondary }]}>
92
121
  {translations.plansTitle || "CHOOSE YOUR PLAN"}
93
122
  </AtomicText>
@@ -242,8 +242,6 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
242
242
  onPurchase={handlePurchase}
243
243
  onRestore={handleRestore}
244
244
  onLegalClick={handleLegalUrl}
245
- isTablet={responsive.isTabletDevice}
246
- isSmallDevice={responsive.isSmallDevice}
247
245
  />
248
246
  </View>
249
247
  </View>