@onairos/react-native 3.0.20 → 3.0.22
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/components/OnairosButton.js +62 -7
- package/lib/commonjs/components/OnairosButton.js.map +1 -1
- package/lib/commonjs/components/PinInput.js +90 -7
- package/lib/commonjs/components/PinInput.js.map +1 -1
- package/lib/module/components/OnairosButton.js +62 -7
- package/lib/module/components/OnairosButton.js.map +1 -1
- package/lib/module/components/PinInput.js +91 -8
- package/lib/module/components/PinInput.js.map +1 -1
- package/lib/typescript/components/OnairosButton.d.ts.map +1 -1
- package/lib/typescript/components/PinInput.d.ts.map +1 -1
- package/lib/typescript/types.d.ts +6 -0
- package/lib/typescript/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/OnairosButton.tsx +365 -305
- package/src/components/PinInput.tsx +98 -5
- package/src/types.ts +6 -0
|
@@ -1,306 +1,366 @@
|
|
|
1
|
-
import React, { useState, useCallback, forwardRef, useImperativeHandle } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
TouchableOpacity,
|
|
4
|
-
Text,
|
|
5
|
-
StyleSheet,
|
|
6
|
-
View,
|
|
7
|
-
ViewStyle,
|
|
8
|
-
TextStyle,
|
|
9
|
-
ActivityIndicator,
|
|
10
|
-
Image,
|
|
11
|
-
} from 'react-native';
|
|
12
|
-
import { UniversalOnboarding } from './UniversalOnboarding';
|
|
13
|
-
import { Overlay } from './Overlay';
|
|
14
|
-
import { COLORS } from '../constants';
|
|
15
|
-
import type { OnairosButtonProps } from '../types';
|
|
16
|
-
import { hasCredentials, getCredentials, deleteCredentials as clearCredentials } from '../utils/secureStorage';
|
|
17
|
-
import { onairosApi } from '../api';
|
|
18
|
-
import { Portal } from '../utils/Portal';
|
|
19
|
-
|
|
20
|
-
export interface OnairosButtonRef {
|
|
21
|
-
trigger: () => Promise<void>;
|
|
22
|
-
reset: () => Promise<void>;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* OnairosButton Component - A sign-in button similar to Google/Apple sign-in
|
|
27
|
-
*/
|
|
28
|
-
export const OnairosButton = forwardRef<OnairosButtonRef, OnairosButtonProps>(({
|
|
29
|
-
returnLink,
|
|
30
|
-
prefillUrl,
|
|
31
|
-
AppName,
|
|
32
|
-
buttonType = 'normal',
|
|
33
|
-
requestData,
|
|
34
|
-
buttonWidth = 180,
|
|
35
|
-
buttonHeight = 48,
|
|
36
|
-
hasStroke = false,
|
|
37
|
-
enabled = true,
|
|
38
|
-
buttonForm = 'default',
|
|
39
|
-
onRejection,
|
|
40
|
-
onResolved,
|
|
41
|
-
preCheck,
|
|
42
|
-
color,
|
|
43
|
-
swerv = false,
|
|
44
|
-
debug = false,
|
|
45
|
-
darkMode = false,
|
|
46
|
-
preferredPlatform,
|
|
47
|
-
testMode = false,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
)
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
1
|
+
import React, { useState, useCallback, forwardRef, useImperativeHandle } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
TouchableOpacity,
|
|
4
|
+
Text,
|
|
5
|
+
StyleSheet,
|
|
6
|
+
View,
|
|
7
|
+
ViewStyle,
|
|
8
|
+
TextStyle,
|
|
9
|
+
ActivityIndicator,
|
|
10
|
+
Image,
|
|
11
|
+
} from 'react-native';
|
|
12
|
+
import { UniversalOnboarding } from './UniversalOnboarding';
|
|
13
|
+
import { Overlay } from './Overlay';
|
|
14
|
+
import { COLORS } from '../constants';
|
|
15
|
+
import type { OnairosButtonProps } from '../types';
|
|
16
|
+
import { hasCredentials, getCredentials, deleteCredentials as clearCredentials } from '../utils/secureStorage';
|
|
17
|
+
import { onairosApi } from '../api';
|
|
18
|
+
import { Portal } from '../utils/Portal';
|
|
19
|
+
|
|
20
|
+
export interface OnairosButtonRef {
|
|
21
|
+
trigger: () => Promise<void>;
|
|
22
|
+
reset: () => Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* OnairosButton Component - A sign-in button similar to Google/Apple sign-in
|
|
27
|
+
*/
|
|
28
|
+
export const OnairosButton = forwardRef<OnairosButtonRef, OnairosButtonProps>(({
|
|
29
|
+
returnLink,
|
|
30
|
+
prefillUrl,
|
|
31
|
+
AppName,
|
|
32
|
+
buttonType = 'normal',
|
|
33
|
+
requestData,
|
|
34
|
+
buttonWidth = 180,
|
|
35
|
+
buttonHeight = 48,
|
|
36
|
+
hasStroke = false,
|
|
37
|
+
enabled = true,
|
|
38
|
+
buttonForm = 'default',
|
|
39
|
+
onRejection,
|
|
40
|
+
onResolved,
|
|
41
|
+
preCheck,
|
|
42
|
+
color,
|
|
43
|
+
swerv = false,
|
|
44
|
+
debug = false,
|
|
45
|
+
darkMode = false,
|
|
46
|
+
preferredPlatform,
|
|
47
|
+
testMode = false,
|
|
48
|
+
autoFetch = false,
|
|
49
|
+
inferenceData,
|
|
50
|
+
textLayout,
|
|
51
|
+
textColor: customTextColor,
|
|
52
|
+
proofMode = false,
|
|
53
|
+
webpageName,
|
|
54
|
+
}, ref) => {
|
|
55
|
+
const [showOnboarding, setShowOnboarding] = useState(false);
|
|
56
|
+
const [showOverlay, setShowOverlay] = useState(false);
|
|
57
|
+
const [storedCredentials, setStoredCredentials] = useState<any>(null);
|
|
58
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
59
|
+
const [isPressed, setIsPressed] = useState(false);
|
|
60
|
+
|
|
61
|
+
// Expose methods via ref
|
|
62
|
+
useImperativeHandle(ref, () => ({
|
|
63
|
+
trigger: async () => {
|
|
64
|
+
await handlePress();
|
|
65
|
+
},
|
|
66
|
+
reset: async () => {
|
|
67
|
+
await clearCredentials();
|
|
68
|
+
}
|
|
69
|
+
}));
|
|
70
|
+
|
|
71
|
+
// Compute button text based on buttonForm
|
|
72
|
+
const getButtonText = () => {
|
|
73
|
+
if (buttonForm === 'connect' || buttonForm === 'signup') {
|
|
74
|
+
return 'Connect with Onairos';
|
|
75
|
+
} else {
|
|
76
|
+
return 'Sign in with Onairos';
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Calculate background color based on props and state
|
|
81
|
+
const getBackgroundColor = (): string => {
|
|
82
|
+
if (!enabled) {
|
|
83
|
+
return darkMode ? '#3A3A3A' : '#e0e0e0';
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (isPressed) {
|
|
87
|
+
return color ?
|
|
88
|
+
(typeof color === 'string' ? `${color}80` : color) :
|
|
89
|
+
(darkMode ? '#32323280' : '#f5f5f580');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return color || (darkMode ? '#2A2A2A' : '#ffffff');
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
// Calculate text color based on background luminance
|
|
96
|
+
const getTextColor = (): string => {
|
|
97
|
+
if (!enabled) {
|
|
98
|
+
return darkMode ? '#777777' : '#AAAAAA';
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (darkMode) {
|
|
102
|
+
return '#FFFFFF';
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const bgColor = getBackgroundColor();
|
|
106
|
+
// Simple luminance check
|
|
107
|
+
return bgColor === '#ffffff' || bgColor === '#f5f5f580' || bgColor.includes('#f') ? '#000000' : '#FFFFFF';
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const handlePress = async () => {
|
|
111
|
+
if (!enabled || isLoading) return;
|
|
112
|
+
|
|
113
|
+
setIsLoading(true);
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
// If autoFetch is enabled, directly call the API with inferenceData
|
|
117
|
+
if (autoFetch) {
|
|
118
|
+
if (!inferenceData) {
|
|
119
|
+
throw new Error('inferenceData is required when autoFetch is enabled');
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
// Check if credentials exist
|
|
124
|
+
const hasStoredCreds = await hasCredentials();
|
|
125
|
+
|
|
126
|
+
if (hasStoredCreds) {
|
|
127
|
+
const credentials = await getCredentials();
|
|
128
|
+
|
|
129
|
+
if (!credentials || !credentials.username) {
|
|
130
|
+
throw new Error('Invalid credentials');
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Call the API directly with inferenceData
|
|
134
|
+
// Using a custom API call for inference
|
|
135
|
+
const result = await fetch(`https://api.onairos.ai/inference`, {
|
|
136
|
+
method: 'POST',
|
|
137
|
+
headers: {
|
|
138
|
+
'Content-Type': 'application/json',
|
|
139
|
+
'Authorization': `Bearer ${credentials.userPin || ''}`
|
|
140
|
+
},
|
|
141
|
+
body: JSON.stringify({
|
|
142
|
+
username: credentials.username,
|
|
143
|
+
modelKey: credentials.userPin || '',
|
|
144
|
+
data: inferenceData,
|
|
145
|
+
requestData: requestData || {},
|
|
146
|
+
proofMode: proofMode,
|
|
147
|
+
webpageName: webpageName || AppName
|
|
148
|
+
})
|
|
149
|
+
}).then(res => res.json());
|
|
150
|
+
|
|
151
|
+
if (result && result.success) {
|
|
152
|
+
if (onResolved) {
|
|
153
|
+
onResolved(result.apiUrl || '', result.token || '', result.data || {});
|
|
154
|
+
}
|
|
155
|
+
setIsLoading(false);
|
|
156
|
+
return;
|
|
157
|
+
} else {
|
|
158
|
+
throw new Error(result?.error || 'API call failed');
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
// No credentials, proceed with normal flow
|
|
162
|
+
console.log('No credentials found, proceeding with normal flow');
|
|
163
|
+
}
|
|
164
|
+
} catch (autoFetchError) {
|
|
165
|
+
console.error('AutoFetch error:', autoFetchError);
|
|
166
|
+
// Fall back to normal flow on error
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (preCheck) {
|
|
171
|
+
const shouldProceed = await preCheck();
|
|
172
|
+
if (!shouldProceed) {
|
|
173
|
+
onRejection?.('Precheck validation failed');
|
|
174
|
+
setIsLoading(false);
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Check if credentials exist
|
|
180
|
+
const hasStoredCreds = await hasCredentials();
|
|
181
|
+
|
|
182
|
+
if (hasStoredCreds) {
|
|
183
|
+
// If credentials exist, fetch them and verify
|
|
184
|
+
const credentials = await getCredentials();
|
|
185
|
+
|
|
186
|
+
if (!credentials || !credentials.username) {
|
|
187
|
+
// Invalid credentials, clear and start fresh
|
|
188
|
+
await clearCredentials();
|
|
189
|
+
setShowOnboarding(true);
|
|
190
|
+
setIsLoading(false);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
// Validate credentials with server
|
|
196
|
+
const isValid = await onairosApi.validateCredentials(credentials.username);
|
|
197
|
+
|
|
198
|
+
if (!isValid) {
|
|
199
|
+
// Clear invalid credentials
|
|
200
|
+
await clearCredentials();
|
|
201
|
+
setShowOnboarding(true);
|
|
202
|
+
setIsLoading(false);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Store and display overlay with valid credentials
|
|
207
|
+
setStoredCredentials(credentials);
|
|
208
|
+
setShowOverlay(true);
|
|
209
|
+
} catch (validationError) {
|
|
210
|
+
console.warn('Validation error, proceeding to onboarding:', validationError);
|
|
211
|
+
setShowOnboarding(true);
|
|
212
|
+
}
|
|
213
|
+
} else {
|
|
214
|
+
// If no credentials, show onboarding
|
|
215
|
+
setShowOnboarding(true);
|
|
216
|
+
}
|
|
217
|
+
} catch (error) {
|
|
218
|
+
console.error('Error during button press flow:', error);
|
|
219
|
+
// Fall back to onboarding on error
|
|
220
|
+
setShowOnboarding(true);
|
|
221
|
+
onRejection?.(error instanceof Error ? error.message : 'Unknown error');
|
|
222
|
+
} finally {
|
|
223
|
+
setIsLoading(false);
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
const handleOnboardingComplete = useCallback((apiUrl: string, token: string, data: any) => {
|
|
228
|
+
setShowOnboarding(false);
|
|
229
|
+
if (onResolved) {
|
|
230
|
+
onResolved(apiUrl, token, data);
|
|
231
|
+
}
|
|
232
|
+
}, [onResolved]);
|
|
233
|
+
|
|
234
|
+
const handleOverlayResolved = useCallback((apiUrl: string, token: string, data: any) => {
|
|
235
|
+
setShowOverlay(false);
|
|
236
|
+
if (onResolved) {
|
|
237
|
+
onResolved(apiUrl, token, data);
|
|
238
|
+
}
|
|
239
|
+
}, [onResolved]);
|
|
240
|
+
|
|
241
|
+
// Calculate button styles based on props
|
|
242
|
+
const buttonStyle: ViewStyle[] = [
|
|
243
|
+
styles.button,
|
|
244
|
+
buttonType === 'pill' && styles.pillButton,
|
|
245
|
+
hasStroke && styles.strokedButton,
|
|
246
|
+
{
|
|
247
|
+
width: buttonWidth,
|
|
248
|
+
height: buttonHeight,
|
|
249
|
+
backgroundColor: getBackgroundColor(),
|
|
250
|
+
borderColor: darkMode ? '#555555' : '#000000',
|
|
251
|
+
},
|
|
252
|
+
swerv && styles.swervButton,
|
|
253
|
+
!enabled && styles.disabledButton
|
|
254
|
+
].filter(Boolean) as ViewStyle[];
|
|
255
|
+
|
|
256
|
+
// Calculate button text color
|
|
257
|
+
const buttonTextColor = getTextColor();
|
|
258
|
+
|
|
259
|
+
// Render components
|
|
260
|
+
return (
|
|
261
|
+
<>
|
|
262
|
+
<TouchableOpacity
|
|
263
|
+
style={buttonStyle}
|
|
264
|
+
onPress={handlePress}
|
|
265
|
+
disabled={!enabled || isLoading}
|
|
266
|
+
accessibilityLabel={`Sign in with Onairos`}
|
|
267
|
+
onPressIn={() => setIsPressed(true)}
|
|
268
|
+
onPressOut={() => setIsPressed(false)}
|
|
269
|
+
>
|
|
270
|
+
{isLoading ? (
|
|
271
|
+
<ActivityIndicator
|
|
272
|
+
size="small"
|
|
273
|
+
color={buttonTextColor}
|
|
274
|
+
/>
|
|
275
|
+
) : (
|
|
276
|
+
<View style={styles.buttonContent}>
|
|
277
|
+
<Image
|
|
278
|
+
source={require('../assets/images/onairos_logo.png')}
|
|
279
|
+
style={styles.logo}
|
|
280
|
+
resizeMode="contain"
|
|
281
|
+
/>
|
|
282
|
+
<Text style={[styles.buttonText, { color: buttonTextColor }]}>
|
|
283
|
+
{getButtonText()}
|
|
284
|
+
</Text>
|
|
285
|
+
</View>
|
|
286
|
+
)}
|
|
287
|
+
</TouchableOpacity>
|
|
288
|
+
|
|
289
|
+
{/* Overlay and Onboarding components rendered outside the button */}
|
|
290
|
+
{showOnboarding && (
|
|
291
|
+
<UniversalOnboarding
|
|
292
|
+
visible={showOnboarding}
|
|
293
|
+
onClose={() => {
|
|
294
|
+
setShowOnboarding(false);
|
|
295
|
+
onRejection?.('User closed onboarding');
|
|
296
|
+
}}
|
|
297
|
+
AppName={AppName}
|
|
298
|
+
requestData={requestData as any}
|
|
299
|
+
returnLink={returnLink || ''}
|
|
300
|
+
onComplete={handleOnboardingComplete}
|
|
301
|
+
debug={debug}
|
|
302
|
+
test={testMode}
|
|
303
|
+
preferredPlatform={preferredPlatform}
|
|
304
|
+
/>
|
|
305
|
+
)}
|
|
306
|
+
|
|
307
|
+
{/* Overlay rendered through Portal to ensure it appears at root level */}
|
|
308
|
+
{showOverlay && storedCredentials && (
|
|
309
|
+
<Portal>
|
|
310
|
+
<Overlay
|
|
311
|
+
data={requestData || {}}
|
|
312
|
+
username={storedCredentials.username}
|
|
313
|
+
modelKey={storedCredentials.userPin || ''}
|
|
314
|
+
onResolved={handleOverlayResolved}
|
|
315
|
+
appName={AppName}
|
|
316
|
+
darkMode={darkMode}
|
|
317
|
+
/>
|
|
318
|
+
</Portal>
|
|
319
|
+
)}
|
|
320
|
+
</>
|
|
321
|
+
);
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
const styles = StyleSheet.create({
|
|
325
|
+
button: {
|
|
326
|
+
flexDirection: 'row',
|
|
327
|
+
alignItems: 'center',
|
|
328
|
+
justifyContent: 'center',
|
|
329
|
+
paddingVertical: 12,
|
|
330
|
+
paddingHorizontal: 16,
|
|
331
|
+
borderRadius: 8,
|
|
332
|
+
shadowColor: '#000',
|
|
333
|
+
shadowOffset: { width: 0, height: 2 },
|
|
334
|
+
shadowOpacity: 0.1,
|
|
335
|
+
shadowRadius: 4,
|
|
336
|
+
elevation: 2,
|
|
337
|
+
},
|
|
338
|
+
buttonContent: {
|
|
339
|
+
flexDirection: 'row',
|
|
340
|
+
alignItems: 'center',
|
|
341
|
+
justifyContent: 'center',
|
|
342
|
+
},
|
|
343
|
+
logo: {
|
|
344
|
+
width: 24,
|
|
345
|
+
height: 24,
|
|
346
|
+
marginRight: 8,
|
|
347
|
+
},
|
|
348
|
+
pillButton: {
|
|
349
|
+
borderRadius: 24,
|
|
350
|
+
},
|
|
351
|
+
strokedButton: {
|
|
352
|
+
backgroundColor: 'transparent',
|
|
353
|
+
borderWidth: 1,
|
|
354
|
+
},
|
|
355
|
+
swervButton: {
|
|
356
|
+
transform: [{ rotate: '-2deg' }],
|
|
357
|
+
},
|
|
358
|
+
disabledButton: {
|
|
359
|
+
opacity: 0.6,
|
|
360
|
+
},
|
|
361
|
+
buttonText: {
|
|
362
|
+
fontSize: 16,
|
|
363
|
+
fontWeight: '600',
|
|
364
|
+
textAlign: 'center',
|
|
365
|
+
},
|
|
306
366
|
});
|