vesant-sdk 1.7.0-dev.e0ee6d5 → 1.7.0-dev.e1da577
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/{client-ZNdnpWe7.d.mts → client-B0qhE2kr.d.mts} +1 -1
- package/dist/{client-DoMSYMMR.d.ts → client-DF7hlMEz.d.ts} +13 -0
- package/dist/{client-DMIRx7Tu.d.mts → client-DrjgZoH_.d.mts} +13 -0
- package/dist/{client-C3DCmGe9.d.ts → client-DtH2RLuy.d.ts} +1 -1
- package/dist/compliance/index.d.mts +2 -2
- package/dist/compliance/index.d.ts +2 -2
- package/dist/compliance/index.js +0 -3
- package/dist/compliance/index.js.map +1 -1
- package/dist/compliance/index.mjs +0 -3
- package/dist/compliance/index.mjs.map +1 -1
- package/dist/geolocation/index.d.mts +2 -2
- package/dist/geolocation/index.d.ts +2 -2
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +40 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +40 -22
- 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 +36 -18
- package/dist/kyc/core.js.map +1 -1
- package/dist/kyc/core.mjs +36 -18
- package/dist/kyc/core.mjs.map +1 -1
- package/dist/kyc/index.d.mts +161 -58
- package/dist/kyc/index.d.ts +161 -58
- package/dist/kyc/index.js +36 -18
- package/dist/kyc/index.js.map +1 -1
- package/dist/kyc/index.mjs +36 -18
- package/dist/kyc/index.mjs.map +1 -1
- package/dist/react.d.mts +18 -14
- package/dist/react.d.ts +18 -14
- package/dist/react.js +303 -35
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +303 -35
- 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 +4 -1
- package/dist/tax/index.js.map +1 -1
- package/dist/tax/index.mjs +4 -1
- package/dist/tax/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react.mjs
CHANGED
|
@@ -882,10 +882,91 @@ function useCustomerProfile(client, customerId, options = {}) {
|
|
|
882
882
|
var Camera = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4NCg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjAvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvVFIvMjAwMS9SRUMtU1ZHLTIwMDEwOTA0L0RURC9zdmcxMC5kdGQiPg0KPCEtLSBVcGxvYWRlZCB0bzogU1ZHIFJlcG8sIHd3dy5zdmdyZXBvLmNvbSwgR2VuZXJhdG9yOiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4NCjxzdmcgdmVyc2lvbj0iMS4wIiBpZD0iTGF5ZXJfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgDQoJIHdpZHRoPSI4MDBweCIgaGVpZ2h0PSI4MDBweCIgdmlld0JveD0iMCAwIDY0IDY0IiBlbmFibGUtYmFja2dyb3VuZD0ibmV3IDAgMCA2NCA2NCIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+DQo8Zz4NCgk8cGF0aCBmaWxsPSIjMjMxRjIwIiBkPSJNNjAsMTBINDkuNjU2bC02LjgyOC02LjgyOEM0Mi4wNzgsMi40MjIsNDEuMDYyLDIsNDAsMkgyNGMtMS4wNjIsMC0yLjA3OCwwLjQyMi0yLjgyOCwxLjE3MkwxNC4zNDQsMTBINA0KCQljLTIuMjExLDAtNCwxLjc4OS00LDR2NDRjMCwyLjIxMSwxLjc4OSw0LDQsNGg1NmMyLjIxMSwwLDQtMS43ODksNC00VjE0QzY0LDExLjc4OSw2Mi4yMTEsMTAsNjAsMTB6IE0zMiw1MA0KCQljLTguODM2LDAtMTYtNy4xNjQtMTYtMTZzNy4xNjQtMTYsMTYtMTZzMTYsNy4xNjQsMTYsMTZTNDAuODM2LDUwLDMyLDUweiIvPg0KCTxjaXJjbGUgZmlsbD0iIzIzMUYyMCIgY3g9IjMyIiBjeT0iMzQiIHI9IjgiLz4NCjwvZz4NCjwvc3ZnPg==";
|
|
883
883
|
var Done = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPg0KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik04LjUgMTIuNUwxMC41IDE0LjVMMTUuNSA5LjUiIHN0cm9rZT0iIzFDMjc0QyIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPg0KPHBhdGggZD0iTTcgMy4zMzc4MkM4LjQ3MDg3IDIuNDg2OTcgMTAuMTc4NiAyIDEyIDJDMTcuNTIyOCAyIDIyIDYuNDc3MTUgMjIgMTJDMjIgMTcuNTIyOCAxNy41MjI4IDIyIDEyIDIyQzYuNDc3MTUgMjIgMiAxNy41MjI4IDIgMTJDMiAxMC4xNzg2IDIuNDg2OTcgOC40NzA4NyAzLjMzNzgyIDciIHN0cm9rZT0iIzFDMjc0QyIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPg0KPC9zdmc+";
|
|
884
884
|
var Close = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPg0KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik0xNC41IDkuNTAwMDJMOS41IDE0LjVNOS40OTk5OCA5LjVMMTQuNSAxNC41IiBzdHJva2U9IiMxQzI3NEMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4NCjxwYXRoIGQ9Ik03IDMuMzM3ODJDOC40NzA4NyAyLjQ4Njk3IDEwLjE3ODYgMiAxMiAyQzE3LjUyMjggMiAyMiA2LjQ3NzE1IDIyIDEyQzIyIDE3LjUyMjggMTcuNTIyOCAyMiAxMiAyMkM2LjQ3NzE1IDIyIDIgMTcuNTIyOCAyIDEyQzIgMTAuMTc4NiAyLjQ4Njk3IDguNDcwODcgMy4zMzc4MiA3IiBzdHJva2U9IiMxQzI3NEMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4NCjwvc3ZnPg==";
|
|
885
|
-
|
|
885
|
+
|
|
886
|
+
// src/kyc/faceDetection.ts
|
|
887
|
+
var FACE_MESSAGES = {
|
|
888
|
+
idle: "Initializing camera...",
|
|
889
|
+
loading: "Loading face detection...",
|
|
890
|
+
scanning: "Position your face in the circle",
|
|
891
|
+
too_far: "Face too far. Please move closer to the camera",
|
|
892
|
+
too_close: "Too close. Please move back a little",
|
|
893
|
+
off_center: "Center your face in the circle",
|
|
894
|
+
ok: "Looking great! Tap the button to capture"
|
|
895
|
+
};
|
|
896
|
+
var FACE_COLORS = {
|
|
897
|
+
idle: "#9ca3af",
|
|
898
|
+
loading: "#3b82f6",
|
|
899
|
+
scanning: "#3b82f6",
|
|
900
|
+
too_far: "#ef4444",
|
|
901
|
+
too_close: "#f59e0b",
|
|
902
|
+
off_center: "#f59e0b",
|
|
903
|
+
ok: "#10b981"
|
|
904
|
+
};
|
|
905
|
+
var MEDIAPIPE_BASE = "https://cdn.jsdelivr.net/npm/@mediapipe/face_detection";
|
|
906
|
+
function mapDetectionsToFaceStatus(detections) {
|
|
907
|
+
if (detections.length === 0) return "scanning";
|
|
908
|
+
const bb = detections[0].boundingBox;
|
|
909
|
+
if (bb.width < 0.18) return "too_far";
|
|
910
|
+
if (bb.width > 0.72) return "too_close";
|
|
911
|
+
if (bb.xCenter < 0.28 || bb.xCenter > 0.72 || bb.yCenter < 0.28 || bb.yCenter > 0.72) {
|
|
912
|
+
return "off_center";
|
|
913
|
+
}
|
|
914
|
+
return "ok";
|
|
915
|
+
}
|
|
916
|
+
function isCaptureDisabled(ready, detectionActive, faceStatus) {
|
|
917
|
+
return !ready || detectionActive && faceStatus !== "ok";
|
|
918
|
+
}
|
|
919
|
+
function resolveMediaPipeBase(base) {
|
|
920
|
+
if (!base) return MEDIAPIPE_BASE;
|
|
921
|
+
return base.endsWith("/") ? base.slice(0, -1) : base;
|
|
922
|
+
}
|
|
923
|
+
var LIVENESS_SAMPLE_LIMIT = 20;
|
|
924
|
+
function buildLivenessArtifact(samples) {
|
|
925
|
+
if (samples.length === 0) return void 0;
|
|
926
|
+
return JSON.stringify({
|
|
927
|
+
version: 1,
|
|
928
|
+
source: "mediapipe-face-detection",
|
|
929
|
+
samples: samples.slice(-LIVENESS_SAMPLE_LIMIT)
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
var mediapipeLoaderPromises = /* @__PURE__ */ new Map();
|
|
933
|
+
function loadMediaPipeFaceDetection(assetBasePath) {
|
|
934
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
935
|
+
return Promise.reject(new Error("MediaPipe requires a browser environment"));
|
|
936
|
+
}
|
|
937
|
+
const w = window;
|
|
938
|
+
if (w.FaceDetection) {
|
|
939
|
+
return Promise.resolve(w.FaceDetection);
|
|
940
|
+
}
|
|
941
|
+
const src = `${resolveMediaPipeBase(assetBasePath)}/face_detection.js`;
|
|
942
|
+
const existing = mediapipeLoaderPromises.get(src);
|
|
943
|
+
if (existing) return existing;
|
|
944
|
+
const loader = new Promise((resolve, reject) => {
|
|
945
|
+
const script = document.createElement("script");
|
|
946
|
+
script.src = src;
|
|
947
|
+
script.async = true;
|
|
948
|
+
script.crossOrigin = "anonymous";
|
|
949
|
+
script.onload = () => {
|
|
950
|
+
if (w.FaceDetection) {
|
|
951
|
+
resolve(w.FaceDetection);
|
|
952
|
+
} else {
|
|
953
|
+
mediapipeLoaderPromises.delete(src);
|
|
954
|
+
reject(new Error("MediaPipe loaded but FaceDetection global is missing"));
|
|
955
|
+
}
|
|
956
|
+
};
|
|
957
|
+
script.onerror = () => {
|
|
958
|
+
mediapipeLoaderPromises.delete(src);
|
|
959
|
+
reject(new Error("Failed to load MediaPipe face_detection script"));
|
|
960
|
+
};
|
|
961
|
+
document.head.appendChild(script);
|
|
962
|
+
});
|
|
963
|
+
mediapipeLoaderPromises.set(src, loader);
|
|
964
|
+
return loader;
|
|
965
|
+
}
|
|
886
966
|
|
|
887
967
|
// src/kyc/FaceCaptureModal.tsx
|
|
888
968
|
var MOBILE_UA = /Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
|
|
969
|
+
var SESSION_EXPIRY_MS = 15 * 60 * 1e3;
|
|
889
970
|
var LIVENESS_MESSAGES = [
|
|
890
971
|
"Position your face inside the circle",
|
|
891
972
|
"Make sure your face is well lit",
|
|
@@ -899,9 +980,9 @@ function headerSubtitle(stageKind) {
|
|
|
899
980
|
case "accepted":
|
|
900
981
|
return "All set";
|
|
901
982
|
case "declined":
|
|
902
|
-
return "Verification
|
|
983
|
+
return "Verification Declined";
|
|
903
984
|
case "max_attempts":
|
|
904
|
-
return "We couldn't verify
|
|
985
|
+
return "We couldn't verify your identity";
|
|
905
986
|
default:
|
|
906
987
|
return "Please capture a clear photo of your face";
|
|
907
988
|
}
|
|
@@ -914,16 +995,19 @@ function FaceCaptureModal({
|
|
|
914
995
|
client,
|
|
915
996
|
session,
|
|
916
997
|
onComplete,
|
|
998
|
+
onCancel,
|
|
917
999
|
defaultDevice,
|
|
918
|
-
renderQR
|
|
1000
|
+
renderQR,
|
|
1001
|
+
mediapipeAssetBasePath
|
|
919
1002
|
}) {
|
|
920
1003
|
const isMobile = typeof navigator !== "undefined" && MOBILE_UA.test(navigator.userAgent);
|
|
1004
|
+
const initialChoice = defaultDevice ?? (isMobile ? "this" : "ask");
|
|
921
1005
|
const initialStage = (() => {
|
|
922
|
-
|
|
923
|
-
if (
|
|
924
|
-
if (choice === "mobile") return { kind: "qr", mobileConnected: false };
|
|
1006
|
+
if (initialChoice === "this") return { kind: "capture" };
|
|
1007
|
+
if (initialChoice === "mobile") return { kind: "qr", mobileConnected: false };
|
|
925
1008
|
return { kind: "choose" };
|
|
926
1009
|
})();
|
|
1010
|
+
const hasMethodChoice = initialChoice === "ask";
|
|
927
1011
|
const [stage, setStage] = useState(initialStage);
|
|
928
1012
|
const [attempts, setAttempts] = useState(session.attempts);
|
|
929
1013
|
const maxAttempts = session.max_attempts || 1;
|
|
@@ -931,21 +1015,30 @@ function FaceCaptureModal({
|
|
|
931
1015
|
const [captureMode, setCaptureMode] = useState("idle");
|
|
932
1016
|
const [capturedPreview, setCapturedPreview] = useState(null);
|
|
933
1017
|
const [capturedBase64, setCapturedBase64] = useState(null);
|
|
1018
|
+
const [capturedArtifact, setCapturedArtifact] = useState(null);
|
|
934
1019
|
const [livenessMessage, setLivenessMessage] = useState(LIVENESS_MESSAGES[0]);
|
|
935
1020
|
const qrPayload = session.link || `vesant://reuse-kyc?token=${encodeURIComponent(session.token)}`;
|
|
936
1021
|
const cancelledRef = useRef(false);
|
|
937
1022
|
const submittingRef = useRef(false);
|
|
1023
|
+
useEffect(() => {
|
|
1024
|
+
const timer = setTimeout(() => {
|
|
1025
|
+
setStage(
|
|
1026
|
+
(prev) => prev.kind === "choose" || prev.kind === "qr" || prev.kind === "capture" ? { kind: "error", message: "Session expired" } : prev
|
|
1027
|
+
);
|
|
1028
|
+
}, SESSION_EXPIRY_MS);
|
|
1029
|
+
return () => clearTimeout(timer);
|
|
1030
|
+
}, [session.token]);
|
|
938
1031
|
useEffect(() => {
|
|
939
1032
|
if (stage.kind !== "qr") return;
|
|
940
1033
|
let stopped = false;
|
|
941
1034
|
const intervalMs = 2e3;
|
|
942
|
-
const deadline = Date.now() +
|
|
1035
|
+
const deadline = Date.now() + SESSION_EXPIRY_MS;
|
|
943
1036
|
let mobileSeen = stage.mobileConnected;
|
|
944
1037
|
const tick = async () => {
|
|
945
1038
|
if (stopped || cancelledRef.current) return;
|
|
946
1039
|
try {
|
|
947
1040
|
if (mobileSeen) {
|
|
948
|
-
const result = await client.
|
|
1041
|
+
const result = await client.getEventBasedFaceVerificationSessionStatus(session.token);
|
|
949
1042
|
if (result.status === "accepted") {
|
|
950
1043
|
setStage({ kind: "accepted", result });
|
|
951
1044
|
stopped = true;
|
|
@@ -1017,10 +1110,13 @@ function FaceCaptureModal({
|
|
|
1017
1110
|
try {
|
|
1018
1111
|
const postPromise = (async () => {
|
|
1019
1112
|
try {
|
|
1020
|
-
const data = await client.
|
|
1113
|
+
const data = await client.submitEventBasedFaceVerificationSession({
|
|
1021
1114
|
token: session.token,
|
|
1022
1115
|
reference: ref,
|
|
1023
|
-
proof
|
|
1116
|
+
proof,
|
|
1117
|
+
// undefined when detection wasn't running for this capture —
|
|
1118
|
+
// JSON.stringify drops it, so the field is absent on the wire.
|
|
1119
|
+
liveness_artifact: capturedArtifact ?? void 0
|
|
1024
1120
|
});
|
|
1025
1121
|
return { ok: true, data };
|
|
1026
1122
|
} catch (err2) {
|
|
@@ -1033,7 +1129,7 @@ function FaceCaptureModal({
|
|
|
1033
1129
|
while (Date.now() < deadline) {
|
|
1034
1130
|
if (settled || cancelledRef.current) return null;
|
|
1035
1131
|
try {
|
|
1036
|
-
const r = await client.
|
|
1132
|
+
const r = await client.getEventBasedFaceVerificationSessionStatus(session.token);
|
|
1037
1133
|
if (isFreshPollResult(r)) return r;
|
|
1038
1134
|
} catch {
|
|
1039
1135
|
}
|
|
@@ -1066,16 +1162,18 @@ function FaceCaptureModal({
|
|
|
1066
1162
|
submittingRef.current = false;
|
|
1067
1163
|
}
|
|
1068
1164
|
};
|
|
1069
|
-
const handleCameraCapture = (dataUrl) => {
|
|
1165
|
+
const handleCameraCapture = (dataUrl, livenessArtifact) => {
|
|
1070
1166
|
const raw = dataUrl.split(",")[1] ?? "";
|
|
1071
1167
|
setCapturedPreview(dataUrl);
|
|
1072
1168
|
setCapturedBase64(raw);
|
|
1169
|
+
setCapturedArtifact(livenessArtifact ?? null);
|
|
1073
1170
|
setCaptureMode("preview");
|
|
1074
1171
|
};
|
|
1075
1172
|
const handleCameraCancel = () => setCaptureMode("idle");
|
|
1076
1173
|
const handleRetake = () => {
|
|
1077
1174
|
setCapturedPreview(null);
|
|
1078
1175
|
setCapturedBase64(null);
|
|
1176
|
+
setCapturedArtifact(null);
|
|
1079
1177
|
setCaptureMode("live");
|
|
1080
1178
|
};
|
|
1081
1179
|
const handleConfirmSubmit = () => {
|
|
@@ -1104,6 +1202,9 @@ function FaceCaptureModal({
|
|
|
1104
1202
|
}, [captureMode]);
|
|
1105
1203
|
const close = (result) => {
|
|
1106
1204
|
cancelledRef.current = true;
|
|
1205
|
+
if (result === null && onCancel) {
|
|
1206
|
+
onCancel();
|
|
1207
|
+
}
|
|
1107
1208
|
onComplete(result);
|
|
1108
1209
|
};
|
|
1109
1210
|
const renderChoose = () => /* @__PURE__ */ React.createElement("div", { style: contentStyle }, /* @__PURE__ */ React.createElement("div", { style: visualGuideContainerStyle }, /* @__PURE__ */ React.createElement("div", { style: visualGuideStyle }, /* @__PURE__ */ React.createElement("div", { style: circleStyle }, /* @__PURE__ */ React.createElement("img", { src: Camera, alt: "", width: 48, height: 48 })))), /* @__PURE__ */ React.createElement("p", { style: subtitleStyle }, "How would you like to verify?"), /* @__PURE__ */ React.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React.createElement(
|
|
@@ -1112,7 +1213,7 @@ function FaceCaptureModal({
|
|
|
1112
1213
|
style: primaryButtonStyle,
|
|
1113
1214
|
onClick: () => setStage({ kind: "capture" })
|
|
1114
1215
|
},
|
|
1115
|
-
/* @__PURE__ */ React.createElement("img", { src:
|
|
1216
|
+
/* @__PURE__ */ React.createElement("img", { src: Camera, alt: "", width: 20, height: 20 }),
|
|
1116
1217
|
/* @__PURE__ */ React.createElement("span", null, "Continue on this device")
|
|
1117
1218
|
), /* @__PURE__ */ React.createElement(
|
|
1118
1219
|
"button",
|
|
@@ -1129,6 +1230,13 @@ function FaceCaptureModal({
|
|
|
1129
1230
|
onClick: () => setStage({ kind: "capture" })
|
|
1130
1231
|
},
|
|
1131
1232
|
"Use this device instead"
|
|
1233
|
+
), hasMethodChoice && /* @__PURE__ */ React.createElement(
|
|
1234
|
+
"button",
|
|
1235
|
+
{
|
|
1236
|
+
style: secondaryButtonStyle,
|
|
1237
|
+
onClick: () => setStage({ kind: "choose" })
|
|
1238
|
+
},
|
|
1239
|
+
"Change verification method"
|
|
1132
1240
|
), /* @__PURE__ */ React.createElement("button", { style: cancelButtonStyle, onClick: () => close(null) }, "Cancel")));
|
|
1133
1241
|
const renderCapture = (declinedReason) => {
|
|
1134
1242
|
if (captureMode === "live") {
|
|
@@ -1137,20 +1245,31 @@ function FaceCaptureModal({
|
|
|
1137
1245
|
{
|
|
1138
1246
|
onCapture: handleCameraCapture,
|
|
1139
1247
|
onCancel: handleCameraCancel,
|
|
1140
|
-
message: livenessMessage
|
|
1248
|
+
message: livenessMessage,
|
|
1249
|
+
assetBasePath: mediapipeAssetBasePath
|
|
1141
1250
|
}
|
|
1142
1251
|
), /* @__PURE__ */ React.createElement("p", { style: attemptsTextStyle }, "Attempt ", attempts + 1, " of ", maxAttempts));
|
|
1143
1252
|
}
|
|
1144
1253
|
if (captureMode === "preview" && capturedPreview) {
|
|
1145
1254
|
return /* @__PURE__ */ React.createElement("div", { style: contentStyle }, declinedReason && /* @__PURE__ */ React.createElement("div", { style: alertBoxStyle }, /* @__PURE__ */ React.createElement("strong", null, "Verification declined."), /* @__PURE__ */ React.createElement("p", { style: alertTextStyle }, declinedReason)), /* @__PURE__ */ React.createElement("p", { style: subtitleStyle }, "Looks good? Submit this selfie or retake it."), /* @__PURE__ */ React.createElement("div", { style: previewBoxStyle }, /* @__PURE__ */ React.createElement("img", { src: capturedPreview, alt: "Captured selfie preview", style: previewImgStyle })), /* @__PURE__ */ React.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React.createElement("button", { style: primaryButtonStyle, onClick: handleConfirmSubmit }, /* @__PURE__ */ React.createElement("img", { src: Done, alt: "", width: 20, height: 20 }), /* @__PURE__ */ React.createElement("span", null, "Submit")), /* @__PURE__ */ React.createElement("button", { style: secondaryButtonStyle, onClick: handleRetake }, "Retake"), /* @__PURE__ */ React.createElement("button", { style: cancelButtonStyle, onClick: () => close(null) }, "Cancel")), /* @__PURE__ */ React.createElement("p", { style: attemptsTextStyle }, "Attempt ", attempts + 1, " of ", maxAttempts));
|
|
1146
1255
|
}
|
|
1147
|
-
return /* @__PURE__ */ React.createElement("div", { style: contentStyle }, /* @__PURE__ */ React.createElement("div", { style: visualGuideContainerStyle }, /* @__PURE__ */ React.createElement("div", { style: visualGuideStyle }, /* @__PURE__ */ React.createElement("div", { style: circleStyle }, /* @__PURE__ */ React.createElement("img", { src: Camera, alt: "", width: 48, height: 48 })), /* @__PURE__ */ React.createElement("div", { style: badgeStyle }, /* @__PURE__ */ React.createElement("img", { src: Done, alt: "", width: 16, height: 16 })))), declinedReason && /* @__PURE__ */ React.createElement("div", { style: alertBoxStyle }, /* @__PURE__ */ React.createElement("strong", null, "Verification declined."), /* @__PURE__ */ React.createElement("p", { style: alertTextStyle }, declinedReason)), /* @__PURE__ */ React.createElement("div", { style: instructionsBoxStyle }, /* @__PURE__ */ React.createElement("h3", { style: instructionsTitleStyle }, "Tips for best results:"), /* @__PURE__ */ React.createElement("ul", { style: instructionsListStyle }, /* @__PURE__ */ React.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React.createElement("span", null, "Ensure good lighting on your face")), /* @__PURE__ */ React.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React.createElement("span", null, "Remove glasses or accessories if possible")), /* @__PURE__ */ React.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React.createElement("span", null, "Look directly at the camera")))), /* @__PURE__ */ React.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React.createElement("button", { style: primaryButtonStyle, onClick: handleOpenCamera }, /* @__PURE__ */ React.createElement("img", { src: Camera, alt: "", width: 20, height: 20 }), /* @__PURE__ */ React.createElement("span", null, declinedReason ? "Try
|
|
1256
|
+
return /* @__PURE__ */ React.createElement("div", { style: contentStyle }, /* @__PURE__ */ React.createElement("div", { style: visualGuideContainerStyle }, /* @__PURE__ */ React.createElement("div", { style: visualGuideStyle }, /* @__PURE__ */ React.createElement("div", { style: circleStyle }, /* @__PURE__ */ React.createElement("img", { src: Camera, alt: "", width: 48, height: 48 })), /* @__PURE__ */ React.createElement("div", { style: badgeStyle }, /* @__PURE__ */ React.createElement("img", { src: Done, alt: "", width: 16, height: 16 })))), declinedReason && /* @__PURE__ */ React.createElement("div", { style: alertBoxStyle }, /* @__PURE__ */ React.createElement("strong", null, "Verification declined."), /* @__PURE__ */ React.createElement("p", { style: alertTextStyle }, declinedReason)), /* @__PURE__ */ React.createElement("div", { style: instructionsBoxStyle }, /* @__PURE__ */ React.createElement("h3", { style: instructionsTitleStyle }, "Tips for best results:"), /* @__PURE__ */ React.createElement("ul", { style: instructionsListStyle }, /* @__PURE__ */ React.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React.createElement("span", null, "Ensure good lighting on your face")), /* @__PURE__ */ React.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React.createElement("span", null, "Remove glasses or accessories if possible")), /* @__PURE__ */ React.createElement("li", { style: instructionItemStyle }, /* @__PURE__ */ React.createElement("span", { style: bulletStyle }, "\u2022"), /* @__PURE__ */ React.createElement("span", null, "Look directly at the camera")))), /* @__PURE__ */ React.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React.createElement("button", { style: primaryButtonStyle, onClick: handleOpenCamera }, /* @__PURE__ */ React.createElement("img", { src: Camera, alt: "", width: 20, height: 20 }), /* @__PURE__ */ React.createElement("span", null, declinedReason ? "Try Again" : "Open Camera")), hasMethodChoice && /* @__PURE__ */ React.createElement(
|
|
1257
|
+
"button",
|
|
1258
|
+
{
|
|
1259
|
+
style: secondaryButtonStyle,
|
|
1260
|
+
onClick: () => setStage({ kind: "choose" })
|
|
1261
|
+
},
|
|
1262
|
+
"Change verification method"
|
|
1263
|
+
), /* @__PURE__ */ React.createElement("button", { style: cancelButtonStyle, onClick: () => close(null) }, "Cancel")), /* @__PURE__ */ React.createElement("p", { style: attemptsTextStyle }, "Attempt ", attempts + 1, " of ", maxAttempts));
|
|
1148
1264
|
};
|
|
1149
1265
|
const renderSubmitting = () => /* @__PURE__ */ React.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center" } }, /* @__PURE__ */ React.createElement("div", { style: { ...spinnerStyle, margin: "24px auto", width: 32, height: 32 } }), /* @__PURE__ */ React.createElement("p", { style: subtitleStyle }, "Verifying your photo\u2026"), /* @__PURE__ */ React.createElement("p", { style: { ...attemptsTextStyle, marginTop: 8 } }, "This usually takes a few seconds."));
|
|
1150
1266
|
const renderAccepted = (result) => /* @__PURE__ */ React.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center" } }, /* @__PURE__ */ React.createElement("div", { style: successCircleStyle }, /* @__PURE__ */ React.createElement("img", { src: Done, alt: "", width: 48, height: 48 })), /* @__PURE__ */ React.createElement("h3", { style: titleStyle }, "Verified"), /* @__PURE__ */ React.createElement("p", { style: subtitleStyle }, "Your identity has been confirmed. You can continue."), /* @__PURE__ */ React.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React.createElement("button", { style: primaryButtonStyle, onClick: () => close(result) }, "Continue")));
|
|
1151
|
-
const renderDeclined = (result) => /* @__PURE__ */ React.createElement("div", { style: contentStyle }, /* @__PURE__ */ React.createElement("div", { style: alertBoxStyle }, /* @__PURE__ */ React.createElement("
|
|
1152
|
-
const renderMaxAttempts = (result) => /* @__PURE__ */ React.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center" } }, /* @__PURE__ */ React.createElement("div", { style: errorCircleStyle }, "!"), /* @__PURE__ */ React.createElement("h3", { style: titleStyle }, "Maximum
|
|
1153
|
-
const renderError = (message) =>
|
|
1267
|
+
const renderDeclined = (result) => /* @__PURE__ */ React.createElement("div", { style: contentStyle }, /* @__PURE__ */ React.createElement("div", { style: alertBoxStyle }, /* @__PURE__ */ React.createElement("p", { style: alertTextStyle }, result.declined_reason ?? "We couldn't match your selfie. Please take a new one.")), /* @__PURE__ */ React.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React.createElement("button", { style: primaryButtonStyle, onClick: handleRetakeAfterDecline }, /* @__PURE__ */ React.createElement("img", { src: Camera, alt: "", width: 20, height: 20 }), /* @__PURE__ */ React.createElement("span", null, "Retake")), /* @__PURE__ */ React.createElement("button", { style: cancelButtonStyle, onClick: () => close(result) }, "Cancel")), /* @__PURE__ */ React.createElement("p", { style: attemptsTextStyle }, "Attempt ", Math.min(attempts + 1, maxAttempts), " of ", maxAttempts));
|
|
1268
|
+
const renderMaxAttempts = (result) => /* @__PURE__ */ React.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center" } }, /* @__PURE__ */ React.createElement("div", { style: errorCircleStyle }, "!"), /* @__PURE__ */ React.createElement("h3", { style: titleStyle }, "Maximum Attempts Reached"), /* @__PURE__ */ React.createElement("p", { style: subtitleStyle }, result.declined_reason ?? "We couldn't verify your identity after several attempts."), result.data?.freeze_account && /* @__PURE__ */ React.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.createElement("p", { style: alertTextStyle }, "You will be signed out of your session."), result.data?.block && /* @__PURE__ */ React.createElement("p", { style: alertTextStyle }, "This action has been blocked for security reasons."), /* @__PURE__ */ React.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React.createElement("button", { style: primaryButtonStyle, onClick: () => close(result) }, "Close")));
|
|
1269
|
+
const renderError = (message) => {
|
|
1270
|
+
const sessionExpired = /session\s+expired/i.test(message);
|
|
1271
|
+
return /* @__PURE__ */ React.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center" } }, /* @__PURE__ */ React.createElement("div", { style: errorCircleStyle }, "!"), /* @__PURE__ */ React.createElement("h3", { style: titleStyle }, sessionExpired ? "Session expired" : "Something Went Wrong"), /* @__PURE__ */ React.createElement("p", { style: alertTextStyle }, sessionExpired ? "Your verification session is no longer valid. Please start a new verification from the beginning." : message), /* @__PURE__ */ React.createElement("div", { style: buttonsContainerStyle }, !sessionExpired && /* @__PURE__ */ React.createElement("button", { style: primaryButtonStyle, onClick: () => setStage({ kind: "capture" }) }, "Try Again"), /* @__PURE__ */ React.createElement("button", { style: cancelButtonStyle, onClick: () => close(null) }, sessionExpired ? "Close" : "Cancel")));
|
|
1272
|
+
};
|
|
1154
1273
|
const body = (() => {
|
|
1155
1274
|
switch (stage.kind) {
|
|
1156
1275
|
case "choose":
|
|
@@ -1358,11 +1477,14 @@ var attemptsTextStyle = {
|
|
|
1358
1477
|
};
|
|
1359
1478
|
var footerStyle = { padding: "12px 24px 16px", borderTop: "1px solid #f3f4f6" };
|
|
1360
1479
|
var footerTextStyle = { margin: 0, fontSize: 12, color: "#9ca3af", textAlign: "center" };
|
|
1361
|
-
function LiveCamera({ onCapture, onCancel, message }) {
|
|
1480
|
+
function LiveCamera({ onCapture, onCancel, message, assetBasePath }) {
|
|
1362
1481
|
const videoRef = useRef(null);
|
|
1363
1482
|
const streamRef = useRef(null);
|
|
1483
|
+
const samplesRef = useRef([]);
|
|
1364
1484
|
const [ready, setReady] = useState(false);
|
|
1365
1485
|
const [error, setError] = useState(null);
|
|
1486
|
+
const [faceStatus, setFaceStatus] = useState("idle");
|
|
1487
|
+
const [faceDetectionFailed, setFaceDetectionFailed] = useState(false);
|
|
1366
1488
|
useEffect(() => {
|
|
1367
1489
|
let cancelled = false;
|
|
1368
1490
|
async function init() {
|
|
@@ -1403,6 +1525,75 @@ function LiveCamera({ onCapture, onCancel, message }) {
|
|
|
1403
1525
|
streamRef.current = null;
|
|
1404
1526
|
};
|
|
1405
1527
|
}, []);
|
|
1528
|
+
useEffect(() => {
|
|
1529
|
+
if (!ready) {
|
|
1530
|
+
setFaceStatus("idle");
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
let cancelled = false;
|
|
1534
|
+
let rafId = null;
|
|
1535
|
+
let detector = null;
|
|
1536
|
+
setFaceStatus("loading");
|
|
1537
|
+
setFaceDetectionFailed(false);
|
|
1538
|
+
samplesRef.current = [];
|
|
1539
|
+
(async () => {
|
|
1540
|
+
try {
|
|
1541
|
+
const FaceDetection = await loadMediaPipeFaceDetection(assetBasePath);
|
|
1542
|
+
if (cancelled) return;
|
|
1543
|
+
const assetBase = resolveMediaPipeBase(assetBasePath);
|
|
1544
|
+
const d = new FaceDetection({
|
|
1545
|
+
locateFile: (f) => `${assetBase}/${f}`
|
|
1546
|
+
});
|
|
1547
|
+
d.setOptions({ model: "short", minDetectionConfidence: 0.5 });
|
|
1548
|
+
d.onResults((results) => {
|
|
1549
|
+
if (cancelled) return;
|
|
1550
|
+
const detections = results.detections ?? [];
|
|
1551
|
+
const status = mapDetectionsToFaceStatus(detections);
|
|
1552
|
+
samplesRef.current.push({
|
|
1553
|
+
t: Date.now(),
|
|
1554
|
+
status,
|
|
1555
|
+
...detections.length > 0 ? { boundingBox: detections[0].boundingBox } : {}
|
|
1556
|
+
});
|
|
1557
|
+
if (samplesRef.current.length > LIVENESS_SAMPLE_LIMIT) {
|
|
1558
|
+
samplesRef.current.shift();
|
|
1559
|
+
}
|
|
1560
|
+
setFaceStatus(status);
|
|
1561
|
+
});
|
|
1562
|
+
await d.initialize();
|
|
1563
|
+
if (cancelled) return;
|
|
1564
|
+
detector = d;
|
|
1565
|
+
setFaceStatus("scanning");
|
|
1566
|
+
const tick = async () => {
|
|
1567
|
+
if (cancelled) return;
|
|
1568
|
+
const v = videoRef.current;
|
|
1569
|
+
if (v?.readyState === 4 && detector) {
|
|
1570
|
+
try {
|
|
1571
|
+
await detector.send({ image: v });
|
|
1572
|
+
} catch {
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
if (!cancelled) {
|
|
1576
|
+
rafId = requestAnimationFrame(tick);
|
|
1577
|
+
}
|
|
1578
|
+
};
|
|
1579
|
+
tick();
|
|
1580
|
+
} catch (err) {
|
|
1581
|
+
console.error("Face detection failed to initialize:", err);
|
|
1582
|
+
if (!cancelled) {
|
|
1583
|
+
setFaceDetectionFailed(true);
|
|
1584
|
+
setFaceStatus("scanning");
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
})();
|
|
1588
|
+
return () => {
|
|
1589
|
+
cancelled = true;
|
|
1590
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
1591
|
+
try {
|
|
1592
|
+
detector?.close?.();
|
|
1593
|
+
} catch {
|
|
1594
|
+
}
|
|
1595
|
+
};
|
|
1596
|
+
}, [ready, assetBasePath]);
|
|
1406
1597
|
const capture = () => {
|
|
1407
1598
|
const video = videoRef.current;
|
|
1408
1599
|
if (!video || !video.videoWidth) return;
|
|
@@ -1419,12 +1610,22 @@ function LiveCamera({ onCapture, onCancel, message }) {
|
|
|
1419
1610
|
ctx.drawImage(video, sx, sy, size, size, 0, 0, size, size);
|
|
1420
1611
|
streamRef.current?.getTracks().forEach((t) => t.stop());
|
|
1421
1612
|
streamRef.current = null;
|
|
1422
|
-
onCapture(canvas.toDataURL("image/jpeg", 0.9));
|
|
1613
|
+
onCapture(canvas.toDataURL("image/jpeg", 0.9), buildLivenessArtifact(samplesRef.current));
|
|
1423
1614
|
};
|
|
1424
1615
|
if (error) {
|
|
1425
1616
|
return /* @__PURE__ */ React.createElement("div", { style: { ...contentStyle, alignItems: "center", textAlign: "center", padding: 0 } }, /* @__PURE__ */ React.createElement("div", { style: errorCircleStyle }, "!"), /* @__PURE__ */ React.createElement("h3", { style: titleStyle }, "Camera unavailable"), /* @__PURE__ */ React.createElement("p", { style: alertTextStyle }, error), /* @__PURE__ */ React.createElement("div", { style: buttonsContainerStyle }, /* @__PURE__ */ React.createElement("button", { style: secondaryButtonStyle, onClick: onCancel }, "Back")));
|
|
1426
1617
|
}
|
|
1427
|
-
|
|
1618
|
+
const detectionActive = ready && !faceDetectionFailed;
|
|
1619
|
+
const liveMessage = detectionActive ? FACE_MESSAGES[faceStatus] : message;
|
|
1620
|
+
const liveFaceColor = detectionActive ? FACE_COLORS[faceStatus] : void 0;
|
|
1621
|
+
const captureDisabled = isCaptureDisabled(ready, detectionActive, faceStatus);
|
|
1622
|
+
const ringPulse = detectionActive && (faceStatus === "too_far" || faceStatus === "too_close") ? "pulse 1.5s ease-in-out infinite" : void 0;
|
|
1623
|
+
const dynamicCircleStyle = {
|
|
1624
|
+
...faceCircleStyle,
|
|
1625
|
+
...liveFaceColor ? { borderColor: liveFaceColor } : null,
|
|
1626
|
+
...ringPulse ? { animation: ringPulse } : null
|
|
1627
|
+
};
|
|
1628
|
+
return /* @__PURE__ */ React.createElement("div", { style: videoFrameStyle }, /* @__PURE__ */ React.createElement(
|
|
1428
1629
|
"video",
|
|
1429
1630
|
{
|
|
1430
1631
|
ref: videoRef,
|
|
@@ -1433,24 +1634,87 @@ function LiveCamera({ onCapture, onCancel, message }) {
|
|
|
1433
1634
|
autoPlay: true,
|
|
1434
1635
|
style: videoStyle
|
|
1435
1636
|
}
|
|
1436
|
-
), /* @__PURE__ */ React.createElement("div", { style: faceOverlayContainerStyle, "aria-hidden": "true" }, /* @__PURE__ */ React.createElement("div", { style: faceRingWrapStyle }, /* @__PURE__ */ React.createElement("div", { style: faceDashedRingStyle }), /* @__PURE__ */ React.createElement("div", { style:
|
|
1637
|
+
), /* @__PURE__ */ React.createElement("div", { style: faceOverlayContainerStyle, "aria-hidden": "true" }, /* @__PURE__ */ React.createElement("div", { style: faceRingWrapStyle }, /* @__PURE__ */ React.createElement("div", { style: faceDashedRingStyle }), /* @__PURE__ */ React.createElement("div", { style: dynamicCircleStyle }))), liveMessage && /* @__PURE__ */ React.createElement("div", { style: liveMessagePillContainerStyle }, /* @__PURE__ */ React.createElement("div", { style: liveMessagePillStyle }, /* @__PURE__ */ React.createElement("span", { style: liveMessagePillTextStyle }, liveMessage))), /* @__PURE__ */ React.createElement(
|
|
1638
|
+
"button",
|
|
1639
|
+
{
|
|
1640
|
+
type: "button",
|
|
1641
|
+
onClick: onCancel,
|
|
1642
|
+
"aria-label": "Close camera",
|
|
1643
|
+
style: overlayCloseButtonStyle
|
|
1644
|
+
},
|
|
1645
|
+
/* @__PURE__ */ React.createElement("img", { src: Close, alt: "", width: 16, height: 16 })
|
|
1646
|
+
), !ready && /* @__PURE__ */ React.createElement("div", { style: videoLoadingStyle }, "Starting camera\u2026"), /* @__PURE__ */ React.createElement("div", { style: bottomGradientStyle }, /* @__PURE__ */ React.createElement(
|
|
1437
1647
|
"button",
|
|
1438
1648
|
{
|
|
1439
|
-
|
|
1649
|
+
type: "button",
|
|
1440
1650
|
onClick: capture,
|
|
1441
|
-
disabled:
|
|
1651
|
+
disabled: captureDisabled,
|
|
1652
|
+
"aria-label": "Capture",
|
|
1653
|
+
style: captureDisabled ? { ...shutterButtonStyle, opacity: 0.5, cursor: "not-allowed" } : shutterButtonStyle
|
|
1442
1654
|
},
|
|
1443
|
-
/* @__PURE__ */ React.createElement("
|
|
1444
|
-
|
|
1445
|
-
), /* @__PURE__ */ React.createElement("button", { style: secondaryButtonStyle, onClick: onCancel }, "Cancel")));
|
|
1655
|
+
/* @__PURE__ */ React.createElement("span", { style: shutterInnerStyle })
|
|
1656
|
+
)));
|
|
1446
1657
|
}
|
|
1447
1658
|
var videoFrameStyle = {
|
|
1448
1659
|
position: "relative",
|
|
1449
1660
|
width: "100%",
|
|
1450
|
-
aspectRatio: "
|
|
1451
|
-
borderRadius:
|
|
1661
|
+
aspectRatio: "3 / 4",
|
|
1662
|
+
borderRadius: 24,
|
|
1452
1663
|
overflow: "hidden",
|
|
1453
|
-
background: "#
|
|
1664
|
+
background: "#000000",
|
|
1665
|
+
border: "4px solid rgba(255, 255, 255, 0.08)",
|
|
1666
|
+
boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.5)"
|
|
1667
|
+
};
|
|
1668
|
+
var overlayCloseButtonStyle = {
|
|
1669
|
+
position: "absolute",
|
|
1670
|
+
top: 12,
|
|
1671
|
+
right: 12,
|
|
1672
|
+
width: 32,
|
|
1673
|
+
height: 32,
|
|
1674
|
+
display: "inline-flex",
|
|
1675
|
+
alignItems: "center",
|
|
1676
|
+
justifyContent: "center",
|
|
1677
|
+
padding: 0,
|
|
1678
|
+
border: "none",
|
|
1679
|
+
borderRadius: "50%",
|
|
1680
|
+
background: "rgba(0, 0, 0, 0.4)",
|
|
1681
|
+
backdropFilter: "blur(6px)",
|
|
1682
|
+
color: "#ffffff",
|
|
1683
|
+
cursor: "pointer",
|
|
1684
|
+
zIndex: 10
|
|
1685
|
+
};
|
|
1686
|
+
var bottomGradientStyle = {
|
|
1687
|
+
position: "absolute",
|
|
1688
|
+
bottom: 0,
|
|
1689
|
+
left: 0,
|
|
1690
|
+
right: 0,
|
|
1691
|
+
padding: "16px",
|
|
1692
|
+
background: "linear-gradient(to top, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0) 100%)",
|
|
1693
|
+
display: "flex",
|
|
1694
|
+
alignItems: "center",
|
|
1695
|
+
justifyContent: "center",
|
|
1696
|
+
zIndex: 10
|
|
1697
|
+
};
|
|
1698
|
+
var shutterButtonStyle = {
|
|
1699
|
+
width: 64,
|
|
1700
|
+
height: 64,
|
|
1701
|
+
borderRadius: "50%",
|
|
1702
|
+
background: "rgba(255, 255, 255, 0.15)",
|
|
1703
|
+
backdropFilter: "blur(6px)",
|
|
1704
|
+
border: "2px solid rgba(255, 255, 255, 0.7)",
|
|
1705
|
+
display: "inline-flex",
|
|
1706
|
+
alignItems: "center",
|
|
1707
|
+
justifyContent: "center",
|
|
1708
|
+
cursor: "pointer",
|
|
1709
|
+
padding: 0,
|
|
1710
|
+
transition: "transform 120ms ease-out, background 120ms"
|
|
1711
|
+
};
|
|
1712
|
+
var shutterInnerStyle = {
|
|
1713
|
+
display: "block",
|
|
1714
|
+
width: 44,
|
|
1715
|
+
height: 44,
|
|
1716
|
+
borderRadius: "50%",
|
|
1717
|
+
background: "rgba(255, 255, 255, 0.85)"
|
|
1454
1718
|
};
|
|
1455
1719
|
var videoStyle = {
|
|
1456
1720
|
width: "100%",
|
|
@@ -1494,7 +1758,9 @@ var videoLoadingStyle = {
|
|
|
1494
1758
|
justifyContent: "center",
|
|
1495
1759
|
color: "#e5e7eb",
|
|
1496
1760
|
fontSize: 14,
|
|
1497
|
-
fontWeight: 500
|
|
1761
|
+
fontWeight: 500,
|
|
1762
|
+
background: "rgba(0, 0, 0, 0.4)",
|
|
1763
|
+
zIndex: 5
|
|
1498
1764
|
};
|
|
1499
1765
|
var liveMessagePillContainerStyle = {
|
|
1500
1766
|
position: "absolute",
|
|
@@ -1859,9 +2125,9 @@ function getRiskColor(risk) {
|
|
|
1859
2125
|
};
|
|
1860
2126
|
return colorMap[risk] || "#6b7280";
|
|
1861
2127
|
}
|
|
1862
|
-
function
|
|
2128
|
+
function useEventBasedFaceVerificationSubmission(client) {
|
|
1863
2129
|
const startSession = useCallback(
|
|
1864
|
-
(request) => client.
|
|
2130
|
+
(request) => client.createEventBasedFaceVerificationSession(request),
|
|
1865
2131
|
[client]
|
|
1866
2132
|
);
|
|
1867
2133
|
const verifyFace = useCallback(
|
|
@@ -1878,6 +2144,8 @@ function useReuseKYCSubmission(client) {
|
|
|
1878
2144
|
session,
|
|
1879
2145
|
defaultDevice: opts.defaultDevice,
|
|
1880
2146
|
renderQR: opts.renderQR,
|
|
2147
|
+
onCancel: opts.onCancel,
|
|
2148
|
+
mediapipeAssetBasePath: opts.mediapipeAssetBasePath,
|
|
1881
2149
|
onComplete: (result) => {
|
|
1882
2150
|
cleanup();
|
|
1883
2151
|
resolve(result);
|
|
@@ -1904,6 +2172,6 @@ function useReuseKYCSubmission(client) {
|
|
|
1904
2172
|
return { startSession, verifyFace, runFlow };
|
|
1905
2173
|
}
|
|
1906
2174
|
|
|
1907
|
-
export { createDeviceFingerprint, fileToBase64, formatKycStatus, getBrowserInfo, getRiskColor, getStatusColor, isValidFileSize, isValidFileType, useCipherText, useCustomerProfile, useGeolocation, useKycAlerts, useKycOverview, useKycPreferences, useKycRequests, useKycSubmission, useLocationCapture, useLocationRequests, useLoginVerification, useRegistration,
|
|
2175
|
+
export { createDeviceFingerprint, fileToBase64, formatKycStatus, getBrowserInfo, getRiskColor, getStatusColor, isValidFileSize, isValidFileType, useCipherText, useCustomerProfile, useEventBasedFaceVerificationSubmission, useGeolocation, useKycAlerts, useKycOverview, useKycPreferences, useKycRequests, useKycSubmission, useLocationCapture, useLocationRequests, useLoginVerification, useRegistration, useTransactionVerification };
|
|
1908
2176
|
//# sourceMappingURL=react.mjs.map
|
|
1909
2177
|
//# sourceMappingURL=react.mjs.map
|