omnipay-reactnative-sdk 1.2.2-beta.0 → 1.2.2-beta.2

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.
Files changed (69) hide show
  1. package/README.md +45 -136
  2. package/android/build.gradle +13 -0
  3. package/android/src/main/AndroidManifest.xml +5 -0
  4. package/android/src/main/java/com/omniretail/omnipay/LivenessCameraViewManager.java +116 -0
  5. package/android/src/main/java/com/omniretail/omnipay/LivenessDetectionModule.java +588 -0
  6. package/android/src/main/java/com/omniretail/omnipay/OmnipayActivityPackage.java +4 -1
  7. package/ios/LivenessCameraView.h +22 -0
  8. package/ios/LivenessCameraView.m +135 -0
  9. package/ios/LivenessCameraViewManager.h +12 -0
  10. package/ios/LivenessCameraViewManager.m +24 -0
  11. package/ios/LivenessDetectionModule.h +46 -0
  12. package/ios/LivenessDetectionModule.m +603 -0
  13. package/lib/commonjs/components/OmnipayProvider.js +6 -56
  14. package/lib/commonjs/components/OmnipayProvider.js.map +1 -1
  15. package/lib/commonjs/components/biometrics/FaceVerification.js +439 -0
  16. package/lib/commonjs/components/biometrics/FaceVerification.js.map +1 -0
  17. package/lib/commonjs/components/biometrics/LivenessCameraView.js +43 -0
  18. package/lib/commonjs/components/biometrics/LivenessCameraView.js.map +1 -0
  19. package/lib/commonjs/components/biometrics/LivenessDetection.js +252 -0
  20. package/lib/commonjs/components/biometrics/LivenessDetection.js.map +1 -0
  21. package/lib/commonjs/index.js +28 -0
  22. package/lib/commonjs/index.js.map +1 -1
  23. package/lib/module/components/OmnipayProvider.js +6 -56
  24. package/lib/module/components/OmnipayProvider.js.map +1 -1
  25. package/lib/module/components/biometrics/FaceVerification.js +429 -0
  26. package/lib/module/components/biometrics/FaceVerification.js.map +1 -0
  27. package/lib/module/components/biometrics/LivenessCameraView.js +38 -0
  28. package/lib/module/components/biometrics/LivenessCameraView.js.map +1 -0
  29. package/lib/module/components/biometrics/LivenessDetection.js +244 -0
  30. package/lib/module/components/biometrics/LivenessDetection.js.map +1 -0
  31. package/lib/module/index.js +5 -0
  32. package/lib/module/index.js.map +1 -1
  33. package/lib/typescript/components/OmnipayProvider.d.ts.map +1 -1
  34. package/lib/typescript/components/biometrics/FaceVerification.d.ts +12 -0
  35. package/lib/typescript/components/biometrics/FaceVerification.d.ts.map +1 -0
  36. package/lib/typescript/components/biometrics/LivenessCameraView.d.ts +22 -0
  37. package/lib/typescript/components/biometrics/LivenessCameraView.d.ts.map +1 -0
  38. package/lib/typescript/components/biometrics/LivenessDetection.d.ts +73 -0
  39. package/lib/typescript/components/biometrics/LivenessDetection.d.ts.map +1 -0
  40. package/lib/typescript/index.d.ts +3 -0
  41. package/lib/typescript/index.d.ts.map +1 -1
  42. package/omnipay-reactnative-sdk.podspec +47 -0
  43. package/package.json +6 -11
  44. package/src/components/OmnipayProvider.tsx +8 -65
  45. package/src/components/biometrics/FaceVerification.tsx +484 -0
  46. package/src/components/biometrics/LivenessCameraView.tsx +61 -0
  47. package/src/components/biometrics/LivenessDetection.ts +305 -0
  48. package/src/index.tsx +18 -0
  49. package/lib/commonjs/components/FaceVerification.js +0 -755
  50. package/lib/commonjs/components/FaceVerification.js.map +0 -1
  51. package/lib/commonjs/types/faceVerification.js +0 -2
  52. package/lib/commonjs/types/faceVerification.js.map +0 -1
  53. package/lib/commonjs/types/index.js +0 -17
  54. package/lib/commonjs/types/index.js.map +0 -1
  55. package/lib/module/components/FaceVerification.js +0 -746
  56. package/lib/module/components/FaceVerification.js.map +0 -1
  57. package/lib/module/types/faceVerification.js +0 -2
  58. package/lib/module/types/faceVerification.js.map +0 -1
  59. package/lib/module/types/index.js +0 -2
  60. package/lib/module/types/index.js.map +0 -1
  61. package/lib/typescript/components/FaceVerification.d.ts +0 -10
  62. package/lib/typescript/components/FaceVerification.d.ts.map +0 -1
  63. package/lib/typescript/types/faceVerification.d.ts +0 -18
  64. package/lib/typescript/types/faceVerification.d.ts.map +0 -1
  65. package/lib/typescript/types/index.d.ts +0 -2
  66. package/lib/typescript/types/index.d.ts.map +0 -1
  67. package/src/components/FaceVerification.tsx +0 -884
  68. package/src/types/faceVerification.ts +0 -27
  69. package/src/types/index.ts +0 -1
