@onairos/react-native 1.0.3 → 2.0.1
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/lib/commonjs/api/index.js +34 -0
- package/lib/commonjs/api/index.js.map +1 -0
- package/lib/commonjs/components/OnairosButton.js +59 -20
- package/lib/commonjs/components/OnairosButton.js.map +1 -1
- package/lib/commonjs/components/Overlay.js +180 -197
- package/lib/commonjs/components/Overlay.js.map +1 -1
- package/lib/commonjs/constants/index.js +13 -9
- package/lib/commonjs/constants/index.js.map +1 -1
- package/lib/commonjs/index.js +220 -0
- package/lib/commonjs/utils/encryption.js +32 -0
- package/lib/commonjs/utils/encryption.js.map +1 -0
- package/lib/module/api/index.js +27 -0
- package/lib/module/api/index.js.map +1 -0
- package/lib/module/components/OnairosButton.js +59 -20
- package/lib/module/components/OnairosButton.js.map +1 -1
- package/lib/module/components/Overlay.js +182 -198
- package/lib/module/components/Overlay.js.map +1 -1
- package/lib/module/constants/index.js +13 -9
- package/lib/module/constants/index.js.map +1 -1
- package/lib/module/utils/encryption.js +24 -0
- package/lib/module/utils/encryption.js.map +1 -0
- package/package.json +2 -1
- package/src/api/index.ts +33 -0
- package/src/components/OnairosButton.tsx +66 -22
- package/src/components/Overlay.tsx +198 -185
- package/src/constants/index.ts +12 -8
- package/src/types/index.ts +20 -14
- package/src/utils/encryption.ts +25 -0
|
@@ -1,49 +1,79 @@
|
|
|
1
1
|
import React, { useState } from 'react';
|
|
2
|
-
import { TouchableOpacity, Text, StyleSheet, View } from 'react-native';
|
|
2
|
+
import { TouchableOpacity, Text, StyleSheet, View, Dimensions } from 'react-native';
|
|
3
3
|
import { UniversalOnboarding } from './UniversalOnboarding';
|
|
4
4
|
import { COLORS } from '../constants';
|
|
5
5
|
import type { OnairosButtonProps } from '../types';
|
|
6
6
|
|
|
7
7
|
export const OnairosButton: React.FC<OnairosButtonProps> = ({
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
style,
|
|
11
|
-
buttonType = 'default',
|
|
12
|
-
buttonForm = 'signup',
|
|
8
|
+
returnLink,
|
|
9
|
+
prefillUrl,
|
|
13
10
|
AppName,
|
|
11
|
+
buttonType = 'normal',
|
|
14
12
|
requestData,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
buttonWidth = 180,
|
|
14
|
+
buttonHeight,
|
|
15
|
+
hasStroke = false,
|
|
16
|
+
enabled = true,
|
|
17
|
+
buttonForm = 'default',
|
|
18
|
+
onRejection,
|
|
19
|
+
onResolved,
|
|
20
|
+
preCheck,
|
|
21
|
+
color,
|
|
22
|
+
swerv = false,
|
|
18
23
|
debug = false,
|
|
19
|
-
|
|
24
|
+
preferredPlatform,
|
|
25
|
+
testMode = false,
|
|
20
26
|
}) => {
|
|
21
27
|
const [showOnboarding, setShowOnboarding] = useState(false);
|
|
22
28
|
|
|
23
|
-
const handlePress = () => {
|
|
29
|
+
const handlePress = async () => {
|
|
30
|
+
if (!enabled) return;
|
|
31
|
+
|
|
32
|
+
if (preCheck) {
|
|
33
|
+
const shouldProceed = await preCheck();
|
|
34
|
+
if (!shouldProceed) {
|
|
35
|
+
onRejection?.();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
24
40
|
if (buttonForm === 'signup') {
|
|
25
41
|
setShowOnboarding(true);
|
|
26
42
|
} else {
|
|
27
|
-
|
|
43
|
+
// Handle login flow
|
|
44
|
+
// TODO: Implement login flow according to account.md
|
|
28
45
|
}
|
|
29
46
|
};
|
|
30
47
|
|
|
31
48
|
const handleOnboardingComplete = (apiUrl: string, token: string, data: any) => {
|
|
32
49
|
setShowOnboarding(false);
|
|
33
|
-
|
|
50
|
+
onResolved?.(apiUrl, token, data);
|
|
34
51
|
};
|
|
35
52
|
|
|
53
|
+
const buttonStyle = [
|
|
54
|
+
styles.button,
|
|
55
|
+
buttonType === 'pill' && styles.pillButton,
|
|
56
|
+
hasStroke && styles.strokedButton,
|
|
57
|
+
{ width: buttonWidth },
|
|
58
|
+
buttonHeight && { height: buttonHeight },
|
|
59
|
+
color && { backgroundColor: color },
|
|
60
|
+
swerv && styles.swervButton,
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
const textStyle = [
|
|
64
|
+
styles.buttonText,
|
|
65
|
+
hasStroke && styles.strokedButtonText,
|
|
66
|
+
color && styles.customColorText,
|
|
67
|
+
];
|
|
68
|
+
|
|
36
69
|
return (
|
|
37
70
|
<View>
|
|
38
71
|
<TouchableOpacity
|
|
39
|
-
style={
|
|
40
|
-
styles.button,
|
|
41
|
-
buttonType === 'pill' && styles.pillButton,
|
|
42
|
-
style,
|
|
43
|
-
]}
|
|
72
|
+
style={buttonStyle}
|
|
44
73
|
onPress={handlePress}
|
|
74
|
+
disabled={!enabled}
|
|
45
75
|
>
|
|
46
|
-
<Text style={
|
|
76
|
+
<Text style={textStyle}>{AppName}</Text>
|
|
47
77
|
</TouchableOpacity>
|
|
48
78
|
|
|
49
79
|
<UniversalOnboarding
|
|
@@ -53,9 +83,9 @@ export const OnairosButton: React.FC<OnairosButtonProps> = ({
|
|
|
53
83
|
requestData={requestData}
|
|
54
84
|
returnLink={returnLink}
|
|
55
85
|
onComplete={handleOnboardingComplete}
|
|
56
|
-
|
|
86
|
+
preferredPlatform={preferredPlatform}
|
|
57
87
|
debug={debug}
|
|
58
|
-
test={
|
|
88
|
+
test={testMode}
|
|
59
89
|
/>
|
|
60
90
|
</View>
|
|
61
91
|
);
|
|
@@ -63,7 +93,7 @@ export const OnairosButton: React.FC<OnairosButtonProps> = ({
|
|
|
63
93
|
|
|
64
94
|
const styles = StyleSheet.create({
|
|
65
95
|
button: {
|
|
66
|
-
backgroundColor:
|
|
96
|
+
backgroundColor: '#000',
|
|
67
97
|
paddingVertical: 12,
|
|
68
98
|
paddingHorizontal: 24,
|
|
69
99
|
borderRadius: 8,
|
|
@@ -73,9 +103,23 @@ const styles = StyleSheet.create({
|
|
|
73
103
|
pillButton: {
|
|
74
104
|
borderRadius: 20,
|
|
75
105
|
},
|
|
106
|
+
strokedButton: {
|
|
107
|
+
backgroundColor: 'transparent',
|
|
108
|
+
borderWidth: 1,
|
|
109
|
+
borderColor: '#000',
|
|
110
|
+
},
|
|
111
|
+
swervButton: {
|
|
112
|
+
transform: [{ rotate: '-2deg' }],
|
|
113
|
+
},
|
|
76
114
|
buttonText: {
|
|
77
115
|
color: '#fff',
|
|
78
116
|
fontSize: 16,
|
|
79
117
|
fontWeight: '600',
|
|
80
118
|
},
|
|
119
|
+
strokedButtonText: {
|
|
120
|
+
color: '#000',
|
|
121
|
+
},
|
|
122
|
+
customColorText: {
|
|
123
|
+
color: '#fff',
|
|
124
|
+
},
|
|
81
125
|
});
|
|
@@ -1,272 +1,285 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
Text,
|
|
5
5
|
StyleSheet,
|
|
6
6
|
TouchableOpacity,
|
|
7
7
|
ScrollView,
|
|
8
|
+
Alert,
|
|
8
9
|
Platform,
|
|
9
|
-
Dimensions,
|
|
10
10
|
} from 'react-native';
|
|
11
|
-
import
|
|
12
|
-
import Icon from 'react-native-vector-icons/MaterialIcons';
|
|
11
|
+
import { BottomSheetModal, BottomSheetBackdrop } from '@gorhom/bottom-sheet';
|
|
13
12
|
import { COLORS } from '../constants';
|
|
13
|
+
import { onairosApi } from '../api';
|
|
14
|
+
import { encryptModelKey, getServerPublicKey } from '../utils/encryption';
|
|
14
15
|
|
|
15
16
|
interface OverlayProps {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
data: {
|
|
18
|
+
[key: string]: {
|
|
19
|
+
type: string;
|
|
20
|
+
descriptions: string;
|
|
21
|
+
reward: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
username: string;
|
|
25
|
+
modelKey: string;
|
|
26
|
+
onResolved: (apiUrl: string, accessToken: string, loginDetails: any) => void;
|
|
22
27
|
}
|
|
23
28
|
|
|
24
|
-
const { height } = Dimensions.get('window');
|
|
25
|
-
|
|
26
29
|
export const Overlay: React.FC<OverlayProps> = ({
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
requestData,
|
|
32
|
-
biometricType = Platform.OS === 'ios' ? 'FaceID' : 'BiometricID',
|
|
30
|
+
data,
|
|
31
|
+
username,
|
|
32
|
+
modelKey,
|
|
33
|
+
onResolved,
|
|
33
34
|
}) => {
|
|
34
|
-
const
|
|
35
|
-
const
|
|
35
|
+
const [selections, setSelections] = useState<{ [key: string]: boolean }>({});
|
|
36
|
+
const [details, setDetails] = useState<string>('');
|
|
37
|
+
const bottomSheetRef = React.useRef<BottomSheetModal>(null);
|
|
36
38
|
|
|
37
|
-
// Expand or collapse the bottom sheet based on visibility
|
|
38
39
|
useEffect(() => {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
// Initialize selection state
|
|
41
|
+
const initialSelections: { [key: string]: boolean } = {};
|
|
42
|
+
Object.keys(data).forEach((key) => {
|
|
43
|
+
initialSelections[key] = false;
|
|
44
|
+
});
|
|
45
|
+
setSelections(initialSelections);
|
|
46
|
+
getDetails();
|
|
47
|
+
}, []);
|
|
48
|
+
|
|
49
|
+
const getDetails = async () => {
|
|
50
|
+
try {
|
|
51
|
+
const response = await onairosApi.post('getAccountInfo', {
|
|
52
|
+
Info: {
|
|
53
|
+
username: username,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
setDetails(response.AccountInfo);
|
|
57
|
+
} catch (e) {
|
|
58
|
+
console.error('Error getting account info:', e);
|
|
43
59
|
}
|
|
44
|
-
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const closeOverlay = () => {
|
|
63
|
+
bottomSheetRef.current?.dismiss();
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const confirmSelection = async () => {
|
|
67
|
+
try {
|
|
68
|
+
let appId = 'unknown';
|
|
69
|
+
try {
|
|
70
|
+
// Try to get package info, but don't fail if it's not available
|
|
71
|
+
const PackageInfo = require('react-native-package-info');
|
|
72
|
+
const packageInfo = await PackageInfo.getPackageInfo();
|
|
73
|
+
appId = packageInfo.packageName;
|
|
74
|
+
} catch (e) {
|
|
75
|
+
console.warn('Package info not available:', e);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const serverPublicKey = await getServerPublicKey();
|
|
79
|
+
const encryptedModelKey = encryptModelKey(serverPublicKey, modelKey);
|
|
45
80
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
81
|
+
const response = await onairosApi.post('getAPIUrlMobile', {
|
|
82
|
+
Info: {
|
|
83
|
+
storage: 'local',
|
|
84
|
+
appId: appId,
|
|
85
|
+
confirmations: selections,
|
|
86
|
+
developerURL: 'devURL',
|
|
87
|
+
EncryptedUserPin: encryptedModelKey,
|
|
88
|
+
account: username,
|
|
89
|
+
proofMode: false,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
if (response.apiUrl && response.token) {
|
|
94
|
+
onResolved(response.apiUrl, response.token, { username });
|
|
95
|
+
closeOverlay();
|
|
96
|
+
}
|
|
97
|
+
} catch (e) {
|
|
98
|
+
console.error('Error in confirmSelection:', e);
|
|
99
|
+
showErrorModal('Failed to confirm selection. Please try again.');
|
|
55
100
|
}
|
|
56
|
-
}
|
|
101
|
+
};
|
|
57
102
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return Object.entries(requestData).map(([category, items]) => (
|
|
61
|
-
<View key={category} style={styles.categoryContainer}>
|
|
62
|
-
<Text style={styles.categoryTitle}>{category}</Text>
|
|
63
|
-
|
|
64
|
-
{Object.entries(items).map(([item, description]) => (
|
|
65
|
-
<View key={item} style={styles.itemContainer}>
|
|
66
|
-
<Icon name="check-circle" size={20} color={COLORS.primary} />
|
|
67
|
-
<View style={styles.itemContent}>
|
|
68
|
-
<Text style={styles.itemTitle}>{item}</Text>
|
|
69
|
-
<Text style={styles.itemDescription}>{description}</Text>
|
|
70
|
-
</View>
|
|
71
|
-
</View>
|
|
72
|
-
))}
|
|
73
|
-
</View>
|
|
74
|
-
));
|
|
103
|
+
const showErrorModal = (errorMessage: string) => {
|
|
104
|
+
Alert.alert('Notice', errorMessage, [{ text: 'OK' }]);
|
|
75
105
|
};
|
|
76
106
|
|
|
107
|
+
const selectedCount = Object.values(selections).filter(Boolean).length;
|
|
108
|
+
|
|
77
109
|
return (
|
|
78
|
-
<
|
|
110
|
+
<BottomSheetModal
|
|
79
111
|
ref={bottomSheetRef}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
style={[
|
|
87
|
-
styles.backdrop,
|
|
88
|
-
{
|
|
89
|
-
opacity: animatedIndex.interpolate({
|
|
90
|
-
inputRange: [0, 1],
|
|
91
|
-
outputRange: [0.5, 0],
|
|
92
|
-
}),
|
|
93
|
-
},
|
|
94
|
-
]}
|
|
112
|
+
snapPoints={['80%']}
|
|
113
|
+
backdropComponent={(props) => (
|
|
114
|
+
<BottomSheetBackdrop
|
|
115
|
+
{...props}
|
|
116
|
+
appearsOnIndex={0}
|
|
117
|
+
disappearsOnIndex={-1}
|
|
95
118
|
/>
|
|
96
119
|
)}
|
|
97
120
|
>
|
|
98
121
|
<View style={styles.container}>
|
|
99
122
|
<View style={styles.header}>
|
|
100
|
-
<
|
|
101
|
-
<
|
|
102
|
-
|
|
103
|
-
<Icon name="close" size={24} color="#000" />
|
|
123
|
+
<Text style={styles.headerTitle}>Onairos</Text>
|
|
124
|
+
<TouchableOpacity onPress={closeOverlay}>
|
|
125
|
+
<Text style={styles.closeButton}>×</Text>
|
|
104
126
|
</TouchableOpacity>
|
|
127
|
+
<Text style={styles.username}>{username}</Text>
|
|
105
128
|
</View>
|
|
106
|
-
|
|
129
|
+
|
|
107
130
|
<ScrollView style={styles.content}>
|
|
108
|
-
|
|
109
|
-
<
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
131
|
+
{Object.entries(data).map(([key, value]) => (
|
|
132
|
+
<View key={key} style={styles.card}>
|
|
133
|
+
<TouchableOpacity
|
|
134
|
+
style={styles.checkboxContainer}
|
|
135
|
+
onPress={() =>
|
|
136
|
+
setSelections((prev) => ({
|
|
137
|
+
...prev,
|
|
138
|
+
[key]: !prev[key],
|
|
139
|
+
}))
|
|
140
|
+
}
|
|
141
|
+
>
|
|
142
|
+
<View
|
|
143
|
+
style={[
|
|
144
|
+
styles.checkbox,
|
|
145
|
+
selections[key] && styles.checkboxSelected,
|
|
146
|
+
]}
|
|
147
|
+
/>
|
|
148
|
+
<View style={styles.cardContent}>
|
|
149
|
+
<Text style={styles.cardTitle}>{value.type} Insight</Text>
|
|
150
|
+
<Text style={styles.cardDescription}>
|
|
151
|
+
Description: {value.descriptions}
|
|
152
|
+
</Text>
|
|
153
|
+
{value.reward && (
|
|
154
|
+
<Text style={styles.cardReward}>
|
|
155
|
+
Reward: {value.reward}
|
|
156
|
+
</Text>
|
|
157
|
+
)}
|
|
158
|
+
</View>
|
|
159
|
+
</TouchableOpacity>
|
|
160
|
+
</View>
|
|
161
|
+
))}
|
|
123
162
|
</ScrollView>
|
|
124
|
-
|
|
163
|
+
|
|
125
164
|
<View style={styles.footer}>
|
|
126
165
|
<TouchableOpacity
|
|
127
|
-
style={styles.
|
|
128
|
-
onPress={
|
|
166
|
+
style={styles.footerButton}
|
|
167
|
+
onPress={closeOverlay}
|
|
129
168
|
>
|
|
130
|
-
<Text style={styles.
|
|
169
|
+
<Text style={styles.footerButtonText}>Cancel</Text>
|
|
131
170
|
</TouchableOpacity>
|
|
132
|
-
|
|
171
|
+
<Text style={styles.selectedCount}>Selected: {selectedCount}</Text>
|
|
133
172
|
<TouchableOpacity
|
|
134
|
-
style={styles.
|
|
135
|
-
onPress={
|
|
173
|
+
style={styles.footerButton}
|
|
174
|
+
onPress={confirmSelection}
|
|
136
175
|
>
|
|
137
|
-
<Text style={styles.
|
|
138
|
-
<Icon name={getBiometricIcon()} size={20} color="#fff" style={styles.buttonIcon} />
|
|
176
|
+
<Text style={styles.footerButtonText}>Confirm</Text>
|
|
139
177
|
</TouchableOpacity>
|
|
140
178
|
</View>
|
|
141
179
|
</View>
|
|
142
|
-
</
|
|
180
|
+
</BottomSheetModal>
|
|
143
181
|
);
|
|
144
182
|
};
|
|
145
183
|
|
|
146
184
|
const styles = StyleSheet.create({
|
|
147
185
|
container: {
|
|
148
186
|
flex: 1,
|
|
149
|
-
backgroundColor:
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
...StyleSheet.absoluteFillObject,
|
|
153
|
-
backgroundColor: '#000',
|
|
187
|
+
backgroundColor: COLORS.white,
|
|
188
|
+
borderTopLeftRadius: 10,
|
|
189
|
+
borderTopRightRadius: 10,
|
|
154
190
|
},
|
|
155
191
|
header: {
|
|
156
192
|
flexDirection: 'row',
|
|
157
193
|
alignItems: 'center',
|
|
194
|
+
justifyContent: 'space-between',
|
|
158
195
|
padding: 16,
|
|
159
|
-
backgroundColor: COLORS.
|
|
160
|
-
borderTopLeftRadius:
|
|
161
|
-
borderTopRightRadius:
|
|
196
|
+
backgroundColor: COLORS.primary,
|
|
197
|
+
borderTopLeftRadius: 10,
|
|
198
|
+
borderTopRightRadius: 10,
|
|
162
199
|
},
|
|
163
200
|
headerTitle: {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
fontWeight: '
|
|
167
|
-
marginLeft: 12,
|
|
168
|
-
color: '#000',
|
|
201
|
+
fontSize: 24,
|
|
202
|
+
color: COLORS.white,
|
|
203
|
+
fontWeight: 'bold',
|
|
169
204
|
},
|
|
170
205
|
closeButton: {
|
|
206
|
+
fontSize: 24,
|
|
207
|
+
color: COLORS.white,
|
|
171
208
|
padding: 8,
|
|
172
209
|
},
|
|
210
|
+
username: {
|
|
211
|
+
fontSize: 18,
|
|
212
|
+
color: COLORS.primary,
|
|
213
|
+
},
|
|
173
214
|
content: {
|
|
174
215
|
flex: 1,
|
|
175
216
|
padding: 16,
|
|
176
217
|
},
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
appName: {
|
|
181
|
-
fontSize: 20,
|
|
182
|
-
fontWeight: 'bold',
|
|
183
|
-
color: '#000',
|
|
184
|
-
marginBottom: 4,
|
|
185
|
-
},
|
|
186
|
-
requestText: {
|
|
187
|
-
fontSize: 16,
|
|
188
|
-
color: '#666',
|
|
189
|
-
},
|
|
190
|
-
categoryContainer: {
|
|
191
|
-
marginBottom: 20,
|
|
192
|
-
},
|
|
193
|
-
categoryTitle: {
|
|
194
|
-
fontSize: 18,
|
|
195
|
-
fontWeight: '600',
|
|
196
|
-
color: '#000',
|
|
218
|
+
card: {
|
|
219
|
+
backgroundColor: COLORS.white,
|
|
220
|
+
borderRadius: 8,
|
|
197
221
|
marginBottom: 12,
|
|
222
|
+
shadowColor: COLORS.black,
|
|
223
|
+
shadowOffset: { width: 0, height: 2 },
|
|
224
|
+
shadowOpacity: 0.1,
|
|
225
|
+
shadowRadius: 4,
|
|
226
|
+
elevation: 3,
|
|
198
227
|
},
|
|
199
|
-
|
|
228
|
+
checkboxContainer: {
|
|
200
229
|
flexDirection: 'row',
|
|
201
|
-
|
|
202
|
-
|
|
230
|
+
padding: 16,
|
|
231
|
+
alignItems: 'center',
|
|
203
232
|
},
|
|
204
|
-
|
|
233
|
+
checkbox: {
|
|
234
|
+
width: 24,
|
|
235
|
+
height: 24,
|
|
236
|
+
borderRadius: 4,
|
|
237
|
+
borderWidth: 2,
|
|
238
|
+
borderColor: COLORS.primary,
|
|
239
|
+
marginRight: 12,
|
|
240
|
+
},
|
|
241
|
+
checkboxSelected: {
|
|
242
|
+
backgroundColor: COLORS.primary,
|
|
243
|
+
},
|
|
244
|
+
cardContent: {
|
|
205
245
|
flex: 1,
|
|
206
|
-
marginLeft: 12,
|
|
207
246
|
},
|
|
208
|
-
|
|
209
|
-
fontSize:
|
|
210
|
-
fontWeight: '
|
|
211
|
-
|
|
212
|
-
marginBottom: 2,
|
|
247
|
+
cardTitle: {
|
|
248
|
+
fontSize: 18,
|
|
249
|
+
fontWeight: 'bold',
|
|
250
|
+
marginBottom: 4,
|
|
213
251
|
},
|
|
214
|
-
|
|
252
|
+
cardDescription: {
|
|
215
253
|
fontSize: 14,
|
|
216
|
-
color:
|
|
217
|
-
|
|
218
|
-
securityNotice: {
|
|
219
|
-
flexDirection: 'row',
|
|
220
|
-
alignItems: 'flex-start',
|
|
221
|
-
backgroundColor: '#f5f5f5',
|
|
222
|
-
padding: 12,
|
|
223
|
-
borderRadius: 8,
|
|
224
|
-
marginBottom: 24,
|
|
254
|
+
color: COLORS.gray,
|
|
255
|
+
marginBottom: 4,
|
|
225
256
|
},
|
|
226
|
-
|
|
227
|
-
flex: 1,
|
|
257
|
+
cardReward: {
|
|
228
258
|
fontSize: 14,
|
|
229
|
-
color:
|
|
230
|
-
|
|
259
|
+
color: COLORS.success,
|
|
260
|
+
fontWeight: 'bold',
|
|
231
261
|
},
|
|
232
262
|
footer: {
|
|
233
263
|
flexDirection: 'row',
|
|
264
|
+
justifyContent: 'space-between',
|
|
265
|
+
alignItems: 'center',
|
|
234
266
|
padding: 16,
|
|
235
267
|
borderTopWidth: 1,
|
|
236
|
-
borderTopColor:
|
|
237
|
-
},
|
|
238
|
-
cancelButton: {
|
|
239
|
-
flex: 1,
|
|
240
|
-
justifyContent: 'center',
|
|
241
|
-
alignItems: 'center',
|
|
242
|
-
paddingVertical: 12,
|
|
243
|
-
borderWidth: 1,
|
|
244
|
-
borderColor: '#ddd',
|
|
245
|
-
borderRadius: 25,
|
|
246
|
-
marginRight: 8,
|
|
268
|
+
borderTopColor: COLORS.lightGray,
|
|
247
269
|
},
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
},
|
|
253
|
-
acceptButton: {
|
|
254
|
-
flex: 2,
|
|
255
|
-
flexDirection: 'row',
|
|
256
|
-
justifyContent: 'center',
|
|
257
|
-
alignItems: 'center',
|
|
258
|
-
paddingVertical: 12,
|
|
270
|
+
footerButton: {
|
|
271
|
+
paddingVertical: 8,
|
|
272
|
+
paddingHorizontal: 16,
|
|
273
|
+
borderRadius: 8,
|
|
259
274
|
backgroundColor: COLORS.primary,
|
|
260
|
-
borderRadius: 25,
|
|
261
|
-
marginLeft: 8,
|
|
262
275
|
},
|
|
263
|
-
|
|
276
|
+
footerButtonText: {
|
|
277
|
+
color: COLORS.white,
|
|
264
278
|
fontSize: 16,
|
|
265
279
|
fontWeight: '600',
|
|
266
|
-
color: '#fff',
|
|
267
|
-
marginRight: 8,
|
|
268
280
|
},
|
|
269
|
-
|
|
270
|
-
|
|
281
|
+
selectedCount: {
|
|
282
|
+
fontSize: 16,
|
|
283
|
+
color: COLORS.gray,
|
|
271
284
|
},
|
|
272
285
|
});
|
package/src/constants/index.ts
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
import type { PlatformConfig } from '../types';
|
|
2
2
|
|
|
3
3
|
export const COLORS = {
|
|
4
|
-
primary: '#
|
|
5
|
-
headerBg: '#
|
|
4
|
+
primary: '#1BA9D4',
|
|
5
|
+
headerBg: '#F8F9FA',
|
|
6
6
|
text: {
|
|
7
7
|
primary: '#000000',
|
|
8
|
-
secondary: '#
|
|
8
|
+
secondary: '#666666',
|
|
9
9
|
},
|
|
10
|
-
border: '#
|
|
11
|
-
success: '#
|
|
12
|
-
error: '#
|
|
13
|
-
instagram: '#
|
|
14
|
-
pinterest: '#
|
|
10
|
+
border: '#E5E5E5',
|
|
11
|
+
success: '#34C759',
|
|
12
|
+
error: '#FF3B30',
|
|
13
|
+
instagram: '#E1306C',
|
|
14
|
+
pinterest: '#E60023',
|
|
15
15
|
reddit: '#FF4500',
|
|
16
16
|
youtube: '#FF0000',
|
|
17
|
+
white: '#FFFFFF',
|
|
18
|
+
black: '#000000',
|
|
19
|
+
gray: '#666666',
|
|
20
|
+
lightGray: '#E5E5E5',
|
|
17
21
|
};
|
|
18
22
|
|
|
19
23
|
export const PLATFORMS: Record<string, PlatformConfig> = {
|