@sanctum-key/react-native-sdk 1.0.18 → 1.0.20
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/README.md +1 -1
- package/build/package.json +3 -2
- package/build/src/components/EnhancedCameraView.d.ts.map +1 -1
- package/build/src/components/EnhancedCameraView.js +19 -182
- package/build/src/components/EnhancedCameraView.js.map +1 -1
- package/build/src/components/KYCElements/CountrySelectionTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/CountrySelectionTemplate.js +40 -128
- package/build/src/components/KYCElements/CountrySelectionTemplate.js.map +1 -1
- package/build/src/components/KYCElements/IDCardCapture.d.ts.map +1 -1
- package/build/src/components/KYCElements/IDCardCapture.js +224 -189
- package/build/src/components/KYCElements/IDCardCapture.js.map +1 -1
- package/build/src/components/KYCElements/PhoneVerificationTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/PhoneVerificationTemplate.js +0 -2
- package/build/src/components/KYCElements/PhoneVerificationTemplate.js.map +1 -1
- package/build/src/components/KYCElements/VerificationProgressTemplate.d.ts.map +1 -1
- package/build/src/components/KYCElements/VerificationProgressTemplate.js +38 -33
- package/build/src/components/KYCElements/VerificationProgressTemplate.js.map +1 -1
- package/build/src/components/OverLay/IdCard.d.ts +6 -1
- package/build/src/components/OverLay/IdCard.d.ts.map +1 -1
- package/build/src/components/OverLay/IdCard.js +36 -34
- package/build/src/components/OverLay/IdCard.js.map +1 -1
- package/build/src/config/countriesData.d.ts.map +1 -1
- package/build/src/config/countriesData.js.map +1 -1
- package/build/src/hooks/useTemplateKYCFlow.js +1 -1
- package/build/src/hooks/useTemplateKYCFlow.js.map +1 -1
- package/build/src/modules/api/CardAuthentification.d.ts +5 -0
- package/build/src/modules/api/CardAuthentification.d.ts.map +1 -1
- package/build/src/modules/api/CardAuthentification.js +67 -14
- package/build/src/modules/api/CardAuthentification.js.map +1 -1
- package/build/src/modules/api/KYCService.d.ts +10 -0
- package/build/src/modules/api/KYCService.d.ts.map +1 -1
- package/build/src/modules/api/KYCService.js +135 -49
- package/build/src/modules/api/KYCService.js.map +1 -1
- package/build/src/web/WebKYCEntry.d.ts.map +1 -1
- package/build/src/web/WebKYCEntry.js +34 -6
- package/build/src/web/WebKYCEntry.js.map +1 -1
- package/package.json +3 -2
- package/src/components/EnhancedCameraView.tsx +28 -219
- package/src/components/KYCElements/CountrySelectionTemplate.tsx +53 -133
- package/src/components/KYCElements/IDCardCapture.tsx +606 -570
- package/src/components/KYCElements/PhoneVerificationTemplate.tsx +0 -2
- package/src/components/KYCElements/VerificationProgressTemplate.tsx +54 -66
- package/src/components/OverLay/IdCard.tsx +48 -36
- package/src/config/countriesData.ts +0 -4
- package/src/hooks/useTemplateKYCFlow.tsx +14 -14
- package/src/modules/api/CardAuthentification.ts +133 -67
- package/src/modules/api/KYCService.ts +189 -66
- package/src/web/WebKYCEntry.tsx +42 -7
package/README.md
CHANGED
|
@@ -45,7 +45,7 @@ npm install @sanctum-key/react-native-sdk --legacy-peer-deps
|
|
|
45
45
|
Use `npx expo install` so Expo automatically resolves the correct versions for your SDK build (e.g., SDK 53 or 54):
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
|
-
npx expo install react-native-vision-camera expo-location expo-image-manipulator react-native-svg expo-file-system expo-dev-client
|
|
48
|
+
npx expo install react-native-vision-camera expo-location expo-image-manipulator react-native-svg expo-file-system expo-dev-client react-native-qrcode-svg
|
|
49
49
|
```
|
|
50
50
|
|
|
51
51
|
### Step 3 — Install Standard NPM Dependencies
|
package/build/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanctum-key/react-native-sdk",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.20",
|
|
4
4
|
"description": "Sanctum Key React Native SDK",
|
|
5
5
|
"main": "build/src/index.js",
|
|
6
6
|
"types": "build/src/index.d.ts",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"expo-blur": "~15.0.8",
|
|
52
52
|
"i18n-js": "4.5.1",
|
|
53
53
|
"iconsax-react-nativejs": "^0.0.8",
|
|
54
|
+
"react-native-qrcode-svg": "^6.3.21",
|
|
54
55
|
"zustand": "^5.0.8"
|
|
55
56
|
},
|
|
56
57
|
"devDependencies": {
|
|
@@ -66,7 +67,7 @@
|
|
|
66
67
|
"expo-location": "*",
|
|
67
68
|
"react": "*",
|
|
68
69
|
"react-native": "*",
|
|
69
|
-
"react-native-svg": "
|
|
70
|
+
"react-native-svg": "^15.15.5",
|
|
70
71
|
"react-native-vision-camera": "^4.7.1"
|
|
71
72
|
}
|
|
72
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EnhancedCameraView.d.ts","sourceRoot":"","sources":["../../../src/components/EnhancedCameraView.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EnhancedCameraView.d.ts","sourceRoot":"","sources":["../../../src/components/EnhancedCameraView.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAOxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAIzD,eAAO,MAAM,kBAAkB,EAAE,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAgHhE,CAAC"}
|
|
@@ -1,146 +1,3 @@
|
|
|
1
|
-
// import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
-
// import { View, StyleSheet, Text, AppState } from 'react-native';
|
|
3
|
-
// import { Camera, useCameraDevice, useCameraFormat } from 'react-native-vision-camera';
|
|
4
|
-
// import VisionCameraModule from '../modules/camera/VisionCameraModule';
|
|
5
|
-
// import { useI18n } from '../hooks/useI18n';
|
|
6
|
-
// import { EnhancedCameraViewProps } from './OverLay/type';
|
|
7
|
-
// import { Button } from './ui/Button';
|
|
8
|
-
// export const EnhancedCameraView: React.FC<EnhancedCameraViewProps> = ({
|
|
9
|
-
// showCamera,
|
|
10
|
-
// cameraType: initialCameraType = 'front',
|
|
11
|
-
// style,
|
|
12
|
-
// onError,
|
|
13
|
-
// onSilentCapture,
|
|
14
|
-
// silentCaptureResult,
|
|
15
|
-
// isProcessing = false,
|
|
16
|
-
// overlayComponent,
|
|
17
|
-
// }) => {
|
|
18
|
-
// const { t } = useI18n();
|
|
19
|
-
// const camera = useRef<Camera>(null);
|
|
20
|
-
// const isCapturingRef = useRef(false);
|
|
21
|
-
// const isProcessingRef = useRef(isProcessing);
|
|
22
|
-
// const [cameraType] = useState<'front' | 'back'>(initialCameraType);
|
|
23
|
-
// const [hasPermission, setHasPermission] = useState<boolean | null>(null);
|
|
24
|
-
// const [isInitialized, setIsInitialized] = useState(false);
|
|
25
|
-
// const [refreshCamera, setRefreshCamera] = useState(false);
|
|
26
|
-
// const [layout, setLayout] = useState({ width: 0, height: 0 });
|
|
27
|
-
// const device = useCameraDevice(cameraType, {
|
|
28
|
-
// physicalDevices: [
|
|
29
|
-
// 'wide-angle-camera' // Explicitly request standard 1x lens
|
|
30
|
-
// ]
|
|
31
|
-
// });
|
|
32
|
-
// const targetRatio = layout.width > 0 ? layout.height / layout.width : 16 / 9;
|
|
33
|
-
// const format = useCameraFormat(device, [
|
|
34
|
-
// { photoAspectRatio: targetRatio },
|
|
35
|
-
// { photoResolution: 'max' }
|
|
36
|
-
// ]);
|
|
37
|
-
// useEffect(() => {
|
|
38
|
-
// isProcessingRef.current = isProcessing;
|
|
39
|
-
// }, [isProcessing]);
|
|
40
|
-
// const checkPermissions = async () => {
|
|
41
|
-
// try {
|
|
42
|
-
// const hasAllPermissions = await VisionCameraModule.hasAllPermissions();
|
|
43
|
-
// if (!hasAllPermissions) {
|
|
44
|
-
// const granted = await VisionCameraModule.requestAllPermissions();
|
|
45
|
-
// if (!granted) {
|
|
46
|
-
// setHasPermission(false);
|
|
47
|
-
// onError?.({ message: t('camera.permissionRequired') });
|
|
48
|
-
// return;
|
|
49
|
-
// }
|
|
50
|
-
// }
|
|
51
|
-
// setHasPermission(true);
|
|
52
|
-
// } catch (error) {
|
|
53
|
-
// setHasPermission(false);
|
|
54
|
-
// onError?.({ message: t('camera.errorOccurred') });
|
|
55
|
-
// }
|
|
56
|
-
// };
|
|
57
|
-
// useEffect(() => {
|
|
58
|
-
// if (showCamera) checkPermissions();
|
|
59
|
-
// }, [showCamera, refreshCamera]);
|
|
60
|
-
// useEffect(() => {
|
|
61
|
-
// const subscription = AppState.addEventListener('change', nextAppState => {
|
|
62
|
-
// if (nextAppState === 'active' && showCamera && hasPermission === false) {
|
|
63
|
-
// checkPermissions();
|
|
64
|
-
// }
|
|
65
|
-
// });
|
|
66
|
-
// return () => subscription.remove();
|
|
67
|
-
// }, [showCamera, hasPermission]);
|
|
68
|
-
// const onInitialized = useCallback(() => setIsInitialized(true), []);
|
|
69
|
-
// const onCameraError = useCallback((error: any) => {
|
|
70
|
-
// onError?.({ message: error.message || t('camera.errorOccurred') });
|
|
71
|
-
// }, [onError, t]);
|
|
72
|
-
// const captureSilentPhoto = useCallback(async () => {
|
|
73
|
-
// if (!camera.current || !isInitialized || isProcessingRef.current || isCapturingRef.current) return;
|
|
74
|
-
// if (silentCaptureResult?.isAnalyzing) return;
|
|
75
|
-
// try {
|
|
76
|
-
// isCapturingRef.current = true;
|
|
77
|
-
// const photo = await camera.current.takePhoto({
|
|
78
|
-
// enableShutterSound: false,
|
|
79
|
-
// flash: 'off',
|
|
80
|
-
// });
|
|
81
|
-
// const result = await VisionCameraModule.processPhotoResult(photo);
|
|
82
|
-
// onSilentCapture?.({
|
|
83
|
-
// ...result,
|
|
84
|
-
// path: result.path || photo.path,
|
|
85
|
-
// });
|
|
86
|
-
// } catch (error) {
|
|
87
|
-
// // Silent background fail
|
|
88
|
-
// } finally {
|
|
89
|
-
// isCapturingRef.current = false;
|
|
90
|
-
// }
|
|
91
|
-
// }, [isInitialized, onSilentCapture, silentCaptureResult]);
|
|
92
|
-
// useEffect(() => {
|
|
93
|
-
// if (!showCamera || !isInitialized || isProcessing) return;
|
|
94
|
-
// let isActive = true;
|
|
95
|
-
// let intervalId: ReturnType<typeof setInterval>;
|
|
96
|
-
// const warmupTimer = setTimeout(() => {
|
|
97
|
-
// if (!isActive) return;
|
|
98
|
-
// intervalId = setInterval(() => {
|
|
99
|
-
// captureSilentPhoto();
|
|
100
|
-
// }, 1500);
|
|
101
|
-
// }, 1000);
|
|
102
|
-
// return () => {
|
|
103
|
-
// isActive = false;
|
|
104
|
-
// clearTimeout(warmupTimer);
|
|
105
|
-
// if (intervalId) clearInterval(intervalId);
|
|
106
|
-
// };
|
|
107
|
-
// }, [showCamera, isInitialized, isProcessing, captureSilentPhoto]);
|
|
108
|
-
// if (hasPermission === null) return <View style={[styles.container, style]} />;
|
|
109
|
-
// if (hasPermission === false) {
|
|
110
|
-
// return (
|
|
111
|
-
// <View style={[styles.container, style, { justifyContent: 'center', alignItems: 'center' }]}>
|
|
112
|
-
// <Text style={styles.permissionMessage}>{t('camera.permissionRequired')}</Text>
|
|
113
|
-
// <Button title="Refresh Camera" onPress={() => setRefreshCamera(prev => !prev)} variant="primary" />
|
|
114
|
-
// </View>
|
|
115
|
-
// );
|
|
116
|
-
// }
|
|
117
|
-
// if (!device || !showCamera) return <View style={[styles.container, style]} />;
|
|
118
|
-
// return (
|
|
119
|
-
// <View
|
|
120
|
-
// style={[styles.container, style]}
|
|
121
|
-
// onLayout={(e) => setLayout({ width: e.nativeEvent.layout.width, height: e.nativeEvent.layout.height })}
|
|
122
|
-
// >
|
|
123
|
-
// <Camera
|
|
124
|
-
// ref={camera}
|
|
125
|
-
// style={StyleSheet.absoluteFill}
|
|
126
|
-
// device={device}
|
|
127
|
-
// format={format}
|
|
128
|
-
// resizeMode="cover"
|
|
129
|
-
// isActive={showCamera && !isProcessing}
|
|
130
|
-
// photo={true}
|
|
131
|
-
// video={false}
|
|
132
|
-
// audio={false}
|
|
133
|
-
// onInitialized={onInitialized}
|
|
134
|
-
// onError={onCameraError}
|
|
135
|
-
// />
|
|
136
|
-
// {overlayComponent}
|
|
137
|
-
// </View>
|
|
138
|
-
// );
|
|
139
|
-
// };
|
|
140
|
-
// const styles = StyleSheet.create({
|
|
141
|
-
// container: { flex: 1, backgroundColor: 'black' },
|
|
142
|
-
// permissionMessage: { color: 'white', textAlign: 'center', margin: 20, fontSize: 16 },
|
|
143
|
-
// });
|
|
144
1
|
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
145
2
|
import { View, StyleSheet, Text, AppState } from 'react-native';
|
|
146
3
|
import { Camera, useCameraDevice } from 'react-native-vision-camera';
|
|
@@ -156,12 +13,8 @@ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType =
|
|
|
156
13
|
const [hasPermission, setHasPermission] = useState(null);
|
|
157
14
|
const [isInitialized, setIsInitialized] = useState(false);
|
|
158
15
|
const [refreshCamera, setRefreshCamera] = useState(false);
|
|
159
|
-
// 🚨 THE FIX: Removed the strict physical device filtering and custom format.
|
|
160
|
-
// This allows Android to select its own supported, stable hardware stream, preventing crashes.
|
|
161
16
|
const device = useCameraDevice(cameraType);
|
|
162
|
-
useEffect(() => {
|
|
163
|
-
isProcessingRef.current = isProcessing;
|
|
164
|
-
}, [isProcessing]);
|
|
17
|
+
useEffect(() => { isProcessingRef.current = isProcessing; }, [isProcessing]);
|
|
165
18
|
const checkPermissions = async () => {
|
|
166
19
|
try {
|
|
167
20
|
const hasAllPermissions = await VisionCameraModule.hasAllPermissions();
|
|
@@ -175,22 +28,19 @@ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType =
|
|
|
175
28
|
}
|
|
176
29
|
setHasPermission(true);
|
|
177
30
|
}
|
|
178
|
-
catch
|
|
31
|
+
catch {
|
|
179
32
|
setHasPermission(false);
|
|
180
33
|
onError?.({ message: t('camera.errorOccurred') });
|
|
181
34
|
}
|
|
182
35
|
};
|
|
36
|
+
useEffect(() => { if (showCamera)
|
|
37
|
+
checkPermissions(); }, [showCamera, refreshCamera]);
|
|
183
38
|
useEffect(() => {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
}, [showCamera, refreshCamera]);
|
|
187
|
-
useEffect(() => {
|
|
188
|
-
const subscription = AppState.addEventListener('change', nextAppState => {
|
|
189
|
-
if (nextAppState === 'active' && showCamera && hasPermission === false) {
|
|
39
|
+
const sub = AppState.addEventListener('change', next => {
|
|
40
|
+
if (next === 'active' && showCamera && hasPermission === false)
|
|
190
41
|
checkPermissions();
|
|
191
|
-
}
|
|
192
42
|
});
|
|
193
|
-
return () =>
|
|
43
|
+
return () => sub.remove();
|
|
194
44
|
}, [showCamera, hasPermission]);
|
|
195
45
|
const onInitialized = useCallback(() => setIsInitialized(true), []);
|
|
196
46
|
const onCameraError = useCallback((error) => {
|
|
@@ -203,19 +53,11 @@ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType =
|
|
|
203
53
|
return;
|
|
204
54
|
try {
|
|
205
55
|
isCapturingRef.current = true;
|
|
206
|
-
const photo = await camera.current.takePhoto({
|
|
207
|
-
enableShutterSound: false,
|
|
208
|
-
flash: 'off',
|
|
209
|
-
});
|
|
56
|
+
const photo = await camera.current.takePhoto({ enableShutterSound: false, flash: 'off' });
|
|
210
57
|
const result = await VisionCameraModule.processPhotoResult(photo);
|
|
211
|
-
onSilentCapture?.({
|
|
212
|
-
...result,
|
|
213
|
-
path: result.path || photo.path,
|
|
214
|
-
});
|
|
215
|
-
}
|
|
216
|
-
catch (error) {
|
|
217
|
-
// Silent background fail
|
|
58
|
+
onSilentCapture?.({ ...result, path: result.path || photo.path });
|
|
218
59
|
}
|
|
60
|
+
catch { /* silent */ }
|
|
219
61
|
finally {
|
|
220
62
|
isCapturingRef.current = false;
|
|
221
63
|
}
|
|
@@ -223,34 +65,29 @@ export const EnhancedCameraView = ({ showCamera, cameraType: initialCameraType =
|
|
|
223
65
|
useEffect(() => {
|
|
224
66
|
if (!showCamera || !isInitialized || isProcessing)
|
|
225
67
|
return;
|
|
226
|
-
let
|
|
227
|
-
let
|
|
228
|
-
const
|
|
229
|
-
if (!
|
|
68
|
+
let active = true;
|
|
69
|
+
let id;
|
|
70
|
+
const timer = setTimeout(() => {
|
|
71
|
+
if (!active)
|
|
230
72
|
return;
|
|
231
|
-
|
|
232
|
-
captureSilentPhoto();
|
|
233
|
-
}, 1500);
|
|
73
|
+
id = setInterval(captureSilentPhoto, 1500);
|
|
234
74
|
}, 1000);
|
|
235
|
-
return () => {
|
|
236
|
-
|
|
237
|
-
clearTimeout(warmupTimer);
|
|
238
|
-
if (intervalId)
|
|
239
|
-
clearInterval(intervalId);
|
|
240
|
-
};
|
|
75
|
+
return () => { active = false; clearTimeout(timer); if (id)
|
|
76
|
+
clearInterval(id); };
|
|
241
77
|
}, [showCamera, isInitialized, isProcessing, captureSilentPhoto]);
|
|
242
78
|
if (hasPermission === null)
|
|
243
79
|
return <View style={[styles.container, style]}/>;
|
|
244
80
|
if (hasPermission === false) {
|
|
245
81
|
return (<View style={[styles.container, style, { justifyContent: 'center', alignItems: 'center' }]}>
|
|
246
82
|
<Text style={styles.permissionMessage}>{t('camera.permissionRequired')}</Text>
|
|
247
|
-
<Button title="Refresh Camera" onPress={() => setRefreshCamera(
|
|
83
|
+
<Button title="Refresh Camera" onPress={() => setRefreshCamera(p => !p)} variant="primary"/>
|
|
248
84
|
</View>);
|
|
249
85
|
}
|
|
250
86
|
if (!device || !showCamera)
|
|
251
87
|
return <View style={[styles.container, style]}/>;
|
|
252
88
|
return (<View style={[styles.container, style]}>
|
|
253
89
|
<Camera ref={camera} style={StyleSheet.absoluteFill} device={device} resizeMode="cover" isActive={showCamera && !isProcessing} photo={true} video={false} audio={false} onInitialized={onInitialized} onError={onCameraError}/>
|
|
90
|
+
|
|
254
91
|
{overlayComponent}
|
|
255
92
|
</View>);
|
|
256
93
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EnhancedCameraView.js","sourceRoot":"","sources":["../../../src/components/EnhancedCameraView.tsx"],"names":[],"mappings":"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","sourcesContent":["// import React, { useCallback, useEffect, useRef, useState } from 'react';\n// import { View, StyleSheet, Text, AppState } from 'react-native';\n// import { Camera, useCameraDevice, useCameraFormat } from 'react-native-vision-camera'; \n// import VisionCameraModule from '../modules/camera/VisionCameraModule';\n// import { useI18n } from '../hooks/useI18n';\n// import { EnhancedCameraViewProps } from './OverLay/type';\n// import { Button } from './ui/Button';\n\n// export const EnhancedCameraView: React.FC<EnhancedCameraViewProps> = ({\n// showCamera,\n// cameraType: initialCameraType = 'front',\n// style,\n// onError,\n// onSilentCapture,\n// silentCaptureResult,\n// isProcessing = false,\n// overlayComponent,\n// }) => {\n// const { t } = useI18n();\n// const camera = useRef<Camera>(null);\n\n// const isCapturingRef = useRef(false);\n// const isProcessingRef = useRef(isProcessing);\n\n// const [cameraType] = useState<'front' | 'back'>(initialCameraType);\n// const [hasPermission, setHasPermission] = useState<boolean | null>(null);\n// const [isInitialized, setIsInitialized] = useState(false);\n// const [refreshCamera, setRefreshCamera] = useState(false);\n// const [layout, setLayout] = useState({ width: 0, height: 0 });\n\n\n// const device = useCameraDevice(cameraType, {\n// physicalDevices: [\n// 'wide-angle-camera' // Explicitly request standard 1x lens\n// ]\n// });\n\n// const targetRatio = layout.width > 0 ? layout.height / layout.width : 16 / 9;\n\n// const format = useCameraFormat(device, [\n// { photoAspectRatio: targetRatio },\n// { photoResolution: 'max' } \n// ]);\n\n// useEffect(() => {\n// isProcessingRef.current = isProcessing;\n// }, [isProcessing]);\n\n// const checkPermissions = async () => {\n// try {\n// const hasAllPermissions = await VisionCameraModule.hasAllPermissions();\n// if (!hasAllPermissions) {\n// const granted = await VisionCameraModule.requestAllPermissions();\n// if (!granted) {\n// setHasPermission(false);\n// onError?.({ message: t('camera.permissionRequired') });\n// return;\n// }\n// }\n// setHasPermission(true);\n// } catch (error) {\n// setHasPermission(false);\n// onError?.({ message: t('camera.errorOccurred') });\n// }\n// };\n\n// useEffect(() => {\n// if (showCamera) checkPermissions();\n// }, [showCamera, refreshCamera]);\n\n// useEffect(() => {\n// const subscription = AppState.addEventListener('change', nextAppState => {\n// if (nextAppState === 'active' && showCamera && hasPermission === false) {\n// checkPermissions();\n// }\n// });\n// return () => subscription.remove();\n// }, [showCamera, hasPermission]);\n\n// const onInitialized = useCallback(() => setIsInitialized(true), []);\n// const onCameraError = useCallback((error: any) => {\n// onError?.({ message: error.message || t('camera.errorOccurred') });\n// }, [onError, t]);\n\n// const captureSilentPhoto = useCallback(async () => {\n// if (!camera.current || !isInitialized || isProcessingRef.current || isCapturingRef.current) return;\n// if (silentCaptureResult?.isAnalyzing) return;\n\n// try {\n// isCapturingRef.current = true;\n// const photo = await camera.current.takePhoto({\n// enableShutterSound: false,\n// flash: 'off',\n// });\n// const result = await VisionCameraModule.processPhotoResult(photo);\n\n// onSilentCapture?.({\n// ...result,\n// path: result.path || photo.path,\n// });\n// } catch (error) {\n// // Silent background fail\n// } finally {\n// isCapturingRef.current = false;\n// }\n// }, [isInitialized, onSilentCapture, silentCaptureResult]);\n\n// useEffect(() => {\n// if (!showCamera || !isInitialized || isProcessing) return;\n// let isActive = true;\n// let intervalId: ReturnType<typeof setInterval>;\n\n// const warmupTimer = setTimeout(() => {\n// if (!isActive) return;\n// intervalId = setInterval(() => {\n// captureSilentPhoto();\n// }, 1500);\n// }, 1000);\n\n// return () => {\n// isActive = false;\n// clearTimeout(warmupTimer);\n// if (intervalId) clearInterval(intervalId);\n// };\n// }, [showCamera, isInitialized, isProcessing, captureSilentPhoto]);\n\n// if (hasPermission === null) return <View style={[styles.container, style]} />;\n\n// if (hasPermission === false) {\n// return (\n// <View style={[styles.container, style, { justifyContent: 'center', alignItems: 'center' }]}>\n// <Text style={styles.permissionMessage}>{t('camera.permissionRequired')}</Text>\n// <Button title=\"Refresh Camera\" onPress={() => setRefreshCamera(prev => !prev)} variant=\"primary\" />\n// </View>\n// );\n// }\n\n// if (!device || !showCamera) return <View style={[styles.container, style]} />;\n\n// return (\n// <View \n// style={[styles.container, style]}\n// onLayout={(e) => setLayout({ width: e.nativeEvent.layout.width, height: e.nativeEvent.layout.height })}\n// >\n// <Camera\n// ref={camera}\n// style={StyleSheet.absoluteFill}\n// device={device}\n// format={format} \n// resizeMode=\"cover\" \n// isActive={showCamera && !isProcessing}\n// photo={true}\n// video={false}\n// audio={false}\n// onInitialized={onInitialized}\n// onError={onCameraError}\n// />\n// {overlayComponent}\n// </View>\n// );\n// };\n\n// const styles = StyleSheet.create({\n// container: { flex: 1, backgroundColor: 'black' },\n// permissionMessage: { color: 'white', textAlign: 'center', margin: 20, fontSize: 16 },\n// });\n\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\nimport { View, StyleSheet, Text, AppState } from 'react-native';\nimport { Camera, useCameraDevice } from 'react-native-vision-camera'; \nimport VisionCameraModule from '../modules/camera/VisionCameraModule';\nimport { useI18n } from '../hooks/useI18n';\nimport { EnhancedCameraViewProps } from './OverLay/type';\nimport { Button } from './ui/Button';\n\nexport const EnhancedCameraView: React.FC<EnhancedCameraViewProps> = ({\n showCamera,\n cameraType: initialCameraType = 'front',\n style,\n onError,\n onSilentCapture,\n silentCaptureResult,\n isProcessing = false,\n overlayComponent,\n}) => {\n const { t } = useI18n();\n const camera = useRef<Camera>(null);\n\n const isCapturingRef = useRef(false);\n const isProcessingRef = useRef(isProcessing);\n\n const [cameraType] = useState<'front' | 'back'>(initialCameraType);\n const [hasPermission, setHasPermission] = useState<boolean | null>(null);\n const [isInitialized, setIsInitialized] = useState(false);\n const [refreshCamera, setRefreshCamera] = useState(false);\n\n // 🚨 THE FIX: Removed the strict physical device filtering and custom format.\n // This allows Android to select its own supported, stable hardware stream, preventing crashes.\n const device = useCameraDevice(cameraType);\n\n useEffect(() => {\n isProcessingRef.current = isProcessing;\n }, [isProcessing]);\n\n const checkPermissions = async () => {\n try {\n const hasAllPermissions = await VisionCameraModule.hasAllPermissions();\n if (!hasAllPermissions) {\n const granted = await VisionCameraModule.requestAllPermissions();\n if (!granted) {\n setHasPermission(false);\n onError?.({ message: t('camera.permissionRequired') });\n return;\n }\n }\n setHasPermission(true);\n } catch (error) {\n setHasPermission(false);\n onError?.({ message: t('camera.errorOccurred') });\n }\n };\n\n useEffect(() => {\n if (showCamera) checkPermissions();\n }, [showCamera, refreshCamera]);\n\n useEffect(() => {\n const subscription = AppState.addEventListener('change', nextAppState => {\n if (nextAppState === 'active' && showCamera && hasPermission === false) {\n checkPermissions();\n }\n });\n return () => subscription.remove();\n }, [showCamera, hasPermission]);\n\n const onInitialized = useCallback(() => setIsInitialized(true), []);\n const onCameraError = useCallback((error: any) => {\n onError?.({ message: error.message || t('camera.errorOccurred') });\n }, [onError, t]);\n\n const captureSilentPhoto = useCallback(async () => {\n if (!camera.current || !isInitialized || isProcessingRef.current || isCapturingRef.current) return;\n if (silentCaptureResult?.isAnalyzing) return;\n\n try {\n isCapturingRef.current = true;\n const photo = await camera.current.takePhoto({\n enableShutterSound: false,\n flash: 'off',\n });\n \n const result = await VisionCameraModule.processPhotoResult(photo);\n\n onSilentCapture?.({\n ...result,\n path: result.path || photo.path,\n });\n } catch (error) {\n // Silent background fail\n } finally {\n isCapturingRef.current = false;\n }\n }, [isInitialized, onSilentCapture, silentCaptureResult]);\n\n useEffect(() => {\n if (!showCamera || !isInitialized || isProcessing) return;\n \n let isActive = true;\n let intervalId: ReturnType<typeof setInterval>;\n\n const warmupTimer = setTimeout(() => {\n if (!isActive) return;\n intervalId = setInterval(() => {\n captureSilentPhoto();\n }, 1500);\n }, 1000);\n\n return () => {\n isActive = false;\n clearTimeout(warmupTimer);\n if (intervalId) clearInterval(intervalId);\n };\n }, [showCamera, isInitialized, isProcessing, captureSilentPhoto]);\n\n if (hasPermission === null) return <View style={[styles.container, style]} />;\n\n if (hasPermission === false) {\n return (\n <View style={[styles.container, style, { justifyContent: 'center', alignItems: 'center' }]}>\n <Text style={styles.permissionMessage}>{t('camera.permissionRequired')}</Text>\n <Button title=\"Refresh Camera\" onPress={() => setRefreshCamera(prev => !prev)} variant=\"primary\" />\n </View>\n );\n }\n\n if (!device || !showCamera) return <View style={[styles.container, style]} />;\n\n return (\n <View style={[styles.container, style]}>\n <Camera\n ref={camera}\n style={StyleSheet.absoluteFill}\n device={device}\n resizeMode=\"cover\" \n isActive={showCamera && !isProcessing}\n photo={true}\n video={false}\n audio={false}\n onInitialized={onInitialized}\n onError={onCameraError}\n />\n {overlayComponent}\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n container: { flex: 1, backgroundColor: 'black' },\n permissionMessage: { color: 'white', textAlign: 'center', margin: 20, fontSize: 16 },\n});"]}
|
|
1
|
+
{"version":3,"file":"EnhancedCameraView.js","sourceRoot":"","sources":["../../../src/components/EnhancedCameraView.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n View, StyleSheet, Text, AppState\n} from 'react-native';\nimport { Camera, useCameraDevice } from 'react-native-vision-camera';\nimport VisionCameraModule from '../modules/camera/VisionCameraModule';\nimport { useI18n } from '../hooks/useI18n';\nimport { EnhancedCameraViewProps } from './OverLay/type';\nimport { Button } from './ui/Button';\n\n\nexport const EnhancedCameraView: React.FC<EnhancedCameraViewProps> = ({\n showCamera,\n cameraType: initialCameraType = 'front',\n style,\n onError,\n onSilentCapture,\n silentCaptureResult,\n isProcessing = false,\n overlayComponent,\n}) => {\n const { t } = useI18n();\n const camera = useRef<Camera>(null);\n\n const isCapturingRef = useRef(false);\n const isProcessingRef = useRef(isProcessing);\n\n const [cameraType] = useState<'front' | 'back'>(initialCameraType);\n const [hasPermission, setHasPermission] = useState<boolean | null>(null);\n const [isInitialized, setIsInitialized] = useState(false);\n const [refreshCamera, setRefreshCamera] = useState(false);\n\n const device = useCameraDevice(cameraType);\n\n useEffect(() => { isProcessingRef.current = isProcessing; }, [isProcessing]);\n\n const checkPermissions = async () => {\n try {\n const hasAllPermissions = await VisionCameraModule.hasAllPermissions();\n if (!hasAllPermissions) {\n const granted = await VisionCameraModule.requestAllPermissions();\n if (!granted) {\n setHasPermission(false);\n onError?.({ message: t('camera.permissionRequired') });\n return;\n }\n }\n setHasPermission(true);\n } catch {\n setHasPermission(false);\n onError?.({ message: t('camera.errorOccurred') });\n }\n };\n\n useEffect(() => { if (showCamera) checkPermissions(); }, [showCamera, refreshCamera]);\n\n useEffect(() => {\n const sub = AppState.addEventListener('change', next => {\n if (next === 'active' && showCamera && hasPermission === false) checkPermissions();\n });\n return () => sub.remove();\n }, [showCamera, hasPermission]);\n\n const onInitialized = useCallback(() => setIsInitialized(true), []);\n const onCameraError = useCallback((error: any) => {\n onError?.({ message: error.message || t('camera.errorOccurred') });\n }, [onError, t]);\n\n const captureSilentPhoto = useCallback(async () => {\n if (!camera.current || !isInitialized || isProcessingRef.current || isCapturingRef.current) return;\n if (silentCaptureResult?.isAnalyzing) return;\n try {\n isCapturingRef.current = true;\n const photo = await camera.current.takePhoto({ enableShutterSound: false, flash: 'off' });\n const result = await VisionCameraModule.processPhotoResult(photo);\n onSilentCapture?.({ ...result, path: result.path || photo.path });\n } catch { /* silent */ } finally {\n isCapturingRef.current = false;\n }\n }, [isInitialized, onSilentCapture, silentCaptureResult]);\n\n useEffect(() => {\n if (!showCamera || !isInitialized || isProcessing) return;\n let active = true;\n let id: ReturnType<typeof setInterval>;\n const timer = setTimeout(() => {\n if (!active) return;\n id = setInterval(captureSilentPhoto, 1500);\n }, 1000);\n return () => { active = false; clearTimeout(timer); if (id) clearInterval(id); };\n }, [showCamera, isInitialized, isProcessing, captureSilentPhoto]);\n\n if (hasPermission === null) return <View style={[styles.container, style]} />;\n\n if (hasPermission === false) {\n return (\n <View style={[styles.container, style, { justifyContent: 'center', alignItems: 'center' }]}>\n <Text style={styles.permissionMessage}>{t('camera.permissionRequired')}</Text>\n <Button title=\"Refresh Camera\" onPress={() => setRefreshCamera(p => !p)} variant=\"primary\" />\n </View>\n );\n }\n\n if (!device || !showCamera) return <View style={[styles.container, style]} />;\n\n return (\n <View style={[styles.container, style]}>\n <Camera\n ref={camera}\n style={StyleSheet.absoluteFill}\n device={device}\n resizeMode=\"cover\"\n isActive={showCamera && !isProcessing}\n photo={true}\n video={false}\n audio={false}\n onInitialized={onInitialized}\n onError={onCameraError}\n />\n\n {overlayComponent}\n </View>\n );\n};\n\nconst styles = StyleSheet.create({\n container: { flex: 1, backgroundColor: 'black' },\n permissionMessage: { color: 'white', textAlign: 'center', margin: 20, fontSize: 16 },\n});"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CountrySelectionTemplate.d.ts","sourceRoot":"","sources":["../../../../src/components/KYCElements/CountrySelectionTemplate.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAE5D,OAAO,EAAE,iBAAiB,EAAyC,OAAO,EAAgB,MAAM,uBAAuB,CAAC;AAMxH,UAAU,6BAA6B;IACrC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACrF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;
|
|
1
|
+
{"version":3,"file":"CountrySelectionTemplate.d.ts","sourceRoot":"","sources":["../../../../src/components/KYCElements/CountrySelectionTemplate.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAE5D,OAAO,EAAE,iBAAiB,EAAyC,OAAO,EAAgB,MAAM,uBAAuB,CAAC;AAMxH,UAAU,6BAA6B;IACrC,SAAS,EAAE,iBAAiB,CAAC;IAC7B,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,aAAa,EAAE,CAAC,KAAK,EAAE,OAAO,GAAG;QAAE,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACrF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAcD,eAAO,MAAM,wBAAwB,EAAE,KAAK,CAAC,EAAE,CAAC,6BAA6B,CA0Y5E,CAAC"}
|
|
@@ -4,6 +4,8 @@ import { countryMapping } from '../../config/region_mapping';
|
|
|
4
4
|
import { useTemplateKYCFlowContext } from '../../hooks/useTemplateKYCFlow';
|
|
5
5
|
import { Button } from '../ui/Button';
|
|
6
6
|
import { countryData } from '../../config/countriesData';
|
|
7
|
+
// Standard ISO 3166-2:CA codes for Canadian provinces and territories
|
|
8
|
+
const CANADIAN_PROVINCES = ['AB', 'BC', 'MB', 'NB', 'NL', 'NT', 'NS', 'NU', 'ON', 'PE', 'QC', 'SK', 'YT'];
|
|
7
9
|
export const CountrySelectionTemplate = ({ component, value, onValueChange, error, language = 'en', }) => {
|
|
8
10
|
const config = component.config;
|
|
9
11
|
const { actions, state } = useTemplateKYCFlowContext();
|
|
@@ -33,8 +35,12 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
|
|
|
33
35
|
setCurrentStep('region');
|
|
34
36
|
}
|
|
35
37
|
else {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
// Check config regions OR enforce Canadian provinces for non-passports
|
|
39
|
+
let regionsCheck = idCardConfig?.regionsByCountry?.[value.code]?.[value.documentType] || [];
|
|
40
|
+
if (regionsCheck.length === 0 && value.code === 'CA' && value.documentType !== 'passport') {
|
|
41
|
+
regionsCheck = CANADIAN_PROVINCES;
|
|
42
|
+
}
|
|
43
|
+
if (Array.isArray(regionsCheck) && regionsCheck.length > 0) {
|
|
38
44
|
setCurrentStep('region');
|
|
39
45
|
}
|
|
40
46
|
else {
|
|
@@ -67,12 +73,16 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
|
|
|
67
73
|
return idCardConfig.documentTypesByCountry[selectedCountryCode] || [];
|
|
68
74
|
}, [selectedCountryCode, idCardConfig?.documentTypesByCountry]);
|
|
69
75
|
const availableRegions = useMemo(() => {
|
|
70
|
-
if (!selectedCountryCode || !selectedDocumentType
|
|
71
|
-
return [];
|
|
72
|
-
const regions = idCardConfig.regionsByCountry[selectedCountryCode];
|
|
73
|
-
if (!regions)
|
|
76
|
+
if (!selectedCountryCode || !selectedDocumentType)
|
|
74
77
|
return [];
|
|
75
|
-
|
|
78
|
+
let regions = [];
|
|
79
|
+
if (idCardConfig?.regionsByCountry?.[selectedCountryCode]?.[selectedDocumentType]) {
|
|
80
|
+
regions = idCardConfig.regionsByCountry[selectedCountryCode][selectedDocumentType];
|
|
81
|
+
}
|
|
82
|
+
if (regions.length === 0 && selectedCountryCode === 'CA' && selectedDocumentType !== 'passport') {
|
|
83
|
+
regions = CANADIAN_PROVINCES;
|
|
84
|
+
}
|
|
85
|
+
return Array.isArray(regions) ? regions : [];
|
|
76
86
|
}, [selectedCountryCode, selectedDocumentType, idCardConfig?.regionsByCountry]);
|
|
77
87
|
const needsRegion = useMemo(() => {
|
|
78
88
|
return availableRegions.length > 0;
|
|
@@ -80,18 +90,15 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
|
|
|
80
90
|
const getLocalizedText = (text) => {
|
|
81
91
|
return text[state.currentLanguage] || text.en || '';
|
|
82
92
|
};
|
|
83
|
-
// 1. Only highlights the country
|
|
84
93
|
const handleCountrySelect = (countryCode) => {
|
|
85
94
|
setSelectedCountryCode(countryCode);
|
|
86
95
|
setSelectedDocumentType(null);
|
|
87
96
|
setSelectedRegion(null);
|
|
88
97
|
};
|
|
89
|
-
// 2. Only highlights the document type
|
|
90
98
|
const handleDocumentTypeSelect = (docType) => {
|
|
91
99
|
setSelectedDocumentType(docType);
|
|
92
100
|
setSelectedRegion(null);
|
|
93
101
|
};
|
|
94
|
-
// 3. Only highlights the region
|
|
95
102
|
const handleRegionSelect = (region) => {
|
|
96
103
|
setSelectedRegion(region);
|
|
97
104
|
};
|
|
@@ -252,7 +259,7 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
|
|
|
252
259
|
case 'documentType':
|
|
253
260
|
return state.currentLanguage === "en" ? "Select Document Type" : "Sélectionnez le type de document";
|
|
254
261
|
case 'region':
|
|
255
|
-
return state.currentLanguage === "en" ? "Select
|
|
262
|
+
return state.currentLanguage === "en" ? "Select Province/State" : "Sélectionnez la province/l'état";
|
|
256
263
|
default:
|
|
257
264
|
return '';
|
|
258
265
|
}
|
|
@@ -267,8 +274,8 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
|
|
|
267
274
|
: "Choisissez le type de document que vous souhaitez utiliser";
|
|
268
275
|
case 'region':
|
|
269
276
|
return state.currentLanguage === "en"
|
|
270
|
-
? "Select
|
|
271
|
-
: "Sélectionnez
|
|
277
|
+
? "Select the issuing province or territory"
|
|
278
|
+
: "Sélectionnez la province ou le territoire de délivrance";
|
|
272
279
|
default:
|
|
273
280
|
return '';
|
|
274
281
|
}
|
|
@@ -311,7 +318,6 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
|
|
|
311
318
|
|
|
312
319
|
<View style={styles.buttonContainer}>
|
|
313
320
|
<Button title={state.currentLanguage === "en" ? "Back" : "Retour"} onPress={handleBack} variant={currentStep === 'country' ? "secondary" : "outline"} size="large" style={{ flex: 1, marginRight: 8 }}/>
|
|
314
|
-
|
|
315
321
|
<Button title={state.currentLanguage === "en" ? "Next" : "Suivant"} onPress={handleNext} variant="primary" size="large" style={{ flex: 1 }} disabled={!canGoNext()}/>
|
|
316
322
|
</View>
|
|
317
323
|
|
|
@@ -320,119 +326,25 @@ export const CountrySelectionTemplate = ({ component, value, onValueChange, erro
|
|
|
320
326
|
</View>);
|
|
321
327
|
};
|
|
322
328
|
const styles = StyleSheet.create({
|
|
323
|
-
root: {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
},
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
},
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
},
|
|
344
|
-
progressText: {
|
|
345
|
-
fontSize: 14,
|
|
346
|
-
color: '#666',
|
|
347
|
-
fontWeight: '500',
|
|
348
|
-
},
|
|
349
|
-
title: {
|
|
350
|
-
fontSize: 24,
|
|
351
|
-
fontWeight: 'bold',
|
|
352
|
-
color: '#333',
|
|
353
|
-
marginBottom: 8,
|
|
354
|
-
textAlign: 'center',
|
|
355
|
-
},
|
|
356
|
-
description: {
|
|
357
|
-
fontSize: 16,
|
|
358
|
-
color: '#666',
|
|
359
|
-
textAlign: 'center',
|
|
360
|
-
marginBottom: 24,
|
|
361
|
-
lineHeight: 22,
|
|
362
|
-
},
|
|
363
|
-
listContainer: {
|
|
364
|
-
maxHeight: 400,
|
|
365
|
-
marginBottom: 24,
|
|
366
|
-
},
|
|
367
|
-
option: {
|
|
368
|
-
flexDirection: 'row',
|
|
369
|
-
alignItems: 'center',
|
|
370
|
-
padding: 16,
|
|
371
|
-
backgroundColor: '#F8F9FA',
|
|
372
|
-
borderRadius: 12,
|
|
373
|
-
marginBottom: 12,
|
|
374
|
-
borderWidth: 2,
|
|
375
|
-
borderColor: '#E9ECEF',
|
|
376
|
-
minHeight: 64,
|
|
377
|
-
},
|
|
378
|
-
selectedOption: {
|
|
379
|
-
borderColor: '#2DBD60',
|
|
380
|
-
backgroundColor: '#F0F9F0',
|
|
381
|
-
},
|
|
382
|
-
flag: {
|
|
383
|
-
fontSize: 32,
|
|
384
|
-
marginRight: 16,
|
|
385
|
-
},
|
|
386
|
-
optionContent: {
|
|
387
|
-
flex: 1,
|
|
388
|
-
},
|
|
389
|
-
optionName: {
|
|
390
|
-
fontSize: 18,
|
|
391
|
-
fontWeight: '600',
|
|
392
|
-
color: '#333',
|
|
393
|
-
},
|
|
394
|
-
selectedOptionName: {
|
|
395
|
-
color: '#2DBD60',
|
|
396
|
-
},
|
|
397
|
-
optionCode: {
|
|
398
|
-
fontSize: 14,
|
|
399
|
-
color: '#666',
|
|
400
|
-
marginTop: 4,
|
|
401
|
-
fontWeight: '500',
|
|
402
|
-
},
|
|
403
|
-
checkmark: {
|
|
404
|
-
width: 24,
|
|
405
|
-
height: 24,
|
|
406
|
-
borderRadius: 12,
|
|
407
|
-
justifyContent: 'center',
|
|
408
|
-
alignItems: 'center',
|
|
409
|
-
},
|
|
410
|
-
checkmarkText: {
|
|
411
|
-
color: 'white',
|
|
412
|
-
fontSize: 16,
|
|
413
|
-
fontWeight: 'bold',
|
|
414
|
-
},
|
|
415
|
-
infoBox: {
|
|
416
|
-
backgroundColor: '#F9FAFB',
|
|
417
|
-
padding: 12,
|
|
418
|
-
borderRadius: 12,
|
|
419
|
-
marginBottom: 16,
|
|
420
|
-
},
|
|
421
|
-
infoText: {
|
|
422
|
-
fontSize: 14,
|
|
423
|
-
color: '#666',
|
|
424
|
-
lineHeight: 20,
|
|
425
|
-
},
|
|
426
|
-
buttonContainer: {
|
|
427
|
-
flexDirection: 'row',
|
|
428
|
-
marginTop: 24,
|
|
429
|
-
gap: 12,
|
|
430
|
-
},
|
|
431
|
-
errorText: {
|
|
432
|
-
color: '#dc2626',
|
|
433
|
-
fontSize: 14,
|
|
434
|
-
marginTop: 8,
|
|
435
|
-
textAlign: 'center',
|
|
436
|
-
},
|
|
329
|
+
root: { flex: 1, maxWidth: 760, width: '100%' },
|
|
330
|
+
container: { backgroundColor: 'white', margin: 10, borderRadius: 10, paddingVertical: 16, paddingHorizontal: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.35, shadowRadius: 4.84, elevation: 10 },
|
|
331
|
+
progressContainer: { marginBottom: 16, alignItems: 'center' },
|
|
332
|
+
progressText: { fontSize: 14, color: '#666', fontWeight: '500' },
|
|
333
|
+
title: { fontSize: 24, fontWeight: 'bold', color: '#333', marginBottom: 8, textAlign: 'center' },
|
|
334
|
+
description: { fontSize: 16, color: '#666', textAlign: 'center', marginBottom: 24, lineHeight: 22 },
|
|
335
|
+
listContainer: { maxHeight: 400, marginBottom: 24 },
|
|
336
|
+
option: { flexDirection: 'row', alignItems: 'center', padding: 16, backgroundColor: '#F8F9FA', borderRadius: 12, marginBottom: 12, borderWidth: 2, borderColor: '#E9ECEF', minHeight: 64 },
|
|
337
|
+
selectedOption: { borderColor: '#2DBD60', backgroundColor: '#F0F9F0' },
|
|
338
|
+
flag: { fontSize: 32, marginRight: 16 },
|
|
339
|
+
optionContent: { flex: 1 },
|
|
340
|
+
optionName: { fontSize: 18, fontWeight: '600', color: '#333' },
|
|
341
|
+
selectedOptionName: { color: '#2DBD60' },
|
|
342
|
+
optionCode: { fontSize: 14, color: '#666', marginTop: 4, fontWeight: '500' },
|
|
343
|
+
checkmark: { width: 24, height: 24, borderRadius: 12, justifyContent: 'center', alignItems: 'center' },
|
|
344
|
+
checkmarkText: { color: 'white', fontSize: 16, fontWeight: 'bold' },
|
|
345
|
+
infoBox: { backgroundColor: '#F9FAFB', padding: 12, borderRadius: 12, marginBottom: 16 },
|
|
346
|
+
infoText: { fontSize: 14, color: '#666', lineHeight: 20 },
|
|
347
|
+
buttonContainer: { flexDirection: 'row', marginTop: 24, gap: 12 },
|
|
348
|
+
errorText: { color: '#dc2626', fontSize: 14, marginTop: 8, textAlign: 'center' },
|
|
437
349
|
});
|
|
438
350
|
//# sourceMappingURL=CountrySelectionTemplate.js.map
|