@umituz/react-native-subscription 2.27.43 → 2.27.44
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 +1 -1
- package/src/domains/paywall/components/PaywallContainer.tsx +4 -0
- package/src/domains/paywall/components/PaywallContainer.types.ts +4 -0
- package/src/domains/paywall/components/PaywallModal.tsx +7 -1
- package/src/domains/paywall/components/PlanCard.tsx +12 -1
- package/src/utils/creditMapper.ts +29 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-subscription",
|
|
3
|
-
"version": "2.27.
|
|
3
|
+
"version": "2.27.44",
|
|
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",
|
|
@@ -19,6 +19,8 @@ export const PaywallContainer: React.FC<PaywallContainerProps> = (props) => {
|
|
|
19
19
|
features,
|
|
20
20
|
heroImage,
|
|
21
21
|
bestValueIdentifier,
|
|
22
|
+
creditAmounts,
|
|
23
|
+
creditsLabel,
|
|
22
24
|
source,
|
|
23
25
|
onPurchaseSuccess,
|
|
24
26
|
onPurchaseError,
|
|
@@ -98,6 +100,8 @@ export const PaywallContainer: React.FC<PaywallContainerProps> = (props) => {
|
|
|
98
100
|
features={features ? [...features] : undefined}
|
|
99
101
|
heroImage={heroImage}
|
|
100
102
|
bestValueIdentifier={bestValueIdentifier}
|
|
103
|
+
creditAmounts={creditAmounts}
|
|
104
|
+
creditsLabel={creditsLabel}
|
|
101
105
|
onPurchase={handlePurchase}
|
|
102
106
|
onRestore={handleRestore}
|
|
103
107
|
trialEligibility={trialEligibility}
|
|
@@ -33,6 +33,10 @@ export interface PaywallContainerProps {
|
|
|
33
33
|
readonly heroImage?: ImageSourcePropType;
|
|
34
34
|
/** Best value package identifier for badge */
|
|
35
35
|
readonly bestValueIdentifier?: string;
|
|
36
|
+
/** Credit amounts per product identifier */
|
|
37
|
+
readonly creditAmounts?: Record<string, number>;
|
|
38
|
+
/** Credits label text (e.g., "credits") */
|
|
39
|
+
readonly creditsLabel?: string;
|
|
36
40
|
/** Source of the paywall - affects pending purchase handling */
|
|
37
41
|
readonly source?: PurchaseSource;
|
|
38
42
|
/** Callback when purchase succeeds */
|
|
@@ -33,6 +33,10 @@ export interface PaywallModalProps {
|
|
|
33
33
|
isLoading?: boolean;
|
|
34
34
|
legalUrls?: PaywallLegalUrls;
|
|
35
35
|
bestValueIdentifier?: string;
|
|
36
|
+
/** Credit amounts per product identifier */
|
|
37
|
+
creditAmounts?: Record<string, number>;
|
|
38
|
+
/** Credits label text (e.g., "credits") */
|
|
39
|
+
creditsLabel?: string;
|
|
36
40
|
heroImage?: ImageSourcePropType;
|
|
37
41
|
onPurchase?: (pkg: PurchasesPackage) => Promise<void | boolean>;
|
|
38
42
|
onRestore?: () => Promise<void | boolean>;
|
|
@@ -43,7 +47,7 @@ export interface PaywallModalProps {
|
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
|
|
46
|
-
const { visible, onClose, translations, packages = [], features = [], isLoading = false, legalUrls = {}, bestValueIdentifier, heroImage, onPurchase, onRestore, trialEligibility = {}, trialSubtitleText } = props;
|
|
50
|
+
const { visible, onClose, translations, packages = [], features = [], isLoading = false, legalUrls = {}, bestValueIdentifier, creditAmounts, creditsLabel, heroImage, onPurchase, onRestore, trialEligibility = {}, trialSubtitleText } = props;
|
|
47
51
|
const tokens = useAppDesignTokens();
|
|
48
52
|
const [selectedPlanId, setSelectedPlanId] = useState<string | null>(null);
|
|
49
53
|
const [isLocalProcessing, setIsLocalProcessing] = useState(false);
|
|
@@ -150,6 +154,8 @@ export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
|
|
|
150
154
|
isSelected={selectedPlanId === productId}
|
|
151
155
|
onSelect={() => setSelectedPlanId(productId)}
|
|
152
156
|
badge={productId === bestValueIdentifier ? translations.bestValueBadgeText : undefined}
|
|
157
|
+
creditAmount={creditAmounts?.[productId]}
|
|
158
|
+
creditsLabel={creditsLabel}
|
|
153
159
|
hasFreeTrial={hasFreeTrial}
|
|
154
160
|
trialSubtitleText={hasFreeTrial ? trialSubtitleText : undefined}
|
|
155
161
|
/>
|
|
@@ -21,6 +21,10 @@ interface PlanCardProps {
|
|
|
21
21
|
onSelect: () => void;
|
|
22
22
|
/** Badge text (e.g., "Best Value") - NOT for trial */
|
|
23
23
|
badge?: string;
|
|
24
|
+
/** Credit amount for this plan */
|
|
25
|
+
creditAmount?: number;
|
|
26
|
+
/** Credits label text (e.g., "credits") */
|
|
27
|
+
creditsLabel?: string;
|
|
24
28
|
/** Whether this plan has a free trial (Apple-compliant display) */
|
|
25
29
|
hasFreeTrial?: boolean;
|
|
26
30
|
/** Trial subtitle text (e.g., "7 days free, then billed") - shown as small gray text */
|
|
@@ -28,7 +32,7 @@ interface PlanCardProps {
|
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
export const PlanCard: React.FC<PlanCardProps> = React.memo(
|
|
31
|
-
({ pkg, isSelected, onSelect, badge, hasFreeTrial, trialSubtitleText }) => {
|
|
35
|
+
({ pkg, isSelected, onSelect, badge, creditAmount, creditsLabel, hasFreeTrial, trialSubtitleText }) => {
|
|
32
36
|
const tokens = useAppDesignTokens();
|
|
33
37
|
const title = pkg.product.title;
|
|
34
38
|
const price = formatPriceWithPeriod(pkg.product.price, pkg.product.currencyCode, pkg.identifier);
|
|
@@ -73,6 +77,13 @@ export const PlanCard: React.FC<PlanCardProps> = React.memo(
|
|
|
73
77
|
{title}
|
|
74
78
|
</AtomicText>
|
|
75
79
|
|
|
80
|
+
{/* Credits info */}
|
|
81
|
+
{creditAmount && creditsLabel && (
|
|
82
|
+
<AtomicText type="bodySmall" style={{ color: tokens.colors.textSecondary }}>
|
|
83
|
+
{creditAmount} {creditsLabel}
|
|
84
|
+
</AtomicText>
|
|
85
|
+
)}
|
|
86
|
+
|
|
76
87
|
{/* Trial info - Apple-compliant: small, gray, subordinate */}
|
|
77
88
|
{hasFreeTrial && trialSubtitleText && (
|
|
78
89
|
<AtomicText
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { detectPackageType, type SubscriptionPackageType } from "./packageTypeDetector";
|
|
2
2
|
import type { PackageAllocationMap } from "../domain/entities/Credits";
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -11,3 +11,31 @@ export function getCreditAllocation(
|
|
|
11
11
|
if (packageType === "unknown" || !allocations) return null;
|
|
12
12
|
return allocations[packageType]?.credits ?? null;
|
|
13
13
|
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Create credit amounts mapping for PaywallModal from RevenueCat packages
|
|
17
|
+
* Maps product.identifier to credit amount using dynamic allocations
|
|
18
|
+
*/
|
|
19
|
+
export function createCreditAmountsFromPackages(
|
|
20
|
+
packages: Array<{ product: { identifier: string } }>,
|
|
21
|
+
allocations?: PackageAllocationMap
|
|
22
|
+
): Record<string, number> {
|
|
23
|
+
const result: Record<string, number> = {};
|
|
24
|
+
|
|
25
|
+
if (!allocations) return result;
|
|
26
|
+
|
|
27
|
+
for (const pkg of packages) {
|
|
28
|
+
const identifier = pkg?.product?.identifier;
|
|
29
|
+
|
|
30
|
+
if (!identifier) continue;
|
|
31
|
+
|
|
32
|
+
const packageType = detectPackageType(identifier);
|
|
33
|
+
const credits = getCreditAllocation(packageType, allocations);
|
|
34
|
+
|
|
35
|
+
if (credits !== null) {
|
|
36
|
+
result[identifier] = credits;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return result;
|
|
41
|
+
}
|