idmission-web-sdk 2.3.89 → 2.3.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/components/common/InvisibleCanvas.d.ts +1 -0
  2. package/dist/components/common/InvisibleCanvas.d.ts.map +1 -1
  3. package/dist/components/id_capture/BarcodeReadabilityModelProvider.d.ts +29 -0
  4. package/dist/components/id_capture/BarcodeReadabilityModelProvider.d.ts.map +1 -0
  5. package/dist/components/id_capture/CapturedDocuments.d.ts +2 -1
  6. package/dist/components/id_capture/CapturedDocuments.d.ts.map +1 -1
  7. package/dist/components/id_capture/FocusModelProvider.d.ts.map +1 -1
  8. package/dist/components/id_capture/IdCapture.d.ts +1 -1
  9. package/dist/components/id_capture/IdCapture.d.ts.map +1 -1
  10. package/dist/components/id_capture/IdCaptureModelsProvider.d.ts +17 -1
  11. package/dist/components/id_capture/IdCaptureModelsProvider.d.ts.map +1 -1
  12. package/dist/components/id_capture/IdCaptureStateProvider.d.ts +7 -0
  13. package/dist/components/id_capture/IdCaptureStateProvider.d.ts.map +1 -1
  14. package/dist/components/id_capture/IdCaptureSuccess.d.ts.map +1 -1
  15. package/dist/components/id_capture/IdCaptureWizard.d.ts +1 -0
  16. package/dist/components/id_capture/IdCaptureWizard.d.ts.map +1 -1
  17. package/dist/components/submission/SubmissionProvider.d.ts +6 -0
  18. package/dist/components/submission/SubmissionProvider.d.ts.map +1 -1
  19. package/dist/components/submission/types.d.ts +2 -0
  20. package/dist/components/submission/types.d.ts.map +1 -1
  21. package/dist/lib/models/BarcodeReadability.d.ts +50 -0
  22. package/dist/lib/models/BarcodeReadability.d.ts.map +1 -0
  23. package/dist/lib/models/DocumentDetection.d.ts +1 -0
  24. package/dist/lib/models/DocumentDetection.d.ts.map +1 -1
  25. package/dist/lib/models/Focus.d.ts.map +1 -1
  26. package/dist/lib/models/defaults/BarcodeReadability.d.ts +2 -0
  27. package/dist/lib/models/defaults/BarcodeReadability.d.ts.map +1 -0
  28. package/dist/lib/models/defaults/index.d.ts +7 -0
  29. package/dist/lib/models/defaults/index.d.ts.map +1 -1
  30. package/dist/lib/models/preloadModels.d.ts +9 -5
  31. package/dist/lib/models/preloadModels.d.ts.map +1 -1
  32. package/dist/lib/utils/cropping.d.ts +3 -1
  33. package/dist/lib/utils/cropping.d.ts.map +1 -1
  34. package/dist/sdk2.cjs.development.js +1971 -1490
  35. package/dist/sdk2.cjs.development.js.map +1 -1
  36. package/dist/sdk2.cjs.production.js +1 -1
  37. package/dist/sdk2.cjs.production.js.map +1 -1
  38. package/dist/sdk2.esm.js +1972 -1491
  39. package/dist/sdk2.esm.js.map +1 -1
  40. package/dist/sdk2.umd.development.js +2434 -1953
  41. package/dist/sdk2.umd.development.js.map +1 -1
  42. package/dist/sdk2.umd.production.js +1 -1
  43. package/dist/sdk2.umd.production.js.map +1 -1
  44. package/dist/version.d.ts +1 -1
  45. package/package.json +3 -3
@@ -236,7 +236,7 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
236
236
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
237
237
  };
238
238
 
239
- var webSdkVersion = '2.3.89';
239
+ var webSdkVersion = '2.3.90';
240
240
 
