@umituz/react-native-subscription 2.11.8 → 2.11.10
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/index.ts +8 -0
- package/src/presentation/components/paywall/SubscriptionModal.tsx +1 -26
- package/src/presentation/components/paywall/SubscriptionPackageList.tsx +14 -5
- package/src/presentation/components/paywall/accordion/AccordionPlanCard.tsx +93 -0
- package/src/presentation/components/paywall/accordion/AccordionPlanCardTypes.ts +33 -0
- package/src/presentation/components/paywall/accordion/PlanCardDetails.tsx +101 -0
- package/src/presentation/components/paywall/accordion/PlanCardHeader.tsx +159 -0
- package/src/presentation/components/paywall/accordion/index.ts +12 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-subscription",
|
|
3
|
-
"version": "2.11.
|
|
3
|
+
"version": "2.11.10",
|
|
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",
|
package/src/index.ts
CHANGED
|
@@ -71,6 +71,14 @@ export {
|
|
|
71
71
|
export { SubscriptionModalHeader } from "./presentation/components/paywall/SubscriptionModalHeader";
|
|
72
72
|
|
|
73
73
|
export { SubscriptionPlanCard } from "./presentation/components/paywall/SubscriptionPlanCard";
|
|
74
|
+
export {
|
|
75
|
+
AccordionPlanCard,
|
|
76
|
+
PlanCardHeader,
|
|
77
|
+
PlanCardDetails,
|
|
78
|
+
type AccordionPlanCardProps,
|
|
79
|
+
type PlanCardHeaderProps,
|
|
80
|
+
type PlanCardDetailsProps,
|
|
81
|
+
} from "./presentation/components/paywall/accordion";
|
|
74
82
|
export { PaywallFeaturesList } from "./presentation/components/paywall/PaywallFeaturesList";
|
|
75
83
|
export { PaywallFeatureItem } from "./presentation/components/paywall/PaywallFeatureItem";
|
|
76
84
|
export { PaywallLegalFooter } from "./presentation/components/paywall/PaywallLegalFooter";
|
|
@@ -5,11 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
import React from "react";
|
|
7
7
|
import { View, StyleSheet, ScrollView } from "react-native";
|
|
8
|
-
import {
|
|
8
|
+
import { BaseModal } from "@umituz/react-native-design-system";
|
|
9
9
|
import type { PurchasesPackage } from "react-native-purchases";
|
|
10
10
|
|
|
11
11
|
import { SubscriptionModalHeader } from "./SubscriptionModalHeader";
|
|
12
|
-
import { PaywallFeaturesList } from "./PaywallFeaturesList";
|
|
13
12
|
import { SubscriptionPackageList } from "./SubscriptionPackageList";
|
|
14
13
|
import { SubscriptionFooter } from "./SubscriptionFooter";
|
|
15
14
|
import { useSubscriptionModal } from "../../hooks/useSubscriptionModal";
|
|
@@ -22,7 +21,6 @@ export interface SubscriptionModalProps {
|
|
|
22
21
|
onRestore: () => Promise<boolean>;
|
|
23
22
|
title: string;
|
|
24
23
|
subtitle?: string;
|
|
25
|
-
features?: Array<{ icon: string; text: string }>;
|
|
26
24
|
isLoading?: boolean;
|
|
27
25
|
purchaseButtonText: string;
|
|
28
26
|
restoreButtonText: string;
|
|
@@ -49,7 +47,6 @@ export const SubscriptionModal: React.FC<SubscriptionModalProps> = React.memo((p
|
|
|
49
47
|
onRestore,
|
|
50
48
|
title,
|
|
51
49
|
subtitle,
|
|
52
|
-
features,
|
|
53
50
|
isLoading = false,
|
|
54
51
|
purchaseButtonText,
|
|
55
52
|
restoreButtonText,
|
|
@@ -65,8 +62,6 @@ export const SubscriptionModal: React.FC<SubscriptionModalProps> = React.memo((p
|
|
|
65
62
|
bestValueIdentifier,
|
|
66
63
|
} = props;
|
|
67
64
|
|
|
68
|
-
const tokens = useAppDesignTokens();
|
|
69
|
-
|
|
70
65
|
const {
|
|
71
66
|
selectedPkg,
|
|
72
67
|
setSelectedPkg,
|
|
@@ -104,20 +99,6 @@ export const SubscriptionModal: React.FC<SubscriptionModalProps> = React.memo((p
|
|
|
104
99
|
creditAmounts={creditAmounts}
|
|
105
100
|
bestValueIdentifier={bestValueIdentifier}
|
|
106
101
|
/>
|
|
107
|
-
|
|
108
|
-
{features && features.length > 0 && (
|
|
109
|
-
<View
|
|
110
|
-
style={[
|
|
111
|
-
styles.featuresSection,
|
|
112
|
-
{
|
|
113
|
-
backgroundColor: tokens.colors.surfaceSecondary,
|
|
114
|
-
borderColor: tokens.colors.border
|
|
115
|
-
}
|
|
116
|
-
]}
|
|
117
|
-
>
|
|
118
|
-
<PaywallFeaturesList features={features} gap={12} />
|
|
119
|
-
</View>
|
|
120
|
-
)}
|
|
121
102
|
</ScrollView>
|
|
122
103
|
|
|
123
104
|
<SubscriptionFooter
|
|
@@ -155,10 +136,4 @@ const styles = StyleSheet.create({
|
|
|
155
136
|
flexGrow: 1,
|
|
156
137
|
paddingBottom: 32,
|
|
157
138
|
},
|
|
158
|
-
featuresSection: {
|
|
159
|
-
borderRadius: 24,
|
|
160
|
-
padding: 24,
|
|
161
|
-
marginTop: 12,
|
|
162
|
-
borderWidth: 1,
|
|
163
|
-
},
|
|
164
139
|
});
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useState, useCallback } from "react";
|
|
2
2
|
import { View, StyleSheet, ActivityIndicator } from "react-native";
|
|
3
3
|
import { AtomicText } from "@umituz/react-native-design-system";
|
|
4
4
|
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
5
5
|
import type { PurchasesPackage } from "react-native-purchases";
|
|
6
|
-
import {
|
|
6
|
+
import { AccordionPlanCard } from "./accordion";
|
|
7
7
|
import { isYearlyPackage, isMonthlyPackage, isWeeklyPackage } from "../../../utils/packagePeriodUtils";
|
|
8
8
|
|
|
9
9
|
interface SubscriptionPackageListProps {
|
|
@@ -34,6 +34,12 @@ export const SubscriptionPackageList: React.FC<SubscriptionPackageListProps> = R
|
|
|
34
34
|
const hasPackages = packages.length > 0;
|
|
35
35
|
const showLoading = isLoading && !hasPackages;
|
|
36
36
|
|
|
37
|
+
const [expandedPackageId, setExpandedPackageId] = useState<string | null>(null);
|
|
38
|
+
|
|
39
|
+
const handleToggleExpand = useCallback((packageId: string) => {
|
|
40
|
+
setExpandedPackageId((prev) => (prev === packageId ? null : packageId));
|
|
41
|
+
}, []);
|
|
42
|
+
|
|
37
43
|
if (showLoading) {
|
|
38
44
|
return (
|
|
39
45
|
<View style={styles.centerContent}>
|
|
@@ -115,13 +121,16 @@ export const SubscriptionPackageList: React.FC<SubscriptionPackageListProps> = R
|
|
|
115
121
|
};
|
|
116
122
|
|
|
117
123
|
const creditAmount = findCreditAmount();
|
|
124
|
+
const packageId = pkg.product.identifier;
|
|
118
125
|
|
|
119
126
|
return (
|
|
120
|
-
<
|
|
121
|
-
key={
|
|
127
|
+
<AccordionPlanCard
|
|
128
|
+
key={packageId}
|
|
122
129
|
package={pkg}
|
|
123
|
-
isSelected={selectedPkg?.product.identifier ===
|
|
130
|
+
isSelected={selectedPkg?.product.identifier === packageId}
|
|
131
|
+
isExpanded={expandedPackageId === packageId}
|
|
124
132
|
onSelect={() => onSelect(pkg)}
|
|
133
|
+
onToggleExpand={() => handleToggleExpand(packageId)}
|
|
125
134
|
isBestValue={isBestValue}
|
|
126
135
|
creditAmount={creditAmount}
|
|
127
136
|
/>
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accordion Plan Card
|
|
3
|
+
* Expandable subscription plan card with credit display
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React, { useCallback } from "react";
|
|
7
|
+
import { View, StyleSheet, type StyleProp, type ViewStyle } from "react-native";
|
|
8
|
+
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
9
|
+
import { formatPrice } from "../../../../utils/priceUtils";
|
|
10
|
+
import { getPeriodLabel, isYearlyPackage } from "../../../../utils/packagePeriodUtils";
|
|
11
|
+
import { useLocalization } from "@umituz/react-native-localization";
|
|
12
|
+
import { PlanCardHeader } from "./PlanCardHeader";
|
|
13
|
+
import { PlanCardDetails } from "./PlanCardDetails";
|
|
14
|
+
import type { AccordionPlanCardProps } from "./AccordionPlanCardTypes";
|
|
15
|
+
|
|
16
|
+
export const AccordionPlanCard: React.FC<AccordionPlanCardProps> = React.memo(
|
|
17
|
+
({
|
|
18
|
+
package: pkg,
|
|
19
|
+
isSelected,
|
|
20
|
+
isExpanded,
|
|
21
|
+
onSelect,
|
|
22
|
+
onToggleExpand,
|
|
23
|
+
isBestValue = false,
|
|
24
|
+
creditAmount,
|
|
25
|
+
}) => {
|
|
26
|
+
const tokens = useAppDesignTokens();
|
|
27
|
+
const { t } = useLocalization();
|
|
28
|
+
|
|
29
|
+
const period = pkg.product.subscriptionPeriod;
|
|
30
|
+
const isYearly = isYearlyPackage(pkg);
|
|
31
|
+
const periodLabel = getPeriodLabel(period);
|
|
32
|
+
const price = formatPrice(pkg.product.price, pkg.product.currencyCode);
|
|
33
|
+
const monthlyEquivalent = isYearly
|
|
34
|
+
? formatPrice(pkg.product.price / 12, pkg.product.currencyCode)
|
|
35
|
+
: null;
|
|
36
|
+
|
|
37
|
+
const title = pkg.product.title || t(`paywall.period.${periodLabel}`);
|
|
38
|
+
const displayPrice = isYearly && monthlyEquivalent
|
|
39
|
+
? `${monthlyEquivalent}/mo`
|
|
40
|
+
: price;
|
|
41
|
+
|
|
42
|
+
const handleHeaderPress = useCallback(() => {
|
|
43
|
+
onSelect();
|
|
44
|
+
if (!isExpanded) {
|
|
45
|
+
onToggleExpand();
|
|
46
|
+
}
|
|
47
|
+
}, [onSelect, onToggleExpand, isExpanded]);
|
|
48
|
+
|
|
49
|
+
const containerStyle: StyleProp<ViewStyle> = [
|
|
50
|
+
styles.container,
|
|
51
|
+
{
|
|
52
|
+
borderColor: isSelected
|
|
53
|
+
? tokens.colors.primary
|
|
54
|
+
: tokens.colors.borderLight,
|
|
55
|
+
borderWidth: isSelected ? 2 : 1,
|
|
56
|
+
backgroundColor: tokens.colors.surface,
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<View style={containerStyle}>
|
|
62
|
+
<PlanCardHeader
|
|
63
|
+
title={title}
|
|
64
|
+
price={displayPrice}
|
|
65
|
+
creditAmount={creditAmount}
|
|
66
|
+
isSelected={isSelected}
|
|
67
|
+
isExpanded={isExpanded}
|
|
68
|
+
isBestValue={isBestValue}
|
|
69
|
+
onToggle={handleHeaderPress}
|
|
70
|
+
/>
|
|
71
|
+
|
|
72
|
+
{isExpanded && (
|
|
73
|
+
<PlanCardDetails
|
|
74
|
+
fullPrice={price}
|
|
75
|
+
monthlyEquivalent={monthlyEquivalent}
|
|
76
|
+
periodLabel={periodLabel}
|
|
77
|
+
isYearly={isYearly}
|
|
78
|
+
/>
|
|
79
|
+
)}
|
|
80
|
+
</View>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
AccordionPlanCard.displayName = "AccordionPlanCard";
|
|
86
|
+
|
|
87
|
+
const styles = StyleSheet.create({
|
|
88
|
+
container: {
|
|
89
|
+
borderRadius: 16,
|
|
90
|
+
overflow: "hidden",
|
|
91
|
+
marginBottom: 12,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accordion Plan Card Types
|
|
3
|
+
* Type definitions for accordion-style subscription cards
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { PurchasesPackage } from "react-native-purchases";
|
|
7
|
+
|
|
8
|
+
export interface AccordionPlanCardProps {
|
|
9
|
+
package: PurchasesPackage;
|
|
10
|
+
isSelected: boolean;
|
|
11
|
+
isExpanded: boolean;
|
|
12
|
+
onSelect: () => void;
|
|
13
|
+
onToggleExpand: () => void;
|
|
14
|
+
isBestValue?: boolean;
|
|
15
|
+
creditAmount?: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface PlanCardHeaderProps {
|
|
19
|
+
title: string;
|
|
20
|
+
price: string;
|
|
21
|
+
creditAmount?: number;
|
|
22
|
+
isSelected: boolean;
|
|
23
|
+
isExpanded: boolean;
|
|
24
|
+
isBestValue?: boolean;
|
|
25
|
+
onToggle: () => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface PlanCardDetailsProps {
|
|
29
|
+
fullPrice: string;
|
|
30
|
+
monthlyEquivalent: string | null;
|
|
31
|
+
periodLabel: string;
|
|
32
|
+
isYearly: boolean;
|
|
33
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Card Details
|
|
3
|
+
* Expanded state of accordion subscription card
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { View, StyleSheet } from "react-native";
|
|
8
|
+
import {
|
|
9
|
+
AtomicText,
|
|
10
|
+
useAppDesignTokens,
|
|
11
|
+
} from "@umituz/react-native-design-system";
|
|
12
|
+
import { useLocalization } from "@umituz/react-native-localization";
|
|
13
|
+
import type { PlanCardDetailsProps } from "./AccordionPlanCardTypes";
|
|
14
|
+
|
|
15
|
+
export const PlanCardDetails: React.FC<PlanCardDetailsProps> = ({
|
|
16
|
+
fullPrice,
|
|
17
|
+
monthlyEquivalent,
|
|
18
|
+
periodLabel,
|
|
19
|
+
isYearly,
|
|
20
|
+
}) => {
|
|
21
|
+
const tokens = useAppDesignTokens();
|
|
22
|
+
const { t } = useLocalization();
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<View
|
|
26
|
+
style={[
|
|
27
|
+
styles.container,
|
|
28
|
+
{
|
|
29
|
+
backgroundColor: tokens.colors.surfaceSecondary,
|
|
30
|
+
borderTopColor: tokens.colors.border,
|
|
31
|
+
},
|
|
32
|
+
]}
|
|
33
|
+
>
|
|
34
|
+
<View style={styles.row}>
|
|
35
|
+
<AtomicText
|
|
36
|
+
type="bodyMedium"
|
|
37
|
+
style={{ color: tokens.colors.textSecondary }}
|
|
38
|
+
>
|
|
39
|
+
{t("paywall.billingPeriod") || "Billing Period"}
|
|
40
|
+
</AtomicText>
|
|
41
|
+
<AtomicText
|
|
42
|
+
type="bodyMedium"
|
|
43
|
+
style={{ color: tokens.colors.textPrimary, fontWeight: "600" }}
|
|
44
|
+
>
|
|
45
|
+
{t(`paywall.period.${periodLabel}`)}
|
|
46
|
+
</AtomicText>
|
|
47
|
+
</View>
|
|
48
|
+
|
|
49
|
+
{isYearly && (
|
|
50
|
+
<View style={styles.row}>
|
|
51
|
+
<AtomicText
|
|
52
|
+
type="bodyMedium"
|
|
53
|
+
style={{ color: tokens.colors.textSecondary }}
|
|
54
|
+
>
|
|
55
|
+
{t("paywall.totalPrice") || "Total Price"}
|
|
56
|
+
</AtomicText>
|
|
57
|
+
<AtomicText
|
|
58
|
+
type="bodyMedium"
|
|
59
|
+
style={{ color: tokens.colors.textPrimary, fontWeight: "600" }}
|
|
60
|
+
>
|
|
61
|
+
{fullPrice}
|
|
62
|
+
</AtomicText>
|
|
63
|
+
</View>
|
|
64
|
+
)}
|
|
65
|
+
|
|
66
|
+
{monthlyEquivalent && (
|
|
67
|
+
<View style={styles.row}>
|
|
68
|
+
<AtomicText
|
|
69
|
+
type="bodyMedium"
|
|
70
|
+
style={{ color: tokens.colors.textSecondary }}
|
|
71
|
+
>
|
|
72
|
+
{t("paywall.perMonth") || "Per Month"}
|
|
73
|
+
</AtomicText>
|
|
74
|
+
<AtomicText
|
|
75
|
+
type="bodyMedium"
|
|
76
|
+
style={{
|
|
77
|
+
color: tokens.colors.primary,
|
|
78
|
+
fontWeight: "700",
|
|
79
|
+
}}
|
|
80
|
+
>
|
|
81
|
+
{monthlyEquivalent}
|
|
82
|
+
</AtomicText>
|
|
83
|
+
</View>
|
|
84
|
+
)}
|
|
85
|
+
</View>
|
|
86
|
+
);
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const styles = StyleSheet.create({
|
|
90
|
+
container: {
|
|
91
|
+
paddingHorizontal: 16,
|
|
92
|
+
paddingVertical: 12,
|
|
93
|
+
borderTopWidth: 1,
|
|
94
|
+
gap: 10,
|
|
95
|
+
},
|
|
96
|
+
row: {
|
|
97
|
+
flexDirection: "row",
|
|
98
|
+
justifyContent: "space-between",
|
|
99
|
+
alignItems: "center",
|
|
100
|
+
},
|
|
101
|
+
});
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan Card Header
|
|
3
|
+
* Collapsed state of accordion subscription card
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from "react";
|
|
7
|
+
import { View, TouchableOpacity, StyleSheet } from "react-native";
|
|
8
|
+
import {
|
|
9
|
+
AtomicText,
|
|
10
|
+
AtomicIcon,
|
|
11
|
+
useAppDesignTokens,
|
|
12
|
+
withAlpha,
|
|
13
|
+
} from "@umituz/react-native-design-system";
|
|
14
|
+
import { BestValueBadge } from "../BestValueBadge";
|
|
15
|
+
import { useLocalization } from "@umituz/react-native-localization";
|
|
16
|
+
import type { PlanCardHeaderProps } from "./AccordionPlanCardTypes";
|
|
17
|
+
|
|
18
|
+
export const PlanCardHeader: React.FC<PlanCardHeaderProps> = ({
|
|
19
|
+
title,
|
|
20
|
+
price,
|
|
21
|
+
creditAmount,
|
|
22
|
+
isSelected,
|
|
23
|
+
isExpanded,
|
|
24
|
+
isBestValue,
|
|
25
|
+
onToggle,
|
|
26
|
+
}) => {
|
|
27
|
+
const tokens = useAppDesignTokens();
|
|
28
|
+
const { t } = useLocalization();
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<TouchableOpacity
|
|
32
|
+
onPress={onToggle}
|
|
33
|
+
activeOpacity={0.7}
|
|
34
|
+
style={styles.container}
|
|
35
|
+
>
|
|
36
|
+
<BestValueBadge text={t("paywall.bestValue")} visible={isBestValue} />
|
|
37
|
+
|
|
38
|
+
<View style={styles.content}>
|
|
39
|
+
<View style={styles.leftSection}>
|
|
40
|
+
<View
|
|
41
|
+
style={[
|
|
42
|
+
styles.radio,
|
|
43
|
+
{
|
|
44
|
+
borderColor: isSelected
|
|
45
|
+
? tokens.colors.primary
|
|
46
|
+
: tokens.colors.border,
|
|
47
|
+
},
|
|
48
|
+
]}
|
|
49
|
+
>
|
|
50
|
+
{isSelected && (
|
|
51
|
+
<View
|
|
52
|
+
style={[
|
|
53
|
+
styles.radioInner,
|
|
54
|
+
{ backgroundColor: tokens.colors.primary },
|
|
55
|
+
]}
|
|
56
|
+
/>
|
|
57
|
+
)}
|
|
58
|
+
</View>
|
|
59
|
+
|
|
60
|
+
<View style={styles.textContainer}>
|
|
61
|
+
<AtomicText
|
|
62
|
+
type="titleSmall"
|
|
63
|
+
style={{ color: tokens.colors.textPrimary, fontWeight: "600" }}
|
|
64
|
+
>
|
|
65
|
+
{title}
|
|
66
|
+
</AtomicText>
|
|
67
|
+
{creditAmount && (
|
|
68
|
+
<View
|
|
69
|
+
style={[
|
|
70
|
+
styles.creditBadge,
|
|
71
|
+
{
|
|
72
|
+
backgroundColor: withAlpha(tokens.colors.primary, 0.15),
|
|
73
|
+
borderColor: withAlpha(tokens.colors.primary, 0.3),
|
|
74
|
+
},
|
|
75
|
+
]}
|
|
76
|
+
>
|
|
77
|
+
<AtomicText
|
|
78
|
+
type="labelSmall"
|
|
79
|
+
style={{
|
|
80
|
+
color: tokens.colors.primary,
|
|
81
|
+
fontWeight: "700",
|
|
82
|
+
fontSize: 11,
|
|
83
|
+
}}
|
|
84
|
+
>
|
|
85
|
+
{creditAmount} {t("paywall.credits") || "Credits"}
|
|
86
|
+
</AtomicText>
|
|
87
|
+
</View>
|
|
88
|
+
)}
|
|
89
|
+
</View>
|
|
90
|
+
</View>
|
|
91
|
+
|
|
92
|
+
<View style={styles.rightSection}>
|
|
93
|
+
<AtomicText
|
|
94
|
+
type="titleMedium"
|
|
95
|
+
style={{
|
|
96
|
+
color: tokens.colors.textPrimary,
|
|
97
|
+
fontWeight: "700",
|
|
98
|
+
marginRight: 8,
|
|
99
|
+
}}
|
|
100
|
+
>
|
|
101
|
+
{price}
|
|
102
|
+
</AtomicText>
|
|
103
|
+
<AtomicIcon
|
|
104
|
+
name={isExpanded ? "ChevronUp" : "ChevronDown"}
|
|
105
|
+
size={20}
|
|
106
|
+
color={tokens.colors.textSecondary as any}
|
|
107
|
+
/>
|
|
108
|
+
</View>
|
|
109
|
+
</View>
|
|
110
|
+
</TouchableOpacity>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const styles = StyleSheet.create({
|
|
115
|
+
container: {
|
|
116
|
+
width: "100%",
|
|
117
|
+
},
|
|
118
|
+
content: {
|
|
119
|
+
flexDirection: "row",
|
|
120
|
+
alignItems: "center",
|
|
121
|
+
justifyContent: "space-between",
|
|
122
|
+
paddingVertical: 16,
|
|
123
|
+
paddingHorizontal: 16,
|
|
124
|
+
},
|
|
125
|
+
leftSection: {
|
|
126
|
+
flexDirection: "row",
|
|
127
|
+
alignItems: "center",
|
|
128
|
+
flex: 1,
|
|
129
|
+
},
|
|
130
|
+
radio: {
|
|
131
|
+
width: 22,
|
|
132
|
+
height: 22,
|
|
133
|
+
borderRadius: 11,
|
|
134
|
+
borderWidth: 2,
|
|
135
|
+
alignItems: "center",
|
|
136
|
+
justifyContent: "center",
|
|
137
|
+
marginRight: 12,
|
|
138
|
+
},
|
|
139
|
+
radioInner: {
|
|
140
|
+
width: 12,
|
|
141
|
+
height: 12,
|
|
142
|
+
borderRadius: 6,
|
|
143
|
+
},
|
|
144
|
+
textContainer: {
|
|
145
|
+
flex: 1,
|
|
146
|
+
gap: 6,
|
|
147
|
+
},
|
|
148
|
+
creditBadge: {
|
|
149
|
+
paddingHorizontal: 10,
|
|
150
|
+
paddingVertical: 4,
|
|
151
|
+
borderRadius: 12,
|
|
152
|
+
borderWidth: 1,
|
|
153
|
+
alignSelf: "flex-start",
|
|
154
|
+
},
|
|
155
|
+
rightSection: {
|
|
156
|
+
flexDirection: "row",
|
|
157
|
+
alignItems: "center",
|
|
158
|
+
},
|
|
159
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Accordion Components Barrel Export
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export { AccordionPlanCard } from "./AccordionPlanCard";
|
|
6
|
+
export { PlanCardHeader } from "./PlanCardHeader";
|
|
7
|
+
export { PlanCardDetails } from "./PlanCardDetails";
|
|
8
|
+
export type {
|
|
9
|
+
AccordionPlanCardProps,
|
|
10
|
+
PlanCardHeaderProps,
|
|
11
|
+
PlanCardDetailsProps,
|
|
12
|
+
} from "./AccordionPlanCardTypes";
|