@umituz/react-native-subscription 2.37.98 → 2.37.100

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.37.98",
3
+ "version": "2.37.100",
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",
@@ -3,7 +3,8 @@ import { StyleSheet } from "react-native";
3
3
 
4
4
  export const paywallModalStyles = StyleSheet.create({
5
5
  modalContent: { padding: 0, borderWidth: 0, overflow: "hidden" },
6
- container: { flex: 1 },
6
+ container: { flex: 1, flexDirection: "column" as const },
7
+ scrollContainer: { flex: 1, flexShrink: 1 },
7
8
  closeBtn: {
8
9
  position: "absolute",
9
10
  top: 12,
@@ -35,7 +36,7 @@ export const paywallModalStyles = StyleSheet.create({
35
36
  loading: { alignItems: "center", paddingVertical: 24 },
36
37
  loadingText: { marginTop: 8 },
37
38
  plans: { marginBottom: 12 },
38
- stickyFooter: { paddingHorizontal: 16, paddingTop: 12, borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: "rgba(128,128,128,0.2)" },
39
+ stickyFooter: { flexShrink: 0, paddingHorizontal: 16, paddingTop: 12, borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: "rgba(128,128,128,0.2)" },
39
40
  cta: { borderRadius: 12, paddingVertical: 14, alignItems: "center", marginBottom: 12 },
40
41
  ctaDisabled: { opacity: 0.5 },
41
42
  ctaText: { fontWeight: "700" },
@@ -1,10 +1,9 @@
1
1
  import React, { useCallback, useEffect } from "react";
2
- import { View, TouchableOpacity, Linking } from "react-native";
2
+ import { View, ScrollView, TouchableOpacity, Linking } from "react-native";
3
3
  import { AtomicText, AtomicIcon, AtomicSpinner } from "@umituz/react-native-design-system/atoms";
4
4
  import { BaseModal } from "@umituz/react-native-design-system/molecules";
5
5
  import { useSafeAreaInsets } from "@umituz/react-native-design-system/safe-area";
6
6
  import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
7
- import { ScreenLayout } from "../../../shared/presentation";
8
7
  import { Image } from "expo-image";
9
8
  import { PlanCard } from "./PlanCard";
10
9
  import { paywallModalStyles as styles } from "./PaywallModal.styles";
@@ -57,7 +56,7 @@ export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
57
56
  </TouchableOpacity>
58
57
 
59
58
  {/* Scrollable content — plan cards scroll, CTA is always pinned below */}
60
- <ScreenLayout scrollable={true} edges={[]} backgroundColor="transparent" contentContainerStyle={styles.scroll}>
59
+ <ScrollView style={styles.scrollContainer} contentContainerStyle={styles.scroll} showsVerticalScrollIndicator={false}>
61
60
  {heroImage && <View style={styles.heroContainer}><Image source={heroImage} style={styles.heroImage} contentFit="cover" transition={0} /></View>}
62
61
  <View style={styles.header}>
63
62
  <AtomicText type="headlineMedium" adjustsFontSizeToFit numberOfLines={2} minimumFontScale={0.75} style={[styles.title, { color: tokens.colors.textPrimary }]}>{translations.title}</AtomicText>
@@ -85,7 +84,7 @@ export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
85
84
  })
86
85
  )}
87
86
  </View>
88
- </ScreenLayout>
87
+ </ScrollView>
89
88
 
90
89
  {/* Sticky footer — always visible, never hidden behind scroll content */}
91
90
  <View style={[styles.stickyFooter, { paddingBottom: Math.max(insets.bottom, 16) }]}>
@@ -111,6 +111,7 @@ export function usePaywallActions({
111
111
 
112
112
  if (success === true) {
113
113
  onPurchaseSuccessRef.current?.();
114
+ onCloseRef.current?.();
114
115
  }
115
116
  } catch (error) {
116
117
  const err = error instanceof Error ? error : new Error(String(error));
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Ümit UZ
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/README.md DELETED
@@ -1,323 +0,0 @@
1
- # @umituz/react-native-subscription
2
-
3
- Complete subscription management with RevenueCat, paywall UI, and credits system for React Native apps.
4
-
5
- ## Package Overview
6
-
7
- **Import Path**: `@umituz/react-native-subscription`
8
-
9
- **Version**: Latest
10
-
11
- **Type**: React Native Package
12
-
13
- This package provides comprehensive subscription and credit management with:
14
- - RevenueCat integration for subscriptions
15
- - Credits system with transaction tracking
16
- - Paywall UI components
17
- - Feature gating (premium, auth, credits)
18
- - DDD architecture with clean layers
19
-
20
- ## Strategy
21
-
22
- ### Architecture Principles
23
-
24
- 1. **Domain-Driven Design (DDD)**
25
- - Separate domains: Wallet, Paywall, Config
26
- - Each domain has its own entities, rules, and boundaries
27
- - Business logic stays in domain layer
28
-
29
- 2. **Clean Architecture**
30
- - Presentation: React hooks and components
31
- - Application: Use cases and orchestration
32
- - Domain: Entities and business rules
33
- - Infrastructure: External integrations
34
-
35
- 3. **Separation of Concerns**
36
- - UI components are pure and reusable
37
- - Business logic is in hooks and services
38
- - Data persistence is abstracted behind repositories
39
-
40
- ### Integration Flow
41
-
42
- 1. **Initialization**
43
- - Configure RevenueCat with API key
44
- - Set up Firebase for credits storage
45
- - Initialize providers at app root
46
-
47
- 2. **Subscription Management**
48
- - Check user tier and subscription status
49
- - Gate premium features
50
- - Handle purchase flows
51
-
52
- 3. **Credits System**
53
- - Initialize credits on purchase
54
- - Deduct credits for feature usage
55
- - Track all transactions
56
- - Handle credit exhaustion
57
-
58
- 4. **Paywall Display**
59
- - Show paywall on feature gates
60
- - Handle purchase operations
61
- - Manage paywall visibility state
62
-
63
- ### Key Dependencies
64
-
65
- - **RevenueCat**: `react-native-purchases` >= 7.0.0
66
- - **Firebase**: `firebase` >= 10.0.0
67
- - **State Management**: `@tanstack/react-query` >= 5.0.0
68
- - **React Native**: `react-native` >= 0.74.0
69
-
70
- ## RevenueCat Best Practices
71
-
72
- This package follows RevenueCat's official best practices:
73
-
74
- ### 1. Trust RevenueCat Data
75
-
76
- - **Expiration dates**: Use RevenueCat's `expirationDate` directly without modification
77
- - **Premium status**: Check `customerInfo.entitlements.active['premium']`
78
- - **Server-side validation**: RevenueCat handles receipt validation server-side
79
-
80
- ### 2. CustomerInfo Listener
81
-
82
- ```typescript
83
- // Real-time subscription updates via listener
84
- Purchases.addCustomerInfoUpdateListener((info) => {
85
- const isPremium = !!info.entitlements.active['premium'];
86
- const expirationDate = info.entitlements.active['premium']?.expirationDate;
87
- });
88
- ```
89
-
90
- ### 3. Entitlements-Based Access
91
-
92
- - Use entitlements (not product IDs) to gate features
93
- - Entitlements abstract away platform differences (iOS/Android)
94
- - Single source of truth for premium access
95
-
96
- ### 4. Testing Guidelines
97
-
98
- - **Real devices only**: Simulators don't support in-app purchases
99
- - **TestFlight uses Sandbox**: Short expiration times (5 min for monthly)
100
- - **App Store Connect delays**: Changes can take hours to propagate
101
-
102
- ### 5. Anonymous to Identified User Transfer
103
-
104
- When user converts from anonymous to identified:
105
- - `Purchases.logIn(userId)` handles user identity
106
- - Configure "Transfer if no purchases" in RevenueCat dashboard
107
- - Use `restorePurchases()` for explicit restore
108
-
109
- ### Sources
110
-
111
- - [RevenueCat React Native SDK](https://github.com/RevenueCat/react-native-purchases)
112
- - [RevenueCat Documentation](https://www.revenuecat.com/docs/getting-started/installation/reactnative)
113
- - [Best Practices Guide](https://www.revenuecat.com/blog/engineering/ad-free-subscriptions-in-react-native/)
114
-
115
- ## Restrictions
116
-
117
- ### REQUIRED
118
-
119
- - **RevenueCat Configuration**: MUST provide valid API key and entitlement ID
120
- - **Firebase Setup**: MUST initialize Firebase for credits system
121
- - **Provider Setup**: MUST wrap app with `SubscriptionProvider`
122
- - **Authentication**: MUST have authenticated user for credits operations
123
- - **Error Handling**: MUST handle all error states appropriately
124
-
125
- ### PROHIBITED
126
-
127
- - **NEVER** use subscription hooks outside provider
128
- - **NEVER** deduce credits without checking balance first
129
- - **NEVER** gate features without proper user feedback
130
- - **DO NOT** bypass gate hooks for premium features
131
- - **DO NOT** initialize RevenueCat multiple times
132
-
133
- ### CRITICAL SAFETY
134
-
135
- - **ALWAYS** check loading states before rendering
136
- - **ALWAYS** handle edge cases (no subscription, expired, etc)
137
- - **ALWAYS** validate return values from credit operations
138
- - **NEVER** assume user has premium or credits
139
- - **MUST** implement proper error boundaries
140
-
141
- ## Rules
142
-
143
- ### Provider Setup
144
-
145
- ```typescript
146
- // CORRECT - Wrap app with provider
147
- <SubscriptionProvider config={{ revenueCatApiKey: 'xxx' }}>
148
- <App />
149
- </SubscriptionProvider>
150
-
151
- // INCORRECT - No provider
152
- <App /> // Hooks will fail
153
-
154
- // INCORRECT - Multiple providers
155
- <SubscriptionProvider>
156
- <SubscriptionProvider> // Duplicate
157
- <App />
158
- </SubscriptionProvider>
159
- </SubscriptionProvider>
160
- ```
161
-
162
- ### Feature Gating
163
-
164
- ```typescript
165
- // CORRECT - Use gate hooks
166
- const { canAccess, showPaywall } = usePremiumGate();
167
- if (!canAccess) {
168
- showPaywall();
169
- return;
170
- }
171
-
172
- // INCORRECT - Manual check
173
- if (!user.isPremium) { // No feedback, no paywall
174
- return;
175
- }
176
- ```
177
-
178
- ### Credit Operations
179
-
180
- ```typescript
181
- // CORRECT - Check return value
182
- const success = await deductCredit(5);
183
- if (success) {
184
- executeFeature();
185
- }
186
-
187
- // INCORRECT - Assume success
188
- await deductCredit(5);
189
- executeFeature(); // May execute if deduction failed
190
- ```
191
-
192
- ### Loading States
193
-
194
- ```typescript
195
- // CORRECT - Respect loading
196
- if (isLoading) return <Spinner />;
197
- if (!isPremium) return <UpgradePrompt />;
198
- return <Content />;
199
-
200
- // INCORRECT - Ignore loading
201
- {!isPremium && <UpgradePrompt />} // Flickers during load
202
- ```
203
-
204
- ## AI Agent Guidelines
205
-
206
- ### When Implementing Features
207
-
208
- 1. **Always** use appropriate gate hooks for feature access
209
- 2. **Always** handle loading, error, and empty states
210
- 3. **Always** provide user feedback for blocked features
211
- 4. **Always** check return values from operations
212
- 5. **Never** bypass gate system or checks
213
- 6. **Must** test with different user tiers
214
- 7. **Must** handle network errors gracefully
215
-
216
- ### Implementation Checklist
217
-
218
- - [ ] Import from correct path
219
- - [ ] Wrap with necessary providers
220
- - [ ] Use gate hooks for features
221
- - [ ] Handle loading states
222
- - [ ] Handle error states
223
- - [ ] Provide user feedback
224
- - [ ] Test with guest user
225
- - [ ] Test with free user
226
- - [ ] Test with premium user
227
- - [ ] Test with no credits
228
- - [ ] Test with insufficient credits
229
-
230
- ### Common Patterns
231
-
232
- 1. **Premium Feature**: Use `usePremiumGate`
233
- 2. **Credit Feature**: Use `useCreditsGate` or `useDeductCredit`
234
- 3. **Auth Feature**: Use `useAuthGate`
235
- 4. **Combined Gates**: Use `useFeatureGate` for complex scenarios
236
- 5. **Paywall Trigger**: Use `usePaywallVisibility` for global state
237
-
238
- ### Error Scenarios to Handle
239
-
240
- - **No Subscription**: Show upgrade prompt
241
- - **Expired Subscription**: Show renewal prompt
242
- - **No Credits**: Show credit purchase prompt
243
- - **Insufficient Credits**: Show credit cost and purchase option
244
- - **Network Error**: Show retry option
245
- - **Purchase Failed**: Show error message and retry
246
-
247
- ## Documentation Structure
248
-
249
- ### Domain Documentation
250
-
251
- - **[Wallet Domain](./src/domains/wallet/README.md)**: Credits and transactions
252
- - **[Paywall Domain](./src/domains/paywall/README.md)**: Paywall components
253
- - **[Config Domain](./src/domains/config/README.md)**: Configuration management
254
-
255
- ### Layer Documentation
256
-
257
- - **[Presentation Layer](./src/presentation/README.md)**: Hooks and components
258
- - **[Application Layer](./src/application/README.md)**: Use cases and ports
259
- - **[Domain Layer](./src/domain/README.md)**: Entities and logic
260
- - **[Infrastructure Layer](./src/infrastructure/README.md)**: Repositories and services
261
-
262
- ### Feature Documentation
263
-
264
- - **[RevenueCat Integration](./src/revenuecat/README.md)**: RevenueCat setup
265
- - **[Subscription Hooks](./src/presentation/hooks/README.md)**: Available hooks
266
- - **[Premium Components](./src/presentation/components/README.md)**: UI components
267
-
268
- ### Quick Reference
269
-
270
- #### Subscription Hooks
271
-
272
- Location: `src/presentation/hooks/`
273
-
274
- - `useSubscription` - Core subscription management
275
- - `usePremium` - Check premium status
276
- - `usePremiumGate` - Gate premium features
277
- - `useUserTier` - Get user tier (guest/free/premium)
278
-
279
- #### Credit Hooks
280
-
281
- Location: `src/presentation/hooks/`
282
-
283
- - `useCredits` - Access credit balance
284
- - `useDeductCredit` - Deduct credits with optimistic updates
285
- - `useCreditChecker` - Check credit availability
286
- - `useCreditsGate` - Gate features by credits
287
-
288
- #### Paywall Hooks
289
-
290
- Location: `src/presentation/hooks/`
291
-
292
- - `usePaywallVisibility` - Manage paywall state
293
- - `usePaywallOperations` - Handle purchase operations
294
-
295
- #### Components
296
-
297
- Location: `src/presentation/components/`
298
-
299
- - `PremiumDetailsCard` - Display subscription details
300
- - `PremiumStatusBadge` - Show subscription badge
301
- - `PaywallModal` - Full paywall modal
302
- - `CreditRow` - Display credit balance with progress
303
-
304
- ## Contributing
305
-
306
- When contributing to this package:
307
-
308
- 1. **Follow Documentation Template**: Use `README_TEMPLATE.md`
309
- 2. **Update Strategy Section**: Document architectural decisions
310
- 3. **List Restrictions**: Clearly state what's required/prohibited
311
- 4. **Provide Rules**: Show correct/incorrect usage
312
- 5. **AI Guidelines**: Include agent instructions
313
- 6. **No Code Examples**: Keep documentation code-agnostic
314
- 7. **English Only**: All documentation in English
315
-
316
- ## Support
317
-
318
- - **Issues**: [GitHub Issues](https://github.com/umituz/react-native-subscription/issues)
319
- - **Author**: Ümit UZ <umit@umituz.com>
320
-
321
- ## License
322
-
323
- MIT License - see LICENSE file for details