vesant-sdk 1.7.0-dev.059da4f → 1.7.0-dev.117915b
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 +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +1 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -13
- package/dist/index.mjs.map +1 -1
- package/dist/kyc/core.js.map +1 -1
- package/dist/kyc/core.mjs.map +1 -1
- package/dist/kyc/index.d.mts +29 -0
- package/dist/kyc/index.d.ts +29 -0
- package/dist/kyc/index.js.map +1 -1
- package/dist/kyc/index.mjs.map +1 -1
- package/dist/react.d.mts +4 -2
- package/dist/react.d.ts +4 -2
- package/dist/react.js +112 -73
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +112 -73
- package/dist/react.mjs.map +1 -1
- package/dist/tax/index.d.mts +1 -24
- package/dist/tax/index.d.ts +1 -24
- package/dist/tax/index.js +1 -10
- package/dist/tax/index.js.map +1 -1
- package/dist/tax/index.mjs +1 -10
- package/dist/tax/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react.js
CHANGED
|
@@ -889,6 +889,87 @@ var Camera = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0i
|
|
|
889
889
|
var Done = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPg0KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik04LjUgMTIuNUwxMC41IDE0LjVMMTUuNSA5LjUiIHN0cm9rZT0iIzFDMjc0QyIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIvPg0KPHBhdGggZD0iTTcgMy4zMzc4MkM4LjQ3MDg3IDIuNDg2OTcgMTAuMTc4NiAyIDEyIDJDMTcuNTIyOCAyIDIyIDYuNDc3MTUgMjIgMTJDMjIgMTcuNTIyOCAxNy41MjI4IDIyIDEyIDIyQzYuNDc3MTUgMjIgMiAxNy41MjI4IDIgMTJDMiAxMC4xNzg2IDIuNDg2OTcgOC40NzA4NyAzLjMzNzgyIDciIHN0cm9rZT0iIzFDMjc0QyIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPg0KPC9zdmc+";
|
|
890
890
|
var Close = "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48IS0tIFVwbG9hZGVkIHRvOiBTVkcgUmVwbywgd3d3LnN2Z3JlcG8uY29tLCBHZW5lcmF0b3I6IFNWRyBSZXBvIE1peGVyIFRvb2xzIC0tPg0KPHN2ZyB3aWR0aD0iODAwcHgiIGhlaWdodD0iODAwcHgiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCjxwYXRoIGQ9Ik0xNC41IDkuNTAwMDJMOS41IDE0LjVNOS40OTk5OCA5LjVMMTQuNSAxNC41IiBzdHJva2U9IiMxQzI3NEMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4NCjxwYXRoIGQ9Ik03IDMuMzM3ODJDOC40NzA4NyAyLjQ4Njk3IDEwLjE3ODYgMiAxMiAyQzE3LjUyMjggMiAyMiA2LjQ3NzE1IDIyIDEyQzIyIDE3LjUyMjggMTcuNTIyOCAyMiAxMiAyMkM2LjQ3NzE1IDIyIDIgMTcuNTIyOCAyIDEyQzIgMTAuMTc4NiAyLjQ4Njk3IDguNDcwODcgMy4zMzc4MiA3IiBzdHJva2U9IiMxQzI3NEMiIHN0cm9rZS13aWR0aD0iMS41IiBzdHJva2UtbGluZWNhcD0icm91bmQiLz4NCjwvc3ZnPg==";
|
|
891
891
|
|
|
892
|
+
// src/kyc/faceDetection.ts
|
|
893
|
+
var FACE_MESSAGES = {
|
|
894
|
+
idle: "Initializing camera...",
|
|
895
|
+
loading: "Loading face detection...",
|
|
896
|
+
scanning: "Position your face in the circle",
|
|
897
|
+
too_far: "Face too far. Please move closer to the camera",
|
|
898
|
+
too_close: "Too close. Please move back a little",
|
|
899
|
+
off_center: "Center your face in the circle",
|
|
900
|
+
ok: "Looking great! Tap the button to capture"
|
|
901
|
+
};
|
|
902
|
+
var FACE_COLORS = {
|
|
903
|
+
idle: "#9ca3af",
|
|
904
|
+
loading: "#3b82f6",
|
|
905
|
+
scanning: "#3b82f6",
|
|
906
|
+
too_far: "#ef4444",
|
|
907
|
+
too_close: "#f59e0b",
|
|
908
|
+
off_center: "#f59e0b",
|
|
909
|
+
ok: "#10b981"
|
|
910
|
+
};
|
|
911
|
+
var MEDIAPIPE_BASE = "https://cdn.jsdelivr.net/npm/@mediapipe/face_detection";
|
|
912
|
+
function mapDetectionsToFaceStatus(detections) {
|
|
913
|
+
if (detections.length === 0) return "scanning";
|
|
914
|
+
const bb = detections[0].boundingBox;
|
|
915
|
+
if (bb.width < 0.18) return "too_far";
|
|
916
|
+
if (bb.width > 0.72) return "too_close";
|
|
917
|
+
if (bb.xCenter < 0.28 || bb.xCenter > 0.72 || bb.yCenter < 0.28 || bb.yCenter > 0.72) {
|
|
918
|
+
return "off_center";
|
|
919
|
+
}
|
|
920
|
+
return "ok";
|
|
921
|
+
}
|
|
922
|
+
function isCaptureDisabled(ready, detectionActive, faceStatus) {
|
|
923
|
+
return !ready || detectionActive && faceStatus !== "ok";
|
|
924
|
+
}
|
|
925
|
+
function resolveMediaPipeBase(base) {
|
|
926
|
+
if (!base) return MEDIAPIPE_BASE;
|
|
927
|
+
return base.endsWith("/") ? base.slice(0, -1) : base;
|
|
928
|
+
}
|
|
929
|
+
var LIVENESS_SAMPLE_LIMIT = 20;
|
|
930
|
+
function buildLivenessArtifact(samples) {
|
|
931
|
+
if (samples.length === 0) return void 0;
|
|
932
|
+
return JSON.stringify({
|
|
933
|
+
version: 1,
|
|
934
|
+
source: "mediapipe-face-detection",
|
|
935
|
+
samples: samples.slice(-LIVENESS_SAMPLE_LIMIT)
|
|
936
|
+
});
|
|
937
|
+
}
|
|
938
|
+
var mediapipeLoaderPromises = /* @__PURE__ */ new Map();
|
|
939
|
+
function loadMediaPipeFaceDetection(assetBasePath) {
|
|
940
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
941
|
+
return Promise.reject(new Error("MediaPipe requires a browser environment"));
|
|
942
|
+
}
|
|
943
|
+
const w = window;
|
|
944
|
+
if (w.FaceDetection) {
|
|
945
|
+
return Promise.resolve(w.FaceDetection);
|
|
946
|
+
}
|
|
947
|
+
const src = `${resolveMediaPipeBase(assetBasePath)}/face_detection.js`;
|
|
948
|
+
const existing = mediapipeLoaderPromises.get(src);
|
|
949
|
+
if (existing) return existing;
|
|
950
|
+
const loader = new Promise((resolve, reject) => {
|
|
951
|
+
const script = document.createElement("script");
|
|
952
|
+
script.src = src;
|
|
953
|
+
script.async = true;
|
|
954
|
+
script.crossOrigin = "anonymous";
|
|
955
|
+
script.onload = () => {
|
|
956
|
+
if (w.FaceDetection) {
|
|
957
|
+
resolve(w.FaceDetection);
|
|
958
|
+
} else {
|
|
959
|
+
mediapipeLoaderPromises.delete(src);
|
|
960
|
+
reject(new Error("MediaPipe loaded but FaceDetection global is missing"));
|
|
961
|
+
}
|
|
962
|
+
};
|
|
963
|
+
script.onerror = () => {
|
|
964
|
+
mediapipeLoaderPromises.delete(src);
|
|
965
|
+
reject(new Error("Failed to load MediaPipe face_detection script"));
|
|
966
|
+
};
|
|
967
|
+
document.head.appendChild(script);
|
|
968
|
+
});
|
|
969
|
+
mediapipeLoaderPromises.set(src, loader);
|
|
970
|
+
return loader;
|
|
971
|
+
}
|
|
972
|
+
|
|
892
973
|
// src/kyc/FaceCaptureModal.tsx
|
|
893
974
|
var MOBILE_UA = /Mobi|Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i;
|
|
894
975
|
var SESSION_EXPIRY_MS = 15 * 60 * 1e3;
|
|
@@ -922,7 +1003,8 @@ function FaceCaptureModal({
|
|
|
922
1003
|
onComplete,
|
|
923
1004
|
onCancel,
|
|
924
1005
|
defaultDevice,
|
|
925
|
-
renderQR
|
|
1006
|
+
renderQR,
|
|
1007
|
+
mediapipeAssetBasePath
|
|
926
1008
|
}) {
|
|
927
1009
|
const isMobile = typeof navigator !== "undefined" && MOBILE_UA.test(navigator.userAgent);
|
|
928
1010
|
const initialChoice = defaultDevice ?? (isMobile ? "this" : "ask");
|
|
@@ -939,6 +1021,7 @@ function FaceCaptureModal({
|
|
|
939
1021
|
const [captureMode, setCaptureMode] = React.useState("idle");
|
|
940
1022
|
const [capturedPreview, setCapturedPreview] = React.useState(null);
|
|
941
1023
|
const [capturedBase64, setCapturedBase64] = React.useState(null);
|
|
1024
|
+
const [capturedArtifact, setCapturedArtifact] = React.useState(null);
|
|
942
1025
|
const [livenessMessage, setLivenessMessage] = React.useState(LIVENESS_MESSAGES[0]);
|
|
943
1026
|
const qrPayload = session.link || `vesant://reuse-kyc?token=${encodeURIComponent(session.token)}`;
|
|
944
1027
|
const cancelledRef = React.useRef(false);
|
|
@@ -1036,7 +1119,10 @@ function FaceCaptureModal({
|
|
|
1036
1119
|
const data = await client.submitEventBasedFaceVerificationSession({
|
|
1037
1120
|
token: session.token,
|
|
1038
1121
|
reference: ref,
|
|
1039
|
-
proof
|
|
1122
|
+
proof,
|
|
1123
|
+
// undefined when detection wasn't running for this capture —
|
|
1124
|
+
// JSON.stringify drops it, so the field is absent on the wire.
|
|
1125
|
+
liveness_artifact: capturedArtifact ?? void 0
|
|
1040
1126
|
});
|
|
1041
1127
|
return { ok: true, data };
|
|
1042
1128
|
} catch (err2) {
|
|
@@ -1082,16 +1168,18 @@ function FaceCaptureModal({
|
|
|
1082
1168
|
submittingRef.current = false;
|
|
1083
1169
|
}
|
|
1084
1170
|
};
|
|
1085
|
-
const handleCameraCapture = (dataUrl) => {
|
|
1171
|
+
const handleCameraCapture = (dataUrl, livenessArtifact) => {
|
|
1086
1172
|
const raw = dataUrl.split(",")[1] ?? "";
|
|
1087
1173
|
setCapturedPreview(dataUrl);
|
|
1088
1174
|
setCapturedBase64(raw);
|
|
1175
|
+
setCapturedArtifact(livenessArtifact ?? null);
|
|
1089
1176
|
setCaptureMode("preview");
|
|
1090
1177
|
};
|
|
1091
1178
|
const handleCameraCancel = () => setCaptureMode("idle");
|
|
1092
1179
|
const handleRetake = () => {
|
|
1093
1180
|
setCapturedPreview(null);
|
|
1094
1181
|
setCapturedBase64(null);
|
|
1182
|
+
setCapturedArtifact(null);
|
|
1095
1183
|
setCaptureMode("live");
|
|
1096
1184
|
};
|
|
1097
1185
|
const handleConfirmSubmit = () => {
|
|
@@ -1163,7 +1251,8 @@ function FaceCaptureModal({
|
|
|
1163
1251
|
{
|
|
1164
1252
|
onCapture: handleCameraCapture,
|
|
1165
1253
|
onCancel: handleCameraCancel,
|
|
1166
|
-
message: livenessMessage
|
|
1254
|
+
message: livenessMessage,
|
|
1255
|
+
assetBasePath: mediapipeAssetBasePath
|
|
1167
1256
|
}
|
|
1168
1257
|
), /* @__PURE__ */ React__default.default.createElement("p", { style: attemptsTextStyle }, "Attempt ", attempts + 1, " of ", maxAttempts));
|
|
1169
1258
|
}
|
|
@@ -1394,59 +1483,10 @@ var attemptsTextStyle = {
|
|
|
1394
1483
|
};
|
|
1395
1484
|
var footerStyle = { padding: "12px 24px 16px", borderTop: "1px solid #f3f4f6" };
|
|
1396
1485
|
var footerTextStyle = { margin: 0, fontSize: 12, color: "#9ca3af", textAlign: "center" };
|
|
1397
|
-
|
|
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
|
-
}
|
|
1447
|
-
function LiveCamera({ onCapture, onCancel, message }) {
|
|
1486
|
+
function LiveCamera({ onCapture, onCancel, message, assetBasePath }) {
|
|
1448
1487
|
const videoRef = React.useRef(null);
|
|
1449
1488
|
const streamRef = React.useRef(null);
|
|
1489
|
+
const samplesRef = React.useRef([]);
|
|
1450
1490
|
const [ready, setReady] = React.useState(false);
|
|
1451
1491
|
const [error, setError] = React.useState(null);
|
|
1452
1492
|
const [faceStatus, setFaceStatus] = React.useState("idle");
|
|
@@ -1501,31 +1541,29 @@ function LiveCamera({ onCapture, onCancel, message }) {
|
|
|
1501
1541
|
let detector = null;
|
|
1502
1542
|
setFaceStatus("loading");
|
|
1503
1543
|
setFaceDetectionFailed(false);
|
|
1544
|
+
samplesRef.current = [];
|
|
1504
1545
|
(async () => {
|
|
1505
1546
|
try {
|
|
1506
|
-
const FaceDetection = await loadMediaPipeFaceDetection();
|
|
1547
|
+
const FaceDetection = await loadMediaPipeFaceDetection(assetBasePath);
|
|
1507
1548
|
if (cancelled) return;
|
|
1549
|
+
const assetBase = resolveMediaPipeBase(assetBasePath);
|
|
1508
1550
|
const d = new FaceDetection({
|
|
1509
|
-
locateFile: (f) => `${
|
|
1551
|
+
locateFile: (f) => `${assetBase}/${f}`
|
|
1510
1552
|
});
|
|
1511
1553
|
d.setOptions({ model: "short", minDetectionConfidence: 0.5 });
|
|
1512
1554
|
d.onResults((results) => {
|
|
1513
1555
|
if (cancelled) return;
|
|
1514
1556
|
const detections = results.detections ?? [];
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
next = "off_center";
|
|
1524
|
-
} else {
|
|
1525
|
-
next = "ok";
|
|
1526
|
-
}
|
|
1557
|
+
const status = mapDetectionsToFaceStatus(detections);
|
|
1558
|
+
samplesRef.current.push({
|
|
1559
|
+
t: Date.now(),
|
|
1560
|
+
status,
|
|
1561
|
+
...detections.length > 0 ? { boundingBox: detections[0].boundingBox } : {}
|
|
1562
|
+
});
|
|
1563
|
+
if (samplesRef.current.length > LIVENESS_SAMPLE_LIMIT) {
|
|
1564
|
+
samplesRef.current.shift();
|
|
1527
1565
|
}
|
|
1528
|
-
setFaceStatus(
|
|
1566
|
+
setFaceStatus(status);
|
|
1529
1567
|
});
|
|
1530
1568
|
await d.initialize();
|
|
1531
1569
|
if (cancelled) return;
|
|
@@ -1561,7 +1599,7 @@ function LiveCamera({ onCapture, onCancel, message }) {
|
|
|
1561
1599
|
} catch {
|
|
1562
1600
|
}
|
|
1563
1601
|
};
|
|
1564
|
-
}, [ready]);
|
|
1602
|
+
}, [ready, assetBasePath]);
|
|
1565
1603
|
const capture = () => {
|
|
1566
1604
|
const video = videoRef.current;
|
|
1567
1605
|
if (!video || !video.videoWidth) return;
|
|
@@ -1578,7 +1616,7 @@ function LiveCamera({ onCapture, onCancel, message }) {
|
|
|
1578
1616
|
ctx.drawImage(video, sx, sy, size, size, 0, 0, size, size);
|
|
1579
1617
|
streamRef.current?.getTracks().forEach((t) => t.stop());
|
|
1580
1618
|
streamRef.current = null;
|
|
1581
|
-
onCapture(canvas.toDataURL("image/jpeg", 0.9));
|
|
1619
|
+
onCapture(canvas.toDataURL("image/jpeg", 0.9), buildLivenessArtifact(samplesRef.current));
|
|
1582
1620
|
};
|
|
1583
1621
|
if (error) {
|
|
1584
1622
|
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")));
|
|
@@ -1586,7 +1624,7 @@ function LiveCamera({ onCapture, onCancel, message }) {
|
|
|
1586
1624
|
const detectionActive = ready && !faceDetectionFailed;
|
|
1587
1625
|
const liveMessage = detectionActive ? FACE_MESSAGES[faceStatus] : message;
|
|
1588
1626
|
const liveFaceColor = detectionActive ? FACE_COLORS[faceStatus] : void 0;
|
|
1589
|
-
const captureDisabled =
|
|
1627
|
+
const captureDisabled = isCaptureDisabled(ready, detectionActive, faceStatus);
|
|
1590
1628
|
const ringPulse = detectionActive && (faceStatus === "too_far" || faceStatus === "too_close") ? "pulse 1.5s ease-in-out infinite" : void 0;
|
|
1591
1629
|
const dynamicCircleStyle = {
|
|
1592
1630
|
...faceCircleStyle,
|
|
@@ -2113,6 +2151,7 @@ function useEventBasedFaceVerificationSubmission(client$1) {
|
|
|
2113
2151
|
defaultDevice: opts.defaultDevice,
|
|
2114
2152
|
renderQR: opts.renderQR,
|
|
2115
2153
|
onCancel: opts.onCancel,
|
|
2154
|
+
mediapipeAssetBasePath: opts.mediapipeAssetBasePath,
|
|
2116
2155
|
onComplete: (result) => {
|
|
2117
2156
|
cleanup();
|
|
2118
2157
|
resolve(result);
|