@@ -1,755 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- var _react = _interopRequireWildcard(require("react"));
8
- var _reactNative = require("react-native");
9
- var _reactNativeVisionCamera = require("react-native-vision-camera");
10
- var _reactNativeVisionCameraFaceDetector = require("react-native-vision-camera-face-detector");
11
- var _reactNativeSvg = _interopRequireWildcard(require("react-native-svg"));
12
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
13
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
14
- const AnimatedCircle = _reactNative.Animated.createAnimatedComponent(_reactNativeSvg.Circle);
15
- const FaceVerification = _ref => {
16
- let {
17
- onSuccess,
18
- onFailure,
19
- onCancel,
20
- onImageCaptured
21
- } = _ref;
22
- const device = (0, _reactNativeVisionCamera.useCameraDevice)('front');
23
- const faceDetectionOptions = (0, _react.useRef)({
24
- landmarkMode: 'all',
25
- classificationMode: 'all'
26
- }).current;
27
- const photoFormat = (0, _reactNativeVisionCamera.useCameraFormat)(device, [{
28
- photoResolution: {
29
- width: 1280,
30
- height: 720
31
- }
32
- }]);
33
- const {
34
- hasPermission,
35
- requestPermission
36
- } = (0, _reactNativeVisionCamera.useCameraPermission)();
37
- const spinValue = (0, _react.useRef)(new _reactNative.Animated.Value(0)).current;
38
- const progressValue = (0, _react.useRef)(new _reactNative.Animated.Value(955)).current; // 955 = circle circumference for r=152
39
-
40
- const [isCameraActive, setIsCameraActive] = (0, _react.useState)(false);
41
- const [isLoading, setIsLoading] = (0, _react.useState)(false);
42
- const [permissionDenied, setPermissionDenied] = (0, _react.useState)(false);
43
- const [isInitializingCamera, setIsInitializingCamera] = (0, _react.useState)(true);
44
- const [currentStep, setCurrentStep] = (0, _react.useState)('position_face');
45
- const [isCapturing, setIsCapturing] = (0, _react.useState)(false);
46
- const [capturedImage, setCapturedImage] = (0, _react.useState)(null);
47
- const frameCountRef = (0, _react.useRef)(0);
48
- const finalPositionFrameCountRef = (0, _react.useRef)(0);
49
- const faceHistoryRef = (0, _react.useRef)([]);
50
- const cameraRef = (0, _react.useRef)(null);
51
-
52
- // RAF optimization: buffer latest face data and process on animation frames
53
- const latestFaceDataRef = (0, _react.useRef)(null);
54
- const rafIdRef = (0, _react.useRef)(null);
55
- const isProcessingRef = (0, _react.useRef)(false);
56
-
57
- // Handle camera device initialization and auto-start
58
- (0, _react.useEffect)(() => {
59
- if (device !== undefined) {
60
- setIsInitializingCamera(false);
61
-
62
- // If permissions are already granted, start camera immediately
63
- if (hasPermission && !isCameraActive && !permissionDenied && !capturedImage) {
64
- setIsCameraActive(true);
65
- progressValue.setValue(955);
66
- }
67
- }
68
- }, [device, hasPermission, isCameraActive, permissionDenied, capturedImage, progressValue]);
69
-
70
- // Start loading animation during camera initialization
71
- (0, _react.useEffect)(() => {
72
- if (isInitializingCamera) {
73
- setIsLoading(true);
74
- } else {
75
- setIsLoading(false);
76
- }
77
- }, [isInitializingCamera]);
78
- (0, _react.useEffect)(() => {
79
- const spin = _reactNative.Animated.loop(_reactNative.Animated.timing(spinValue, {
80
- toValue: 1,
81
- duration: 1000,
82
- useNativeDriver: true
83
- }));
84
- if (isLoading) {
85
- spin.start();
86
- } else {
87
- spin.stop();
88
- spinValue.setValue(0);
89
- }
90
- return () => spin.stop();
91
- }, [isLoading, spinValue]);
92
- (0, _react.useEffect)(() => {
93
- const progressPercentage = calculateProgress();
94
- const strokeDasharray = 955;
95
- const targetOffset = strokeDasharray - progressPercentage / 100 * strokeDasharray;
96
- if (isCameraActive && progressPercentage >= 0) {
97
- _reactNative.Animated.timing(progressValue, {
98
- toValue: targetOffset,
99
- duration: 800,
100
- useNativeDriver: false
101
- }).start();
102
- }
103
- }, [currentStep, progressValue, isCameraActive]);
104
-
105
- // RAF-based face processing to throttle heavy computations
106
- const processFaceData = () => {
107
- if (!latestFaceDataRef.current || isProcessingRef.current) {
108
- rafIdRef.current = null;
109
- return;
110
- }
111
- isProcessingRef.current = true;
112
- const {
113
- faces
114
- } = latestFaceDataRef.current;
115
-
116
- // Clear the buffer since we're processing this data
117
- latestFaceDataRef.current = null;
118
- try {
119
- handleFaceDetectionLogic(faces);
120
- } finally {
121
- isProcessingRef.current = false;
122
- rafIdRef.current = null;
123
- }
124
- };
125
-
126
- // Cleanup RAF on unmount
127
- (0, _react.useEffect)(() => {
128
- return () => {
129
- if (rafIdRef.current) {
130
- cancelAnimationFrame(rafIdRef.current);
131
- }
132
- };
133
- }, []);
134
- const getInstructionText = () => {
135
- switch (currentStep) {
136
- case 'position_face':
137
- return 'Position your face in the frame';
138
- case 'blink':
139
- return 'Please blink your eyes';
140
- case 'smile':
141
- return 'Now smile';
142
- case 'final_position':
143
- return 'Look straight at the camera and hold still';
144
- case 'complete':
145
- return '';
146
- default:
147
- return 'Position your face in the frame';
148
- }
149
- };
150
- const calculateProgress = () => {
151
- switch (currentStep) {
152
- case 'position_face':
153
- return 10;
154
- case 'blink':
155
- return 30;
156
- case 'smile':
157
- return 60;
158
- case 'final_position':
159
- return 80;
160
- case 'complete':
161
- return 100;
162
- default:
163
- return 0;
164
- }
165
- };
166
- const detectBlink = () => {
167
- if (frameCountRef.current < 20 || faceHistoryRef.current.length < 4) return false;
168
- const threshold = {
169
- eyeOpen: 0.5,
170
- eyeClosed: 0.3
171
- };
172
- const recentFrames = faceHistoryRef.current.slice(-4);
173
- for (let i = 0; i < recentFrames.length - 1; i++) {
174
- const frame1 = recentFrames[i];
175
- const frame2 = recentFrames[i + 1];
176
- if (!frame1 || !frame2) continue;
177
- const eyesWereOpen = frame1.leftEyeOpenProbability > threshold.eyeOpen && frame1.rightEyeOpenProbability > threshold.eyeOpen;
178
- const eyesAreClosed = frame2.leftEyeOpenProbability < threshold.eyeClosed && frame2.rightEyeOpenProbability < threshold.eyeClosed;
179
- if (eyesWereOpen && eyesAreClosed) {
180
- return true;
181
- }
182
- }
183
- return false;
184
- };
185
- const detectSmile = face => {
186
- if (frameCountRef.current < 20 || faceHistoryRef.current.length < 3) return false;
187
- const threshold = 0.7;
188
- const currentSmiling = face.smilingProbability > threshold;
189
- const recentFrames = faceHistoryRef.current.slice(-3);
190
- const hadNotSmilingFrames = recentFrames.some(frame => frame.smilingProbability < 0.4);
191
- return currentSmiling && hadNotSmilingFrames;
192
- };
193
- const isInFinalPosition = face => {
194
- const isLookingStraight = Math.abs(face.yawAngle) < 15;
195
- const eyesOpen = face.leftEyeOpenProbability > 0.5 && face.rightEyeOpenProbability > 0.5;
196
- const isNotSmiling = face.smilingProbability < 0.1;
197
- return isLookingStraight && eyesOpen && isNotSmiling;
198
- };
199
-
200
- // Fast callback that just buffers data - called by camera at high frequency
201
- function handleFacesDetection(faces, frame) {
202
- // Store the latest face data
203
- latestFaceDataRef.current = {
204
- faces,
205
- frame
206
- };
207
-
208
- // Schedule processing on next animation frame if not already scheduled
209
- if (!rafIdRef.current) {
210
- rafIdRef.current = requestAnimationFrame(processFaceData);
211
- }
212
- }
213
-
214
- // Heavy processing logic - called at animation frame rate (60fps max)
215
- function handleFaceDetectionLogic(faces) {
216
- if (faces.length === 0) {
217
- if (currentStep !== 'position_face' && currentStep !== 'complete') {
218
- setCurrentStep('position_face');
219
- frameCountRef.current = 0;
220
- faceHistoryRef.current = [];
221
- finalPositionFrameCountRef.current = 0;
222
- }
223
- return;
224
- }
225
- const face = faces[0];
226
- if (!face) return;
227
- frameCountRef.current++;
228
- faceHistoryRef.current = [...faceHistoryRef.current.slice(-7), face];
229
- switch (currentStep) {
230
- case 'position_face':
231
- if (frameCountRef.current > 10) {
232
- setCurrentStep('blink');
233
- }
234
- break;
235
- case 'blink':
236
- if (detectBlink()) {
237
- setCurrentStep('smile');
238
- }
239
- break;
240
- case 'smile':
241
- if (detectSmile(face)) {
242
- setCurrentStep('final_position');
243
- }
244
- break;
245
- case 'final_position':
246
- if (isInFinalPosition(face)) {
247
- finalPositionFrameCountRef.current++;
248
- // Require 5 consecutive frames for stability before capturing
249
- if (finalPositionFrameCountRef.current >= 5) {
250
- setCurrentStep('complete');
251
- captureCurrentFrame();
252
- }
253
- } else {
254
- finalPositionFrameCountRef.current = 0;
255
- }
256
- break;
257
- default:
258
- break;
259
- }
260
- }
261
- const captureCurrentFrame = async () => {
262
- if (isCapturing || !cameraRef.current) return;
263
- try {
264
- setIsCapturing(true);
265
- const photo = await cameraRef.current.takePhoto({
266
- enableShutterSound: false
267
- });
268
- const response = await fetch(`file://${photo.path}`);
269
- const blob = await response.blob();
270
- const reader = new FileReader();
271
- reader.onloadend = () => {
272
- const base64String = reader.result;
273
- setCapturedImage(base64String);
274
- setIsCameraActive(false);
275
- };
276
- reader.readAsDataURL(blob);
277
- } catch (error) {
278
- onFailure === null || onFailure === void 0 ? void 0 : onFailure();
279
- } finally {
280
- setIsCapturing(false);
281
- }
282
- };
283
- const handleContinue = () => {
284
- if (capturedImage) {
285
- const base64String = capturedImage.replace(/^data:image\/[a-z]+;base64,/, '');
286
-
287
- // Call onImageCaptured immediately for UI feedback
288
- onImageCaptured === null || onImageCaptured === void 0 ? void 0 : onImageCaptured(base64String);
289
-
290
- // Still call onSuccess for backward compatibility
291
- onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(base64String);
292
- }
293
- };
294
- const handleRetake = () => {
295
- setCurrentStep('position_face');
296
- faceHistoryRef.current = [];
297
- frameCountRef.current = 0;
298
- setCapturedImage(null);
299
- finalPositionFrameCountRef.current = 0;
300
- progressValue.setValue(955);
301
- setIsCameraActive(true);
302
- setIsLoading(true);
303
- setTimeout(() => {
304
- setIsLoading(false);
305
- }, 1000);
306
- };
307
- const startCamera = async () => {
308
- setIsLoading(true);
309
- setPermissionDenied(false);
310
- try {
311
- const permission = await requestPermission();
312
- if (permission === true) {
313
- setIsCameraActive(true);
314
- progressValue.setValue(955);
315
- setTimeout(() => {
316
- setIsLoading(false);
317
- }, 1000);
318
- } else {
319
- setPermissionDenied(true);
320
- setIsLoading(false);
321
- }
322
- } catch (error) {
323
- setPermissionDenied(true);
324
- setIsLoading(false);
325
- }
326
- };
327
- const openSettings = () => {
328
- if (_reactNative.Platform.OS === 'ios') {
329
- _reactNative.Linking.openURL('app-settings:');
330
- } else {
331
- _reactNative.Linking.openSettings();
332
- }
333
- };
334
- if (permissionDenied) {
335
- return /*#__PURE__*/_react.default.createElement(_reactNative.View, {
336
- style: [styles.container]
337
- }, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
338
- style: styles.centeredContainer
339
- }, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
340
- style: styles.permissionDeniedContainer
341
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
342
- style: styles.permissionDeniedTitle
343
- }, "Camera Access Required"), /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
344
- style: styles.permissionDeniedText
345
- }, "This app needs camera access to verify your identity. Please allow camera permission in your device settings."), /*#__PURE__*/_react.default.createElement(_reactNative.View, {
346
- style: styles.permissionActions
347
- }, /*#__PURE__*/_react.default.createElement(_reactNative.TouchableOpacity, {
348
- style: styles.settingsButton,
349
- onPress: openSettings
350
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
351
- style: styles.settingsButtonText
352
- }, "Open Settings")), /*#__PURE__*/_react.default.createElement(_reactNative.TouchableOpacity, {
353
- style: styles.retryButton,
354
- onPress: () => setPermissionDenied(false)
355
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
356
- style: styles.retryButtonText
357
- }, "Try Again"))))));
358
- }
359
- if (isInitializingCamera || device === undefined) {
360
- const spin = spinValue.interpolate({
361
- inputRange: [0, 1],
362
- outputRange: ['0deg', '360deg']
363
- });
364
- return /*#__PURE__*/_react.default.createElement(_reactNative.View, {
365
- style: [styles.container]
366
- }, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
367
- style: styles.centeredContainer
368
- }, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
369
- style: styles.loadingContainer
370
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Animated.View, {
371
- style: [styles.loadingSpinner, {
372
- transform: [{
373
- rotate: spin
374
- }]
375
- }]
376
- }), /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
377
- style: styles.loadingText
378
- }, isInitializingCamera ? 'Initializing camera...' : 'No camera device available'))));
379
- }
380
- const strokeDasharray = 955;
381
- const spin = spinValue.interpolate({
382
- inputRange: [0, 1],
383
- outputRange: ['0deg', '360deg']
384
- });
385
- return /*#__PURE__*/_react.default.createElement(_reactNative.View, {
386
- style: [styles.container]
387
- }, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
388
- style: styles.centeredContainer
389
- }, isLoading ? /*#__PURE__*/_react.default.createElement(_reactNative.View, {
390
- style: styles.loadingContainer
391
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Animated.View, {
392
- style: [styles.loadingSpinner, {
393
- transform: [{
394
- rotate: spin
395
- }]
396
- }]
397
- })) : /*#__PURE__*/_react.default.createElement(_reactNative.View, {
398
- style: styles.contentContainer
399
- }, capturedImage ? /*#__PURE__*/_react.default.createElement(_reactNative.View, {
400
- style: styles.capturedImageContainer
401
- }, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
402
- style: styles.capturedImageWrapper
403
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Image, {
404
- source: {
405
- uri: capturedImage
406
- },
407
- style: styles.capturedImage,
408
- resizeMode: "cover"
409
- })), /*#__PURE__*/_react.default.createElement(_reactNative.View, {
410
- style: styles.capturedImageActions
411
- }, /*#__PURE__*/_react.default.createElement(_reactNative.TouchableOpacity, {
412
- style: styles.continueButton,
413
- onPress: handleContinue
414
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
415
- style: styles.continueButtonText
416
- }, "Continue")), /*#__PURE__*/_react.default.createElement(_reactNative.TouchableOpacity, {
417
- style: styles.retakeButton,
418
- onPress: handleRetake
419
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
420
- style: styles.retakeButtonText
421
- }, "Retake")))) : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
422
- style: styles.captureSection
423
- }, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
424
- style: styles.captureBackground
425
- }, isCameraActive ? /*#__PURE__*/_react.default.createElement(_reactNativeVisionCameraFaceDetector.Camera, {
426
- ref: cameraRef,
427
- device: device,
428
- isActive: true,
429
- style: styles.camera,
430
- faceDetectionCallback: handleFacesDetection,
431
- faceDetectionOptions: faceDetectionOptions,
432
- photo: true,
433
- format: photoFormat
434
- }) : /*#__PURE__*/_react.default.createElement(_reactNative.View, {
435
- style: styles.avatarPlaceholder
436
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
437
- style: styles.avatarText
438
- }, "\uD83D\uDC64"))), isCameraActive && /*#__PURE__*/_react.default.createElement(_reactNative.View, {
439
- style: styles.progressRingContainer
440
- }, /*#__PURE__*/_react.default.createElement(_reactNativeSvg.default, {
441
- width: 320,
442
- height: 320,
443
- viewBox: "0 0 320 320",
444
- style: styles.progressRing
445
- }, /*#__PURE__*/_react.default.createElement(_reactNativeSvg.Circle, {
446
- cx: 160,
447
- cy: 160,
448
- r: 150,
449
- stroke: "#E5E7EB",
450
- strokeWidth: "0",
451
- fill: "none"
452
- }), /*#__PURE__*/_react.default.createElement(AnimatedCircle, {
453
- cx: 160,
454
- cy: 160,
455
- r: 152,
456
- stroke: "#214287",
457
- strokeWidth: 6,
458
- fill: "none",
459
- strokeDasharray: strokeDasharray,
460
- strokeDashoffset: progressValue,
461
- strokeLinecap: "round"
462
- }))), !isCameraActive && /*#__PURE__*/_react.default.createElement(_reactNative.View, {
463
- style: styles.cameraIconSection
464
- }, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
465
- style: styles.cameraIconContainer
466
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
467
- style: styles.cameraIcon
468
- }, "\uD83D\uDCF7")))), isCameraActive && /*#__PURE__*/_react.default.createElement(_reactNative.View, {
469
- style: styles.instructionContainer
470
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
471
- style: styles.instructionText
472
- }, getInstructionText())), !isCameraActive && !hasPermission && /*#__PURE__*/_react.default.createElement(_reactNative.View, {
473
- style: styles.startContainer
474
- }, /*#__PURE__*/_react.default.createElement(_reactNative.TouchableOpacity, {
475
- style: styles.startButton,
476
- onPress: startCamera
477
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
478
- style: styles.startButtonText
479
- }, "Proceed")))))), /*#__PURE__*/_react.default.createElement(_reactNative.TouchableOpacity, {
480
- style: styles.closeButton,
481
- onPress: onCancel
482
- }, /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
483
- style: styles.closeButtonText
484
- }, "\u2715")));
485
- };
486
- const styles = _reactNative.StyleSheet.create({
487
- container: {
488
- flex: 1,
489
- marginHorizontal: 'auto',
490
- width: '100%'
491
- },
492
- centeredContainer: {
493
- flex: 1,
494
- alignSelf: 'center',
495
- justifyContent: 'center',
496
- width: '100%',
497
- paddingHorizontal: 0,
498
- paddingBottom: 40,
499
- paddingTop: 20
500
- },
501
- contentContainer: {
502
- flex: 1,
503
- alignItems: 'center',
504
- justifyContent: 'flex-start',
505
- gap: 16
506
- },
507
- captureSection: {
508
- justifyContent: 'flex-start',
509
- alignItems: 'center',
510
- position: 'relative',
511
- width: 320
512
- },
513
- captureBackground: {
514
- width: 300,
515
- height: 300,
516
- backgroundColor: '#F1F5F9',
517
- overflow: 'hidden',
518
- position: 'relative',
519
- justifyContent: 'center',
520
- alignItems: 'center',
521
- borderRadius: 150
522
- },
523
- camera: {
524
- width: '100%',
525
- height: '100%',
526
- transform: [{
527
- scaleX: -1
528
- }]
529
- },
530
- avatarFrame: {
531
- width: 140,
532
- height: 140
533
- },
534
- avatarPlaceholder: {
535
- width: 140,
536
- height: 140,
537
- justifyContent: 'center',
538
- alignItems: 'center'
539
- },
540
- avatarText: {
541
- fontSize: 80
542
- },
543
- progressRingContainer: {
544
- position: 'absolute',
545
- top: '50%',
546
- left: '50%',
547
- transform: [{
548
- translateX: -160
549
- }, {
550
- translateY: -160
551
- }],
552
- width: 320,
553
- height: 320
554
- },
555
- progressRing: {
556
- width: '100%',
557
- height: '100%'
558
- },
559
- cameraIconSection: {
560
- position: 'absolute',
561
- top: 240,
562
- right: 40,
563
- width: 42,
564
- height: 42,
565
- borderRadius: 21,
566
- backgroundColor: '#ffffff',
567
- justifyContent: 'center',
568
- alignItems: 'center'
569
- },
570
- cameraIconContainer: {
571
- width: 38,
572
- height: 38,
573
- borderRadius: 19,
574
- backgroundColor: '#214287',
575
- justifyContent: 'center',
576
- alignItems: 'center'
577
- },
578
- cameraIcon: {
579
- fontSize: 16,
580
- color: '#ffffff'
581
- },
582
- instructionContainer: {
583
- marginBottom: 16,
584
- paddingHorizontal: 20,
585
- alignItems: 'center'
586
- },
587
- instructionText: {
588
- fontSize: 16,
589
- color: '#667085',
590
- textAlign: 'center',
591
- lineHeight: 24
592
- },
593
- startContainer: {
594
- alignItems: 'center',
595
- marginTop: 24
596
- },
597
- startButton: {
598
- backgroundColor: '#214287',
599
- borderRadius: 10,
600
- padding: 15,
601
- alignItems: 'center',
602
- minWidth: 250
603
- },
604
- startButtonText: {
605
- color: '#ffffff',
606
- fontSize: 16,
607
- fontWeight: '600',
608
- textAlign: 'center'
609
- },
610
- loadingContainer: {
611
- flex: 1,
612
- justifyContent: 'center',
613
- alignItems: 'center',
614
- paddingVertical: 50
615
- },
616
- loadingSpinner: {
617
- width: 48,
618
- height: 48,
619
- borderRadius: 24,
620
- borderWidth: 4,
621
- borderColor: '#e5e7eb',
622
- borderTopColor: '#214287',
623
- marginBottom: 16
624
- },
625
- loadingText: {
626
- fontSize: 16,
627
- color: '#667085',
628
- textAlign: 'center'
629
- },
630
- capturedImageContainer: {
631
- alignItems: 'center',
632
- justifyContent: 'center',
633
- gap: 24,
634
- width: '100%'
635
- },
636
- capturedImageWrapper: {
637
- width: '100%',
638
- height: 300,
639
- borderRadius: 12,
640
- overflow: 'hidden',
641
- backgroundColor: '#F1F5F9',
642
- shadowColor: '#000',
643
- shadowOffset: {
644
- width: 0,
645
- height: 4
646
- },
647
- shadowOpacity: 0.1,
648
- shadowRadius: 8,
649
- elevation: 5
650
- },
651
- capturedImage: {
652
- width: '100%',
653
- height: '100%'
654
- },
655
- capturedImageActions: {
656
- width: '100%',
657
- gap: 12
658
- },
659
- continueButton: {
660
- backgroundColor: '#214287',
661
- borderRadius: 10,
662
- padding: 15,
663
- alignItems: 'center',
664
- width: '100%'
665
- },
666
- continueButtonText: {
667
- color: '#ffffff',
668
- fontSize: 16,
669
- fontWeight: '600',
670
- textAlign: 'center'
671
- },
672
- retakeButton: {
673
- borderWidth: 1,
674
- borderColor: '#214287',
675
- borderRadius: 10,
676
- padding: 15,
677
- alignItems: 'center',
678
- backgroundColor: 'transparent',
679
- width: '100%'
680
- },
681
- retakeButtonText: {
682
- color: '#214287',
683
- fontSize: 16,
684
- fontWeight: '600',
685
- textAlign: 'center'
686
- },
687
- permissionDeniedContainer: {
688
- alignItems: 'center'
689
- },
690
- permissionDeniedTitle: {
691
- fontSize: 20,
692
- fontWeight: '600',
693
- color: '#333333',
694
- textAlign: 'center',
695
- marginBottom: 15
696
- },
697
- permissionDeniedText: {
698
- fontSize: 16,
699
- color: '#666666',
700
- textAlign: 'center',
701
- lineHeight: 24,
702
- marginBottom: 30
703
- },
704
- permissionActions: {
705
- width: '100%',
706
- gap: 12
707
- },
708
- settingsButton: {
709
- backgroundColor: '#214287',
710
- borderRadius: 10,
711
- padding: 15,
712
- alignItems: 'center',
713
- width: '100%'
714
- },
715
- settingsButtonText: {
716
- color: '#ffffff',
717
- fontSize: 16,
718
- fontWeight: '600',
719
- textAlign: 'center'
720
- },
721
- retryButton: {
722
- borderWidth: 1,
723
- borderColor: '#214287',
724
- borderRadius: 10,
725
- padding: 15,
726
- alignItems: 'center',
727
- backgroundColor: 'transparent',
728
- width: '100%'
729
- },
730
- retryButtonText: {
731
- color: '#214287',
732
- fontSize: 16,
733
- fontWeight: '600',
734
- textAlign: 'center'
735
- },
736
- closeButton: {
737
- position: 'absolute',
738
- top: 50,
739
- right: 20,
740
- width: 44,
741
- height: 44,
742
- borderRadius: 22,
743
- backgroundColor: 'rgba(0,0,0,0.5)',
744
- justifyContent: 'center',
745
- alignItems: 'center'
746
- },
747
- closeButtonText: {
748
- color: 'white',
749
- fontSize: 18,
750
- fontWeight: 'bold'
751
- }
752
- });
753
- var _default = FaceVerification;
754
- exports.default = _default;
755
- //# sourceMappingURL=FaceVerification.js.map