241
241
  function getPlatform() {
242
242
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -497,27 +497,27 @@ var GuidanceMessageContainer = function GuidanceMessageContainer(props) {
497
497
  if (!portalLocation) return element;
498
498
  return /*#__PURE__*/reactDom.createPortal(element, portalLocation);
499
499
  };
500
- var GuidanceMessage = styled__default.default.div(templateObject_2$I || (templateObject_2$I = __makeTemplateObject(["\n margin-left: auto;\n margin-right: auto;\n background: ", ";\n color: ", ";\n border-radius: 8px;\n z-index: 10001;\n padding: 16px 24px;\n font-size: 18px;\n font-weight: bold;\n box-shadow:\n 0 1px 3px 0 rgb(0 0 0 / 0.1),\n 0 1px 2px -1px rgb(0 0 0 / 0.1);\n"], ["\n margin-left: auto;\n margin-right: auto;\n background: ", ";\n color: ", ";\n border-radius: 8px;\n z-index: 10001;\n padding: 16px 24px;\n font-size: 18px;\n font-weight: bold;\n box-shadow:\n 0 1px 3px 0 rgb(0 0 0 / 0.1),\n 0 1px 2px -1px rgb(0 0 0 / 0.1);\n"])), function (props) {
500
+ var GuidanceMessage = styled__default.default.div(templateObject_2$J || (templateObject_2$J = __makeTemplateObject(["\n margin-left: auto;\n margin-right: auto;\n background: ", ";\n color: ", ";\n border-radius: 8px;\n z-index: 10001;\n padding: 16px 24px;\n font-size: 18px;\n font-weight: bold;\n box-shadow:\n 0 1px 3px 0 rgb(0 0 0 / 0.1),\n 0 1px 2px -1px rgb(0 0 0 / 0.1);\n"], ["\n margin-left: auto;\n margin-right: auto;\n background: ", ";\n color: ", ";\n border-radius: 8px;\n z-index: 10001;\n padding: 16px 24px;\n font-size: 18px;\n font-weight: bold;\n box-shadow:\n 0 1px 3px 0 rgb(0 0 0 / 0.1),\n 0 1px 2px -1px rgb(0 0 0 / 0.1);\n"])), function (props) {
501
501
  var _a, _b, _c, _d, _e, _f;
502
502
  return (_f = (_a = props.$background) !== null && _a !== void 0 ? _a : (_e = (_c = (_b = props.theme) === null || _b === void 0 ? void 0 : _b.guidanceMessages) === null || _c === void 0 ? void 0 : _c[(_d = props.$variant) !== null && _d !== void 0 ? _d : 'default']) === null || _e === void 0 ? void 0 : _e.backgroundColor) !== null && _f !== void 0 ? _f : 'white';
503
503
  }, function (props) {
504
504
  var _a, _b, _c, _d, _e, _f;
505
505
  return (_f = (_a = props.$textColor) !== null && _a !== void 0 ? _a : (_e = (_c = (_b = props.theme) === null || _b === void 0 ? void 0 : _b.guidanceMessages) === null || _c === void 0 ? void 0 : _c[(_d = props.$variant) !== null && _d !== void 0 ? _d : 'default']) === null || _e === void 0 ? void 0 : _e.textColor) !== null && _f !== void 0 ? _f : 'black';
506
506
  });
507
- var templateObject_1$P, templateObject_2$I;
507
+ var templateObject_1$P, templateObject_2$J;
508
508
 
509
509
  var wavesAnimation = styled.keyframes(templateObject_1$O || (templateObject_1$O = __makeTemplateObject(["\n 0% {\n opacity: 0;\n transform: scale3d(1, 1, 1);\n }\n 80% {\n opacity: 1;\n }\n 100% {\n transform: scale3d(2, 2, 1);\n opacity: 0;\n }\n"], ["\n 0% {\n opacity: 0;\n transform: scale3d(1, 1, 1);\n }\n 80% {\n opacity: 1;\n }\n 100% {\n transform: scale3d(2, 2, 1);\n opacity: 0;\n }\n"])));
510
- var progressBarAnimation = styled.keyframes(templateObject_2$H || (templateObject_2$H = __makeTemplateObject(["\n 0% {\n width: 0;\n }\n 100% {\n width: 100%;\n }\n"], ["\n 0% {\n width: 0;\n }\n 100% {\n width: 100%;\n }\n"])));
510
+ var progressBarAnimation = styled.keyframes(templateObject_2$I || (templateObject_2$I = __makeTemplateObject(["\n 0% {\n width: 0;\n }\n 100% {\n width: 100%;\n }\n"], ["\n 0% {\n width: 0;\n }\n 100% {\n width: 100%;\n }\n"])));
511
511
  var dualRingSpinnerAnimation = styled.keyframes(templateObject_3$u || (templateObject_3$u = __makeTemplateObject(["\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n"], ["\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n"])));
512
512
  var progressBorderAnimation = styled.keyframes(templateObject_4$o || (templateObject_4$o = __makeTemplateObject(["\n to {\n stroke-dashoffset: 0;\n }\n"], ["\n to {\n stroke-dashoffset: 0;\n }\n"])));
513
- var templateObject_1$O, templateObject_2$H, templateObject_3$u, templateObject_4$o;
513
+ var templateObject_1$O, templateObject_2$I, templateObject_3$u, templateObject_4$o;
514
514
 
515
515
  var OverlayContainer = styled__default.default.div(templateObject_1$N || (templateObject_1$N = __makeTemplateObject(["\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n display: flex;\n flex-direction: column;\n\n overflow-x: hidden;\n overflow-y: auto;\n\n background: ", ";\n ", "\n\n z-index: 10000;\n"], ["\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n display: flex;\n flex-direction: column;\n\n overflow-x: hidden;\n overflow-y: auto;\n\n background: ", ";\n ", "\n\n z-index: 10000;\n"])), function (props) {
516
516
  return props.theme.background ? "".concat(props.theme.background) : "white";
517
517
  }, function (props) {
518
518
  return props.theme.textColor ? "color: ".concat(props.theme.textColor, ";") : "";
519
519
  });
520
- var OverlayInner$2 = styled__default.default.div(templateObject_2$G || (templateObject_2$G = __makeTemplateObject(["\n text-align: ", ";\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n width: 100%;\n height: 100%;\n ", "\n"], ["\n text-align: ", ";\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n width: 100%;\n height: 100%;\n ", "\n"])), function (props) {
520
+ var OverlayInner$2 = styled__default.default.div(templateObject_2$H || (templateObject_2$H = __makeTemplateObject(["\n text-align: ", ";\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n width: 100%;\n height: 100%;\n ", "\n"], ["\n text-align: ", ";\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n width: 100%;\n height: 100%;\n ", "\n"])), function (props) {
521
521
  var _a;
522
522
  return (_a = props.theme.textAlign) !== null && _a !== void 0 ? _a : 'center';
523
523
  }, function (props) {
@@ -565,7 +565,7 @@ var LoadingOverlayLoadingListItem = styled__default.default.li(templateObject_19
565
565
  var LoadingOverlayProgressContainer = styled__default.default.div(templateObject_20 || (templateObject_20 = __makeTemplateObject(["\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n"], ["\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n"])));
566
566
  var LoadingOverlayCustomLoadingGraphic = styled__default.default.img(templateObject_21 || (templateObject_21 = __makeTemplateObject(["\n transform-style: preserve-3d;\n"], ["\n transform-style: preserve-3d;\n"])));
567
567
  var LoadingOverlayContinueButtonContainer = styled__default.default.div(templateObject_22 || (templateObject_22 = __makeTemplateObject(["\n display: flex;\n"], ["\n display: flex;\n"])));
568
- var templateObject_1$N, templateObject_2$G, templateObject_3$t, templateObject_4$n, templateObject_5$f, templateObject_6$9, templateObject_7$5, templateObject_8$4, templateObject_9$2, templateObject_10$1, templateObject_11$1, templateObject_12$1, templateObject_13$1, templateObject_14, templateObject_15, templateObject_16, templateObject_17, templateObject_18, templateObject_19, templateObject_20, templateObject_21, templateObject_22;
568
+ var templateObject_1$N, templateObject_2$H, templateObject_3$t, templateObject_4$n, templateObject_5$f, templateObject_6$9, templateObject_7$5, templateObject_8$4, templateObject_9$2, templateObject_10$1, templateObject_11$1, templateObject_12$1, templateObject_13$1, templateObject_14, templateObject_15, templateObject_16, templateObject_17, templateObject_18, templateObject_19, templateObject_20, templateObject_21, templateObject_22;
569
569
 
570
570
  var GeolocationAccessDeniedOverlay = function GeolocationAccessDeniedOverlay(_a) {
571
571
  var accessBlockedImageUrl = _a.accessBlockedImageUrl;
@@ -1134,6 +1134,11 @@ var SubmissionContext = /*#__PURE__*/React.createContext({
1134
1134
  idFrontImage: null,
1135
1135
  idBackImage: null,
1136
1136
  passportImage: null,
1137
+ idFrontIrImage: null,
1138
+ idBackIrImage: null,
1139
+ idFrontUvImage: null,
1140
+ idBackUvImage: null,
1141
+ idBarcodeImage: null,
1137
1142
  selfieImage: null,
1138
1143
  signatureData: null,
1139
1144
  signatureVideoUrl: null,
@@ -1164,6 +1169,9 @@ var SubmissionContext = /*#__PURE__*/React.createContext({
1164
1169
  setIdBackUvImage: function setIdBackUvImage() {
1165
1170
  return null;
1166
1171
  },
1172
+ setIdBarcodeImage: function setIdBarcodeImage() {
1173
+ return null;
1174
+ },
1167
1175
  setSelfieImage: function setSelfieImage() {
1168
1176
  return null;
1169
1177
  },
@@ -1337,59 +1345,62 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1337
1345
  passportImage = _13[0],
1338
1346
  setPassportImage = _13[1];
1339
1347
  var _14 = React.useState(null),
1340
- selfieImage = _14[0],
1341
- setSelfieImage = _14[1];
1348
+ idBarcodeImage = _14[0],
1349
+ setIdBarcodeImage = _14[1];
1342
1350
  var _15 = React.useState(null),
1343
- signatureData = _15[0],
1344
- setSignatureData = _15[1];
1351
+ selfieImage = _15[0],
1352
+ setSelfieImage = _15[1];
1345
1353
  var _16 = React.useState(null),
1346
- signatureVideoUrl = _16[0],
1347
- setSignatureVideoUrl = _16[1];
1354
+ signatureData = _16[0],
1355
+ setSignatureData = _16[1];
1348
1356
  var _17 = React.useState(null),
1349
- signatureStartTimestamp = _17[0],
1350
- setSignatureStartTimestamp = _17[1];
1357
+ signatureVideoUrl = _17[0],
1358
+ setSignatureVideoUrl = _17[1];
1351
1359
  var _18 = React.useState(null),
1352
- signatureEndTimestamp = _18[0],
1353
- setSignatureEndTimestamp = _18[1];
1360
+ signatureStartTimestamp = _18[0],
1361
+ setSignatureStartTimestamp = _18[1];
1354
1362
  var _19 = React.useState(null),
1355
- idCaptureVideoUrl = _19[0],
1356
- setIdCaptureVideoUrl = _19[1];
1363
+ signatureEndTimestamp = _19[0],
1364
+ setSignatureEndTimestamp = _19[1];
1357
1365
  var _20 = React.useState(null),
1358
- idCaptureVideoIdFrontImage = _20[0],
1359
- setIdCaptureVideoIdFrontImage = _20[1];
1366
+ idCaptureVideoUrl = _20[0],
1367
+ setIdCaptureVideoUrl = _20[1];
1360
1368
  var _21 = React.useState(null),
1361
- idCaptureVideoIdBackImage = _21[0],
1362
- setIdCaptureVideoIdBackImage = _21[1];
1369
+ idCaptureVideoIdFrontImage = _21[0],
1370
+ setIdCaptureVideoIdFrontImage = _21[1];
1363
1371
  var _22 = React.useState(null),
1364
- idCaptureVideoAudioUrl = _22[0],
1365
- setIdCaptureVideoAudioUrl = _22[1];
1372
+ idCaptureVideoIdBackImage = _22[0],
1373
+ setIdCaptureVideoIdBackImage = _22[1];
1366
1374
  var _23 = React.useState(null),
1367
- idCaptureVideoAudioStartsAt = _23[0],
1368
- setIdCaptureVideoAudioStartsAt = _23[1];
1375
+ idCaptureVideoAudioUrl = _23[0],
1376
+ setIdCaptureVideoAudioUrl = _23[1];
1369
1377
  var _24 = React.useState(null),
1370
- expectedAudioText = _24[0],
1371
- setExpectedAudioText = _24[1];
1378
+ idCaptureVideoAudioStartsAt = _24[0],
1379
+ setIdCaptureVideoAudioStartsAt = _24[1];
1372
1380
  var _25 = React.useState(null),
1373
- additionalDocuments = _25[0],
1374
- setAdditionalDocuments = _25[1];
1381
+ expectedAudioText = _25[0],
1382
+ setExpectedAudioText = _25[1];
1375
1383
  var _26 = React.useState(null),
1376
- geolocationResult = _26[0],
1377
- setGeolocationResult = _26[1];
1378
- var _27 = React.useState(0),
1379
- geolocationAttempts = _27[0],
1380
- setGeolocationAttempts = _27[1];
1381
- var _28 = React.useState(false),
1382
- geolocationBlocked = _28[0],
1383
- setGeolocationBlocked = _28[1];
1384
- var _29 = React.useState([]),
1385
- idFrontCaptureAttempts = _29[0],
1386
- setIdFrontCaptureAttempts = _29[1];
1384
+ additionalDocuments = _26[0],
1385
+ setAdditionalDocuments = _26[1];
1386
+ var _27 = React.useState(null),
1387
+ geolocationResult = _27[0],
1388
+ setGeolocationResult = _27[1];
1389
+ var _28 = React.useState(0),
1390
+ geolocationAttempts = _28[0],
1391
+ setGeolocationAttempts = _28[1];
1392
+ var _29 = React.useState(false),
1393
+ geolocationBlocked = _29[0],
1394
+ setGeolocationBlocked = _29[1];
1387
1395
  var _30 = React.useState([]),
1388
- idBackCaptureAttempts = _30[0],
1389
- setIdBackCaptureAttempts = _30[1];
1396
+ idFrontCaptureAttempts = _30[0],
1397
+ setIdFrontCaptureAttempts = _30[1];
1390
1398
  var _31 = React.useState([]),
1391
- selfieCaptureAttempts = _31[0],
1392
- setSelfieCaptureAttempts = _31[1];
1399
+ idBackCaptureAttempts = _31[0],
1400
+ setIdBackCaptureAttempts = _31[1];
1401
+ var _32 = React.useState([]),
1402
+ selfieCaptureAttempts = _32[0],
1403
+ setSelfieCaptureAttempts = _32[1];
1393
1404
  var logIdFrontCaptureAttempt = React.useCallback(function (attempt) {
1394
1405
  setIdFrontCaptureAttempts(function (attempts) {
1395
1406
  return __spreadArray(__spreadArray([], attempts, true), [attempt], false);
@@ -1515,6 +1526,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1515
1526
  idFrontImage: idFrontImage,
1516
1527
  idBackImage: idBackImage,
1517
1528
  passportImage: passportImage,
1529
+ idBarcodeImage: idBarcodeImage,
1518
1530
  selfieImage: selfieImage
1519
1531
  };
1520
1532
  _a = signatureVideoUrl;
@@ -1620,6 +1632,9 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1620
1632
  if (documents.passportImage) {
1621
1633
  submissionRequest.customerData.idData.idImageFront = documents.passportImage;
1622
1634
  }
1635
+ if (documents.idBarcodeImage) {
1636
+ submissionRequest.customerData.idData.idBarcodeImage = documents.idBarcodeImage;
1637
+ }
1623
1638
  if (documents.idFrontIrImage) {
1624
1639
  submissionRequest.customerData.idData.idFrontIrImage = documents.idFrontIrImage;
1625
1640
  }
@@ -1714,7 +1729,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1714
1729
  }
1715
1730
  });
1716
1731
  });
1717
- }, [additionalDocuments, bypassAgeValidation, bypassNameMatching, cardData, clientRequestID, companyId, customerDataMatchConfig, deduplicationEnabled, deduplicationSynchronous, documentServiceUrl, enrollmentId, expectedAudioText, geolocationResult, idBackCaptureAttempts, idBackImage, idBackImageRequired, idBackIrImage, idBackUvImage, idCaptureVideoAudioStartsAt, idCaptureVideoAudioUrl, idCaptureVideoIdBackImage, idCaptureVideoIdFrontImage, idCaptureVideoUrl, idCardForFaceMatch, idData, idFrontCaptureAttempts, idFrontImage, idFrontIrImage, idFrontUvImage, idImageResolutionCheck, jobId, manualReviewRequired, needImmediateResponse, passportImage, personalData, selfieCaptureAttempts, selfieImage, signatureData, signatureEndTimestamp, signatureStartTimestamp, signatureVideoUrl, uploadDocument, verifyIdWithExternalDatabases, webhooksClientTraceId, webhooksEnabled, webhooksFireOnReview, webhooksFireOnReviewURL, webhooksSendInputImages, webhooksSendProcessedImages, webhooksStripSpecialCharacters, webhooksURL]);
1732
+ }, [additionalDocuments, bypassAgeValidation, bypassNameMatching, cardData, clientRequestID, companyId, customerDataMatchConfig, deduplicationEnabled, deduplicationSynchronous, documentServiceUrl, enrollmentId, expectedAudioText, geolocationResult, idBackCaptureAttempts, idBackImage, idBackImageRequired, idBackIrImage, idBackUvImage, idBarcodeImage, idCaptureVideoAudioStartsAt, idCaptureVideoAudioUrl, idCaptureVideoIdBackImage, idCaptureVideoIdFrontImage, idCaptureVideoUrl, idCardForFaceMatch, idData, idFrontCaptureAttempts, idFrontImage, idFrontIrImage, idFrontUvImage, idImageResolutionCheck, jobId, manualReviewRequired, needImmediateResponse, passportImage, personalData, selfieCaptureAttempts, selfieImage, signatureData, signatureEndTimestamp, signatureStartTimestamp, signatureVideoUrl, uploadDocument, verifyIdWithExternalDatabases, webhooksClientTraceId, webhooksEnabled, webhooksFireOnReview, webhooksFireOnReviewURL, webhooksSendInputImages, webhooksSendProcessedImages, webhooksStripSpecialCharacters, webhooksURL]);
1718
1733
  var defaultOnSubmit = React.useCallback(function () {
1719
1734
  return __awaiter(void 0, void 0, void 0, function () {
1720
1735
  var submissionResponse_1, payload, host, endpoint, response, statusMessage, submissionResponse_2, e_1, err;
@@ -1992,6 +2007,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1992
2007
  idFrontUvImage: idFrontUvImage,
1993
2008
  idBackUvImage: idBackUvImage,
1994
2009
  passportImage: passportImage,
2010
+ idBarcodeImage: idBarcodeImage,
1995
2011
  selfieImage: selfieImage,
1996
2012
  signatureData: signatureData,
1997
2013
  signatureVideoUrl: signatureVideoUrl,
@@ -2008,6 +2024,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
2008
2024
  setIdBackIrImage: setIdBackIrImage,
2009
2025
  setIdFrontUvImage: setIdFrontUvImage,
2010
2026
  setIdBackUvImage: setIdBackUvImage,
2027
+ setIdBarcodeImage: setIdBarcodeImage,
2011
2028
  setSelfieImage: setSelfieImage,
2012
2029
  setSignatureData: setSignatureData,
2013
2030
  setSignatureVideoUrl: setSignatureVideoUrl,
@@ -2028,7 +2045,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
2028
2045
  checkLiveness: checkLiveness,
2029
2046
  retryLocationAccess: retryLocationAccess
2030
2047
  };
2031
- }, [additionalDocuments, checkLiveness, environment, idBackImage, idBackIrImage, idBackUvImage, idCaptureVideoAudioStartsAt, idCaptureVideoAudioUrl, idCaptureVideoIdBackImage, idCaptureVideoIdFrontImage, idCaptureVideoUrl, idFrontImage, idFrontIrImage, idFrontUvImage, livenessCheckRequest, logIdBackCaptureAttempt, logIdFrontCaptureAttempt, logSelfieCaptureAttempt, passportImage, retryLocationAccess, selfieImage, signatureData, signatureVideoUrl, submissionError, submissionRequest, submissionResponse, submissionStatus, submit, uploadDocument]);
2048
+ }, [additionalDocuments, checkLiveness, environment, idBackImage, idBackIrImage, idBackUvImage, idBarcodeImage, idCaptureVideoAudioStartsAt, idCaptureVideoAudioUrl, idCaptureVideoIdBackImage, idCaptureVideoIdFrontImage, idCaptureVideoUrl, idFrontImage, idFrontIrImage, idFrontUvImage, livenessCheckRequest, logIdBackCaptureAttempt, logIdFrontCaptureAttempt, logSelfieCaptureAttempt, passportImage, retryLocationAccess, selfieImage, signatureData, signatureVideoUrl, submissionError, submissionRequest, submissionResponse, submissionStatus, submit, uploadDocument]);
2032
2049
  return /*#__PURE__*/React__namespace.default.createElement(SubmissionContext.Provider, {
2033
2050
  value: value
2034
2051
  }, geolocationRequired && geolocationBlocked ? ( /*#__PURE__*/React__namespace.default.createElement(GeolocationAccessDeniedOverlay, null)) : children, submissionError && ( /*#__PURE__*/React__namespace.default.createElement(SubmissionErrorOverlay, {
@@ -2222,97 +2239,6 @@ function preloadVisionRuntime() {
2222
2239
  });
2223
2240
  }
2224
2241
 
2225
- function getFrameDimensions(frame) {
2226
- var frameWidth = frame.width,
2227
- frameHeight = frame.height;
2228
- if (frame instanceof HTMLImageElement) {
2229
- frameWidth = frame.naturalWidth;
2230
- frameHeight = frame.naturalHeight;
2231
- }
2232
- if (frame instanceof HTMLVideoElement) {
2233
- frameWidth = frame.videoWidth;
2234
- frameHeight = frame.videoHeight;
2235
- }
2236
- return [frameWidth, frameHeight];
2237
- }
2238
-
2239
- var InvisibleCanvas = styled__default.default.canvas(templateObject_1$M || (templateObject_1$M = __makeTemplateObject(["\n display: none;\n"], ["\n display: none;\n"])));
2240
- function drawToCanvas(canvas, frame, width, height) {
2241
- if (!canvas) return;
2242
- var ctx = canvas.getContext('2d');
2243
- if (!ctx) return;
2244
- if (!width || !height) {
2245
- var _a = getFrameDimensions(frame),
2246
- frameWidth = _a[0],
2247
- frameHeight = _a[1];
2248
- width || (width = frameWidth);
2249
- height || (height = frameHeight);
2250
- }
2251
- canvas.width = width;
2252
- canvas.height = height;
2253
- ctx.drawImage(frame, 0, 0, width, height);
2254
- }
2255
- function clearCanvas(canvas) {
2256
- var _a;
2257
- (_a = canvas === null || canvas === void 0 ? void 0 : canvas.getContext('2d')) === null || _a === void 0 ? void 0 : _a.clearRect(0, 0, canvas === null || canvas === void 0 ? void 0 : canvas.width, canvas === null || canvas === void 0 ? void 0 : canvas.height);
2258
- }
2259
- var templateObject_1$M;
2260
-
2261
- function cropToShoulders(rawCanvas, cropCanvas, resizeCanvas, frame, face, quality, maxHeight) {
2262
- var _a;
2263
- if (quality === void 0) {
2264
- quality = 0.92;
2265
- }
2266
- if (!rawCanvas || !cropCanvas || !resizeCanvas) return '';
2267
- var rawCtx = rawCanvas.getContext('2d');
2268
- var cropCtx = cropCanvas.getContext('2d');
2269
- var resizeCtx = resizeCanvas.getContext('2d');
2270
- if (!rawCtx || !cropCtx || !resizeCtx) throw new Error('could not get 2d context');
2271
- rawCanvas.width = frame.width;
2272
- rawCanvas.height = frame.height;
2273
- rawCtx.putImageData(frame, 0, 0);
2274
- if (frame.height > frame.width) {
2275
- cropCanvas.width = frame.width;
2276
- cropCanvas.height = frame.height;
2277
- cropCtx.drawImage(rawCanvas, 0, 0, cropCanvas.width, cropCanvas.height);
2278
- } else {
2279
- var _b = (_a = face === null || face === void 0 ? void 0 : face.box) !== null && _a !== void 0 ? _a : {
2280
- xMin: 0,
2281
- width: frame.width
2282
- },
2283
- xMin = _b.xMin,
2284
- width = _b.width;
2285
- var desiredWidth = frame.height * 0.6;
2286
- var faceCenterX = xMin + width / 2;
2287
- var xPos = Math.max(0, faceCenterX - desiredWidth / 2);
2288
- cropCanvas.width = desiredWidth;
2289
- cropCanvas.height = frame.height;
2290
- cropCtx.drawImage(rawCanvas, xPos, 0, cropCanvas.width, cropCanvas.height, 0, 0, cropCanvas.width, cropCanvas.height);
2291
- }
2292
- resizeCanvas.height = maxHeight !== null && maxHeight !== void 0 ? maxHeight : cropCanvas.height;
2293
- resizeCanvas.width = cropCanvas.width * (resizeCanvas.height / cropCanvas.height);
2294
- resizeCtx === null || resizeCtx === void 0 ? void 0 : resizeCtx.drawImage(cropCanvas, 0, 0, resizeCanvas.width, resizeCanvas.height);
2295
- var dataURL = resizeCanvas.toDataURL('image/jpeg', quality);
2296
- log('cropToShoulders size', new TextEncoder().encode(dataURL).length);
2297
- clearCanvas(rawCanvas);
2298
- clearCanvas(cropCanvas);
2299
- clearCanvas(resizeCanvas);
2300
- return dataURL;
2301
- }
2302
- function cropToDetectedObjectBox(frame, box, canvas) {
2303
- canvas || (canvas = document.createElement('canvas'));
2304
- var ctx = canvas.getContext('2d');
2305
- if (!ctx) throw new Error('could not get 2d context');
2306
- var xMin = box.xMin,
2307
- yMin = box.yMin,
2308
- width = box.width,
2309
- height = box.height;
2310
- canvas.width = width;
2311
- canvas.height = height;
2312
- ctx.drawImage(frame, xMin, yMin, width, height, 0, 0, width, height);
2313
- return canvas;
2314
- }
2315
-
2316
2242
  var defaultImageSegmenterModelPath = 'https://websdk-cdn-dev.idmission.com/assets/models/selfiesegmenter20240524/selfie_segmenter.tflite';
2317
2243
  var imageSegmenterModelSizeInBytes = 256440.32;
2318
2244
  // The idea here is that we globally set a cache key based on the time at page load. That way our built-in speed test
@@ -2442,6 +2368,192 @@ function giveUpAfter(maxTime) {
2442
2368
  });
2443
2369
  }
2444
2370
 
2371
+ var DEFAULT_CDN_URL = 'https://websdk-cdn-dev.idmission.com/assets';
2372
+
2373
+ var defaultDocumentDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/DocumentDetector/DocumentDetector-20250815_115859.tflite");
2374
+
2375
+ var defaultFocusModelPath = "".concat(DEFAULT_CDN_URL, "/models/Focus/Focus-20241008_102708.tflite");
2376
+
2377
+ var defaultFaceDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/FaceDetector/FaceDetector-20250820_154546.tflite");
2378
+
2379
+ var defaultBarcodeReadabilityModelPath = "".concat(DEFAULT_CDN_URL, "/models/BarcodeReadability/BarcodeReadability-20250815_120417.tflite");
2380
+
2381
+ var defaultModelPaths = {
2382
+ documentDetector: defaultDocumentDetectorModelPath,
2383
+ focus: defaultFocusModelPath,
2384
+ faceDetection: defaultFaceDetectorModelPath,
2385
+ barcodeReadability: defaultBarcodeReadabilityModelPath
2386
+ };
2387
+
2388
+ var preloadModels = function preloadModels(_a) {
2389
+ return __awaiter(void 0, [_a], void 0, function (_b) {
2390
+ var preloadTasks;
2391
+ var _c = _b.documentDetectionModel,
2392
+ documentDetectionModel = _c === void 0 ? true : _c,
2393
+ _d = _b.focusModel,
2394
+ focusModel = _d === void 0 ? true : _d,
2395
+ _e = _b.faceDetectionModel,
2396
+ faceDetectionModel = _e === void 0 ? true : _e,
2397
+ _f = _b.barcodeReadabilityModel,
2398
+ barcodeReadabilityModel = _f === void 0 ? true : _f;
2399
+ return __generator(this, function (_g) {
2400
+ switch (_g.label) {
2401
+ case 0:
2402
+ return [4 /*yield*/, probeModelCapabilities()];
2403
+ case 1:
2404
+ _g.sent();
2405
+ preloadTasks = [];
2406
+ if (documentDetectionModel) {
2407
+ preloadTasks.push(preloadDocumentDetectorDependencies);
2408
+ }
2409
+ if (focusModel) {
2410
+ preloadTasks.push(preloadFocusModelDependencies);
2411
+ }
2412
+ if (faceDetectionModel) {
2413
+ preloadTasks.push(preloadFaceDetectorDependencies);
2414
+ }
2415
+ if (barcodeReadabilityModel) {
2416
+ preloadTasks.push(preloadBarcodeReadabilityModelDependencies);
2417
+ }
2418
+ return [4 /*yield*/, Promise.all(preloadTasks)];
2419
+ case 2:
2420
+ _g.sent();
2421
+ return [2 /*return*/];
2422
+ }
2423
+ });
2424
+ });
2425
+ };
2426
+ var progressByUrl = {};
2427
+ var progressByUseCase = {
2428
+ visionRuntime: {
2429
+ loaded: 0,
2430
+ total: 0
2431
+ },
2432
+ documentDetector: {
2433
+ loaded: 0,
2434
+ total: 0
2435
+ },
2436
+ focus: {
2437
+ loaded: 0,
2438
+ total: 0
2439
+ },
2440
+ faceDetection: {
2441
+ loaded: 0,
2442
+ total: 0
2443
+ },
2444
+ barcodeReadability: {
2445
+ loaded: 0,
2446
+ total: 0
2447
+ }
2448
+ };
2449
+ function preloadDependency(url) {
2450
+ return __awaiter(this, void 0, void 0, function () {
2451
+ return __generator(this, function (_a) {
2452
+ return [2 /*return*/, new Promise(function (resolve, reject) {
2453
+ var req = new XMLHttpRequest();
2454
+ req.addEventListener('progress', function (event) {
2455
+ if (!event.lengthComputable) return;
2456
+ progressByUrl[url] = event;
2457
+ document.dispatchEvent(new CustomEvent('idmission.preloadProgress', {
2458
+ detail: {
2459
+ url: url,
2460
+ loaded: event.loaded,
2461
+ total: event.total
2462
+ }
2463
+ }));
2464
+ });
2465
+ req.addEventListener('loadend', function () {
2466
+ resolve(req.readyState === 4 && req.status === 200);
2467
+ });
2468
+ req.addEventListener('error', reject);
2469
+ req.open('GET', url, true);
2470
+ req.send();
2471
+ })];
2472
+ });
2473
+ });
2474
+ }
2475
+ var modelsPreloading = {
2476
+ documentDetector: false,
2477
+ focus: false,
2478
+ faceDetection: false,
2479
+ barcodeReadability: false
2480
+ };
2481
+ var preloadDocumentDetectorDependencies = function preloadDocumentDetectorDependencies() {
2482
+ return preloadModelDependencies('documentDetector');
2483
+ };
2484
+ var preloadFocusModelDependencies = function preloadFocusModelDependencies() {
2485
+ return preloadModelDependencies('focus');
2486
+ };
2487
+ var preloadFaceDetectorDependencies = function preloadFaceDetectorDependencies() {
2488
+ return preloadModelDependencies('faceDetection');
2489
+ };
2490
+ var preloadBarcodeReadabilityModelDependencies = function preloadBarcodeReadabilityModelDependencies() {
2491
+ return preloadModelDependencies('barcodeReadability');
2492
+ };
2493
+ function preloadModelDependencies(model) {
2494
+ return __awaiter(this, void 0, void 0, function () {
2495
+ function handleModelDownloadProgress(event) {
2496
+ var detail = event.detail;
2497
+ if (!dependencies.includes(detail.url)) return;
2498
+ progressByUseCase[model] = sumUpProgressForDependencies(dependencies);
2499
+ document.dispatchEvent(new CustomEvent("idmission.preloadProgress.".concat(model), {
2500
+ detail: progressByUseCase[model]
2501
+ }));
2502
+ }
2503
+ var dependencies;
2504
+ return __generator(this, function (_a) {
2505
+ switch (_a.label) {
2506
+ case 0:
2507
+ if (modelsPreloading[model]) return [2 /*return*/, new Promise(function (resolve) {
2508
+ var i = setInterval(function () {
2509
+ if (!modelsPreloading[model]) {
2510
+ clearInterval(i);
2511
+ resolve();
2512
+ }
2513
+ }, 100);
2514
+ })];
2515
+ modelsPreloading[model] = true;
2516
+ return [4 /*yield*/, probeModelCapabilities()];
2517
+ case 1:
2518
+ _a.sent();
2519
+ if (modelCapabilities.delegate === 'NONE') {
2520
+ throw new Error("No available delegate for ".concat(model, " model."));
2521
+ }
2522
+ dependencies = [defaultModelPaths[model]];
2523
+ document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
2524
+ _a.label = 2;
2525
+ case 2:
2526
+ _a.trys.push([2,, 4, 5]);
2527
+ return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
2528
+ case 3:
2529
+ _a.sent();
2530
+ return [3 /*break*/, 5];
2531
+ case 4:
2532
+ document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
2533
+ modelsPreloading[model] = false;
2534
+ return [7 /*endfinally*/];
2535
+ case 5:
2536
+ return [2 /*return*/];
2537
+ }
2538
+ });
2539
+ });
2540
+ }
2541
+ function progressToPercentage(progress) {
2542
+ return progress.total > 0 ? Math.round(100.0 * progress.loaded / progress.total) : 0;
2543
+ }
2544
+ function sumUpProgressForDependencies(dependencies) {
2545
+ return dependencies.reduce(function (result, dependency) {
2546
+ var dependencyProgress = progressByUrl[dependency];
2547
+ if (!dependencyProgress) return result;
2548
+ result.loaded += dependencyProgress.loaded;
2549
+ result.total += dependencyProgress.total;
2550
+ return result;
2551
+ }, {
2552
+ loaded: 0,
2553
+ total: 0
2554
+ });
2555
+ }
2556
+
2445
2557
  function convertBoundingBox(box) {
2446
2558
  var _a, _b, _c, _d, _e, _f, _g, _h;
2447
2559
  return {
@@ -2496,53 +2608,50 @@ function average(arr) {
2496
2608
  return sum / len;
2497
2609
  }
2498
2610
 
2499
- var DEFAULT_CDN_URL = 'https://websdk-cdn-dev.idmission.com/assets';
2500
-
2501
- var defaultDocumentDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/DocumentDetector/DocumentDetector-20250815_115859.tflite");
2502
-
2503
- var defaultFocusModelPath = "".concat(DEFAULT_CDN_URL, "/models/Focus/Focus-20241008_102708.tflite");
2504
-
2505
- var defaultFaceDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/FaceDetector/FaceDetector-20250820_154546.tflite");
2506
-
2507
- var defaultFocusModelLoadTimeoutMs = 45000;
2508
- var defaultFocusThresholds = {
2509
- idCardFront: {
2510
- desktop: 0,
2511
- mobile: 0.3
2512
- },
2513
- idCardBack: {
2514
- desktop: 0,
2515
- mobile: 0.3
2516
- },
2517
- passport: {
2518
- desktop: 0,
2519
- mobile: 0.3
2520
- },
2521
- singlePage: {
2522
- desktop: 0,
2523
- mobile: 0.3
2611
+ var defaultDocumentDetectionScoreThreshold = 0.1;
2612
+ var defaultDocumentDetectionModelLoadTimeoutMs = 45000;
2613
+ var defaultDocumentDetectionThresholds = {
2614
+ idCardFront: 0.6,
2615
+ idCardBack: 0.6,
2616
+ passport: 0.4,
2617
+ singlePage: 0.4,
2618
+ stability: {
2619
+ idCardFront: 0.85,
2620
+ idCardBack: 0.85,
2621
+ passport: 0.5,
2622
+ singlePage: 0.5
2524
2623
  }
2525
2624
  };
2526
- var classifier = null;
2527
- var classifierSettings = null;
2528
- function loadFocusModel() {
2529
- return __awaiter(this, arguments, void 0, function (modelAssetPath) {
2625
+ var documentTypeDisplayNames = {
2626
+ idCardFront: 'ID card front',
2627
+ idCardBack: 'ID card back',
2628
+ passport: 'Passport',
2629
+ singlePage: 'Single page',
2630
+ none: 'None'
2631
+ };
2632
+ var detector$1 = null;
2633
+ var detectorSettings$1 = null;
2634
+ function loadDocumentDetector() {
2635
+ return __awaiter(this, arguments, void 0, function (modelAssetPath, scoreThreshold) {
2530
2636
  var _a, _b;
2531
2637
  if (modelAssetPath === void 0) {
2532
- modelAssetPath = defaultFocusModelPath;
2638
+ modelAssetPath = defaultDocumentDetectorModelPath;
2639
+ }
2640
+ if (scoreThreshold === void 0) {
2641
+ scoreThreshold = defaultDocumentDetectionScoreThreshold;
2533
2642
  }
2534
2643
  return __generator(this, function (_c) {
2535
2644
  switch (_c.label) {
2536
2645
  case 0:
2537
- if (classifier && (classifierSettings === null || classifierSettings === void 0 ? void 0 : classifierSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier];
2538
- closeFocusModel();
2539
- return [4 /*yield*/, preloadFocusModelDependencies()];
2646
+ if (detector$1 && (detectorSettings$1 === null || detectorSettings$1 === void 0 ? void 0 : detectorSettings$1.modelAssetPath) === modelAssetPath && (detectorSettings$1 === null || detectorSettings$1 === void 0 ? void 0 : detectorSettings$1.scoreThreshold) === scoreThreshold) return [2 /*return*/, detector$1];
2647
+ closeDocumentDetector();
2648
+ return [4 /*yield*/, preloadDocumentDetectorDependencies()];
2540
2649
  case 1:
2541
2650
  _c.sent();
2542
2651
  if (modelCapabilities.delegate === 'NONE') {
2543
- throw new Error('No available delegate for focus detector.');
2652
+ throw new Error('No available delegate for document detector.');
2544
2653
  }
2545
- _b = (_a = tasksVision.ImageClassifier).createFromOptions;
2654
+ _b = (_a = tasksVision.ObjectDetector).createFromOptions;
2546
2655
  return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
2547
2656
  case 2:
2548
2657
  return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
@@ -2551,44 +2660,48 @@ function loadFocusModel() {
2551
2660
  delegate: modelCapabilities.delegate
2552
2661
  },
2553
2662
  // canvas: document.createElement('canvas'),
2663
+ scoreThreshold: scoreThreshold,
2554
2664
  runningMode: 'VIDEO'
2555
2665
  }])];
2556
2666
  case 3:
2557
- classifier = _c.sent();
2558
- classifierSettings = {
2559
- modelAssetPath: modelAssetPath
2667
+ detector$1 = _c.sent();
2668
+ detectorSettings$1 = {
2669
+ modelAssetPath: modelAssetPath,
2670
+ scoreThreshold: scoreThreshold
2560
2671
  };
2561
- return [2 /*return*/, classifier];
2672
+ return [2 /*return*/, detector$1];
2562
2673
  }
2563
2674
  });
2564
2675
  });
2565
2676
  }
2566
- function closeFocusModel() {
2567
- classifier === null || classifier === void 0 ? void 0 : classifier.close();
2568
- classifier = null;
2569
- classifierSettings = null;
2677
+ function closeDocumentDetector() {
2678
+ detector$1 === null || detector$1 === void 0 ? void 0 : detector$1.close();
2679
+ detector$1 = null;
2680
+ detectorSettings$1 = null;
2570
2681
  }
2571
- function useLoadFocusModel(_a) {
2572
- var _b = _a.modelPath,
2573
- modelPath = _b === void 0 ? defaultFocusModelPath : _b,
2574
- _c = _a.modelLoadTimeoutMs,
2575
- modelLoadTimeoutMs = _c === void 0 ? defaultFocusModelLoadTimeoutMs : _c,
2682
+ function useLoadDocumentDetector(_a) {
2683
+ var _b = _a.shouldLoadModels,
2684
+ shouldLoadModels = _b === void 0 ? true : _b,
2685
+ _c = _a.modelPath,
2686
+ modelPath = _c === void 0 ? defaultDocumentDetectorModelPath : _c,
2687
+ _d = _a.modelLoadTimeoutMs,
2688
+ modelLoadTimeoutMs = _d === void 0 ? defaultDocumentDetectionModelLoadTimeoutMs : _d,
2689
+ _e = _a.scoreThreshold,
2690
+ scoreThreshold = _e === void 0 ? defaultDocumentDetectionScoreThreshold : _e,
2576
2691
  onModelError = _a.onModelError,
2577
- videoRef = _a.videoRef,
2578
- _d = _a.shouldLoadModels,
2579
- shouldLoadModels = _d === void 0 ? true : _d;
2580
- var _e = React.useState('not-started'),
2581
- modelLoadState = _e[0],
2582
- setModelLoadState = _e[1];
2583
- var _f = React.useState(0),
2584
- modelDownloadProgress = _f[0],
2585
- setModelDownloadProgress = _f[1];
2692
+ videoRef = _a.videoRef;
2693
+ var _f = React.useState('not-started'),
2694
+ modelLoadState = _f[0],
2695
+ setModelLoadState = _f[1];
2586
2696
  var _g = React.useState(null),
2587
2697
  modelWarmingStartedAt = _g[0],
2588
2698
  setModelWarmingStartedAt = _g[1];
2589
- var _h = React.useState(null),
2590
- modelError = _h[0],
2591
- setModelError = _h[1];
2699
+ var _h = React.useState(0),
2700
+ modelDownloadProgress = _h[0],
2701
+ setModelDownloadProgress = _h[1];
2702
+ var _j = React.useState(null),
2703
+ modelError = _j[0],
2704
+ setModelError = _j[1];
2592
2705
  React.useEffect(function loadModel() {
2593
2706
  var _this = this;
2594
2707
  if (!shouldLoadModels) return;
@@ -2597,21 +2710,24 @@ function useLoadFocusModel(_a) {
2597
2710
  function handleDownloadProgress(event) {
2598
2711
  setModelDownloadProgress(progressToPercentage(event.detail));
2599
2712
  }
2600
- document.addEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
2713
+ document.addEventListener('idmission.preloadProgress.documentDetector', handleDownloadProgress);
2601
2714
  var modelLoadTimeout = setTimeout(function () {
2602
2715
  setModelError(new Error('Model loading time limit exceeded.'));
2603
2716
  }, modelLoadTimeoutMs);
2604
2717
  var cancelVideoReady = function cancelVideoReady() {};
2605
- loadFocusModel(modelPath).then(function (loadedModel) {
2718
+ loadDocumentDetector(modelPath, scoreThreshold).then(function (model) {
2606
2719
  return __awaiter(_this, void 0, void 0, function () {
2607
2720
  var _a, videoReady, cancel, cancelled;
2608
2721
  return __generator(this, function (_b) {
2609
2722
  switch (_b.label) {
2610
2723
  case 0:
2611
2724
  setModelDownloadProgress(100);
2612
- clearTimeout(modelLoadTimeout);
2613
2725
  setModelLoadState('warming');
2614
- setModelWarmingStartedAt(new Date().getTime());
2726
+ setModelWarmingStartedAt(performance.now());
2727
+ clearTimeout(modelLoadTimeout);
2728
+ return [4 /*yield*/, testDocumentDetectionAgainstKnownImage(model)];
2729
+ case 1:
2730
+ _b.sent();
2615
2731
  _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
2616
2732
  cancelled = false;
2617
2733
  cancelVideoReady = function cancelVideoReady() {
@@ -2619,11 +2735,11 @@ function useLoadFocusModel(_a) {
2619
2735
  cancel();
2620
2736
  };
2621
2737
  return [4 /*yield*/, videoReady];
2622
- case 1:
2738
+ case 2:
2623
2739
  _b.sent();
2624
2740
  setTimeout(function () {
2625
2741
  if (cancelled) return;
2626
- loadedModel.classifyForVideo(videoRef.current, performance.now());
2742
+ model.detectForVideo(videoRef.current, performance.now());
2627
2743
  setModelLoadState('ready');
2628
2744
  }, 500);
2629
2745
  return [2 /*return*/];
@@ -2637,13 +2753,13 @@ function useLoadFocusModel(_a) {
2637
2753
  clearTimeout(modelLoadTimeout);
2638
2754
  });
2639
2755
  return function () {
2640
- log('unloading focus model');
2756
+ log('unloading document detection model');
2641
2757
  cancelVideoReady();
2642
- closeFocusModel();
2758
+ closeDocumentDetector();
2643
2759
  clearTimeout(modelLoadTimeout);
2644
- document.removeEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
2760
+ document.removeEventListener('idmission.preloadProgress.documentDetector', handleDownloadProgress);
2645
2761
  };
2646
- }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
2762
+ }, [shouldLoadModels, modelLoadTimeoutMs, modelPath, scoreThreshold, videoRef]);
2647
2763
  React.useEffect(function handleModelError() {
2648
2764
  if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
2649
2765
  }, [modelError, onModelError]);
@@ -2653,185 +2769,41 @@ function useLoadFocusModel(_a) {
2653
2769
  modelLoadState: modelLoadState,
2654
2770
  modelDownloadProgress: modelDownloadProgress,
2655
2771
  modelWarmingStartedAt: modelWarmingStartedAt,
2656
- modelError: modelError
2772
+ modelError: modelError,
2773
+ setModelError: setModelError
2657
2774
  };
2658
2775
  }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
2659
2776
  }
2660
- var lastFocusPredictionAt = 0;
2661
- var lastFocusPredictionTime = 0;
2662
- function setLastFocusPredictionAt(time) {
2663
- lastFocusPredictionTime = time - lastFocusPredictionAt;
2664
- lastFocusPredictionAt = time;
2665
- }
2666
- function makeFocusModelPrediction(imageData, cropCanvas, rotateCanvas, box) {
2667
- var _a, _b, _c, _d, _e;
2668
- if (!classifier) return null;
2669
- var startedAt = new Date();
2670
- var image = cropIfNecessary(imageData, cropCanvas, rotateCanvas, box);
2671
- var result = classifier.classifyForVideo(image, performance.now());
2672
- var score = (_e = (_d = (_c = (_b = (_a = result === null || result === void 0 ? void 0 : result.classifications) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.categories) === null || _c === void 0 ? void 0 : _c.find(function (c) {
2673
- return c.categoryName === 'focused';
2674
- })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
2675
- var predictionTime = new Date().getTime() - startedAt.getTime();
2676
- return {
2677
- score: score,
2678
- predictionTime: predictionTime
2679
- };
2680
- }
2681
- function cropIfNecessary(imageData, cropCanvas, rotateCanvas, box) {
2682
- if (!box) return imageData;
2683
- var cropped = cropToDetectedObjectBox(imageData, box, cropCanvas);
2684
- var _a = [box.width, box.height],
2685
- bw = _a[0],
2686
- bh = _a[1];
2687
- if (bh <= bw) return cropped;
2688
- var ctx = rotateCanvas.getContext('2d');
2689
- if (!ctx) return cropped;
2690
- rotateCanvas.width = bh;
2691
- rotateCanvas.height = bw;
2692
- ctx.clearRect(0, 0, rotateCanvas.width, rotateCanvas.height);
2693
- ctx.translate(rotateCanvas.width / 2, rotateCanvas.height / 2);
2694
- ctx.rotate(1.5708); // 90 deg in radians
2695
- ctx.drawImage(cropped, -bw / 2, -bh / 2);
2696
- return rotateCanvas;
2697
- }
2698
-
2699
- var defaultSelfieCaptureModelLoadTimeoutMs = 45000;
2700
- var detector$1 = null;
2701
- var detectorSettings$1 = null;
2702
- function loadFaceDetector() {
2703
- return __awaiter(this, arguments, void 0, function (modelAssetPath) {
2704
- var _a, _b;
2705
- if (modelAssetPath === void 0) {
2706
- modelAssetPath = defaultFaceDetectorModelPath;
2707
- }
2708
- return __generator(this, function (_c) {
2709
- switch (_c.label) {
2710
- case 0:
2711
- if (detector$1 && (detectorSettings$1 === null || detectorSettings$1 === void 0 ? void 0 : detectorSettings$1.modelAssetPath) === modelAssetPath) return [2 /*return*/, detector$1];
2712
- closeFaceDetector();
2713
- return [4 /*yield*/, preloadFaceDetectorDependencies()];
2714
- case 1:
2715
- _c.sent();
2716
- if (modelCapabilities.delegate === 'NONE') {
2717
- throw new Error('No available delegate for face detector.');
2718
- }
2719
- _b = (_a = tasksVision.FaceDetector).createFromOptions;
2720
- return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
2721
- case 2:
2722
- return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
2723
- // canvas: document.createElement('canvas'),
2724
- baseOptions: {
2725
- modelAssetPath: modelAssetPath,
2726
- delegate: modelCapabilities.delegate
2727
- },
2728
- runningMode: 'VIDEO'
2729
- }])];
2730
- case 3:
2731
- detector$1 = _c.sent();
2732
- detectorSettings$1 = {
2733
- modelAssetPath: modelAssetPath
2734
- };
2735
- return [2 /*return*/, detector$1];
2777
+ function makeDocumentDetectorPrediction(frame) {
2778
+ return __awaiter(this, void 0, void 0, function () {
2779
+ var startedAt, prediction, time, frameWidth, frameHeight;
2780
+ return __generator(this, function (_a) {
2781
+ if (!detector$1) return [2 /*return*/, null];
2782
+ startedAt = performance.now();
2783
+ // Detectors can throw errors, for example when using custom URLs that
2784
+ // contain a model that doesn't provide the expected output.
2785
+ try {
2786
+ prediction = detector$1.detectForVideo(frame, performance.now());
2787
+ time = performance.now() - startedAt;
2788
+ frameWidth = frame.width;
2789
+ frameHeight = frame.height;
2790
+ return [2 /*return*/, _assign(_assign({}, prediction), {
2791
+ time: time,
2792
+ frameWidth: frameWidth,
2793
+ frameHeight: frameHeight
2794
+ })];
2795
+ } catch (e) {
2796
+ error('caught object detection error', e);
2736
2797
  }
2798
+ return [2 /*return*/, null];
2737
2799
  });
2738
2800
  });
2739
2801
  }
2740
- function closeFaceDetector() {
2741
- detector$1 === null || detector$1 === void 0 ? void 0 : detector$1.close();
2742
- detector$1 = null;
2743
- detectorSettings$1 = null;
2744
- }
2745
- function useLoadFaceDetector(_a) {
2746
- var onModelError = _a.onModelError,
2747
- _b = _a.modelLoadTimeoutMs,
2748
- modelLoadTimeoutMs = _b === void 0 ? defaultSelfieCaptureModelLoadTimeoutMs : _b,
2749
- videoRef = _a.videoRef;
2750
- var _c = React.useState('not-started'),
2751
- modelLoadState = _c[0],
2752
- setModelLoadState = _c[1];
2753
- var _d = React.useState(0),
2754
- modelDownloadProgress = _d[0],
2755
- setModelDownloadProgress = _d[1];
2756
- var _e = React.useState(null),
2757
- modelWarmingStartedAt = _e[0],
2758
- setModelWarmingStartedAt = _e[1];
2759
- var _f = React.useState(null),
2760
- modelError = _f[0],
2761
- setModelError = _f[1];
2762
- React.useEffect(function loadModel() {
2763
- var _this = this;
2764
- setModelLoadState('downloading');
2765
- setModelWarmingStartedAt(null);
2766
- var modelLoadTimeout = setTimeout(function () {
2767
- setModelError(new Error('Model loading time limit exceeded.'));
2768
- }, modelLoadTimeoutMs);
2769
- function handleDownloadProgress(event) {
2770
- setModelDownloadProgress(progressToPercentage(event.detail));
2771
- }
2772
- document.addEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
2773
- var cancelVideoReady = function cancelVideoReady() {};
2774
- loadFaceDetector().then(function (model) {
2775
- return __awaiter(_this, void 0, void 0, function () {
2776
- var _a, videoReady, cancel, cancelled;
2777
- return __generator(this, function (_b) {
2778
- switch (_b.label) {
2779
- case 0:
2780
- setModelDownloadProgress(100);
2781
- clearTimeout(modelLoadTimeout);
2782
- setModelLoadState('warming');
2783
- setModelWarmingStartedAt(new Date().getTime());
2784
- return [4 /*yield*/, testFaceDetectionAgainstKnownImage(model)];
2785
- case 1:
2786
- _b.sent();
2787
- _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
2788
- cancelled = false;
2789
- cancelVideoReady = function cancelVideoReady() {
2790
- cancelled = true;
2791
- cancel();
2792
- };
2793
- return [4 /*yield*/, videoReady];
2794
- case 2:
2795
- _b.sent();
2796
- if (cancelled) return [2 /*return*/];
2797
- model.detectForVideo(videoRef.current, performance.now());
2798
- setModelLoadState('ready');
2799
- return [2 /*return*/];
2800
- }
2801
- });
2802
- });
2803
- })["catch"](function (e) {
2804
- setModelError(e);
2805
- setModelLoadState('error');
2806
- })["finally"](function () {
2807
- clearTimeout(modelLoadTimeout);
2808
- });
2809
- return function () {
2810
- log('unloading face detection model');
2811
- cancelVideoReady();
2812
- closeFaceDetector();
2813
- clearTimeout(modelLoadTimeout);
2814
- document.removeEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
2815
- };
2816
- }, [modelLoadTimeoutMs, videoRef]);
2817
- React.useEffect(function handleModelError() {
2818
- if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
2819
- }, [modelError, onModelError]);
2820
- return React.useMemo(function () {
2821
- return {
2822
- ready: modelLoadState === 'ready',
2823
- modelLoadState: modelLoadState,
2824
- modelDownloadProgress: modelDownloadProgress,
2825
- modelWarmingStartedAt: modelWarmingStartedAt,
2826
- modelError: modelError
2827
- };
2828
- }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
2829
- }
2830
- var lastFaceDetectionAt = 0;
2831
- var lastFaceDetectionTime = 0;
2832
- function setLastFaceDetectionAt(time) {
2833
- lastFaceDetectionTime = time - lastFaceDetectionAt;
2834
- lastFaceDetectionAt = time;
2802
+ var lastDetectionAt = 0;
2803
+ var lastDetectionTime = 0;
2804
+ function setLastDetectionAt(time) {
2805
+ lastDetectionTime = time - lastDetectionAt;
2806
+ lastDetectionAt = time;
2835
2807
  }
2836
2808
  var framesNeededSamples$1 = [];
2837
2809
  function trackFramesNeeded$1(value, bufferLength) {
@@ -2841,970 +2813,375 @@ function trackFramesNeeded$1(value, bufferLength) {
2841
2813
  framesNeededSamples$1.unshift(value);
2842
2814
  if (framesNeededSamples$1.length > bufferLength) framesNeededSamples$1.length = bufferLength;
2843
2815
  }
2844
- var lastNFaces = [];
2845
- var lastNFacePairs = [];
2846
- var lastNNoses = [];
2847
- var lastNNosePairs = [];
2848
- function trackFace(face, framesNeeded, frameWidth, frameHeight) {
2816
+ var lastNBoxes = [];
2817
+ var lastNPairs = [];
2818
+ function trackBox(box, framesNeeded) {
2849
2819
  if (framesNeeded === void 0) {
2850
2820
  framesNeeded = 12;
2851
2821
  }
2852
- var nose = face.keypoints[2];
2853
- if (!nose) return;
2854
- lastNFaces.unshift(face);
2855
- lastNNoses.unshift(nose);
2856
- if (lastNFaces.length > framesNeeded) lastNFaces.length = framesNeeded;
2857
- if (lastNNoses.length > framesNeeded) lastNNoses.length = framesNeeded;
2858
- if (lastNFaces.length > 1) {
2859
- var lastFace = lastNFaces[1];
2860
- var iou = calculateIoU(face.box, lastFace.box);
2861
- lastNFacePairs.unshift({
2862
- a: face,
2863
- b: lastFace,
2822
+ lastNBoxes.unshift(box);
2823
+ if (lastNBoxes.length > framesNeeded) lastNBoxes.length = framesNeeded;
2824
+ if (lastNBoxes.length > 1) {
2825
+ var lastBox = lastNBoxes[1];
2826
+ var iou = calculateIoU(box, lastBox);
2827
+ lastNPairs.unshift({
2828
+ a: box,
2829
+ b: lastBox,
2864
2830
  iou: iou
2865
2831
  });
2866
- if (lastNFacePairs.length > framesNeeded - 1) lastNFacePairs.length = framesNeeded - 1;
2832
+ if (lastNPairs.length > framesNeeded - 1) lastNPairs.length = framesNeeded - 1;
2867
2833
  }
2868
- if (lastNNoses.length > 1) {
2869
- var lastNose = lastNNoses[1];
2870
- var noseDistance = Math.sqrt(Math.pow((nose.x - lastNose.x) / frameWidth, 2) + Math.pow((nose.y - lastNose.y) / frameHeight, 2));
2871
- lastNNosePairs.unshift({
2872
- a: nose,
2873
- b: lastNose,
2874
- distance: noseDistance
2834
+ }
2835
+ var defaultDocumentDetectionBoundaries = {
2836
+ top: 20,
2837
+ bottom: 20,
2838
+ left: 20,
2839
+ right: 20
2840
+ };
2841
+ function processDocumentDetectorPrediction(prediction, thresholds, boundaries) {
2842
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
2843
+ if (boundaries === void 0) {
2844
+ boundaries = defaultDocumentDetectionBoundaries;
2845
+ }
2846
+ var detections = prediction.detections,
2847
+ frameWidth = prediction.frameWidth,
2848
+ frameHeight = prediction.frameHeight,
2849
+ time = prediction.time;
2850
+ var boundaryTop = (_a = boundaries.top) !== null && _a !== void 0 ? _a : 20;
2851
+ var boundaryLeft = (_b = boundaries.left) !== null && _b !== void 0 ? _b : 20;
2852
+ var boundaryRight = (_c = boundaries.right) !== null && _c !== void 0 ? _c : 20;
2853
+ var boundaryBottom = (_d = boundaries.bottom) !== null && _d !== void 0 ? _d : 20;
2854
+ var frameWidth80Pct = frameWidth * 0.8;
2855
+ var detectedObjects = applyNonMaxSuppression(detections.flatMap(function (d) {
2856
+ return d.categories.map(function (category) {
2857
+ return {
2858
+ label: category === null || category === void 0 ? void 0 : category.categoryName,
2859
+ score: category === null || category === void 0 ? void 0 : category.score,
2860
+ box: convertBoundingBox(d.boundingBox)
2861
+ };
2862
+ });
2863
+ }), function (obj) {
2864
+ var _a = obj.box,
2865
+ xMin = _a.xMin,
2866
+ yMin = _a.yMin,
2867
+ width = _a.width,
2868
+ height = _a.height;
2869
+ return yMin > boundaryTop &&
2870
+ // Is it valid top edge of ID detected?
2871
+ yMin + height + boundaryBottom < frameHeight && (
2872
+ // Is it valid bottom edge less than max video height
2873
+ xMin > boundaryLeft || xMin + width > frameWidth80Pct) &&
2874
+ // If either the left side visible or if not, right edge of ID should be more than 80% of width.
2875
+ xMin + width + boundaryRight < frameWidth // Valid right edge if it's less than video width.
2876
+ ;
2877
+ });
2878
+ var allZero = detections.length > 0 && !detections.some(function (_a) {
2879
+ var boundingBox = _a.boundingBox;
2880
+ return Object.values(boundingBox !== null && boundingBox !== void 0 ? boundingBox : {}).some(function (n) {
2881
+ return n > 0;
2882
+ });
2883
+ });
2884
+ var bestIdCardFront = detectedObjects.find(function (obj) {
2885
+ return obj.label === 'Document';
2886
+ });
2887
+ var bestIdCardBack = detectedObjects.find(function (obj) {
2888
+ return obj.label === 'Document back';
2889
+ });
2890
+ var bestPassportPage = detectedObjects.find(function (obj) {
2891
+ return obj.label === 'Passport page';
2892
+ });
2893
+ var bestSinglePage = detectedObjects.find(function (obj) {
2894
+ return obj.label === 'Single page';
2895
+ });
2896
+ var idCardFrontDetectionScore = (_e = bestIdCardFront === null || bestIdCardFront === void 0 ? void 0 : bestIdCardFront.score) !== null && _e !== void 0 ? _e : 0;
2897
+ var idCardBackDetectionScore = (_f = bestIdCardBack === null || bestIdCardBack === void 0 ? void 0 : bestIdCardBack.score) !== null && _f !== void 0 ? _f : 0;
2898
+ var passportDetectionScore = (_g = bestPassportPage === null || bestPassportPage === void 0 ? void 0 : bestPassportPage.score) !== null && _g !== void 0 ? _g : 0;
2899
+ var singlePageDetectionScore = (_h = bestSinglePage === null || bestSinglePage === void 0 ? void 0 : bestSinglePage.score) !== null && _h !== void 0 ? _h : 0;
2900
+ var idCardFrontDetectionThresholdMet = idCardFrontDetectionScore >= ((_j = thresholds.idCardFront) !== null && _j !== void 0 ? _j : 0);
2901
+ var idCardBackDetectionThresholdMet = idCardBackDetectionScore >= ((_k = thresholds.idCardBack) !== null && _k !== void 0 ? _k : 0);
2902
+ var passportDetectionThresholdMet = passportDetectionScore >= ((_l = thresholds.passport) !== null && _l !== void 0 ? _l : 0);
2903
+ var singlePageDetectionThresholdMet = singlePageDetectionScore >= ((_m = thresholds.singlePage) !== null && _m !== void 0 ? _m : 0);
2904
+ var bestDocument = singlePageDetectionThresholdMet ? bestSinglePage : passportDetectionThresholdMet ? bestPassportPage : idCardBackDetectionThresholdMet ? bestIdCardBack : bestIdCardFront;
2905
+ var detectionThreshold = singlePageDetectionThresholdMet ? thresholds.singlePage : passportDetectionThresholdMet ? thresholds.passport : idCardBackDetectionThresholdMet ? thresholds.idCardBack : thresholds.idCardFront;
2906
+ var detectionScore = (_o = bestDocument === null || bestDocument === void 0 ? void 0 : bestDocument.score) !== null && _o !== void 0 ? _o : 0;
2907
+ var detectionThresholdMet = detectionScore >= (detectionThreshold !== null && detectionThreshold !== void 0 ? detectionThreshold : 0);
2908
+ var detectedDocumentType = 'none';
2909
+ if (singlePageDetectionThresholdMet) {
2910
+ detectedDocumentType = 'singlePage';
2911
+ } else if (passportDetectionThresholdMet) {
2912
+ detectedDocumentType = 'passport';
2913
+ } else if (idCardBackDetectionThresholdMet) {
2914
+ detectedDocumentType = 'idCardBack';
2915
+ } else if (detectionThresholdMet) {
2916
+ detectedDocumentType = 'idCardFront';
2917
+ }
2918
+ var documentInBounds = !!bestDocument;
2919
+ if (lastDetectionTime > 0) {
2920
+ trackFramesNeeded$1(1000 / lastDetectionTime);
2921
+ }
2922
+ var documentIsStable = false;
2923
+ var documentTooClose = false;
2924
+ if (bestDocument) {
2925
+ var _q = [bestDocument.box.width / frameWidth, bestDocument.box.height / frameHeight],
2926
+ docWidth = _q[0],
2927
+ docHeight = _q[1];
2928
+ documentTooClose = docWidth > 0.85 || docHeight > 0.85;
2929
+ if (detectionThresholdMet && documentInBounds && !documentTooClose) {
2930
+ var thresholdSet = (_p = thresholds.stability) !== null && _p !== void 0 ? _p : defaultDocumentDetectionThresholds.stability;
2931
+ var threshold_1 = thresholdSet[detectedDocumentType];
2932
+ var framesNeeded = Math.ceil(average(framesNeededSamples$1));
2933
+ trackBox(bestDocument.box, framesNeeded);
2934
+ documentIsStable = lastNBoxes.length >= framesNeeded && !lastNPairs.some(function (pair) {
2935
+ return pair.iou < threshold_1;
2936
+ });
2937
+ }
2938
+ }
2939
+ var bestPDF417;
2940
+ if (detectedObjects.length > 0) {
2941
+ bestPDF417 = detectedObjects.find(function (obj) {
2942
+ return obj.label === 'PDF417';
2875
2943
  });
2876
- if (lastNNosePairs.length > framesNeeded - 1) lastNNosePairs.length = framesNeeded - 1;
2877
2944
  }
2945
+ return {
2946
+ prediction: prediction,
2947
+ detectedObjects: detectedObjects,
2948
+ detectionScore: detectionScore,
2949
+ detectionTime: time,
2950
+ detectionThresholdMet: detectionThresholdMet,
2951
+ detectedDocumentType: detectedDocumentType,
2952
+ idCardFrontDetectionScore: idCardFrontDetectionScore,
2953
+ idCardFrontDetectionThresholdMet: idCardFrontDetectionThresholdMet,
2954
+ idCardBackDetectionScore: idCardBackDetectionScore,
2955
+ idCardBackDetectionThresholdMet: idCardBackDetectionThresholdMet,
2956
+ passportDetectionScore: passportDetectionScore,
2957
+ passportDetectionThresholdMet: passportDetectionThresholdMet,
2958
+ singlePageDetectionScore: singlePageDetectionScore,
2959
+ singlePageDetectionThresholdMet: singlePageDetectionThresholdMet,
2960
+ bestDocument: bestDocument,
2961
+ bestPDF417: bestPDF417,
2962
+ documentInBounds: documentInBounds,
2963
+ documentTooClose: documentTooClose,
2964
+ documentIsStable: documentIsStable,
2965
+ frameWidth: frameWidth,
2966
+ frameHeight: frameHeight,
2967
+ allZero: allZero
2968
+ };
2878
2969
  }
2879
- function makeFaceDetectorPrediction(imageData) {
2880
- if (!detector$1) return null;
2881
- var prediction = detector$1.detectForVideo(imageData, performance.now());
2882
- var faces = prediction.detections.map(function (d) {
2883
- return {
2884
- box: convertBoundingBox(d.boundingBox),
2885
- keypoints: d.keypoints.map(function (k) {
2886
- var _a;
2887
- return _assign(_assign({}, k), {
2888
- x: k.x * imageData.width,
2889
- y: k.y * imageData.height,
2890
- name: (_a = k.label) !== null && _a !== void 0 ? _a : ''
2891
- });
2892
- })
2893
- };
2970
+ function applyNonMaxSuppression(detectedObjects, isGoodBox) {
2971
+ var maxes = {};
2972
+ detectedObjects.forEach(function (obj, i) {
2973
+ if (obj) {
2974
+ if (!maxes[obj.label]) maxes[obj.label] = [0, -1];
2975
+ if (obj.score > maxes[obj.label][0] && (isGoodBox === null || isGoodBox === void 0 ? void 0 : isGoodBox(obj))) maxes[obj.label] = [obj.score, i];
2976
+ }
2894
2977
  });
2895
- return _assign(_assign({}, prediction), {
2896
- faces: faces
2978
+ return Object.keys(maxes).map(function (label) {
2979
+ return detectedObjects[maxes[label][1]];
2980
+ }).filter(function (obj) {
2981
+ return !!obj;
2897
2982
  });
2898
2983
  }
2899
- function processFaceDetectorPrediction(_a) {
2900
- var faces = _a.faces,
2901
- videoWidth = _a.videoWidth,
2902
- videoHeight = _a.videoHeight,
2903
- _b = _a.requireVerticalFaceCentering,
2904
- requireVerticalFaceCentering = _b === void 0 ? true : _b,
2905
- _c = _a.stabilityThreshold,
2906
- stabilityThreshold = _c === void 0 ? 0.7 : _c,
2907
- _d = _a.noseDistanceThreshold,
2908
- noseDistanceThreshold = _d === void 0 ? 0.025 : _d,
2909
- _e = _a.xBoundary,
2910
- xBoundary = _e === void 0 ? 0.01 : _e,
2911
- // this represents the edge that the sides of the face box should not cross -- 1% of video width
2912
- _f = _a.yBoundary,
2913
- // this represents the edge that the sides of the face box should not cross -- 1% of video width
2914
- yBoundary = _f === void 0 ? 0.01 : _f,
2915
- // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
2916
- _g = _a.xCentroidBoundary,
2917
- // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
2918
- xCentroidBoundary = _g === void 0 ? 0.125 : _g,
2919
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
2920
- _h = _a.yCentroidBoundary,
2921
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
2922
- yCentroidBoundary = _h === void 0 ? 0.125 : _h,
2923
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
2924
- _j = _a.foreheadRatio,
2925
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
2926
- foreheadRatio = _j === void 0 ? 0.275 : _j,
2927
- // we found that the bounding box ends at the brow and misses the forehead. this ratio represents how much we should extend the box to include the forehead.
2928
- _k = _a.noseTrackingThreshold,
2929
- // we found that the bounding box ends at the brow and misses the forehead. this ratio represents how much we should extend the box to include the forehead.
2930
- noseTrackingThreshold = _k === void 0 ? 0.2 : _k,
2931
- // this represents the maximum distance that the nose can be from the center of the face box -- 20% of the face box width or height
2932
- minCaptureBrightnessThreshold = _a.minCaptureBrightnessThreshold,
2933
- minCaptureRangeThreshold = _a.minCaptureRangeThreshold,
2934
- minCaptureVarianceThreshold = _a.minCaptureVarianceThreshold,
2935
- brightness = _a.brightness,
2936
- range = _a.range,
2937
- variance = _a.variance;
2938
- var face = faces[0];
2939
- var faceNotDetected = faces.length === 0;
2940
- var faceNotCentered = false,
2941
- faceLookingAway = false,
2942
- faceTooClose = false,
2943
- faceTooFar = false,
2944
- faceVisibilityTooLow = false;
2945
- var hasAnyThreshold = minCaptureBrightnessThreshold !== undefined || minCaptureRangeThreshold !== undefined || minCaptureVarianceThreshold !== undefined;
2946
- if (hasAnyThreshold) {
2947
- var tooDark = minCaptureBrightnessThreshold !== undefined && brightness !== undefined && brightness < minCaptureBrightnessThreshold;
2948
- var tooLowRange = minCaptureRangeThreshold !== undefined && range !== undefined && range < minCaptureRangeThreshold;
2949
- var tooLowVariance = minCaptureVarianceThreshold !== undefined && variance !== undefined && variance < minCaptureVarianceThreshold;
2950
- faceVisibilityTooLow = !!(tooDark || tooLowRange || tooLowVariance);
2951
- }
2952
- if (face && !faceVisibilityTooLow) {
2953
- // calculate frame centroids
2954
- var frameCX = videoWidth / 2;
2955
- var frameCY = videoHeight / 2;
2956
- // calculate head bounding box, with forehead extension
2957
- var foreheadSize = face.box.height * foreheadRatio;
2958
- var headXMin = face.box.xMin;
2959
- var headXMax = face.box.xMax;
2960
- var headYMin = face.box.yMin - foreheadSize;
2961
- var headYMax = face.box.yMax;
2962
- // calculate head centroids
2963
- var headCX = (headXMin + headXMax) / 2;
2964
- var headCY = (headYMin + headYMax) / 2;
2965
- // calculate thresholds
2966
- var vTX = videoWidth * xBoundary;
2967
- var vTY = videoHeight * yBoundary;
2968
- var vCTX = videoWidth * xCentroidBoundary;
2969
- var vCTY = videoHeight * yCentroidBoundary;
2970
- var faceNotCenteredHorizontally = Math.abs(frameCX - headCX) > vCTX;
2971
- var faceNotCenteredVertically = Math.abs(frameCY - headCY) > vCTY;
2972
- var faceViolatesHorizontalBoundary = headXMin < vTX || headXMax > videoWidth - vTX;
2973
- var faceViolatesVerticalBoundary = headYMin < vTY || headYMax > videoHeight - vTY;
2974
- faceNotCentered = faceViolatesHorizontalBoundary || faceViolatesVerticalBoundary || faceNotCenteredHorizontally || requireVerticalFaceCentering && faceNotCenteredVertically;
2975
- var isMobile = videoWidth < videoHeight;
2976
- var tooCloseMultiple = 1.5;
2977
- var tooFarMultiple = isMobile ? 6 : 7;
2978
- faceTooClose = face.box.width > videoWidth / tooCloseMultiple;
2979
- faceTooFar = face.box.width < videoWidth / tooFarMultiple;
2980
- var nose = face.keypoints[2];
2981
- var fTW = face.box.width * noseTrackingThreshold;
2982
- var fTH = face.box.height * noseTrackingThreshold;
2983
- faceLookingAway = !nose || Math.abs(headCX - nose.x) > fTW || Math.abs(headCY - nose.y) > fTH;
2984
- }
2985
- var faceInGuides = !faceNotDetected && !faceNotCentered && !faceLookingAway && !faceTooClose && !faceTooFar;
2986
- if (lastFaceDetectionTime > 0) {
2987
- trackFramesNeeded$1(500 / lastFaceDetectionTime);
2988
- }
2989
- var faceIsStable = false,
2990
- noseIsStable = false;
2991
- if (faceInGuides && !faceVisibilityTooLow) {
2992
- var framesNeeded = Math.max(Math.ceil(average(framesNeededSamples$1)), 5);
2993
- trackFace(face, framesNeeded, videoWidth, videoHeight);
2994
- faceIsStable = lastNFaces.length >= framesNeeded && !lastNFacePairs.some(function (pair) {
2995
- return pair.iou < stabilityThreshold;
2996
- });
2997
- noseIsStable = lastNNoses.length >= framesNeeded && !lastNNosePairs.some(function (pair) {
2998
- return pair.distance > noseDistanceThreshold;
2999
- });
3000
- }
3001
- var faceReady = faceInGuides && faceIsStable && noseIsStable && !faceVisibilityTooLow;
3002
- return {
3003
- face: face,
3004
- faceNotDetected: faceNotDetected,
3005
- faceNotCentered: faceNotCentered,
3006
- faceLookingAway: faceLookingAway,
3007
- faceTooClose: faceTooClose,
3008
- faceTooFar: faceTooFar,
3009
- faceReady: faceReady,
3010
- faceReadyAt: faceReady ? new Date() : null,
3011
- faceIsStable: faceIsStable,
3012
- noseIsStable: noseIsStable,
3013
- faceVisibilityTooLow: faceVisibilityTooLow
3014
- };
3015
- }
3016
- function testFaceDetectionAgainstKnownImage(detector) {
2984
+ function testDocumentDetectionAgainstKnownImage(detector) {
3017
2985
  return new Promise(function (resolve, reject) {
3018
2986
  var img = new Image();
3019
2987
  img.crossOrigin = 'anonymous';
3020
2988
  img.onload = function () {
3021
2989
  var prediction = detector.detectForVideo(img, performance.now());
3022
2990
  if (prediction.detections.length > 0) {
3023
- debug('face detection test result', prediction.detections);
2991
+ debug('document detection test result', prediction.detections);
3024
2992
  resolve(void 0);
3025
2993
  } else {
3026
- warn('face detection test failed');
3027
- reject(new Error('testFaceDetectionAgainstKnownImage failed to predict'));
2994
+ warn('document detection test failed');
2995
+ reject(new Error('testDocumentDetectionAgainstKnownImage failed to predict'));
3028
2996
  }
3029
2997
  };
3030
2998
  img.onerror = function () {
3031
- return reject(new Error('testFaceDetectionAgainstKnownImage failed to load image'));
2999
+ return reject(new Error('testDocumentDetectionAgainstKnownImage failed to load image'));
3032
3000
  };
3033
- img.src = "".concat(DEFAULT_CDN_URL, "/head-test.jpg");
3001
+ img.src = "".concat(DEFAULT_CDN_URL, "/id-card-test.jpg");
3034
3002
  });
3035
3003
  }
3036
3004
 
3037
- var preloadModels = function preloadModels(_a) {
3038
- return __awaiter(void 0, [_a], void 0, function (_b) {
3039
- var preloadTasks;
3040
- var _c = _b.documentDetectionModel,
3041
- documentDetectionModel = _c === void 0 ? true : _c,
3042
- _d = _b.focusModel,
3043
- focusModel = _d === void 0 ? true : _d,
3044
- _e = _b.faceDetectionModel,
3045
- faceDetectionModel = _e === void 0 ? true : _e;
3046
- return __generator(this, function (_f) {
3047
- switch (_f.label) {
3048
- case 0:
3049
- return [4 /*yield*/, probeModelCapabilities()];
3050
- case 1:
3051
- _f.sent();
3052
- preloadTasks = [];
3053
- if (documentDetectionModel) {
3054
- preloadTasks.push(preloadDocumentDetectorDependencies);
3055
- }
3056
- if (focusModel) {
3057
- preloadTasks.push(preloadFocusModelDependencies);
3058
- }
3059
- if (faceDetectionModel) {
3060
- preloadTasks.push(preloadFaceDetectorDependencies);
3061
- }
3062
- return [4 /*yield*/, Promise.all(preloadTasks)];
3063
- case 2:
3064
- _f.sent();
3065
- return [2 /*return*/];
3066
- }
3067
- });
3068
- });
3069
- };
3070
- var progressByUrl = {};
3071
- var progressByUseCase = {
3072
- visionRuntime: {
3073
- loaded: 0,
3074
- total: 0
3075
- },
3076
- documentDetection: {
3077
- loaded: 0,
3078
- total: 0
3079
- },
3080
- focus: {
3081
- loaded: 0,
3082
- total: 0
3083
- },
3084
- faceDetection: {
3085
- loaded: 0,
3086
- total: 0
3005
+ function getFrameDimensions(frame) {
3006
+ var frameWidth = frame.width,
3007
+ frameHeight = frame.height;
3008
+ if (frame instanceof HTMLImageElement) {
3009
+ frameWidth = frame.naturalWidth;
3010
+ frameHeight = frame.naturalHeight;
3087
3011
  }
3088
- };
3089
- function preloadDependency(url) {
3090
- return __awaiter(this, void 0, void 0, function () {
3091
- return __generator(this, function (_a) {
3092
- return [2 /*return*/, new Promise(function (resolve, reject) {
3093
- var req = new XMLHttpRequest();
3094
- req.addEventListener('progress', function (event) {
3095
- if (!event.lengthComputable) return;
3096
- progressByUrl[url] = event;
3097
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress', {
3098
- detail: {
3099
- url: url,
3100
- loaded: event.loaded,
3101
- total: event.total
3102
- }
3103
- }));
3104
- });
3105
- req.addEventListener('loadend', function () {
3106
- resolve(req.readyState === 4 && req.status === 200);
3107
- });
3108
- req.addEventListener('error', reject);
3109
- req.open('GET', url, true);
3110
- req.send();
3111
- })];
3112
- });
3113
- });
3012
+ if (frame instanceof HTMLVideoElement) {
3013
+ frameWidth = frame.videoWidth;
3014
+ frameHeight = frame.videoHeight;
3015
+ }
3016
+ return [frameWidth, frameHeight];
3114
3017
  }
3115
- var documentDetectorPreloading = false,
3116
- focusModelPreloading = false,
3117
- faceDetectorPreloading = false;
3118
- function preloadDocumentDetectorDependencies() {
3119
- return __awaiter(this, void 0, void 0, function () {
3120
- function handleDownloadProgress(event) {
3121
- var detail = event.detail;
3122
- if (!dependencies.includes(detail.url)) return;
3123
- progressByUseCase.documentDetection = sumUpProgressForDependencies(dependencies);
3124
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.documentDetection', {
3125
- detail: progressByUseCase.documentDetection
3126
- }));
3127
- }
3128
- var dependencies;
3129
- return __generator(this, function (_a) {
3130
- switch (_a.label) {
3131
- case 0:
3132
- if (documentDetectorPreloading) return [2 /*return*/, new Promise(function (resolve) {
3133
- var i = setInterval(function () {
3134
- if (!documentDetectorPreloading) {
3135
- clearInterval(i);
3136
- resolve();
3137
- }
3138
- }, 100);
3139
- })];
3140
- documentDetectorPreloading = true;
3141
- return [4 /*yield*/, probeModelCapabilities()];
3142
- case 1:
3143
- _a.sent();
3144
- if (modelCapabilities.delegate === 'NONE') {
3145
- throw new Error('No available delegate for document detector.');
3146
- }
3147
- dependencies = [defaultDocumentDetectorModelPath];
3148
- document.addEventListener('idmission.preloadProgress', handleDownloadProgress);
3149
- _a.label = 2;
3150
- case 2:
3151
- _a.trys.push([2,, 4, 5]);
3152
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
3153
- case 3:
3154
- _a.sent();
3155
- return [3 /*break*/, 5];
3156
- case 4:
3157
- document.removeEventListener('idmission.preloadProgress', handleDownloadProgress);
3158
- documentDetectorPreloading = false;
3159
- return [7 /*endfinally*/];
3160
- case 5:
3161
- return [2 /*return*/];
3162
- }
3163
- });
3164
- });
3018
+
3019
+ var InvisibleCanvasContainer = styled__default.default.div(templateObject_1$M || (templateObject_1$M = __makeTemplateObject(["\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n pointer-events: none;\n user-select: none;\n"], ["\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n pointer-events: none;\n user-select: none;\n"])));
3020
+ var InvisibleCanvas = styled__default.default.canvas(templateObject_2$G || (templateObject_2$G = __makeTemplateObject(["\n display: none;\n"], ["\n display: none;\n"])));
3021
+ function drawToCanvas(canvas, frame, width, height) {
3022
+ if (!canvas) return;
3023
+ var ctx = canvas.getContext('2d');
3024
+ if (!ctx) return;
3025
+ if (!width || !height) {
3026
+ var _a = getFrameDimensions(frame),
3027
+ frameWidth = _a[0],
3028
+ frameHeight = _a[1];
3029
+ width || (width = frameWidth);
3030
+ height || (height = frameHeight);
3031
+ }
3032
+ canvas.width = width;
3033
+ canvas.height = height;
3034
+ ctx.drawImage(frame, 0, 0, width, height);
3165
3035
  }
3166
- function preloadFocusModelDependencies() {
3167
- return __awaiter(this, void 0, void 0, function () {
3168
- function handleModelDownloadProgress(event) {
3169
- var detail = event.detail;
3170
- if (!dependencies.includes(detail.url)) return;
3171
- progressByUseCase.focus = sumUpProgressForDependencies(dependencies);
3172
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.focus', {
3173
- detail: progressByUseCase.focus
3174
- }));
3175
- }
3176
- var dependencies;
3177
- return __generator(this, function (_a) {
3178
- switch (_a.label) {
3179
- case 0:
3180
- if (focusModelPreloading) return [2 /*return*/, new Promise(function (resolve) {
3181
- var i = setInterval(function () {
3182
- if (!focusModelPreloading) {
3183
- clearInterval(i);
3184
- resolve();
3185
- }
3186
- }, 100);
3187
- })];
3188
- focusModelPreloading = true;
3189
- return [4 /*yield*/, probeModelCapabilities()];
3190
- case 1:
3191
- _a.sent();
3192
- if (modelCapabilities.delegate === 'NONE') {
3193
- throw new Error('No available delegate for document detector.');
3036
+ function clearCanvas(canvas) {
3037
+ var _a;
3038
+ (_a = canvas === null || canvas === void 0 ? void 0 : canvas.getContext('2d')) === null || _a === void 0 ? void 0 : _a.clearRect(0, 0, canvas === null || canvas === void 0 ? void 0 : canvas.width, canvas === null || canvas === void 0 ? void 0 : canvas.height);
3039
+ }
3040
+ var templateObject_1$M, templateObject_2$G;
3041
+
3042
+ function useFrameLoop(fn, options) {
3043
+ if (options === void 0) {
3044
+ options = {};
3045
+ }
3046
+ var _a = React.useState(false),
3047
+ running = _a[0],
3048
+ setRunning = _a[1];
3049
+ var startedAtRef = React.useRef(null);
3050
+ var loopId = React.useRef(0);
3051
+ var frameId = React.useRef(0);
3052
+ React.useEffect(function runFrameLoop() {
3053
+ if (!running) return;
3054
+ var timer;
3055
+ var currentLoopId = loopId.current;
3056
+ function hotLoop() {
3057
+ return __awaiter(this, void 0, void 0, function () {
3058
+ var start, timeRunning, took, amountToThrottle;
3059
+ var _a, _b, _c;
3060
+ return __generator(this, function (_d) {
3061
+ switch (_d.label) {
3062
+ case 0:
3063
+ if (currentLoopId !== loopId.current) return [2 /*return*/];
3064
+ start = new Date().getTime();
3065
+ timeRunning = start - ((_b = (_a = startedAtRef.current) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : 0);
3066
+ return [4 /*yield*/, fn(frameId.current, timeRunning)];
3067
+ case 1:
3068
+ _d.sent();
3069
+ took = new Date().getTime() - start;
3070
+ amountToThrottle = Math.max(((_c = options.throttleMs) !== null && _c !== void 0 ? _c : 0) - took, 0);
3071
+ timer = setTimeout(function () {
3072
+ frameId.current = requestAnimationFrame(hotLoop);
3073
+ }, amountToThrottle);
3074
+ return [2 /*return*/];
3194
3075
  }
3195
- dependencies = [defaultFocusModelPath];
3196
- document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3197
- _a.label = 2;
3198
- case 2:
3199
- _a.trys.push([2,, 4, 5]);
3200
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
3201
- case 3:
3202
- _a.sent();
3203
- return [3 /*break*/, 5];
3204
- case 4:
3205
- document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3206
- focusModelPreloading = false;
3207
- return [7 /*endfinally*/];
3208
- case 5:
3209
- return [2 /*return*/];
3210
- }
3211
- });
3212
- });
3076
+ });
3077
+ });
3078
+ }
3079
+ void hotLoop();
3080
+ return function () {
3081
+ loopId.current += 1;
3082
+ if (frameId.current) cancelAnimationFrame(frameId.current);
3083
+ if (timer) clearTimeout(timer);
3084
+ };
3085
+ }, [fn, running, options.throttleMs]);
3086
+ var start = React.useCallback(function () {
3087
+ startedAtRef.current = new Date();
3088
+ setRunning(true);
3089
+ }, []);
3090
+ var stop = React.useCallback(function () {
3091
+ loopId.current += 1; // force the loop to stop immediately.
3092
+ setRunning(false);
3093
+ startedAtRef.current = null;
3094
+ }, []);
3095
+ React.useEffect(function startAutomatically() {
3096
+ if (options.autoStart) start();
3097
+ return stop;
3098
+ }, [options.autoStart, start, stop]);
3099
+ return {
3100
+ start: start,
3101
+ stop: stop
3102
+ };
3213
3103
  }
3214
- function preloadFaceDetectorDependencies() {
3215
- return __awaiter(this, void 0, void 0, function () {
3216
- function handleModelDownloadProgress(event) {
3217
- var detail = event.detail;
3218
- if (!dependencies.includes(detail.url)) return;
3219
- progressByUseCase.faceDetection = sumUpProgressForDependencies(dependencies);
3220
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.faceDetection', {
3221
- detail: progressByUseCase.faceDetection
3222
- }));
3104
+
3105
+ function listAvailableCameras(facingMode_1) {
3106
+ return __awaiter(this, arguments, void 0, function (facingMode, requestMicAccess) {
3107
+ var cameraEnumerationStream, allDevices, allowedVideoDevices;
3108
+ if (requestMicAccess === void 0) {
3109
+ requestMicAccess = false;
3223
3110
  }
3224
- var dependencies;
3225
3111
  return __generator(this, function (_a) {
3226
3112
  switch (_a.label) {
3227
3113
  case 0:
3228
- if (faceDetectorPreloading) return [2 /*return*/, new Promise(function (resolve) {
3229
- var i = setInterval(function () {
3230
- if (!faceDetectorPreloading) {
3231
- clearInterval(i);
3232
- resolve();
3114
+ return [4 /*yield*/, navigator.mediaDevices.getUserMedia({
3115
+ video: {
3116
+ facingMode: {
3117
+ exact: facingMode
3233
3118
  }
3234
- }, 100);
3235
- })];
3236
- faceDetectorPreloading = true;
3237
- return [4 /*yield*/, probeModelCapabilities()];
3119
+ },
3120
+ audio: requestMicAccess
3121
+ })
3122
+ // This lists all available cameras attached to the user's device.
3123
+ ];
3238
3124
  case 1:
3239
- _a.sent();
3240
- if (modelCapabilities.delegate === 'NONE') {
3241
- throw new Error('No available delegate for document detector.');
3242
- }
3243
- dependencies = [defaultFaceDetectorModelPath];
3244
- document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3245
- _a.label = 2;
3125
+ cameraEnumerationStream = _a.sent();
3126
+ return [4 /*yield*/, navigator.mediaDevices.enumerateDevices()];
3246
3127
  case 2:
3247
- _a.trys.push([2,, 4, 5]);
3248
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
3249
- case 3:
3250
- _a.sent();
3251
- return [3 /*break*/, 5];
3252
- case 4:
3253
- document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3254
- faceDetectorPreloading = false;
3255
- return [7 /*endfinally*/];
3256
- case 5:
3257
- return [2 /*return*/];
3128
+ allDevices = _a.sent();
3129
+ allowedVideoDevices = allDevices.filter(function (_a) {
3130
+ var kind = _a.kind,
3131
+ label = _a.label;
3132
+ return kind === 'videoinput' && !label.toLowerCase().includes('virtual');
3133
+ });
3134
+ // Release the access to the user's camera that we obtained for enumeration purposes.
3135
+ cameraEnumerationStream.getVideoTracks().forEach(function (track) {
3136
+ track.enabled = false;
3137
+ track.stop();
3138
+ });
3139
+ cameraEnumerationStream = null;
3140
+ return [2 /*return*/, allowedVideoDevices];
3258
3141
  }
3259
3142
  });
3260
3143
  });
3261
3144
  }
3262
- function progressToPercentage(progress) {
3263
- return progress.total > 0 ? Math.round(100.0 * progress.loaded / progress.total) : 0;
3264
- }
3265
- function sumUpProgressForDependencies(dependencies) {
3266
- return dependencies.reduce(function (result, dependency) {
3267
- var dependencyProgress = progressByUrl[dependency];
3268
- if (!dependencyProgress) return result;
3269
- result.loaded += dependencyProgress.loaded;
3270
- result.total += dependencyProgress.total;
3271
- return result;
3272
- }, {
3273
- loaded: 0,
3274
- total: 0
3145
+ var frontCameraLabels = ['front', 'avant', 'anteriore', 'cameraaanvoorzijde', 'kamerapåframsidan', 'forsidekamera', 'kamerapåforsiden', 'aparatprzedni', 'etukamera', 'kameradepan', 'ÖnKamera', 'cameramặttrước', 'camerăfață', 'prednákamera', 'prednjakamera', 'előlapikamera', 'přednífotoaparát', 'μπροστινήκάμερα', 'переднякамера', 'передняякамера', 'преднакамера', 'алдыңғыкамера', 'מצלמה קדמית', 'الكاميرا الأمامية', 'फ़्रंटकैमरा', '前置相机', '前置鏡頭', '前面カメラ', '전면카메라', 'กล้องด้านหน้า'].map(function (s) {
3146
+ return s.toLocaleLowerCase().split(' ').join('');
3147
+ });
3148
+ var rearCameraLabels = ['back', 'rear', 'posterior', 'trasera', 'traseira', 'arrière', 'rückkamera', 'fotocamera(posteriore)', 'cameraaanachterzijde', 'kamerapåbaksidan', 'kamerapåbaksiden', 'bagsidekamera', 'aparattylny', 'takakamera', 'arkakamera', 'kamerabelakang', 'cameramặtsau', 'camerăspate', 'stražnjakamera', 'zadnákamera', 'hátoldalikamera', 'zadnífotoaparát', 'πίσωκάμερα', 'заднякамера', 'Задняякамера', 'заднакамера', 'артқыкамера', 'מצלמה אחורית', 'الكاميرا الخلفية', 'बैककैमरा', '后置相机', '後置鏡頭', '背面カメラ', '후면카메라', 'กล้องด้านหลัง'].map(function (s) {
3149
+ return s.toLocaleLowerCase().split(' ').join('');
3150
+ });
3151
+ var backUltraWideCameraLabels = ['backdualwidecamera', 'backultrawidecamera', 'ultraampliaposterior', 'ultra-angulartraseira', 'ultragrandeangulartraseira', 'ultragrandangle', 'ultragranangular', 'ultra-weitwinkelkamera', 'ultra-grandangolo', 'ultrabredecameraaanachterzijde', 'ultravidvinkelkamerapåbaksidan', 'ultravidvinkelkameraetpåbagsiden', 'ultravidvinkelkamerabak', 'ultragenişkameraarkayüzü', 'ultralaajakulmainentakakamera', 'tylnyaparatultraszerokokątny', 'cameracựcrộngmặtsau', 'camerăcuobiectivultra‑superangularspate', 'ultraszéleslátószögűkamera', 'kameraultralebarbelakang', 'stražnjaultraširokakamera', 'zadníultraširokoúhlýfotoaparát', 'ultraširokouhlá', 'πίσωυπερευρείακάμερα', 'заднянадширококутнакамера', 'Задняясверхширокоугольнаякамера', 'Задна свръх широкоъгълна камера', 'артқыультракеңбұрыштыкамера', 'מצלמה אולטרה רחבה אחורית', 'كاميرا خلفية عريضة جدًا', 'बैकअल्ट्रावाइडकैमरा', '后置超广角相机', '後置超廣角鏡頭相機', '背面超広角カメラ', '후면울트라와이드카메라', 'กล้องด้านหลังอัลตร้าไวด์'].map(function (s) {
3152
+ return s.toLocaleLowerCase().split(' ').join('');
3153
+ });
3154
+ var cameraLabelMatches = function cameraLabelMatches(labelOrDevice, labelSetOrLabel) {
3155
+ var label = labelOrDevice instanceof MediaDeviceInfo ? getDeviceLabel(labelOrDevice) : labelOrDevice;
3156
+ var labelSet = typeof labelSetOrLabel === 'string' ? [labelSetOrLabel] : labelSetOrLabel;
3157
+ return labelSet.some(function (l) {
3158
+ return label.includes(l);
3275
3159
  });
3276
- }
3277
-
3278
- var defaultDocumentDetectionScoreThreshold = 0.1;
3279
- var defaultDocumentDetectionModelLoadTimeoutMs = 45000;
3280
- var defaultDocumentDetectionThresholds = {
3281
- idCardFront: 0.6,
3282
- idCardBack: 0.6,
3283
- passport: 0.4,
3284
- singlePage: 0.4,
3285
- stability: {
3286
- idCardFront: 0.85,
3287
- idCardBack: 0.85,
3288
- passport: 0.5,
3289
- singlePage: 0.5
3290
- }
3291
3160
  };
3292
- var documentTypeDisplayNames = {
3293
- idCardFront: 'ID card front',
3294
- idCardBack: 'ID card back',
3295
- passport: 'Passport',
3296
- singlePage: 'Single page',
3297
- none: 'None'
3161
+ var getDeviceLabel = function getDeviceLabel(deviceInfo) {
3162
+ return deviceInfo.label.toLocaleLowerCase().split(' ').join('');
3298
3163
  };
3299
- var detector = null;
3300
- var detectorSettings = null;
3301
- function loadDocumentDetector() {
3302
- return __awaiter(this, arguments, void 0, function (modelAssetPath, scoreThreshold) {
3303
- var _a, _b;
3304
- if (modelAssetPath === void 0) {
3305
- modelAssetPath = defaultDocumentDetectorModelPath;
3306
- }
3307
- if (scoreThreshold === void 0) {
3308
- scoreThreshold = defaultDocumentDetectionScoreThreshold;
3309
- }
3310
- return __generator(this, function (_c) {
3311
- switch (_c.label) {
3312
- case 0:
3313
- if (detector && (detectorSettings === null || detectorSettings === void 0 ? void 0 : detectorSettings.modelAssetPath) === modelAssetPath && (detectorSettings === null || detectorSettings === void 0 ? void 0 : detectorSettings.scoreThreshold) === scoreThreshold) return [2 /*return*/, detector];
3314
- closeDocumentDetector();
3315
- return [4 /*yield*/, preloadDocumentDetectorDependencies()];
3316
- case 1:
3317
- _c.sent();
3318
- if (modelCapabilities.delegate === 'NONE') {
3319
- throw new Error('No available delegate for document detector.');
3320
- }
3321
- _b = (_a = tasksVision.ObjectDetector).createFromOptions;
3322
- return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
3323
- case 2:
3324
- return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
3325
- baseOptions: {
3326
- modelAssetPath: modelAssetPath,
3327
- delegate: modelCapabilities.delegate
3328
- },
3329
- // canvas: document.createElement('canvas'),
3330
- scoreThreshold: scoreThreshold,
3331
- runningMode: 'VIDEO'
3332
- }])];
3333
- case 3:
3334
- detector = _c.sent();
3335
- detectorSettings = {
3336
- modelAssetPath: modelAssetPath,
3337
- scoreThreshold: scoreThreshold
3338
- };
3339
- return [2 /*return*/, detector];
3340
- }
3341
- });
3342
- });
3343
- }
3344
- function closeDocumentDetector() {
3345
- detector === null || detector === void 0 ? void 0 : detector.close();
3346
- detector = null;
3347
- detectorSettings = null;
3348
- }
3349
- function useLoadDocumentDetector(_a) {
3350
- var _b = _a.shouldLoadModels,
3351
- shouldLoadModels = _b === void 0 ? true : _b,
3352
- _c = _a.modelPath,
3353
- modelPath = _c === void 0 ? defaultDocumentDetectorModelPath : _c,
3354
- _d = _a.modelLoadTimeoutMs,
3355
- modelLoadTimeoutMs = _d === void 0 ? defaultDocumentDetectionModelLoadTimeoutMs : _d,
3356
- _e = _a.scoreThreshold,
3357
- scoreThreshold = _e === void 0 ? defaultDocumentDetectionScoreThreshold : _e,
3358
- onModelError = _a.onModelError,
3359
- videoRef = _a.videoRef;
3360
- var _f = React.useState('not-started'),
3361
- modelLoadState = _f[0],
3362
- setModelLoadState = _f[1];
3363
- var _g = React.useState(null),
3364
- modelWarmingStartedAt = _g[0],
3365
- setModelWarmingStartedAt = _g[1];
3366
- var _h = React.useState(0),
3367
- modelDownloadProgress = _h[0],
3368
- setModelDownloadProgress = _h[1];
3369
- var _j = React.useState(null),
3370
- modelError = _j[0],
3371
- setModelError = _j[1];
3372
- React.useEffect(function loadModel() {
3373
- var _this = this;
3374
- if (!shouldLoadModels) return;
3375
- setModelLoadState('downloading');
3376
- setModelWarmingStartedAt(null);
3377
- function handleDownloadProgress(event) {
3378
- setModelDownloadProgress(progressToPercentage(event.detail));
3379
- }
3380
- document.addEventListener('idmission.preloadProgress.documentDetection', handleDownloadProgress);
3381
- var modelLoadTimeout = setTimeout(function () {
3382
- setModelError(new Error('Model loading time limit exceeded.'));
3383
- }, modelLoadTimeoutMs);
3384
- var cancelVideoReady = function cancelVideoReady() {};
3385
- loadDocumentDetector(modelPath, scoreThreshold).then(function (model) {
3386
- return __awaiter(_this, void 0, void 0, function () {
3387
- var _a, videoReady, cancel, cancelled;
3388
- return __generator(this, function (_b) {
3389
- switch (_b.label) {
3390
- case 0:
3391
- setModelDownloadProgress(100);
3392
- setModelLoadState('warming');
3393
- setModelWarmingStartedAt(new Date().getTime());
3394
- clearTimeout(modelLoadTimeout);
3395
- return [4 /*yield*/, testDocumentDetectionAgainstKnownImage(model)];
3396
- case 1:
3397
- _b.sent();
3398
- _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
3399
- cancelled = false;
3400
- cancelVideoReady = function cancelVideoReady() {
3401
- cancelled = true;
3402
- cancel();
3403
- };
3404
- return [4 /*yield*/, videoReady];
3405
- case 2:
3406
- _b.sent();
3407
- setTimeout(function () {
3408
- if (cancelled) return;
3409
- model.detectForVideo(videoRef.current, performance.now());
3410
- setModelLoadState('ready');
3411
- }, 500);
3412
- return [2 /*return*/];
3413
- }
3414
- });
3415
- });
3416
- })["catch"](function (e) {
3417
- setModelError(e);
3418
- setModelLoadState('error');
3419
- })["finally"](function () {
3420
- clearTimeout(modelLoadTimeout);
3421
- });
3422
- return function () {
3423
- log('unloading document detection model');
3424
- cancelVideoReady();
3425
- closeDocumentDetector();
3426
- clearTimeout(modelLoadTimeout);
3427
- document.removeEventListener('idmission.preloadProgress.documentDetection', handleDownloadProgress);
3428
- };
3429
- }, [shouldLoadModels, modelLoadTimeoutMs, modelPath, scoreThreshold, videoRef]);
3430
- React.useEffect(function handleModelError() {
3431
- if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
3432
- }, [modelError, onModelError]);
3433
- return React.useMemo(function () {
3434
- return {
3435
- ready: modelLoadState === 'ready',
3436
- modelLoadState: modelLoadState,
3437
- modelDownloadProgress: modelDownloadProgress,
3438
- modelWarmingStartedAt: modelWarmingStartedAt,
3439
- modelError: modelError,
3440
- setModelError: setModelError
3441
- };
3442
- }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
3443
- }
3444
- function makeDocumentDetectorPrediction(frame) {
3445
- return __awaiter(this, void 0, void 0, function () {
3446
- var startedAt, prediction, time, frameWidth, frameHeight;
3447
- return __generator(this, function (_a) {
3448
- if (!detector) return [2 /*return*/, null];
3449
- startedAt = new Date();
3450
- // Detectors can throw errors, for example when using custom URLs that
3451
- // contain a model that doesn't provide the expected output.
3452
- try {
3453
- prediction = detector.detectForVideo(frame, performance.now());
3454
- time = new Date().getTime() - startedAt.getTime();
3455
- frameWidth = frame.width;
3456
- frameHeight = frame.height;
3457
- return [2 /*return*/, _assign(_assign({}, prediction), {
3458
- time: time,
3459
- frameWidth: frameWidth,
3460
- frameHeight: frameHeight
3461
- })];
3462
- } catch (e) {
3463
- error('caught object detection error', e);
3464
- }
3465
- return [2 /*return*/, null];
3466
- });
3467
- });
3468
- }
3469
- var lastDetectionAt = 0;
3470
- var lastDetectionTime = 0;
3471
- function setLastDetectionAt(time) {
3472
- lastDetectionTime = time - lastDetectionAt;
3473
- lastDetectionAt = time;
3474
- }
3475
- var framesNeededSamples = [];
3476
- function trackFramesNeeded(value, bufferLength) {
3477
- if (bufferLength === void 0) {
3478
- bufferLength = 25;
3479
- }
3480
- framesNeededSamples.unshift(value);
3481
- if (framesNeededSamples.length > bufferLength) framesNeededSamples.length = bufferLength;
3482
- }
3483
- var lastNBoxes = [];
3484
- var lastNPairs = [];
3485
- function trackBox(box, framesNeeded) {
3486
- if (framesNeeded === void 0) {
3487
- framesNeeded = 12;
3488
- }
3489
- lastNBoxes.unshift(box);
3490
- if (lastNBoxes.length > framesNeeded) lastNBoxes.length = framesNeeded;
3491
- if (lastNBoxes.length > 1) {
3492
- var lastBox = lastNBoxes[1];
3493
- var iou = calculateIoU(box, lastBox);
3494
- lastNPairs.unshift({
3495
- a: box,
3496
- b: lastBox,
3497
- iou: iou
3498
- });
3499
- if (lastNPairs.length > framesNeeded - 1) lastNPairs.length = framesNeeded - 1;
3500
- }
3501
- }
3502
- var defaultDocumentDetectionBoundaries = {
3503
- top: 20,
3504
- bottom: 20,
3505
- left: 20,
3506
- right: 20
3507
- };
3508
- function processDocumentDetectorPrediction(prediction, thresholds, boundaries) {
3509
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
3510
- if (boundaries === void 0) {
3511
- boundaries = defaultDocumentDetectionBoundaries;
3512
- }
3513
- var detections = prediction.detections,
3514
- frameWidth = prediction.frameWidth,
3515
- frameHeight = prediction.frameHeight,
3516
- time = prediction.time;
3517
- var boundaryTop = (_a = boundaries.top) !== null && _a !== void 0 ? _a : 20;
3518
- var boundaryLeft = (_b = boundaries.left) !== null && _b !== void 0 ? _b : 20;
3519
- var boundaryRight = (_c = boundaries.right) !== null && _c !== void 0 ? _c : 20;
3520
- var boundaryBottom = (_d = boundaries.bottom) !== null && _d !== void 0 ? _d : 20;
3521
- var frameWidth80Pct = frameWidth * 0.8;
3522
- var detectedObjects = applyNonMaxSuppression(detections.flatMap(function (d) {
3523
- return d.categories.map(function (category) {
3524
- return {
3525
- label: category === null || category === void 0 ? void 0 : category.categoryName,
3526
- score: category === null || category === void 0 ? void 0 : category.score,
3527
- box: convertBoundingBox(d.boundingBox)
3528
- };
3529
- });
3530
- }), function (obj) {
3531
- var _a = obj.box,
3532
- xMin = _a.xMin,
3533
- yMin = _a.yMin,
3534
- width = _a.width,
3535
- height = _a.height;
3536
- return yMin > boundaryTop &&
3537
- // Is it valid top edge of ID detected?
3538
- yMin + height + boundaryBottom < frameHeight && (
3539
- // Is it valid bottom edge less than max video height
3540
- xMin > boundaryLeft || xMin + width > frameWidth80Pct) &&
3541
- // If either the left side visible or if not, right edge of ID should be more than 80% of width.
3542
- xMin + width + boundaryRight < frameWidth // Valid right edge if it's less than video width.
3543
- ;
3544
- });
3545
- var allZero = detections.length > 0 && !detections.some(function (_a) {
3546
- var boundingBox = _a.boundingBox;
3547
- return Object.values(boundingBox !== null && boundingBox !== void 0 ? boundingBox : {}).some(function (n) {
3548
- return n > 0;
3549
- });
3550
- });
3551
- var bestIdCardFront = detectedObjects.find(function (obj) {
3552
- return obj.label === 'Document';
3553
- });
3554
- var bestIdCardBack = detectedObjects.find(function (obj) {
3555
- return obj.label === 'Document back';
3556
- });
3557
- var bestPassportPage = detectedObjects.find(function (obj) {
3558
- return obj.label === 'Passport page';
3559
- });
3560
- var bestSinglePage = detectedObjects.find(function (obj) {
3561
- return obj.label === 'Single page';
3562
- });
3563
- var idCardFrontDetectionScore = (_e = bestIdCardFront === null || bestIdCardFront === void 0 ? void 0 : bestIdCardFront.score) !== null && _e !== void 0 ? _e : 0;
3564
- var idCardBackDetectionScore = (_f = bestIdCardBack === null || bestIdCardBack === void 0 ? void 0 : bestIdCardBack.score) !== null && _f !== void 0 ? _f : 0;
3565
- var passportDetectionScore = (_g = bestPassportPage === null || bestPassportPage === void 0 ? void 0 : bestPassportPage.score) !== null && _g !== void 0 ? _g : 0;
3566
- var singlePageDetectionScore = (_h = bestSinglePage === null || bestSinglePage === void 0 ? void 0 : bestSinglePage.score) !== null && _h !== void 0 ? _h : 0;
3567
- var idCardFrontDetectionThresholdMet = idCardFrontDetectionScore >= ((_j = thresholds.idCardFront) !== null && _j !== void 0 ? _j : 0);
3568
- var idCardBackDetectionThresholdMet = idCardBackDetectionScore >= ((_k = thresholds.idCardBack) !== null && _k !== void 0 ? _k : 0);
3569
- var passportDetectionThresholdMet = passportDetectionScore >= ((_l = thresholds.passport) !== null && _l !== void 0 ? _l : 0);
3570
- var singlePageDetectionThresholdMet = singlePageDetectionScore >= ((_m = thresholds.singlePage) !== null && _m !== void 0 ? _m : 0);
3571
- var bestDocument = singlePageDetectionThresholdMet ? bestSinglePage : passportDetectionThresholdMet ? bestPassportPage : idCardBackDetectionThresholdMet ? bestIdCardBack : bestIdCardFront;
3572
- var detectionThreshold = singlePageDetectionThresholdMet ? thresholds.singlePage : passportDetectionThresholdMet ? thresholds.passport : idCardBackDetectionThresholdMet ? thresholds.idCardBack : thresholds.idCardFront;
3573
- var detectionScore = (_o = bestDocument === null || bestDocument === void 0 ? void 0 : bestDocument.score) !== null && _o !== void 0 ? _o : 0;
3574
- var detectionThresholdMet = detectionScore >= (detectionThreshold !== null && detectionThreshold !== void 0 ? detectionThreshold : 0);
3575
- var detectedDocumentType = 'none';
3576
- if (singlePageDetectionThresholdMet) {
3577
- detectedDocumentType = 'singlePage';
3578
- } else if (passportDetectionThresholdMet) {
3579
- detectedDocumentType = 'passport';
3580
- } else if (idCardBackDetectionThresholdMet) {
3581
- detectedDocumentType = 'idCardBack';
3582
- } else if (detectionThresholdMet) {
3583
- detectedDocumentType = 'idCardFront';
3584
- }
3585
- var documentInBounds = !!bestDocument;
3586
- if (lastDetectionTime > 0) {
3587
- trackFramesNeeded(1000 / lastDetectionTime);
3588
- }
3589
- var documentIsStable = false;
3590
- var documentTooClose = false;
3591
- if (bestDocument) {
3592
- var _q = [bestDocument.box.width / frameWidth, bestDocument.box.height / frameHeight],
3593
- docWidth = _q[0],
3594
- docHeight = _q[1];
3595
- documentTooClose = docWidth > 0.85 || docHeight > 0.85;
3596
- if (detectionThresholdMet && documentInBounds && !documentTooClose) {
3597
- var thresholdSet = (_p = thresholds.stability) !== null && _p !== void 0 ? _p : defaultDocumentDetectionThresholds.stability;
3598
- var threshold_1 = thresholdSet[detectedDocumentType];
3599
- var framesNeeded = Math.ceil(average(framesNeededSamples));
3600
- trackBox(bestDocument.box, framesNeeded);
3601
- documentIsStable = lastNBoxes.length >= framesNeeded && !lastNPairs.some(function (pair) {
3602
- return pair.iou < threshold_1;
3603
- });
3604
- }
3605
- }
3606
- return {
3607
- prediction: prediction,
3608
- detectedObjects: detectedObjects,
3609
- detectionScore: detectionScore,
3610
- detectionTime: time,
3611
- detectionThresholdMet: detectionThresholdMet,
3612
- detectedDocumentType: detectedDocumentType,
3613
- idCardFrontDetectionScore: idCardFrontDetectionScore,
3614
- idCardFrontDetectionThresholdMet: idCardFrontDetectionThresholdMet,
3615
- idCardBackDetectionScore: idCardBackDetectionScore,
3616
- idCardBackDetectionThresholdMet: idCardBackDetectionThresholdMet,
3617
- passportDetectionScore: passportDetectionScore,
3618
- passportDetectionThresholdMet: passportDetectionThresholdMet,
3619
- singlePageDetectionScore: singlePageDetectionScore,
3620
- singlePageDetectionThresholdMet: singlePageDetectionThresholdMet,
3621
- bestDocument: bestDocument,
3622
- documentInBounds: documentInBounds,
3623
- documentTooClose: documentTooClose,
3624
- documentIsStable: documentIsStable,
3625
- frameWidth: frameWidth,
3626
- frameHeight: frameHeight,
3627
- allZero: allZero
3628
- };
3629
- }
3630
- function applyNonMaxSuppression(detectedObjects, isGoodBox) {
3631
- var maxes = {};
3632
- detectedObjects.forEach(function (obj, i) {
3633
- if (obj) {
3634
- if (!maxes[obj.label]) maxes[obj.label] = [0, -1];
3635
- if (obj.score > maxes[obj.label][0] && (isGoodBox === null || isGoodBox === void 0 ? void 0 : isGoodBox(obj))) maxes[obj.label] = [obj.score, i];
3636
- }
3637
- });
3638
- return Object.keys(maxes).map(function (label) {
3639
- return detectedObjects[maxes[label][1]];
3640
- }).filter(function (obj) {
3641
- return !!obj;
3642
- });
3643
- }
3644
- function testDocumentDetectionAgainstKnownImage(detector) {
3645
- return new Promise(function (resolve, reject) {
3646
- var img = new Image();
3647
- img.crossOrigin = 'anonymous';
3648
- img.onload = function () {
3649
- var prediction = detector.detectForVideo(img, performance.now());
3650
- if (prediction.detections.length > 0) {
3651
- debug('document detection test result', prediction.detections);
3652
- resolve(void 0);
3653
- } else {
3654
- warn('document detection test failed');
3655
- reject(new Error('testDocumentDetectionAgainstKnownImage failed to predict'));
3656
- }
3657
- };
3658
- img.onerror = function () {
3659
- return reject(new Error('testDocumentDetectionAgainstKnownImage failed to load image'));
3660
- };
3661
- img.src = "".concat(DEFAULT_CDN_URL, "/id-card-test.jpg");
3662
- });
3663
- }
3664
-
3665
- function useFrameLoop(fn, options) {
3666
- if (options === void 0) {
3667
- options = {};
3668
- }
3669
- var _a = React.useState(false),
3670
- running = _a[0],
3671
- setRunning = _a[1];
3672
- var startedAtRef = React.useRef(null);
3673
- var loopId = React.useRef(0);
3674
- var frameId = React.useRef(0);
3675
- React.useEffect(function runFrameLoop() {
3676
- if (!running) return;
3677
- var timer;
3678
- var currentLoopId = loopId.current;
3679
- function hotLoop() {
3680
- return __awaiter(this, void 0, void 0, function () {
3681
- var start, timeRunning, took, amountToThrottle;
3682
- var _a, _b, _c;
3683
- return __generator(this, function (_d) {
3684
- switch (_d.label) {
3685
- case 0:
3686
- if (currentLoopId !== loopId.current) return [2 /*return*/];
3687
- start = new Date().getTime();
3688
- timeRunning = start - ((_b = (_a = startedAtRef.current) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : 0);
3689
- return [4 /*yield*/, fn(frameId.current, timeRunning)];
3690
- case 1:
3691
- _d.sent();
3692
- took = new Date().getTime() - start;
3693
- amountToThrottle = Math.max(((_c = options.throttleMs) !== null && _c !== void 0 ? _c : 0) - took, 0);
3694
- timer = setTimeout(function () {
3695
- frameId.current = requestAnimationFrame(hotLoop);
3696
- }, amountToThrottle);
3697
- return [2 /*return*/];
3698
- }
3699
- });
3700
- });
3701
- }
3702
- void hotLoop();
3703
- return function () {
3704
- loopId.current += 1;
3705
- if (frameId.current) cancelAnimationFrame(frameId.current);
3706
- if (timer) clearTimeout(timer);
3707
- };
3708
- }, [fn, running, options.throttleMs]);
3709
- var start = React.useCallback(function () {
3710
- startedAtRef.current = new Date();
3711
- setRunning(true);
3712
- }, []);
3713
- var stop = React.useCallback(function () {
3714
- loopId.current += 1; // force the loop to stop immediately.
3715
- setRunning(false);
3716
- startedAtRef.current = null;
3717
- }, []);
3718
- React.useEffect(function startAutomatically() {
3719
- if (options.autoStart) start();
3720
- return stop;
3721
- }, [options.autoStart, start, stop]);
3722
- return {
3723
- start: start,
3724
- stop: stop
3725
- };
3726
- }
3727
-
3728
- function listAvailableCameras(facingMode_1) {
3729
- return __awaiter(this, arguments, void 0, function (facingMode, requestMicAccess) {
3730
- var cameraEnumerationStream, allDevices, allowedVideoDevices;
3731
- if (requestMicAccess === void 0) {
3732
- requestMicAccess = false;
3733
- }
3734
- return __generator(this, function (_a) {
3735
- switch (_a.label) {
3736
- case 0:
3737
- return [4 /*yield*/, navigator.mediaDevices.getUserMedia({
3738
- video: {
3739
- facingMode: {
3740
- exact: facingMode
3741
- }
3742
- },
3743
- audio: requestMicAccess
3744
- })
3745
- // This lists all available cameras attached to the user's device.
3746
- ];
3747
- case 1:
3748
- cameraEnumerationStream = _a.sent();
3749
- return [4 /*yield*/, navigator.mediaDevices.enumerateDevices()];
3750
- case 2:
3751
- allDevices = _a.sent();
3752
- allowedVideoDevices = allDevices.filter(function (_a) {
3753
- var kind = _a.kind,
3754
- label = _a.label;
3755
- return kind === 'videoinput' && !label.toLowerCase().includes('virtual');
3756
- });
3757
- // Release the access to the user's camera that we obtained for enumeration purposes.
3758
- cameraEnumerationStream.getVideoTracks().forEach(function (track) {
3759
- track.enabled = false;
3760
- track.stop();
3761
- });
3762
- cameraEnumerationStream = null;
3763
- return [2 /*return*/, allowedVideoDevices];
3764
- }
3765
- });
3766
- });
3767
- }
3768
- var frontCameraLabels = ['front', 'avant', 'anteriore', 'cameraaanvoorzijde', 'kamerapåframsidan', 'forsidekamera', 'kamerapåforsiden', 'aparatprzedni', 'etukamera', 'kameradepan', 'ÖnKamera', 'cameramặttrước', 'camerăfață', 'prednákamera', 'prednjakamera', 'előlapikamera', 'přednífotoaparát', 'μπροστινήκάμερα', 'переднякамера', 'передняякамера', 'преднакамера', 'алдыңғыкамера', 'מצלמה קדמית', 'الكاميرا الأمامية', 'फ़्रंटकैमरा', '前置相机', '前置鏡頭', '前面カメラ', '전면카메라', 'กล้องด้านหน้า'].map(function (s) {
3769
- return s.toLocaleLowerCase().split(' ').join('');
3770
- });
3771
- var rearCameraLabels = ['back', 'rear', 'posterior', 'trasera', 'traseira', 'arrière', 'rückkamera', 'fotocamera(posteriore)', 'cameraaanachterzijde', 'kamerapåbaksidan', 'kamerapåbaksiden', 'bagsidekamera', 'aparattylny', 'takakamera', 'arkakamera', 'kamerabelakang', 'cameramặtsau', 'camerăspate', 'stražnjakamera', 'zadnákamera', 'hátoldalikamera', 'zadnífotoaparát', 'πίσωκάμερα', 'заднякамера', 'Задняякамера', 'заднакамера', 'артқыкамера', 'מצלמה אחורית', 'الكاميرا الخلفية', 'बैककैमरा', '后置相机', '後置鏡頭', '背面カメラ', '후면카메라', 'กล้องด้านหลัง'].map(function (s) {
3772
- return s.toLocaleLowerCase().split(' ').join('');
3773
- });
3774
- var backUltraWideCameraLabels = ['backdualwidecamera', 'backultrawidecamera', 'ultraampliaposterior', 'ultra-angulartraseira', 'ultragrandeangulartraseira', 'ultragrandangle', 'ultragranangular', 'ultra-weitwinkelkamera', 'ultra-grandangolo', 'ultrabredecameraaanachterzijde', 'ultravidvinkelkamerapåbaksidan', 'ultravidvinkelkameraetpåbagsiden', 'ultravidvinkelkamerabak', 'ultragenişkameraarkayüzü', 'ultralaajakulmainentakakamera', 'tylnyaparatultraszerokokątny', 'cameracựcrộngmặtsau', 'camerăcuobiectivultra‑superangularspate', 'ultraszéleslátószögűkamera', 'kameraultralebarbelakang', 'stražnjaultraširokakamera', 'zadníultraširokoúhlýfotoaparát', 'ultraširokouhlá', 'πίσωυπερευρείακάμερα', 'заднянадширококутнакамера', 'Задняясверхширокоугольнаякамера', 'Задна свръх широкоъгълна камера', 'артқыультракеңбұрыштыкамера', 'מצלמה אולטרה רחבה אחורית', 'كاميرا خلفية عريضة جدًا', 'बैकअल्ट्रावाइडकैमरा', '后置超广角相机', '後置超廣角鏡頭相機', '背面超広角カメラ', '후면울트라와이드카메라', 'กล้องด้านหลังอัลตร้าไวด์'].map(function (s) {
3775
- return s.toLocaleLowerCase().split(' ').join('');
3776
- });
3777
- var cameraLabelMatches = function cameraLabelMatches(labelOrDevice, labelSetOrLabel) {
3778
- var label = labelOrDevice instanceof MediaDeviceInfo ? getDeviceLabel(labelOrDevice) : labelOrDevice;
3779
- var labelSet = typeof labelSetOrLabel === 'string' ? [labelSetOrLabel] : labelSetOrLabel;
3780
- return labelSet.some(function (l) {
3781
- return label.includes(l);
3782
- });
3783
- };
3784
- var getDeviceLabel = function getDeviceLabel(deviceInfo) {
3785
- return deviceInfo.label.toLocaleLowerCase().split(' ').join('');
3786
- };
3787
- var currentCamera;
3788
- function obtainCameraAccess(stream, deviceLabel, video) {
3789
- releaseCameraAccess();
3790
- log('obtaining camera access...');
3791
- var _a = stream.getVideoTracks()[0].getSettings(),
3792
- width = _a.width,
3793
- height = _a.height;
3794
- log('camera dimensions', width, height);
3795
- var label = deviceLabel.toLocaleLowerCase().split(' ').join('');
3796
- log('camera label', label);
3797
- var isRearFacing = cameraLabelMatches(label, __spreadArray(__spreadArray(__spreadArray([], rearCameraLabels, true), backUltraWideCameraLabels, true), ['iphone'], false));
3798
- log('is rear facing?', isRearFacing);
3799
- var release = function release() {
3800
- stream.getTracks().forEach(function (track) {
3801
- track.enabled = false;
3802
- track.stop();
3803
- });
3804
- if (video) {
3805
- video.pause();
3806
- video.srcObject = null;
3807
- video.src = '';
3164
+ var currentCamera;
3165
+ function obtainCameraAccess(stream, deviceLabel, video) {
3166
+ releaseCameraAccess();
3167
+ log('obtaining camera access...');
3168
+ var _a = stream.getVideoTracks()[0].getSettings(),
3169
+ width = _a.width,
3170
+ height = _a.height;
3171
+ log('camera dimensions', width, height);
3172
+ var label = deviceLabel.toLocaleLowerCase().split(' ').join('');
3173
+ log('camera label', label);
3174
+ var isRearFacing = cameraLabelMatches(label, __spreadArray(__spreadArray(__spreadArray([], rearCameraLabels, true), backUltraWideCameraLabels, true), ['iphone'], false));
3175
+ log('is rear facing?', isRearFacing);
3176
+ var release = function release() {
3177
+ stream.getTracks().forEach(function (track) {
3178
+ track.enabled = false;
3179
+ track.stop();
3180
+ });
3181
+ if (video) {
3182
+ video.pause();
3183
+ video.srcObject = null;
3184
+ video.src = '';
3808
3185
  }
3809
3186
  };
3810
3187
  width || (width = 0);
@@ -5609,29 +4986,294 @@ function DocumentDetectionModelProvider(_a) {
5609
4986
  }, []);
5610
4987
  var value = React.useMemo(function () {
5611
4988
  return {
5612
- startDocumentDetection: start,
5613
- stopDocumentDetection: stop,
5614
- loadDocumentDetectionModel: load,
5615
- documentDetectionModelState: modelLoadState,
5616
- documentDetectionModelWarmingStartedAt: modelWarmingStartedAt,
5617
- documentDetectionModelError: modelError,
5618
- documentDetectionModelDownloadProgress: modelDownloadProgress,
5619
- onDocumentDetected: onDocumentDetected,
5620
- detectionTime: lastDetectionTime,
5621
- documentDetectionThresholds: documentDetectionThresholds,
5622
- setDocumentDetectionThresholds: setDocumentDetectionThresholds,
5623
- documentDetectionBoundaries: documentDetectionBoundaries,
5624
- setDocumentDetectionBoundaries: setDocumentDetectionBoundaries,
5625
- documentDetectionLastPredictionCanvas: lastPredictionCanvas,
5626
- clearDocumentDetectionLastPredictionCanvas: clearDocumentDetectionLastPredictionCanvas
4989
+ startDocumentDetection: start,
4990
+ stopDocumentDetection: stop,
4991
+ loadDocumentDetectionModel: load,
4992
+ documentDetectionModelState: modelLoadState,
4993
+ documentDetectionModelWarmingStartedAt: modelWarmingStartedAt,
4994
+ documentDetectionModelError: modelError,
4995
+ documentDetectionModelDownloadProgress: modelDownloadProgress,
4996
+ onDocumentDetected: onDocumentDetected,
4997
+ detectionTime: lastDetectionTime,
4998
+ documentDetectionThresholds: documentDetectionThresholds,
4999
+ setDocumentDetectionThresholds: setDocumentDetectionThresholds,
5000
+ documentDetectionBoundaries: documentDetectionBoundaries,
5001
+ setDocumentDetectionBoundaries: setDocumentDetectionBoundaries,
5002
+ documentDetectionLastPredictionCanvas: lastPredictionCanvas,
5003
+ clearDocumentDetectionLastPredictionCanvas: clearDocumentDetectionLastPredictionCanvas
5004
+ };
5005
+ }, [start, stop, load, modelLoadState, modelWarmingStartedAt, modelError, modelDownloadProgress, onDocumentDetected, documentDetectionThresholds, documentDetectionBoundaries, clearDocumentDetectionLastPredictionCanvas]);
5006
+ return /*#__PURE__*/React__namespace.createElement(DocumentDetectionModelContext.Provider, {
5007
+ value: value
5008
+ }, /*#__PURE__*/React__namespace.createElement(InvisibleCanvas, {
5009
+ key: canvasKey,
5010
+ ref: lastPredictionCanvas
5011
+ }), children);
5012
+ }
5013
+
5014
+ function cropToShoulders(rawCanvas, cropCanvas, resizeCanvas, frame, face, quality, maxHeight) {
5015
+ var _a;
5016
+ if (quality === void 0) {
5017
+ quality = 0.92;
5018
+ }
5019
+ if (!rawCanvas || !cropCanvas || !resizeCanvas) return '';
5020
+ var rawCtx = rawCanvas.getContext('2d');
5021
+ var cropCtx = cropCanvas.getContext('2d');
5022
+ var resizeCtx = resizeCanvas.getContext('2d');
5023
+ if (!rawCtx || !cropCtx || !resizeCtx) throw new Error('could not get 2d context');
5024
+ rawCanvas.width = frame.width;
5025
+ rawCanvas.height = frame.height;
5026
+ rawCtx.putImageData(frame, 0, 0);
5027
+ if (frame.height > frame.width) {
5028
+ cropCanvas.width = frame.width;
5029
+ cropCanvas.height = frame.height;
5030
+ cropCtx.drawImage(rawCanvas, 0, 0, cropCanvas.width, cropCanvas.height);
5031
+ } else {
5032
+ var _b = (_a = face === null || face === void 0 ? void 0 : face.box) !== null && _a !== void 0 ? _a : {
5033
+ xMin: 0,
5034
+ width: frame.width
5035
+ },
5036
+ xMin = _b.xMin,
5037
+ width = _b.width;
5038
+ var desiredWidth = frame.height * 0.6;
5039
+ var faceCenterX = xMin + width / 2;
5040
+ var xPos = Math.max(0, faceCenterX - desiredWidth / 2);
5041
+ cropCanvas.width = desiredWidth;
5042
+ cropCanvas.height = frame.height;
5043
+ cropCtx.drawImage(rawCanvas, xPos, 0, cropCanvas.width, cropCanvas.height, 0, 0, cropCanvas.width, cropCanvas.height);
5044
+ }
5045
+ resizeCanvas.height = maxHeight !== null && maxHeight !== void 0 ? maxHeight : cropCanvas.height;
5046
+ resizeCanvas.width = cropCanvas.width * (resizeCanvas.height / cropCanvas.height);
5047
+ resizeCtx === null || resizeCtx === void 0 ? void 0 : resizeCtx.drawImage(cropCanvas, 0, 0, resizeCanvas.width, resizeCanvas.height);
5048
+ var dataURL = resizeCanvas.toDataURL('image/jpeg', quality);
5049
+ log('cropToShoulders size', new TextEncoder().encode(dataURL).length);
5050
+ clearCanvas(rawCanvas);
5051
+ clearCanvas(cropCanvas);
5052
+ clearCanvas(resizeCanvas);
5053
+ return dataURL;
5054
+ }
5055
+ function cropToDetectedObjectBox(frame, box, canvas, padding) {
5056
+ if (padding === void 0) {
5057
+ padding = 0;
5058
+ }
5059
+ canvas || (canvas = document.createElement('canvas'));
5060
+ var ctx = canvas.getContext('2d');
5061
+ if (!ctx) throw new Error('could not get 2d context');
5062
+ var xMin = box.xMin,
5063
+ yMin = box.yMin,
5064
+ width = box.width,
5065
+ height = box.height;
5066
+ canvas.width = width + padding * 2;
5067
+ canvas.height = height + padding * 2;
5068
+ ctx.drawImage(frame, xMin - padding, yMin - padding, width + padding * 2, height + padding * 2, 0, 0, canvas.width, canvas.height);
5069
+ return canvas;
5070
+ }
5071
+ function cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box, padding) {
5072
+ if (padding === void 0) {
5073
+ padding = 0;
5074
+ }
5075
+ if (!box) return imageData;
5076
+ var cropped = cropToDetectedObjectBox(imageData, box, cropCanvas, padding);
5077
+ var _a = [box.width, box.height],
5078
+ bw = _a[0],
5079
+ bh = _a[1];
5080
+ if (bh <= bw) return cropped;
5081
+ var ctx = rotateCanvas.getContext('2d');
5082
+ if (!ctx) return cropped;
5083
+ rotateCanvas.width = bh;
5084
+ rotateCanvas.height = bw;
5085
+ ctx.clearRect(0, 0, rotateCanvas.width, rotateCanvas.height);
5086
+ ctx.translate(rotateCanvas.width / 2, rotateCanvas.height / 2);
5087
+ ctx.rotate(1.5708); // 90 deg in radians
5088
+ ctx.drawImage(cropped, -bw / 2, -bh / 2);
5089
+ return rotateCanvas;
5090
+ }
5091
+ function resizeIfNecessary(imageData, resizeCanvas, maxWidth) {
5092
+ var width = imageData.width,
5093
+ height = imageData.height;
5094
+ if (width <= maxWidth) return imageData;
5095
+ var resizeCtx = resizeCanvas.getContext('2d');
5096
+ if (!resizeCtx) return imageData;
5097
+ var scale = maxWidth / width;
5098
+ resizeCanvas.width = maxWidth;
5099
+ resizeCanvas.height = height * scale;
5100
+ resizeCtx.drawImage(imageData, 0, 0, resizeCanvas.width, resizeCanvas.height);
5101
+ return resizeCanvas;
5102
+ }
5103
+
5104
+ var defaultFocusModelLoadTimeoutMs = 45000;
5105
+ var defaultFocusThresholds = {
5106
+ idCardFront: {
5107
+ desktop: 0,
5108
+ mobile: 0.3
5109
+ },
5110
+ idCardBack: {
5111
+ desktop: 0,
5112
+ mobile: 0.3
5113
+ },
5114
+ passport: {
5115
+ desktop: 0,
5116
+ mobile: 0.3
5117
+ },
5118
+ singlePage: {
5119
+ desktop: 0,
5120
+ mobile: 0.3
5121
+ }
5122
+ };
5123
+ var classifier$1 = null;
5124
+ var classifierSettings$1 = null;
5125
+ function loadFocusModel() {
5126
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
5127
+ var _a, _b;
5128
+ if (modelAssetPath === void 0) {
5129
+ modelAssetPath = defaultFocusModelPath;
5130
+ }
5131
+ return __generator(this, function (_c) {
5132
+ switch (_c.label) {
5133
+ case 0:
5134
+ if (classifier$1 && (classifierSettings$1 === null || classifierSettings$1 === void 0 ? void 0 : classifierSettings$1.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier$1];
5135
+ closeFocusModel();
5136
+ return [4 /*yield*/, preloadFocusModelDependencies()];
5137
+ case 1:
5138
+ _c.sent();
5139
+ if (modelCapabilities.delegate === 'NONE') {
5140
+ throw new Error('No available delegate for focus detector.');
5141
+ }
5142
+ _b = (_a = tasksVision.ImageClassifier).createFromOptions;
5143
+ return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
5144
+ case 2:
5145
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
5146
+ baseOptions: {
5147
+ modelAssetPath: modelAssetPath,
5148
+ delegate: modelCapabilities.delegate
5149
+ },
5150
+ // canvas: document.createElement('canvas'),
5151
+ runningMode: 'VIDEO'
5152
+ }])];
5153
+ case 3:
5154
+ classifier$1 = _c.sent();
5155
+ classifierSettings$1 = {
5156
+ modelAssetPath: modelAssetPath
5157
+ };
5158
+ return [2 /*return*/, classifier$1];
5159
+ }
5160
+ });
5161
+ });
5162
+ }
5163
+ function closeFocusModel() {
5164
+ classifier$1 === null || classifier$1 === void 0 ? void 0 : classifier$1.close();
5165
+ classifier$1 = null;
5166
+ classifierSettings$1 = null;
5167
+ }
5168
+ function useLoadFocusModel(_a) {
5169
+ var _b = _a.modelPath,
5170
+ modelPath = _b === void 0 ? defaultFocusModelPath : _b,
5171
+ _c = _a.modelLoadTimeoutMs,
5172
+ modelLoadTimeoutMs = _c === void 0 ? defaultFocusModelLoadTimeoutMs : _c,
5173
+ onModelError = _a.onModelError,
5174
+ videoRef = _a.videoRef,
5175
+ _d = _a.shouldLoadModels,
5176
+ shouldLoadModels = _d === void 0 ? true : _d;
5177
+ var _e = React.useState('not-started'),
5178
+ modelLoadState = _e[0],
5179
+ setModelLoadState = _e[1];
5180
+ var _f = React.useState(0),
5181
+ modelDownloadProgress = _f[0],
5182
+ setModelDownloadProgress = _f[1];
5183
+ var _g = React.useState(null),
5184
+ modelWarmingStartedAt = _g[0],
5185
+ setModelWarmingStartedAt = _g[1];
5186
+ var _h = React.useState(null),
5187
+ modelError = _h[0],
5188
+ setModelError = _h[1];
5189
+ React.useEffect(function loadModel() {
5190
+ var _this = this;
5191
+ if (!shouldLoadModels) return;
5192
+ setModelLoadState('downloading');
5193
+ setModelWarmingStartedAt(null);
5194
+ function handleDownloadProgress(event) {
5195
+ setModelDownloadProgress(progressToPercentage(event.detail));
5196
+ }
5197
+ document.addEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
5198
+ var modelLoadTimeout = setTimeout(function () {
5199
+ setModelError(new Error('Model loading time limit exceeded.'));
5200
+ }, modelLoadTimeoutMs);
5201
+ var cancelVideoReady = function cancelVideoReady() {};
5202
+ loadFocusModel(modelPath).then(function (loadedModel) {
5203
+ return __awaiter(_this, void 0, void 0, function () {
5204
+ var _a, videoReady, cancel, cancelled;
5205
+ return __generator(this, function (_b) {
5206
+ switch (_b.label) {
5207
+ case 0:
5208
+ setModelDownloadProgress(100);
5209
+ clearTimeout(modelLoadTimeout);
5210
+ setModelLoadState('warming');
5211
+ setModelWarmingStartedAt(performance.now());
5212
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
5213
+ cancelled = false;
5214
+ cancelVideoReady = function cancelVideoReady() {
5215
+ cancelled = true;
5216
+ cancel();
5217
+ };
5218
+ return [4 /*yield*/, videoReady];
5219
+ case 1:
5220
+ _b.sent();
5221
+ setTimeout(function () {
5222
+ if (cancelled) return;
5223
+ loadedModel.classifyForVideo(videoRef.current, performance.now());
5224
+ setModelLoadState('ready');
5225
+ }, 500);
5226
+ return [2 /*return*/];
5227
+ }
5228
+ });
5229
+ });
5230
+ })["catch"](function (e) {
5231
+ setModelError(e);
5232
+ setModelLoadState('error');
5233
+ })["finally"](function () {
5234
+ clearTimeout(modelLoadTimeout);
5235
+ });
5236
+ return function () {
5237
+ log('unloading focus model');
5238
+ cancelVideoReady();
5239
+ closeFocusModel();
5240
+ clearTimeout(modelLoadTimeout);
5241
+ document.removeEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
5242
+ };
5243
+ }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
5244
+ React.useEffect(function handleModelError() {
5245
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
5246
+ }, [modelError, onModelError]);
5247
+ return React.useMemo(function () {
5248
+ return {
5249
+ ready: modelLoadState === 'ready',
5250
+ modelLoadState: modelLoadState,
5251
+ modelDownloadProgress: modelDownloadProgress,
5252
+ modelWarmingStartedAt: modelWarmingStartedAt,
5253
+ modelError: modelError
5627
5254
  };
5628
- }, [start, stop, load, modelLoadState, modelWarmingStartedAt, modelError, modelDownloadProgress, onDocumentDetected, documentDetectionThresholds, documentDetectionBoundaries, clearDocumentDetectionLastPredictionCanvas]);
5629
- return /*#__PURE__*/React__namespace.createElement(DocumentDetectionModelContext.Provider, {
5630
- value: value
5631
- }, /*#__PURE__*/React__namespace.createElement(InvisibleCanvas, {
5632
- key: canvasKey,
5633
- ref: lastPredictionCanvas
5634
- }), children);
5255
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
5256
+ }
5257
+ var lastFocusPredictionAt = 0;
5258
+ var lastFocusPredictionTime = 0;
5259
+ function setLastFocusPredictionAt(time) {
5260
+ lastFocusPredictionTime = time - lastFocusPredictionAt;
5261
+ lastFocusPredictionAt = time;
5262
+ }
5263
+ function makeFocusModelPrediction(imageData, cropCanvas, rotateCanvas, box) {
5264
+ var _a, _b, _c, _d, _e;
5265
+ if (!classifier$1) return null;
5266
+ var startedAt = performance.now();
5267
+ var image = cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box);
5268
+ var result = classifier$1.classifyForVideo(image, performance.now());
5269
+ var score = (_e = (_d = (_c = (_b = (_a = result === null || result === void 0 ? void 0 : result.classifications) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.categories) === null || _c === void 0 ? void 0 : _c.find(function (c) {
5270
+ return c.categoryName === 'focused';
5271
+ })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
5272
+ var predictionTime = performance.now() - startedAt;
5273
+ return {
5274
+ score: score,
5275
+ predictionTime: predictionTime
5276
+ };
5635
5277
  }
5636
5278
 
5637
5279
  var FocusModelContext = /*#__PURE__*/React.createContext({
@@ -5708,52 +5350,424 @@ function FocusModelProvider(_a) {
5708
5350
  }, [focusThresholds, load, makeFocusPrediction, modelDownloadProgress, modelError, modelLoadState, modelWarmingStartedAt]);
5709
5351
  return /*#__PURE__*/React__namespace.default.createElement(FocusModelContext.Provider, {
5710
5352
  value: value
5711
- }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5353
+ }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5712
5354
  ref: rotateCanvas,
5713
5355
  style: showCanvases ? {
5714
5356
  display: 'block'
5715
5357
  } : undefined
5716
5358
  }), /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5717
- ref: cropCanvas,
5359
+ ref: cropCanvas,
5360
+ style: showCanvases ? {
5361
+ display: 'block'
5362
+ } : undefined
5363
+ })), children);
5364
+ }
5365
+
5366
+ function _isNavigatorDefined() {
5367
+ return typeof navigator !== 'undefined' && navigator != null;
5368
+ }
5369
+ var isMobileCache;
5370
+ function isMobile() {
5371
+ if (isMobileCache !== undefined) return isMobileCache;
5372
+ isMobileCache = evaluateIsMobile();
5373
+ return isMobileCache;
5374
+ }
5375
+ function evaluateIsMobile(nav) {
5376
+ if (nav || _isNavigatorDefined()) {
5377
+ if (!nav) {
5378
+ nav = navigator;
5379
+ }
5380
+ if (nav.product === 'ReactNative') {
5381
+ return true;
5382
+ }
5383
+ var a = nav.userAgent || nav.vendor || (
5384
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5385
+ // @ts-ignore
5386
+ typeof window !== 'undefined' ? window.opera : '');
5387
+ if (!a) {
5388
+ var navAny = nav;
5389
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5390
+ // @ts-ignore
5391
+ return navAny.userAgentData && navAny.userAgentData.mobile;
5392
+ }
5393
+ return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4));
5394
+ }
5395
+ return false;
5396
+ }
5397
+
5398
+ var defaultBarcodeReadabilityModelLoadTimeoutMs = 45000;
5399
+ var classifier = null;
5400
+ var classifierSettings = null;
5401
+ function loadBarcodeReadabilityModel() {
5402
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
5403
+ var _a, _b;
5404
+ if (modelAssetPath === void 0) {
5405
+ modelAssetPath = defaultBarcodeReadabilityModelPath;
5406
+ }
5407
+ return __generator(this, function (_c) {
5408
+ switch (_c.label) {
5409
+ case 0:
5410
+ if (classifier && (classifierSettings === null || classifierSettings === void 0 ? void 0 : classifierSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier];
5411
+ closeBarcodeReadabilityModel();
5412
+ return [4 /*yield*/, preloadBarcodeReadabilityModelDependencies()];
5413
+ case 1:
5414
+ _c.sent();
5415
+ if (modelCapabilities.delegate === 'NONE') {
5416
+ throw new Error('No available delegate for barcode readability model.');
5417
+ }
5418
+ _b = (_a = tasksVision.ImageClassifier).createFromOptions;
5419
+ return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
5420
+ case 2:
5421
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
5422
+ baseOptions: {
5423
+ modelAssetPath: modelAssetPath,
5424
+ delegate: 'CPU'
5425
+ },
5426
+ runningMode: 'VIDEO',
5427
+ maxResults: 1
5428
+ }])];
5429
+ case 3:
5430
+ classifier = _c.sent();
5431
+ classifierSettings = {
5432
+ modelAssetPath: modelAssetPath
5433
+ };
5434
+ return [2 /*return*/, classifier];
5435
+ }
5436
+ });
5437
+ });
5438
+ }
5439
+ function closeBarcodeReadabilityModel() {
5440
+ classifier === null || classifier === void 0 ? void 0 : classifier.close();
5441
+ classifier = null;
5442
+ classifierSettings = null;
5443
+ }
5444
+ function useLoadBarcodeReadabilityModel(_a) {
5445
+ var _b = _a.modelPath,
5446
+ modelPath = _b === void 0 ? defaultBarcodeReadabilityModelPath : _b,
5447
+ _c = _a.modelLoadTimeoutMs,
5448
+ modelLoadTimeoutMs = _c === void 0 ? defaultBarcodeReadabilityModelLoadTimeoutMs : _c,
5449
+ onModelError = _a.onModelError,
5450
+ videoRef = _a.videoRef,
5451
+ _d = _a.shouldLoadModels,
5452
+ shouldLoadModels = _d === void 0 ? true : _d;
5453
+ var _e = React.useState('not-started'),
5454
+ modelLoadState = _e[0],
5455
+ setModelLoadState = _e[1];
5456
+ var _f = React.useState(0),
5457
+ modelDownloadProgress = _f[0],
5458
+ setModelDownloadProgress = _f[1];
5459
+ var _g = React.useState(null),
5460
+ modelWarmingStartedAt = _g[0],
5461
+ setModelWarmingStartedAt = _g[1];
5462
+ var _h = React.useState(null),
5463
+ modelError = _h[0],
5464
+ setModelError = _h[1];
5465
+ React.useEffect(function loadModel() {
5466
+ var _this = this;
5467
+ if (!shouldLoadModels) return;
5468
+ setModelLoadState('downloading');
5469
+ setModelWarmingStartedAt(null);
5470
+ function handleDownloadProgress(event) {
5471
+ setModelDownloadProgress(progressToPercentage(event.detail));
5472
+ }
5473
+ document.addEventListener('idmission.preloadProgress.barcodeReadability', handleDownloadProgress);
5474
+ var modelLoadTimeout = setTimeout(function () {
5475
+ setModelError(new Error('Model loading time limit exceeded.'));
5476
+ }, modelLoadTimeoutMs);
5477
+ var cancelVideoReady = function cancelVideoReady() {};
5478
+ loadBarcodeReadabilityModel(modelPath).then(function (loadedModel) {
5479
+ return __awaiter(_this, void 0, void 0, function () {
5480
+ var _a, videoReady, cancel, cancelled;
5481
+ return __generator(this, function (_b) {
5482
+ switch (_b.label) {
5483
+ case 0:
5484
+ setModelDownloadProgress(100);
5485
+ clearTimeout(modelLoadTimeout);
5486
+ setModelLoadState('warming');
5487
+ setModelWarmingStartedAt(new Date().getTime());
5488
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
5489
+ cancelled = false;
5490
+ cancelVideoReady = function cancelVideoReady() {
5491
+ cancelled = true;
5492
+ cancel();
5493
+ };
5494
+ return [4 /*yield*/, videoReady];
5495
+ case 1:
5496
+ _b.sent();
5497
+ setTimeout(function () {
5498
+ if (cancelled) return;
5499
+ loadedModel.classifyForVideo(videoRef.current, performance.now());
5500
+ setModelLoadState('ready');
5501
+ }, 500);
5502
+ return [2 /*return*/];
5503
+ }
5504
+ });
5505
+ });
5506
+ })["catch"](function (e) {
5507
+ setModelError(e);
5508
+ setModelLoadState('error');
5509
+ })["finally"](function () {
5510
+ clearTimeout(modelLoadTimeout);
5511
+ });
5512
+ return function () {
5513
+ log('unloading barcode readability model');
5514
+ cancelVideoReady();
5515
+ closeBarcodeReadabilityModel();
5516
+ clearTimeout(modelLoadTimeout);
5517
+ document.removeEventListener('idmission.preloadProgress.barcodeReadability', handleDownloadProgress);
5518
+ };
5519
+ }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
5520
+ React.useEffect(function handleModelError() {
5521
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
5522
+ }, [modelError, onModelError]);
5523
+ return React.useMemo(function () {
5524
+ return {
5525
+ ready: modelLoadState === 'ready',
5526
+ modelLoadState: modelLoadState,
5527
+ modelDownloadProgress: modelDownloadProgress,
5528
+ modelWarmingStartedAt: modelWarmingStartedAt,
5529
+ modelError: modelError
5530
+ };
5531
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
5532
+ }
5533
+ var lastBarcodeReadabilityPredictionAt = 0;
5534
+ var lastBarcodeReadabilityPredictionTime = 0;
5535
+ function setLastBarcodeReadabilityPredictionAt(time) {
5536
+ lastBarcodeReadabilityPredictionTime = time - lastBarcodeReadabilityPredictionAt;
5537
+ lastBarcodeReadabilityPredictionAt = time;
5538
+ }
5539
+ function makeBarcodeReadabilityModelPrediction(imageData, cropCanvas, rotateCanvas, resizeCanvas, box) {
5540
+ var _a, _b, _c, _d, _e;
5541
+ if (!classifier) return null;
5542
+ var startedAt = performance.now();
5543
+ var image = cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box);
5544
+ var resized = resizeIfNecessary(image, resizeCanvas, 500);
5545
+ var result = classifier.classifyForVideo(resized, performance.now());
5546
+ var score = (_e = (_d = (_c = (_b = (_a = result === null || result === void 0 ? void 0 : result.classifications) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.categories) === null || _c === void 0 ? void 0 : _c.find(function (c) {
5547
+ return c.categoryName === 'blurry';
5548
+ })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
5549
+ debug('barcode prediction', "".concat(performance.now() - startedAt, "ms"), score);
5550
+ var predictionTime = performance.now() - startedAt;
5551
+ return {
5552
+ score: score,
5553
+ predictionTime: predictionTime
5554
+ };
5555
+ }
5556
+
5557
+ var BarcodeReadabilityModelContext = /*#__PURE__*/React.createContext({
5558
+ loadBarcodeReadabilityModel: function loadBarcodeReadabilityModel() {
5559
+ return null;
5560
+ },
5561
+ barcodeReadabilityModelState: 'not-started',
5562
+ barcodeReadabilityModelDownloadProgress: 0,
5563
+ barcodeReadabilityModelWarmingStartedAt: null,
5564
+ barcodeReadabilityModelError: null,
5565
+ barcodeReadabilityThresholds: {},
5566
+ setBarcodeReadabilityThresholds: function setBarcodeReadabilityThresholds() {
5567
+ return null;
5568
+ },
5569
+ makeBarcodeReadabilityPrediction: function makeBarcodeReadabilityPrediction() {
5570
+ return null;
5571
+ },
5572
+ barcodeReadabilityPredictionTime: 0
5573
+ });
5574
+ function BarcodeReadabilityModelProvider(_a) {
5575
+ var children = _a.children,
5576
+ _b = _a.barcodeReadabilityModelPath,
5577
+ barcodeReadabilityModelPath = _b === void 0 ? defaultBarcodeReadabilityModelPath : _b,
5578
+ _c = _a.barcodeReadabilityModelLoadTimeoutMs,
5579
+ barcodeReadabilityModelLoadTimeoutMs = _c === void 0 ? defaultBarcodeReadabilityModelLoadTimeoutMs : _c,
5580
+ onBarcodeReadabilityModelError = _a.onBarcodeReadabilityModelError,
5581
+ _d = _a.showCanvases,
5582
+ showCanvases = _d === void 0 ? false : _d,
5583
+ _e = _a.shouldLoadModels,
5584
+ shouldLoadModelsProp = _e === void 0 ? true : _e;
5585
+ var cropCanvas = React.useRef(null);
5586
+ var rotateCanvas = React.useRef(null);
5587
+ var resizeCanvas = React.useRef(null);
5588
+ var _f = React.useState({}),
5589
+ barcodeReadabilityThresholds = _f[0],
5590
+ setBarcodeReadabilityThresholds = _f[1];
5591
+ var videoRef = useCameraStore().videoRef;
5592
+ var _g = React.useState(shouldLoadModelsProp),
5593
+ shouldLoadModels = _g[0],
5594
+ setShouldLoadModels = _g[1];
5595
+ var load = React.useCallback(function () {
5596
+ return setShouldLoadModels(true);
5597
+ }, []);
5598
+ var _h = useLoadBarcodeReadabilityModel({
5599
+ modelPath: barcodeReadabilityModelPath,
5600
+ modelLoadTimeoutMs: barcodeReadabilityModelLoadTimeoutMs,
5601
+ onModelError: onBarcodeReadabilityModelError,
5602
+ videoRef: videoRef,
5603
+ shouldLoadModels: shouldLoadModels
5604
+ }),
5605
+ ready = _h.ready,
5606
+ modelLoadState = _h.modelLoadState,
5607
+ modelDownloadProgress = _h.modelDownloadProgress,
5608
+ modelWarmingStartedAt = _h.modelWarmingStartedAt,
5609
+ modelError = _h.modelError;
5610
+ var makeBarcodeReadabilityPrediction = React.useCallback(function (imageData, box) {
5611
+ if (!ready) return null;
5612
+ var prediction = makeBarcodeReadabilityModelPrediction(imageData, cropCanvas.current, rotateCanvas.current, resizeCanvas.current, box);
5613
+ if (!prediction) return null;
5614
+ setLastBarcodeReadabilityPredictionAt(prediction.predictionTime);
5615
+ return prediction;
5616
+ }, [ready]);
5617
+ var value = React.useMemo(function () {
5618
+ return {
5619
+ loadBarcodeReadabilityModel: load,
5620
+ barcodeReadabilityModelState: modelLoadState,
5621
+ barcodeReadabilityModelDownloadProgress: modelDownloadProgress,
5622
+ barcodeReadabilityModelWarmingStartedAt: modelWarmingStartedAt,
5623
+ barcodeReadabilityModelError: modelError,
5624
+ makeBarcodeReadabilityPrediction: makeBarcodeReadabilityPrediction,
5625
+ barcodeReadabilityPredictionTime: lastBarcodeReadabilityPredictionTime,
5626
+ barcodeReadabilityThresholds: barcodeReadabilityThresholds,
5627
+ setBarcodeReadabilityThresholds: setBarcodeReadabilityThresholds
5628
+ };
5629
+ }, [barcodeReadabilityThresholds, load, makeBarcodeReadabilityPrediction, modelDownloadProgress, modelError, modelLoadState, modelWarmingStartedAt]);
5630
+ return /*#__PURE__*/React__namespace.default.createElement(BarcodeReadabilityModelContext.Provider, {
5631
+ value: value
5632
+ }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5633
+ ref: rotateCanvas
5634
+ }), /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5635
+ ref: cropCanvas
5636
+ }), /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5637
+ ref: resizeCanvas,
5718
5638
  style: showCanvases ? {
5719
5639
  display: 'block'
5720
5640
  } : undefined
5721
- }), children);
5722
- }
5723
-
5724
- function _isNavigatorDefined() {
5725
- return typeof navigator !== 'undefined' && navigator != null;
5641
+ })), children);
5726
5642
  }
5727
- var isMobileCache;
5728
- function isMobile() {
5729
- if (isMobileCache !== undefined) return isMobileCache;
5730
- isMobileCache = evaluateIsMobile();
5731
- return isMobileCache;
5732
- }
5733
- function evaluateIsMobile(nav) {
5734
- if (nav || _isNavigatorDefined()) {
5735
- if (!nav) {
5736
- nav = navigator;
5737
- }
5738
- if (nav.product === 'ReactNative') {
5739
- return true;
5740
- }
5741
- var a = nav.userAgent || nav.vendor || (
5742
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5743
- // @ts-ignore
5744
- typeof window !== 'undefined' ? window.opera : '');
5745
- if (!a) {
5746
- var navAny = nav;
5747
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5748
- // @ts-ignore
5749
- return navAny.userAgentData && navAny.userAgentData.mobile;
5750
- }
5751
- return /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4));
5643
+ function useBarcodeReadabilityModelContext() {
5644
+ var context = React.useContext(BarcodeReadabilityModelContext);
5645
+ if (!context) {
5646
+ throw new Error('useBarcodeReadabilityModelContext must be used within a BarcodeReadabilityModelProvider');
5752
5647
  }
5753
- return false;
5648
+ return context;
5754
5649
  }
5755
5650
 
5756
5651
  var onMobile = isMobile();
5652
+ /**
5653
+ * Analyzes barcode readability for a detected document
5654
+ * @param prediction The document detection prediction
5655
+ * @param lastPredictionCanvas The canvas containing the original frame
5656
+ * @param croppedDocumentCanvas Canvas for storing cropped document
5657
+ * @param bestBarcodeCanvas Canvas for storing best barcode crop
5658
+ * @param currentBestBarcodeScore Current best barcode score
5659
+ * @param documentDetectionThresholds Thresholds for document detection
5660
+ * @param makeBarcodeReadabilityPrediction Function to make barcode readability predictions
5661
+ * @param barcodeReadabilityThresholds Thresholds for barcode readability
5662
+ * @returns Object containing barcode analysis results
5663
+ */
5664
+ function analyzeBarcodeReadability(prediction, lastPredictionCanvas, croppedDocumentCanvas, bestBarcodeCanvas, currentBestBarcodeScore, documentDetectionThresholds, makeBarcodeReadabilityPrediction, barcodeReadabilityThreshold) {
5665
+ return __awaiter(this, void 0, void 0, function () {
5666
+ var pdf417PredictionTime, pdf417PredictionScore, pdf417PredictionThresholdMet, newBestBarcodeScore, newBestBarcodeDetails, documentCroppedPrediction, processedCroppedPrediction, pdf417Prediction;
5667
+ var _a;
5668
+ return __generator(this, function (_b) {
5669
+ switch (_b.label) {
5670
+ case 0:
5671
+ pdf417PredictionTime = 0;
5672
+ pdf417PredictionScore = 0;
5673
+ pdf417PredictionThresholdMet = false;
5674
+ if (!prediction.bestDocument || !((_a = prediction.bestPDF417) === null || _a === void 0 ? void 0 : _a.box) || !bestBarcodeCanvas) {
5675
+ return [2 /*return*/, {
5676
+ pdf417PredictionTime: pdf417PredictionTime,
5677
+ pdf417PredictionScore: pdf417PredictionScore,
5678
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet,
5679
+ newBestBarcodeScore: newBestBarcodeScore,
5680
+ newBestBarcodeDetails: newBestBarcodeDetails
5681
+ }];
5682
+ }
5683
+ /**
5684
+ * Step 1: Crop the full frame to just the document area
5685
+ * This removes background noise and focuses analysis on the document
5686
+ */
5687
+ cropToDetectedObjectBox(lastPredictionCanvas, prediction.bestDocument.box, croppedDocumentCanvas);
5688
+ return [4 /*yield*/, makeDocumentDetectorPrediction(croppedDocumentCanvas)];
5689
+ case 1:
5690
+ documentCroppedPrediction = _b.sent();
5691
+ if (!documentCroppedPrediction) {
5692
+ // error occurred during prediction (error logged by callee)
5693
+ return [2 /*return*/, {
5694
+ pdf417PredictionTime: pdf417PredictionTime,
5695
+ pdf417PredictionScore: pdf417PredictionScore,
5696
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet,
5697
+ newBestBarcodeScore: newBestBarcodeScore,
5698
+ newBestBarcodeDetails: newBestBarcodeDetails
5699
+ }];
5700
+ }
5701
+ processedCroppedPrediction = processDocumentDetectorPrediction(documentCroppedPrediction, documentDetectionThresholds);
5702
+ if (processedCroppedPrediction.bestPDF417) {
5703
+ pdf417Prediction = makeBarcodeReadabilityPrediction(croppedDocumentCanvas, processedCroppedPrediction.bestPDF417.box);
5704
+ if (pdf417Prediction) {
5705
+ pdf417PredictionTime = pdf417Prediction.predictionTime;
5706
+ pdf417PredictionScore = pdf417Prediction.score;
5707
+ if (pdf417Prediction.score > currentBestBarcodeScore) {
5708
+ /**
5709
+ * Step 5: Update best barcode
5710
+ */
5711
+ newBestBarcodeScore = pdf417Prediction.score;
5712
+ newBestBarcodeDetails = {
5713
+ boundingBox: prediction.bestPDF417.box,
5714
+ score: pdf417Prediction.score
5715
+ };
5716
+ if (pdf417PredictionScore >= barcodeReadabilityThreshold) {
5717
+ pdf417PredictionThresholdMet = true;
5718
+ }
5719
+ cropToDetectedObjectBox(croppedDocumentCanvas, processedCroppedPrediction.bestPDF417.box, bestBarcodeCanvas, 16);
5720
+ }
5721
+ }
5722
+ }
5723
+ return [2 /*return*/, {
5724
+ pdf417PredictionTime: pdf417PredictionTime,
5725
+ pdf417PredictionScore: pdf417PredictionScore,
5726
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet,
5727
+ newBestBarcodeScore: newBestBarcodeScore,
5728
+ newBestBarcodeDetails: newBestBarcodeDetails
5729
+ }];
5730
+ }
5731
+ });
5732
+ });
5733
+ }
5734
+ /**
5735
+ * Calculates the barcode readability threshold for a given document type
5736
+ * @param detectedDocumentType The type of document detected
5737
+ * @param barcodeReadabilityThresholds The threshold configuration object
5738
+ * @returns The appropriate threshold value for the current platform (mobile/desktop)
5739
+ */
5740
+ function calculateBarcodeReadabilityThreshold(detectedDocumentType, barcodeReadabilityThresholds) {
5741
+ var barcodeReadabilityThresholdSet = detectedDocumentType in barcodeReadabilityThresholds ? barcodeReadabilityThresholds[detectedDocumentType] : undefined;
5742
+ if (barcodeReadabilityThresholdSet) {
5743
+ return onMobile ? barcodeReadabilityThresholdSet.mobile || 0 : barcodeReadabilityThresholdSet.desktop || 0;
5744
+ }
5745
+ return 0;
5746
+ }
5747
+ /**
5748
+ * Hook that calculates the barcode readability threshold for a given document type
5749
+ */
5750
+ function useBarcodeReadabilityThreshold() {
5751
+ var barcodeReadabilityThresholds = useBarcodeReadabilityModelContext().barcodeReadabilityThresholds;
5752
+ return React.useCallback(function (detectedDocumentType) {
5753
+ return calculateBarcodeReadabilityThreshold(detectedDocumentType, barcodeReadabilityThresholds);
5754
+ }, [barcodeReadabilityThresholds]);
5755
+ }
5756
+ function useBarcodeReadabilityAnalysis() {
5757
+ var _this = this;
5758
+ var documentDetectionThresholds = React.useContext(DocumentDetectionModelContext).documentDetectionThresholds;
5759
+ var makeBarcodeReadabilityPrediction = useBarcodeReadabilityModelContext().makeBarcodeReadabilityPrediction;
5760
+ var getBarcodeReadabilityThreshold = useBarcodeReadabilityThreshold();
5761
+ return React.useCallback(function (prediction, lastPredictionCanvas, croppedDocumentCanvas, bestBarcodeCanvas, currentBestBarcodeScore) {
5762
+ return __awaiter(_this, void 0, void 0, function () {
5763
+ var barcodeReadabilityThreshold;
5764
+ return __generator(this, function (_a) {
5765
+ barcodeReadabilityThreshold = getBarcodeReadabilityThreshold(prediction.detectedDocumentType);
5766
+ return [2 /*return*/, analyzeBarcodeReadability(prediction, lastPredictionCanvas, croppedDocumentCanvas, bestBarcodeCanvas, currentBestBarcodeScore, documentDetectionThresholds, makeBarcodeReadabilityPrediction, barcodeReadabilityThreshold)];
5767
+ });
5768
+ });
5769
+ }, [documentDetectionThresholds, makeBarcodeReadabilityPrediction, getBarcodeReadabilityThreshold]);
5770
+ }
5757
5771
  var defaultIdCaptureThresholds = {
5758
5772
  detection: defaultDocumentDetectionThresholds,
5759
5773
  focus: defaultFocusThresholds
@@ -5786,6 +5800,7 @@ var IdCaptureModelsContext = /*#__PURE__*/React.createContext({
5786
5800
  },
5787
5801
  detectionTime: 0,
5788
5802
  focusPredictionTime: 0,
5803
+ barcodeReadabilityPredictionTime: 0,
5789
5804
  bestFrameDetails: {
5790
5805
  current: null
5791
5806
  },
@@ -5795,55 +5810,80 @@ var IdCaptureModelsContext = /*#__PURE__*/React.createContext({
5795
5810
  resetBestFrame: function resetBestFrame() {
5796
5811
  return null;
5797
5812
  },
5813
+ bestBarcodeDetails: {
5814
+ current: null
5815
+ },
5816
+ getBestBarcode: function getBestBarcode() {
5817
+ return null;
5818
+ },
5798
5819
  requiredDocumentType: 'none',
5799
5820
  setRequiredDocumentType: function setRequiredDocumentType() {
5800
5821
  return null;
5801
5822
  }
5802
5823
  });
5803
5824
  function IdCaptureModelsProviderInner(_a) {
5825
+ var _b;
5804
5826
  var children = _a.children,
5805
5827
  onModelError = _a.onModelError,
5806
- _b = _a.allowSinglePageIdCapture,
5807
- allowSinglePageIdCapture = _b === void 0 ? false : _b;
5808
- var _c = React.useContext(DocumentDetectionModelContext),
5809
- documentDetectionModelState = _c.documentDetectionModelState,
5810
- documentDetectionModelDownloadProgress = _c.documentDetectionModelDownloadProgress,
5811
- documentDetectionModelWarmingStartedAt = _c.documentDetectionModelWarmingStartedAt,
5812
- startDocumentDetection = _c.startDocumentDetection,
5813
- stopDocumentDetection = _c.stopDocumentDetection,
5814
- loadDocumentDetectionModel = _c.loadDocumentDetectionModel,
5815
- lastPredictionCanvas = _c.documentDetectionLastPredictionCanvas,
5816
- clearDocumentDetectionLastPredictionCanvas = _c.clearDocumentDetectionLastPredictionCanvas,
5817
- onDocumentDetected = _c.onDocumentDetected,
5818
- detectionTime = _c.detectionTime,
5819
- documentDetectionThresholds = _c.documentDetectionThresholds,
5820
- setDocumentDetectionThresholds = _c.setDocumentDetectionThresholds,
5821
- documentDetectionBoundaries = _c.documentDetectionBoundaries,
5822
- setDocumentDetectionBoundaries = _c.setDocumentDetectionBoundaries,
5823
- documentDetectionModelError = _c.documentDetectionModelError;
5824
- var _d = React.useContext(FocusModelContext),
5825
- loadFocusModel = _d.loadFocusModel,
5826
- focusModelState = _d.focusModelState,
5827
- focusModelDownloadProgress = _d.focusModelDownloadProgress,
5828
- focusModelWarmingStartedAt = _d.focusModelWarmingStartedAt,
5829
- makeFocusPrediction = _d.makeFocusPrediction,
5830
- focusThresholds = _d.focusThresholds,
5831
- setFocusThresholds = _d.setFocusThresholds,
5832
- focusPredictionTime = _d.focusPredictionTime,
5833
- focusModelError = _d.focusModelError;
5828
+ _c = _a.allowSinglePageIdCapture,
5829
+ allowSinglePageIdCapture = _c === void 0 ? false : _c,
5830
+ _d = _a.enableBarcodeReadabilityModel,
5831
+ enableBarcodeReadabilityModel = _d === void 0 ? true : _d;
5832
+ var _e = React.useContext(DocumentDetectionModelContext),
5833
+ documentDetectionModelState = _e.documentDetectionModelState,
5834
+ documentDetectionModelDownloadProgress = _e.documentDetectionModelDownloadProgress,
5835
+ documentDetectionModelWarmingStartedAt = _e.documentDetectionModelWarmingStartedAt,
5836
+ startDocumentDetection = _e.startDocumentDetection,
5837
+ stopDocumentDetection = _e.stopDocumentDetection,
5838
+ loadDocumentDetectionModel = _e.loadDocumentDetectionModel,
5839
+ lastPredictionCanvas = _e.documentDetectionLastPredictionCanvas,
5840
+ clearDocumentDetectionLastPredictionCanvas = _e.clearDocumentDetectionLastPredictionCanvas,
5841
+ onDocumentDetected = _e.onDocumentDetected,
5842
+ detectionTime = _e.detectionTime,
5843
+ documentDetectionThresholds = _e.documentDetectionThresholds,
5844
+ setDocumentDetectionThresholds = _e.setDocumentDetectionThresholds,
5845
+ documentDetectionBoundaries = _e.documentDetectionBoundaries,
5846
+ setDocumentDetectionBoundaries = _e.setDocumentDetectionBoundaries,
5847
+ documentDetectionModelError = _e.documentDetectionModelError;
5848
+ var _f = React.useContext(FocusModelContext),
5849
+ loadFocusModel = _f.loadFocusModel,
5850
+ focusModelState = _f.focusModelState,
5851
+ focusModelDownloadProgress = _f.focusModelDownloadProgress,
5852
+ focusModelWarmingStartedAt = _f.focusModelWarmingStartedAt,
5853
+ makeFocusPrediction = _f.makeFocusPrediction,
5854
+ focusThresholds = _f.focusThresholds,
5855
+ setFocusThresholds = _f.setFocusThresholds,
5856
+ focusPredictionTime = _f.focusPredictionTime,
5857
+ focusModelError = _f.focusModelError;
5858
+ var _g = useBarcodeReadabilityModelContext(),
5859
+ loadBarcodeReadabilityModel = _g.loadBarcodeReadabilityModel,
5860
+ barcodeReadabilityModelState = _g.barcodeReadabilityModelState,
5861
+ barcodeReadabilityModelDownloadProgress = _g.barcodeReadabilityModelDownloadProgress,
5862
+ barcodeReadabilityModelWarmingStartedAt = _g.barcodeReadabilityModelWarmingStartedAt,
5863
+ makeBarcodeReadabilityPrediction = _g.makeBarcodeReadabilityPrediction,
5864
+ barcodeReadabilityThresholds = _g.barcodeReadabilityThresholds,
5865
+ setBarcodeReadabilityThresholds = _g.setBarcodeReadabilityThresholds,
5866
+ barcodeReadabilityPredictionTime = _g.barcodeReadabilityPredictionTime,
5867
+ barcodeReadabilityModelError = _g.barcodeReadabilityModelError;
5834
5868
  var onPredictionHandler = React.useRef();
5835
5869
  var bestFrameDetails = React.useRef(null);
5870
+ var bestBarcodeDetails = React.useRef(null);
5836
5871
  var bestPredictionCanvas = React.useRef(null);
5872
+ var bestBarcodeCanvas = React.useRef(null);
5873
+ var croppedDocumentCanvas = React.useRef(null);
5837
5874
  var bestFocusScore = React.useRef(0);
5875
+ var bestBarcodeScore = React.useRef(0);
5838
5876
  var stopDetection = React.useRef(0);
5839
- var _e = React.useState('none'),
5840
- requiredDocumentType = _e[0],
5841
- setRequiredDocumentType = _e[1];
5877
+ var analyzeBarcodeReadability = useBarcodeReadabilityAnalysis();
5878
+ var _h = React.useState('none'),
5879
+ requiredDocumentType = _h[0],
5880
+ setRequiredDocumentType = _h[1];
5842
5881
  var thresholds = React.useMemo(function () {
5843
5882
  return _assign(_assign({}, documentDetectionThresholds), {
5844
- focus: focusThresholds
5883
+ focus: focusThresholds,
5884
+ barcodeReadability: barcodeReadabilityThresholds
5845
5885
  });
5846
- }, [documentDetectionThresholds, focusThresholds]);
5886
+ }, [documentDetectionThresholds, focusThresholds, barcodeReadabilityThresholds]);
5847
5887
  var setThresholds = React.useCallback(function (thresholds) {
5848
5888
  if (thresholds.detection) {
5849
5889
  setDocumentDetectionThresholds(thresholds.detection);
@@ -5851,57 +5891,87 @@ function IdCaptureModelsProviderInner(_a) {
5851
5891
  if (thresholds.focus) {
5852
5892
  setFocusThresholds(thresholds.focus);
5853
5893
  }
5854
- }, [setDocumentDetectionThresholds, setFocusThresholds]);
5894
+ if (thresholds.barcodeReadability) {
5895
+ setBarcodeReadabilityThresholds(thresholds.barcodeReadability);
5896
+ }
5897
+ }, [setBarcodeReadabilityThresholds, setDocumentDetectionThresholds, setFocusThresholds]);
5855
5898
  React.useEffect(function handleDetections() {
5856
5899
  var _this = this;
5857
5900
  onDocumentDetected(function (prediction) {
5858
5901
  return __awaiter(_this, void 0, void 0, function () {
5859
- var stopDetectionAtStart, focusPredictionTime, focusScore, focusThresholdMet, isSinglePage, isRequiredDocumentType, focusPrediction, focusThresholdSet, focusThreshold;
5902
+ var stopDetectionAtStart, focusPredictionTime, focusScore, focusThresholdMet, pdf417PredictionTime, pdf417PredictionScore, pdf417PredictionThresholdMet, isSinglePage, isRequiredDocumentType, focusPrediction, focusThresholdSet, focusThreshold, barcodeAnalysisResult;
5860
5903
  var _a, _b, _c, _d, _e, _f, _g;
5861
5904
  return __generator(this, function (_h) {
5862
- if (!lastPredictionCanvas.current) return [2 /*return*/];
5863
- stopDetectionAtStart = stopDetection.current;
5864
- focusPredictionTime = 0, focusScore = 0, focusThresholdMet = false;
5865
- isSinglePage = prediction.detectedDocumentType === 'singlePage';
5866
- if (!allowSinglePageIdCapture && isSinglePage) {
5867
- prediction.detectedDocumentType = 'passport';
5868
- prediction.passportDetectionScore = prediction.singlePageDetectionScore;
5869
- prediction.passportDetectionThresholdMet = prediction.singlePageDetectionThresholdMet;
5870
- prediction.singlePageDetectionScore = 0;
5871
- prediction.singlePageDetectionThresholdMet = false;
5872
- }
5873
- isRequiredDocumentType = requiredDocumentType === 'none' || prediction.detectedDocumentType === requiredDocumentType || ((_a = requiredDocumentType.includes) === null || _a === void 0 ? void 0 : _a.call(requiredDocumentType, prediction.detectedDocumentType)) || allowSinglePageIdCapture && isSinglePage && ((_b = requiredDocumentType.includes) === null || _b === void 0 ? void 0 : _b.call(requiredDocumentType, 'idCardFront'));
5874
- if (isRequiredDocumentType && prediction.detectedDocumentType !== 'none' && prediction.detectionThresholdMet && prediction.documentInBounds && !prediction.documentTooClose && prediction.documentIsStable) {
5875
- focusPrediction = makeFocusPrediction(lastPredictionCanvas.current, (_c = prediction.bestDocument) === null || _c === void 0 ? void 0 : _c.box);
5876
- if (focusPrediction) {
5877
- focusScore = focusPrediction.score;
5878
- focusPredictionTime = focusPrediction.predictionTime;
5879
- }
5880
- focusThresholdSet = (_d = thresholds.focus) === null || _d === void 0 ? void 0 : _d[prediction.detectedDocumentType];
5881
- focusThreshold = (_e = onMobile ? focusThresholdSet === null || focusThresholdSet === void 0 ? void 0 : focusThresholdSet.mobile : focusThresholdSet === null || focusThresholdSet === void 0 ? void 0 : focusThresholdSet.desktop) !== null && _e !== void 0 ? _e : 0;
5882
- focusThresholdMet = focusScore >= focusThreshold;
5883
- if (bestFocusScore.current <= focusScore && stopDetectionAtStart === stopDetection.current) {
5884
- bestFocusScore.current = focusScore;
5885
- drawToCanvas(bestPredictionCanvas.current, lastPredictionCanvas.current);
5886
- bestFrameDetails.current = {
5887
- boundingBox: (_f = prediction.bestDocument) === null || _f === void 0 ? void 0 : _f.box,
5888
- documentType: prediction.detectedDocumentType,
5889
- detectionScore: prediction.detectionScore,
5890
- focusScore: focusScore
5891
- };
5892
- }
5905
+ switch (_h.label) {
5906
+ case 0:
5907
+ if (!lastPredictionCanvas.current) return [2 /*return*/];
5908
+ stopDetectionAtStart = stopDetection.current;
5909
+ focusPredictionTime = 0, focusScore = 0, focusThresholdMet = false, pdf417PredictionTime = 0, pdf417PredictionScore = 0, pdf417PredictionThresholdMet = false;
5910
+ isSinglePage = prediction.detectedDocumentType === 'singlePage';
5911
+ if (!allowSinglePageIdCapture && isSinglePage) {
5912
+ prediction.detectedDocumentType = 'passport';
5913
+ prediction.passportDetectionScore = prediction.singlePageDetectionScore;
5914
+ prediction.passportDetectionThresholdMet = prediction.singlePageDetectionThresholdMet;
5915
+ prediction.singlePageDetectionScore = 0;
5916
+ prediction.singlePageDetectionThresholdMet = false;
5917
+ }
5918
+ isRequiredDocumentType = requiredDocumentType === 'none' || prediction.detectedDocumentType === requiredDocumentType || ((_a = requiredDocumentType.includes) === null || _a === void 0 ? void 0 : _a.call(requiredDocumentType, prediction.detectedDocumentType)) || allowSinglePageIdCapture && isSinglePage && ((_b = requiredDocumentType.includes) === null || _b === void 0 ? void 0 : _b.call(requiredDocumentType, 'idCardFront'));
5919
+ if (!(isRequiredDocumentType && prediction.detectedDocumentType !== 'none' && prediction.detectionThresholdMet && prediction.documentInBounds && !prediction.documentTooClose && prediction.documentIsStable)) return [3 /*break*/, 2];
5920
+ focusPrediction = makeFocusPrediction(lastPredictionCanvas.current, (_c = prediction.bestDocument) === null || _c === void 0 ? void 0 : _c.box);
5921
+ if (focusPrediction) {
5922
+ focusScore = focusPrediction.score;
5923
+ focusPredictionTime = focusPrediction.predictionTime;
5924
+ }
5925
+ focusThresholdSet = (_d = thresholds.focus) === null || _d === void 0 ? void 0 : _d[prediction.detectedDocumentType];
5926
+ focusThreshold = (_e = onMobile ? focusThresholdSet === null || focusThresholdSet === void 0 ? void 0 : focusThresholdSet.mobile : focusThresholdSet === null || focusThresholdSet === void 0 ? void 0 : focusThresholdSet.desktop) !== null && _e !== void 0 ? _e : 0;
5927
+ focusThresholdMet = focusScore >= focusThreshold;
5928
+ if (!(stopDetectionAtStart === stopDetection.current)) return [3 /*break*/, 2];
5929
+ if (bestFocusScore.current <= focusScore) {
5930
+ bestFocusScore.current = focusScore;
5931
+ drawToCanvas(bestPredictionCanvas.current, lastPredictionCanvas.current);
5932
+ bestFrameDetails.current = {
5933
+ boundingBox: (_f = prediction.bestDocument) === null || _f === void 0 ? void 0 : _f.box,
5934
+ documentType: prediction.detectedDocumentType,
5935
+ detectionScore: prediction.detectionScore,
5936
+ focusScore: focusScore
5937
+ };
5938
+ }
5939
+ if (!(enableBarcodeReadabilityModel && prediction.bestDocument && prediction.bestPDF417 && croppedDocumentCanvas.current)) return [3 /*break*/, 2];
5940
+ return [4 /*yield*/, analyzeBarcodeReadability(prediction, lastPredictionCanvas.current, croppedDocumentCanvas.current, bestBarcodeCanvas.current, bestBarcodeScore.current)];
5941
+ case 1:
5942
+ barcodeAnalysisResult = _h.sent();
5943
+ pdf417PredictionTime = barcodeAnalysisResult.pdf417PredictionTime;
5944
+ pdf417PredictionScore = barcodeAnalysisResult.pdf417PredictionScore;
5945
+ pdf417PredictionThresholdMet = barcodeAnalysisResult.pdf417PredictionThresholdMet;
5946
+ if (barcodeAnalysisResult.newBestBarcodeScore) {
5947
+ bestBarcodeScore.current = barcodeAnalysisResult.newBestBarcodeScore;
5948
+ }
5949
+ if (barcodeAnalysisResult.newBestBarcodeDetails) {
5950
+ bestBarcodeDetails.current = barcodeAnalysisResult.newBestBarcodeDetails;
5951
+ }
5952
+ _h.label = 2;
5953
+ case 2:
5954
+ /**
5955
+ * @note
5956
+ * This should ALWAYS be called.
5957
+ * Do not return early from this function unless
5958
+ * lastPredictionCanvas.current is not set
5959
+ */
5960
+ (_g = onPredictionHandler.current) === null || _g === void 0 ? void 0 : _g.call(onPredictionHandler, _assign(_assign({}, prediction), {
5961
+ focusScore: focusScore,
5962
+ focusPredictionTime: focusPredictionTime,
5963
+ focusThresholdMet: focusThresholdMet,
5964
+ pdf417PredictionTime: pdf417PredictionTime,
5965
+ pdf417PredictionScore: pdf417PredictionScore,
5966
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet
5967
+ }));
5968
+ return [2 /*return*/];
5893
5969
  }
5894
- (_g = onPredictionHandler.current) === null || _g === void 0 ? void 0 : _g.call(onPredictionHandler, _assign(_assign({}, prediction), {
5895
- focusScore: focusScore,
5896
- focusPredictionTime: focusPredictionTime,
5897
- focusThresholdMet: focusThresholdMet
5898
- }));
5899
- return [2 /*return*/];
5900
5970
  });
5901
5971
  });
5902
5972
  });
5903
- }, [allowSinglePageIdCapture, lastPredictionCanvas, makeFocusPrediction, onDocumentDetected, requiredDocumentType, thresholds.focus]);
5904
- var modelError = documentDetectionModelError !== null && documentDetectionModelError !== void 0 ? documentDetectionModelError : focusModelError;
5973
+ }, [allowSinglePageIdCapture, analyzeBarcodeReadability, barcodeReadabilityThresholds, enableBarcodeReadabilityModel, lastPredictionCanvas, makeBarcodeReadabilityPrediction, makeFocusPrediction, onDocumentDetected, requiredDocumentType, thresholds.focus]);
5974
+ var modelError = (_b = documentDetectionModelError !== null && documentDetectionModelError !== void 0 ? documentDetectionModelError : focusModelError) !== null && _b !== void 0 ? _b : barcodeReadabilityModelError;
5905
5975
  React.useEffect(function handleModelErrors() {
5906
5976
  if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
5907
5977
  }, [modelError, onModelError]);
@@ -5914,9 +5984,15 @@ function IdCaptureModelsProviderInner(_a) {
5914
5984
  canvas: bestPredictionCanvas.current
5915
5985
  });
5916
5986
  }, []);
5917
- var _f = React.useState(0),
5918
- canvasKey = _f[0],
5919
- setCanvasKey = _f[1];
5987
+ var getBestBarcode = React.useCallback(function () {
5988
+ if (!bestBarcodeDetails.current || !bestBarcodeCanvas.current) return null;
5989
+ return _assign(_assign({}, bestBarcodeDetails.current), {
5990
+ canvas: bestBarcodeCanvas.current
5991
+ });
5992
+ }, []);
5993
+ var _j = React.useState(0),
5994
+ canvasKey = _j[0],
5995
+ setCanvasKey = _j[1];
5920
5996
  var resetBestFrame = React.useCallback(function () {
5921
5997
  stopDetection.current += 1;
5922
5998
  setCanvasKey(function (n) {
@@ -5932,16 +6008,45 @@ function IdCaptureModelsProviderInner(_a) {
5932
6008
  var load = React.useCallback(function () {
5933
6009
  loadDocumentDetectionModel();
5934
6010
  loadFocusModel();
5935
- }, [loadDocumentDetectionModel, loadFocusModel]);
5936
- var ready = documentDetectionModelState === 'ready' && focusModelState === 'ready';
5937
- var modelLoadState = ready ? 'ready' : documentDetectionModelState === 'warming' || focusModelState === 'warming' ? 'warming' : focusModelState === 'downloading' || documentDetectionModelState === 'downloading' ? 'downloading' : 'not-started';
5938
- var modelWarmingStartedAt = !documentDetectionModelWarmingStartedAt && !focusModelWarmingStartedAt ? null : Math.min.apply(Math, [documentDetectionModelWarmingStartedAt, focusModelWarmingStartedAt].filter(function (v) {
5939
- return v !== null;
5940
- }));
6011
+ if (enableBarcodeReadabilityModel) loadBarcodeReadabilityModel();
6012
+ }, [enableBarcodeReadabilityModel, loadBarcodeReadabilityModel, loadDocumentDetectionModel, loadFocusModel]);
6013
+ var _k = React.useMemo(function () {
6014
+ var modelStates = [documentDetectionModelState, focusModelState];
6015
+ var modelWarmingStartedAts = [documentDetectionModelWarmingStartedAt, focusModelWarmingStartedAt];
6016
+ var modelDownloadProgresses = [documentDetectionModelDownloadProgress, focusModelDownloadProgress];
6017
+ if (enableBarcodeReadabilityModel) {
6018
+ modelStates.push(barcodeReadabilityModelState);
6019
+ modelWarmingStartedAts.push(barcodeReadabilityModelWarmingStartedAt);
6020
+ modelDownloadProgresses.push(barcodeReadabilityModelDownloadProgress);
6021
+ }
6022
+ var ready = modelStates.every(function (state) {
6023
+ return state === 'ready';
6024
+ });
6025
+ return {
6026
+ ready: ready,
6027
+ modelLoadState: ready ? 'ready' : modelStates.some(function (state) {
6028
+ return state === 'warming';
6029
+ }) ? 'warming' : modelStates.some(function (state) {
6030
+ return state === 'downloading';
6031
+ }) ? 'downloading' : 'not-started',
6032
+ modelWarmingStartedAt: modelWarmingStartedAts.every(function (v) {
6033
+ return v === null;
6034
+ }) ? null : Math.min.apply(Math, modelWarmingStartedAts.filter(function (v) {
6035
+ return v !== null;
6036
+ })),
6037
+ modelDownloadProgress: modelDownloadProgresses.reduce(function (a, b) {
6038
+ return a + b;
6039
+ }, 0) / modelDownloadProgresses.length
6040
+ };
6041
+ }, [barcodeReadabilityModelDownloadProgress, barcodeReadabilityModelState, barcodeReadabilityModelWarmingStartedAt, documentDetectionModelDownloadProgress, documentDetectionModelState, documentDetectionModelWarmingStartedAt, enableBarcodeReadabilityModel, focusModelDownloadProgress, focusModelState, focusModelWarmingStartedAt]),
6042
+ ready = _k.ready,
6043
+ modelLoadState = _k.modelLoadState,
6044
+ modelWarmingStartedAt = _k.modelWarmingStartedAt,
6045
+ modelDownloadProgress = _k.modelDownloadProgress;
5941
6046
  var value = React.useMemo(function () {
5942
6047
  return {
5943
6048
  ready: ready,
5944
- modelDownloadProgress: (documentDetectionModelDownloadProgress + focusModelDownloadProgress) / 2,
6049
+ modelDownloadProgress: modelDownloadProgress,
5945
6050
  modelLoadState: modelLoadState,
5946
6051
  modelWarmingStartedAt: modelWarmingStartedAt,
5947
6052
  modelError: modelError,
@@ -5955,24 +6060,35 @@ function IdCaptureModelsProviderInner(_a) {
5955
6060
  onPredictionMade: onPredictionMade,
5956
6061
  detectionTime: detectionTime,
5957
6062
  focusPredictionTime: focusPredictionTime,
6063
+ barcodeReadabilityPredictionTime: barcodeReadabilityPredictionTime,
5958
6064
  getBestFrame: getBestFrame,
5959
6065
  resetBestFrame: resetBestFrame,
5960
6066
  bestFrameDetails: bestFrameDetails,
6067
+ bestBarcodeDetails: bestBarcodeDetails,
6068
+ getBestBarcode: getBestBarcode,
5961
6069
  requiredDocumentType: requiredDocumentType,
5962
6070
  setRequiredDocumentType: setRequiredDocumentType
5963
6071
  };
5964
- }, [detectionTime, documentDetectionBoundaries, documentDetectionModelDownloadProgress, focusModelDownloadProgress, focusPredictionTime, getBestFrame, load, modelLoadState, modelError, modelWarmingStartedAt, onPredictionMade, ready, requiredDocumentType, resetBestFrame, setDocumentDetectionBoundaries, setThresholds, startDocumentDetection, stopDocumentDetection, thresholds]);
6072
+ }, [ready, modelDownloadProgress, modelLoadState, modelWarmingStartedAt, modelError, startDocumentDetection, stopDocumentDetection, load, thresholds, setThresholds, documentDetectionBoundaries, setDocumentDetectionBoundaries, onPredictionMade, detectionTime, focusPredictionTime, barcodeReadabilityPredictionTime, getBestFrame, resetBestFrame, getBestBarcode, requiredDocumentType]);
5965
6073
  return /*#__PURE__*/React__namespace.default.createElement(IdCaptureModelsContext.Provider, {
5966
6074
  value: value
5967
- }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5968
- key: canvasKey,
6075
+ }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
6076
+ key: "bf-".concat(canvasKey),
5969
6077
  ref: bestPredictionCanvas
5970
- }), children);
6078
+ }), /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
6079
+ key: "bb-".concat(canvasKey),
6080
+ ref: bestBarcodeCanvas
6081
+ }), /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
6082
+ key: "cd-".concat(canvasKey),
6083
+ ref: croppedDocumentCanvas
6084
+ })), children);
5971
6085
  }
5972
6086
  function IdCaptureModelsProvider(_a) {
5973
6087
  var children = _a.children,
5974
6088
  props = __rest(_a, ["children"]);
5975
- return /*#__PURE__*/React__namespace.default.createElement(DocumentDetectionModelProvider, _assign({}, props), /*#__PURE__*/React__namespace.default.createElement(FocusModelProvider, _assign({}, props), /*#__PURE__*/React__namespace.default.createElement(IdCaptureModelsProviderInner, _assign({}, props), children)));
6089
+ return /*#__PURE__*/React__namespace.default.createElement(DocumentDetectionModelProvider, _assign({}, props), /*#__PURE__*/React__namespace.default.createElement(FocusModelProvider, _assign({}, props), /*#__PURE__*/React__namespace.default.createElement(BarcodeReadabilityModelProvider, _assign({}, props, {
6090
+ shouldLoadModels: props.enableBarcodeReadabilityModel
6091
+ }), /*#__PURE__*/React__namespace.default.createElement(IdCaptureModelsProviderInner, _assign({}, props), children))));
5976
6092
  }
5977
6093
  function useIdCaptureModelsContext() {
5978
6094
  var context = React.useContext(IdCaptureModelsContext);
@@ -5982,7 +6098,7 @@ function useIdCaptureModelsContext() {
5982
6098
  return context;
5983
6099
  }
5984
6100
 
5985
- var CapturedDocumentTypeValues = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'selfie', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
6101
+ var CapturedDocumentTypeValues = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'selfie', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage', 'idBarcodeImage'];
5986
6102
 
5987
6103
  var acceptedDocumentTypesForIdCaptureRequirementOption = {
5988
6104
  idCardFront: ['idCardFront'],
@@ -6068,6 +6184,7 @@ var initialState$5 = {
6068
6184
  capturing: false,
6069
6185
  captureFailed: false,
6070
6186
  imageUrl: null,
6187
+ idBarcodeImage: null,
6071
6188
  captureState: 'initializing',
6072
6189
  capturedDocuments: {},
6073
6190
  captureRequirement: 'idCardOrPassport',
@@ -6347,6 +6464,17 @@ var _reducer = function reducer(state, action) {
6347
6464
  }
6348
6465
  return newState;
6349
6466
  }
6467
+ case 'barcodeCaptured':
6468
+ return _reducer(state, {
6469
+ type: 'documentCaptured',
6470
+ payload: {
6471
+ imageData: action.payload.imageUrl,
6472
+ documentType: 'idBarcodeImage',
6473
+ width: 0,
6474
+ height: 0,
6475
+ barcodeReadabilityScore: action.payload.barcodeReadabilityScore
6476
+ }
6477
+ });
6350
6478
  case 'flipRequestCompleted':
6351
6479
  return _assign(_assign({}, state), {
6352
6480
  captureState: 'capturing',
@@ -6838,12 +6966,13 @@ var IdCapture = function IdCapture(_a) {
6838
6966
  height = _q === void 0 ? 1 : _q;
6839
6967
  var state = useIdCaptureStore();
6840
6968
  var isRearFacing = useCameraStore().isRearFacing;
6841
- var _r = React.useContext(IdCaptureModelsContext),
6969
+ var _r = useIdCaptureModelsContext(),
6842
6970
  modelsReady = _r.ready,
6843
6971
  setThresholds = _r.setThresholds,
6844
6972
  detectionTime = _r.detectionTime,
6845
6973
  focusPredictionTime = _r.focusPredictionTime,
6846
- getBestFrame = _r.getBestFrame;
6974
+ getBestFrame = _r.getBestFrame,
6975
+ getBestBarcode = _r.getBestBarcode;
6847
6976
  React.useEffect(function () {
6848
6977
  return dispatchIdCaptureAction({
6849
6978
  type: 'captureInitialized'
@@ -6882,6 +7011,16 @@ var IdCapture = function IdCapture(_a) {
6882
7011
  });
6883
7012
  return;
6884
7013
  }
7014
+ var bestBarcode = getBestBarcode();
7015
+ if (bestBarcode) {
7016
+ dispatchIdCaptureAction({
7017
+ type: 'barcodeCaptured',
7018
+ payload: {
7019
+ imageUrl: bestBarcode.canvas.toDataURL('image/jpeg', 0.95),
7020
+ barcodeReadabilityScore: bestBarcode.score
7021
+ }
7022
+ });
7023
+ }
6885
7024
  var canvas = bestFrame.canvas,
6886
7025
  documentType = bestFrame.documentType,
6887
7026
  boundingBox = bestFrame.boundingBox,
@@ -6898,21 +7037,22 @@ var IdCapture = function IdCapture(_a) {
6898
7037
  });
6899
7038
  var capturedDocumentType = documentType;
6900
7039
  setTimeout(function () {
6901
- var _a;
6902
- var captureTime = new Date().getTime() - ((_a = state.captureStartedAt) !== null && _a !== void 0 ? _a : new Date()).getTime();
7040
+ var _a, _b;
7041
+ var captureTime = performance.now() - ((_a = state.captureStartedAt) !== null && _a !== void 0 ? _a : new Date()).getTime();
6903
7042
  var metadata = {
6904
7043
  autoCapture: 'Y',
6905
7044
  captureTime: captureTime,
6906
7045
  boundingBox: boundingBox,
6907
7046
  bestDetectionScore: detectionScore,
6908
- bestFocusScore: focusScore
7047
+ bestFocusScore: focusScore,
7048
+ bestBarcodeScore: (_b = bestBarcode === null || bestBarcode === void 0 ? void 0 : bestBarcode.score) !== null && _b !== void 0 ? _b : 0
6909
7049
  };
6910
7050
  onCapture === null || onCapture === void 0 ? void 0 : onCapture(imageUrl, width, height, capturedDocumentType, metadata);
6911
7051
  dispatchIdCaptureAction({
6912
7052
  type: 'captured'
6913
7053
  });
6914
7054
  }, 0);
6915
- }, [getBestFrame, onCapture, shouldCapture, state.captureStartedAt, state.requestedDocumentType]);
7055
+ }, [getBestBarcode, getBestFrame, onCapture, shouldCapture, state.captureStartedAt, state.requestedDocumentType]);
6916
7056
  var theme = styled.useTheme();
6917
7057
  colors.guideBoxUnsatisfiedColor || (colors.guideBoxUnsatisfiedColor = (_d = (_c = (_b = theme.idCapture) === null || _b === void 0 ? void 0 : _b.guideBox) === null || _c === void 0 ? void 0 : _c.unsatisfiedColor) !== null && _d !== void 0 ? _d : 'white');
6918
7058
  colors.guideBoxSatisfiedColor || (colors.guideBoxSatisfiedColor = (_g = (_f = (_e = theme.idCapture) === null || _e === void 0 ? void 0 : _e.guideBox) === null || _f === void 0 ? void 0 : _f.satisfiedColor) !== null && _g !== void 0 ? _g : 'green');
@@ -7712,7 +7852,7 @@ var IdCaptureLoadingOverlayDefault = function IdCaptureLoadingOverlayDefault(_a)
7712
7852
  };
7713
7853
  }, [ready]);
7714
7854
  var imageRef = React.useRef(null);
7715
- var timeSinceWarmingStarted = modelWarmingStartedAt ? new Date().getTime() - modelWarmingStartedAt : 0;
7855
+ var timeSinceWarmingStarted = modelWarmingStartedAt ? performance.now() - modelWarmingStartedAt : 0;
7716
7856
  var warmingProgress = timeSinceWarmingStarted / 5000.0;
7717
7857
  var modelLoadProgress = modelsReady ? 100 : modelDownloadProgress * 0.5 + warmingProgress * 49.0;
7718
7858
  useLoadProgressHooks({
@@ -8050,7 +8190,7 @@ var Card = styled__default.default.div(templateObject_1$D || (templateObject_1$D
8050
8190
  var FlexCard = styled__default.default(Card)(templateObject_2$y || (templateObject_2$y = __makeTemplateObject(["\n display: flex;\n flex-direction: column;\n"], ["\n display: flex;\n flex-direction: column;\n"])));
8051
8191
  var templateObject_1$D, templateObject_2$y;
8052
8192
 
8053
- var imageDisplayOrder = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
8193
+ var imageDisplayOrder = ['idCardFront', 'idCardBack', 'idBarcodeImage', 'passport', 'singlePage', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
8054
8194
  var IdCaptureSuccess = function IdCaptureSuccess(_a) {
8055
8195
  var capturedDocuments = _a.capturedDocuments,
8056
8196
  onSubmitClick = _a.onSubmitClick,
@@ -8092,7 +8232,7 @@ var IdCaptureSuccess = function IdCaptureSuccess(_a) {
8092
8232
  image: doc,
8093
8233
  className: classNames.image,
8094
8234
  alt: doc.documentType
8095
- }), debugMode && ( /*#__PURE__*/React__namespace.default.createElement(DebugPre, null, "Document Type: ".concat(doc.documentType, "\nDetection Score: ").concat(doc.detectionScore, "\nFocus Score: ").concat(doc.focusScore, "\nBounding Box: ").concat(JSON.stringify(doc.boundingBox)))));
8235
+ }), debugMode && ( /*#__PURE__*/React__namespace.default.createElement(DebugPre, null, name === 'idBarcodeImage' ? "Document Type: ".concat(doc.documentType, "\nReadability Score: ").concat(doc.barcodeReadabilityScore) : "Document Type: ".concat(doc.documentType, "\nDetection Score: ").concat(doc.detectionScore, "\nFocus Score: ").concat(doc.focusScore, "\nBounding Box: ").concat(JSON.stringify(doc.boundingBox)))));
8096
8236
  }))), /*#__PURE__*/React__namespace.default.createElement(ButtonsColumn, {
8097
8237
  className: classNames.buttonsRow
8098
8238
  }, /*#__PURE__*/React__namespace.default.createElement(WideButton, {
@@ -10714,7 +10854,7 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10714
10854
  var _6 = React.useState(false),
10715
10855
  overlayDismissed = _6[0],
10716
10856
  setOverlayDismissed = _6[1];
10717
- var _7 = React.useContext(SubmissionContext),
10857
+ var _7 = useSubmissionContext(),
10718
10858
  submissionStatus = _7.submissionStatus,
10719
10859
  setIdFrontImage = _7.setIdFrontImage,
10720
10860
  setIdBackImage = _7.setIdBackImage,
@@ -10723,6 +10863,7 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10723
10863
  setIdBackIrImage = _7.setIdBackIrImage,
10724
10864
  setIdFrontUvImage = _7.setIdFrontUvImage,
10725
10865
  setIdBackUvImage = _7.setIdBackUvImage,
10866
+ setIdBarcodeImage = _7.setIdBarcodeImage,
10726
10867
  logIdFrontCaptureAttempt = _7.logIdFrontCaptureAttempt,
10727
10868
  logIdBackCaptureAttempt = _7.logIdBackCaptureAttempt;
10728
10869
  var _8 = useIdCaptureModelsContext(),
@@ -10823,7 +10964,7 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10823
10964
  });
10824
10965
  }, [logCaptureMetadata, onDocumentCaptured]);
10825
10966
  var onSubmitClick = React.useCallback(function () {
10826
- var _a, _b, _c, _d, _e, _f, _g, _h;
10967
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
10827
10968
  var docs = state.capturedDocuments;
10828
10969
  var submission = {
10829
10970
  idFrontImage: maybeDataUrlToBase64Sync((_a = docs.idCardFront) === null || _a === void 0 ? void 0 : _a.imageData),
@@ -10833,7 +10974,8 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10833
10974
  idFrontIrImage: maybeDataUrlToBase64Sync((_e = docs.idFrontIrImage) === null || _e === void 0 ? void 0 : _e.imageData),
10834
10975
  idBackIrImage: maybeDataUrlToBase64Sync((_f = docs.idBackIrImage) === null || _f === void 0 ? void 0 : _f.imageData),
10835
10976
  idFrontUvImage: maybeDataUrlToBase64Sync((_g = docs.idFrontUvImage) === null || _g === void 0 ? void 0 : _g.imageData),
10836
- idBackUvImage: maybeDataUrlToBase64Sync((_h = docs.idBackUvImage) === null || _h === void 0 ? void 0 : _h.imageData)
10977
+ idBackUvImage: maybeDataUrlToBase64Sync((_h = docs.idBackUvImage) === null || _h === void 0 ? void 0 : _h.imageData),
10978
+ idBarcodeImage: maybeDataUrlToBase64Sync((_j = docs.idBarcodeImage) === null || _j === void 0 ? void 0 : _j.imageData)
10837
10979
  };
10838
10980
  if (submission.idFrontImage) setIdFrontImage(submission.idFrontImage);
10839
10981
  if (submission.idBackImage) setIdBackImage(submission.idBackImage);
@@ -10843,11 +10985,12 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10843
10985
  if (submission.idBackIrImage) setIdBackIrImage(submission.idBackIrImage);
10844
10986
  if (submission.idFrontUvImage) setIdFrontUvImage(submission.idFrontUvImage);
10845
10987
  if (submission.idBackUvImage) setIdBackUvImage(submission.idBackUvImage);
10988
+ if (submission.idBarcodeImage) setIdBarcodeImage(submission.idBarcodeImage);
10846
10989
  if (releaseCameraAccessOnExit) releaseCameraAccess();
10847
10990
  setTimeout(function () {
10848
10991
  return onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(submission);
10849
10992
  }, 0);
10850
- }, [onSuccess, releaseCameraAccess, releaseCameraAccessOnExit, setIdBackImage, setIdBackIrImage, setIdBackUvImage, setIdFrontImage, setIdFrontIrImage, setIdFrontUvImage, setPassportImage, state.capturedDocuments]);
10993
+ }, [onSuccess, releaseCameraAccess, releaseCameraAccessOnExit, setIdBarcodeImage, setIdBackImage, setIdBackIrImage, setIdBackUvImage, setIdFrontImage, setIdFrontIrImage, setIdFrontUvImage, setPassportImage, state.capturedDocuments]);
10851
10994
  var showSuccessScreen = useShowSuccessScreen(skipSuccessScreen, state.captureState === 'complete', onSubmitClick);
10852
10995
  var onRetryClick = React.useCallback(function () {
10853
10996
  return dispatchIdCaptureAction({
@@ -11656,40 +11799,378 @@ function SelfieCaptureAnimatedMaskWithStatus(_a) {
11656
11799
  });
11657
11800
  }, 250);
11658
11801
  return function () {
11659
- clearInterval(interval);
11802
+ clearInterval(interval);
11803
+ };
11804
+ }, [status]);
11805
+ return /*#__PURE__*/React__namespace.default.createElement(SelfieCaptureAnimatedMask, _assign({}, props, {
11806
+ frame: frame,
11807
+ status: status
11808
+ }));
11809
+ }
11810
+ var templateObject_1$o, templateObject_2$m, templateObject_3$g;
11811
+
11812
+ var FaceCaptureGuideContainer = styled__default.default.div(templateObject_1$n || (templateObject_1$n = __makeTemplateObject(["\n position: absolute;\n z-index: 1000;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n box-sizing: border-box;\n"], ["\n position: absolute;\n z-index: 1000;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n box-sizing: border-box;\n"])));
11813
+ var FaceCaptureGuideInner = styled__default.default.div(templateObject_2$l || (templateObject_2$l = __makeTemplateObject(["\n position: relative;\n height: 60%;\n"], ["\n position: relative;\n height: 60%;\n"])));
11814
+ var FaceCaptureGuideOverlay = function FaceCaptureGuideOverlay(_a) {
11815
+ var _b = _a.classNames,
11816
+ classNames = _b === void 0 ? {} : _b,
11817
+ _c = _a.status,
11818
+ status = _c === void 0 ? 'ready' : _c,
11819
+ _d = _a.borderWidth,
11820
+ borderWidth = _d === void 0 ? 5 : _d,
11821
+ _e = _a.borderColor,
11822
+ borderColor = _e === void 0 ? 'white' : _e,
11823
+ _f = _a.borderOpacity,
11824
+ borderOpacity = _f === void 0 ? 0.8 : _f;
11825
+ return /*#__PURE__*/React__namespace.default.createElement(FaceCaptureGuideContainer, {
11826
+ className: classNames.container
11827
+ }, /*#__PURE__*/React__namespace.default.createElement(FaceCaptureGuideInner, null, /*#__PURE__*/React__namespace.default.createElement(SelfieCaptureAnimatedMaskWithStatus, {
11828
+ status: status,
11829
+ borderColor: borderColor,
11830
+ borderWidth: borderWidth,
11831
+ borderOpacity: borderOpacity,
11832
+ verticalAlign: "center"
11833
+ })));
11834
+ };
11835
+ var templateObject_1$n, templateObject_2$l;
11836
+
11837
+ var defaultSelfieCaptureModelLoadTimeoutMs = 45000;
11838
+ var detector = null;
11839
+ var detectorSettings = null;
11840
+ function loadFaceDetector() {
11841
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
11842
+ var _a, _b;
11843
+ if (modelAssetPath === void 0) {
11844
+ modelAssetPath = defaultFaceDetectorModelPath;
11845
+ }
11846
+ return __generator(this, function (_c) {
11847
+ switch (_c.label) {
11848
+ case 0:
11849
+ if (detector && (detectorSettings === null || detectorSettings === void 0 ? void 0 : detectorSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, detector];
11850
+ closeFaceDetector();
11851
+ return [4 /*yield*/, preloadFaceDetectorDependencies()];
11852
+ case 1:
11853
+ _c.sent();
11854
+ if (modelCapabilities.delegate === 'NONE') {
11855
+ throw new Error('No available delegate for face detector.');
11856
+ }
11857
+ _b = (_a = tasksVision.FaceDetector).createFromOptions;
11858
+ return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
11859
+ case 2:
11860
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
11861
+ // canvas: document.createElement('canvas'),
11862
+ baseOptions: {
11863
+ modelAssetPath: modelAssetPath,
11864
+ delegate: modelCapabilities.delegate
11865
+ },
11866
+ runningMode: 'VIDEO'
11867
+ }])];
11868
+ case 3:
11869
+ detector = _c.sent();
11870
+ detectorSettings = {
11871
+ modelAssetPath: modelAssetPath
11872
+ };
11873
+ return [2 /*return*/, detector];
11874
+ }
11875
+ });
11876
+ });
11877
+ }
11878
+ function closeFaceDetector() {
11879
+ detector === null || detector === void 0 ? void 0 : detector.close();
11880
+ detector = null;
11881
+ detectorSettings = null;
11882
+ }
11883
+ function useLoadFaceDetector(_a) {
11884
+ var onModelError = _a.onModelError,
11885
+ _b = _a.modelLoadTimeoutMs,
11886
+ modelLoadTimeoutMs = _b === void 0 ? defaultSelfieCaptureModelLoadTimeoutMs : _b,
11887
+ videoRef = _a.videoRef;
11888
+ var _c = React.useState('not-started'),
11889
+ modelLoadState = _c[0],
11890
+ setModelLoadState = _c[1];
11891
+ var _d = React.useState(0),
11892
+ modelDownloadProgress = _d[0],
11893
+ setModelDownloadProgress = _d[1];
11894
+ var _e = React.useState(null),
11895
+ modelWarmingStartedAt = _e[0],
11896
+ setModelWarmingStartedAt = _e[1];
11897
+ var _f = React.useState(null),
11898
+ modelError = _f[0],
11899
+ setModelError = _f[1];
11900
+ React.useEffect(function loadModel() {
11901
+ var _this = this;
11902
+ setModelLoadState('downloading');
11903
+ setModelWarmingStartedAt(null);
11904
+ var modelLoadTimeout = setTimeout(function () {
11905
+ setModelError(new Error('Model loading time limit exceeded.'));
11906
+ }, modelLoadTimeoutMs);
11907
+ function handleDownloadProgress(event) {
11908
+ setModelDownloadProgress(progressToPercentage(event.detail));
11909
+ }
11910
+ document.addEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
11911
+ var cancelVideoReady = function cancelVideoReady() {};
11912
+ loadFaceDetector().then(function (model) {
11913
+ return __awaiter(_this, void 0, void 0, function () {
11914
+ var _a, videoReady, cancel, cancelled;
11915
+ return __generator(this, function (_b) {
11916
+ switch (_b.label) {
11917
+ case 0:
11918
+ setModelDownloadProgress(100);
11919
+ clearTimeout(modelLoadTimeout);
11920
+ setModelLoadState('warming');
11921
+ setModelWarmingStartedAt(performance.now());
11922
+ return [4 /*yield*/, testFaceDetectionAgainstKnownImage(model)];
11923
+ case 1:
11924
+ _b.sent();
11925
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
11926
+ cancelled = false;
11927
+ cancelVideoReady = function cancelVideoReady() {
11928
+ cancelled = true;
11929
+ cancel();
11930
+ };
11931
+ return [4 /*yield*/, videoReady];
11932
+ case 2:
11933
+ _b.sent();
11934
+ if (cancelled) return [2 /*return*/];
11935
+ model.detectForVideo(videoRef.current, performance.now());
11936
+ setModelLoadState('ready');
11937
+ return [2 /*return*/];
11938
+ }
11939
+ });
11940
+ });
11941
+ })["catch"](function (e) {
11942
+ setModelError(e);
11943
+ setModelLoadState('error');
11944
+ })["finally"](function () {
11945
+ clearTimeout(modelLoadTimeout);
11946
+ });
11947
+ return function () {
11948
+ log('unloading face detection model');
11949
+ cancelVideoReady();
11950
+ closeFaceDetector();
11951
+ clearTimeout(modelLoadTimeout);
11952
+ document.removeEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
11660
11953
  };
11661
- }, [status]);
11662
- return /*#__PURE__*/React__namespace.default.createElement(SelfieCaptureAnimatedMask, _assign({}, props, {
11663
- frame: frame,
11664
- status: status
11665
- }));
11954
+ }, [modelLoadTimeoutMs, videoRef]);
11955
+ React.useEffect(function handleModelError() {
11956
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
11957
+ }, [modelError, onModelError]);
11958
+ return React.useMemo(function () {
11959
+ return {
11960
+ ready: modelLoadState === 'ready',
11961
+ modelLoadState: modelLoadState,
11962
+ modelDownloadProgress: modelDownloadProgress,
11963
+ modelWarmingStartedAt: modelWarmingStartedAt,
11964
+ modelError: modelError
11965
+ };
11966
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
11967
+ }
11968
+ var lastFaceDetectionAt = 0;
11969
+ var lastFaceDetectionTime = 0;
11970
+ function setLastFaceDetectionAt(time) {
11971
+ lastFaceDetectionTime = time - lastFaceDetectionAt;
11972
+ lastFaceDetectionAt = time;
11973
+ }
11974
+ var framesNeededSamples = [];
11975
+ function trackFramesNeeded(value, bufferLength) {
11976
+ if (bufferLength === void 0) {
11977
+ bufferLength = 25;
11978
+ }
11979
+ framesNeededSamples.unshift(value);
11980
+ if (framesNeededSamples.length > bufferLength) framesNeededSamples.length = bufferLength;
11981
+ }
11982
+ var lastNFaces = [];
11983
+ var lastNFacePairs = [];
11984
+ var lastNNoses = [];
11985
+ var lastNNosePairs = [];
11986
+ function trackFace(face, framesNeeded, frameWidth, frameHeight) {
11987
+ if (framesNeeded === void 0) {
11988
+ framesNeeded = 12;
11989
+ }
11990
+ var nose = face.keypoints[2];
11991
+ if (!nose) return;
11992
+ lastNFaces.unshift(face);
11993
+ lastNNoses.unshift(nose);
11994
+ if (lastNFaces.length > framesNeeded) lastNFaces.length = framesNeeded;
11995
+ if (lastNNoses.length > framesNeeded) lastNNoses.length = framesNeeded;
11996
+ if (lastNFaces.length > 1) {
11997
+ var lastFace = lastNFaces[1];
11998
+ var iou = calculateIoU(face.box, lastFace.box);
11999
+ lastNFacePairs.unshift({
12000
+ a: face,
12001
+ b: lastFace,
12002
+ iou: iou
12003
+ });
12004
+ if (lastNFacePairs.length > framesNeeded - 1) lastNFacePairs.length = framesNeeded - 1;
12005
+ }
12006
+ if (lastNNoses.length > 1) {
12007
+ var lastNose = lastNNoses[1];
12008
+ var noseDistance = Math.sqrt(Math.pow((nose.x - lastNose.x) / frameWidth, 2) + Math.pow((nose.y - lastNose.y) / frameHeight, 2));
12009
+ lastNNosePairs.unshift({
12010
+ a: nose,
12011
+ b: lastNose,
12012
+ distance: noseDistance
12013
+ });
12014
+ if (lastNNosePairs.length > framesNeeded - 1) lastNNosePairs.length = framesNeeded - 1;
12015
+ }
12016
+ }
12017
+ function makeFaceDetectorPrediction(imageData) {
12018
+ if (!detector) return null;
12019
+ var prediction = detector.detectForVideo(imageData, performance.now());
12020
+ var faces = prediction.detections.map(function (d) {
12021
+ return {
12022
+ box: convertBoundingBox(d.boundingBox),
12023
+ keypoints: d.keypoints.map(function (k) {
12024
+ var _a;
12025
+ return _assign(_assign({}, k), {
12026
+ x: k.x * imageData.width,
12027
+ y: k.y * imageData.height,
12028
+ name: (_a = k.label) !== null && _a !== void 0 ? _a : ''
12029
+ });
12030
+ })
12031
+ };
12032
+ });
12033
+ return _assign(_assign({}, prediction), {
12034
+ faces: faces
12035
+ });
12036
+ }
12037
+ function processFaceDetectorPrediction(_a) {
12038
+ var faces = _a.faces,
12039
+ videoWidth = _a.videoWidth,
12040
+ videoHeight = _a.videoHeight,
12041
+ _b = _a.requireVerticalFaceCentering,
12042
+ requireVerticalFaceCentering = _b === void 0 ? true : _b,
12043
+ _c = _a.stabilityThreshold,
12044
+ stabilityThreshold = _c === void 0 ? 0.7 : _c,
12045
+ _d = _a.noseDistanceThreshold,
12046
+ noseDistanceThreshold = _d === void 0 ? 0.025 : _d,
12047
+ _e = _a.xBoundary,
12048
+ xBoundary = _e === void 0 ? 0.01 : _e,
12049
+ // this represents the edge that the sides of the face box should not cross -- 1% of video width
12050
+ _f = _a.yBoundary,
12051
+ // this represents the edge that the sides of the face box should not cross -- 1% of video width
12052
+ yBoundary = _f === void 0 ? 0.01 : _f,
12053
+ // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
12054
+ _g = _a.xCentroidBoundary,
12055
+ // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
12056
+ xCentroidBoundary = _g === void 0 ? 0.125 : _g,
12057
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
12058
+ _h = _a.yCentroidBoundary,
12059
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
12060
+ yCentroidBoundary = _h === void 0 ? 0.125 : _h,
12061
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
12062
+ _j = _a.foreheadRatio,
12063
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
12064
+ foreheadRatio = _j === void 0 ? 0.275 : _j,
12065
+ // we found that the bounding box ends at the brow and misses the forehead. this ratio represents how much we should extend the box to include the forehead.
12066
+ _k = _a.noseTrackingThreshold,
12067
+ // we found that the bounding box ends at the brow and misses the forehead. this ratio represents how much we should extend the box to include the forehead.
12068
+ noseTrackingThreshold = _k === void 0 ? 0.2 : _k,
12069
+ // this represents the maximum distance that the nose can be from the center of the face box -- 20% of the face box width or height
12070
+ minCaptureBrightnessThreshold = _a.minCaptureBrightnessThreshold,
12071
+ minCaptureRangeThreshold = _a.minCaptureRangeThreshold,
12072
+ minCaptureVarianceThreshold = _a.minCaptureVarianceThreshold,
12073
+ brightness = _a.brightness,
12074
+ range = _a.range,
12075
+ variance = _a.variance;
12076
+ var face = faces[0];
12077
+ var faceNotDetected = faces.length === 0;
12078
+ var faceNotCentered = false,
12079
+ faceLookingAway = false,
12080
+ faceTooClose = false,
12081
+ faceTooFar = false,
12082
+ faceVisibilityTooLow = false;
12083
+ var hasAnyThreshold = minCaptureBrightnessThreshold !== undefined || minCaptureRangeThreshold !== undefined || minCaptureVarianceThreshold !== undefined;
12084
+ if (hasAnyThreshold) {
12085
+ var tooDark = minCaptureBrightnessThreshold !== undefined && brightness !== undefined && brightness < minCaptureBrightnessThreshold;
12086
+ var tooLowRange = minCaptureRangeThreshold !== undefined && range !== undefined && range < minCaptureRangeThreshold;
12087
+ var tooLowVariance = minCaptureVarianceThreshold !== undefined && variance !== undefined && variance < minCaptureVarianceThreshold;
12088
+ faceVisibilityTooLow = !!(tooDark || tooLowRange || tooLowVariance);
12089
+ }
12090
+ if (face && !faceVisibilityTooLow) {
12091
+ // calculate frame centroids
12092
+ var frameCX = videoWidth / 2;
12093
+ var frameCY = videoHeight / 2;
12094
+ // calculate head bounding box, with forehead extension
12095
+ var foreheadSize = face.box.height * foreheadRatio;
12096
+ var headXMin = face.box.xMin;
12097
+ var headXMax = face.box.xMax;
12098
+ var headYMin = face.box.yMin - foreheadSize;
12099
+ var headYMax = face.box.yMax;
12100
+ // calculate head centroids
12101
+ var headCX = (headXMin + headXMax) / 2;
12102
+ var headCY = (headYMin + headYMax) / 2;
12103
+ // calculate thresholds
12104
+ var vTX = videoWidth * xBoundary;
12105
+ var vTY = videoHeight * yBoundary;
12106
+ var vCTX = videoWidth * xCentroidBoundary;
12107
+ var vCTY = videoHeight * yCentroidBoundary;
12108
+ var faceNotCenteredHorizontally = Math.abs(frameCX - headCX) > vCTX;
12109
+ var faceNotCenteredVertically = Math.abs(frameCY - headCY) > vCTY;
12110
+ var faceViolatesHorizontalBoundary = headXMin < vTX || headXMax > videoWidth - vTX;
12111
+ var faceViolatesVerticalBoundary = headYMin < vTY || headYMax > videoHeight - vTY;
12112
+ faceNotCentered = faceViolatesHorizontalBoundary || faceViolatesVerticalBoundary || faceNotCenteredHorizontally || requireVerticalFaceCentering && faceNotCenteredVertically;
12113
+ var isMobile = videoWidth < videoHeight;
12114
+ var tooCloseMultiple = 1.5;
12115
+ var tooFarMultiple = isMobile ? 6 : 7;
12116
+ faceTooClose = face.box.width > videoWidth / tooCloseMultiple;
12117
+ faceTooFar = face.box.width < videoWidth / tooFarMultiple;
12118
+ var nose = face.keypoints[2];
12119
+ var fTW = face.box.width * noseTrackingThreshold;
12120
+ var fTH = face.box.height * noseTrackingThreshold;
12121
+ faceLookingAway = !nose || Math.abs(headCX - nose.x) > fTW || Math.abs(headCY - nose.y) > fTH;
12122
+ }
12123
+ var faceInGuides = !faceNotDetected && !faceNotCentered && !faceLookingAway && !faceTooClose && !faceTooFar;
12124
+ if (lastFaceDetectionTime > 0) {
12125
+ trackFramesNeeded(500 / lastFaceDetectionTime);
12126
+ }
12127
+ var faceIsStable = false,
12128
+ noseIsStable = false;
12129
+ if (faceInGuides && !faceVisibilityTooLow) {
12130
+ var framesNeeded = Math.max(Math.ceil(average(framesNeededSamples)), 5);
12131
+ trackFace(face, framesNeeded, videoWidth, videoHeight);
12132
+ faceIsStable = lastNFaces.length >= framesNeeded && !lastNFacePairs.some(function (pair) {
12133
+ return pair.iou < stabilityThreshold;
12134
+ });
12135
+ noseIsStable = lastNNoses.length >= framesNeeded && !lastNNosePairs.some(function (pair) {
12136
+ return pair.distance > noseDistanceThreshold;
12137
+ });
12138
+ }
12139
+ var faceReady = faceInGuides && faceIsStable && noseIsStable && !faceVisibilityTooLow;
12140
+ return {
12141
+ face: face,
12142
+ faceNotDetected: faceNotDetected,
12143
+ faceNotCentered: faceNotCentered,
12144
+ faceLookingAway: faceLookingAway,
12145
+ faceTooClose: faceTooClose,
12146
+ faceTooFar: faceTooFar,
12147
+ faceReady: faceReady,
12148
+ faceReadyAt: faceReady ? new Date() : null,
12149
+ faceIsStable: faceIsStable,
12150
+ noseIsStable: noseIsStable,
12151
+ faceVisibilityTooLow: faceVisibilityTooLow
12152
+ };
12153
+ }
12154
+ function testFaceDetectionAgainstKnownImage(detector) {
12155
+ return new Promise(function (resolve, reject) {
12156
+ var img = new Image();
12157
+ img.crossOrigin = 'anonymous';
12158
+ img.onload = function () {
12159
+ var prediction = detector.detectForVideo(img, performance.now());
12160
+ if (prediction.detections.length > 0) {
12161
+ debug('face detection test result', prediction.detections);
12162
+ resolve(void 0);
12163
+ } else {
12164
+ warn('face detection test failed');
12165
+ reject(new Error('testFaceDetectionAgainstKnownImage failed to predict'));
12166
+ }
12167
+ };
12168
+ img.onerror = function () {
12169
+ return reject(new Error('testFaceDetectionAgainstKnownImage failed to load image'));
12170
+ };
12171
+ img.src = "".concat(DEFAULT_CDN_URL, "/head-test.jpg");
12172
+ });
11666
12173
  }
11667
- var templateObject_1$o, templateObject_2$m, templateObject_3$g;
11668
-
11669
- var FaceCaptureGuideContainer = styled__default.default.div(templateObject_1$n || (templateObject_1$n = __makeTemplateObject(["\n position: absolute;\n z-index: 1000;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n box-sizing: border-box;\n"], ["\n position: absolute;\n z-index: 1000;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n box-sizing: border-box;\n"])));
11670
- var FaceCaptureGuideInner = styled__default.default.div(templateObject_2$l || (templateObject_2$l = __makeTemplateObject(["\n position: relative;\n height: 60%;\n"], ["\n position: relative;\n height: 60%;\n"])));
11671
- var FaceCaptureGuideOverlay = function FaceCaptureGuideOverlay(_a) {
11672
- var _b = _a.classNames,
11673
- classNames = _b === void 0 ? {} : _b,
11674
- _c = _a.status,
11675
- status = _c === void 0 ? 'ready' : _c,
11676
- _d = _a.borderWidth,
11677
- borderWidth = _d === void 0 ? 5 : _d,
11678
- _e = _a.borderColor,
11679
- borderColor = _e === void 0 ? 'white' : _e,
11680
- _f = _a.borderOpacity,
11681
- borderOpacity = _f === void 0 ? 0.8 : _f;
11682
- return /*#__PURE__*/React__namespace.default.createElement(FaceCaptureGuideContainer, {
11683
- className: classNames.container
11684
- }, /*#__PURE__*/React__namespace.default.createElement(FaceCaptureGuideInner, null, /*#__PURE__*/React__namespace.default.createElement(SelfieCaptureAnimatedMaskWithStatus, {
11685
- status: status,
11686
- borderColor: borderColor,
11687
- borderWidth: borderWidth,
11688
- borderOpacity: borderOpacity,
11689
- verticalAlign: "center"
11690
- })));
11691
- };
11692
- var templateObject_1$n, templateObject_2$l;
11693
12174
 
11694
12175
  function detectBrightnessAndContrast(frame, brightnessAverager) {
11695
12176
  var ctx = frame.getContext('2d');
@@ -12983,7 +13464,7 @@ var SelfieCaptureLoadingOverlayDefault = function SelfieCaptureLoadingOverlayDef
12983
13464
  });
12984
13465
  }, 3000);
12985
13466
  }, []);
12986
- var timeSinceWarmingStarted = modelWarmingStartedAt ? new Date().getTime() - modelWarmingStartedAt : 0;
13467
+ var timeSinceWarmingStarted = modelWarmingStartedAt ? performance.now() - modelWarmingStartedAt : 0;
12987
13468
  var warmingProgress = timeSinceWarmingStarted / 5000.0;
12988
13469
  var _o = React.useState(false),
12989
13470
  overrideModelsReady = _o[0],