vesant-sdk 1.7.0-dev.e0ee6d5 → 1.7.0-dev.f9faca4
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/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +19 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +19 -12
- package/dist/index.mjs.map +1 -1
- package/dist/kyc/core.d.mts +1 -1
- package/dist/kyc/core.d.ts +1 -1
- package/dist/kyc/core.js +16 -12
- package/dist/kyc/core.js.map +1 -1
- package/dist/kyc/core.mjs +16 -12
- package/dist/kyc/core.mjs.map +1 -1
- package/dist/kyc/index.d.mts +56 -50
- package/dist/kyc/index.d.ts +56 -50
- package/dist/kyc/index.js +16 -12
- package/dist/kyc/index.js.map +1 -1
- package/dist/kyc/index.mjs +16 -12
- package/dist/kyc/index.mjs.map +1 -1
- package/dist/react.d.mts +14 -12
- package/dist/react.d.ts +14 -12
- package/dist/react.js +258 -29
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +258 -29
- package/dist/react.mjs.map +1 -1
- package/dist/tax/index.d.mts +18 -1
- package/dist/tax/index.d.ts +18 -1
- package/dist/tax/index.js +3 -0
- package/dist/tax/index.js.map +1 -1
- package/dist/tax/index.mjs +3 -0
- package/dist/tax/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { D as DeviceFingerprintRequest, G as GeolocationClient, i as CipherTextO
|
|
|
2
2
|
import { e as LoginVerificationResponse, L as LoginVerificationRequest, f as RegistrationVerificationResponse, R as RegistrationVerificationRequest, h as TransactionVerificationResponse, g as TransactionVerificationRequest, C as ComplianceClient } from './client-C3DCmGe9.js';
|
|
3
3
|
import { RiskProfileClient } from './risk-profile/index.js';
|
|
4
4
|
import { C as CustomerProfile } from './types-UGyDl1fd.js';
|
|
5
|
-
import { KycClient, UseKycAlertsOptions, UseKycAlertsResult, UseKycOverviewOptions, UseKycOverviewResult, UseKycPreferencesResult, UseKycRequestsOptions, UseKycRequestsResult, UseKycSubmissionOptions, UseKycSubmissionResult
|
|
5
|
+
import { KycClient, CreateEventBasedFaceVerificationSessionRequest, CreateEventBasedFaceVerificationSessionResponse, EventBasedFaceVerificationCallback, UseKycAlertsOptions, UseKycAlertsResult, UseKycOverviewOptions, UseKycOverviewResult, UseKycPreferencesResult, UseKycRequestsOptions, UseKycRequestsResult, UseKycSubmissionOptions, UseKycSubmissionResult } from './kyc/index.js';
|
|
6
6
|
import './client-BolQlL5e.js';
|
|
7
7
|
import './types-CBQRNL-l.js';
|
|
8
8
|
|
|
@@ -508,7 +508,7 @@ declare function getStatusColor(status: string): string;
|
|
|
508
508
|
*/
|
|
509
509
|
declare function getRiskColor(risk: string): string;
|
|
510
510
|
/**
|
|
511
|
-
* Hook for the
|
|
511
|
+
* Hook for the Event-Based Face Verification face-capture flow.
|
|
512
512
|
*
|
|
513
513
|
* Returns helpers that cover both mobile (direct capture) and desktop
|
|
514
514
|
* (QR + polling) modes. Device detection happens here on the client —
|
|
@@ -524,26 +524,28 @@ declare function getRiskColor(risk: string): string;
|
|
|
524
524
|
* - `runFlow(req, opts?)` — convenience wrapper: `startSession` then
|
|
525
525
|
* `verifyFace`, with a short-circuit when `is_required` is false.
|
|
526
526
|
*/
|
|
527
|
-
declare function
|
|
528
|
-
startSession: (request:
|
|
529
|
-
verifyFace: (session:
|
|
527
|
+
declare function useEventBasedFaceVerificationSubmission(client: KycClient): {
|
|
528
|
+
startSession: (request: CreateEventBasedFaceVerificationSessionRequest) => Promise<CreateEventBasedFaceVerificationSessionResponse>;
|
|
529
|
+
verifyFace: (session: CreateEventBasedFaceVerificationSessionResponse, opts?: {
|
|
530
530
|
defaultDevice?: "ask" | "this" | "mobile";
|
|
531
531
|
renderQR?: (payload: string) => React.ReactNode;
|
|
532
|
-
|
|
533
|
-
|
|
532
|
+
onCancel?: () => void;
|
|
533
|
+
}) => Promise<EventBasedFaceVerificationCallback | null>;
|
|
534
|
+
runFlow: (request: CreateEventBasedFaceVerificationSessionRequest, opts?: {
|
|
534
535
|
defaultDevice?: "ask" | "this" | "mobile";
|
|
535
536
|
renderQR?: (payload: string) => React.ReactNode;
|
|
537
|
+
onCancel?: () => void;
|
|
536
538
|
}) => Promise<{
|
|
537
539
|
kind: "not_required";
|
|
538
|
-
session:
|
|
540
|
+
session: CreateEventBasedFaceVerificationSessionResponse;
|
|
539
541
|
} | {
|
|
540
542
|
kind: "cancelled";
|
|
541
|
-
session:
|
|
543
|
+
session: CreateEventBasedFaceVerificationSessionResponse;
|
|
542
544
|
} | {
|
|
543
545
|
kind: "completed";
|
|
544
|
-
session:
|
|
545
|
-
result:
|
|
546
|
+
session: CreateEventBasedFaceVerificationSessionResponse;
|
|
547
|
+
result: EventBasedFaceVerificationCallback;
|
|
546
548
|
}>;
|
|
547
549
|
};
|
|
548
550
|
|
|
549
|
-
export { type UseCustomerProfileOptions, type UseCustomerProfileResult, UseGeolocationOptions, UseGeolocationResult, UseKycAlertsOptions, UseKycAlertsResult, UseKycOverviewOptions, UseKycOverviewResult, UseKycPreferencesResult, UseKycRequestsOptions, UseKycRequestsResult, UseKycSubmissionOptions, UseKycSubmissionResult, UseLocationCaptureOptions, UseLocationCaptureResult, UseLocationRequestsOptions, UseLocationRequestsResult, type UseLoginVerificationOptions, type UseLoginVerificationResult, type UseRegistrationOptions, type UseRegistrationResult, type UseTransactionVerificationOptions, type UseTransactionVerificationResult, createDeviceFingerprint, fileToBase64, formatKycStatus, getBrowserInfo, getRiskColor, getStatusColor, isValidFileSize, isValidFileType, useCipherText, useCustomerProfile, useGeolocation, useKycAlerts, useKycOverview, useKycPreferences, useKycRequests, useKycSubmission, useLocationCapture, useLocationRequests, useLoginVerification, useRegistration,
|
|
551
|
+
export { type UseCustomerProfileOptions, type UseCustomerProfileResult, UseGeolocationOptions, UseGeolocationResult, UseKycAlertsOptions, UseKycAlertsResult, UseKycOverviewOptions, UseKycOverviewResult, UseKycPreferencesResult, UseKycRequestsOptions, UseKycRequestsResult, UseKycSubmissionOptions, UseKycSubmissionResult, UseLocationCaptureOptions, UseLocationCaptureResult, UseLocationRequestsOptions, UseLocationRequestsResult, type UseLoginVerificationOptions, type UseLoginVerificationResult, type UseRegistrationOptions, type UseRegistrationResult, type UseTransactionVerificationOptions, type UseTransactionVerificationResult, createDeviceFingerprint, fileToBase64, formatKycStatus, getBrowserInfo, getRiskColor, getStatusColor, isValidFileSize, isValidFileType, useCipherText, useCustomerProfile, useEventBasedFaceVerificationSubmission, useGeolocation, useKycAlerts, useKycOverview, useKycPreferences, useKycRequests, useKycSubmission, useLocationCapture, useLocationRequests, useLoginVerification, useRegistration, useTransactionVerification };
|
package/dist/react.js
CHANGED
|
@@ -888,10 +888,10 @@ function useCustomerProfile(client, customerId, options = {}) {
|
|
|
888
888
|
var Camera = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjAvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvVFIvMjAwMS9SRUMtU1ZHLTIwMDEwOTA0L0RURC9zdmcxMC5kdGQiPg0KPCEtLSBVcGxvYWRlZCB0bzogU1ZHIFJlcG8sIHd3dy5zdmdyZXBvLmNvbSwgR2VuZXJhdG9yOiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4NCjxzdmcgdmVyc2lvbj0iMS4wIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgDQoJIHdpZHRoPSI4MDBweCIgaGVpZ2h0PSI4MDBweCIgdmlld0JveD0iMCAwIDY0IDY0IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA2NCA2NCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8Zz4NCgk8cGF0aCBmaWxsPSIjMjMxRjIwIiBkPSJNNjAsMTBINDkuNjU2bC02LjgyOC02LjgyOEM0Mi4wNzgsMi40MjIsNDEuMDYyLDIsNDAsMkgyNGMtMS4wNjIsMC0yLjA3OCwwLjQyMi0yLjgyOCwxLjE3MkwxNC4zNDQsMTBINA0KCQljLTIuMjExLDAtNCwxLjc4OS00LDR2NDRjMCwyLjIxMSwxLjc4OSw0LDQsNGg1NmMyLjIxMSwwLDQtMS43ODksNC00VjE0QzY0LDExLjc4OSw2Mi4yMTEsMTAsNjAsMTB6IE0zMiw1MA0KCQljLTguODM2LDAtMTYtNy4xNjQtMTYtMTZzNy4xNjQtMTYsMTYtMTZzMTYsNy4xNjQsMTYsMTZTNDAuODM2LDUwLDMyLDUweiIvPg0KCTxjaXJjbGUgZmlsbD0iIzIzMUYyMCIgY3g9IjMyIiBjeT0iMzQiIHI9IjgiLz4NCjwvZz4NCjwvc3ZnPg==";
|
|
889
889
|
var Done = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPg0KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik04LjUgMTIuNUwxMC41IDE0LjVMMTUuNSA5LjUiIHN0cm9rZT0iIzFDMjc0QyIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPg0KPHBhdGggZD0iTTcgMy4zMzc4MkM4LjQ3MDg3IDIuNDg2OTcgMTAuMTc4NiAyIDEyIDJDMTcuNTIyOCAyIDIyIDYuNDc3MTUgMjIgMTJDMjIgMTcuNTIyOCAxNy41MjI4IDIyIDEyIDIyQzYuNDc3MTUgMjIgMiAxNy41MjI4IDIgMTJDMiAxMC4xNzg2IDIuNDg2OTcgOC40NzA4NyAzLjMzNzgyIDciIHN0cm9rZT0iIzFDMjc0QyIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPg0KPC9zdmc+";
|
|
890
890
|
var Close = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPg0KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik0xNC41IDkuNTAwMDJMOS41IDE0LjVNOS40OTk5OCA5LjVMMTQuNSAxNC41IiBzdHJva2U9IiMxQzI3NEMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4NCjxwYXRoIGQ9Ik03IDMuMzM3ODJDOC40NzA4NyAyLjQ4Njk3IDEwLjE3ODYgMiAxMiAyQzE3LjUyMjggMiAyMiA2LjQ3NzE1IDIyIDEyQzIyIDE3LjUyMjggMTcuNTIyOCAyMiAxMiAyMkM2LjQ3NzE1IDIyIDIgMTcuNTIyOCAyIDEyQzIgMTAuMTc4NiAyLjQ4Njk3IDguNDcwODcgMy4zMzc4MiA3IiBzdHJva2U9IiMxQzI3NEMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4NCjwvc3ZnPg==";
|
|
891
|
-
var Upload = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPg0KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik0xNyAxN0gxNy4wMU0xNS42IDE0SDE4QzE4LjkzMTkgMTQgMTkuMzk3OCAxNCAxOS43NjU0IDE0LjE1MjJDMjAuMjU1NCAxNC4zNTUyIDIwLjY0NDggMTQuNzQ0NiAyMC44NDc4IDE1LjIzNDZDMjEgMTUuNjAyMiAyMSAxNi4wNjgxIDIxIDE3QzIxIDE3LjkzMTkgMjEgMTguMzk3OCAyMC44NDc4IDE4Ljc2NTRDMjAuNjQ0OCAxOS4yNTU0IDIwLjI1NTQgMTkuNjQ0OCAxOS43NjU0IDE5Ljg0NzhDMTkuMzk3OCAyMCAxOC45MzE5IDIwIDE4IDIwSDZDNS4wNjgxMiAyMCA0LjYwMjE4IDIwIDQuMjM0NjMgMTkuODQ3OEMzLjc0NDU4IDE5LjY0NDggMy4zNTUyMyAxOS4yNTU0IDMuMTUyMjQgMTguNzY1NEMzIDE4LjM5NzggMyAxNy45MzE5IDMgMTdDMyAxNi4wNjgxIDMgMTUuNjAyMiAzLjE1MjI0IDE1LjIzNDZDMy4zNTUyMyAxNC43NDQ2IDMuNzQ0NTggMTQuMzU1MiA0LjIzNDYzIDE0LjE1MjJDNC42MDIxOCAxNCA1LjA2ODEyIDE0IDYgMTRIOC40TTEyIDE1VjRNMTIgNEwxNSA3TTEyIDRMOSA3IiBzdHJva2U9IiMwMDAwMDAiIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2UtbGluZWpvaW49InJvdW5kIi8+DQo8L3N2Zz4=";
|
|
892
891
|
|
|
893
892
|
// src/kyc/FaceCaptureModal.tsx
|
|
894
893
|
var MOBILE_UA = /Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
|
|
894
|
+
var SESSION_EXPIRY_MS = 15 * 60 * 1e3;
|
|
895
895
|
var LIVENESS_MESSAGES = [
|
|
896
896
|
"Position your face inside the circle",
|
|
897
897
|
"Make sure your face is well lit",
|
|
@@ -905,9 +905,9 @@ function headerSubtitle(stageKind) {
|
|
|
905
905
|
case "accepted":
|
|
906
906
|
return "All set";
|
|
907
907
|
case "declined":
|
|
908
|
-
return "Verification
|
|
908
|
+
return "Verification Declined";
|
|
909
909
|
case "max_attempts":
|
|
910
|
-
return "We couldn't verify
|
|
910
|
+
return "We couldn't verify your identity";
|
|
911
911
|
default:
|
|
912
912
|
return "Please capture a clear photo of your face";
|
|
913
913
|
}
|
|
@@ -920,16 +920,18 @@ function FaceCaptureModal({
|
|
|
920
920
|
client,
|
|
921
921
|
session,
|
|
922
922
|
onComplete,
|
|
923
|
+
onCancel,
|
|
923
924
|
defaultDevice,
|
|
924
925
|
renderQR
|
|
925
926
|
}) {
|
|
926
927
|
const isMobile = typeof navigator !== "undefined" && MOBILE_UA.test(navigator.userAgent);
|
|
928
|
+
const initialChoice = defaultDevice ?? (isMobile ? "this" : "ask");
|
|
927
929
|
const initialStage = (() => {
|
|
928
|
-
|
|
929
|
-
if (
|
|
930
|
-
if (choice === "mobile") return { kind: "qr", mobileConnected: false };
|
|
930
|
+
if (initialChoice === "this") return { kind: "capture" };
|
|
931
|
+
if (initialChoice === "mobile") return { kind: "qr", mobileConnected: false };
|
|
931
932
|
return { kind: "choose" };
|
|
932
933
|
})();
|
|
934
|
+
const hasMethodChoice = initialChoice === "ask";
|
|
933
935
|
const [stage, setStage] = React.useState(initialStage);
|
|
934
936
|
const [attempts, setAttempts] = React.useState(session.attempts);
|
|
935
937
|
const maxAttempts = session.max_attempts || 1;
|
|
@@ -941,17 +943,25 @@ function FaceCaptureModal({
|
|
|
941
943
|
const qrPayload = session.link || `vesant://reuse-kyc?token=${encodeURIComponent(session.token)}`;
|
|
942
944
|
const cancelledRef = React.useRef(false);
|
|
943
945
|
const submittingRef = React.useRef(false);
|
|
946
|
+
React.useEffect(() => {
|
|
947
|
+
const timer = setTimeout(() => {
|
|
948
|
+
setStage(
|
|
949
|
+
(prev) => prev.kind === "choose" || prev.kind === "qr" || prev.kind === "capture" ? { kind: "error", message: "Session expired" } : prev
|
|
950
|
+
);
|
|
951
|
+
}, SESSION_EXPIRY_MS);
|
|
952
|
+
return () => clearTimeout(timer);
|
|
953
|
+
}, [session.token]);
|
|
944
954
|
React.useEffect(() => {
|
|
945
955
|
if (stage.kind !== "qr") return;
|
|
946
956
|
let stopped = false;
|
|
947
957
|
const intervalMs = 2e3;
|
|
948
|
-
const deadline = Date.now() +
|
|
958
|
+
const deadline = Date.now() + SESSION_EXPIRY_MS;
|
|
949
959
|
let mobileSeen = stage.mobileConnected;
|
|
950
960
|
const tick = async () => {
|
|
951
961
|
if (stopped || cancelledRef.current) return;
|
|
952
962
|
try {
|
|
953
963
|
if (mobileSeen) {
|
|
954
|
-
const result = await client.
|
|
964
|
+
const result = await client.getEventBasedFaceVerificationSessionStatus(session.token);
|
|
955
965
|
if (result.status === "accepted") {
|
|
956
966
|
setStage({ kind: "accepted", result });
|
|
957
967
|
stopped = true;
|
|
@@ -1023,7 +1033,7 @@ function FaceCaptureModal({
|
|
|
1023
1033
|
try {
|
|
1024
1034
|
const postPromise = (async () => {
|
|
1025
1035
|
try {
|
|
1026
|
-
const data = await client.
|
|
1036
|
+
const data = await client.submitEventBasedFaceVerificationSession({
|
|
1027
1037
|
token: session.token,
|
|
1028
1038
|
reference: ref,
|
|
1029
1039
|
proof
|
|
@@ -1039,7 +1049,7 @@ function FaceCaptureModal({
|
|
|
1039
1049
|
while (Date.now() < deadline) {
|
|
1040
1050
|
if (settled || cancelledRef.current) return null;
|
|
1041
1051
|
try {
|
|
1042
|
-
const r = await client.
|
|
1052
|
+
const r = await client.getEventBasedFaceVerificationSessionStatus(session.token);
|
|
1043
1053
|
if (isFreshPollResult(r)) return r;
|
|
1044
1054
|
} catch {
|
|
1045
1055
|
}
|
|
@@ -1110,6 +1120,9 @@ function FaceCaptureModal({
|
|
|
1110
1120
|
}, [captureMode]);
|
|
1111
1121
|
const close = (result) => {
|
|
1112
1122
|
cancelledRef.current = true;
|
|
1123
|
+
if (result === null && onCancel) {
|
|
1124
|
+
onCancel();
|
|
1125
|
+
}
|
|
1113
1126
|
onComplete(result);
|
|
1114
1127
|
};
|
|
1115
1128
|
const renderChoose = () => /* @__PURE__ */ React__default.default.createElement("div", { style: contentStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: visualGuideContainerStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: visualGuideStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: circleStyle }, /* @__PURE__ */ React__default.default.createElement("img", { src: Camera, alt: "", width: 48, height: 48 })))), /* @__PURE__ */ React__default.default.createElement("p", { style: subtitleStyle }, "How would you like to verify?"), /* @__PURE__ */ React__default.default.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React__default.default.createElement(
|
|
@@ -1118,7 +1131,7 @@ function FaceCaptureModal({
|
|
|
1118
1131
|
style: primaryButtonStyle,
|
|
1119
1132
|
onClick: () => setStage({ kind: "capture" })
|
|
1120
1133
|
},
|
|
1121
|
-
/* @__PURE__ */ React__default.default.createElement("img", { src:
|
|
1134
|
+
/* @__PURE__ */ React__default.default.createElement("img", { src: Camera, alt: "", width: 20, height: 20 }),
|
|
1122
1135
|
/* @__PURE__ */ React__default.default.createElement("span", null, "Continue on this device")
|
|
1123
1136
|
), /* @__PURE__ */ React__default.default.createElement(
|
|
1124
1137
|
"button",
|
|
@@ -1135,6 +1148,13 @@ function FaceCaptureModal({
|
|
|
1135
1148
|
onClick: () => setStage({ kind: "capture" })
|
|
1136
1149
|
},
|
|
1137
1150
|
"Use this device instead"
|
|
1151
|
+
), hasMethodChoice && /* @__PURE__ */ React__default.default.createElement(
|
|
1152
|
+
"button",
|
|
1153
|
+
{
|
|
1154
|
+
style: secondaryButtonStyle,
|
|
1155
|
+
onClick: () => setStage({ kind: "choose" })
|
|
1156
|
+
},
|
|
1157
|
+
"Change verification method"
|
|
1138
1158
|
), /* @__PURE__ */ React__default.default.createElement("button", { style: cancelButtonStyle, onClick: () => close(null) }, "Cancel")));
|
|
1139
1159
|
const renderCapture = (declinedReason) => {
|
|
1140
1160
|
if (captureMode === "live") {
|
|
@@ -1150,13 +1170,23 @@ function FaceCaptureModal({
|
|
|
1150
1170
|
if (captureMode === "preview" && capturedPreview) {
|
|
1151
1171
|
return /* @__PURE__ */ React__default.default.createElement("div", { style: contentStyle }, declinedReason && /* @__PURE__ */ React__default.default.createElement("div", { style: alertBoxStyle }, /* @__PURE__ */ React__default.default.createElement("strong", null, "Verification declined."), /* @__PURE__ */ React__default.default.createElement("p", { style: alertTextStyle }, declinedReason)), /* @__PURE__ */ React__default.default.createElement("p", { style: subtitleStyle }, "Looks good? Submit this selfie or retake it."), /* @__PURE__ */ React__default.default.createElement("div", { style: previewBoxStyle }, /* @__PURE__ */ React__default.default.createElement("img", { src: capturedPreview, alt: "Captured selfie preview", style: previewImgStyle })), /* @__PURE__ */ React__default.default.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React__default.default.createElement("button", { style: primaryButtonStyle, onClick: handleConfirmSubmit }, /* @__PURE__ */ React__default.default.createElement("img", { src: Done, alt: "", width: 20, height: 20 }), /* @__PURE__ */ React__default.default.createElement("span", null, "Submit")), /* @__PURE__ */ React__default.default.createElement("button", { style: secondaryButtonStyle, onClick: handleRetake }, "Retake"), /* @__PURE__ */ React__default.default.createElement("button", { style: cancelButtonStyle, onClick: () => close(null) }, "Cancel")), /* @__PURE__ */ React__default.default.createElement("p", { style: attemptsTextStyle }, "Attempt ", attempts + 1, " of ", maxAttempts));
|
|
1152
1172
|
}
|
|
1153
|
-
return /* @__PURE__ */ React__default.default.createElement("div", { style: contentStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: visualGuideContainerStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: visualGuideStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: circleStyle }, /* @__PURE__ */ React__default.default.createElement("img", { src: Camera, alt: "", width: 48, height: 48 })), /* @__PURE__ */ React__default.default.createElement("div", { style: badgeStyle }, /* @__PURE__ */ React__default.default.createElement("img", { src: Done, alt: "", width: 16, height: 16 })))), declinedReason && /* @__PURE__ */ React__default.default.createElement("div", { style: alertBoxStyle }, /* @__PURE__ */ React__default.default.createElement("strong", null, "Verification declined."), /* @__PURE__ */ React__default.default.createElement("p", { style: alertTextStyle }, declinedReason)), /* @__PURE__ */ React__default.default.createElement("div", { style: instructionsBoxStyle }, /* @__PURE__ */ React__default.default.createElement("h3", { style: instructionsTitleStyle }, "Tips for best results:"), /* @__PURE__ */ React__default.default.createElement("ul", { style: instructionsListStyle }, /* @__PURE__ */ React__default.default.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React__default.default.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React__default.default.createElement("span", null, "Ensure good lighting on your face")), /* @__PURE__ */ React__default.default.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React__default.default.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React__default.default.createElement("span", null, "Remove glasses or accessories if possible")), /* @__PURE__ */ React__default.default.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React__default.default.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React__default.default.createElement("span", null, "Look directly at the camera")))), /* @__PURE__ */ React__default.default.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React__default.default.createElement("button", { style: primaryButtonStyle, onClick: handleOpenCamera }, /* @__PURE__ */ React__default.default.createElement("img", { src: Camera, alt: "", width: 20, height: 20 }), /* @__PURE__ */ React__default.default.createElement("span", null, declinedReason ? "Try
|
|
1173
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { style: contentStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: visualGuideContainerStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: visualGuideStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: circleStyle }, /* @__PURE__ */ React__default.default.createElement("img", { src: Camera, alt: "", width: 48, height: 48 })), /* @__PURE__ */ React__default.default.createElement("div", { style: badgeStyle }, /* @__PURE__ */ React__default.default.createElement("img", { src: Done, alt: "", width: 16, height: 16 })))), declinedReason && /* @__PURE__ */ React__default.default.createElement("div", { style: alertBoxStyle }, /* @__PURE__ */ React__default.default.createElement("strong", null, "Verification declined."), /* @__PURE__ */ React__default.default.createElement("p", { style: alertTextStyle }, declinedReason)), /* @__PURE__ */ React__default.default.createElement("div", { style: instructionsBoxStyle }, /* @__PURE__ */ React__default.default.createElement("h3", { style: instructionsTitleStyle }, "Tips for best results:"), /* @__PURE__ */ React__default.default.createElement("ul", { style: instructionsListStyle }, /* @__PURE__ */ React__default.default.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React__default.default.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React__default.default.createElement("span", null, "Ensure good lighting on your face")), /* @__PURE__ */ React__default.default.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React__default.default.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React__default.default.createElement("span", null, "Remove glasses or accessories if possible")), /* @__PURE__ */ React__default.default.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React__default.default.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React__default.default.createElement("span", null, "Look directly at the camera")))), /* @__PURE__ */ React__default.default.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React__default.default.createElement("button", { style: primaryButtonStyle, onClick: handleOpenCamera }, /* @__PURE__ */ React__default.default.createElement("img", { src: Camera, alt: "", width: 20, height: 20 }), /* @__PURE__ */ React__default.default.createElement("span", null, declinedReason ? "Try Again" : "Open Camera")), hasMethodChoice && /* @__PURE__ */ React__default.default.createElement(
|
|
1174
|
+
"button",
|
|
1175
|
+
{
|
|
1176
|
+
style: secondaryButtonStyle,
|
|
1177
|
+
onClick: () => setStage({ kind: "choose" })
|
|
1178
|
+
},
|
|
1179
|
+
"Change verification method"
|
|
1180
|
+
), /* @__PURE__ */ React__default.default.createElement("button", { style: cancelButtonStyle, onClick: () => close(null) }, "Cancel")), /* @__PURE__ */ React__default.default.createElement("p", { style: attemptsTextStyle }, "Attempt ", attempts + 1, " of ", maxAttempts));
|
|
1154
1181
|
};
|
|
1155
1182
|
const renderSubmitting = () => /* @__PURE__ */ React__default.default.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center" } }, /* @__PURE__ */ React__default.default.createElement("div", { style: { ...spinnerStyle, margin: "24px auto", width: 32, height: 32 } }), /* @__PURE__ */ React__default.default.createElement("p", { style: subtitleStyle }, "Verifying your photo\u2026"), /* @__PURE__ */ React__default.default.createElement("p", { style: { ...attemptsTextStyle, marginTop: 8 } }, "This usually takes a few seconds."));
|
|
1156
1183
|
const renderAccepted = (result) => /* @__PURE__ */ React__default.default.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center" } }, /* @__PURE__ */ React__default.default.createElement("div", { style: successCircleStyle }, /* @__PURE__ */ React__default.default.createElement("img", { src: Done, alt: "", width: 48, height: 48 })), /* @__PURE__ */ React__default.default.createElement("h3", { style: titleStyle }, "Verified"), /* @__PURE__ */ React__default.default.createElement("p", { style: subtitleStyle }, "Your identity has been confirmed. You can continue."), /* @__PURE__ */ React__default.default.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React__default.default.createElement("button", { style: primaryButtonStyle, onClick: () => close(result) }, "Continue")));
|
|
1157
|
-
const renderDeclined = (result) => /* @__PURE__ */ React__default.default.createElement("div", { style: contentStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: alertBoxStyle }, /* @__PURE__ */ React__default.default.createElement("
|
|
1158
|
-
const renderMaxAttempts = (result) => /* @__PURE__ */ React__default.default.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center" } }, /* @__PURE__ */ React__default.default.createElement("div", { style: errorCircleStyle }, "!"), /* @__PURE__ */ React__default.default.createElement("h3", { style: titleStyle }, "Maximum
|
|
1159
|
-
const renderError = (message) =>
|
|
1184
|
+
const renderDeclined = (result) => /* @__PURE__ */ React__default.default.createElement("div", { style: contentStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: alertBoxStyle }, /* @__PURE__ */ React__default.default.createElement("p", { style: alertTextStyle }, result.declined_reason ?? "We couldn't match your selfie. Please take a new one.")), /* @__PURE__ */ React__default.default.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React__default.default.createElement("button", { style: primaryButtonStyle, onClick: handleRetakeAfterDecline }, /* @__PURE__ */ React__default.default.createElement("img", { src: Camera, alt: "", width: 20, height: 20 }), /* @__PURE__ */ React__default.default.createElement("span", null, "Retake")), /* @__PURE__ */ React__default.default.createElement("button", { style: cancelButtonStyle, onClick: () => close(result) }, "Cancel")), /* @__PURE__ */ React__default.default.createElement("p", { style: attemptsTextStyle }, "Attempt ", Math.min(attempts + 1, maxAttempts), " of ", maxAttempts));
|
|
1185
|
+
const renderMaxAttempts = (result) => /* @__PURE__ */ React__default.default.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center" } }, /* @__PURE__ */ React__default.default.createElement("div", { style: errorCircleStyle }, "!"), /* @__PURE__ */ React__default.default.createElement("h3", { style: titleStyle }, "Maximum Attempts Reached"), /* @__PURE__ */ React__default.default.createElement("p", { style: subtitleStyle }, result.declined_reason ?? "We couldn't verify your identity after several attempts."), result.data?.freeze_account && /* @__PURE__ */ React__default.default.createElement("p", { style: alertTextStyle }, "For your security, your account has been temporarily restricted", result.data.freeze_duration_minutes ? ` for ${result.data.freeze_duration_minutes} minutes` : "", ". Please contact support if you need immediate help."), result.data?.enforce_logout && /* @__PURE__ */ React__default.default.createElement("p", { style: alertTextStyle }, "You will be signed out of your session."), result.data?.block && /* @__PURE__ */ React__default.default.createElement("p", { style: alertTextStyle }, "This action has been blocked for security reasons."), /* @__PURE__ */ React__default.default.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React__default.default.createElement("button", { style: primaryButtonStyle, onClick: () => close(result) }, "Close")));
|
|
1186
|
+
const renderError = (message) => {
|
|
1187
|
+
const sessionExpired = /session\s+expired/i.test(message);
|
|
1188
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center" } }, /* @__PURE__ */ React__default.default.createElement("div", { style: errorCircleStyle }, "!"), /* @__PURE__ */ React__default.default.createElement("h3", { style: titleStyle }, sessionExpired ? "Session expired" : "Something Went Wrong"), /* @__PURE__ */ React__default.default.createElement("p", { style: alertTextStyle }, sessionExpired ? "Your verification session is no longer valid. Please start a new verification from the beginning." : message), /* @__PURE__ */ React__default.default.createElement("div", { style: buttonsContainerStyle }, !sessionExpired && /* @__PURE__ */ React__default.default.createElement("button", { style: primaryButtonStyle, onClick: () => setStage({ kind: "capture" }) }, "Try Again"), /* @__PURE__ */ React__default.default.createElement("button", { style: cancelButtonStyle, onClick: () => close(null) }, sessionExpired ? "Close" : "Cancel")));
|
|
1189
|
+
};
|
|
1160
1190
|
const body = (() => {
|
|
1161
1191
|
switch (stage.kind) {
|
|
1162
1192
|
case "choose":
|
|
@@ -1364,11 +1394,63 @@ var attemptsTextStyle = {
|
|
|
1364
1394
|
};
|
|
1365
1395
|
var footerStyle = { padding: "12px 24px 16px", borderTop: "1px solid #f3f4f6" };
|
|
1366
1396
|
var footerTextStyle = { margin: 0, fontSize: 12, color: "#9ca3af", textAlign: "center" };
|
|
1397
|
+
var FACE_MESSAGES = {
|
|
1398
|
+
idle: "Initializing camera...",
|
|
1399
|
+
loading: "Loading face detection...",
|
|
1400
|
+
scanning: "Position your face in the circle",
|
|
1401
|
+
too_far: "Face too far. Please move closer to the camera",
|
|
1402
|
+
too_close: "Too close. Please move back a little",
|
|
1403
|
+
off_center: "Center your face in the circle",
|
|
1404
|
+
ok: "Looking great! Tap the button to capture"
|
|
1405
|
+
};
|
|
1406
|
+
var FACE_COLORS = {
|
|
1407
|
+
idle: "#9ca3af",
|
|
1408
|
+
loading: "#3b82f6",
|
|
1409
|
+
scanning: "#3b82f6",
|
|
1410
|
+
too_far: "#ef4444",
|
|
1411
|
+
too_close: "#f59e0b",
|
|
1412
|
+
off_center: "#f59e0b",
|
|
1413
|
+
ok: "#10b981"
|
|
1414
|
+
};
|
|
1415
|
+
var MEDIAPIPE_BASE = "https://cdn.jsdelivr.net/npm/@mediapipe/face_detection";
|
|
1416
|
+
var mediapipeLoaderPromise = null;
|
|
1417
|
+
function loadMediaPipeFaceDetection() {
|
|
1418
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
1419
|
+
return Promise.reject(new Error("MediaPipe requires a browser environment"));
|
|
1420
|
+
}
|
|
1421
|
+
const w = window;
|
|
1422
|
+
if (w.FaceDetection) {
|
|
1423
|
+
return Promise.resolve(w.FaceDetection);
|
|
1424
|
+
}
|
|
1425
|
+
if (mediapipeLoaderPromise) return mediapipeLoaderPromise;
|
|
1426
|
+
mediapipeLoaderPromise = new Promise((resolve, reject) => {
|
|
1427
|
+
const script = document.createElement("script");
|
|
1428
|
+
script.src = `${MEDIAPIPE_BASE}/face_detection.js`;
|
|
1429
|
+
script.async = true;
|
|
1430
|
+
script.crossOrigin = "anonymous";
|
|
1431
|
+
script.onload = () => {
|
|
1432
|
+
if (w.FaceDetection) {
|
|
1433
|
+
resolve(w.FaceDetection);
|
|
1434
|
+
} else {
|
|
1435
|
+
mediapipeLoaderPromise = null;
|
|
1436
|
+
reject(new Error("MediaPipe loaded but FaceDetection global is missing"));
|
|
1437
|
+
}
|
|
1438
|
+
};
|
|
1439
|
+
script.onerror = () => {
|
|
1440
|
+
mediapipeLoaderPromise = null;
|
|
1441
|
+
reject(new Error("Failed to load MediaPipe face_detection script"));
|
|
1442
|
+
};
|
|
1443
|
+
document.head.appendChild(script);
|
|
1444
|
+
});
|
|
1445
|
+
return mediapipeLoaderPromise;
|
|
1446
|
+
}
|
|
1367
1447
|
function LiveCamera({ onCapture, onCancel, message }) {
|
|
1368
1448
|
const videoRef = React.useRef(null);
|
|
1369
1449
|
const streamRef = React.useRef(null);
|
|
1370
1450
|
const [ready, setReady] = React.useState(false);
|
|
1371
1451
|
const [error, setError] = React.useState(null);
|
|
1452
|
+
const [faceStatus, setFaceStatus] = React.useState("idle");
|
|
1453
|
+
const [faceDetectionFailed, setFaceDetectionFailed] = React.useState(false);
|
|
1372
1454
|
React.useEffect(() => {
|
|
1373
1455
|
let cancelled = false;
|
|
1374
1456
|
async function init() {
|
|
@@ -1409,6 +1491,77 @@ function LiveCamera({ onCapture, onCancel, message }) {
|
|
|
1409
1491
|
streamRef.current = null;
|
|
1410
1492
|
};
|
|
1411
1493
|
}, []);
|
|
1494
|
+
React.useEffect(() => {
|
|
1495
|
+
if (!ready) {
|
|
1496
|
+
setFaceStatus("idle");
|
|
1497
|
+
return;
|
|
1498
|
+
}
|
|
1499
|
+
let cancelled = false;
|
|
1500
|
+
let rafId = null;
|
|
1501
|
+
let detector = null;
|
|
1502
|
+
setFaceStatus("loading");
|
|
1503
|
+
setFaceDetectionFailed(false);
|
|
1504
|
+
(async () => {
|
|
1505
|
+
try {
|
|
1506
|
+
const FaceDetection = await loadMediaPipeFaceDetection();
|
|
1507
|
+
if (cancelled) return;
|
|
1508
|
+
const d = new FaceDetection({
|
|
1509
|
+
locateFile: (f) => `${MEDIAPIPE_BASE}/${f}`
|
|
1510
|
+
});
|
|
1511
|
+
d.setOptions({ model: "short", minDetectionConfidence: 0.5 });
|
|
1512
|
+
d.onResults((results) => {
|
|
1513
|
+
if (cancelled) return;
|
|
1514
|
+
const detections = results.detections ?? [];
|
|
1515
|
+
let next;
|
|
1516
|
+
if (detections.length === 0) {
|
|
1517
|
+
next = "scanning";
|
|
1518
|
+
} else {
|
|
1519
|
+
const bb = detections[0].boundingBox;
|
|
1520
|
+
if (bb.width < 0.18) next = "too_far";
|
|
1521
|
+
else if (bb.width > 0.72) next = "too_close";
|
|
1522
|
+
else if (bb.xCenter < 0.28 || bb.xCenter > 0.72 || bb.yCenter < 0.28 || bb.yCenter > 0.72) {
|
|
1523
|
+
next = "off_center";
|
|
1524
|
+
} else {
|
|
1525
|
+
next = "ok";
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
setFaceStatus(next);
|
|
1529
|
+
});
|
|
1530
|
+
await d.initialize();
|
|
1531
|
+
if (cancelled) return;
|
|
1532
|
+
detector = d;
|
|
1533
|
+
setFaceStatus("scanning");
|
|
1534
|
+
const tick = async () => {
|
|
1535
|
+
if (cancelled) return;
|
|
1536
|
+
const v = videoRef.current;
|
|
1537
|
+
if (v?.readyState === 4 && detector) {
|
|
1538
|
+
try {
|
|
1539
|
+
await detector.send({ image: v });
|
|
1540
|
+
} catch {
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
if (!cancelled) {
|
|
1544
|
+
rafId = requestAnimationFrame(tick);
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1547
|
+
tick();
|
|
1548
|
+
} catch (err) {
|
|
1549
|
+
console.error("Face detection failed to initialize:", err);
|
|
1550
|
+
if (!cancelled) {
|
|
1551
|
+
setFaceDetectionFailed(true);
|
|
1552
|
+
setFaceStatus("scanning");
|
|
1553
|
+
}
|
|
1554
|
+
}
|
|
1555
|
+
})();
|
|
1556
|
+
return () => {
|
|
1557
|
+
cancelled = true;
|
|
1558
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
1559
|
+
try {
|
|
1560
|
+
detector?.close?.();
|
|
1561
|
+
} catch {
|
|
1562
|
+
}
|
|
1563
|
+
};
|
|
1564
|
+
}, [ready]);
|
|
1412
1565
|
const capture = () => {
|
|
1413
1566
|
const video = videoRef.current;
|
|
1414
1567
|
if (!video || !video.videoWidth) return;
|
|
@@ -1430,7 +1583,17 @@ function LiveCamera({ onCapture, onCancel, message }) {
|
|
|
1430
1583
|
if (error) {
|
|
1431
1584
|
return /* @__PURE__ */ React__default.default.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center", padding: 0 } }, /* @__PURE__ */ React__default.default.createElement("div", { style: errorCircleStyle }, "!"), /* @__PURE__ */ React__default.default.createElement("h3", { style: titleStyle }, "Camera unavailable"), /* @__PURE__ */ React__default.default.createElement("p", { style: alertTextStyle }, error), /* @__PURE__ */ React__default.default.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React__default.default.createElement("button", { style: secondaryButtonStyle, onClick: onCancel }, "Back")));
|
|
1432
1585
|
}
|
|
1433
|
-
|
|
1586
|
+
const detectionActive = ready && !faceDetectionFailed;
|
|
1587
|
+
const liveMessage = detectionActive ? FACE_MESSAGES[faceStatus] : message;
|
|
1588
|
+
const liveFaceColor = detectionActive ? FACE_COLORS[faceStatus] : void 0;
|
|
1589
|
+
const captureDisabled = !ready || detectionActive && faceStatus !== "ok";
|
|
1590
|
+
const ringPulse = detectionActive && (faceStatus === "too_far" || faceStatus === "too_close") ? "pulse 1.5s ease-in-out infinite" : void 0;
|
|
1591
|
+
const dynamicCircleStyle = {
|
|
1592
|
+
...faceCircleStyle,
|
|
1593
|
+
...liveFaceColor ? { borderColor: liveFaceColor } : null,
|
|
1594
|
+
...ringPulse ? { animation: ringPulse } : null
|
|
1595
|
+
};
|
|
1596
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { style: videoFrameStyle }, /* @__PURE__ */ React__default.default.createElement(
|
|
1434
1597
|
"video",
|
|
1435
1598
|
{
|
|
1436
1599
|
ref: videoRef,
|
|
@@ -1439,24 +1602,87 @@ function LiveCamera({ onCapture, onCancel, message }) {
|
|
|
1439
1602
|
autoPlay: true,
|
|
1440
1603
|
style: videoStyle
|
|
1441
1604
|
}
|
|
1442
|
-
), /* @__PURE__ */ React__default.default.createElement("div", { style: faceOverlayContainerStyle, "aria-hidden": "true" }, /* @__PURE__ */ React__default.default.createElement("div", { style: faceRingWrapStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: faceDashedRingStyle }), /* @__PURE__ */ React__default.default.createElement("div", { style:
|
|
1605
|
+
), /* @__PURE__ */ React__default.default.createElement("div", { style: faceOverlayContainerStyle, "aria-hidden": "true" }, /* @__PURE__ */ React__default.default.createElement("div", { style: faceRingWrapStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: faceDashedRingStyle }), /* @__PURE__ */ React__default.default.createElement("div", { style: dynamicCircleStyle }))), liveMessage && /* @__PURE__ */ React__default.default.createElement("div", { style: liveMessagePillContainerStyle }, /* @__PURE__ */ React__default.default.createElement("div", { style: liveMessagePillStyle }, /* @__PURE__ */ React__default.default.createElement("span", { style: liveMessagePillTextStyle }, liveMessage))), /* @__PURE__ */ React__default.default.createElement(
|
|
1606
|
+
"button",
|
|
1607
|
+
{
|
|
1608
|
+
type: "button",
|
|
1609
|
+
onClick: onCancel,
|
|
1610
|
+
"aria-label": "Close camera",
|
|
1611
|
+
style: overlayCloseButtonStyle
|
|
1612
|
+
},
|
|
1613
|
+
/* @__PURE__ */ React__default.default.createElement("img", { src: Close, alt: "", width: 16, height: 16 })
|
|
1614
|
+
), !ready && /* @__PURE__ */ React__default.default.createElement("div", { style: videoLoadingStyle }, "Starting camera\u2026"), /* @__PURE__ */ React__default.default.createElement("div", { style: bottomGradientStyle }, /* @__PURE__ */ React__default.default.createElement(
|
|
1443
1615
|
"button",
|
|
1444
1616
|
{
|
|
1445
|
-
|
|
1617
|
+
type: "button",
|
|
1446
1618
|
onClick: capture,
|
|
1447
|
-
disabled:
|
|
1619
|
+
disabled: captureDisabled,
|
|
1620
|
+
"aria-label": "Capture",
|
|
1621
|
+
style: captureDisabled ? { ...shutterButtonStyle, opacity: 0.5, cursor: "not-allowed" } : shutterButtonStyle
|
|
1448
1622
|
},
|
|
1449
|
-
/* @__PURE__ */ React__default.default.createElement("
|
|
1450
|
-
|
|
1451
|
-
), /* @__PURE__ */ React__default.default.createElement("button", { style: secondaryButtonStyle, onClick: onCancel }, "Cancel")));
|
|
1623
|
+
/* @__PURE__ */ React__default.default.createElement("span", { style: shutterInnerStyle })
|
|
1624
|
+
)));
|
|
1452
1625
|
}
|
|
1453
1626
|
var videoFrameStyle = {
|
|
1454
1627
|
position: "relative",
|
|
1455
1628
|
width: "100%",
|
|
1456
|
-
aspectRatio: "
|
|
1457
|
-
borderRadius:
|
|
1629
|
+
aspectRatio: "3 / 4",
|
|
1630
|
+
borderRadius: 24,
|
|
1458
1631
|
overflow: "hidden",
|
|
1459
|
-
background: "#
|
|
1632
|
+
background: "#000000",
|
|
1633
|
+
border: "4px solid rgba(255, 255, 255, 0.08)",
|
|
1634
|
+
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.5)"
|
|
1635
|
+
};
|
|
1636
|
+
var overlayCloseButtonStyle = {
|
|
1637
|
+
position: "absolute",
|
|
1638
|
+
top: 12,
|
|
1639
|
+
right: 12,
|
|
1640
|
+
width: 32,
|
|
1641
|
+
height: 32,
|
|
1642
|
+
display: "inline-flex",
|
|
1643
|
+
alignItems: "center",
|
|
1644
|
+
justifyContent: "center",
|
|
1645
|
+
padding: 0,
|
|
1646
|
+
border: "none",
|
|
1647
|
+
borderRadius: "50%",
|
|
1648
|
+
background: "rgba(0, 0, 0, 0.4)",
|
|
1649
|
+
backdropFilter: "blur(6px)",
|
|
1650
|
+
color: "#ffffff",
|
|
1651
|
+
cursor: "pointer",
|
|
1652
|
+
zIndex: 10
|
|
1653
|
+
};
|
|
1654
|
+
var bottomGradientStyle = {
|
|
1655
|
+
position: "absolute",
|
|
1656
|
+
bottom: 0,
|
|
1657
|
+
left: 0,
|
|
1658
|
+
right: 0,
|
|
1659
|
+
padding: "16px",
|
|
1660
|
+
background: "linear-gradient(to top, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0) 100%)",
|
|
1661
|
+
display: "flex",
|
|
1662
|
+
alignItems: "center",
|
|
1663
|
+
justifyContent: "center",
|
|
1664
|
+
zIndex: 10
|
|
1665
|
+
};
|
|
1666
|
+
var shutterButtonStyle = {
|
|
1667
|
+
width: 64,
|
|
1668
|
+
height: 64,
|
|
1669
|
+
borderRadius: "50%",
|
|
1670
|
+
background: "rgba(255, 255, 255, 0.15)",
|
|
1671
|
+
backdropFilter: "blur(6px)",
|
|
1672
|
+
border: "2px solid rgba(255, 255, 255, 0.7)",
|
|
1673
|
+
display: "inline-flex",
|
|
1674
|
+
alignItems: "center",
|
|
1675
|
+
justifyContent: "center",
|
|
1676
|
+
cursor: "pointer",
|
|
1677
|
+
padding: 0,
|
|
1678
|
+
transition: "transform 120ms ease-out, background 120ms"
|
|
1679
|
+
};
|
|
1680
|
+
var shutterInnerStyle = {
|
|
1681
|
+
display: "block",
|
|
1682
|
+
width: 44,
|
|
1683
|
+
height: 44,
|
|
1684
|
+
borderRadius: "50%",
|
|
1685
|
+
background: "rgba(255, 255, 255, 0.85)"
|
|
1460
1686
|
};
|
|
1461
1687
|
var videoStyle = {
|
|
1462
1688
|
width: "100%",
|
|
@@ -1500,7 +1726,9 @@ var videoLoadingStyle = {
|
|
|
1500
1726
|
justifyContent: "center",
|
|
1501
1727
|
color: "#e5e7eb",
|
|
1502
1728
|
fontSize: 14,
|
|
1503
|
-
fontWeight: 500
|
|
1729
|
+
fontWeight: 500,
|
|
1730
|
+
background: "rgba(0, 0, 0, 0.4)",
|
|
1731
|
+
zIndex: 5
|
|
1504
1732
|
};
|
|
1505
1733
|
var liveMessagePillContainerStyle = {
|
|
1506
1734
|
position: "absolute",
|
|
@@ -1865,9 +2093,9 @@ function getRiskColor(risk) {
|
|
|
1865
2093
|
};
|
|
1866
2094
|
return colorMap[risk] || "#6b7280";
|
|
1867
2095
|
}
|
|
1868
|
-
function
|
|
2096
|
+
function useEventBasedFaceVerificationSubmission(client$1) {
|
|
1869
2097
|
const startSession = React.useCallback(
|
|
1870
|
-
(request) => client$1.
|
|
2098
|
+
(request) => client$1.createEventBasedFaceVerificationSession(request),
|
|
1871
2099
|
[client$1]
|
|
1872
2100
|
);
|
|
1873
2101
|
const verifyFace = React.useCallback(
|
|
@@ -1884,6 +2112,7 @@ function useReuseKYCSubmission(client$1) {
|
|
|
1884
2112
|
session,
|
|
1885
2113
|
defaultDevice: opts.defaultDevice,
|
|
1886
2114
|
renderQR: opts.renderQR,
|
|
2115
|
+
onCancel: opts.onCancel,
|
|
1887
2116
|
onComplete: (result) => {
|
|
1888
2117
|
cleanup();
|
|
1889
2118
|
resolve(result);
|
|
@@ -1920,6 +2149,7 @@ exports.isValidFileSize = isValidFileSize;
|
|
|
1920
2149
|
exports.isValidFileType = isValidFileType;
|
|
1921
2150
|
exports.useCipherText = useCipherText;
|
|
1922
2151
|
exports.useCustomerProfile = useCustomerProfile;
|
|
2152
|
+
exports.useEventBasedFaceVerificationSubmission = useEventBasedFaceVerificationSubmission;
|
|
1923
2153
|
exports.useGeolocation = useGeolocation;
|
|
1924
2154
|
exports.useKycAlerts = useKycAlerts;
|
|
1925
2155
|
exports.useKycOverview = useKycOverview;
|
|
@@ -1930,7 +2160,6 @@ exports.useLocationCapture = useLocationCapture;
|
|
|
1930
2160
|
exports.useLocationRequests = useLocationRequests;
|
|
1931
2161
|
exports.useLoginVerification = useLoginVerification;
|
|
1932
2162
|
exports.useRegistration = useRegistration;
|
|
1933
|
-
exports.useReuseKYCSubmission = useReuseKYCSubmission;
|
|
1934
2163
|
exports.useTransactionVerification = useTransactionVerification;
|
|
1935
2164
|
//# sourceMappingURL=react.js.map
|
|
1936
2165
|
//# sourceMappingURL=react.js.map
|