@onairos/react-native 3.0.9 → 3.0.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/lib/commonjs/assets/images/onairos_logo.svg +6 -0
- package/lib/commonjs/components/Onairos.js +214 -60
- package/lib/commonjs/components/Onairos.js.map +1 -1
- package/lib/commonjs/components/OnairosButton.js +105 -42
- package/lib/commonjs/components/OnairosButton.js.map +1 -1
- package/lib/commonjs/components/UniversalOnboarding.js +98 -26
- package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
- package/lib/module/assets/images/onairos_logo.svg +6 -0
- package/lib/module/components/Onairos.js +217 -62
- package/lib/module/components/Onairos.js.map +1 -1
- package/lib/module/components/OnairosButton.js +107 -43
- package/lib/module/components/OnairosButton.js.map +1 -1
- package/lib/module/components/UniversalOnboarding.js +100 -28
- package/lib/module/components/UniversalOnboarding.js.map +1 -1
- package/lib/module/index.js +10 -9
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/components/Onairos.d.ts +26 -24
- package/lib/typescript/components/Onairos.d.ts.map +1 -1
- package/lib/typescript/components/OnairosButton.d.ts +5 -1
- package/lib/typescript/components/OnairosButton.d.ts.map +1 -1
- package/lib/typescript/components/UniversalOnboarding.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +2 -1
- package/lib/typescript/types.d.ts.map +1 -1
- package/package.json +5 -3
- package/src/assets/images/onairos_logo.svg +6 -0
- package/src/components/Onairos.tsx +283 -89
- package/src/components/OnairosButton.tsx +110 -46
- package/src/components/UniversalOnboarding.tsx +105 -28
- package/src/types.ts +2 -1
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import React, { useState, useCallback } from 'react';
|
|
1
|
+
import React, { useState, useCallback, forwardRef, useImperativeHandle } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
TouchableOpacity,
|
|
4
4
|
Text,
|
|
5
5
|
StyleSheet,
|
|
6
6
|
View,
|
|
7
7
|
ViewStyle,
|
|
8
|
-
TextStyle,
|
|
9
|
-
Image,
|
|
8
|
+
TextStyle,
|
|
10
9
|
ActivityIndicator,
|
|
11
|
-
Alert
|
|
12
10
|
} from 'react-native';
|
|
11
|
+
import { SvgXml } from 'react-native-svg';
|
|
13
12
|
import { UniversalOnboarding } from './UniversalOnboarding';
|
|
14
13
|
import { Overlay } from './Overlay';
|
|
15
14
|
import { COLORS } from '../constants';
|
|
@@ -18,18 +17,31 @@ import { hasCredentials, getCredentials, deleteCredentials as clearCredentials }
|
|
|
18
17
|
import { onairosApi } from '../api';
|
|
19
18
|
import { Portal } from '../utils/Portal';
|
|
20
19
|
|
|
20
|
+
// Import the Onairos logo SVG
|
|
21
|
+
const onairosLogoSvg = `<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
22
|
+
<rect width="40" height="40" rx="8" fill="currentColor"/>
|
|
23
|
+
<path d="M20 10C14.48 10 10 14.48 10 20C10 25.52 14.48 30 20 30C25.52 30 30 25.52 30 20C30 14.48 25.52 10 20 10ZM20 28C15.59 28 12 24.41 12 20C12 15.59 15.59 12 20 12C24.41 12 28 15.59 28 20C28 24.41 24.41 28 20 28Z" fill="white"/>
|
|
24
|
+
<path d="M20 15C18.9 15 18 15.9 18 17V19C18 20.1 18.9 21 20 21C21.1 21 22 20.1 22 19V17C22 15.9 21.1 15 20 15Z" fill="white"/>
|
|
25
|
+
<path d="M20 24C19.448 24 19 24.448 19 25C19 25.552 19.448 26 20 26C20.552 26 21 25.552 21 25C21 24.448 20.552 24 20 24Z" fill="white"/>
|
|
26
|
+
</svg>`;
|
|
27
|
+
|
|
28
|
+
export interface OnairosButtonRef {
|
|
29
|
+
trigger: () => Promise<void>;
|
|
30
|
+
reset: () => Promise<void>;
|
|
31
|
+
}
|
|
32
|
+
|
|
21
33
|
/**
|
|
22
34
|
* OnairosButton Component - A sign-in button similar to Google/Apple sign-in
|
|
23
35
|
*/
|
|
24
|
-
export const OnairosButton
|
|
36
|
+
export const OnairosButton = forwardRef<OnairosButtonRef, OnairosButtonProps>(({
|
|
25
37
|
returnLink,
|
|
26
38
|
prefillUrl,
|
|
27
39
|
AppName,
|
|
28
40
|
buttonType = 'normal',
|
|
29
41
|
requestData,
|
|
30
|
-
buttonWidth =
|
|
42
|
+
buttonWidth = 180,
|
|
31
43
|
buttonHeight = 48,
|
|
32
|
-
hasStroke =
|
|
44
|
+
hasStroke = false,
|
|
33
45
|
enabled = true,
|
|
34
46
|
buttonForm = 'default',
|
|
35
47
|
onRejection,
|
|
@@ -38,15 +50,64 @@ export const OnairosButton: React.FC<OnairosButtonProps> = ({
|
|
|
38
50
|
color,
|
|
39
51
|
swerv = false,
|
|
40
52
|
debug = false,
|
|
53
|
+
darkMode = false,
|
|
41
54
|
preferredPlatform,
|
|
42
55
|
testMode = false,
|
|
43
|
-
}) => {
|
|
56
|
+
}, ref) => {
|
|
44
57
|
const [showOnboarding, setShowOnboarding] = useState(false);
|
|
45
58
|
const [showOverlay, setShowOverlay] = useState(false);
|
|
46
59
|
const [storedCredentials, setStoredCredentials] = useState<any>(null);
|
|
47
60
|
const [isLoading, setIsLoading] = useState(false);
|
|
61
|
+
const [isPressed, setIsPressed] = useState(false);
|
|
62
|
+
|
|
63
|
+
// Expose methods via ref
|
|
64
|
+
useImperativeHandle(ref, () => ({
|
|
65
|
+
trigger: async () => {
|
|
66
|
+
await handlePress();
|
|
67
|
+
},
|
|
68
|
+
reset: async () => {
|
|
69
|
+
await clearCredentials();
|
|
70
|
+
}
|
|
71
|
+
}));
|
|
72
|
+
|
|
73
|
+
// Compute button text based on buttonForm
|
|
74
|
+
const getButtonText = () => {
|
|
75
|
+
if (buttonForm === 'connect' || buttonForm === 'signup') {
|
|
76
|
+
return 'Connect with Onairos';
|
|
77
|
+
} else {
|
|
78
|
+
return 'Sign in with Onairos';
|
|
79
|
+
}
|
|
80
|
+
};
|
|
48
81
|
|
|
49
|
-
|
|
82
|
+
// Calculate background color based on props and state
|
|
83
|
+
const getBackgroundColor = (): string => {
|
|
84
|
+
if (!enabled) {
|
|
85
|
+
return darkMode ? '#3A3A3A' : '#e0e0e0';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (isPressed) {
|
|
89
|
+
return color ?
|
|
90
|
+
(typeof color === 'string' ? `${color}80` : color) :
|
|
91
|
+
(darkMode ? '#32323280' : '#f5f5f580');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return color || (darkMode ? '#2A2A2A' : '#ffffff');
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Calculate text color based on background luminance
|
|
98
|
+
const getTextColor = (): string => {
|
|
99
|
+
if (!enabled) {
|
|
100
|
+
return darkMode ? '#777777' : '#AAAAAA';
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (darkMode) {
|
|
104
|
+
return '#FFFFFF';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const bgColor = getBackgroundColor();
|
|
108
|
+
// Simple luminance check
|
|
109
|
+
return bgColor === '#ffffff' || bgColor === '#f5f5f580' || bgColor.includes('#f') ? '#000000' : '#FFFFFF';
|
|
110
|
+
};
|
|
50
111
|
|
|
51
112
|
const handlePress = async () => {
|
|
52
113
|
if (!enabled || isLoading) return;
|
|
@@ -79,7 +140,7 @@ export const OnairosButton: React.FC<OnairosButtonProps> = ({
|
|
|
79
140
|
}
|
|
80
141
|
|
|
81
142
|
try {
|
|
82
|
-
// Validate credentials with server
|
|
143
|
+
// Validate credentials with server
|
|
83
144
|
const isValid = await onairosApi.validateCredentials(credentials.username);
|
|
84
145
|
|
|
85
146
|
if (!isValid) {
|
|
@@ -132,20 +193,17 @@ export const OnairosButton: React.FC<OnairosButtonProps> = ({
|
|
|
132
193
|
hasStroke && styles.strokedButton,
|
|
133
194
|
{
|
|
134
195
|
width: buttonWidth,
|
|
135
|
-
height: buttonHeight
|
|
196
|
+
height: buttonHeight,
|
|
197
|
+
backgroundColor: getBackgroundColor(),
|
|
198
|
+
borderColor: darkMode ? '#555555' : '#000000',
|
|
136
199
|
},
|
|
137
|
-
color ? { backgroundColor: color } : null,
|
|
138
|
-
isDarkMode ? styles.darkButton : styles.lightButton,
|
|
139
200
|
swerv && styles.swervButton,
|
|
140
201
|
!enabled && styles.disabledButton
|
|
141
202
|
].filter(Boolean) as ViewStyle[];
|
|
142
203
|
|
|
143
|
-
// Calculate text
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
isDarkMode ? styles.lightText : styles.darkText,
|
|
147
|
-
!enabled && styles.disabledText
|
|
148
|
-
].filter(Boolean) as TextStyle[];
|
|
204
|
+
// Calculate text color
|
|
205
|
+
const textColor = getTextColor();
|
|
206
|
+
const logoColor = textColor;
|
|
149
207
|
|
|
150
208
|
// Render components
|
|
151
209
|
return (
|
|
@@ -155,17 +213,26 @@ export const OnairosButton: React.FC<OnairosButtonProps> = ({
|
|
|
155
213
|
onPress={handlePress}
|
|
156
214
|
disabled={!enabled || isLoading}
|
|
157
215
|
accessibilityLabel={`Sign in with Onairos`}
|
|
216
|
+
onPressIn={() => setIsPressed(true)}
|
|
217
|
+
onPressOut={() => setIsPressed(false)}
|
|
158
218
|
>
|
|
159
219
|
{isLoading ? (
|
|
160
220
|
<ActivityIndicator
|
|
161
221
|
size="small"
|
|
162
|
-
color={
|
|
222
|
+
color={textColor}
|
|
163
223
|
/>
|
|
164
224
|
) : (
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
225
|
+
<View style={styles.buttonContent}>
|
|
226
|
+
<SvgXml
|
|
227
|
+
xml={onairosLogoSvg.replace('currentColor', logoColor)}
|
|
228
|
+
width={24}
|
|
229
|
+
height={24}
|
|
230
|
+
style={styles.logo}
|
|
231
|
+
/>
|
|
232
|
+
<Text style={[styles.buttonText, { color: textColor }]}>
|
|
233
|
+
{getButtonText()}
|
|
234
|
+
</Text>
|
|
235
|
+
</View>
|
|
169
236
|
)}
|
|
170
237
|
</TouchableOpacity>
|
|
171
238
|
|
|
@@ -178,11 +245,12 @@ export const OnairosButton: React.FC<OnairosButtonProps> = ({
|
|
|
178
245
|
onRejection?.('User closed onboarding');
|
|
179
246
|
}}
|
|
180
247
|
AppName={AppName}
|
|
181
|
-
requestData={requestData}
|
|
182
|
-
returnLink={returnLink}
|
|
248
|
+
requestData={requestData as any}
|
|
249
|
+
returnLink={returnLink || ''}
|
|
183
250
|
onComplete={handleOnboardingComplete}
|
|
184
251
|
debug={debug}
|
|
185
252
|
test={testMode}
|
|
253
|
+
preferredPlatform={preferredPlatform}
|
|
186
254
|
/>
|
|
187
255
|
)}
|
|
188
256
|
|
|
@@ -195,12 +263,13 @@ export const OnairosButton: React.FC<OnairosButtonProps> = ({
|
|
|
195
263
|
modelKey={storedCredentials.userPin || ''}
|
|
196
264
|
onResolved={handleOverlayResolved}
|
|
197
265
|
appName={AppName}
|
|
266
|
+
darkMode={darkMode}
|
|
198
267
|
/>
|
|
199
268
|
</Portal>
|
|
200
269
|
)}
|
|
201
270
|
</>
|
|
202
271
|
);
|
|
203
|
-
};
|
|
272
|
+
});
|
|
204
273
|
|
|
205
274
|
const styles = StyleSheet.create({
|
|
206
275
|
button: {
|
|
@@ -209,7 +278,20 @@ const styles = StyleSheet.create({
|
|
|
209
278
|
justifyContent: 'center',
|
|
210
279
|
paddingVertical: 12,
|
|
211
280
|
paddingHorizontal: 16,
|
|
212
|
-
borderRadius:
|
|
281
|
+
borderRadius: 8,
|
|
282
|
+
shadowColor: '#000',
|
|
283
|
+
shadowOffset: { width: 0, height: 2 },
|
|
284
|
+
shadowOpacity: 0.1,
|
|
285
|
+
shadowRadius: 4,
|
|
286
|
+
elevation: 2,
|
|
287
|
+
},
|
|
288
|
+
buttonContent: {
|
|
289
|
+
flexDirection: 'row',
|
|
290
|
+
alignItems: 'center',
|
|
291
|
+
justifyContent: 'center',
|
|
292
|
+
},
|
|
293
|
+
logo: {
|
|
294
|
+
marginRight: 8,
|
|
213
295
|
},
|
|
214
296
|
pillButton: {
|
|
215
297
|
borderRadius: 24,
|
|
@@ -217,19 +299,10 @@ const styles = StyleSheet.create({
|
|
|
217
299
|
strokedButton: {
|
|
218
300
|
backgroundColor: 'transparent',
|
|
219
301
|
borderWidth: 1,
|
|
220
|
-
borderColor: '#000',
|
|
221
302
|
},
|
|
222
303
|
swervButton: {
|
|
223
304
|
transform: [{ rotate: '-2deg' }],
|
|
224
305
|
},
|
|
225
|
-
darkButton: {
|
|
226
|
-
backgroundColor: '#000',
|
|
227
|
-
borderColor: '#000',
|
|
228
|
-
},
|
|
229
|
-
lightButton: {
|
|
230
|
-
backgroundColor: '#fff',
|
|
231
|
-
borderColor: '#000',
|
|
232
|
-
},
|
|
233
306
|
disabledButton: {
|
|
234
307
|
opacity: 0.6,
|
|
235
308
|
},
|
|
@@ -238,13 +311,4 @@ const styles = StyleSheet.create({
|
|
|
238
311
|
fontWeight: '600',
|
|
239
312
|
textAlign: 'center',
|
|
240
313
|
},
|
|
241
|
-
lightText: {
|
|
242
|
-
color: '#fff',
|
|
243
|
-
},
|
|
244
|
-
darkText: {
|
|
245
|
-
color: '#000',
|
|
246
|
-
},
|
|
247
|
-
disabledText: {
|
|
248
|
-
opacity: 0.7,
|
|
249
|
-
},
|
|
250
314
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useEffect,
|
|
1
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
Text,
|
|
@@ -7,8 +7,11 @@ import {
|
|
|
7
7
|
ActivityIndicator,
|
|
8
8
|
Dimensions,
|
|
9
9
|
Platform,
|
|
10
|
+
Modal,
|
|
11
|
+
Animated,
|
|
12
|
+
SafeAreaView,
|
|
13
|
+
TouchableWithoutFeedback,
|
|
10
14
|
} from 'react-native';
|
|
11
|
-
import BottomSheet from '@gorhom/bottom-sheet';
|
|
12
15
|
import Icon from 'react-native-vector-icons/MaterialIcons';
|
|
13
16
|
import { PlatformList } from './PlatformList';
|
|
14
17
|
import { PinInput } from './PinInput';
|
|
@@ -17,7 +20,7 @@ import { useConnections } from '../hooks/useConnections';
|
|
|
17
20
|
import { COLORS } from '../constants';
|
|
18
21
|
import type { UniversalOnboardingProps, ConnectionStatus } from '../types';
|
|
19
22
|
|
|
20
|
-
const { height } = Dimensions.get('window');
|
|
23
|
+
const { height, width } = Dimensions.get('window');
|
|
21
24
|
|
|
22
25
|
export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
23
26
|
visible,
|
|
@@ -29,8 +32,8 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
29
32
|
embedd = false,
|
|
30
33
|
debug = false,
|
|
31
34
|
test = false,
|
|
35
|
+
preferredPlatform,
|
|
32
36
|
}) => {
|
|
33
|
-
const bottomSheetRef = useRef<BottomSheet>(null);
|
|
34
37
|
const [step, setStep] = useState<'connect' | 'pin' | 'training'>('connect');
|
|
35
38
|
const [connections, setConnections] = useState<ConnectionStatus>({});
|
|
36
39
|
const [pin, setPin] = useState<string>('');
|
|
@@ -39,6 +42,7 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
39
42
|
progress: number;
|
|
40
43
|
eta: string;
|
|
41
44
|
}>({ progress: 0, eta: '' });
|
|
45
|
+
const [slideAnim] = useState(new Animated.Value(height));
|
|
42
46
|
|
|
43
47
|
const {
|
|
44
48
|
connectPlatform,
|
|
@@ -47,12 +51,15 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
47
51
|
isConnecting,
|
|
48
52
|
} = useConnections();
|
|
49
53
|
|
|
50
|
-
const snapPoints = useMemo(() => ['90%'], []);
|
|
51
|
-
|
|
52
54
|
useEffect(() => {
|
|
53
55
|
if (visible) {
|
|
54
|
-
bottomSheetRef.current?.expand();
|
|
55
56
|
loadInitialStatus();
|
|
57
|
+
// Animate in
|
|
58
|
+
Animated.spring(slideAnim, {
|
|
59
|
+
toValue: 0,
|
|
60
|
+
useNativeDriver: true,
|
|
61
|
+
bounciness: 0,
|
|
62
|
+
}).start();
|
|
56
63
|
|
|
57
64
|
// Debug mode for Expo Go
|
|
58
65
|
if (debug || Platform.OS === 'web') {
|
|
@@ -65,10 +72,36 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
65
72
|
});
|
|
66
73
|
}
|
|
67
74
|
}
|
|
75
|
+
|
|
76
|
+
// If there's a preferred platform, pre-connect
|
|
77
|
+
if (preferredPlatform && debug) {
|
|
78
|
+
setConnections(prev => ({
|
|
79
|
+
...prev,
|
|
80
|
+
[preferredPlatform]: { userName: `${preferredPlatform}_user`, connected: true }
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
68
83
|
} else {
|
|
69
|
-
|
|
84
|
+
// Animate out
|
|
85
|
+
Animated.timing(slideAnim, {
|
|
86
|
+
toValue: height,
|
|
87
|
+
duration: 250,
|
|
88
|
+
useNativeDriver: true,
|
|
89
|
+
}).start(() => {
|
|
90
|
+
// Reset state if needed
|
|
91
|
+
});
|
|
70
92
|
}
|
|
71
|
-
}, [visible]);
|
|
93
|
+
}, [visible, preferredPlatform]);
|
|
94
|
+
|
|
95
|
+
const handleClose = () => {
|
|
96
|
+
// Animate out and then call onClose
|
|
97
|
+
Animated.timing(slideAnim, {
|
|
98
|
+
toValue: height,
|
|
99
|
+
duration: 250,
|
|
100
|
+
useNativeDriver: true,
|
|
101
|
+
}).start(() => {
|
|
102
|
+
onClose();
|
|
103
|
+
});
|
|
104
|
+
};
|
|
72
105
|
|
|
73
106
|
const loadInitialStatus = useCallback(async () => {
|
|
74
107
|
const status = await getConnectionStatus();
|
|
@@ -111,7 +144,7 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
111
144
|
}, 1000);
|
|
112
145
|
}, [connections, onComplete, selectedTier, requestData]);
|
|
113
146
|
|
|
114
|
-
const canProceedToPin =
|
|
147
|
+
const canProceedToPin = useCallback(() => {
|
|
115
148
|
const connectedPlatforms = Object.values(connections).filter(Boolean).length;
|
|
116
149
|
return connectedPlatforms >= 2;
|
|
117
150
|
}, [connections]);
|
|
@@ -119,8 +152,8 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
119
152
|
const renderHeader = () => (
|
|
120
153
|
<View style={styles.header}>
|
|
121
154
|
<Icon name="auto_awesome" size={24} color={COLORS.primary} />
|
|
122
|
-
<Text style={styles.headerTitle}>Connect with
|
|
123
|
-
<TouchableOpacity onPress={
|
|
155
|
+
<Text style={styles.headerTitle}>Connect with {AppName}</Text>
|
|
156
|
+
<TouchableOpacity onPress={handleClose} style={styles.closeButton}>
|
|
124
157
|
<Icon name="close" size={24} color="#000" />
|
|
125
158
|
</TouchableOpacity>
|
|
126
159
|
</View>
|
|
@@ -134,7 +167,7 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
134
167
|
connections={connections}
|
|
135
168
|
onToggle={handlePlatformToggle}
|
|
136
169
|
isLoading={isConnecting}
|
|
137
|
-
canProceed={canProceedToPin}
|
|
170
|
+
canProceed={canProceedToPin()}
|
|
138
171
|
onProceed={() => setStep('pin')}
|
|
139
172
|
/>
|
|
140
173
|
);
|
|
@@ -151,7 +184,7 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
151
184
|
return (
|
|
152
185
|
<TrainingModal
|
|
153
186
|
visible={step === 'training'}
|
|
154
|
-
onClose={
|
|
187
|
+
onClose={handleClose}
|
|
155
188
|
onComplete={() => {
|
|
156
189
|
onComplete('https://api2.onairos.uk', 'dummy-token', {
|
|
157
190
|
pin,
|
|
@@ -164,40 +197,84 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
164
197
|
username="demo_user"
|
|
165
198
|
progress={training.progress}
|
|
166
199
|
eta={training.eta}
|
|
167
|
-
onCancel={
|
|
200
|
+
onCancel={handleClose}
|
|
168
201
|
/>
|
|
169
202
|
);
|
|
170
203
|
}
|
|
171
204
|
};
|
|
172
205
|
|
|
206
|
+
if (!visible) return null;
|
|
207
|
+
|
|
173
208
|
return (
|
|
174
|
-
<
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
209
|
+
<Modal
|
|
210
|
+
visible={visible}
|
|
211
|
+
transparent
|
|
212
|
+
animationType="none"
|
|
213
|
+
statusBarTranslucent
|
|
214
|
+
onRequestClose={handleClose}
|
|
180
215
|
>
|
|
181
|
-
<
|
|
182
|
-
{
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
216
|
+
<TouchableWithoutFeedback onPress={handleClose}>
|
|
217
|
+
<View style={styles.modalOverlay}>
|
|
218
|
+
<TouchableWithoutFeedback onPress={e => e.stopPropagation()}>
|
|
219
|
+
<Animated.View
|
|
220
|
+
style={[
|
|
221
|
+
styles.bottomSheet,
|
|
222
|
+
{
|
|
223
|
+
transform: [{ translateY: slideAnim }],
|
|
224
|
+
}
|
|
225
|
+
]}
|
|
226
|
+
>
|
|
227
|
+
<SafeAreaView style={styles.container}>
|
|
228
|
+
<View style={styles.handleContainer}>
|
|
229
|
+
<View style={styles.handle} />
|
|
230
|
+
</View>
|
|
231
|
+
{renderHeader()}
|
|
232
|
+
{renderContent()}
|
|
233
|
+
</SafeAreaView>
|
|
234
|
+
</Animated.View>
|
|
235
|
+
</TouchableWithoutFeedback>
|
|
236
|
+
</View>
|
|
237
|
+
</TouchableWithoutFeedback>
|
|
238
|
+
</Modal>
|
|
186
239
|
);
|
|
187
240
|
};
|
|
188
241
|
|
|
189
242
|
const styles = StyleSheet.create({
|
|
243
|
+
modalOverlay: {
|
|
244
|
+
flex: 1,
|
|
245
|
+
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
246
|
+
justifyContent: 'flex-end',
|
|
247
|
+
alignItems: 'center',
|
|
248
|
+
},
|
|
249
|
+
bottomSheet: {
|
|
250
|
+
backgroundColor: '#fff',
|
|
251
|
+
width: width,
|
|
252
|
+
height: height * 0.9,
|
|
253
|
+
borderTopLeftRadius: 24,
|
|
254
|
+
borderTopRightRadius: 24,
|
|
255
|
+
overflow: 'hidden',
|
|
256
|
+
},
|
|
190
257
|
container: {
|
|
191
258
|
flex: 1,
|
|
192
259
|
backgroundColor: '#fff',
|
|
193
260
|
},
|
|
261
|
+
handleContainer: {
|
|
262
|
+
width: '100%',
|
|
263
|
+
alignItems: 'center',
|
|
264
|
+
paddingTop: 12,
|
|
265
|
+
paddingBottom: 8,
|
|
266
|
+
},
|
|
267
|
+
handle: {
|
|
268
|
+
width: 40,
|
|
269
|
+
height: 5,
|
|
270
|
+
borderRadius: 3,
|
|
271
|
+
backgroundColor: '#E0E0E0',
|
|
272
|
+
},
|
|
194
273
|
header: {
|
|
195
274
|
flexDirection: 'row',
|
|
196
275
|
alignItems: 'center',
|
|
197
276
|
padding: 16,
|
|
198
277
|
backgroundColor: COLORS.headerBg,
|
|
199
|
-
borderTopLeftRadius: 16,
|
|
200
|
-
borderTopRightRadius: 16,
|
|
201
278
|
},
|
|
202
279
|
headerTitle: {
|
|
203
280
|
flex: 1,
|
package/src/types.ts
CHANGED
|
@@ -44,13 +44,14 @@ export interface OnairosButtonProps {
|
|
|
44
44
|
buttonHeight?: number;
|
|
45
45
|
hasStroke?: boolean;
|
|
46
46
|
enabled?: boolean;
|
|
47
|
-
buttonForm?: 'default' | 'login' | 'signup';
|
|
47
|
+
buttonForm?: 'default' | 'login' | 'signup' | 'connect';
|
|
48
48
|
onRejection?: (error?: string) => void;
|
|
49
49
|
onResolved?: (apiUrl: string, token: string, userData: any) => void;
|
|
50
50
|
preCheck?: () => Promise<boolean>;
|
|
51
51
|
color?: string;
|
|
52
52
|
swerv?: boolean;
|
|
53
53
|
debug?: boolean;
|
|
54
|
+
darkMode?: boolean;
|
|
54
55
|
preferredPlatform?: string;
|
|
55
56
|
testMode?: boolean;
|
|
56
57
|
}
|