@umituz/react-native-subscription 2.26.17 → 2.26.19
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 +67 -3
- package/src/domains/paywall/components/PaywallContainer.types.ts +17 -0
- package/src/domains/paywall/components/PaywallModal.tsx +7 -5
- package/src/domains/paywall/components/PlanCard.tsx +36 -17
- package/src/domains/paywall/components/index.ts +1 -1
- package/src/domains/paywall/entities/types.ts +0 -4
- package/src/domains/paywall/hooks/usePaywallTranslations.ts +0 -8
- package/src/global.d.ts +13 -0
- package/src/revenuecat/domain/types/RevenueCatTypes.ts +9 -33
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-subscription",
|
|
3
|
-
"version": "2.26.
|
|
3
|
+
"version": "2.26.19",
|
|
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",
|
|
@@ -1,19 +1,39 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* PaywallContainer Component
|
|
3
3
|
* Uses centralized pending purchase state - no local auth handling
|
|
4
|
+
* Apple Guideline 3.1.2 compliant trial display
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
|
-
import React, { useMemo } from "react";
|
|
7
|
+
import React, { useMemo, useEffect } from "react";
|
|
7
8
|
import { usePaywallVisibility } from "../../../presentation/hooks/usePaywallVisibility";
|
|
8
9
|
import { useSubscriptionPackages } from "../../../revenuecat/presentation/hooks/useSubscriptionPackages";
|
|
10
|
+
import { useRevenueCatTrialEligibility } from "../../../revenuecat/presentation/hooks/useRevenueCatTrialEligibility";
|
|
9
11
|
import { filterPackagesByMode } from "../../../utils/packageFilter";
|
|
10
12
|
import { createCreditAmountsFromPackages } from "../../../utils/creditMapper";
|
|
11
|
-
import { PaywallModal } from "./PaywallModal";
|
|
13
|
+
import { PaywallModal, type TrialEligibilityInfo } from "./PaywallModal";
|
|
12
14
|
import { usePaywallActions } from "../hooks/usePaywallActions";
|
|
13
15
|
import type { PaywallContainerProps } from "./PaywallContainer.types";
|
|
14
16
|
|
|
15
17
|
export const PaywallContainer: React.FC<PaywallContainerProps> = (props) => {
|
|
16
|
-
const {
|
|
18
|
+
const {
|
|
19
|
+
userId,
|
|
20
|
+
translations,
|
|
21
|
+
mode = "subscription",
|
|
22
|
+
legalUrls,
|
|
23
|
+
features,
|
|
24
|
+
heroImage,
|
|
25
|
+
bestValueIdentifier,
|
|
26
|
+
creditsLabel,
|
|
27
|
+
creditAmounts,
|
|
28
|
+
packageFilterConfig,
|
|
29
|
+
source,
|
|
30
|
+
onPurchaseSuccess,
|
|
31
|
+
onPurchaseError,
|
|
32
|
+
onAuthRequired,
|
|
33
|
+
visible,
|
|
34
|
+
onClose,
|
|
35
|
+
trialConfig,
|
|
36
|
+
} = props;
|
|
17
37
|
|
|
18
38
|
const { showPaywall, closePaywall, currentSource } = usePaywallVisibility();
|
|
19
39
|
const isVisible = visible ?? showPaywall;
|
|
@@ -22,6 +42,7 @@ export const PaywallContainer: React.FC<PaywallContainerProps> = (props) => {
|
|
|
22
42
|
const purchaseSource = source ?? currentSource ?? "settings";
|
|
23
43
|
|
|
24
44
|
const { data: allPackages = [], isLoading } = useSubscriptionPackages(userId ?? undefined);
|
|
45
|
+
const { eligibilityMap, checkEligibility } = useRevenueCatTrialEligibility();
|
|
25
46
|
const { handlePurchase, handleRestore } = usePaywallActions({
|
|
26
47
|
userId: userId ?? undefined,
|
|
27
48
|
source: purchaseSource,
|
|
@@ -31,6 +52,47 @@ export const PaywallContainer: React.FC<PaywallContainerProps> = (props) => {
|
|
|
31
52
|
onClose: handleClose,
|
|
32
53
|
});
|
|
33
54
|
|
|
55
|
+
// Check trial eligibility only if trialConfig is enabled
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
if (!trialConfig?.enabled) return;
|
|
58
|
+
if (allPackages.length === 0) return;
|
|
59
|
+
|
|
60
|
+
// Get all actual product IDs from packages
|
|
61
|
+
const allProductIds = allPackages.map((pkg) => pkg.product.identifier);
|
|
62
|
+
|
|
63
|
+
// If eligibleProductIds are provided, filter to matching packages (partial match)
|
|
64
|
+
// e.g., "yearly" matches "futureus.yearly"
|
|
65
|
+
let productIdsToCheck: string[];
|
|
66
|
+
if (trialConfig.eligibleProductIds?.length) {
|
|
67
|
+
productIdsToCheck = allProductIds.filter((actualId) =>
|
|
68
|
+
trialConfig.eligibleProductIds?.some((configId) =>
|
|
69
|
+
actualId.toLowerCase().includes(configId.toLowerCase())
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
} else {
|
|
73
|
+
productIdsToCheck = allProductIds;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (productIdsToCheck.length > 0) {
|
|
77
|
+
checkEligibility(productIdsToCheck);
|
|
78
|
+
}
|
|
79
|
+
}, [allPackages, checkEligibility, trialConfig?.enabled, trialConfig?.eligibleProductIds]);
|
|
80
|
+
|
|
81
|
+
// Convert eligibility map to format expected by PaywallModal
|
|
82
|
+
// Only process if trial is enabled
|
|
83
|
+
const trialEligibility = useMemo((): Record<string, TrialEligibilityInfo> => {
|
|
84
|
+
if (!trialConfig?.enabled) return {};
|
|
85
|
+
|
|
86
|
+
const result: Record<string, TrialEligibilityInfo> = {};
|
|
87
|
+
for (const [productId, info] of Object.entries(eligibilityMap)) {
|
|
88
|
+
result[productId] = {
|
|
89
|
+
eligible: info.eligible,
|
|
90
|
+
durationDays: trialConfig.durationDays ?? info.trialDurationDays ?? 7,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return result;
|
|
94
|
+
}, [eligibilityMap, trialConfig?.enabled, trialConfig?.durationDays]);
|
|
95
|
+
|
|
34
96
|
const { filteredPackages, computedCreditAmounts } = useMemo(() => ({
|
|
35
97
|
filteredPackages: filterPackagesByMode(allPackages, mode, packageFilterConfig),
|
|
36
98
|
computedCreditAmounts: mode !== "subscription" && !creditAmounts ? createCreditAmountsFromPackages(allPackages) : creditAmounts
|
|
@@ -53,6 +115,8 @@ export const PaywallContainer: React.FC<PaywallContainerProps> = (props) => {
|
|
|
53
115
|
creditAmounts={computedCreditAmounts}
|
|
54
116
|
onPurchase={handlePurchase}
|
|
55
117
|
onRestore={handleRestore}
|
|
118
|
+
trialEligibility={trialEligibility}
|
|
119
|
+
trialSubtitleText={trialConfig?.enabled ? trialConfig.trialText : undefined}
|
|
56
120
|
/>
|
|
57
121
|
);
|
|
58
122
|
};
|
|
@@ -8,6 +8,21 @@ import type { PaywallMode, PaywallTranslations, PaywallLegalUrls, SubscriptionFe
|
|
|
8
8
|
import type { PackageFilterConfig } from "../../../utils/packageFilter";
|
|
9
9
|
import type { PurchaseSource } from "../../../domain/entities/Credits";
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Trial display configuration
|
|
13
|
+
* Controls how free trial info is displayed (Apple-compliant)
|
|
14
|
+
*/
|
|
15
|
+
export interface TrialConfig {
|
|
16
|
+
/** Enable trial display (default: false) */
|
|
17
|
+
readonly enabled: boolean;
|
|
18
|
+
/** Product IDs that have trial offers (if empty, checks all via RevenueCat) */
|
|
19
|
+
readonly eligibleProductIds?: readonly string[];
|
|
20
|
+
/** Trial duration in days (default: 7) */
|
|
21
|
+
readonly durationDays?: number;
|
|
22
|
+
/** Text to show for trial (e.g., "7 days free, then billed") */
|
|
23
|
+
readonly trialText?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
11
26
|
export interface PaywallContainerProps {
|
|
12
27
|
/** User ID for subscription management */
|
|
13
28
|
readonly userId: string | null;
|
|
@@ -43,5 +58,7 @@ export interface PaywallContainerProps {
|
|
|
43
58
|
readonly visible?: boolean;
|
|
44
59
|
/** Callback when paywall is closed */
|
|
45
60
|
readonly onClose?: () => void;
|
|
61
|
+
/** Trial display configuration (Apple-compliant) */
|
|
62
|
+
readonly trialConfig?: TrialConfig;
|
|
46
63
|
}
|
|
47
64
|
|
|
@@ -40,10 +40,12 @@ export interface PaywallModalProps {
|
|
|
40
40
|
onRestore?: () => Promise<void | boolean>;
|
|
41
41
|
/** Trial eligibility map per product ID */
|
|
42
42
|
trialEligibility?: Record<string, TrialEligibilityInfo>;
|
|
43
|
+
/** Trial subtitle text for PlanCard (e.g., "7 days free, then billed") */
|
|
44
|
+
trialSubtitleText?: string;
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
|
|
46
|
-
const { visible, onClose, translations, packages = [], features = [], isLoading = false, legalUrls = {}, bestValueIdentifier, creditAmounts, creditsLabel, heroImage, onPurchase, onRestore, trialEligibility = {} } = props;
|
|
48
|
+
const { visible, onClose, translations, packages = [], features = [], isLoading = false, legalUrls = {}, bestValueIdentifier, creditAmounts, creditsLabel, heroImage, onPurchase, onRestore, trialEligibility = {}, trialSubtitleText } = props;
|
|
47
49
|
const tokens = useAppDesignTokens();
|
|
48
50
|
const [selectedPlanId, setSelectedPlanId] = useState<string | null>(null);
|
|
49
51
|
const [isLocalProcessing, setIsLocalProcessing] = useState(false);
|
|
@@ -124,9 +126,10 @@ export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
|
|
|
124
126
|
|
|
125
127
|
<View style={styles.header}>
|
|
126
128
|
<AtomicText type="headlineMedium" style={[styles.title, { color: tokens.colors.textPrimary }]}>{translations.title}</AtomicText>
|
|
127
|
-
{
|
|
129
|
+
{/* Apple compliance: Don't promote trial in header, show regular subtitle only */}
|
|
130
|
+
{translations.subtitle && (
|
|
128
131
|
<AtomicText type="bodyMedium" style={[styles.subtitle, { color: tokens.colors.textSecondary }]}>
|
|
129
|
-
{translations.
|
|
132
|
+
{translations.subtitle}
|
|
130
133
|
</AtomicText>
|
|
131
134
|
)}
|
|
132
135
|
</View>
|
|
@@ -152,8 +155,7 @@ export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
|
|
|
152
155
|
creditAmount={creditAmounts?.[productId]}
|
|
153
156
|
creditsLabel={creditsLabel}
|
|
154
157
|
hasFreeTrial={hasFreeTrial}
|
|
155
|
-
|
|
156
|
-
trialBadgeText={hasFreeTrial ? translations.trialBadgeText : undefined}
|
|
158
|
+
trialSubtitleText={hasFreeTrial ? trialSubtitleText : undefined}
|
|
157
159
|
/>
|
|
158
160
|
);
|
|
159
161
|
})}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Plan Card
|
|
3
|
-
* Subscription plan selection card
|
|
3
|
+
* Subscription plan selection card (Apple-compliant)
|
|
4
|
+
*
|
|
5
|
+
* Apple Guideline 3.1.2 Compliance:
|
|
6
|
+
* - Price is the most prominent element
|
|
7
|
+
* - Trial info is displayed in subordinate position and size
|
|
8
|
+
* - No toggle for enabling/disabling trial
|
|
4
9
|
*/
|
|
5
10
|
|
|
6
11
|
import React from "react";
|
|
@@ -14,26 +19,22 @@ interface PlanCardProps {
|
|
|
14
19
|
pkg: PurchasesPackage;
|
|
15
20
|
isSelected: boolean;
|
|
16
21
|
onSelect: () => void;
|
|
22
|
+
/** Badge text (e.g., "Best Value") - NOT for trial */
|
|
17
23
|
badge?: string;
|
|
18
24
|
creditAmount?: number;
|
|
19
25
|
creditsLabel?: string;
|
|
20
|
-
/** Whether this plan has a free trial */
|
|
26
|
+
/** Whether this plan has a free trial (Apple-compliant display) */
|
|
21
27
|
hasFreeTrial?: boolean;
|
|
22
|
-
/** Trial
|
|
23
|
-
|
|
24
|
-
/** Trial badge text (e.g., "7 days free") */
|
|
25
|
-
trialBadgeText?: string;
|
|
28
|
+
/** Trial subtitle text (e.g., "7 days free, then billed") - shown as small gray text */
|
|
29
|
+
trialSubtitleText?: string;
|
|
26
30
|
}
|
|
27
31
|
|
|
28
32
|
export const PlanCard: React.FC<PlanCardProps> = React.memo(
|
|
29
|
-
({ pkg, isSelected, onSelect, badge, creditAmount, creditsLabel, hasFreeTrial,
|
|
33
|
+
({ pkg, isSelected, onSelect, badge, creditAmount, creditsLabel, hasFreeTrial, trialSubtitleText }) => {
|
|
30
34
|
const tokens = useAppDesignTokens();
|
|
31
35
|
const title = pkg.product.title;
|
|
32
36
|
const price = formatPrice(pkg.product.price, pkg.product.currencyCode);
|
|
33
37
|
|
|
34
|
-
// Determine which badge to show (trial badge takes priority if eligible)
|
|
35
|
-
const displayBadge = hasFreeTrial && trialBadgeText ? trialBadgeText : badge;
|
|
36
|
-
|
|
37
38
|
return (
|
|
38
39
|
<TouchableOpacity onPress={onSelect} activeOpacity={0.7} style={styles.touchable}>
|
|
39
40
|
<View
|
|
@@ -46,13 +47,10 @@ export const PlanCard: React.FC<PlanCardProps> = React.memo(
|
|
|
46
47
|
},
|
|
47
48
|
]}
|
|
48
49
|
>
|
|
49
|
-
{
|
|
50
|
+
{/* Badge for "Best Value" etc. - NOT for trial (Apple compliance) */}
|
|
51
|
+
{badge && (
|
|
50
52
|
<View style={styles.badgeContainer}>
|
|
51
|
-
<AtomicBadge
|
|
52
|
-
text={displayBadge}
|
|
53
|
-
variant={hasFreeTrial ? "success" : "primary"}
|
|
54
|
-
size="sm"
|
|
55
|
-
/>
|
|
53
|
+
<AtomicBadge text={badge} variant="primary" size="sm" />
|
|
56
54
|
</View>
|
|
57
55
|
)}
|
|
58
56
|
|
|
@@ -76,17 +74,38 @@ export const PlanCard: React.FC<PlanCardProps> = React.memo(
|
|
|
76
74
|
<AtomicText type="titleSmall" style={{ color: tokens.colors.textPrimary, fontWeight: "600" }}>
|
|
77
75
|
{title}
|
|
78
76
|
</AtomicText>
|
|
77
|
+
|
|
78
|
+
{/* Credits info */}
|
|
79
79
|
{creditAmount && creditsLabel && (
|
|
80
80
|
<AtomicText type="bodySmall" style={{ color: tokens.colors.textSecondary }}>
|
|
81
81
|
{creditAmount} {creditsLabel}
|
|
82
82
|
</AtomicText>
|
|
83
83
|
)}
|
|
84
|
+
|
|
85
|
+
{/* Trial info - Apple-compliant: small, gray, subordinate */}
|
|
86
|
+
{hasFreeTrial && trialSubtitleText && (
|
|
87
|
+
<AtomicText
|
|
88
|
+
type="bodySmall"
|
|
89
|
+
style={{
|
|
90
|
+
color: tokens.colors.textTertiary ?? tokens.colors.textSecondary,
|
|
91
|
+
fontSize: 11,
|
|
92
|
+
marginTop: 2,
|
|
93
|
+
}}
|
|
94
|
+
>
|
|
95
|
+
{trialSubtitleText}
|
|
96
|
+
</AtomicText>
|
|
97
|
+
)}
|
|
84
98
|
</View>
|
|
85
99
|
</View>
|
|
86
100
|
|
|
101
|
+
{/* Price - MOST PROMINENT (Apple compliance) */}
|
|
87
102
|
<AtomicText
|
|
88
103
|
type="titleMedium"
|
|
89
|
-
style={{
|
|
104
|
+
style={{
|
|
105
|
+
color: isSelected ? tokens.colors.primary : tokens.colors.textPrimary,
|
|
106
|
+
fontWeight: "700",
|
|
107
|
+
fontSize: 18,
|
|
108
|
+
}}
|
|
90
109
|
>
|
|
91
110
|
{price}
|
|
92
111
|
</AtomicText>
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
export { PaywallContainer } from "./PaywallContainer";
|
|
6
|
-
export type { PaywallContainerProps } from "./PaywallContainer.types";
|
|
6
|
+
export type { PaywallContainerProps, TrialConfig } from "./PaywallContainer.types";
|
|
7
7
|
|
|
8
8
|
export { PaywallModal } from "./PaywallModal";
|
|
9
9
|
export type { PaywallModalProps } from "./PaywallModal";
|
|
@@ -41,10 +41,6 @@ export interface PaywallTranslations {
|
|
|
41
41
|
privacyText?: string;
|
|
42
42
|
termsOfServiceText?: string;
|
|
43
43
|
bestValueBadgeText?: string;
|
|
44
|
-
/** Trial-related translations */
|
|
45
|
-
trialBadgeText?: string;
|
|
46
|
-
/** Trial subtitle (e.g., "Try free for 7 days, then $X/year") */
|
|
47
|
-
trialSubtitle?: string;
|
|
48
44
|
}
|
|
49
45
|
|
|
50
46
|
export interface PaywallLegalUrls {
|
|
@@ -13,10 +13,6 @@ interface PaywallTranslationKeys {
|
|
|
13
13
|
processingText: string;
|
|
14
14
|
privacyText: string;
|
|
15
15
|
termsOfServiceText: string;
|
|
16
|
-
/** Trial badge text key */
|
|
17
|
-
trialBadgeText?: string;
|
|
18
|
-
/** Trial subtitle key */
|
|
19
|
-
trialSubtitle?: string;
|
|
20
16
|
}
|
|
21
17
|
|
|
22
18
|
interface UsePaywallTranslationsParams {
|
|
@@ -42,8 +38,6 @@ const DEFAULT_KEYS: PaywallTranslationKeys = {
|
|
|
42
38
|
processingText: "paywall.processing",
|
|
43
39
|
privacyText: "auth.privacyPolicy",
|
|
44
40
|
termsOfServiceText: "auth.termsOfService",
|
|
45
|
-
trialBadgeText: "paywall.trial.badge",
|
|
46
|
-
trialSubtitle: "paywall.trial.subtitle",
|
|
47
41
|
};
|
|
48
42
|
|
|
49
43
|
export const usePaywallTranslations = ({
|
|
@@ -68,8 +62,6 @@ export const usePaywallTranslations = ({
|
|
|
68
62
|
processingText: t(mergedKeys.processingText),
|
|
69
63
|
privacyText: t(mergedKeys.privacyText),
|
|
70
64
|
termsOfServiceText: t(mergedKeys.termsOfServiceText),
|
|
71
|
-
trialBadgeText: mergedKeys.trialBadgeText ? t(mergedKeys.trialBadgeText) : undefined,
|
|
72
|
-
trialSubtitle: mergedKeys.trialSubtitle ? t(mergedKeys.trialSubtitle) : undefined,
|
|
73
65
|
}),
|
|
74
66
|
[t, mergedKeys],
|
|
75
67
|
);
|
package/src/global.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global type declarations for React Native environment
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/** React Native development flag */
|
|
6
|
+
declare const __DEV__: boolean;
|
|
7
|
+
|
|
8
|
+
/** Extend NodeJS namespace for React Native compatibility */
|
|
9
|
+
declare namespace NodeJS {
|
|
10
|
+
interface Global {
|
|
11
|
+
__DEV__: boolean;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -56,14 +56,21 @@ export function getPremiumEntitlement(
|
|
|
56
56
|
};
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/**
|
|
60
|
+
* Type guard for RevenueCat purchase error
|
|
61
|
+
*/
|
|
62
|
+
function isRevenueCatPurchaseError(error: unknown): error is RevenueCatPurchaseErrorInfo {
|
|
63
|
+
return error instanceof Error && "userCancelled" in error;
|
|
64
|
+
}
|
|
65
|
+
|
|
59
66
|
/**
|
|
60
67
|
* Check if error is a user cancellation
|
|
61
68
|
*/
|
|
62
69
|
export function isUserCancelledError(error: unknown): boolean {
|
|
63
|
-
if (!error
|
|
70
|
+
if (!isRevenueCatPurchaseError(error)) {
|
|
64
71
|
return false;
|
|
65
72
|
}
|
|
66
|
-
return
|
|
73
|
+
return error.userCancelled === true;
|
|
67
74
|
}
|
|
68
75
|
|
|
69
76
|
/**
|
|
@@ -76,34 +83,3 @@ export function getErrorMessage(error: unknown, fallback: string): string {
|
|
|
76
83
|
return fallback;
|
|
77
84
|
}
|
|
78
85
|
|
|
79
|
-
/**
|
|
80
|
-
* Trial Eligibility Types
|
|
81
|
-
* For RevenueCat introductory offer (free trial) support
|
|
82
|
-
*/
|
|
83
|
-
|
|
84
|
-
/** Trial info for a subscription product */
|
|
85
|
-
export interface TrialInfo {
|
|
86
|
-
/** Whether user is eligible for trial */
|
|
87
|
-
eligible: boolean;
|
|
88
|
-
/** Trial duration in days */
|
|
89
|
-
durationDays: number;
|
|
90
|
-
/** Product identifier */
|
|
91
|
-
productId: string;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/** Configuration for trial display */
|
|
95
|
-
export interface TrialDisplayConfig {
|
|
96
|
-
/** Product IDs that have trial offers */
|
|
97
|
-
trialProductIds: string[];
|
|
98
|
-
/** Default trial duration in days */
|
|
99
|
-
defaultTrialDays: number;
|
|
100
|
-
/** Whether to show trial badge */
|
|
101
|
-
showTrialBadge: boolean;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/** Default trial configuration */
|
|
105
|
-
export const DEFAULT_TRIAL_CONFIG: TrialDisplayConfig = {
|
|
106
|
-
trialProductIds: [],
|
|
107
|
-
defaultTrialDays: 7,
|
|
108
|
-
showTrialBadge: true,
|
|
109
|
-
};
|