idmission-web-sdk 2.3.66 → 2.3.68

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 (63) 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/locales/de.d.ts +1 -0
  22. package/dist/lib/locales/de.d.ts.map +1 -1
  23. package/dist/lib/locales/es.d.ts +1 -0
  24. package/dist/lib/locales/es.d.ts.map +1 -1
  25. package/dist/lib/locales/fr.d.ts +1 -0
  26. package/dist/lib/locales/fr.d.ts.map +1 -1
  27. package/dist/lib/locales/index.d.ts +8 -0
  28. package/dist/lib/locales/index.d.ts.map +1 -1
  29. package/dist/lib/locales/it.d.ts +1 -0
  30. package/dist/lib/locales/it.d.ts.map +1 -1
  31. package/dist/lib/locales/ja.d.ts +1 -0
  32. package/dist/lib/locales/ja.d.ts.map +1 -1
  33. package/dist/lib/locales/pt.d.ts +1 -0
  34. package/dist/lib/locales/pt.d.ts.map +1 -1
  35. package/dist/lib/locales/ru.d.ts +1 -0
  36. package/dist/lib/locales/ru.d.ts.map +1 -1
  37. package/dist/lib/locales/zh.d.ts +1 -0
  38. package/dist/lib/locales/zh.d.ts.map +1 -1
  39. package/dist/lib/models/BarcodeReadability.d.ts +50 -0
  40. package/dist/lib/models/BarcodeReadability.d.ts.map +1 -0
  41. package/dist/lib/models/DocumentDetection.d.ts +1 -0
  42. package/dist/lib/models/DocumentDetection.d.ts.map +1 -1
  43. package/dist/lib/models/Focus.d.ts.map +1 -1
  44. package/dist/lib/models/defaults/BarcodeReadability.d.ts +2 -0
  45. package/dist/lib/models/defaults/BarcodeReadability.d.ts.map +1 -0
  46. package/dist/lib/models/defaults/index.d.ts +7 -0
  47. package/dist/lib/models/defaults/index.d.ts.map +1 -1
  48. package/dist/lib/models/preloadModels.d.ts +9 -5
  49. package/dist/lib/models/preloadModels.d.ts.map +1 -1
  50. package/dist/lib/utils/cropping.d.ts +3 -1
  51. package/dist/lib/utils/cropping.d.ts.map +1 -1
  52. package/dist/sdk2.cjs.development.js +1971 -1610
  53. package/dist/sdk2.cjs.development.js.map +1 -1
  54. package/dist/sdk2.cjs.production.js +1 -1
  55. package/dist/sdk2.cjs.production.js.map +1 -1
  56. package/dist/sdk2.esm.js +1972 -1611
  57. package/dist/sdk2.esm.js.map +1 -1
  58. package/dist/sdk2.umd.development.js +1624 -1263
  59. package/dist/sdk2.umd.development.js.map +1 -1
  60. package/dist/sdk2.umd.production.js +1 -1
  61. package/dist/sdk2.umd.production.js.map +1 -1
  62. package/dist/version.d.ts +1 -1
  63. package/package.json +1 -1
@@ -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.66';
239
+ var webSdkVersion = '2.3.68';
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$Q, templateObject_2$I;
507
+ var templateObject_1$Q, templateObject_2$J;
508
508
 
509
509
  var wavesAnimation = styled.keyframes(templateObject_1$P || (templateObject_1$P = __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$n || (templateObject_4$n = __makeTemplateObject(["\n to {\n stroke-dashoffset: 0;\n }\n"], ["\n to {\n stroke-dashoffset: 0;\n }\n"])));
513
- var templateObject_1$P, templateObject_2$H, templateObject_3$u, templateObject_4$n;
513
+ var templateObject_1$P, templateObject_2$I, templateObject_3$u, templateObject_4$n;
514
514
 
515
515
  var OverlayContainer = styled__default.default.div(templateObject_1$O || (templateObject_1$O = __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$O, templateObject_2$G, templateObject_3$t, templateObject_4$m, templateObject_5$e, 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$O, templateObject_2$H, templateObject_3$t, templateObject_4$m, templateObject_5$e, 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
  },
@@ -1331,53 +1339,56 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1331
1339
  passportImage = _13[0],
1332
1340
  setPassportImage = _13[1];
1333
1341
  var _14 = React.useState(null),
1334
- selfieImage = _14[0],
1335
- setSelfieImage = _14[1];
1342
+ idBarcodeImage = _14[0],
1343
+ setIdBarcodeImage = _14[1];
1336
1344
  var _15 = React.useState(null),
1337
- signatureData = _15[0],
1338
- setSignatureData = _15[1];
1345
+ selfieImage = _15[0],
1346
+ setSelfieImage = _15[1];
1339
1347
  var _16 = React.useState(null),
1340
- signatureVideoUrl = _16[0],
1341
- setSignatureVideoUrl = _16[1];
1348
+ signatureData = _16[0],
1349
+ setSignatureData = _16[1];
1342
1350
  var _17 = React.useState(null),
1343
- idCaptureVideoUrl = _17[0],
1344
- setIdCaptureVideoUrl = _17[1];
1351
+ signatureVideoUrl = _17[0],
1352
+ setSignatureVideoUrl = _17[1];
1345
1353
  var _18 = React.useState(null),
1346
- idCaptureVideoIdFrontImage = _18[0],
1347
- setIdCaptureVideoIdFrontImage = _18[1];
1354
+ idCaptureVideoUrl = _18[0],
1355
+ setIdCaptureVideoUrl = _18[1];
1348
1356
  var _19 = React.useState(null),
1349
- idCaptureVideoIdBackImage = _19[0],
1350
- setIdCaptureVideoIdBackImage = _19[1];
1357
+ idCaptureVideoIdFrontImage = _19[0],
1358
+ setIdCaptureVideoIdFrontImage = _19[1];
1351
1359
  var _20 = React.useState(null),
1352
- idCaptureVideoAudioUrl = _20[0],
1353
- setIdCaptureVideoAudioUrl = _20[1];
1360
+ idCaptureVideoIdBackImage = _20[0],
1361
+ setIdCaptureVideoIdBackImage = _20[1];
1354
1362
  var _21 = React.useState(null),
1355
- idCaptureVideoAudioStartsAt = _21[0],
1356
- setIdCaptureVideoAudioStartsAt = _21[1];
1363
+ idCaptureVideoAudioUrl = _21[0],
1364
+ setIdCaptureVideoAudioUrl = _21[1];
1357
1365
  var _22 = React.useState(null),
1358
- expectedAudioText = _22[0],
1359
- setExpectedAudioText = _22[1];
1366
+ idCaptureVideoAudioStartsAt = _22[0],
1367
+ setIdCaptureVideoAudioStartsAt = _22[1];
1360
1368
  var _23 = React.useState(null),
1361
- additionalDocuments = _23[0],
1362
- setAdditionalDocuments = _23[1];
1369
+ expectedAudioText = _23[0],
1370
+ setExpectedAudioText = _23[1];
1363
1371
  var _24 = React.useState(null),
1364
- geolocationResult = _24[0],
1365
- setGeolocationResult = _24[1];
1366
- var _25 = React.useState(0),
1367
- geolocationAttempts = _25[0],
1368
- setGeolocationAttempts = _25[1];
1369
- var _26 = React.useState(false),
1370
- geolocationBlocked = _26[0],
1371
- setGeolocationBlocked = _26[1];
1372
- var _27 = React.useState([]),
1373
- idFrontCaptureAttempts = _27[0],
1374
- setIdFrontCaptureAttempts = _27[1];
1372
+ additionalDocuments = _24[0],
1373
+ setAdditionalDocuments = _24[1];
1374
+ var _25 = React.useState(null),
1375
+ geolocationResult = _25[0],
1376
+ setGeolocationResult = _25[1];
1377
+ var _26 = React.useState(0),
1378
+ geolocationAttempts = _26[0],
1379
+ setGeolocationAttempts = _26[1];
1380
+ var _27 = React.useState(false),
1381
+ geolocationBlocked = _27[0],
1382
+ setGeolocationBlocked = _27[1];
1375
1383
  var _28 = React.useState([]),
1376
- idBackCaptureAttempts = _28[0],
1377
- setIdBackCaptureAttempts = _28[1];
1384
+ idFrontCaptureAttempts = _28[0],
1385
+ setIdFrontCaptureAttempts = _28[1];
1378
1386
  var _29 = React.useState([]),
1379
- selfieCaptureAttempts = _29[0],
1380
- setSelfieCaptureAttempts = _29[1];
1387
+ idBackCaptureAttempts = _29[0],
1388
+ setIdBackCaptureAttempts = _29[1];
1389
+ var _30 = React.useState([]),
1390
+ selfieCaptureAttempts = _30[0],
1391
+ setSelfieCaptureAttempts = _30[1];
1381
1392
  var logIdFrontCaptureAttempt = React.useCallback(function (attempt) {
1382
1393
  setIdFrontCaptureAttempts(function (attempts) {
1383
1394
  return __spreadArray(__spreadArray([], attempts, true), [attempt], false);
@@ -1503,6 +1514,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1503
1514
  idFrontImage: idFrontImage,
1504
1515
  idBackImage: idBackImage,
1505
1516
  passportImage: passportImage,
1517
+ idBarcodeImage: idBarcodeImage,
1506
1518
  selfieImage: selfieImage
1507
1519
  };
1508
1520
  _a = signatureVideoUrl;
@@ -1608,6 +1620,9 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1608
1620
  if (documents.passportImage) {
1609
1621
  submissionRequest.customerData.idData.idImageFront = documents.passportImage;
1610
1622
  }
1623
+ if (documents.idBarcodeImage) {
1624
+ submissionRequest.customerData.idData.idBarcodeImage = documents.idBarcodeImage;
1625
+ }
1611
1626
  if (documents.idFrontIrImage) {
1612
1627
  submissionRequest.customerData.idData.idFrontIrImage = documents.idFrontIrImage;
1613
1628
  }
@@ -1696,7 +1711,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1696
1711
  }
1697
1712
  });
1698
1713
  });
1699
- }, [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, signatureVideoUrl, uploadDocument, verifyIdWithExternalDatabases, webhooksClientTraceId, webhooksEnabled, webhooksFireOnReview, webhooksFireOnReviewURL, webhooksSendInputImages, webhooksSendProcessedImages, webhooksStripSpecialCharacters, webhooksURL]);
1714
+ }, [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, signatureVideoUrl, uploadDocument, verifyIdWithExternalDatabases, webhooksClientTraceId, webhooksEnabled, webhooksFireOnReview, webhooksFireOnReviewURL, webhooksSendInputImages, webhooksSendProcessedImages, webhooksStripSpecialCharacters, webhooksURL]);
1700
1715
  var defaultOnSubmit = React.useCallback(function () {
1701
1716
  return __awaiter(void 0, void 0, void 0, function () {
1702
1717
  var submissionResponse_1, payload, host, endpoint, response, statusMessage, submissionResponse_2, e_1, err;
@@ -1974,6 +1989,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1974
1989
  idFrontUvImage: idFrontUvImage,
1975
1990
  idBackUvImage: idBackUvImage,
1976
1991
  passportImage: passportImage,
1992
+ idBarcodeImage: idBarcodeImage,
1977
1993
  selfieImage: selfieImage,
1978
1994
  signatureData: signatureData,
1979
1995
  signatureVideoUrl: signatureVideoUrl,
@@ -1990,6 +2006,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1990
2006
  setIdBackIrImage: setIdBackIrImage,
1991
2007
  setIdFrontUvImage: setIdFrontUvImage,
1992
2008
  setIdBackUvImage: setIdBackUvImage,
2009
+ setIdBarcodeImage: setIdBarcodeImage,
1993
2010
  setSelfieImage: setSelfieImage,
1994
2011
  setSignatureData: setSignatureData,
1995
2012
  setSignatureVideoUrl: setSignatureVideoUrl,
@@ -2008,7 +2025,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
2008
2025
  checkLiveness: checkLiveness,
2009
2026
  retryLocationAccess: retryLocationAccess
2010
2027
  };
2011
- }, [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]);
2028
+ }, [additionalDocuments, checkLiveness, environment, idBackImage, idBackIrImage, idBackUvImage, idCaptureVideoAudioStartsAt, idCaptureVideoAudioUrl, idCaptureVideoIdBackImage, idCaptureVideoIdFrontImage, idCaptureVideoUrl, idFrontImage, idFrontIrImage, idFrontUvImage, livenessCheckRequest, logIdBackCaptureAttempt, logIdFrontCaptureAttempt, logSelfieCaptureAttempt, idBarcodeImage, passportImage, retryLocationAccess, selfieImage, signatureData, signatureVideoUrl, submissionError, submissionRequest, submissionResponse, submissionStatus, submit, uploadDocument]);
2012
2029
  return /*#__PURE__*/React__namespace.default.createElement(SubmissionContext.Provider, {
2013
2030
  value: value
2014
2031
  }, geolocationRequired && geolocationBlocked ? ( /*#__PURE__*/React__namespace.default.createElement(GeolocationAccessDeniedOverlay, null)) : children, submissionError && ( /*#__PURE__*/React__namespace.default.createElement(SubmissionErrorOverlay, {
@@ -2202,97 +2219,6 @@ function preloadVisionRuntime() {
2202
2219
  });
2203
2220
  }
2204
2221
 
2205
- function getFrameDimensions(frame) {
2206
- var frameWidth = frame.width,
2207
- frameHeight = frame.height;
2208
- if (frame instanceof HTMLImageElement) {
2209
- frameWidth = frame.naturalWidth;
2210
- frameHeight = frame.naturalHeight;
2211
- }
2212
- if (frame instanceof HTMLVideoElement) {
2213
- frameWidth = frame.videoWidth;
2214
- frameHeight = frame.videoHeight;
2215
- }
2216
- return [frameWidth, frameHeight];
2217
- }
2218
-
2219
- var InvisibleCanvas = styled__default.default.canvas(templateObject_1$N || (templateObject_1$N = __makeTemplateObject(["\n display: none;\n"], ["\n display: none;\n"])));
2220
- function drawToCanvas(canvas, frame, width, height) {
2221
- if (!canvas) return;
2222
- var ctx = canvas.getContext('2d');
2223
- if (!ctx) return;
2224
- if (!width || !height) {
2225
- var _a = getFrameDimensions(frame),
2226
- frameWidth = _a[0],
2227
- frameHeight = _a[1];
2228
- width || (width = frameWidth);
2229
- height || (height = frameHeight);
2230
- }
2231
- canvas.width = width;
2232
- canvas.height = height;
2233
- ctx.drawImage(frame, 0, 0, width, height);
2234
- }
2235
- function clearCanvas(canvas) {
2236
- var _a;
2237
- (_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);
2238
- }
2239
- var templateObject_1$N;
2240
-
2241
- function cropToShoulders(rawCanvas, cropCanvas, resizeCanvas, frame, face, quality, maxHeight) {
2242
- var _a;
2243
- if (quality === void 0) {
2244
- quality = 0.92;
2245
- }
2246
- if (!rawCanvas || !cropCanvas || !resizeCanvas) return '';
2247
- var rawCtx = rawCanvas.getContext('2d');
2248
- var cropCtx = cropCanvas.getContext('2d');
2249
- var resizeCtx = resizeCanvas.getContext('2d');
2250
- if (!rawCtx || !cropCtx || !resizeCtx) throw new Error('could not get 2d context');
2251
- rawCanvas.width = frame.width;
2252
- rawCanvas.height = frame.height;
2253
- rawCtx.putImageData(frame, 0, 0);
2254
- if (frame.height > frame.width) {
2255
- cropCanvas.width = frame.width;
2256
- cropCanvas.height = frame.height;
2257
- cropCtx.drawImage(rawCanvas, 0, 0, cropCanvas.width, cropCanvas.height);
2258
- } else {
2259
- var _b = (_a = face === null || face === void 0 ? void 0 : face.box) !== null && _a !== void 0 ? _a : {
2260
- xMin: 0,
2261
- width: frame.width
2262
- },
2263
- xMin = _b.xMin,
2264
- width = _b.width;
2265
- var desiredWidth = frame.height * 0.6;
2266
- var faceCenterX = xMin + width / 2;
2267
- var xPos = Math.max(0, faceCenterX - desiredWidth / 2);
2268
- cropCanvas.width = desiredWidth;
2269
- cropCanvas.height = frame.height;
2270
- cropCtx.drawImage(rawCanvas, xPos, 0, cropCanvas.width, cropCanvas.height, 0, 0, cropCanvas.width, cropCanvas.height);
2271
- }
2272
- resizeCanvas.height = maxHeight !== null && maxHeight !== void 0 ? maxHeight : cropCanvas.height;
2273
- resizeCanvas.width = cropCanvas.width * (resizeCanvas.height / cropCanvas.height);
2274
- resizeCtx === null || resizeCtx === void 0 ? void 0 : resizeCtx.drawImage(cropCanvas, 0, 0, resizeCanvas.width, resizeCanvas.height);
2275
- var dataURL = resizeCanvas.toDataURL('image/jpeg', quality);
2276
- log('cropToShoulders size', new TextEncoder().encode(dataURL).length);
2277
- clearCanvas(rawCanvas);
2278
- clearCanvas(cropCanvas);
2279
- clearCanvas(resizeCanvas);
2280
- return dataURL;
2281
- }
2282
- function cropToDetectedObjectBox(frame, box, canvas) {
2283
- canvas || (canvas = document.createElement('canvas'));
2284
- var ctx = canvas.getContext('2d');
2285
- if (!ctx) throw new Error('could not get 2d context');
2286
- var xMin = box.xMin,
2287
- yMin = box.yMin,
2288
- width = box.width,
2289
- height = box.height;
2290
- canvas.width = width;
2291
- canvas.height = height;
2292
- ctx.drawImage(frame, xMin, yMin, width, height, 0, 0, width, height);
2293
- return canvas;
2294
- }
2295
-
2296
2222
  var defaultImageSegmenterModelPath = 'https://websdk-cdn-dev.idmission.com/assets/models/selfiesegmenter20240524/selfie_segmenter.tflite';
2297
2223
  var imageSegmenterModelSizeInBytes = 256440.32;
2298
2224
  // 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
@@ -2422,6 +2348,192 @@ function giveUpAfter(maxTime) {
2422
2348
  });
2423
2349
  }
2424
2350
 
2351
+ var DEFAULT_CDN_URL = 'https://websdk-cdn-dev.idmission.com/assets';
2352
+
2353
+ var defaultDocumentDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/DocumentDetector/DocumentDetector-20250815_115859.tflite");
2354
+
2355
+ var defaultFocusModelPath = "".concat(DEFAULT_CDN_URL, "/models/Focus/Focus-20241008_102708.tflite");
2356
+
2357
+ var defaultFaceDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/blazeface20240207/blaze_face_short_range.tflite");
2358
+
2359
+ var defaultBarcodeReadabilityModelPath = "".concat(DEFAULT_CDN_URL, "/models/BarcodeReadability/BarcodeReadability-20250815_120417.tflite");
2360
+
2361
+ var defaultModelPaths = {
2362
+ documentDetector: defaultDocumentDetectorModelPath,
2363
+ focus: defaultFocusModelPath,
2364
+ faceDetection: defaultFaceDetectorModelPath,
2365
+ barcodeReadability: defaultBarcodeReadabilityModelPath
2366
+ };
2367
+
2368
+ var preloadModels = function preloadModels(_a) {
2369
+ return __awaiter(void 0, [_a], void 0, function (_b) {
2370
+ var preloadTasks;
2371
+ var _c = _b.documentDetectionModel,
2372
+ documentDetectionModel = _c === void 0 ? true : _c,
2373
+ _d = _b.focusModel,
2374
+ focusModel = _d === void 0 ? true : _d,
2375
+ _e = _b.faceDetectionModel,
2376
+ faceDetectionModel = _e === void 0 ? true : _e,
2377
+ _f = _b.barcodeReadabilityModel,
2378
+ barcodeReadabilityModel = _f === void 0 ? true : _f;
2379
+ return __generator(this, function (_g) {
2380
+ switch (_g.label) {
2381
+ case 0:
2382
+ return [4 /*yield*/, probeModelCapabilities()];
2383
+ case 1:
2384
+ _g.sent();
2385
+ preloadTasks = [];
2386
+ if (documentDetectionModel) {
2387
+ preloadTasks.push(preloadDocumentDetectorDependencies);
2388
+ }
2389
+ if (focusModel) {
2390
+ preloadTasks.push(preloadFocusModelDependencies);
2391
+ }
2392
+ if (faceDetectionModel) {
2393
+ preloadTasks.push(preloadFaceDetectorDependencies);
2394
+ }
2395
+ if (barcodeReadabilityModel) {
2396
+ preloadTasks.push(preloadBarcodeReadabilityModelDependencies);
2397
+ }
2398
+ return [4 /*yield*/, Promise.all(preloadTasks)];
2399
+ case 2:
2400
+ _g.sent();
2401
+ return [2 /*return*/];
2402
+ }
2403
+ });
2404
+ });
2405
+ };
2406
+ var progressByUrl = {};
2407
+ var progressByUseCase = {
2408
+ visionRuntime: {
2409
+ loaded: 0,
2410
+ total: 0
2411
+ },
2412
+ documentDetector: {
2413
+ loaded: 0,
2414
+ total: 0
2415
+ },
2416
+ focus: {
2417
+ loaded: 0,
2418
+ total: 0
2419
+ },
2420
+ faceDetection: {
2421
+ loaded: 0,
2422
+ total: 0
2423
+ },
2424
+ barcodeReadability: {
2425
+ loaded: 0,
2426
+ total: 0
2427
+ }
2428
+ };
2429
+ function preloadDependency(url) {
2430
+ return __awaiter(this, void 0, void 0, function () {
2431
+ return __generator(this, function (_a) {
2432
+ return [2 /*return*/, new Promise(function (resolve, reject) {
2433
+ var req = new XMLHttpRequest();
2434
+ req.addEventListener('progress', function (event) {
2435
+ if (!event.lengthComputable) return;
2436
+ progressByUrl[url] = event;
2437
+ document.dispatchEvent(new CustomEvent('idmission.preloadProgress', {
2438
+ detail: {
2439
+ url: url,
2440
+ loaded: event.loaded,
2441
+ total: event.total
2442
+ }
2443
+ }));
2444
+ });
2445
+ req.addEventListener('loadend', function () {
2446
+ resolve(req.readyState === 4 && req.status === 200);
2447
+ });
2448
+ req.addEventListener('error', reject);
2449
+ req.open('GET', url, true);
2450
+ req.send();
2451
+ })];
2452
+ });
2453
+ });
2454
+ }
2455
+ var modelsPreloading = {
2456
+ documentDetector: false,
2457
+ focus: false,
2458
+ faceDetection: false,
2459
+ barcodeReadability: false
2460
+ };
2461
+ var preloadDocumentDetectorDependencies = function preloadDocumentDetectorDependencies() {
2462
+ return preloadModelDependencies('documentDetector');
2463
+ };
2464
+ var preloadFocusModelDependencies = function preloadFocusModelDependencies() {
2465
+ return preloadModelDependencies('focus');
2466
+ };
2467
+ var preloadFaceDetectorDependencies = function preloadFaceDetectorDependencies() {
2468
+ return preloadModelDependencies('faceDetection');
2469
+ };
2470
+ var preloadBarcodeReadabilityModelDependencies = function preloadBarcodeReadabilityModelDependencies() {
2471
+ return preloadModelDependencies('barcodeReadability');
2472
+ };
2473
+ function preloadModelDependencies(model) {
2474
+ return __awaiter(this, void 0, void 0, function () {
2475
+ function handleModelDownloadProgress(event) {
2476
+ var detail = event.detail;
2477
+ if (!dependencies.includes(detail.url)) return;
2478
+ progressByUseCase[model] = sumUpProgressForDependencies(dependencies);
2479
+ document.dispatchEvent(new CustomEvent("idmission.preloadProgress.".concat(model), {
2480
+ detail: progressByUseCase[model]
2481
+ }));
2482
+ }
2483
+ var dependencies;
2484
+ return __generator(this, function (_a) {
2485
+ switch (_a.label) {
2486
+ case 0:
2487
+ if (modelsPreloading[model]) return [2 /*return*/, new Promise(function (resolve) {
2488
+ var i = setInterval(function () {
2489
+ if (!modelsPreloading[model]) {
2490
+ clearInterval(i);
2491
+ resolve();
2492
+ }
2493
+ }, 100);
2494
+ })];
2495
+ modelsPreloading[model] = true;
2496
+ return [4 /*yield*/, probeModelCapabilities()];
2497
+ case 1:
2498
+ _a.sent();
2499
+ if (modelCapabilities.delegate === 'NONE') {
2500
+ throw new Error("No available delegate for ".concat(model, " model."));
2501
+ }
2502
+ dependencies = [defaultModelPaths[model]];
2503
+ document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
2504
+ _a.label = 2;
2505
+ case 2:
2506
+ _a.trys.push([2,, 4, 5]);
2507
+ return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
2508
+ case 3:
2509
+ _a.sent();
2510
+ return [3 /*break*/, 5];
2511
+ case 4:
2512
+ document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
2513
+ modelsPreloading[model] = false;
2514
+ return [7 /*endfinally*/];
2515
+ case 5:
2516
+ return [2 /*return*/];
2517
+ }
2518
+ });
2519
+ });
2520
+ }
2521
+ function progressToPercentage(progress) {
2522
+ return progress.total > 0 ? Math.round(100.0 * progress.loaded / progress.total) : 0;
2523
+ }
2524
+ function sumUpProgressForDependencies(dependencies) {
2525
+ return dependencies.reduce(function (result, dependency) {
2526
+ var dependencyProgress = progressByUrl[dependency];
2527
+ if (!dependencyProgress) return result;
2528
+ result.loaded += dependencyProgress.loaded;
2529
+ result.total += dependencyProgress.total;
2530
+ return result;
2531
+ }, {
2532
+ loaded: 0,
2533
+ total: 0
2534
+ });
2535
+ }
2536
+
2425
2537
  function convertBoundingBox(box) {
2426
2538
  var _a, _b, _c, _d, _e, _f, _g, _h;
2427
2539
  return {
@@ -2476,53 +2588,50 @@ function average(arr) {
2476
2588
  return sum / len;
2477
2589
  }
2478
2590
 
2479
- var DEFAULT_CDN_URL = 'https://websdk-cdn-dev.idmission.com/assets';
2480
-
2481
- var defaultDocumentDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/DocumentDetector/DocumentDetector-20250815_115859.tflite");
2482
-
2483
- var defaultFocusModelPath = "".concat(DEFAULT_CDN_URL, "/models/Focus/Focus-20241008_102708.tflite");
2484
-
2485
- var defaultFaceDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/blazeface20240207/blaze_face_short_range.tflite");
2486
-
2487
- var defaultFocusModelLoadTimeoutMs = 45000;
2488
- var defaultFocusThresholds = {
2489
- idCardFront: {
2490
- desktop: 0,
2491
- mobile: 0.3
2492
- },
2493
- idCardBack: {
2494
- desktop: 0,
2495
- mobile: 0.3
2496
- },
2497
- passport: {
2498
- desktop: 0,
2499
- mobile: 0.3
2500
- },
2501
- singlePage: {
2502
- desktop: 0,
2503
- mobile: 0.3
2591
+ var defaultDocumentDetectionScoreThreshold = 0.1;
2592
+ var defaultDocumentDetectionModelLoadTimeoutMs = 45000;
2593
+ var defaultDocumentDetectionThresholds = {
2594
+ idCardFront: 0.6,
2595
+ idCardBack: 0.6,
2596
+ passport: 0.4,
2597
+ singlePage: 0.4,
2598
+ stability: {
2599
+ idCardFront: 0.85,
2600
+ idCardBack: 0.85,
2601
+ passport: 0.5,
2602
+ singlePage: 0.5
2504
2603
  }
2505
2604
  };
2506
- var classifier = null;
2507
- var classifierSettings = null;
2508
- function loadFocusModel() {
2509
- return __awaiter(this, arguments, void 0, function (modelAssetPath) {
2605
+ var documentTypeDisplayNames = {
2606
+ idCardFront: 'ID card front',
2607
+ idCardBack: 'ID card back',
2608
+ passport: 'Passport',
2609
+ singlePage: 'Single page',
2610
+ none: 'None'
2611
+ };
2612
+ var detector$1 = null;
2613
+ var detectorSettings$1 = null;
2614
+ function loadDocumentDetector() {
2615
+ return __awaiter(this, arguments, void 0, function (modelAssetPath, scoreThreshold) {
2510
2616
  var _a, _b;
2511
2617
  if (modelAssetPath === void 0) {
2512
- modelAssetPath = defaultFocusModelPath;
2618
+ modelAssetPath = defaultDocumentDetectorModelPath;
2619
+ }
2620
+ if (scoreThreshold === void 0) {
2621
+ scoreThreshold = defaultDocumentDetectionScoreThreshold;
2513
2622
  }
2514
2623
  return __generator(this, function (_c) {
2515
2624
  switch (_c.label) {
2516
2625
  case 0:
2517
- if (classifier && (classifierSettings === null || classifierSettings === void 0 ? void 0 : classifierSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier];
2518
- closeFocusModel();
2519
- return [4 /*yield*/, preloadFocusModelDependencies()];
2626
+ 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];
2627
+ closeDocumentDetector();
2628
+ return [4 /*yield*/, preloadDocumentDetectorDependencies()];
2520
2629
  case 1:
2521
2630
  _c.sent();
2522
2631
  if (modelCapabilities.delegate === 'NONE') {
2523
- throw new Error('No available delegate for focus detector.');
2632
+ throw new Error('No available delegate for document detector.');
2524
2633
  }
2525
- _b = (_a = tasksVision.ImageClassifier).createFromOptions;
2634
+ _b = (_a = tasksVision.ObjectDetector).createFromOptions;
2526
2635
  return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
2527
2636
  case 2:
2528
2637
  return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
@@ -2531,44 +2640,48 @@ function loadFocusModel() {
2531
2640
  delegate: modelCapabilities.delegate
2532
2641
  },
2533
2642
  // canvas: document.createElement('canvas'),
2643
+ scoreThreshold: scoreThreshold,
2534
2644
  runningMode: 'VIDEO'
2535
2645
  }])];
2536
2646
  case 3:
2537
- classifier = _c.sent();
2538
- classifierSettings = {
2539
- modelAssetPath: modelAssetPath
2647
+ detector$1 = _c.sent();
2648
+ detectorSettings$1 = {
2649
+ modelAssetPath: modelAssetPath,
2650
+ scoreThreshold: scoreThreshold
2540
2651
  };
2541
- return [2 /*return*/, classifier];
2652
+ return [2 /*return*/, detector$1];
2542
2653
  }
2543
2654
  });
2544
2655
  });
2545
2656
  }
2546
- function closeFocusModel() {
2547
- classifier === null || classifier === void 0 ? void 0 : classifier.close();
2548
- classifier = null;
2549
- classifierSettings = null;
2657
+ function closeDocumentDetector() {
2658
+ detector$1 === null || detector$1 === void 0 ? void 0 : detector$1.close();
2659
+ detector$1 = null;
2660
+ detectorSettings$1 = null;
2550
2661
  }
2551
- function useLoadFocusModel(_a) {
2552
- var _b = _a.modelPath,
2553
- modelPath = _b === void 0 ? defaultFocusModelPath : _b,
2554
- _c = _a.modelLoadTimeoutMs,
2555
- modelLoadTimeoutMs = _c === void 0 ? defaultFocusModelLoadTimeoutMs : _c,
2662
+ function useLoadDocumentDetector(_a) {
2663
+ var _b = _a.shouldLoadModels,
2664
+ shouldLoadModels = _b === void 0 ? true : _b,
2665
+ _c = _a.modelPath,
2666
+ modelPath = _c === void 0 ? defaultDocumentDetectorModelPath : _c,
2667
+ _d = _a.modelLoadTimeoutMs,
2668
+ modelLoadTimeoutMs = _d === void 0 ? defaultDocumentDetectionModelLoadTimeoutMs : _d,
2669
+ _e = _a.scoreThreshold,
2670
+ scoreThreshold = _e === void 0 ? defaultDocumentDetectionScoreThreshold : _e,
2556
2671
  onModelError = _a.onModelError,
2557
- videoRef = _a.videoRef,
2558
- _d = _a.shouldLoadModels,
2559
- shouldLoadModels = _d === void 0 ? true : _d;
2560
- var _e = React.useState('not-started'),
2561
- modelLoadState = _e[0],
2562
- setModelLoadState = _e[1];
2563
- var _f = React.useState(0),
2564
- modelDownloadProgress = _f[0],
2565
- setModelDownloadProgress = _f[1];
2672
+ videoRef = _a.videoRef;
2673
+ var _f = React.useState('not-started'),
2674
+ modelLoadState = _f[0],
2675
+ setModelLoadState = _f[1];
2566
2676
  var _g = React.useState(null),
2567
2677
  modelWarmingStartedAt = _g[0],
2568
2678
  setModelWarmingStartedAt = _g[1];
2569
- var _h = React.useState(null),
2570
- modelError = _h[0],
2571
- setModelError = _h[1];
2679
+ var _h = React.useState(0),
2680
+ modelDownloadProgress = _h[0],
2681
+ setModelDownloadProgress = _h[1];
2682
+ var _j = React.useState(null),
2683
+ modelError = _j[0],
2684
+ setModelError = _j[1];
2572
2685
  React.useEffect(function loadModel() {
2573
2686
  var _this = this;
2574
2687
  if (!shouldLoadModels) return;
@@ -2577,21 +2690,24 @@ function useLoadFocusModel(_a) {
2577
2690
  function handleDownloadProgress(event) {
2578
2691
  setModelDownloadProgress(progressToPercentage(event.detail));
2579
2692
  }
2580
- document.addEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
2693
+ document.addEventListener('idmission.preloadProgress.documentDetector', handleDownloadProgress);
2581
2694
  var modelLoadTimeout = setTimeout(function () {
2582
2695
  setModelError(new Error('Model loading time limit exceeded.'));
2583
2696
  }, modelLoadTimeoutMs);
2584
2697
  var cancelVideoReady = function cancelVideoReady() {};
2585
- loadFocusModel(modelPath).then(function (loadedModel) {
2698
+ loadDocumentDetector(modelPath, scoreThreshold).then(function (model) {
2586
2699
  return __awaiter(_this, void 0, void 0, function () {
2587
2700
  var _a, videoReady, cancel, cancelled;
2588
2701
  return __generator(this, function (_b) {
2589
2702
  switch (_b.label) {
2590
2703
  case 0:
2591
2704
  setModelDownloadProgress(100);
2592
- clearTimeout(modelLoadTimeout);
2593
2705
  setModelLoadState('warming');
2594
- setModelWarmingStartedAt(new Date().getTime());
2706
+ setModelWarmingStartedAt(performance.now());
2707
+ clearTimeout(modelLoadTimeout);
2708
+ return [4 /*yield*/, testDocumentDetectionAgainstKnownImage(model)];
2709
+ case 1:
2710
+ _b.sent();
2595
2711
  _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
2596
2712
  cancelled = false;
2597
2713
  cancelVideoReady = function cancelVideoReady() {
@@ -2599,11 +2715,11 @@ function useLoadFocusModel(_a) {
2599
2715
  cancel();
2600
2716
  };
2601
2717
  return [4 /*yield*/, videoReady];
2602
- case 1:
2718
+ case 2:
2603
2719
  _b.sent();
2604
2720
  setTimeout(function () {
2605
2721
  if (cancelled) return;
2606
- loadedModel.classifyForVideo(videoRef.current, performance.now());
2722
+ model.detectForVideo(videoRef.current, performance.now());
2607
2723
  setModelLoadState('ready');
2608
2724
  }, 500);
2609
2725
  return [2 /*return*/];
@@ -2617,13 +2733,13 @@ function useLoadFocusModel(_a) {
2617
2733
  clearTimeout(modelLoadTimeout);
2618
2734
  });
2619
2735
  return function () {
2620
- log('unloading focus model');
2736
+ log('unloading document detection model');
2621
2737
  cancelVideoReady();
2622
- closeFocusModel();
2738
+ closeDocumentDetector();
2623
2739
  clearTimeout(modelLoadTimeout);
2624
- document.removeEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
2740
+ document.removeEventListener('idmission.preloadProgress.documentDetector', handleDownloadProgress);
2625
2741
  };
2626
- }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
2742
+ }, [shouldLoadModels, modelLoadTimeoutMs, modelPath, scoreThreshold, videoRef]);
2627
2743
  React.useEffect(function handleModelError() {
2628
2744
  if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
2629
2745
  }, [modelError, onModelError]);
@@ -2633,185 +2749,41 @@ function useLoadFocusModel(_a) {
2633
2749
  modelLoadState: modelLoadState,
2634
2750
  modelDownloadProgress: modelDownloadProgress,
2635
2751
  modelWarmingStartedAt: modelWarmingStartedAt,
2636
- modelError: modelError
2752
+ modelError: modelError,
2753
+ setModelError: setModelError
2637
2754
  };
2638
2755
  }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
2639
2756
  }
2640
- var lastFocusPredictionAt = 0;
2641
- var lastFocusPredictionTime = 0;
2642
- function setLastFocusPredictionAt(time) {
2643
- lastFocusPredictionTime = time - lastFocusPredictionAt;
2644
- lastFocusPredictionAt = time;
2645
- }
2646
- function makeFocusModelPrediction(imageData, cropCanvas, rotateCanvas, box) {
2647
- var _a, _b, _c, _d, _e;
2648
- if (!classifier) return null;
2649
- var startedAt = new Date();
2650
- var image = cropIfNecessary(imageData, cropCanvas, rotateCanvas, box);
2651
- var result = classifier.classifyForVideo(image, performance.now());
2652
- 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) {
2653
- return c.categoryName === 'focused';
2654
- })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
2655
- var predictionTime = new Date().getTime() - startedAt.getTime();
2656
- return {
2657
- score: score,
2658
- predictionTime: predictionTime
2659
- };
2660
- }
2661
- function cropIfNecessary(imageData, cropCanvas, rotateCanvas, box) {
2662
- if (!box) return imageData;
2663
- var cropped = cropToDetectedObjectBox(imageData, box, cropCanvas);
2664
- var _a = [box.width, box.height],
2665
- bw = _a[0],
2666
- bh = _a[1];
2667
- if (bh <= bw) return cropped;
2668
- var ctx = rotateCanvas.getContext('2d');
2669
- if (!ctx) return cropped;
2670
- rotateCanvas.width = bh;
2671
- rotateCanvas.height = bw;
2672
- ctx.clearRect(0, 0, rotateCanvas.width, rotateCanvas.height);
2673
- ctx.translate(rotateCanvas.width / 2, rotateCanvas.height / 2);
2674
- ctx.rotate(1.5708); // 90 deg in radians
2675
- ctx.drawImage(cropped, -bw / 2, -bh / 2);
2676
- return rotateCanvas;
2677
- }
2678
-
2679
- var defaultSelfieCaptureModelLoadTimeoutMs = 45000;
2680
- var detector$1 = null;
2681
- var detectorSettings$1 = null;
2682
- function loadFaceDetector() {
2683
- return __awaiter(this, arguments, void 0, function (modelAssetPath) {
2684
- var _a, _b;
2685
- if (modelAssetPath === void 0) {
2686
- modelAssetPath = defaultFaceDetectorModelPath;
2687
- }
2688
- return __generator(this, function (_c) {
2689
- switch (_c.label) {
2690
- case 0:
2691
- if (detector$1 && (detectorSettings$1 === null || detectorSettings$1 === void 0 ? void 0 : detectorSettings$1.modelAssetPath) === modelAssetPath) return [2 /*return*/, detector$1];
2692
- closeFaceDetector();
2693
- return [4 /*yield*/, preloadFaceDetectorDependencies()];
2694
- case 1:
2695
- _c.sent();
2696
- if (modelCapabilities.delegate === 'NONE') {
2697
- throw new Error('No available delegate for face detector.');
2698
- }
2699
- _b = (_a = tasksVision.FaceDetector).createFromOptions;
2700
- return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
2701
- case 2:
2702
- return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
2703
- // canvas: document.createElement('canvas'),
2704
- baseOptions: {
2705
- modelAssetPath: modelAssetPath,
2706
- delegate: modelCapabilities.delegate
2707
- },
2708
- runningMode: 'VIDEO'
2709
- }])];
2710
- case 3:
2711
- detector$1 = _c.sent();
2712
- detectorSettings$1 = {
2713
- modelAssetPath: modelAssetPath
2714
- };
2715
- return [2 /*return*/, detector$1];
2757
+ function makeDocumentDetectorPrediction(frame) {
2758
+ return __awaiter(this, void 0, void 0, function () {
2759
+ var startedAt, prediction, time, frameWidth, frameHeight;
2760
+ return __generator(this, function (_a) {
2761
+ if (!detector$1) return [2 /*return*/, null];
2762
+ startedAt = performance.now();
2763
+ // Detectors can throw errors, for example when using custom URLs that
2764
+ // contain a model that doesn't provide the expected output.
2765
+ try {
2766
+ prediction = detector$1.detectForVideo(frame, performance.now());
2767
+ time = performance.now() - startedAt;
2768
+ frameWidth = frame.width;
2769
+ frameHeight = frame.height;
2770
+ return [2 /*return*/, _assign(_assign({}, prediction), {
2771
+ time: time,
2772
+ frameWidth: frameWidth,
2773
+ frameHeight: frameHeight
2774
+ })];
2775
+ } catch (e) {
2776
+ error('caught object detection error', e);
2716
2777
  }
2778
+ return [2 /*return*/, null];
2717
2779
  });
2718
2780
  });
2719
2781
  }
2720
- function closeFaceDetector() {
2721
- detector$1 === null || detector$1 === void 0 ? void 0 : detector$1.close();
2722
- detector$1 = null;
2723
- detectorSettings$1 = null;
2724
- }
2725
- function useLoadFaceDetector(_a) {
2726
- var onModelError = _a.onModelError,
2727
- _b = _a.modelLoadTimeoutMs,
2728
- modelLoadTimeoutMs = _b === void 0 ? defaultSelfieCaptureModelLoadTimeoutMs : _b,
2729
- videoRef = _a.videoRef;
2730
- var _c = React.useState('not-started'),
2731
- modelLoadState = _c[0],
2732
- setModelLoadState = _c[1];
2733
- var _d = React.useState(0),
2734
- modelDownloadProgress = _d[0],
2735
- setModelDownloadProgress = _d[1];
2736
- var _e = React.useState(null),
2737
- modelWarmingStartedAt = _e[0],
2738
- setModelWarmingStartedAt = _e[1];
2739
- var _f = React.useState(null),
2740
- modelError = _f[0],
2741
- setModelError = _f[1];
2742
- React.useEffect(function loadModel() {
2743
- var _this = this;
2744
- setModelLoadState('downloading');
2745
- setModelWarmingStartedAt(null);
2746
- var modelLoadTimeout = setTimeout(function () {
2747
- setModelError(new Error('Model loading time limit exceeded.'));
2748
- }, modelLoadTimeoutMs);
2749
- function handleDownloadProgress(event) {
2750
- setModelDownloadProgress(progressToPercentage(event.detail));
2751
- }
2752
- document.addEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
2753
- var cancelVideoReady = function cancelVideoReady() {};
2754
- loadFaceDetector().then(function (model) {
2755
- return __awaiter(_this, void 0, void 0, function () {
2756
- var _a, videoReady, cancel, cancelled;
2757
- return __generator(this, function (_b) {
2758
- switch (_b.label) {
2759
- case 0:
2760
- setModelDownloadProgress(100);
2761
- clearTimeout(modelLoadTimeout);
2762
- setModelLoadState('warming');
2763
- setModelWarmingStartedAt(new Date().getTime());
2764
- return [4 /*yield*/, testFaceDetectionAgainstKnownImage(model)];
2765
- case 1:
2766
- _b.sent();
2767
- _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
2768
- cancelled = false;
2769
- cancelVideoReady = function cancelVideoReady() {
2770
- cancelled = true;
2771
- cancel();
2772
- };
2773
- return [4 /*yield*/, videoReady];
2774
- case 2:
2775
- _b.sent();
2776
- if (cancelled) return [2 /*return*/];
2777
- model.detectForVideo(videoRef.current, performance.now());
2778
- setModelLoadState('ready');
2779
- return [2 /*return*/];
2780
- }
2781
- });
2782
- });
2783
- })["catch"](function (e) {
2784
- setModelError(e);
2785
- setModelLoadState('error');
2786
- })["finally"](function () {
2787
- clearTimeout(modelLoadTimeout);
2788
- });
2789
- return function () {
2790
- log('unloading face detection model');
2791
- cancelVideoReady();
2792
- closeFaceDetector();
2793
- clearTimeout(modelLoadTimeout);
2794
- document.removeEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
2795
- };
2796
- }, [modelLoadTimeoutMs, videoRef]);
2797
- React.useEffect(function handleModelError() {
2798
- if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
2799
- }, [modelError, onModelError]);
2800
- return React.useMemo(function () {
2801
- return {
2802
- ready: modelLoadState === 'ready',
2803
- modelLoadState: modelLoadState,
2804
- modelDownloadProgress: modelDownloadProgress,
2805
- modelWarmingStartedAt: modelWarmingStartedAt,
2806
- modelError: modelError
2807
- };
2808
- }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
2809
- }
2810
- var lastFaceDetectionAt = 0;
2811
- var lastFaceDetectionTime = 0;
2812
- function setLastFaceDetectionAt(time) {
2813
- lastFaceDetectionTime = time - lastFaceDetectionAt;
2814
- lastFaceDetectionAt = time;
2782
+ var lastDetectionAt = 0;
2783
+ var lastDetectionTime = 0;
2784
+ function setLastDetectionAt(time) {
2785
+ lastDetectionTime = time - lastDetectionAt;
2786
+ lastDetectionAt = time;
2815
2787
  }
2816
2788
  var framesNeededSamples$1 = [];
2817
2789
  function trackFramesNeeded$1(value, bufferLength) {
@@ -2821,922 +2793,397 @@ function trackFramesNeeded$1(value, bufferLength) {
2821
2793
  framesNeededSamples$1.unshift(value);
2822
2794
  if (framesNeededSamples$1.length > bufferLength) framesNeededSamples$1.length = bufferLength;
2823
2795
  }
2824
- var lastNFaces = [];
2796
+ var lastNBoxes = [];
2825
2797
  var lastNPairs$1 = [];
2826
- function trackFace(face, framesNeeded) {
2798
+ function trackBox(box, framesNeeded) {
2827
2799
  if (framesNeeded === void 0) {
2828
2800
  framesNeeded = 12;
2829
2801
  }
2830
- lastNFaces.unshift(face);
2831
- if (lastNFaces.length > framesNeeded) lastNFaces.length = framesNeeded;
2832
- if (lastNFaces.length > 1) {
2833
- var lastFace = lastNFaces[1];
2834
- var iou = calculateIoU(face.box, lastFace.box);
2802
+ lastNBoxes.unshift(box);
2803
+ if (lastNBoxes.length > framesNeeded) lastNBoxes.length = framesNeeded;
2804
+ if (lastNBoxes.length > 1) {
2805
+ var lastBox = lastNBoxes[1];
2806
+ var iou = calculateIoU(box, lastBox);
2835
2807
  lastNPairs$1.unshift({
2836
- a: face,
2837
- b: lastFace,
2808
+ a: box,
2809
+ b: lastBox,
2838
2810
  iou: iou
2839
2811
  });
2840
2812
  if (lastNPairs$1.length > framesNeeded - 1) lastNPairs$1.length = framesNeeded - 1;
2841
2813
  }
2842
2814
  }
2843
- function makeFaceDetectorPrediction(imageData) {
2844
- if (!detector$1) return null;
2845
- var prediction = detector$1.detectForVideo(imageData, performance.now());
2846
- var faces = prediction.detections.map(function (d) {
2847
- return {
2848
- box: convertBoundingBox(d.boundingBox),
2849
- keypoints: d.keypoints.map(function (k) {
2850
- var _a;
2851
- return _assign(_assign({}, k), {
2852
- x: k.x * imageData.width,
2853
- y: k.y * imageData.height,
2854
- name: (_a = k.label) !== null && _a !== void 0 ? _a : ''
2855
- });
2856
- })
2857
- };
2815
+ var defaultDocumentDetectionBoundaries = {
2816
+ top: 20,
2817
+ bottom: 20,
2818
+ left: 20,
2819
+ right: 20
2820
+ };
2821
+ function processDocumentDetectorPrediction(prediction, thresholds, boundaries) {
2822
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
2823
+ if (boundaries === void 0) {
2824
+ boundaries = defaultDocumentDetectionBoundaries;
2825
+ }
2826
+ var detections = prediction.detections,
2827
+ frameWidth = prediction.frameWidth,
2828
+ frameHeight = prediction.frameHeight,
2829
+ time = prediction.time;
2830
+ var boundaryTop = (_a = boundaries.top) !== null && _a !== void 0 ? _a : 20;
2831
+ var boundaryLeft = (_b = boundaries.left) !== null && _b !== void 0 ? _b : 20;
2832
+ var boundaryRight = (_c = boundaries.right) !== null && _c !== void 0 ? _c : 20;
2833
+ var boundaryBottom = (_d = boundaries.bottom) !== null && _d !== void 0 ? _d : 20;
2834
+ var frameWidth80Pct = frameWidth * 0.8;
2835
+ var detectedObjects = applyNonMaxSuppression(detections.flatMap(function (d) {
2836
+ return d.categories.map(function (category) {
2837
+ return {
2838
+ label: category === null || category === void 0 ? void 0 : category.categoryName,
2839
+ score: category === null || category === void 0 ? void 0 : category.score,
2840
+ box: convertBoundingBox(d.boundingBox)
2841
+ };
2842
+ });
2843
+ }), function (obj) {
2844
+ var _a = obj.box,
2845
+ xMin = _a.xMin,
2846
+ yMin = _a.yMin,
2847
+ width = _a.width,
2848
+ height = _a.height;
2849
+ return yMin > boundaryTop &&
2850
+ // Is it valid top edge of ID detected?
2851
+ yMin + height + boundaryBottom < frameHeight && (
2852
+ // Is it valid bottom edge less than max video height
2853
+ xMin > boundaryLeft || xMin + width > frameWidth80Pct) &&
2854
+ // If either the left side visible or if not, right edge of ID should be more than 80% of width.
2855
+ xMin + width + boundaryRight < frameWidth // Valid right edge if it's less than video width.
2856
+ ;
2858
2857
  });
2859
- return _assign(_assign({}, prediction), {
2860
- faces: faces
2858
+ var allZero = detections.length > 0 && !detections.some(function (_a) {
2859
+ var boundingBox = _a.boundingBox;
2860
+ return Object.values(boundingBox !== null && boundingBox !== void 0 ? boundingBox : {}).some(function (n) {
2861
+ return n > 0;
2862
+ });
2861
2863
  });
2862
- }
2863
- function processFaceDetectorPrediction(_a) {
2864
- var faces = _a.faces,
2865
- videoWidth = _a.videoWidth,
2866
- videoHeight = _a.videoHeight,
2867
- _b = _a.requireVerticalFaceCentering,
2868
- requireVerticalFaceCentering = _b === void 0 ? true : _b,
2869
- _c = _a.stabilityThreshold,
2870
- stabilityThreshold = _c === void 0 ? 0.7 : _c;
2871
- var face = faces[0];
2872
- var faceNotDetected = faces.length === 0;
2873
- var faceNotCentered = false,
2874
- faceLookingAway = false,
2875
- faceTooClose = false,
2876
- faceTooFar = false;
2877
- if (face) {
2878
- // calculate centroids
2879
- var vCX = videoWidth / 2;
2880
- var vCY = videoHeight / 2;
2881
- var fCX = (face.box.xMin + face.box.xMax) / 2;
2882
- var fCY = (face.box.yMin + face.box.yMax) / 2;
2883
- // calculate thresholds
2884
- var vTX = videoWidth * 0.125;
2885
- var vTY = videoHeight * 0.125;
2886
- var fTW = face.box.width * 0.2;
2887
- var fTH = face.box.height * 0.2;
2888
- var nose = face.keypoints[2]; //.find((k) => k.name === 'noseTip')
2889
- if (nose) {
2890
- faceLookingAway = Math.abs(fCX - nose.x) > fTW || Math.abs(fCY - nose.y) > fTH;
2891
- var faceNotCenteredHorizontally = Math.abs(vCX - fCX) > vTX;
2892
- var faceNotCenteredVertically = Math.abs(vCY + 50 - fCY) > vTY;
2893
- faceNotCentered = faceNotCenteredHorizontally || requireVerticalFaceCentering && faceNotCenteredVertically;
2894
- }
2895
- var isMobile = videoWidth < videoHeight;
2896
- var tooCloseMultiple = 1.5;
2897
- var tooFarMultiple = isMobile ? 6 : 7;
2898
- faceTooClose = face.box.width > videoWidth / tooCloseMultiple;
2899
- faceTooFar = face.box.width < videoWidth / tooFarMultiple;
2864
+ var bestIdCardFront = detectedObjects.find(function (obj) {
2865
+ return obj.label === 'Document';
2866
+ });
2867
+ var bestIdCardBack = detectedObjects.find(function (obj) {
2868
+ return obj.label === 'Document back';
2869
+ });
2870
+ var bestPassportPage = detectedObjects.find(function (obj) {
2871
+ return obj.label === 'Passport page';
2872
+ });
2873
+ var bestSinglePage = detectedObjects.find(function (obj) {
2874
+ return obj.label === 'Single page';
2875
+ });
2876
+ var idCardFrontDetectionScore = (_e = bestIdCardFront === null || bestIdCardFront === void 0 ? void 0 : bestIdCardFront.score) !== null && _e !== void 0 ? _e : 0;
2877
+ var idCardBackDetectionScore = (_f = bestIdCardBack === null || bestIdCardBack === void 0 ? void 0 : bestIdCardBack.score) !== null && _f !== void 0 ? _f : 0;
2878
+ var passportDetectionScore = (_g = bestPassportPage === null || bestPassportPage === void 0 ? void 0 : bestPassportPage.score) !== null && _g !== void 0 ? _g : 0;
2879
+ var singlePageDetectionScore = (_h = bestSinglePage === null || bestSinglePage === void 0 ? void 0 : bestSinglePage.score) !== null && _h !== void 0 ? _h : 0;
2880
+ var idCardFrontDetectionThresholdMet = idCardFrontDetectionScore >= ((_j = thresholds.idCardFront) !== null && _j !== void 0 ? _j : 0);
2881
+ var idCardBackDetectionThresholdMet = idCardBackDetectionScore >= ((_k = thresholds.idCardBack) !== null && _k !== void 0 ? _k : 0);
2882
+ var passportDetectionThresholdMet = passportDetectionScore >= ((_l = thresholds.passport) !== null && _l !== void 0 ? _l : 0);
2883
+ var singlePageDetectionThresholdMet = singlePageDetectionScore >= ((_m = thresholds.singlePage) !== null && _m !== void 0 ? _m : 0);
2884
+ var bestDocument = singlePageDetectionThresholdMet ? bestSinglePage : passportDetectionThresholdMet ? bestPassportPage : idCardBackDetectionThresholdMet ? bestIdCardBack : bestIdCardFront;
2885
+ var detectionThreshold = singlePageDetectionThresholdMet ? thresholds.singlePage : passportDetectionThresholdMet ? thresholds.passport : idCardBackDetectionThresholdMet ? thresholds.idCardBack : thresholds.idCardFront;
2886
+ var detectionScore = (_o = bestDocument === null || bestDocument === void 0 ? void 0 : bestDocument.score) !== null && _o !== void 0 ? _o : 0;
2887
+ var detectionThresholdMet = detectionScore >= (detectionThreshold !== null && detectionThreshold !== void 0 ? detectionThreshold : 0);
2888
+ var detectedDocumentType = 'none';
2889
+ if (singlePageDetectionThresholdMet) {
2890
+ detectedDocumentType = 'singlePage';
2891
+ } else if (passportDetectionThresholdMet) {
2892
+ detectedDocumentType = 'passport';
2893
+ } else if (idCardBackDetectionThresholdMet) {
2894
+ detectedDocumentType = 'idCardBack';
2895
+ } else if (detectionThresholdMet) {
2896
+ detectedDocumentType = 'idCardFront';
2900
2897
  }
2901
- var faceInGuides = !faceNotDetected && !faceNotCentered && !faceLookingAway && !faceTooClose && !faceTooFar;
2902
- if (lastFaceDetectionTime > 0) {
2903
- trackFramesNeeded$1(500 / lastFaceDetectionTime);
2898
+ var documentInBounds = !!bestDocument;
2899
+ if (lastDetectionTime > 0) {
2900
+ trackFramesNeeded$1(1000 / lastDetectionTime);
2904
2901
  }
2905
- var faceIsStable = false;
2906
- if (faceInGuides) {
2907
- var framesNeeded = Math.ceil(average(framesNeededSamples$1));
2908
- trackFace(face, framesNeeded);
2909
- faceIsStable = lastNFaces.length >= framesNeeded && !lastNPairs$1.some(function (pair) {
2910
- return pair.iou < stabilityThreshold;
2902
+ var documentIsStable = false;
2903
+ var documentTooClose = false;
2904
+ if (bestDocument) {
2905
+ var _q = [bestDocument.box.width / frameWidth, bestDocument.box.height / frameHeight],
2906
+ docWidth = _q[0],
2907
+ docHeight = _q[1];
2908
+ documentTooClose = docWidth > 0.85 || docHeight > 0.85;
2909
+ if (detectionThresholdMet && documentInBounds && !documentTooClose) {
2910
+ var thresholdSet = (_p = thresholds.stability) !== null && _p !== void 0 ? _p : defaultDocumentDetectionThresholds.stability;
2911
+ var threshold_1 = thresholdSet[detectedDocumentType];
2912
+ var framesNeeded = Math.ceil(average(framesNeededSamples$1));
2913
+ trackBox(bestDocument.box, framesNeeded);
2914
+ documentIsStable = lastNBoxes.length >= framesNeeded && !lastNPairs$1.some(function (pair) {
2915
+ return pair.iou < threshold_1;
2916
+ });
2917
+ }
2918
+ }
2919
+ var bestPDF417;
2920
+ if (detectedObjects.length > 0) {
2921
+ bestPDF417 = detectedObjects.find(function (obj) {
2922
+ return obj.label === 'PDF417';
2911
2923
  });
2912
2924
  }
2913
- var faceReady = faceInGuides && faceIsStable;
2914
2925
  return {
2915
- face: face,
2916
- faceNotDetected: faceNotDetected,
2917
- faceNotCentered: faceNotCentered,
2918
- faceLookingAway: faceLookingAway,
2919
- faceTooClose: faceTooClose,
2920
- faceTooFar: faceTooFar,
2921
- faceReady: faceReady,
2922
- faceReadyAt: faceReady ? new Date() : null,
2923
- faceIsStable: faceIsStable
2924
- };
2925
- }
2926
- function testFaceDetectionAgainstKnownImage(detector) {
2927
- return new Promise(function (resolve, reject) {
2928
- var img = new Image();
2929
- img.crossOrigin = 'anonymous';
2930
- img.onload = function () {
2931
- var prediction = detector.detectForVideo(img, performance.now());
2932
- if (prediction.detections.length > 0) {
2933
- debug('face detection test result', prediction.detections);
2934
- resolve(void 0);
2935
- } else {
2936
- warn('face detection test failed');
2937
- reject(new Error('testFaceDetectionAgainstKnownImage failed to predict'));
2938
- }
2939
- };
2940
- img.onerror = function () {
2941
- return reject(new Error('testFaceDetectionAgainstKnownImage failed to load image'));
2942
- };
2943
- img.src = "".concat(DEFAULT_CDN_URL, "/head-test.jpg");
2926
+ prediction: prediction,
2927
+ detectedObjects: detectedObjects,
2928
+ detectionScore: detectionScore,
2929
+ detectionTime: time,
2930
+ detectionThresholdMet: detectionThresholdMet,
2931
+ detectedDocumentType: detectedDocumentType,
2932
+ idCardFrontDetectionScore: idCardFrontDetectionScore,
2933
+ idCardFrontDetectionThresholdMet: idCardFrontDetectionThresholdMet,
2934
+ idCardBackDetectionScore: idCardBackDetectionScore,
2935
+ idCardBackDetectionThresholdMet: idCardBackDetectionThresholdMet,
2936
+ passportDetectionScore: passportDetectionScore,
2937
+ passportDetectionThresholdMet: passportDetectionThresholdMet,
2938
+ singlePageDetectionScore: singlePageDetectionScore,
2939
+ singlePageDetectionThresholdMet: singlePageDetectionThresholdMet,
2940
+ bestDocument: bestDocument,
2941
+ bestPDF417: bestPDF417,
2942
+ documentInBounds: documentInBounds,
2943
+ documentTooClose: documentTooClose,
2944
+ documentIsStable: documentIsStable,
2945
+ frameWidth: frameWidth,
2946
+ frameHeight: frameHeight,
2947
+ allZero: allZero
2948
+ };
2949
+ }
2950
+ function applyNonMaxSuppression(detectedObjects, isGoodBox) {
2951
+ var maxes = {};
2952
+ detectedObjects.forEach(function (obj, i) {
2953
+ if (obj) {
2954
+ if (!maxes[obj.label]) maxes[obj.label] = [0, -1];
2955
+ if (obj.score > maxes[obj.label][0] && (isGoodBox === null || isGoodBox === void 0 ? void 0 : isGoodBox(obj))) maxes[obj.label] = [obj.score, i];
2956
+ }
2957
+ });
2958
+ return Object.keys(maxes).map(function (label) {
2959
+ return detectedObjects[maxes[label][1]];
2960
+ }).filter(function (obj) {
2961
+ return !!obj;
2944
2962
  });
2945
2963
  }
2946
-
2947
- var preloadModels = function preloadModels(_a) {
2948
- return __awaiter(void 0, [_a], void 0, function (_b) {
2949
- var preloadTasks;
2950
- var _c = _b.documentDetectionModel,
2951
- documentDetectionModel = _c === void 0 ? true : _c,
2952
- _d = _b.focusModel,
2953
- focusModel = _d === void 0 ? true : _d,
2954
- _e = _b.faceDetectionModel,
2955
- faceDetectionModel = _e === void 0 ? true : _e;
2956
- return __generator(this, function (_f) {
2957
- switch (_f.label) {
2958
- case 0:
2959
- return [4 /*yield*/, probeModelCapabilities()];
2960
- case 1:
2961
- _f.sent();
2962
- preloadTasks = [];
2963
- if (documentDetectionModel) {
2964
- preloadTasks.push(preloadDocumentDetectorDependencies);
2965
- }
2966
- if (focusModel) {
2967
- preloadTasks.push(preloadFocusModelDependencies);
2968
- }
2969
- if (faceDetectionModel) {
2970
- preloadTasks.push(preloadFaceDetectorDependencies);
2971
- }
2972
- return [4 /*yield*/, Promise.all(preloadTasks)];
2973
- case 2:
2974
- _f.sent();
2975
- return [2 /*return*/];
2964
+ function testDocumentDetectionAgainstKnownImage(detector) {
2965
+ return new Promise(function (resolve, reject) {
2966
+ var img = new Image();
2967
+ img.crossOrigin = 'anonymous';
2968
+ img.onload = function () {
2969
+ var prediction = detector.detectForVideo(img, performance.now());
2970
+ if (prediction.detections.length > 0) {
2971
+ debug('document detection test result', prediction.detections);
2972
+ resolve(void 0);
2973
+ } else {
2974
+ warn('document detection test failed');
2975
+ reject(new Error('testDocumentDetectionAgainstKnownImage failed to predict'));
2976
2976
  }
2977
- });
2977
+ };
2978
+ img.onerror = function () {
2979
+ return reject(new Error('testDocumentDetectionAgainstKnownImage failed to load image'));
2980
+ };
2981
+ img.src = "".concat(DEFAULT_CDN_URL, "/id-card-test.jpg");
2978
2982
  });
2979
- };
2980
- var progressByUrl = {};
2981
- var progressByUseCase = {
2982
- visionRuntime: {
2983
- loaded: 0,
2984
- total: 0
2985
- },
2986
- documentDetection: {
2987
- loaded: 0,
2988
- total: 0
2989
- },
2990
- focus: {
2991
- loaded: 0,
2992
- total: 0
2993
- },
2994
- faceDetection: {
2995
- loaded: 0,
2996
- total: 0
2983
+ }
2984
+
2985
+ function getFrameDimensions(frame) {
2986
+ var frameWidth = frame.width,
2987
+ frameHeight = frame.height;
2988
+ if (frame instanceof HTMLImageElement) {
2989
+ frameWidth = frame.naturalWidth;
2990
+ frameHeight = frame.naturalHeight;
2997
2991
  }
2998
- };
2999
- function preloadDependency(url) {
3000
- return __awaiter(this, void 0, void 0, function () {
3001
- return __generator(this, function (_a) {
3002
- return [2 /*return*/, new Promise(function (resolve, reject) {
3003
- var req = new XMLHttpRequest();
3004
- req.addEventListener('progress', function (event) {
3005
- if (!event.lengthComputable) return;
3006
- progressByUrl[url] = event;
3007
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress', {
3008
- detail: {
3009
- url: url,
3010
- loaded: event.loaded,
3011
- total: event.total
3012
- }
3013
- }));
3014
- });
3015
- req.addEventListener('loadend', function () {
3016
- resolve(req.readyState === 4 && req.status === 200);
2992
+ if (frame instanceof HTMLVideoElement) {
2993
+ frameWidth = frame.videoWidth;
2994
+ frameHeight = frame.videoHeight;
2995
+ }
2996
+ return [frameWidth, frameHeight];
2997
+ }
2998
+
2999
+ var InvisibleCanvasContainer = 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 display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\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"])));
3000
+ var InvisibleCanvas = styled__default.default.canvas(templateObject_2$G || (templateObject_2$G = __makeTemplateObject(["\n display: none;\n"], ["\n display: none;\n"])));
3001
+ function drawToCanvas(canvas, frame, width, height) {
3002
+ if (!canvas) return;
3003
+ var ctx = canvas.getContext('2d');
3004
+ if (!ctx) return;
3005
+ if (!width || !height) {
3006
+ var _a = getFrameDimensions(frame),
3007
+ frameWidth = _a[0],
3008
+ frameHeight = _a[1];
3009
+ width || (width = frameWidth);
3010
+ height || (height = frameHeight);
3011
+ }
3012
+ canvas.width = width;
3013
+ canvas.height = height;
3014
+ ctx.drawImage(frame, 0, 0, width, height);
3015
+ }
3016
+ function clearCanvas(canvas) {
3017
+ var _a;
3018
+ (_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);
3019
+ }
3020
+ var templateObject_1$N, templateObject_2$G;
3021
+
3022
+ function useFrameLoop(fn, options) {
3023
+ if (options === void 0) {
3024
+ options = {};
3025
+ }
3026
+ var _a = React.useState(false),
3027
+ running = _a[0],
3028
+ setRunning = _a[1];
3029
+ var startedAtRef = React.useRef(null);
3030
+ var loopId = React.useRef(0);
3031
+ var frameId = React.useRef(0);
3032
+ React.useEffect(function runFrameLoop() {
3033
+ if (!running) return;
3034
+ var timer;
3035
+ var currentLoopId = loopId.current;
3036
+ function hotLoop() {
3037
+ return __awaiter(this, void 0, void 0, function () {
3038
+ var start, timeRunning, took, amountToThrottle;
3039
+ var _a, _b, _c;
3040
+ return __generator(this, function (_d) {
3041
+ switch (_d.label) {
3042
+ case 0:
3043
+ if (currentLoopId !== loopId.current) return [2 /*return*/];
3044
+ start = new Date().getTime();
3045
+ timeRunning = start - ((_b = (_a = startedAtRef.current) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : 0);
3046
+ return [4 /*yield*/, fn(frameId.current, timeRunning)];
3047
+ case 1:
3048
+ _d.sent();
3049
+ took = new Date().getTime() - start;
3050
+ amountToThrottle = Math.max(((_c = options.throttleMs) !== null && _c !== void 0 ? _c : 0) - took, 0);
3051
+ timer = setTimeout(function () {
3052
+ frameId.current = requestAnimationFrame(hotLoop);
3053
+ }, amountToThrottle);
3054
+ return [2 /*return*/];
3055
+ }
3017
3056
  });
3018
- req.addEventListener('error', reject);
3019
- req.open('GET', url, true);
3020
- req.send();
3021
- })];
3022
- });
3023
- });
3057
+ });
3058
+ }
3059
+ void hotLoop();
3060
+ return function () {
3061
+ loopId.current += 1;
3062
+ if (frameId.current) cancelAnimationFrame(frameId.current);
3063
+ if (timer) clearTimeout(timer);
3064
+ };
3065
+ }, [fn, running, options.throttleMs]);
3066
+ var start = React.useCallback(function () {
3067
+ startedAtRef.current = new Date();
3068
+ setRunning(true);
3069
+ }, []);
3070
+ var stop = React.useCallback(function () {
3071
+ loopId.current += 1; // force the loop to stop immediately.
3072
+ setRunning(false);
3073
+ startedAtRef.current = null;
3074
+ }, []);
3075
+ React.useEffect(function startAutomatically() {
3076
+ if (options.autoStart) start();
3077
+ return stop;
3078
+ }, [options.autoStart, start, stop]);
3079
+ return {
3080
+ start: start,
3081
+ stop: stop
3082
+ };
3024
3083
  }
3025
- var documentDetectorPreloading = false,
3026
- focusModelPreloading = false,
3027
- faceDetectorPreloading = false;
3028
- function preloadDocumentDetectorDependencies() {
3029
- return __awaiter(this, void 0, void 0, function () {
3030
- function handleDownloadProgress(event) {
3031
- var detail = event.detail;
3032
- if (!dependencies.includes(detail.url)) return;
3033
- progressByUseCase.documentDetection = sumUpProgressForDependencies(dependencies);
3034
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.documentDetection', {
3035
- detail: progressByUseCase.documentDetection
3036
- }));
3084
+
3085
+ function listAvailableCameras(facingMode_1) {
3086
+ return __awaiter(this, arguments, void 0, function (facingMode, requestMicAccess) {
3087
+ var cameraEnumerationStream, allDevices, allowedVideoDevices;
3088
+ if (requestMicAccess === void 0) {
3089
+ requestMicAccess = false;
3037
3090
  }
3038
- var dependencies;
3039
3091
  return __generator(this, function (_a) {
3040
3092
  switch (_a.label) {
3041
3093
  case 0:
3042
- if (documentDetectorPreloading) return [2 /*return*/, new Promise(function (resolve) {
3043
- var i = setInterval(function () {
3044
- if (!documentDetectorPreloading) {
3045
- clearInterval(i);
3046
- resolve();
3094
+ return [4 /*yield*/, navigator.mediaDevices.getUserMedia({
3095
+ video: {
3096
+ facingMode: {
3097
+ exact: facingMode
3047
3098
  }
3048
- }, 100);
3049
- })];
3050
- documentDetectorPreloading = true;
3051
- return [4 /*yield*/, probeModelCapabilities()];
3099
+ },
3100
+ audio: requestMicAccess
3101
+ })
3102
+ // This lists all available cameras attached to the user's device.
3103
+ ];
3052
3104
  case 1:
3053
- _a.sent();
3054
- if (modelCapabilities.delegate === 'NONE') {
3055
- throw new Error('No available delegate for document detector.');
3056
- }
3057
- dependencies = [defaultDocumentDetectorModelPath];
3058
- document.addEventListener('idmission.preloadProgress', handleDownloadProgress);
3059
- _a.label = 2;
3105
+ cameraEnumerationStream = _a.sent();
3106
+ return [4 /*yield*/, navigator.mediaDevices.enumerateDevices()];
3060
3107
  case 2:
3061
- _a.trys.push([2,, 4, 5]);
3062
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
3063
- case 3:
3064
- _a.sent();
3065
- return [3 /*break*/, 5];
3066
- case 4:
3067
- document.removeEventListener('idmission.preloadProgress', handleDownloadProgress);
3068
- documentDetectorPreloading = false;
3069
- return [7 /*endfinally*/];
3070
- case 5:
3071
- return [2 /*return*/];
3072
- }
3073
- });
3074
- });
3075
- }
3076
- function preloadFocusModelDependencies() {
3077
- return __awaiter(this, void 0, void 0, function () {
3078
- function handleModelDownloadProgress(event) {
3079
- var detail = event.detail;
3080
- if (!dependencies.includes(detail.url)) return;
3081
- progressByUseCase.focus = sumUpProgressForDependencies(dependencies);
3082
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.focus', {
3083
- detail: progressByUseCase.focus
3084
- }));
3085
- }
3086
- var dependencies;
3087
- return __generator(this, function (_a) {
3088
- switch (_a.label) {
3089
- case 0:
3090
- if (focusModelPreloading) return [2 /*return*/, new Promise(function (resolve) {
3091
- var i = setInterval(function () {
3092
- if (!focusModelPreloading) {
3093
- clearInterval(i);
3094
- resolve();
3095
- }
3096
- }, 100);
3097
- })];
3098
- focusModelPreloading = true;
3099
- return [4 /*yield*/, probeModelCapabilities()];
3100
- case 1:
3101
- _a.sent();
3102
- if (modelCapabilities.delegate === 'NONE') {
3103
- throw new Error('No available delegate for document detector.');
3104
- }
3105
- dependencies = [defaultFocusModelPath];
3106
- document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3107
- _a.label = 2;
3108
- case 2:
3109
- _a.trys.push([2,, 4, 5]);
3110
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
3111
- case 3:
3112
- _a.sent();
3113
- return [3 /*break*/, 5];
3114
- case 4:
3115
- document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3116
- focusModelPreloading = false;
3117
- return [7 /*endfinally*/];
3118
- case 5:
3119
- return [2 /*return*/];
3120
- }
3121
- });
3122
- });
3123
- }
3124
- function preloadFaceDetectorDependencies() {
3125
- return __awaiter(this, void 0, void 0, function () {
3126
- function handleModelDownloadProgress(event) {
3127
- var detail = event.detail;
3128
- if (!dependencies.includes(detail.url)) return;
3129
- progressByUseCase.faceDetection = sumUpProgressForDependencies(dependencies);
3130
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.faceDetection', {
3131
- detail: progressByUseCase.faceDetection
3132
- }));
3133
- }
3134
- var dependencies;
3135
- return __generator(this, function (_a) {
3136
- switch (_a.label) {
3137
- case 0:
3138
- if (faceDetectorPreloading) return [2 /*return*/, new Promise(function (resolve) {
3139
- var i = setInterval(function () {
3140
- if (!faceDetectorPreloading) {
3141
- clearInterval(i);
3142
- resolve();
3143
- }
3144
- }, 100);
3145
- })];
3146
- faceDetectorPreloading = true;
3147
- return [4 /*yield*/, probeModelCapabilities()];
3148
- case 1:
3149
- _a.sent();
3150
- if (modelCapabilities.delegate === 'NONE') {
3151
- throw new Error('No available delegate for document detector.');
3152
- }
3153
- dependencies = [defaultFaceDetectorModelPath];
3154
- document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3155
- _a.label = 2;
3156
- case 2:
3157
- _a.trys.push([2,, 4, 5]);
3158
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
3159
- case 3:
3160
- _a.sent();
3161
- return [3 /*break*/, 5];
3162
- case 4:
3163
- document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3164
- faceDetectorPreloading = false;
3165
- return [7 /*endfinally*/];
3166
- case 5:
3167
- return [2 /*return*/];
3108
+ allDevices = _a.sent();
3109
+ allowedVideoDevices = allDevices.filter(function (_a) {
3110
+ var kind = _a.kind,
3111
+ label = _a.label;
3112
+ return kind === 'videoinput' && !label.toLowerCase().includes('virtual');
3113
+ });
3114
+ // Release the access to the user's camera that we obtained for enumeration purposes.
3115
+ cameraEnumerationStream.getVideoTracks().forEach(function (track) {
3116
+ track.enabled = false;
3117
+ track.stop();
3118
+ });
3119
+ cameraEnumerationStream = null;
3120
+ return [2 /*return*/, allowedVideoDevices];
3168
3121
  }
3169
3122
  });
3170
3123
  });
3171
3124
  }
3172
- function progressToPercentage(progress) {
3173
- return progress.total > 0 ? Math.round(100.0 * progress.loaded / progress.total) : 0;
3174
- }
3175
- function sumUpProgressForDependencies(dependencies) {
3176
- return dependencies.reduce(function (result, dependency) {
3177
- var dependencyProgress = progressByUrl[dependency];
3178
- if (!dependencyProgress) return result;
3179
- result.loaded += dependencyProgress.loaded;
3180
- result.total += dependencyProgress.total;
3181
- return result;
3182
- }, {
3183
- loaded: 0,
3184
- total: 0
3125
+ 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) {
3126
+ return s.toLocaleLowerCase().split(' ').join('');
3127
+ });
3128
+ 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) {
3129
+ return s.toLocaleLowerCase().split(' ').join('');
3130
+ });
3131
+ 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) {
3132
+ return s.toLocaleLowerCase().split(' ').join('');
3133
+ });
3134
+ var cameraLabelMatches = function cameraLabelMatches(labelOrDevice, labelSetOrLabel) {
3135
+ var label = labelOrDevice instanceof MediaDeviceInfo ? getDeviceLabel(labelOrDevice) : labelOrDevice;
3136
+ var labelSet = typeof labelSetOrLabel === 'string' ? [labelSetOrLabel] : labelSetOrLabel;
3137
+ return labelSet.some(function (l) {
3138
+ return label.includes(l);
3185
3139
  });
3186
- }
3187
-
3188
- var defaultDocumentDetectionScoreThreshold = 0.1;
3189
- var defaultDocumentDetectionModelLoadTimeoutMs = 45000;
3190
- var defaultDocumentDetectionThresholds = {
3191
- idCardFront: 0.6,
3192
- idCardBack: 0.6,
3193
- passport: 0.4,
3194
- singlePage: 0.4,
3195
- stability: {
3196
- idCardFront: 0.85,
3197
- idCardBack: 0.85,
3198
- passport: 0.5,
3199
- singlePage: 0.5
3200
- }
3201
3140
  };
3202
- var documentTypeDisplayNames = {
3203
- idCardFront: 'ID card front',
3204
- idCardBack: 'ID card back',
3205
- passport: 'Passport',
3206
- singlePage: 'Single page',
3207
- none: 'None'
3141
+ var getDeviceLabel = function getDeviceLabel(deviceInfo) {
3142
+ return deviceInfo.label.toLocaleLowerCase().split(' ').join('');
3208
3143
  };
3209
- var detector = null;
3210
- var detectorSettings = null;
3211
- function loadDocumentDetector() {
3212
- return __awaiter(this, arguments, void 0, function (modelAssetPath, scoreThreshold) {
3213
- var _a, _b;
3214
- if (modelAssetPath === void 0) {
3215
- modelAssetPath = defaultDocumentDetectorModelPath;
3216
- }
3217
- if (scoreThreshold === void 0) {
3218
- scoreThreshold = defaultDocumentDetectionScoreThreshold;
3219
- }
3220
- return __generator(this, function (_c) {
3221
- switch (_c.label) {
3222
- case 0:
3223
- 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];
3224
- closeDocumentDetector();
3225
- return [4 /*yield*/, preloadDocumentDetectorDependencies()];
3226
- case 1:
3227
- _c.sent();
3228
- if (modelCapabilities.delegate === 'NONE') {
3229
- throw new Error('No available delegate for document detector.');
3230
- }
3231
- _b = (_a = tasksVision.ObjectDetector).createFromOptions;
3232
- return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
3233
- case 2:
3234
- return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
3235
- baseOptions: {
3236
- modelAssetPath: modelAssetPath,
3237
- delegate: modelCapabilities.delegate
3238
- },
3239
- // canvas: document.createElement('canvas'),
3240
- scoreThreshold: scoreThreshold,
3241
- runningMode: 'VIDEO'
3242
- }])];
3243
- case 3:
3244
- detector = _c.sent();
3245
- detectorSettings = {
3246
- modelAssetPath: modelAssetPath,
3247
- scoreThreshold: scoreThreshold
3248
- };
3249
- return [2 /*return*/, detector];
3250
- }
3144
+ var currentCamera;
3145
+ function obtainCameraAccess(stream, deviceLabel, video) {
3146
+ releaseCameraAccess();
3147
+ log('obtaining camera access...');
3148
+ var _a = stream.getVideoTracks()[0].getSettings(),
3149
+ width = _a.width,
3150
+ height = _a.height;
3151
+ log('camera dimensions', width, height);
3152
+ var label = deviceLabel.toLocaleLowerCase().split(' ').join('');
3153
+ log('camera label', label);
3154
+ var isRearFacing = cameraLabelMatches(label, __spreadArray(__spreadArray(__spreadArray([], rearCameraLabels, true), backUltraWideCameraLabels, true), ['iphone'], false));
3155
+ log('is rear facing?', isRearFacing);
3156
+ var release = function release() {
3157
+ stream.getTracks().forEach(function (track) {
3158
+ track.enabled = false;
3159
+ track.stop();
3251
3160
  });
3252
- });
3161
+ if (video) {
3162
+ video.pause();
3163
+ video.srcObject = null;
3164
+ video.src = '';
3165
+ }
3166
+ };
3167
+ width || (width = 0);
3168
+ height || (height = 0);
3169
+ currentCamera = {
3170
+ label: deviceLabel,
3171
+ stream: stream,
3172
+ width: width,
3173
+ height: height,
3174
+ isRearFacing: isRearFacing,
3175
+ release: release
3176
+ };
3177
+ log('camera access granted');
3178
+ // if (video) video.srcObject = stream
3179
+ // log('video source initialized')
3180
+ return currentCamera;
3253
3181
  }
3254
- function closeDocumentDetector() {
3255
- detector === null || detector === void 0 ? void 0 : detector.close();
3256
- detector = null;
3257
- detectorSettings = null;
3258
- }
3259
- function useLoadDocumentDetector(_a) {
3260
- var _b = _a.shouldLoadModels,
3261
- shouldLoadModels = _b === void 0 ? true : _b,
3262
- _c = _a.modelPath,
3263
- modelPath = _c === void 0 ? defaultDocumentDetectorModelPath : _c,
3264
- _d = _a.modelLoadTimeoutMs,
3265
- modelLoadTimeoutMs = _d === void 0 ? defaultDocumentDetectionModelLoadTimeoutMs : _d,
3266
- _e = _a.scoreThreshold,
3267
- scoreThreshold = _e === void 0 ? defaultDocumentDetectionScoreThreshold : _e,
3268
- onModelError = _a.onModelError,
3269
- videoRef = _a.videoRef;
3270
- var _f = React.useState('not-started'),
3271
- modelLoadState = _f[0],
3272
- setModelLoadState = _f[1];
3273
- var _g = React.useState(null),
3274
- modelWarmingStartedAt = _g[0],
3275
- setModelWarmingStartedAt = _g[1];
3276
- var _h = React.useState(0),
3277
- modelDownloadProgress = _h[0],
3278
- setModelDownloadProgress = _h[1];
3279
- var _j = React.useState(null),
3280
- modelError = _j[0],
3281
- setModelError = _j[1];
3282
- React.useEffect(function loadModel() {
3283
- var _this = this;
3284
- if (!shouldLoadModels) return;
3285
- setModelLoadState('downloading');
3286
- setModelWarmingStartedAt(null);
3287
- function handleDownloadProgress(event) {
3288
- setModelDownloadProgress(progressToPercentage(event.detail));
3289
- }
3290
- document.addEventListener('idmission.preloadProgress.documentDetection', handleDownloadProgress);
3291
- var modelLoadTimeout = setTimeout(function () {
3292
- setModelError(new Error('Model loading time limit exceeded.'));
3293
- }, modelLoadTimeoutMs);
3294
- var cancelVideoReady = function cancelVideoReady() {};
3295
- loadDocumentDetector(modelPath, scoreThreshold).then(function (model) {
3296
- return __awaiter(_this, void 0, void 0, function () {
3297
- var _a, videoReady, cancel, cancelled;
3298
- return __generator(this, function (_b) {
3299
- switch (_b.label) {
3300
- case 0:
3301
- setModelDownloadProgress(100);
3302
- setModelLoadState('warming');
3303
- setModelWarmingStartedAt(new Date().getTime());
3304
- clearTimeout(modelLoadTimeout);
3305
- return [4 /*yield*/, testDocumentDetectionAgainstKnownImage(model)];
3306
- case 1:
3307
- _b.sent();
3308
- _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
3309
- cancelled = false;
3310
- cancelVideoReady = function cancelVideoReady() {
3311
- cancelled = true;
3312
- cancel();
3313
- };
3314
- return [4 /*yield*/, videoReady];
3315
- case 2:
3316
- _b.sent();
3317
- setTimeout(function () {
3318
- if (cancelled) return;
3319
- model.detectForVideo(videoRef.current, performance.now());
3320
- setModelLoadState('ready');
3321
- }, 500);
3322
- return [2 /*return*/];
3323
- }
3324
- });
3325
- });
3326
- })["catch"](function (e) {
3327
- setModelError(e);
3328
- setModelLoadState('error');
3329
- })["finally"](function () {
3330
- clearTimeout(modelLoadTimeout);
3331
- });
3332
- return function () {
3333
- log('unloading document detection model');
3334
- cancelVideoReady();
3335
- closeDocumentDetector();
3336
- clearTimeout(modelLoadTimeout);
3337
- document.removeEventListener('idmission.preloadProgress.documentDetection', handleDownloadProgress);
3338
- };
3339
- }, [shouldLoadModels, modelLoadTimeoutMs, modelPath, scoreThreshold, videoRef]);
3340
- React.useEffect(function handleModelError() {
3341
- if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
3342
- }, [modelError, onModelError]);
3343
- return React.useMemo(function () {
3344
- return {
3345
- ready: modelLoadState === 'ready',
3346
- modelLoadState: modelLoadState,
3347
- modelDownloadProgress: modelDownloadProgress,
3348
- modelWarmingStartedAt: modelWarmingStartedAt,
3349
- modelError: modelError,
3350
- setModelError: setModelError
3351
- };
3352
- }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
3353
- }
3354
- function makeDocumentDetectorPrediction(frame) {
3355
- return __awaiter(this, void 0, void 0, function () {
3356
- var startedAt, prediction, time, frameWidth, frameHeight;
3357
- return __generator(this, function (_a) {
3358
- if (!detector) return [2 /*return*/, null];
3359
- startedAt = new Date();
3360
- // Detectors can throw errors, for example when using custom URLs that
3361
- // contain a model that doesn't provide the expected output.
3362
- try {
3363
- prediction = detector.detectForVideo(frame, performance.now());
3364
- time = new Date().getTime() - startedAt.getTime();
3365
- frameWidth = frame.width;
3366
- frameHeight = frame.height;
3367
- return [2 /*return*/, _assign(_assign({}, prediction), {
3368
- time: time,
3369
- frameWidth: frameWidth,
3370
- frameHeight: frameHeight
3371
- })];
3372
- } catch (e) {
3373
- error('caught object detection error', e);
3374
- }
3375
- return [2 /*return*/, null];
3376
- });
3377
- });
3378
- }
3379
- var lastDetectionAt = 0;
3380
- var lastDetectionTime = 0;
3381
- function setLastDetectionAt(time) {
3382
- lastDetectionTime = time - lastDetectionAt;
3383
- lastDetectionAt = time;
3384
- }
3385
- var framesNeededSamples = [];
3386
- function trackFramesNeeded(value, bufferLength) {
3387
- if (bufferLength === void 0) {
3388
- bufferLength = 25;
3389
- }
3390
- framesNeededSamples.unshift(value);
3391
- if (framesNeededSamples.length > bufferLength) framesNeededSamples.length = bufferLength;
3392
- }
3393
- var lastNBoxes = [];
3394
- var lastNPairs = [];
3395
- function trackBox(box, framesNeeded) {
3396
- if (framesNeeded === void 0) {
3397
- framesNeeded = 12;
3398
- }
3399
- lastNBoxes.unshift(box);
3400
- if (lastNBoxes.length > framesNeeded) lastNBoxes.length = framesNeeded;
3401
- if (lastNBoxes.length > 1) {
3402
- var lastBox = lastNBoxes[1];
3403
- var iou = calculateIoU(box, lastBox);
3404
- lastNPairs.unshift({
3405
- a: box,
3406
- b: lastBox,
3407
- iou: iou
3408
- });
3409
- if (lastNPairs.length > framesNeeded - 1) lastNPairs.length = framesNeeded - 1;
3410
- }
3411
- }
3412
- var defaultDocumentDetectionBoundaries = {
3413
- top: 20,
3414
- bottom: 20,
3415
- left: 20,
3416
- right: 20
3417
- };
3418
- function processDocumentDetectorPrediction(prediction, thresholds, boundaries) {
3419
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
3420
- if (boundaries === void 0) {
3421
- boundaries = defaultDocumentDetectionBoundaries;
3422
- }
3423
- var detections = prediction.detections,
3424
- frameWidth = prediction.frameWidth,
3425
- frameHeight = prediction.frameHeight,
3426
- time = prediction.time;
3427
- var boundaryTop = (_a = boundaries.top) !== null && _a !== void 0 ? _a : 20;
3428
- var boundaryLeft = (_b = boundaries.left) !== null && _b !== void 0 ? _b : 20;
3429
- var boundaryRight = (_c = boundaries.right) !== null && _c !== void 0 ? _c : 20;
3430
- var boundaryBottom = (_d = boundaries.bottom) !== null && _d !== void 0 ? _d : 20;
3431
- var frameWidth80Pct = frameWidth * 0.8;
3432
- var detectedObjects = applyNonMaxSuppression(detections.flatMap(function (d) {
3433
- return d.categories.map(function (category) {
3434
- return {
3435
- label: category === null || category === void 0 ? void 0 : category.categoryName,
3436
- score: category === null || category === void 0 ? void 0 : category.score,
3437
- box: convertBoundingBox(d.boundingBox)
3438
- };
3439
- });
3440
- }), function (obj) {
3441
- var _a = obj.box,
3442
- xMin = _a.xMin,
3443
- yMin = _a.yMin,
3444
- width = _a.width,
3445
- height = _a.height;
3446
- return yMin > boundaryTop &&
3447
- // Is it valid top edge of ID detected?
3448
- yMin + height + boundaryBottom < frameHeight && (
3449
- // Is it valid bottom edge less than max video height
3450
- xMin > boundaryLeft || xMin + width > frameWidth80Pct) &&
3451
- // If either the left side visible or if not, right edge of ID should be more than 80% of width.
3452
- xMin + width + boundaryRight < frameWidth // Valid right edge if it's less than video width.
3453
- ;
3454
- });
3455
- var allZero = detections.length > 0 && !detections.some(function (_a) {
3456
- var boundingBox = _a.boundingBox;
3457
- return Object.values(boundingBox !== null && boundingBox !== void 0 ? boundingBox : {}).some(function (n) {
3458
- return n > 0;
3459
- });
3460
- });
3461
- var bestIdCardFront = detectedObjects.find(function (obj) {
3462
- return obj.label === 'Document';
3463
- });
3464
- var bestIdCardBack = detectedObjects.find(function (obj) {
3465
- return obj.label === 'Document back';
3466
- });
3467
- var bestPassportPage = detectedObjects.find(function (obj) {
3468
- return obj.label === 'Passport page';
3469
- });
3470
- var bestSinglePage = detectedObjects.find(function (obj) {
3471
- return obj.label === 'Single page';
3472
- });
3473
- var idCardFrontDetectionScore = (_e = bestIdCardFront === null || bestIdCardFront === void 0 ? void 0 : bestIdCardFront.score) !== null && _e !== void 0 ? _e : 0;
3474
- var idCardBackDetectionScore = (_f = bestIdCardBack === null || bestIdCardBack === void 0 ? void 0 : bestIdCardBack.score) !== null && _f !== void 0 ? _f : 0;
3475
- var passportDetectionScore = (_g = bestPassportPage === null || bestPassportPage === void 0 ? void 0 : bestPassportPage.score) !== null && _g !== void 0 ? _g : 0;
3476
- var singlePageDetectionScore = (_h = bestSinglePage === null || bestSinglePage === void 0 ? void 0 : bestSinglePage.score) !== null && _h !== void 0 ? _h : 0;
3477
- var idCardFrontDetectionThresholdMet = idCardFrontDetectionScore >= ((_j = thresholds.idCardFront) !== null && _j !== void 0 ? _j : 0);
3478
- var idCardBackDetectionThresholdMet = idCardBackDetectionScore >= ((_k = thresholds.idCardBack) !== null && _k !== void 0 ? _k : 0);
3479
- var passportDetectionThresholdMet = passportDetectionScore >= ((_l = thresholds.passport) !== null && _l !== void 0 ? _l : 0);
3480
- var singlePageDetectionThresholdMet = singlePageDetectionScore >= ((_m = thresholds.singlePage) !== null && _m !== void 0 ? _m : 0);
3481
- var bestDocument = singlePageDetectionThresholdMet ? bestSinglePage : passportDetectionThresholdMet ? bestPassportPage : idCardBackDetectionThresholdMet ? bestIdCardBack : bestIdCardFront;
3482
- var detectionThreshold = singlePageDetectionThresholdMet ? thresholds.singlePage : passportDetectionThresholdMet ? thresholds.passport : idCardBackDetectionThresholdMet ? thresholds.idCardBack : thresholds.idCardFront;
3483
- var detectionScore = (_o = bestDocument === null || bestDocument === void 0 ? void 0 : bestDocument.score) !== null && _o !== void 0 ? _o : 0;
3484
- var detectionThresholdMet = detectionScore >= (detectionThreshold !== null && detectionThreshold !== void 0 ? detectionThreshold : 0);
3485
- var detectedDocumentType = 'none';
3486
- if (singlePageDetectionThresholdMet) {
3487
- detectedDocumentType = 'singlePage';
3488
- } else if (passportDetectionThresholdMet) {
3489
- detectedDocumentType = 'passport';
3490
- } else if (idCardBackDetectionThresholdMet) {
3491
- detectedDocumentType = 'idCardBack';
3492
- } else if (detectionThresholdMet) {
3493
- detectedDocumentType = 'idCardFront';
3494
- }
3495
- var documentInBounds = !!bestDocument;
3496
- if (lastDetectionTime > 0) {
3497
- trackFramesNeeded(1000 / lastDetectionTime);
3498
- }
3499
- var documentIsStable = false;
3500
- var documentTooClose = false;
3501
- if (bestDocument) {
3502
- var _q = [bestDocument.box.width / frameWidth, bestDocument.box.height / frameHeight],
3503
- docWidth = _q[0],
3504
- docHeight = _q[1];
3505
- documentTooClose = docWidth > 0.85 || docHeight > 0.85;
3506
- if (detectionThresholdMet && documentInBounds && !documentTooClose) {
3507
- var thresholdSet = (_p = thresholds.stability) !== null && _p !== void 0 ? _p : defaultDocumentDetectionThresholds.stability;
3508
- var threshold_1 = thresholdSet[detectedDocumentType];
3509
- var framesNeeded = Math.ceil(average(framesNeededSamples));
3510
- trackBox(bestDocument.box, framesNeeded);
3511
- documentIsStable = lastNBoxes.length >= framesNeeded && !lastNPairs.some(function (pair) {
3512
- return pair.iou < threshold_1;
3513
- });
3514
- }
3515
- }
3516
- return {
3517
- prediction: prediction,
3518
- detectedObjects: detectedObjects,
3519
- detectionScore: detectionScore,
3520
- detectionTime: time,
3521
- detectionThresholdMet: detectionThresholdMet,
3522
- detectedDocumentType: detectedDocumentType,
3523
- idCardFrontDetectionScore: idCardFrontDetectionScore,
3524
- idCardFrontDetectionThresholdMet: idCardFrontDetectionThresholdMet,
3525
- idCardBackDetectionScore: idCardBackDetectionScore,
3526
- idCardBackDetectionThresholdMet: idCardBackDetectionThresholdMet,
3527
- passportDetectionScore: passportDetectionScore,
3528
- passportDetectionThresholdMet: passportDetectionThresholdMet,
3529
- singlePageDetectionScore: singlePageDetectionScore,
3530
- singlePageDetectionThresholdMet: singlePageDetectionThresholdMet,
3531
- bestDocument: bestDocument,
3532
- documentInBounds: documentInBounds,
3533
- documentTooClose: documentTooClose,
3534
- documentIsStable: documentIsStable,
3535
- frameWidth: frameWidth,
3536
- frameHeight: frameHeight,
3537
- allZero: allZero
3538
- };
3539
- }
3540
- function applyNonMaxSuppression(detectedObjects, isGoodBox) {
3541
- var maxes = {};
3542
- detectedObjects.forEach(function (obj, i) {
3543
- if (obj) {
3544
- if (!maxes[obj.label]) maxes[obj.label] = [0, -1];
3545
- if (obj.score > maxes[obj.label][0] && (isGoodBox === null || isGoodBox === void 0 ? void 0 : isGoodBox(obj))) maxes[obj.label] = [obj.score, i];
3546
- }
3547
- });
3548
- return Object.keys(maxes).map(function (label) {
3549
- return detectedObjects[maxes[label][1]];
3550
- }).filter(function (obj) {
3551
- return !!obj;
3552
- });
3553
- }
3554
- function testDocumentDetectionAgainstKnownImage(detector) {
3555
- return new Promise(function (resolve, reject) {
3556
- var img = new Image();
3557
- img.crossOrigin = 'anonymous';
3558
- img.onload = function () {
3559
- var prediction = detector.detectForVideo(img, performance.now());
3560
- if (prediction.detections.length > 0) {
3561
- debug('document detection test result', prediction.detections);
3562
- resolve(void 0);
3563
- } else {
3564
- warn('document detection test failed');
3565
- reject(new Error('testDocumentDetectionAgainstKnownImage failed to predict'));
3566
- }
3567
- };
3568
- img.onerror = function () {
3569
- return reject(new Error('testDocumentDetectionAgainstKnownImage failed to load image'));
3570
- };
3571
- img.src = "".concat(DEFAULT_CDN_URL, "/id-card-test.jpg");
3572
- });
3573
- }
3574
-
3575
- function useFrameLoop(fn, options) {
3576
- if (options === void 0) {
3577
- options = {};
3578
- }
3579
- var _a = React.useState(false),
3580
- running = _a[0],
3581
- setRunning = _a[1];
3582
- var startedAtRef = React.useRef(null);
3583
- var loopId = React.useRef(0);
3584
- var frameId = React.useRef(0);
3585
- React.useEffect(function runFrameLoop() {
3586
- if (!running) return;
3587
- var timer;
3588
- var currentLoopId = loopId.current;
3589
- function hotLoop() {
3590
- return __awaiter(this, void 0, void 0, function () {
3591
- var start, timeRunning, took, amountToThrottle;
3592
- var _a, _b, _c;
3593
- return __generator(this, function (_d) {
3594
- switch (_d.label) {
3595
- case 0:
3596
- if (currentLoopId !== loopId.current) return [2 /*return*/];
3597
- start = new Date().getTime();
3598
- timeRunning = start - ((_b = (_a = startedAtRef.current) === null || _a === void 0 ? void 0 : _a.getTime()) !== null && _b !== void 0 ? _b : 0);
3599
- return [4 /*yield*/, fn(frameId.current, timeRunning)];
3600
- case 1:
3601
- _d.sent();
3602
- took = new Date().getTime() - start;
3603
- amountToThrottle = Math.max(((_c = options.throttleMs) !== null && _c !== void 0 ? _c : 0) - took, 0);
3604
- timer = setTimeout(function () {
3605
- frameId.current = requestAnimationFrame(hotLoop);
3606
- }, amountToThrottle);
3607
- return [2 /*return*/];
3608
- }
3609
- });
3610
- });
3611
- }
3612
- void hotLoop();
3613
- return function () {
3614
- loopId.current += 1;
3615
- if (frameId.current) cancelAnimationFrame(frameId.current);
3616
- if (timer) clearTimeout(timer);
3617
- };
3618
- }, [fn, running, options.throttleMs]);
3619
- var start = React.useCallback(function () {
3620
- startedAtRef.current = new Date();
3621
- setRunning(true);
3622
- }, []);
3623
- var stop = React.useCallback(function () {
3624
- loopId.current += 1; // force the loop to stop immediately.
3625
- setRunning(false);
3626
- startedAtRef.current = null;
3627
- }, []);
3628
- React.useEffect(function startAutomatically() {
3629
- if (options.autoStart) start();
3630
- return stop;
3631
- }, [options.autoStart, start, stop]);
3632
- return {
3633
- start: start,
3634
- stop: stop
3635
- };
3636
- }
3637
-
3638
- function listAvailableCameras(facingMode_1) {
3639
- return __awaiter(this, arguments, void 0, function (facingMode, requestMicAccess) {
3640
- var cameraEnumerationStream, allDevices, allowedVideoDevices;
3641
- if (requestMicAccess === void 0) {
3642
- requestMicAccess = false;
3643
- }
3644
- return __generator(this, function (_a) {
3645
- switch (_a.label) {
3646
- case 0:
3647
- return [4 /*yield*/, navigator.mediaDevices.getUserMedia({
3648
- video: {
3649
- facingMode: {
3650
- exact: facingMode
3651
- }
3652
- },
3653
- audio: requestMicAccess
3654
- })
3655
- // This lists all available cameras attached to the user's device.
3656
- ];
3657
- case 1:
3658
- cameraEnumerationStream = _a.sent();
3659
- return [4 /*yield*/, navigator.mediaDevices.enumerateDevices()];
3660
- case 2:
3661
- allDevices = _a.sent();
3662
- allowedVideoDevices = allDevices.filter(function (_a) {
3663
- var kind = _a.kind,
3664
- label = _a.label;
3665
- return kind === 'videoinput' && !label.toLowerCase().includes('virtual');
3666
- });
3667
- // Release the access to the user's camera that we obtained for enumeration purposes.
3668
- cameraEnumerationStream.getVideoTracks().forEach(function (track) {
3669
- track.enabled = false;
3670
- track.stop();
3671
- });
3672
- cameraEnumerationStream = null;
3673
- return [2 /*return*/, allowedVideoDevices];
3674
- }
3675
- });
3676
- });
3677
- }
3678
- 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) {
3679
- return s.toLocaleLowerCase().split(' ').join('');
3680
- });
3681
- 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) {
3682
- return s.toLocaleLowerCase().split(' ').join('');
3683
- });
3684
- 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) {
3685
- return s.toLocaleLowerCase().split(' ').join('');
3686
- });
3687
- var cameraLabelMatches = function cameraLabelMatches(labelOrDevice, labelSetOrLabel) {
3688
- var label = labelOrDevice instanceof MediaDeviceInfo ? getDeviceLabel(labelOrDevice) : labelOrDevice;
3689
- var labelSet = typeof labelSetOrLabel === 'string' ? [labelSetOrLabel] : labelSetOrLabel;
3690
- return labelSet.some(function (l) {
3691
- return label.includes(l);
3692
- });
3693
- };
3694
- var getDeviceLabel = function getDeviceLabel(deviceInfo) {
3695
- return deviceInfo.label.toLocaleLowerCase().split(' ').join('');
3696
- };
3697
- var currentCamera;
3698
- function obtainCameraAccess(stream, deviceLabel, video) {
3699
- releaseCameraAccess();
3700
- log('obtaining camera access...');
3701
- var _a = stream.getVideoTracks()[0].getSettings(),
3702
- width = _a.width,
3703
- height = _a.height;
3704
- log('camera dimensions', width, height);
3705
- var label = deviceLabel.toLocaleLowerCase().split(' ').join('');
3706
- log('camera label', label);
3707
- var isRearFacing = cameraLabelMatches(label, __spreadArray(__spreadArray(__spreadArray([], rearCameraLabels, true), backUltraWideCameraLabels, true), ['iphone'], false));
3708
- log('is rear facing?', isRearFacing);
3709
- var release = function release() {
3710
- stream.getTracks().forEach(function (track) {
3711
- track.enabled = false;
3712
- track.stop();
3713
- });
3714
- if (video) {
3715
- video.pause();
3716
- video.srcObject = null;
3717
- video.src = '';
3718
- }
3719
- };
3720
- width || (width = 0);
3721
- height || (height = 0);
3722
- currentCamera = {
3723
- label: deviceLabel,
3724
- stream: stream,
3725
- width: width,
3726
- height: height,
3727
- isRearFacing: isRearFacing,
3728
- release: release
3729
- };
3730
- log('camera access granted');
3731
- // if (video) video.srcObject = stream
3732
- // log('video source initialized')
3733
- return currentCamera;
3734
- }
3735
- function releaseCameraAccess() {
3736
- if (!currentCamera) return;
3737
- log('releasing camera access...');
3738
- currentCamera.release();
3739
- currentCamera = undefined;
3182
+ function releaseCameraAccess() {
3183
+ if (!currentCamera) return;
3184
+ log('releasing camera access...');
3185
+ currentCamera.release();
3186
+ currentCamera = undefined;
3740
3187
  }
3741
3188
 
3742
3189
  var en = {};
@@ -3867,7 +3314,8 @@ var es = {
3867
3314
  Cancel: 'Cancelar',
3868
3315
  'Upload the back of the ID if it is not included in the front image.': 'Adjuntar el reverso de la ID si no se incluye en la imagen del frente',
3869
3316
  'Camera tampering detected': 'Se ha detectado un intento de manipulación de la cámara',
3870
- "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'Lo sentimos, pero parece que la cámara está siendo manipulada. Por favor, verifique su dispositivo y vuelva a intentarlo recargando la página.'
3317
+ "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'Lo sentimos, pero parece que la cámara está siendo manipulada. Por favor, verifique su dispositivo y vuelva a intentarlo recargando la página.',
3318
+ 'Position your face in the circle and click to capture.': 'Enfoca tu cara en el círculo y da clic en capturar.'
3871
3319
  };
3872
3320
 
3873
3321
  var de = {
@@ -3996,7 +3444,8 @@ var de = {
3996
3444
  Cancel: 'Abbrechen',
3997
3445
  'Upload the back of the ID if it is not included in the front image.': 'Laden Sie die Rückseite des Ausweises hoch, wenn diese nicht im Bild der Vorderseite enthalten ist.',
3998
3446
  'Camera tampering detected': 'Kamera manipuliert',
3999
- "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'Leider scheint die Kamera manipuliert zu werden. Bitte prüfen Sie Ihr Gerät und laden Sie die Seite neu.'
3447
+ "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'Leider scheint die Kamera manipuliert zu werden. Bitte prüfen Sie Ihr Gerät und laden Sie die Seite neu.',
3448
+ 'Position your face in the circle and click to capture.': 'Stellen Sie Ihr Gesicht im Kreis ein und klicken Sie auf Erfassen.'
4000
3449
  };
4001
3450
 
4002
3451
  var fr = {
@@ -4125,7 +3574,8 @@ var fr = {
4125
3574
  Cancel: 'Annuler',
4126
3575
  'Upload the back of the ID if it is not included in the front image.': "Téléchargez le verso de la pièce d'identité si ce n'est pas inclus dans l'image du recto.",
4127
3576
  'Camera tampering detected': 'Manipulation de la caméra détectée',
4128
- "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'Nous sommes désolés, mais il semble que la caméra soit manipulée. Veuillez vérifier votre appareil et réessayer en rechargeant la page.'
3577
+ "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'Nous sommes désolés, mais il semble que la caméra soit manipulée. Veuillez vérifier votre appareil et réessayer en rechargeant la page.',
3578
+ 'Position your face in the circle and click to capture.': 'Positionnez votre visage dans le cercle et cliquez pour capturer.'
4129
3579
  };
4130
3580
 
4131
3581
  var it = {
@@ -4254,7 +3704,8 @@ var it = {
4254
3704
  Cancel: 'Annulla',
4255
3705
  'Upload the back of the ID if it is not included in the front image.': "Carica il retro dell'ID se non è incluso nell'immagine del fronte.",
4256
3706
  'Camera tampering detected': 'Manipolazione della fotocamera rilevata',
4257
- "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'Siamo spiacenti, ma sembra che la fotocamera stia venendo manipolata. Controlla il tuo dispositivo e riprova ricaricando la pagina.'
3707
+ "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'Siamo spiacenti, ma sembra che la fotocamera stia venendo manipolata. Controlla il tuo dispositivo e riprova ricaricando la pagina.',
3708
+ 'Position your face in the circle and click to capture.': 'Posiziona il tuo volto nel cerchio e clicca per acquisire.'
4258
3709
  };
4259
3710
 
4260
3711
  var ja = {
@@ -4383,7 +3834,8 @@ var ja = {
4383
3834
  Cancel: 'キャンセル',
4384
3835
  'Upload the back of the ID if it is not included in the front image.': '表面画像に裏面が含まれていない場合は、裏面をアップロードしてください。',
4385
3836
  'Camera tampering detected': 'カメラの操作が検出されました',
4386
- "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'カメラの操作が検出されました。デバイスを確認し、ページを再読み込みしてください。'
3837
+ "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'カメラの操作が検出されました。デバイスを確認し、ページを再読み込みしてください。',
3838
+ 'Position your face in the circle and click to capture.': '顔を円の中に合わせてクリックして撮影してください。'
4387
3839
  };
4388
3840
 
4389
3841
  var pt = {
@@ -4512,7 +3964,8 @@ var pt = {
4512
3964
  Cancel: 'Cancelar',
4513
3965
  'Upload the back of the ID if it is not included in the front image.': 'Carregue o verso do ID se não estiver incluído na imagem da frente.',
4514
3966
  'Camera tampering detected': 'Manipulação da câmera detectada',
4515
- "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'Lamentamos, mas parece que a câmera está sendo manipulada. Verifique seu dispositivo e tente novamente recarregando a página.'
3967
+ "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'Lamentamos, mas parece que a câmera está sendo manipulada. Verifique seu dispositivo e tente novamente recarregando a página.',
3968
+ 'Position your face in the circle and click to capture.': 'Posicione seu rosto no círculo e clique para capturar.'
4516
3969
  };
4517
3970
 
4518
3971
  var ru = {
@@ -4641,7 +4094,8 @@ var ru = {
4641
4094
  Cancel: 'Отменить',
4642
4095
  'Upload the back of the ID if it is not included in the front image.': 'Загрузите заднюю сторону удостоверения, если она не включена в изображение передней стороны.',
4643
4096
  'Camera tampering detected': 'Обнаружена манипуляция с камерой',
4644
- "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'К сожалению, кажется, что камера подвергается манипуляциям. Пожалуйста, проверьте свое устройство и попробуйте снова, перезагрузив страницу.'
4097
+ "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": 'К сожалению, кажется, что камера подвергается манипуляциям. Пожалуйста, проверьте свое устройство и попробуйте снова, перезагрузив страницу.',
4098
+ 'Position your face in the circle and click to capture.': 'Поместите свое лицо в круг и нажмите для съемки.'
4645
4099
  };
4646
4100
 
4647
4101
  var zh = {
@@ -4770,7 +4224,8 @@ var zh = {
4770
4224
  Cancel: '取消',
4771
4225
  'Upload the back of the ID if it is not included in the front image.': '如果正面照片没有包含身份证背面,请上传背面照片。',
4772
4226
  'Camera tampering detected': '檢測到相機被篡改',
4773
- "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": '很抱歉,看起來相機被篡改了。請檢查您的設備並重新載入頁面。'
4227
+ "We're sorry, but it looks like the camera is being tampered with. Please check your device and try again by reloading the page.": '很抱歉,看起來相機被篡改了。請檢查您的設備並重新載入頁面。',
4228
+ 'Position your face in the circle and click to capture.': '將您的臉部置於圓圈中,點擊拍攝。'
4774
4229
  };
4775
4230
 
4776
4231
  function renderVerbiage(verbiage) {
@@ -5335,224 +4790,768 @@ function CameraTamperSeal(_a) {
5335
4790
  className: classNames.message
5336
4791
  }, messageText)));
5337
4792
  }
5338
- var StyledOverlayInner$4 = styled__default.default(OverlayInner$2)(templateObject_1$M || (templateObject_1$M = __makeTemplateObject(["\n justify-content: center;\n"], ["\n justify-content: center;\n"])));
5339
- var StyledOverlayHeading = styled__default.default.h3(templateObject_2$F || (templateObject_2$F = __makeTemplateObject(["\n margin-bottom: 8px;\n"], ["\n margin-bottom: 8px;\n"])));
5340
- function useCameraStore(selector) {
5341
- var store = React.useContext(CameraStoreContext);
5342
- if (!store) throw new Error('useCameraStore cannot be used without Provider');
5343
- return zustand.useStore(store, selector);
4793
+ var StyledOverlayInner$4 = styled__default.default(OverlayInner$2)(templateObject_1$M || (templateObject_1$M = __makeTemplateObject(["\n justify-content: center;\n"], ["\n justify-content: center;\n"])));
4794
+ var StyledOverlayHeading = styled__default.default.h3(templateObject_2$F || (templateObject_2$F = __makeTemplateObject(["\n margin-bottom: 8px;\n"], ["\n margin-bottom: 8px;\n"])));
4795
+ function useCameraStore(selector) {
4796
+ var store = React.useContext(CameraStoreContext);
4797
+ if (!store) throw new Error('useCameraStore cannot be used without Provider');
4798
+ return zustand.useStore(store, selector);
4799
+ }
4800
+ var templateObject_1$M, templateObject_2$F;
4801
+
4802
+ var DocumentDetectionModelContext = /*#__PURE__*/React.createContext({
4803
+ startDocumentDetection: function startDocumentDetection() {
4804
+ return null;
4805
+ },
4806
+ stopDocumentDetection: function stopDocumentDetection() {
4807
+ return null;
4808
+ },
4809
+ loadDocumentDetectionModel: function loadDocumentDetectionModel() {
4810
+ return null;
4811
+ },
4812
+ documentDetectionModelState: 'not-started',
4813
+ documentDetectionModelDownloadProgress: 0,
4814
+ documentDetectionModelWarmingStartedAt: null,
4815
+ documentDetectionModelError: null,
4816
+ onDocumentDetected: function onDocumentDetected() {
4817
+ return null;
4818
+ },
4819
+ detectionTime: 0,
4820
+ documentDetectionThresholds: {},
4821
+ setDocumentDetectionThresholds: function setDocumentDetectionThresholds() {
4822
+ return null;
4823
+ },
4824
+ documentDetectionBoundaries: defaultDocumentDetectionBoundaries,
4825
+ setDocumentDetectionBoundaries: function setDocumentDetectionBoundaries() {
4826
+ return null;
4827
+ },
4828
+ documentDetectionLastPredictionCanvas: {
4829
+ current: null
4830
+ },
4831
+ clearDocumentDetectionLastPredictionCanvas: function clearDocumentDetectionLastPredictionCanvas() {
4832
+ return null;
4833
+ }
4834
+ });
4835
+ function DocumentDetectionModelProvider(_a) {
4836
+ var _this = this;
4837
+ var _b = _a.autoStart,
4838
+ autoStart = _b === void 0 ? true : _b,
4839
+ children = _a.children,
4840
+ _c = _a.throttleMs,
4841
+ throttleMs = _c === void 0 ? 16 : _c,
4842
+ _d = _a.delayAfterStartMs,
4843
+ delayAfterStartMs = _d === void 0 ? 0 : _d,
4844
+ _e = _a.documentDetectionModelPath,
4845
+ documentDetectionModelPath = _e === void 0 ? defaultDocumentDetectorModelPath : _e,
4846
+ _f = _a.documentDetectionModelScoreThreshold,
4847
+ documentDetectionModelScoreThreshold = _f === void 0 ? defaultDocumentDetectionScoreThreshold : _f,
4848
+ _g = _a.modelLoadTimeoutMs,
4849
+ modelLoadTimeoutMs = _g === void 0 ? defaultDocumentDetectionModelLoadTimeoutMs : _g,
4850
+ onDocumentDetectionModelError = _a.onDocumentDetectionModelError,
4851
+ _h = _a.shouldLoadModels,
4852
+ shouldLoadModelsProp = _h === void 0 ? true : _h;
4853
+ var _j = useCameraStore(),
4854
+ videoRef = _j.videoRef,
4855
+ videoLoaded = _j.videoLoaded,
4856
+ cameraReady = _j.cameraReady;
4857
+ var lastPredictionCanvas = React.useRef(null);
4858
+ var onPredictionHandler = React.useRef();
4859
+ var _k = React.useState({}),
4860
+ documentDetectionThresholds = _k[0],
4861
+ setDocumentDetectionThresholds = _k[1];
4862
+ var _l = React.useState(defaultDocumentDetectionBoundaries),
4863
+ documentDetectionBoundaries = _l[0],
4864
+ setDocumentDetectionBoundaries = _l[1];
4865
+ var _m = React.useState(0),
4866
+ timesAllZero = _m[0],
4867
+ setTimesAllZero = _m[1];
4868
+ var _o = React.useState(0),
4869
+ canvasKey = _o[0],
4870
+ setCanvasKey = _o[1];
4871
+ var stopDetection = React.useRef(0);
4872
+ var _p = React.useState(shouldLoadModelsProp),
4873
+ shouldLoadModels = _p[0],
4874
+ setShouldLoadModels = _p[1];
4875
+ var load = React.useCallback(function () {
4876
+ return setShouldLoadModels(true);
4877
+ }, []);
4878
+ var _q = useLoadDocumentDetector({
4879
+ modelPath: documentDetectionModelPath,
4880
+ modelLoadTimeoutMs: modelLoadTimeoutMs,
4881
+ scoreThreshold: documentDetectionModelScoreThreshold,
4882
+ onModelError: onDocumentDetectionModelError,
4883
+ videoRef: videoRef,
4884
+ shouldLoadModels: shouldLoadModels
4885
+ }),
4886
+ ready = _q.ready,
4887
+ modelLoadState = _q.modelLoadState,
4888
+ modelDownloadProgress = _q.modelDownloadProgress,
4889
+ modelWarmingStartedAt = _q.modelWarmingStartedAt,
4890
+ modelError = _q.modelError,
4891
+ setModelError = _q.setModelError;
4892
+ var _r = useFrameLoop(React.useCallback(function (frameId, timeRunning) {
4893
+ return __awaiter(_this, void 0, void 0, function () {
4894
+ var stopDetectionAtStart, vw, vh, ctx, prediction, processedPrediction;
4895
+ var _a;
4896
+ return __generator(this, function (_b) {
4897
+ switch (_b.label) {
4898
+ case 0:
4899
+ if (!videoLoaded || !cameraReady || !ready || !videoRef.current || !lastPredictionCanvas.current) return [2 /*return*/];
4900
+ stopDetectionAtStart = stopDetection.current;
4901
+ vw = videoRef.current.videoWidth;
4902
+ vh = videoRef.current.videoHeight;
4903
+ lastPredictionCanvas.current.width = vw;
4904
+ lastPredictionCanvas.current.height = vh;
4905
+ ctx = lastPredictionCanvas.current.getContext('2d');
4906
+ if (!(ctx && videoRef.current.readyState === 4)) return [3 /*break*/, 3];
4907
+ if (stopDetectionAtStart !== stopDetection.current) return [2 /*return*/];
4908
+ ctx.drawImage(videoRef.current, 0, 0, vw, vh);
4909
+ return [4 /*yield*/, makeDocumentDetectorPrediction(lastPredictionCanvas.current)];
4910
+ case 1:
4911
+ prediction = _b.sent();
4912
+ if (!prediction) return [3 /*break*/, 3];
4913
+ processedPrediction = processDocumentDetectorPrediction(prediction, documentDetectionThresholds, documentDetectionBoundaries);
4914
+ processedPrediction.frameId = frameId;
4915
+ setLastDetectionAt(new Date().getTime());
4916
+ debug(processedPrediction);
4917
+ if (processedPrediction.allZero) setTimesAllZero(function (n) {
4918
+ return n + 1;
4919
+ });
4920
+ if (stopDetectionAtStart !== stopDetection.current) return [2 /*return*/];
4921
+ if (timeRunning < delayAfterStartMs) return [2 /*return*/];
4922
+ return [4 /*yield*/, (_a = onPredictionHandler.current) === null || _a === void 0 ? void 0 : _a.call(onPredictionHandler, processedPrediction)];
4923
+ case 2:
4924
+ _b.sent();
4925
+ _b.label = 3;
4926
+ case 3:
4927
+ return [2 /*return*/];
4928
+ }
4929
+ });
4930
+ });
4931
+ }, [cameraReady, delayAfterStartMs, documentDetectionBoundaries, documentDetectionThresholds, ready, videoLoaded, videoRef]), {
4932
+ throttleMs: throttleMs,
4933
+ autoStart: autoStart
4934
+ }),
4935
+ start = _r.start,
4936
+ stop = _r.stop;
4937
+ React.useEffect(function setErrorIfAllZero() {
4938
+ if (timesAllZero >= 2) {
4939
+ setModelError(new Error('model is returning all zeroes'));
4940
+ }
4941
+ }, [setModelError, timesAllZero]);
4942
+ var onDocumentDetected = React.useCallback(function (handler) {
4943
+ onPredictionHandler.current = handler;
4944
+ }, []);
4945
+ var clearDocumentDetectionLastPredictionCanvas = React.useCallback(function () {
4946
+ stopDetection.current += 1;
4947
+ setCanvasKey(function (n) {
4948
+ return n + 1;
4949
+ });
4950
+ }, []);
4951
+ var value = React.useMemo(function () {
4952
+ return {
4953
+ startDocumentDetection: start,
4954
+ stopDocumentDetection: stop,
4955
+ loadDocumentDetectionModel: load,
4956
+ documentDetectionModelState: modelLoadState,
4957
+ documentDetectionModelWarmingStartedAt: modelWarmingStartedAt,
4958
+ documentDetectionModelError: modelError,
4959
+ documentDetectionModelDownloadProgress: modelDownloadProgress,
4960
+ onDocumentDetected: onDocumentDetected,
4961
+ detectionTime: lastDetectionTime,
4962
+ documentDetectionThresholds: documentDetectionThresholds,
4963
+ setDocumentDetectionThresholds: setDocumentDetectionThresholds,
4964
+ documentDetectionBoundaries: documentDetectionBoundaries,
4965
+ setDocumentDetectionBoundaries: setDocumentDetectionBoundaries,
4966
+ documentDetectionLastPredictionCanvas: lastPredictionCanvas,
4967
+ clearDocumentDetectionLastPredictionCanvas: clearDocumentDetectionLastPredictionCanvas
4968
+ };
4969
+ }, [start, stop, load, modelLoadState, modelWarmingStartedAt, modelError, modelDownloadProgress, onDocumentDetected, documentDetectionThresholds, documentDetectionBoundaries, clearDocumentDetectionLastPredictionCanvas]);
4970
+ return /*#__PURE__*/React__namespace.createElement(DocumentDetectionModelContext.Provider, {
4971
+ value: value
4972
+ }, /*#__PURE__*/React__namespace.createElement(InvisibleCanvas, {
4973
+ key: canvasKey,
4974
+ ref: lastPredictionCanvas
4975
+ }), children);
4976
+ }
4977
+
4978
+ function cropToShoulders(rawCanvas, cropCanvas, resizeCanvas, frame, face, quality, maxHeight) {
4979
+ var _a;
4980
+ if (quality === void 0) {
4981
+ quality = 0.92;
4982
+ }
4983
+ if (!rawCanvas || !cropCanvas || !resizeCanvas) return '';
4984
+ var rawCtx = rawCanvas.getContext('2d');
4985
+ var cropCtx = cropCanvas.getContext('2d');
4986
+ var resizeCtx = resizeCanvas.getContext('2d');
4987
+ if (!rawCtx || !cropCtx || !resizeCtx) throw new Error('could not get 2d context');
4988
+ rawCanvas.width = frame.width;
4989
+ rawCanvas.height = frame.height;
4990
+ rawCtx.putImageData(frame, 0, 0);
4991
+ if (frame.height > frame.width) {
4992
+ cropCanvas.width = frame.width;
4993
+ cropCanvas.height = frame.height;
4994
+ cropCtx.drawImage(rawCanvas, 0, 0, cropCanvas.width, cropCanvas.height);
4995
+ } else {
4996
+ var _b = (_a = face === null || face === void 0 ? void 0 : face.box) !== null && _a !== void 0 ? _a : {
4997
+ xMin: 0,
4998
+ width: frame.width
4999
+ },
5000
+ xMin = _b.xMin,
5001
+ width = _b.width;
5002
+ var desiredWidth = frame.height * 0.6;
5003
+ var faceCenterX = xMin + width / 2;
5004
+ var xPos = Math.max(0, faceCenterX - desiredWidth / 2);
5005
+ cropCanvas.width = desiredWidth;
5006
+ cropCanvas.height = frame.height;
5007
+ cropCtx.drawImage(rawCanvas, xPos, 0, cropCanvas.width, cropCanvas.height, 0, 0, cropCanvas.width, cropCanvas.height);
5008
+ }
5009
+ resizeCanvas.height = maxHeight !== null && maxHeight !== void 0 ? maxHeight : cropCanvas.height;
5010
+ resizeCanvas.width = cropCanvas.width * (resizeCanvas.height / cropCanvas.height);
5011
+ resizeCtx === null || resizeCtx === void 0 ? void 0 : resizeCtx.drawImage(cropCanvas, 0, 0, resizeCanvas.width, resizeCanvas.height);
5012
+ var dataURL = resizeCanvas.toDataURL('image/jpeg', quality);
5013
+ log('cropToShoulders size', new TextEncoder().encode(dataURL).length);
5014
+ clearCanvas(rawCanvas);
5015
+ clearCanvas(cropCanvas);
5016
+ clearCanvas(resizeCanvas);
5017
+ return dataURL;
5018
+ }
5019
+ function cropToDetectedObjectBox(frame, box, canvas, padding) {
5020
+ if (padding === void 0) {
5021
+ padding = 0;
5022
+ }
5023
+ canvas || (canvas = document.createElement('canvas'));
5024
+ var ctx = canvas.getContext('2d');
5025
+ if (!ctx) throw new Error('could not get 2d context');
5026
+ var xMin = box.xMin,
5027
+ yMin = box.yMin,
5028
+ width = box.width,
5029
+ height = box.height;
5030
+ canvas.width = width + padding * 2;
5031
+ canvas.height = height + padding * 2;
5032
+ ctx.drawImage(frame, xMin - padding, yMin - padding, width + padding * 2, height + padding * 2, 0, 0, canvas.width, canvas.height);
5033
+ return canvas;
5034
+ }
5035
+ function cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box, padding) {
5036
+ if (padding === void 0) {
5037
+ padding = 0;
5038
+ }
5039
+ if (!box) return imageData;
5040
+ var cropped = cropToDetectedObjectBox(imageData, box, cropCanvas, padding);
5041
+ var _a = [box.width, box.height],
5042
+ bw = _a[0],
5043
+ bh = _a[1];
5044
+ if (bh <= bw) return cropped;
5045
+ var ctx = rotateCanvas.getContext('2d');
5046
+ if (!ctx) return cropped;
5047
+ rotateCanvas.width = bh;
5048
+ rotateCanvas.height = bw;
5049
+ ctx.clearRect(0, 0, rotateCanvas.width, rotateCanvas.height);
5050
+ ctx.translate(rotateCanvas.width / 2, rotateCanvas.height / 2);
5051
+ ctx.rotate(1.5708); // 90 deg in radians
5052
+ ctx.drawImage(cropped, -bw / 2, -bh / 2);
5053
+ return rotateCanvas;
5054
+ }
5055
+ function resizeIfNecessary(imageData, resizeCanvas, maxWidth) {
5056
+ var width = imageData.width,
5057
+ height = imageData.height;
5058
+ if (width <= maxWidth) return imageData;
5059
+ var resizeCtx = resizeCanvas.getContext('2d');
5060
+ if (!resizeCtx) return imageData;
5061
+ var scale = maxWidth / width;
5062
+ resizeCanvas.width = maxWidth;
5063
+ resizeCanvas.height = height * scale;
5064
+ resizeCtx.drawImage(imageData, 0, 0, resizeCanvas.width, resizeCanvas.height);
5065
+ return resizeCanvas;
5344
5066
  }
5345
- var templateObject_1$M, templateObject_2$F;
5346
5067
 
5347
- var DocumentDetectionModelContext = /*#__PURE__*/React.createContext({
5348
- startDocumentDetection: function startDocumentDetection() {
5349
- return null;
5350
- },
5351
- stopDocumentDetection: function stopDocumentDetection() {
5352
- return null;
5353
- },
5354
- loadDocumentDetectionModel: function loadDocumentDetectionModel() {
5355
- return null;
5356
- },
5357
- documentDetectionModelState: 'not-started',
5358
- documentDetectionModelDownloadProgress: 0,
5359
- documentDetectionModelWarmingStartedAt: null,
5360
- documentDetectionModelError: null,
5361
- onDocumentDetected: function onDocumentDetected() {
5362
- return null;
5363
- },
5364
- detectionTime: 0,
5365
- documentDetectionThresholds: {},
5366
- setDocumentDetectionThresholds: function setDocumentDetectionThresholds() {
5367
- return null;
5068
+ var defaultFocusModelLoadTimeoutMs = 45000;
5069
+ var defaultFocusThresholds = {
5070
+ idCardFront: {
5071
+ desktop: 0,
5072
+ mobile: 0.3
5368
5073
  },
5369
- documentDetectionBoundaries: defaultDocumentDetectionBoundaries,
5370
- setDocumentDetectionBoundaries: function setDocumentDetectionBoundaries() {
5371
- return null;
5074
+ idCardBack: {
5075
+ desktop: 0,
5076
+ mobile: 0.3
5372
5077
  },
5373
- documentDetectionLastPredictionCanvas: {
5374
- current: null
5078
+ passport: {
5079
+ desktop: 0,
5080
+ mobile: 0.3
5375
5081
  },
5376
- clearDocumentDetectionLastPredictionCanvas: function clearDocumentDetectionLastPredictionCanvas() {
5377
- return null;
5082
+ singlePage: {
5083
+ desktop: 0,
5084
+ mobile: 0.3
5378
5085
  }
5379
- });
5380
- function DocumentDetectionModelProvider(_a) {
5381
- var _this = this;
5382
- var _b = _a.autoStart,
5383
- autoStart = _b === void 0 ? true : _b,
5384
- children = _a.children,
5385
- _c = _a.throttleMs,
5386
- throttleMs = _c === void 0 ? 16 : _c,
5387
- _d = _a.delayAfterStartMs,
5388
- delayAfterStartMs = _d === void 0 ? 0 : _d,
5389
- _e = _a.documentDetectionModelPath,
5390
- documentDetectionModelPath = _e === void 0 ? defaultDocumentDetectorModelPath : _e,
5391
- _f = _a.documentDetectionModelScoreThreshold,
5392
- documentDetectionModelScoreThreshold = _f === void 0 ? defaultDocumentDetectionScoreThreshold : _f,
5393
- _g = _a.modelLoadTimeoutMs,
5394
- modelLoadTimeoutMs = _g === void 0 ? defaultDocumentDetectionModelLoadTimeoutMs : _g,
5395
- onDocumentDetectionModelError = _a.onDocumentDetectionModelError,
5396
- _h = _a.shouldLoadModels,
5397
- shouldLoadModelsProp = _h === void 0 ? true : _h;
5398
- var _j = useCameraStore(),
5399
- videoRef = _j.videoRef,
5400
- videoLoaded = _j.videoLoaded,
5401
- cameraReady = _j.cameraReady;
5402
- var lastPredictionCanvas = React.useRef(null);
5403
- var onPredictionHandler = React.useRef();
5404
- var _k = React.useState({}),
5405
- documentDetectionThresholds = _k[0],
5406
- setDocumentDetectionThresholds = _k[1];
5407
- var _l = React.useState(defaultDocumentDetectionBoundaries),
5408
- documentDetectionBoundaries = _l[0],
5409
- setDocumentDetectionBoundaries = _l[1];
5410
- var _m = React.useState(0),
5411
- timesAllZero = _m[0],
5412
- setTimesAllZero = _m[1];
5413
- var _o = React.useState(0),
5414
- canvasKey = _o[0],
5415
- setCanvasKey = _o[1];
5416
- var stopDetection = React.useRef(0);
5417
- var _p = React.useState(shouldLoadModelsProp),
5418
- shouldLoadModels = _p[0],
5419
- setShouldLoadModels = _p[1];
5086
+ };
5087
+ var classifier$1 = null;
5088
+ var classifierSettings$1 = null;
5089
+ function loadFocusModel() {
5090
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
5091
+ var _a, _b;
5092
+ if (modelAssetPath === void 0) {
5093
+ modelAssetPath = defaultFocusModelPath;
5094
+ }
5095
+ return __generator(this, function (_c) {
5096
+ switch (_c.label) {
5097
+ case 0:
5098
+ if (classifier$1 && (classifierSettings$1 === null || classifierSettings$1 === void 0 ? void 0 : classifierSettings$1.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier$1];
5099
+ closeFocusModel();
5100
+ return [4 /*yield*/, preloadFocusModelDependencies()];
5101
+ case 1:
5102
+ _c.sent();
5103
+ if (modelCapabilities.delegate === 'NONE') {
5104
+ throw new Error('No available delegate for focus detector.');
5105
+ }
5106
+ _b = (_a = tasksVision.ImageClassifier).createFromOptions;
5107
+ return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
5108
+ case 2:
5109
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
5110
+ baseOptions: {
5111
+ modelAssetPath: modelAssetPath,
5112
+ delegate: modelCapabilities.delegate
5113
+ },
5114
+ // canvas: document.createElement('canvas'),
5115
+ runningMode: 'VIDEO'
5116
+ }])];
5117
+ case 3:
5118
+ classifier$1 = _c.sent();
5119
+ classifierSettings$1 = {
5120
+ modelAssetPath: modelAssetPath
5121
+ };
5122
+ return [2 /*return*/, classifier$1];
5123
+ }
5124
+ });
5125
+ });
5126
+ }
5127
+ function closeFocusModel() {
5128
+ classifier$1 === null || classifier$1 === void 0 ? void 0 : classifier$1.close();
5129
+ classifier$1 = null;
5130
+ classifierSettings$1 = null;
5131
+ }
5132
+ function useLoadFocusModel(_a) {
5133
+ var _b = _a.modelPath,
5134
+ modelPath = _b === void 0 ? defaultFocusModelPath : _b,
5135
+ _c = _a.modelLoadTimeoutMs,
5136
+ modelLoadTimeoutMs = _c === void 0 ? defaultFocusModelLoadTimeoutMs : _c,
5137
+ onModelError = _a.onModelError,
5138
+ videoRef = _a.videoRef,
5139
+ _d = _a.shouldLoadModels,
5140
+ shouldLoadModels = _d === void 0 ? true : _d;
5141
+ var _e = React.useState('not-started'),
5142
+ modelLoadState = _e[0],
5143
+ setModelLoadState = _e[1];
5144
+ var _f = React.useState(0),
5145
+ modelDownloadProgress = _f[0],
5146
+ setModelDownloadProgress = _f[1];
5147
+ var _g = React.useState(null),
5148
+ modelWarmingStartedAt = _g[0],
5149
+ setModelWarmingStartedAt = _g[1];
5150
+ var _h = React.useState(null),
5151
+ modelError = _h[0],
5152
+ setModelError = _h[1];
5153
+ React.useEffect(function loadModel() {
5154
+ var _this = this;
5155
+ if (!shouldLoadModels) return;
5156
+ setModelLoadState('downloading');
5157
+ setModelWarmingStartedAt(null);
5158
+ function handleDownloadProgress(event) {
5159
+ setModelDownloadProgress(progressToPercentage(event.detail));
5160
+ }
5161
+ document.addEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
5162
+ var modelLoadTimeout = setTimeout(function () {
5163
+ setModelError(new Error('Model loading time limit exceeded.'));
5164
+ }, modelLoadTimeoutMs);
5165
+ var cancelVideoReady = function cancelVideoReady() {};
5166
+ loadFocusModel(modelPath).then(function (loadedModel) {
5167
+ return __awaiter(_this, void 0, void 0, function () {
5168
+ var _a, videoReady, cancel, cancelled;
5169
+ return __generator(this, function (_b) {
5170
+ switch (_b.label) {
5171
+ case 0:
5172
+ setModelDownloadProgress(100);
5173
+ clearTimeout(modelLoadTimeout);
5174
+ setModelLoadState('warming');
5175
+ setModelWarmingStartedAt(performance.now());
5176
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
5177
+ cancelled = false;
5178
+ cancelVideoReady = function cancelVideoReady() {
5179
+ cancelled = true;
5180
+ cancel();
5181
+ };
5182
+ return [4 /*yield*/, videoReady];
5183
+ case 1:
5184
+ _b.sent();
5185
+ setTimeout(function () {
5186
+ if (cancelled) return;
5187
+ loadedModel.classifyForVideo(videoRef.current, performance.now());
5188
+ setModelLoadState('ready');
5189
+ }, 500);
5190
+ return [2 /*return*/];
5191
+ }
5192
+ });
5193
+ });
5194
+ })["catch"](function (e) {
5195
+ setModelError(e);
5196
+ setModelLoadState('error');
5197
+ })["finally"](function () {
5198
+ clearTimeout(modelLoadTimeout);
5199
+ });
5200
+ return function () {
5201
+ log('unloading focus model');
5202
+ cancelVideoReady();
5203
+ closeFocusModel();
5204
+ clearTimeout(modelLoadTimeout);
5205
+ document.removeEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
5206
+ };
5207
+ }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
5208
+ React.useEffect(function handleModelError() {
5209
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
5210
+ }, [modelError, onModelError]);
5211
+ return React.useMemo(function () {
5212
+ return {
5213
+ ready: modelLoadState === 'ready',
5214
+ modelLoadState: modelLoadState,
5215
+ modelDownloadProgress: modelDownloadProgress,
5216
+ modelWarmingStartedAt: modelWarmingStartedAt,
5217
+ modelError: modelError
5218
+ };
5219
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
5220
+ }
5221
+ var lastFocusPredictionAt = 0;
5222
+ var lastFocusPredictionTime = 0;
5223
+ function setLastFocusPredictionAt(time) {
5224
+ lastFocusPredictionTime = time - lastFocusPredictionAt;
5225
+ lastFocusPredictionAt = time;
5226
+ }
5227
+ function makeFocusModelPrediction(imageData, cropCanvas, rotateCanvas, box) {
5228
+ var _a, _b, _c, _d, _e;
5229
+ if (!classifier$1) return null;
5230
+ var startedAt = performance.now();
5231
+ var image = cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box);
5232
+ var result = classifier$1.classifyForVideo(image, performance.now());
5233
+ 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) {
5234
+ return c.categoryName === 'focused';
5235
+ })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
5236
+ var predictionTime = performance.now() - startedAt;
5237
+ return {
5238
+ score: score,
5239
+ predictionTime: predictionTime
5240
+ };
5241
+ }
5242
+
5243
+ var FocusModelContext = /*#__PURE__*/React.createContext({
5244
+ loadFocusModel: function loadFocusModel() {
5245
+ return null;
5246
+ },
5247
+ focusModelState: 'not-started',
5248
+ focusModelDownloadProgress: 0,
5249
+ focusModelWarmingStartedAt: null,
5250
+ focusModelError: null,
5251
+ focusThresholds: {},
5252
+ setFocusThresholds: function setFocusThresholds() {
5253
+ return null;
5254
+ },
5255
+ makeFocusPrediction: function makeFocusPrediction() {
5256
+ return null;
5257
+ },
5258
+ focusPredictionTime: 0
5259
+ });
5260
+ function FocusModelProvider(_a) {
5261
+ var children = _a.children,
5262
+ _b = _a.focusModelPath,
5263
+ focusModelPath = _b === void 0 ? defaultFocusModelPath : _b,
5264
+ _c = _a.focusModelLoadTimeoutMs,
5265
+ focusModelLoadTimeoutMs = _c === void 0 ? defaultFocusModelLoadTimeoutMs : _c,
5266
+ onFocusModelError = _a.onFocusModelError,
5267
+ _d = _a.showCanvases,
5268
+ showCanvases = _d === void 0 ? false : _d,
5269
+ _e = _a.shouldLoadModels,
5270
+ shouldLoadModelsProp = _e === void 0 ? true : _e;
5271
+ var cropCanvas = React.useRef(null);
5272
+ var rotateCanvas = React.useRef(null);
5273
+ var _f = React.useState({}),
5274
+ focusThresholds = _f[0],
5275
+ setFocusThresholds = _f[1];
5276
+ var videoRef = useCameraStore().videoRef;
5277
+ var _g = React.useState(shouldLoadModelsProp),
5278
+ shouldLoadModels = _g[0],
5279
+ setShouldLoadModels = _g[1];
5420
5280
  var load = React.useCallback(function () {
5421
5281
  return setShouldLoadModels(true);
5422
5282
  }, []);
5423
- var _q = useLoadDocumentDetector({
5424
- modelPath: documentDetectionModelPath,
5425
- modelLoadTimeoutMs: modelLoadTimeoutMs,
5426
- scoreThreshold: documentDetectionModelScoreThreshold,
5427
- onModelError: onDocumentDetectionModelError,
5283
+ var _h = useLoadFocusModel({
5284
+ modelPath: focusModelPath,
5285
+ modelLoadTimeoutMs: focusModelLoadTimeoutMs,
5286
+ onModelError: onFocusModelError,
5428
5287
  videoRef: videoRef,
5429
5288
  shouldLoadModels: shouldLoadModels
5430
5289
  }),
5431
- ready = _q.ready,
5432
- modelLoadState = _q.modelLoadState,
5433
- modelDownloadProgress = _q.modelDownloadProgress,
5434
- modelWarmingStartedAt = _q.modelWarmingStartedAt,
5435
- modelError = _q.modelError,
5436
- setModelError = _q.setModelError;
5437
- var _r = useFrameLoop(React.useCallback(function (frameId, timeRunning) {
5290
+ ready = _h.ready,
5291
+ modelLoadState = _h.modelLoadState,
5292
+ modelDownloadProgress = _h.modelDownloadProgress,
5293
+ modelWarmingStartedAt = _h.modelWarmingStartedAt,
5294
+ modelError = _h.modelError;
5295
+ var makeFocusPrediction = React.useCallback(function (imageData, box) {
5296
+ if (!ready) return null;
5297
+ var prediction = makeFocusModelPrediction(imageData, cropCanvas.current, rotateCanvas.current, box);
5298
+ if (!prediction) return null;
5299
+ setLastFocusPredictionAt(prediction.predictionTime);
5300
+ return prediction;
5301
+ }, [ready]);
5302
+ var value = React.useMemo(function () {
5303
+ return {
5304
+ loadFocusModel: load,
5305
+ focusModelState: modelLoadState,
5306
+ focusModelDownloadProgress: modelDownloadProgress,
5307
+ focusModelWarmingStartedAt: modelWarmingStartedAt,
5308
+ focusModelError: modelError,
5309
+ makeFocusPrediction: makeFocusPrediction,
5310
+ focusPredictionTime: lastFocusPredictionTime,
5311
+ focusThresholds: focusThresholds,
5312
+ setFocusThresholds: setFocusThresholds
5313
+ };
5314
+ }, [focusThresholds, load, makeFocusPrediction, modelDownloadProgress, modelError, modelLoadState, modelWarmingStartedAt]);
5315
+ return /*#__PURE__*/React__namespace.default.createElement(FocusModelContext.Provider, {
5316
+ value: value
5317
+ }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5318
+ ref: rotateCanvas,
5319
+ style: showCanvases ? {
5320
+ display: 'block'
5321
+ } : undefined
5322
+ }), /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5323
+ ref: cropCanvas,
5324
+ style: showCanvases ? {
5325
+ display: 'block'
5326
+ } : undefined
5327
+ })), children);
5328
+ }
5329
+
5330
+ function _isNavigatorDefined() {
5331
+ return typeof navigator !== 'undefined' && navigator != null;
5332
+ }
5333
+ var isMobileCache;
5334
+ function isMobile() {
5335
+ if (isMobileCache !== undefined) return isMobileCache;
5336
+ isMobileCache = evaluateIsMobile();
5337
+ return isMobileCache;
5338
+ }
5339
+ function evaluateIsMobile(nav) {
5340
+ if (nav || _isNavigatorDefined()) {
5341
+ if (!nav) {
5342
+ nav = navigator;
5343
+ }
5344
+ if (nav.product === 'ReactNative') {
5345
+ return true;
5346
+ }
5347
+ var a = nav.userAgent || nav.vendor || (
5348
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5349
+ // @ts-ignore
5350
+ typeof window !== 'undefined' ? window.opera : '');
5351
+ if (!a) {
5352
+ var navAny = nav;
5353
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5354
+ // @ts-ignore
5355
+ return navAny.userAgentData && navAny.userAgentData.mobile;
5356
+ }
5357
+ 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));
5358
+ }
5359
+ return false;
5360
+ }
5361
+
5362
+ var defaultBarcodeReadabilityModelLoadTimeoutMs = 45000;
5363
+ var classifier = null;
5364
+ var classifierSettings = null;
5365
+ function loadBarcodeReadabilityModel() {
5366
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
5367
+ var _a, _b;
5368
+ if (modelAssetPath === void 0) {
5369
+ modelAssetPath = defaultBarcodeReadabilityModelPath;
5370
+ }
5371
+ return __generator(this, function (_c) {
5372
+ switch (_c.label) {
5373
+ case 0:
5374
+ if (classifier && (classifierSettings === null || classifierSettings === void 0 ? void 0 : classifierSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier];
5375
+ closeBarcodeReadabilityModel();
5376
+ return [4 /*yield*/, preloadBarcodeReadabilityModelDependencies()];
5377
+ case 1:
5378
+ _c.sent();
5379
+ if (modelCapabilities.delegate === 'NONE') {
5380
+ throw new Error('No available delegate for barcode readability model.');
5381
+ }
5382
+ _b = (_a = tasksVision.ImageClassifier).createFromOptions;
5383
+ return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
5384
+ case 2:
5385
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
5386
+ baseOptions: {
5387
+ modelAssetPath: modelAssetPath,
5388
+ delegate: 'CPU'
5389
+ },
5390
+ runningMode: 'VIDEO',
5391
+ maxResults: 1
5392
+ }])];
5393
+ case 3:
5394
+ classifier = _c.sent();
5395
+ classifierSettings = {
5396
+ modelAssetPath: modelAssetPath
5397
+ };
5398
+ return [2 /*return*/, classifier];
5399
+ }
5400
+ });
5401
+ });
5402
+ }
5403
+ function closeBarcodeReadabilityModel() {
5404
+ classifier === null || classifier === void 0 ? void 0 : classifier.close();
5405
+ classifier = null;
5406
+ classifierSettings = null;
5407
+ }
5408
+ function useLoadBarcodeReadabilityModel(_a) {
5409
+ var _b = _a.modelPath,
5410
+ modelPath = _b === void 0 ? defaultBarcodeReadabilityModelPath : _b,
5411
+ _c = _a.modelLoadTimeoutMs,
5412
+ modelLoadTimeoutMs = _c === void 0 ? defaultBarcodeReadabilityModelLoadTimeoutMs : _c,
5413
+ onModelError = _a.onModelError,
5414
+ videoRef = _a.videoRef,
5415
+ _d = _a.shouldLoadModels,
5416
+ shouldLoadModels = _d === void 0 ? true : _d;
5417
+ var _e = React.useState('not-started'),
5418
+ modelLoadState = _e[0],
5419
+ setModelLoadState = _e[1];
5420
+ var _f = React.useState(0),
5421
+ modelDownloadProgress = _f[0],
5422
+ setModelDownloadProgress = _f[1];
5423
+ var _g = React.useState(null),
5424
+ modelWarmingStartedAt = _g[0],
5425
+ setModelWarmingStartedAt = _g[1];
5426
+ var _h = React.useState(null),
5427
+ modelError = _h[0],
5428
+ setModelError = _h[1];
5429
+ React.useEffect(function loadModel() {
5430
+ var _this = this;
5431
+ if (!shouldLoadModels) return;
5432
+ setModelLoadState('downloading');
5433
+ setModelWarmingStartedAt(null);
5434
+ function handleDownloadProgress(event) {
5435
+ setModelDownloadProgress(progressToPercentage(event.detail));
5436
+ }
5437
+ document.addEventListener('idmission.preloadProgress.barcodeReadability', handleDownloadProgress);
5438
+ var modelLoadTimeout = setTimeout(function () {
5439
+ setModelError(new Error('Model loading time limit exceeded.'));
5440
+ }, modelLoadTimeoutMs);
5441
+ var cancelVideoReady = function cancelVideoReady() {};
5442
+ loadBarcodeReadabilityModel(modelPath).then(function (loadedModel) {
5438
5443
  return __awaiter(_this, void 0, void 0, function () {
5439
- var stopDetectionAtStart, vw, vh, ctx, prediction, processedPrediction;
5440
- var _a;
5444
+ var _a, videoReady, cancel, cancelled;
5441
5445
  return __generator(this, function (_b) {
5442
5446
  switch (_b.label) {
5443
5447
  case 0:
5444
- if (!videoLoaded || !cameraReady || !ready || !videoRef.current || !lastPredictionCanvas.current) return [2 /*return*/];
5445
- stopDetectionAtStart = stopDetection.current;
5446
- vw = videoRef.current.videoWidth;
5447
- vh = videoRef.current.videoHeight;
5448
- lastPredictionCanvas.current.width = vw;
5449
- lastPredictionCanvas.current.height = vh;
5450
- ctx = lastPredictionCanvas.current.getContext('2d');
5451
- if (!(ctx && videoRef.current.readyState === 4)) return [3 /*break*/, 3];
5452
- if (stopDetectionAtStart !== stopDetection.current) return [2 /*return*/];
5453
- ctx.drawImage(videoRef.current, 0, 0, vw, vh);
5454
- return [4 /*yield*/, makeDocumentDetectorPrediction(lastPredictionCanvas.current)];
5448
+ setModelDownloadProgress(100);
5449
+ clearTimeout(modelLoadTimeout);
5450
+ setModelLoadState('warming');
5451
+ setModelWarmingStartedAt(new Date().getTime());
5452
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
5453
+ cancelled = false;
5454
+ cancelVideoReady = function cancelVideoReady() {
5455
+ cancelled = true;
5456
+ cancel();
5457
+ };
5458
+ return [4 /*yield*/, videoReady];
5455
5459
  case 1:
5456
- prediction = _b.sent();
5457
- if (!prediction) return [3 /*break*/, 3];
5458
- processedPrediction = processDocumentDetectorPrediction(prediction, documentDetectionThresholds, documentDetectionBoundaries);
5459
- processedPrediction.frameId = frameId;
5460
- setLastDetectionAt(new Date().getTime());
5461
- debug(processedPrediction);
5462
- if (processedPrediction.allZero) setTimesAllZero(function (n) {
5463
- return n + 1;
5464
- });
5465
- if (stopDetectionAtStart !== stopDetection.current) return [2 /*return*/];
5466
- if (timeRunning < delayAfterStartMs) return [2 /*return*/];
5467
- return [4 /*yield*/, (_a = onPredictionHandler.current) === null || _a === void 0 ? void 0 : _a.call(onPredictionHandler, processedPrediction)];
5468
- case 2:
5469
5460
  _b.sent();
5470
- _b.label = 3;
5471
- case 3:
5472
- return [2 /*return*/];
5473
- }
5474
- });
5475
- });
5476
- }, [cameraReady, delayAfterStartMs, documentDetectionBoundaries, documentDetectionThresholds, ready, videoLoaded, videoRef]), {
5477
- throttleMs: throttleMs,
5478
- autoStart: autoStart
5479
- }),
5480
- start = _r.start,
5481
- stop = _r.stop;
5482
- React.useEffect(function setErrorIfAllZero() {
5483
- if (timesAllZero >= 2) {
5484
- setModelError(new Error('model is returning all zeroes'));
5485
- }
5486
- }, [setModelError, timesAllZero]);
5487
- var onDocumentDetected = React.useCallback(function (handler) {
5488
- onPredictionHandler.current = handler;
5489
- }, []);
5490
- var clearDocumentDetectionLastPredictionCanvas = React.useCallback(function () {
5491
- stopDetection.current += 1;
5492
- setCanvasKey(function (n) {
5493
- return n + 1;
5461
+ setTimeout(function () {
5462
+ if (cancelled) return;
5463
+ loadedModel.classifyForVideo(videoRef.current, performance.now());
5464
+ setModelLoadState('ready');
5465
+ }, 500);
5466
+ return [2 /*return*/];
5467
+ }
5468
+ });
5469
+ });
5470
+ })["catch"](function (e) {
5471
+ setModelError(e);
5472
+ setModelLoadState('error');
5473
+ })["finally"](function () {
5474
+ clearTimeout(modelLoadTimeout);
5494
5475
  });
5495
- }, []);
5496
- var value = React.useMemo(function () {
5476
+ return function () {
5477
+ log('unloading barcode readability model');
5478
+ cancelVideoReady();
5479
+ closeBarcodeReadabilityModel();
5480
+ clearTimeout(modelLoadTimeout);
5481
+ document.removeEventListener('idmission.preloadProgress.barcodeReadability', handleDownloadProgress);
5482
+ };
5483
+ }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
5484
+ React.useEffect(function handleModelError() {
5485
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
5486
+ }, [modelError, onModelError]);
5487
+ return React.useMemo(function () {
5497
5488
  return {
5498
- startDocumentDetection: start,
5499
- stopDocumentDetection: stop,
5500
- loadDocumentDetectionModel: load,
5501
- documentDetectionModelState: modelLoadState,
5502
- documentDetectionModelWarmingStartedAt: modelWarmingStartedAt,
5503
- documentDetectionModelError: modelError,
5504
- documentDetectionModelDownloadProgress: modelDownloadProgress,
5505
- onDocumentDetected: onDocumentDetected,
5506
- detectionTime: lastDetectionTime,
5507
- documentDetectionThresholds: documentDetectionThresholds,
5508
- setDocumentDetectionThresholds: setDocumentDetectionThresholds,
5509
- documentDetectionBoundaries: documentDetectionBoundaries,
5510
- setDocumentDetectionBoundaries: setDocumentDetectionBoundaries,
5511
- documentDetectionLastPredictionCanvas: lastPredictionCanvas,
5512
- clearDocumentDetectionLastPredictionCanvas: clearDocumentDetectionLastPredictionCanvas
5489
+ ready: modelLoadState === 'ready',
5490
+ modelLoadState: modelLoadState,
5491
+ modelDownloadProgress: modelDownloadProgress,
5492
+ modelWarmingStartedAt: modelWarmingStartedAt,
5493
+ modelError: modelError
5513
5494
  };
5514
- }, [start, stop, load, modelLoadState, modelWarmingStartedAt, modelError, modelDownloadProgress, onDocumentDetected, documentDetectionThresholds, documentDetectionBoundaries, clearDocumentDetectionLastPredictionCanvas]);
5515
- return /*#__PURE__*/React__namespace.createElement(DocumentDetectionModelContext.Provider, {
5516
- value: value
5517
- }, /*#__PURE__*/React__namespace.createElement(InvisibleCanvas, {
5518
- key: canvasKey,
5519
- ref: lastPredictionCanvas
5520
- }), children);
5495
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
5496
+ }
5497
+ var lastBarcodeReadabilityPredictionAt = 0;
5498
+ var lastBarcodeReadabilityPredictionTime = 0;
5499
+ function setLastBarcodeReadabilityPredictionAt(time) {
5500
+ lastBarcodeReadabilityPredictionTime = time - lastBarcodeReadabilityPredictionAt;
5501
+ lastBarcodeReadabilityPredictionAt = time;
5502
+ }
5503
+ function makeBarcodeReadabilityModelPrediction(imageData, cropCanvas, rotateCanvas, resizeCanvas, box) {
5504
+ var _a, _b, _c, _d, _e;
5505
+ if (!classifier) return null;
5506
+ var startedAt = performance.now();
5507
+ var image = cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box);
5508
+ var resized = resizeIfNecessary(image, resizeCanvas, 500);
5509
+ var result = classifier.classifyForVideo(resized, performance.now());
5510
+ 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) {
5511
+ return c.categoryName === 'blurry';
5512
+ })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
5513
+ debug('barcode prediction', "".concat(performance.now() - startedAt, "ms"), score);
5514
+ var predictionTime = performance.now() - startedAt;
5515
+ return {
5516
+ score: score,
5517
+ predictionTime: predictionTime
5518
+ };
5521
5519
  }
5522
5520
 
5523
- var FocusModelContext = /*#__PURE__*/React.createContext({
5524
- loadFocusModel: function loadFocusModel() {
5521
+ var BarcodeReadabilityModelContext = /*#__PURE__*/React.createContext({
5522
+ loadBarcodeReadabilityModel: function loadBarcodeReadabilityModel() {
5525
5523
  return null;
5526
5524
  },
5527
- focusModelState: 'not-started',
5528
- focusModelDownloadProgress: 0,
5529
- focusModelWarmingStartedAt: null,
5530
- focusModelError: null,
5531
- focusThresholds: {},
5532
- setFocusThresholds: function setFocusThresholds() {
5525
+ barcodeReadabilityModelState: 'not-started',
5526
+ barcodeReadabilityModelDownloadProgress: 0,
5527
+ barcodeReadabilityModelWarmingStartedAt: null,
5528
+ barcodeReadabilityModelError: null,
5529
+ barcodeReadabilityThresholds: {},
5530
+ setBarcodeReadabilityThresholds: function setBarcodeReadabilityThresholds() {
5533
5531
  return null;
5534
5532
  },
5535
- makeFocusPrediction: function makeFocusPrediction() {
5533
+ makeBarcodeReadabilityPrediction: function makeBarcodeReadabilityPrediction() {
5536
5534
  return null;
5537
5535
  },
5538
- focusPredictionTime: 0
5536
+ barcodeReadabilityPredictionTime: 0
5539
5537
  });
5540
- function FocusModelProvider(_a) {
5538
+ function BarcodeReadabilityModelProvider(_a) {
5541
5539
  var children = _a.children,
5542
- _b = _a.focusModelPath,
5543
- focusModelPath = _b === void 0 ? defaultFocusModelPath : _b,
5544
- _c = _a.focusModelLoadTimeoutMs,
5545
- focusModelLoadTimeoutMs = _c === void 0 ? defaultFocusModelLoadTimeoutMs : _c,
5546
- onFocusModelError = _a.onFocusModelError,
5540
+ _b = _a.barcodeReadabilityModelPath,
5541
+ barcodeReadabilityModelPath = _b === void 0 ? defaultBarcodeReadabilityModelPath : _b,
5542
+ _c = _a.barcodeReadabilityModelLoadTimeoutMs,
5543
+ barcodeReadabilityModelLoadTimeoutMs = _c === void 0 ? defaultBarcodeReadabilityModelLoadTimeoutMs : _c,
5544
+ onBarcodeReadabilityModelError = _a.onBarcodeReadabilityModelError,
5547
5545
  _d = _a.showCanvases,
5548
5546
  showCanvases = _d === void 0 ? false : _d,
5549
5547
  _e = _a.shouldLoadModels,
5550
5548
  shouldLoadModelsProp = _e === void 0 ? true : _e;
5551
5549
  var cropCanvas = React.useRef(null);
5552
5550
  var rotateCanvas = React.useRef(null);
5551
+ var resizeCanvas = React.useRef(null);
5553
5552
  var _f = React.useState({}),
5554
- focusThresholds = _f[0],
5555
- setFocusThresholds = _f[1];
5553
+ barcodeReadabilityThresholds = _f[0],
5554
+ setBarcodeReadabilityThresholds = _f[1];
5556
5555
  var videoRef = useCameraStore().videoRef;
5557
5556
  var _g = React.useState(shouldLoadModelsProp),
5558
5557
  shouldLoadModels = _g[0],
@@ -5560,10 +5559,10 @@ function FocusModelProvider(_a) {
5560
5559
  var load = React.useCallback(function () {
5561
5560
  return setShouldLoadModels(true);
5562
5561
  }, []);
5563
- var _h = useLoadFocusModel({
5564
- modelPath: focusModelPath,
5565
- modelLoadTimeoutMs: focusModelLoadTimeoutMs,
5566
- onModelError: onFocusModelError,
5562
+ var _h = useLoadBarcodeReadabilityModel({
5563
+ modelPath: barcodeReadabilityModelPath,
5564
+ modelLoadTimeoutMs: barcodeReadabilityModelLoadTimeoutMs,
5565
+ onModelError: onBarcodeReadabilityModelError,
5567
5566
  videoRef: videoRef,
5568
5567
  shouldLoadModels: shouldLoadModels
5569
5568
  }),
@@ -5572,71 +5571,45 @@ function FocusModelProvider(_a) {
5572
5571
  modelDownloadProgress = _h.modelDownloadProgress,
5573
5572
  modelWarmingStartedAt = _h.modelWarmingStartedAt,
5574
5573
  modelError = _h.modelError;
5575
- var makeFocusPrediction = React.useCallback(function (imageData, box) {
5574
+ var makeBarcodeReadabilityPrediction = React.useCallback(function (imageData, box) {
5576
5575
  if (!ready) return null;
5577
- var prediction = makeFocusModelPrediction(imageData, cropCanvas.current, rotateCanvas.current, box);
5576
+ var prediction = makeBarcodeReadabilityModelPrediction(imageData, cropCanvas.current, rotateCanvas.current, resizeCanvas.current, box);
5578
5577
  if (!prediction) return null;
5579
- setLastFocusPredictionAt(prediction.predictionTime);
5578
+ setLastBarcodeReadabilityPredictionAt(prediction.predictionTime);
5580
5579
  return prediction;
5581
5580
  }, [ready]);
5582
5581
  var value = React.useMemo(function () {
5583
5582
  return {
5584
- loadFocusModel: load,
5585
- focusModelState: modelLoadState,
5586
- focusModelDownloadProgress: modelDownloadProgress,
5587
- focusModelWarmingStartedAt: modelWarmingStartedAt,
5588
- focusModelError: modelError,
5589
- makeFocusPrediction: makeFocusPrediction,
5590
- focusPredictionTime: lastFocusPredictionTime,
5591
- focusThresholds: focusThresholds,
5592
- setFocusThresholds: setFocusThresholds
5583
+ loadBarcodeReadabilityModel: load,
5584
+ barcodeReadabilityModelState: modelLoadState,
5585
+ barcodeReadabilityModelDownloadProgress: modelDownloadProgress,
5586
+ barcodeReadabilityModelWarmingStartedAt: modelWarmingStartedAt,
5587
+ barcodeReadabilityModelError: modelError,
5588
+ makeBarcodeReadabilityPrediction: makeBarcodeReadabilityPrediction,
5589
+ barcodeReadabilityPredictionTime: lastBarcodeReadabilityPredictionTime,
5590
+ barcodeReadabilityThresholds: barcodeReadabilityThresholds,
5591
+ setBarcodeReadabilityThresholds: setBarcodeReadabilityThresholds
5593
5592
  };
5594
- }, [focusThresholds, load, makeFocusPrediction, modelDownloadProgress, modelError, modelLoadState, modelWarmingStartedAt]);
5595
- return /*#__PURE__*/React__namespace.default.createElement(FocusModelContext.Provider, {
5593
+ }, [barcodeReadabilityThresholds, load, makeBarcodeReadabilityPrediction, modelDownloadProgress, modelError, modelLoadState, modelWarmingStartedAt]);
5594
+ return /*#__PURE__*/React__namespace.default.createElement(BarcodeReadabilityModelContext.Provider, {
5596
5595
  value: value
5597
- }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5598
- ref: rotateCanvas,
5599
- style: showCanvases ? {
5600
- display: 'block'
5601
- } : undefined
5596
+ }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5597
+ ref: rotateCanvas
5602
5598
  }), /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5603
- ref: cropCanvas,
5599
+ ref: cropCanvas
5600
+ }), /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5601
+ ref: resizeCanvas,
5604
5602
  style: showCanvases ? {
5605
5603
  display: 'block'
5606
5604
  } : undefined
5607
- }), children);
5608
- }
5609
-
5610
- function _isNavigatorDefined() {
5611
- return typeof navigator !== 'undefined' && navigator != null;
5605
+ })), children);
5612
5606
  }
5613
- var isMobileCache;
5614
- function isMobile() {
5615
- if (isMobileCache !== undefined) return isMobileCache;
5616
- isMobileCache = evaluateIsMobile();
5617
- return isMobileCache;
5618
- }
5619
- function evaluateIsMobile(nav) {
5620
- if (nav || _isNavigatorDefined()) {
5621
- if (!nav) {
5622
- nav = navigator;
5623
- }
5624
- if (nav.product === 'ReactNative') {
5625
- return true;
5626
- }
5627
- var a = nav.userAgent || nav.vendor || (
5628
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5629
- // @ts-ignore
5630
- typeof window !== 'undefined' ? window.opera : '');
5631
- if (!a) {
5632
- var navAny = nav;
5633
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
5634
- // @ts-ignore
5635
- return navAny.userAgentData && navAny.userAgentData.mobile;
5636
- }
5637
- 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));
5607
+ function useBarcodeReadabilityModelContext() {
5608
+ var context = React.useContext(BarcodeReadabilityModelContext);
5609
+ if (!context) {
5610
+ throw new Error('useBarcodeReadabilityModelContext must be used within an BarcodeReadabilityModelProvider');
5638
5611
  }
5639
- return false;
5612
+ return context;
5640
5613
  }
5641
5614
 
5642
5615
  var onMobile = isMobile();
@@ -5672,6 +5645,7 @@ var IdCaptureModelsContext = /*#__PURE__*/React.createContext({
5672
5645
  },
5673
5646
  detectionTime: 0,
5674
5647
  focusPredictionTime: 0,
5648
+ barcodeReadabilityPredictionTime: 0,
5675
5649
  bestFrameDetails: {
5676
5650
  current: null
5677
5651
  },
@@ -5681,55 +5655,78 @@ var IdCaptureModelsContext = /*#__PURE__*/React.createContext({
5681
5655
  resetBestFrame: function resetBestFrame() {
5682
5656
  return null;
5683
5657
  },
5658
+ bestBarcodeDetails: {
5659
+ current: null
5660
+ },
5661
+ getBestBarcode: function getBestBarcode() {
5662
+ return null;
5663
+ },
5684
5664
  requiredDocumentType: 'none',
5685
5665
  setRequiredDocumentType: function setRequiredDocumentType() {
5686
5666
  return null;
5687
5667
  }
5688
5668
  });
5689
5669
  function IdCaptureModelsProviderInner(_a) {
5670
+ var _b;
5690
5671
  var children = _a.children,
5691
5672
  onModelError = _a.onModelError,
5692
- _b = _a.allowSinglePageIdCapture,
5693
- allowSinglePageIdCapture = _b === void 0 ? false : _b;
5694
- var _c = React.useContext(DocumentDetectionModelContext),
5695
- documentDetectionModelState = _c.documentDetectionModelState,
5696
- documentDetectionModelDownloadProgress = _c.documentDetectionModelDownloadProgress,
5697
- documentDetectionModelWarmingStartedAt = _c.documentDetectionModelWarmingStartedAt,
5698
- startDocumentDetection = _c.startDocumentDetection,
5699
- stopDocumentDetection = _c.stopDocumentDetection,
5700
- loadDocumentDetectionModel = _c.loadDocumentDetectionModel,
5701
- lastPredictionCanvas = _c.documentDetectionLastPredictionCanvas,
5702
- clearDocumentDetectionLastPredictionCanvas = _c.clearDocumentDetectionLastPredictionCanvas,
5703
- onDocumentDetected = _c.onDocumentDetected,
5704
- detectionTime = _c.detectionTime,
5705
- documentDetectionThresholds = _c.documentDetectionThresholds,
5706
- setDocumentDetectionThresholds = _c.setDocumentDetectionThresholds,
5707
- documentDetectionBoundaries = _c.documentDetectionBoundaries,
5708
- setDocumentDetectionBoundaries = _c.setDocumentDetectionBoundaries,
5709
- documentDetectionModelError = _c.documentDetectionModelError;
5710
- var _d = React.useContext(FocusModelContext),
5711
- loadFocusModel = _d.loadFocusModel,
5712
- focusModelState = _d.focusModelState,
5713
- focusModelDownloadProgress = _d.focusModelDownloadProgress,
5714
- focusModelWarmingStartedAt = _d.focusModelWarmingStartedAt,
5715
- makeFocusPrediction = _d.makeFocusPrediction,
5716
- focusThresholds = _d.focusThresholds,
5717
- setFocusThresholds = _d.setFocusThresholds,
5718
- focusPredictionTime = _d.focusPredictionTime,
5719
- focusModelError = _d.focusModelError;
5673
+ _c = _a.allowSinglePageIdCapture,
5674
+ allowSinglePageIdCapture = _c === void 0 ? false : _c,
5675
+ _d = _a.enableBarcodeReadabilityModel,
5676
+ enableBarcodeReadabilityModel = _d === void 0 ? true : _d;
5677
+ var _e = React.useContext(DocumentDetectionModelContext),
5678
+ documentDetectionModelState = _e.documentDetectionModelState,
5679
+ documentDetectionModelDownloadProgress = _e.documentDetectionModelDownloadProgress,
5680
+ documentDetectionModelWarmingStartedAt = _e.documentDetectionModelWarmingStartedAt,
5681
+ startDocumentDetection = _e.startDocumentDetection,
5682
+ stopDocumentDetection = _e.stopDocumentDetection,
5683
+ loadDocumentDetectionModel = _e.loadDocumentDetectionModel,
5684
+ lastPredictionCanvas = _e.documentDetectionLastPredictionCanvas,
5685
+ clearDocumentDetectionLastPredictionCanvas = _e.clearDocumentDetectionLastPredictionCanvas,
5686
+ onDocumentDetected = _e.onDocumentDetected,
5687
+ detectionTime = _e.detectionTime,
5688
+ documentDetectionThresholds = _e.documentDetectionThresholds,
5689
+ setDocumentDetectionThresholds = _e.setDocumentDetectionThresholds,
5690
+ documentDetectionBoundaries = _e.documentDetectionBoundaries,
5691
+ setDocumentDetectionBoundaries = _e.setDocumentDetectionBoundaries,
5692
+ documentDetectionModelError = _e.documentDetectionModelError;
5693
+ var _f = React.useContext(FocusModelContext),
5694
+ loadFocusModel = _f.loadFocusModel,
5695
+ focusModelState = _f.focusModelState,
5696
+ focusModelDownloadProgress = _f.focusModelDownloadProgress,
5697
+ focusModelWarmingStartedAt = _f.focusModelWarmingStartedAt,
5698
+ makeFocusPrediction = _f.makeFocusPrediction,
5699
+ focusThresholds = _f.focusThresholds,
5700
+ setFocusThresholds = _f.setFocusThresholds,
5701
+ focusPredictionTime = _f.focusPredictionTime,
5702
+ focusModelError = _f.focusModelError;
5703
+ var _g = useBarcodeReadabilityModelContext(),
5704
+ loadBarcodeReadabilityModel = _g.loadBarcodeReadabilityModel,
5705
+ barcodeReadabilityModelState = _g.barcodeReadabilityModelState,
5706
+ barcodeReadabilityModelDownloadProgress = _g.barcodeReadabilityModelDownloadProgress,
5707
+ barcodeReadabilityModelWarmingStartedAt = _g.barcodeReadabilityModelWarmingStartedAt,
5708
+ makeBarcodeReadabilityPrediction = _g.makeBarcodeReadabilityPrediction,
5709
+ barcodeReadabilityThresholds = _g.barcodeReadabilityThresholds,
5710
+ setBarcodeReadabilityThresholds = _g.setBarcodeReadabilityThresholds,
5711
+ barcodeReadabilityPredictionTime = _g.barcodeReadabilityPredictionTime,
5712
+ barcodeReadabilityModelError = _g.barcodeReadabilityModelError;
5720
5713
  var onPredictionHandler = React.useRef();
5721
5714
  var bestFrameDetails = React.useRef(null);
5715
+ var bestBarcodeDetails = React.useRef(null);
5722
5716
  var bestPredictionCanvas = React.useRef(null);
5717
+ var bestBarcodeCanvas = React.useRef(null);
5723
5718
  var bestFocusScore = React.useRef(0);
5719
+ var bestBarcodeScore = React.useRef(0);
5724
5720
  var stopDetection = React.useRef(0);
5725
- var _e = React.useState('none'),
5726
- requiredDocumentType = _e[0],
5727
- setRequiredDocumentType = _e[1];
5721
+ var _h = React.useState('none'),
5722
+ requiredDocumentType = _h[0],
5723
+ setRequiredDocumentType = _h[1];
5728
5724
  var thresholds = React.useMemo(function () {
5729
5725
  return _assign(_assign({}, documentDetectionThresholds), {
5730
- focus: focusThresholds
5726
+ focus: focusThresholds,
5727
+ barcodeReadability: barcodeReadabilityThresholds
5731
5728
  });
5732
- }, [documentDetectionThresholds, focusThresholds]);
5729
+ }, [documentDetectionThresholds, focusThresholds, barcodeReadabilityThresholds]);
5733
5730
  var setThresholds = React.useCallback(function (thresholds) {
5734
5731
  if (thresholds.detection) {
5735
5732
  setDocumentDetectionThresholds(thresholds.detection);
@@ -5737,17 +5734,20 @@ function IdCaptureModelsProviderInner(_a) {
5737
5734
  if (thresholds.focus) {
5738
5735
  setFocusThresholds(thresholds.focus);
5739
5736
  }
5740
- }, [setDocumentDetectionThresholds, setFocusThresholds]);
5737
+ if (thresholds.barcodeReadability) {
5738
+ setBarcodeReadabilityThresholds(thresholds.barcodeReadability);
5739
+ }
5740
+ }, [setBarcodeReadabilityThresholds, setDocumentDetectionThresholds, setFocusThresholds]);
5741
5741
  React.useEffect(function handleDetections() {
5742
5742
  var _this = this;
5743
5743
  onDocumentDetected(function (prediction) {
5744
5744
  return __awaiter(_this, void 0, void 0, function () {
5745
- var stopDetectionAtStart, focusPredictionTime, focusScore, focusThresholdMet, isSinglePage, isRequiredDocumentType, focusPrediction, focusThresholdSet, focusThreshold;
5746
- var _a, _b, _c, _d, _e, _f, _g;
5747
- return __generator(this, function (_h) {
5745
+ var stopDetectionAtStart, focusPredictionTime, focusScore, focusThresholdMet, pdf417PredictionTime, pdf417PredictionScore, pdf417PredictionThresholdMet, isSinglePage, isRequiredDocumentType, focusPrediction, focusThresholdSet, focusThreshold, pdf417Prediction, barcodeReadabilityThresholdSet, barcodeReadabilityThreshold;
5746
+ var _a, _b, _c, _d, _e, _f, _g, _h;
5747
+ return __generator(this, function (_j) {
5748
5748
  if (!lastPredictionCanvas.current) return [2 /*return*/];
5749
5749
  stopDetectionAtStart = stopDetection.current;
5750
- focusPredictionTime = 0, focusScore = 0, focusThresholdMet = false;
5750
+ focusPredictionTime = 0, focusScore = 0, focusThresholdMet = false, pdf417PredictionTime = 0, pdf417PredictionScore = 0, pdf417PredictionThresholdMet = false;
5751
5751
  isSinglePage = prediction.detectedDocumentType === 'singlePage';
5752
5752
  if (!allowSinglePageIdCapture && isSinglePage) {
5753
5753
  prediction.detectedDocumentType = 'passport';
@@ -5766,28 +5766,51 @@ function IdCaptureModelsProviderInner(_a) {
5766
5766
  focusThresholdSet = (_d = thresholds.focus) === null || _d === void 0 ? void 0 : _d[prediction.detectedDocumentType];
5767
5767
  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;
5768
5768
  focusThresholdMet = focusScore >= focusThreshold;
5769
- if (bestFocusScore.current <= focusScore && stopDetectionAtStart === stopDetection.current) {
5770
- bestFocusScore.current = focusScore;
5771
- drawToCanvas(bestPredictionCanvas.current, lastPredictionCanvas.current);
5772
- bestFrameDetails.current = {
5773
- boundingBox: (_f = prediction.bestDocument) === null || _f === void 0 ? void 0 : _f.box,
5774
- documentType: prediction.detectedDocumentType,
5775
- detectionScore: prediction.detectionScore,
5776
- focusScore: focusScore
5777
- };
5769
+ if (stopDetectionAtStart === stopDetection.current) {
5770
+ if (bestFocusScore.current <= focusScore) {
5771
+ bestFocusScore.current = focusScore;
5772
+ drawToCanvas(bestPredictionCanvas.current, lastPredictionCanvas.current);
5773
+ bestFrameDetails.current = {
5774
+ boundingBox: (_f = prediction.bestDocument) === null || _f === void 0 ? void 0 : _f.box,
5775
+ documentType: prediction.detectedDocumentType,
5776
+ detectionScore: prediction.detectionScore,
5777
+ focusScore: focusScore
5778
+ };
5779
+ }
5780
+ if (enableBarcodeReadabilityModel && prediction.bestPDF417) {
5781
+ pdf417Prediction = makeBarcodeReadabilityPrediction(lastPredictionCanvas.current, prediction.bestPDF417.box);
5782
+ if (pdf417Prediction) {
5783
+ pdf417PredictionTime = pdf417Prediction.predictionTime;
5784
+ pdf417PredictionScore = pdf417Prediction.score;
5785
+ if (bestBarcodeScore.current <= pdf417Prediction.score) {
5786
+ bestBarcodeScore.current = pdf417Prediction.score;
5787
+ bestBarcodeDetails.current = {
5788
+ boundingBox: prediction.bestPDF417.box,
5789
+ score: pdf417Prediction.score
5790
+ };
5791
+ drawToCanvas(bestBarcodeCanvas.current, cropToDetectedObjectBox(lastPredictionCanvas.current, prediction.bestPDF417.box, undefined, 16));
5792
+ barcodeReadabilityThresholdSet = barcodeReadabilityThresholds[prediction.detectedDocumentType];
5793
+ barcodeReadabilityThreshold = (_g = onMobile ? barcodeReadabilityThresholdSet === null || barcodeReadabilityThresholdSet === void 0 ? void 0 : barcodeReadabilityThresholdSet.mobile : barcodeReadabilityThresholdSet === null || barcodeReadabilityThresholdSet === void 0 ? void 0 : barcodeReadabilityThresholdSet.desktop) !== null && _g !== void 0 ? _g : 0;
5794
+ pdf417PredictionThresholdMet = pdf417PredictionScore >= barcodeReadabilityThreshold;
5795
+ }
5796
+ }
5797
+ }
5778
5798
  }
5779
5799
  }
5780
- (_g = onPredictionHandler.current) === null || _g === void 0 ? void 0 : _g.call(onPredictionHandler, _assign(_assign({}, prediction), {
5800
+ (_h = onPredictionHandler.current) === null || _h === void 0 ? void 0 : _h.call(onPredictionHandler, _assign(_assign({}, prediction), {
5781
5801
  focusScore: focusScore,
5782
5802
  focusPredictionTime: focusPredictionTime,
5783
- focusThresholdMet: focusThresholdMet
5803
+ focusThresholdMet: focusThresholdMet,
5804
+ pdf417PredictionTime: pdf417PredictionTime,
5805
+ pdf417PredictionScore: pdf417PredictionScore,
5806
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet
5784
5807
  }));
5785
5808
  return [2 /*return*/];
5786
5809
  });
5787
5810
  });
5788
5811
  });
5789
- }, [allowSinglePageIdCapture, lastPredictionCanvas, makeFocusPrediction, onDocumentDetected, requiredDocumentType, thresholds.focus]);
5790
- var modelError = documentDetectionModelError !== null && documentDetectionModelError !== void 0 ? documentDetectionModelError : focusModelError;
5812
+ }, [allowSinglePageIdCapture, barcodeReadabilityThresholds, enableBarcodeReadabilityModel, lastPredictionCanvas, makeBarcodeReadabilityPrediction, makeFocusPrediction, onDocumentDetected, requiredDocumentType, thresholds.focus]);
5813
+ var modelError = (_b = documentDetectionModelError !== null && documentDetectionModelError !== void 0 ? documentDetectionModelError : focusModelError) !== null && _b !== void 0 ? _b : barcodeReadabilityModelError;
5791
5814
  React.useEffect(function handleModelErrors() {
5792
5815
  if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
5793
5816
  }, [modelError, onModelError]);
@@ -5800,9 +5823,15 @@ function IdCaptureModelsProviderInner(_a) {
5800
5823
  canvas: bestPredictionCanvas.current
5801
5824
  });
5802
5825
  }, []);
5803
- var _f = React.useState(0),
5804
- canvasKey = _f[0],
5805
- setCanvasKey = _f[1];
5826
+ var getBestBarcode = React.useCallback(function () {
5827
+ if (!bestBarcodeDetails.current || !bestBarcodeCanvas.current) return null;
5828
+ return _assign(_assign({}, bestBarcodeDetails.current), {
5829
+ canvas: bestBarcodeCanvas.current
5830
+ });
5831
+ }, []);
5832
+ var _j = React.useState(0),
5833
+ canvasKey = _j[0],
5834
+ setCanvasKey = _j[1];
5806
5835
  var resetBestFrame = React.useCallback(function () {
5807
5836
  stopDetection.current += 1;
5808
5837
  setCanvasKey(function (n) {
@@ -5818,16 +5847,45 @@ function IdCaptureModelsProviderInner(_a) {
5818
5847
  var load = React.useCallback(function () {
5819
5848
  loadDocumentDetectionModel();
5820
5849
  loadFocusModel();
5821
- }, [loadDocumentDetectionModel, loadFocusModel]);
5822
- var ready = documentDetectionModelState === 'ready' && focusModelState === 'ready';
5823
- var modelLoadState = ready ? 'ready' : documentDetectionModelState === 'warming' || focusModelState === 'warming' ? 'warming' : focusModelState === 'downloading' || documentDetectionModelState === 'downloading' ? 'downloading' : 'not-started';
5824
- var modelWarmingStartedAt = !documentDetectionModelWarmingStartedAt && !focusModelWarmingStartedAt ? null : Math.min.apply(Math, [documentDetectionModelWarmingStartedAt, focusModelWarmingStartedAt].filter(function (v) {
5825
- return v !== null;
5826
- }));
5850
+ if (enableBarcodeReadabilityModel) loadBarcodeReadabilityModel();
5851
+ }, [enableBarcodeReadabilityModel, loadBarcodeReadabilityModel, loadDocumentDetectionModel, loadFocusModel]);
5852
+ var _k = React.useMemo(function () {
5853
+ var modelStates = [documentDetectionModelState, focusModelState];
5854
+ var modelWarmingStartedAts = [documentDetectionModelWarmingStartedAt, focusModelWarmingStartedAt];
5855
+ var modelDownloadProgresses = [documentDetectionModelDownloadProgress, focusModelDownloadProgress];
5856
+ if (enableBarcodeReadabilityModel) {
5857
+ modelStates.push(barcodeReadabilityModelState);
5858
+ modelWarmingStartedAts.push(barcodeReadabilityModelWarmingStartedAt);
5859
+ modelDownloadProgresses.push(barcodeReadabilityModelDownloadProgress);
5860
+ }
5861
+ var ready = modelStates.every(function (state) {
5862
+ return state === 'ready';
5863
+ });
5864
+ return {
5865
+ ready: ready,
5866
+ modelLoadState: ready ? 'ready' : modelStates.some(function (state) {
5867
+ return state === 'warming';
5868
+ }) ? 'warming' : modelStates.some(function (state) {
5869
+ return state === 'downloading';
5870
+ }) ? 'downloading' : 'not-started',
5871
+ modelWarmingStartedAt: modelWarmingStartedAts.every(function (v) {
5872
+ return v === null;
5873
+ }) ? null : Math.min.apply(Math, modelWarmingStartedAts.filter(function (v) {
5874
+ return v !== null;
5875
+ })),
5876
+ modelDownloadProgress: modelDownloadProgresses.reduce(function (a, b) {
5877
+ return a + b;
5878
+ }, 0) / modelDownloadProgresses.length
5879
+ };
5880
+ }, [barcodeReadabilityModelDownloadProgress, barcodeReadabilityModelState, barcodeReadabilityModelWarmingStartedAt, documentDetectionModelDownloadProgress, documentDetectionModelState, documentDetectionModelWarmingStartedAt, enableBarcodeReadabilityModel, focusModelDownloadProgress, focusModelState, focusModelWarmingStartedAt]),
5881
+ ready = _k.ready,
5882
+ modelLoadState = _k.modelLoadState,
5883
+ modelWarmingStartedAt = _k.modelWarmingStartedAt,
5884
+ modelDownloadProgress = _k.modelDownloadProgress;
5827
5885
  var value = React.useMemo(function () {
5828
5886
  return {
5829
5887
  ready: ready,
5830
- modelDownloadProgress: (documentDetectionModelDownloadProgress + focusModelDownloadProgress) / 2,
5888
+ modelDownloadProgress: modelDownloadProgress,
5831
5889
  modelLoadState: modelLoadState,
5832
5890
  modelWarmingStartedAt: modelWarmingStartedAt,
5833
5891
  modelError: modelError,
@@ -5841,24 +5899,32 @@ function IdCaptureModelsProviderInner(_a) {
5841
5899
  onPredictionMade: onPredictionMade,
5842
5900
  detectionTime: detectionTime,
5843
5901
  focusPredictionTime: focusPredictionTime,
5902
+ barcodeReadabilityPredictionTime: barcodeReadabilityPredictionTime,
5844
5903
  getBestFrame: getBestFrame,
5845
5904
  resetBestFrame: resetBestFrame,
5846
5905
  bestFrameDetails: bestFrameDetails,
5906
+ bestBarcodeDetails: bestBarcodeDetails,
5907
+ getBestBarcode: getBestBarcode,
5847
5908
  requiredDocumentType: requiredDocumentType,
5848
5909
  setRequiredDocumentType: setRequiredDocumentType
5849
5910
  };
5850
- }, [detectionTime, documentDetectionBoundaries, documentDetectionModelDownloadProgress, focusModelDownloadProgress, focusPredictionTime, getBestFrame, load, modelLoadState, modelError, modelWarmingStartedAt, onPredictionMade, ready, requiredDocumentType, resetBestFrame, setDocumentDetectionBoundaries, setThresholds, startDocumentDetection, stopDocumentDetection, thresholds]);
5911
+ }, [ready, modelDownloadProgress, modelLoadState, modelWarmingStartedAt, modelError, startDocumentDetection, stopDocumentDetection, load, thresholds, setThresholds, documentDetectionBoundaries, setDocumentDetectionBoundaries, onPredictionMade, detectionTime, focusPredictionTime, barcodeReadabilityPredictionTime, getBestFrame, resetBestFrame, getBestBarcode, requiredDocumentType]);
5851
5912
  return /*#__PURE__*/React__namespace.default.createElement(IdCaptureModelsContext.Provider, {
5852
5913
  value: value
5853
5914
  }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5854
- key: canvasKey,
5915
+ key: "bf-".concat(canvasKey),
5855
5916
  ref: bestPredictionCanvas
5917
+ }), /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5918
+ key: "bb-".concat(canvasKey),
5919
+ ref: bestBarcodeCanvas
5856
5920
  }), children);
5857
5921
  }
5858
5922
  function IdCaptureModelsProvider(_a) {
5859
5923
  var children = _a.children,
5860
5924
  props = __rest(_a, ["children"]);
5861
- 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)));
5925
+ 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, {
5926
+ shouldLoadModels: props.enableBarcodeReadabilityModel
5927
+ }), /*#__PURE__*/React__namespace.default.createElement(IdCaptureModelsProviderInner, _assign({}, props), children))));
5862
5928
  }
5863
5929
  function useIdCaptureModelsContext() {
5864
5930
  var context = React.useContext(IdCaptureModelsContext);
@@ -5868,7 +5934,7 @@ function useIdCaptureModelsContext() {
5868
5934
  return context;
5869
5935
  }
5870
5936
 
5871
- var CapturedDocumentTypeValues = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'selfie', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
5937
+ var CapturedDocumentTypeValues = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'selfie', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage', 'idBarcodeImage'];
5872
5938
 
5873
5939
  var acceptedDocumentTypesForIdCaptureRequirementOption = {
5874
5940
  idCardFront: ['idCardFront'],
@@ -5954,6 +6020,7 @@ var initialState$5 = {
5954
6020
  capturing: false,
5955
6021
  captureFailed: false,
5956
6022
  imageUrl: null,
6023
+ idBarcodeImage: null,
5957
6024
  captureState: 'initializing',
5958
6025
  capturedDocuments: {},
5959
6026
  captureRequirement: 'idCardOrPassport',
@@ -6233,6 +6300,17 @@ var _reducer = function reducer(state, action) {
6233
6300
  }
6234
6301
  return newState;
6235
6302
  }
6303
+ case 'barcodeCaptured':
6304
+ return _reducer(state, {
6305
+ type: 'documentCaptured',
6306
+ payload: {
6307
+ imageData: action.payload.imageUrl,
6308
+ documentType: 'idBarcodeImage',
6309
+ width: 0,
6310
+ height: 0,
6311
+ barcodeReadabilityScore: action.payload.barcodeReadabilityScore
6312
+ }
6313
+ });
6236
6314
  case 'flipRequestCompleted':
6237
6315
  return _assign(_assign({}, state), {
6238
6316
  captureState: 'capturing',
@@ -6724,12 +6802,13 @@ var IdCapture = function IdCapture(_a) {
6724
6802
  height = _q === void 0 ? 1 : _q;
6725
6803
  var state = useIdCaptureStore();
6726
6804
  var isRearFacing = useCameraStore().isRearFacing;
6727
- var _r = React.useContext(IdCaptureModelsContext),
6805
+ var _r = useIdCaptureModelsContext(),
6728
6806
  modelsReady = _r.ready,
6729
6807
  setThresholds = _r.setThresholds,
6730
6808
  detectionTime = _r.detectionTime,
6731
6809
  focusPredictionTime = _r.focusPredictionTime,
6732
- getBestFrame = _r.getBestFrame;
6810
+ getBestFrame = _r.getBestFrame,
6811
+ getBestBarcode = _r.getBestBarcode;
6733
6812
  React.useEffect(function () {
6734
6813
  return dispatchIdCaptureAction({
6735
6814
  type: 'captureInitialized'
@@ -6768,6 +6847,16 @@ var IdCapture = function IdCapture(_a) {
6768
6847
  });
6769
6848
  return;
6770
6849
  }
6850
+ var bestBarcode = getBestBarcode();
6851
+ if (bestBarcode) {
6852
+ dispatchIdCaptureAction({
6853
+ type: 'barcodeCaptured',
6854
+ payload: {
6855
+ imageUrl: bestBarcode.canvas.toDataURL('image/jpeg', 0.95),
6856
+ barcodeReadabilityScore: bestBarcode.score
6857
+ }
6858
+ });
6859
+ }
6771
6860
  var canvas = bestFrame.canvas,
6772
6861
  documentType = bestFrame.documentType,
6773
6862
  boundingBox = bestFrame.boundingBox,
@@ -6784,21 +6873,22 @@ var IdCapture = function IdCapture(_a) {
6784
6873
  });
6785
6874
  var capturedDocumentType = documentType;
6786
6875
  setTimeout(function () {
6787
- var _a;
6788
- var captureTime = new Date().getTime() - ((_a = state.captureStartedAt) !== null && _a !== void 0 ? _a : new Date()).getTime();
6876
+ var _a, _b;
6877
+ var captureTime = performance.now() - ((_a = state.captureStartedAt) !== null && _a !== void 0 ? _a : new Date()).getTime();
6789
6878
  var metadata = {
6790
6879
  autoCapture: 'Y',
6791
6880
  captureTime: captureTime,
6792
6881
  boundingBox: boundingBox,
6793
6882
  bestDetectionScore: detectionScore,
6794
- bestFocusScore: focusScore
6883
+ bestFocusScore: focusScore,
6884
+ bestBarcodeScore: (_b = bestBarcode === null || bestBarcode === void 0 ? void 0 : bestBarcode.score) !== null && _b !== void 0 ? _b : 0
6795
6885
  };
6796
6886
  onCapture === null || onCapture === void 0 ? void 0 : onCapture(imageUrl, width, height, capturedDocumentType, metadata);
6797
6887
  dispatchIdCaptureAction({
6798
6888
  type: 'captured'
6799
6889
  });
6800
6890
  }, 0);
6801
- }, [getBestFrame, onCapture, shouldCapture, state.captureStartedAt, state.requestedDocumentType]);
6891
+ }, [getBestBarcode, getBestFrame, onCapture, shouldCapture, state.captureStartedAt, state.requestedDocumentType]);
6802
6892
  var theme = styled.useTheme();
6803
6893
  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');
6804
6894
  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');
@@ -7936,7 +8026,7 @@ var Card = styled__default.default.div(templateObject_1$E || (templateObject_1$E
7936
8026
  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"])));
7937
8027
  var templateObject_1$E, templateObject_2$y;
7938
8028
 
7939
- var imageDisplayOrder = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
8029
+ var imageDisplayOrder = ['idCardFront', 'idCardBack', 'idBarcodeImage', 'passport', 'singlePage', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
7940
8030
  var IdCaptureSuccess = function IdCaptureSuccess(_a) {
7941
8031
  var capturedDocuments = _a.capturedDocuments,
7942
8032
  onSubmitClick = _a.onSubmitClick,
@@ -7978,7 +8068,7 @@ var IdCaptureSuccess = function IdCaptureSuccess(_a) {
7978
8068
  image: doc,
7979
8069
  className: classNames.image,
7980
8070
  alt: doc.documentType
7981
- }), 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)))));
8071
+ }), 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)))));
7982
8072
  }))), /*#__PURE__*/React__namespace.default.createElement(ButtonsColumn, {
7983
8073
  className: classNames.buttonsRow
7984
8074
  }, /*#__PURE__*/React__namespace.default.createElement(WideButton, {
@@ -10590,7 +10680,7 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10590
10680
  var _5 = React.useState(false),
10591
10681
  overlayDismissed = _5[0],
10592
10682
  setOverlayDismissed = _5[1];
10593
- var _6 = React.useContext(SubmissionContext),
10683
+ var _6 = useSubmissionContext(),
10594
10684
  submissionStatus = _6.submissionStatus,
10595
10685
  setIdFrontImage = _6.setIdFrontImage,
10596
10686
  setIdBackImage = _6.setIdBackImage,
@@ -10599,6 +10689,7 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10599
10689
  setIdBackIrImage = _6.setIdBackIrImage,
10600
10690
  setIdFrontUvImage = _6.setIdFrontUvImage,
10601
10691
  setIdBackUvImage = _6.setIdBackUvImage,
10692
+ setIdBarcodeImage = _6.setIdBarcodeImage,
10602
10693
  logIdFrontCaptureAttempt = _6.logIdFrontCaptureAttempt,
10603
10694
  logIdBackCaptureAttempt = _6.logIdBackCaptureAttempt;
10604
10695
  var _7 = useIdCaptureModelsContext(),
@@ -10689,7 +10780,7 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10689
10780
  });
10690
10781
  }, [logCaptureMetadata, onDocumentCaptured]);
10691
10782
  var onSubmitClick = React.useCallback(function () {
10692
- var _a, _b, _c, _d, _e, _f, _g, _h;
10783
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
10693
10784
  var docs = state.capturedDocuments;
10694
10785
  var submission = {
10695
10786
  idFrontImage: maybeDataUrlToBase64Sync((_a = docs.idCardFront) === null || _a === void 0 ? void 0 : _a.imageData),
@@ -10699,7 +10790,8 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10699
10790
  idFrontIrImage: maybeDataUrlToBase64Sync((_e = docs.idFrontIrImage) === null || _e === void 0 ? void 0 : _e.imageData),
10700
10791
  idBackIrImage: maybeDataUrlToBase64Sync((_f = docs.idBackIrImage) === null || _f === void 0 ? void 0 : _f.imageData),
10701
10792
  idFrontUvImage: maybeDataUrlToBase64Sync((_g = docs.idFrontUvImage) === null || _g === void 0 ? void 0 : _g.imageData),
10702
- idBackUvImage: maybeDataUrlToBase64Sync((_h = docs.idBackUvImage) === null || _h === void 0 ? void 0 : _h.imageData)
10793
+ idBackUvImage: maybeDataUrlToBase64Sync((_h = docs.idBackUvImage) === null || _h === void 0 ? void 0 : _h.imageData),
10794
+ idBarcodeImage: maybeDataUrlToBase64Sync((_j = docs.idBarcodeImage) === null || _j === void 0 ? void 0 : _j.imageData)
10703
10795
  };
10704
10796
  if (submission.idFrontImage) setIdFrontImage(submission.idFrontImage);
10705
10797
  if (submission.idBackImage) setIdBackImage(submission.idBackImage);
@@ -10709,11 +10801,12 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10709
10801
  if (submission.idBackIrImage) setIdBackIrImage(submission.idBackIrImage);
10710
10802
  if (submission.idFrontUvImage) setIdFrontUvImage(submission.idFrontUvImage);
10711
10803
  if (submission.idBackUvImage) setIdBackUvImage(submission.idBackUvImage);
10804
+ if (submission.idBarcodeImage) setIdBarcodeImage(submission.idBarcodeImage);
10712
10805
  if (releaseCameraAccessOnExit) releaseCameraAccess();
10713
10806
  setTimeout(function () {
10714
10807
  return onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(submission);
10715
10808
  }, 0);
10716
- }, [onSuccess, releaseCameraAccess, releaseCameraAccessOnExit, setIdBackImage, setIdBackIrImage, setIdBackUvImage, setIdFrontImage, setIdFrontIrImage, setIdFrontUvImage, setPassportImage, state.capturedDocuments]);
10809
+ }, [onSuccess, releaseCameraAccess, releaseCameraAccessOnExit, setIdBarcodeImage, setIdBackImage, setIdBackIrImage, setIdBackUvImage, setIdFrontImage, setIdFrontIrImage, setIdFrontUvImage, setPassportImage, state.capturedDocuments]);
10717
10810
  var showSuccessScreen = useShowSuccessScreen(skipSuccessScreen, state.captureState === 'complete', onSubmitClick);
10718
10811
  var onRetryClick = React.useCallback(function () {
10719
10812
  return dispatchIdCaptureAction({
@@ -11515,47 +11608,315 @@ function SelfieCaptureAnimatedMaskWithStatus(_a) {
11515
11608
  setFrame(0);
11516
11609
  return;
11517
11610
  }
11518
- setFrame(1);
11519
- var interval = setInterval(function () {
11520
- setFrame(function (n) {
11521
- return (n + 1) % 6;
11611
+ setFrame(1);
11612
+ var interval = setInterval(function () {
11613
+ setFrame(function (n) {
11614
+ return (n + 1) % 6;
11615
+ });
11616
+ }, 250);
11617
+ return function () {
11618
+ clearInterval(interval);
11619
+ };
11620
+ }, [status]);
11621
+ return /*#__PURE__*/React__namespace.default.createElement(SelfieCaptureAnimatedMask, _assign({}, props, {
11622
+ frame: frame,
11623
+ status: status
11624
+ }));
11625
+ }
11626
+ var templateObject_1$p, templateObject_2$m, templateObject_3$g;
11627
+
11628
+ var FaceCaptureGuideContainer = styled__default.default.div(templateObject_1$o || (templateObject_1$o = __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"])));
11629
+ 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"])));
11630
+ var FaceCaptureGuideOverlay = function FaceCaptureGuideOverlay(_a) {
11631
+ var _b = _a.classNames,
11632
+ classNames = _b === void 0 ? {} : _b,
11633
+ _c = _a.status,
11634
+ status = _c === void 0 ? 'ready' : _c,
11635
+ _d = _a.borderWidth,
11636
+ borderWidth = _d === void 0 ? 5 : _d,
11637
+ _e = _a.borderColor,
11638
+ borderColor = _e === void 0 ? 'white' : _e,
11639
+ _f = _a.borderOpacity,
11640
+ borderOpacity = _f === void 0 ? 0.8 : _f;
11641
+ return /*#__PURE__*/React__namespace.default.createElement(FaceCaptureGuideContainer, {
11642
+ className: classNames.container
11643
+ }, /*#__PURE__*/React__namespace.default.createElement(FaceCaptureGuideInner, null, /*#__PURE__*/React__namespace.default.createElement(SelfieCaptureAnimatedMaskWithStatus, {
11644
+ status: status,
11645
+ borderColor: borderColor,
11646
+ borderWidth: borderWidth,
11647
+ borderOpacity: borderOpacity,
11648
+ verticalAlign: "center"
11649
+ })));
11650
+ };
11651
+ var templateObject_1$o, templateObject_2$l;
11652
+
11653
+ var defaultSelfieCaptureModelLoadTimeoutMs = 45000;
11654
+ var detector = null;
11655
+ var detectorSettings = null;
11656
+ function loadFaceDetector() {
11657
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
11658
+ var _a, _b;
11659
+ if (modelAssetPath === void 0) {
11660
+ modelAssetPath = defaultFaceDetectorModelPath;
11661
+ }
11662
+ return __generator(this, function (_c) {
11663
+ switch (_c.label) {
11664
+ case 0:
11665
+ if (detector && (detectorSettings === null || detectorSettings === void 0 ? void 0 : detectorSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, detector];
11666
+ closeFaceDetector();
11667
+ return [4 /*yield*/, preloadFaceDetectorDependencies()];
11668
+ case 1:
11669
+ _c.sent();
11670
+ if (modelCapabilities.delegate === 'NONE') {
11671
+ throw new Error('No available delegate for face detector.');
11672
+ }
11673
+ _b = (_a = tasksVision.FaceDetector).createFromOptions;
11674
+ return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
11675
+ case 2:
11676
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
11677
+ // canvas: document.createElement('canvas'),
11678
+ baseOptions: {
11679
+ modelAssetPath: modelAssetPath,
11680
+ delegate: modelCapabilities.delegate
11681
+ },
11682
+ runningMode: 'VIDEO'
11683
+ }])];
11684
+ case 3:
11685
+ detector = _c.sent();
11686
+ detectorSettings = {
11687
+ modelAssetPath: modelAssetPath
11688
+ };
11689
+ return [2 /*return*/, detector];
11690
+ }
11691
+ });
11692
+ });
11693
+ }
11694
+ function closeFaceDetector() {
11695
+ detector === null || detector === void 0 ? void 0 : detector.close();
11696
+ detector = null;
11697
+ detectorSettings = null;
11698
+ }
11699
+ function useLoadFaceDetector(_a) {
11700
+ var onModelError = _a.onModelError,
11701
+ _b = _a.modelLoadTimeoutMs,
11702
+ modelLoadTimeoutMs = _b === void 0 ? defaultSelfieCaptureModelLoadTimeoutMs : _b,
11703
+ videoRef = _a.videoRef;
11704
+ var _c = React.useState('not-started'),
11705
+ modelLoadState = _c[0],
11706
+ setModelLoadState = _c[1];
11707
+ var _d = React.useState(0),
11708
+ modelDownloadProgress = _d[0],
11709
+ setModelDownloadProgress = _d[1];
11710
+ var _e = React.useState(null),
11711
+ modelWarmingStartedAt = _e[0],
11712
+ setModelWarmingStartedAt = _e[1];
11713
+ var _f = React.useState(null),
11714
+ modelError = _f[0],
11715
+ setModelError = _f[1];
11716
+ React.useEffect(function loadModel() {
11717
+ var _this = this;
11718
+ setModelLoadState('downloading');
11719
+ setModelWarmingStartedAt(null);
11720
+ var modelLoadTimeout = setTimeout(function () {
11721
+ setModelError(new Error('Model loading time limit exceeded.'));
11722
+ }, modelLoadTimeoutMs);
11723
+ function handleDownloadProgress(event) {
11724
+ setModelDownloadProgress(progressToPercentage(event.detail));
11725
+ }
11726
+ document.addEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
11727
+ var cancelVideoReady = function cancelVideoReady() {};
11728
+ loadFaceDetector().then(function (model) {
11729
+ return __awaiter(_this, void 0, void 0, function () {
11730
+ var _a, videoReady, cancel, cancelled;
11731
+ return __generator(this, function (_b) {
11732
+ switch (_b.label) {
11733
+ case 0:
11734
+ setModelDownloadProgress(100);
11735
+ clearTimeout(modelLoadTimeout);
11736
+ setModelLoadState('warming');
11737
+ setModelWarmingStartedAt(performance.now());
11738
+ return [4 /*yield*/, testFaceDetectionAgainstKnownImage(model)];
11739
+ case 1:
11740
+ _b.sent();
11741
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
11742
+ cancelled = false;
11743
+ cancelVideoReady = function cancelVideoReady() {
11744
+ cancelled = true;
11745
+ cancel();
11746
+ };
11747
+ return [4 /*yield*/, videoReady];
11748
+ case 2:
11749
+ _b.sent();
11750
+ if (cancelled) return [2 /*return*/];
11751
+ model.detectForVideo(videoRef.current, performance.now());
11752
+ setModelLoadState('ready');
11753
+ return [2 /*return*/];
11754
+ }
11755
+ });
11522
11756
  });
11523
- }, 250);
11757
+ })["catch"](function (e) {
11758
+ setModelError(e);
11759
+ setModelLoadState('error');
11760
+ })["finally"](function () {
11761
+ clearTimeout(modelLoadTimeout);
11762
+ });
11524
11763
  return function () {
11525
- clearInterval(interval);
11764
+ log('unloading face detection model');
11765
+ cancelVideoReady();
11766
+ closeFaceDetector();
11767
+ clearTimeout(modelLoadTimeout);
11768
+ document.removeEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
11526
11769
  };
11527
- }, [status]);
11528
- return /*#__PURE__*/React__namespace.default.createElement(SelfieCaptureAnimatedMask, _assign({}, props, {
11529
- frame: frame,
11530
- status: status
11531
- }));
11770
+ }, [modelLoadTimeoutMs, videoRef]);
11771
+ React.useEffect(function handleModelError() {
11772
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
11773
+ }, [modelError, onModelError]);
11774
+ return React.useMemo(function () {
11775
+ return {
11776
+ ready: modelLoadState === 'ready',
11777
+ modelLoadState: modelLoadState,
11778
+ modelDownloadProgress: modelDownloadProgress,
11779
+ modelWarmingStartedAt: modelWarmingStartedAt,
11780
+ modelError: modelError
11781
+ };
11782
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
11783
+ }
11784
+ var lastFaceDetectionAt = 0;
11785
+ var lastFaceDetectionTime = 0;
11786
+ function setLastFaceDetectionAt(time) {
11787
+ lastFaceDetectionTime = time - lastFaceDetectionAt;
11788
+ lastFaceDetectionAt = time;
11789
+ }
11790
+ var framesNeededSamples = [];
11791
+ function trackFramesNeeded(value, bufferLength) {
11792
+ if (bufferLength === void 0) {
11793
+ bufferLength = 25;
11794
+ }
11795
+ framesNeededSamples.unshift(value);
11796
+ if (framesNeededSamples.length > bufferLength) framesNeededSamples.length = bufferLength;
11797
+ }
11798
+ var lastNFaces = [];
11799
+ var lastNPairs = [];
11800
+ function trackFace(face, framesNeeded) {
11801
+ if (framesNeeded === void 0) {
11802
+ framesNeeded = 12;
11803
+ }
11804
+ lastNFaces.unshift(face);
11805
+ if (lastNFaces.length > framesNeeded) lastNFaces.length = framesNeeded;
11806
+ if (lastNFaces.length > 1) {
11807
+ var lastFace = lastNFaces[1];
11808
+ var iou = calculateIoU(face.box, lastFace.box);
11809
+ lastNPairs.unshift({
11810
+ a: face,
11811
+ b: lastFace,
11812
+ iou: iou
11813
+ });
11814
+ if (lastNPairs.length > framesNeeded - 1) lastNPairs.length = framesNeeded - 1;
11815
+ }
11816
+ }
11817
+ function makeFaceDetectorPrediction(imageData) {
11818
+ if (!detector) return null;
11819
+ var prediction = detector.detectForVideo(imageData, performance.now());
11820
+ var faces = prediction.detections.map(function (d) {
11821
+ return {
11822
+ box: convertBoundingBox(d.boundingBox),
11823
+ keypoints: d.keypoints.map(function (k) {
11824
+ var _a;
11825
+ return _assign(_assign({}, k), {
11826
+ x: k.x * imageData.width,
11827
+ y: k.y * imageData.height,
11828
+ name: (_a = k.label) !== null && _a !== void 0 ? _a : ''
11829
+ });
11830
+ })
11831
+ };
11832
+ });
11833
+ return _assign(_assign({}, prediction), {
11834
+ faces: faces
11835
+ });
11836
+ }
11837
+ function processFaceDetectorPrediction(_a) {
11838
+ var faces = _a.faces,
11839
+ videoWidth = _a.videoWidth,
11840
+ videoHeight = _a.videoHeight,
11841
+ _b = _a.requireVerticalFaceCentering,
11842
+ requireVerticalFaceCentering = _b === void 0 ? true : _b,
11843
+ _c = _a.stabilityThreshold,
11844
+ stabilityThreshold = _c === void 0 ? 0.7 : _c;
11845
+ var face = faces[0];
11846
+ var faceNotDetected = faces.length === 0;
11847
+ var faceNotCentered = false,
11848
+ faceLookingAway = false,
11849
+ faceTooClose = false,
11850
+ faceTooFar = false;
11851
+ if (face) {
11852
+ // calculate centroids
11853
+ var vCX = videoWidth / 2;
11854
+ var vCY = videoHeight / 2;
11855
+ var fCX = (face.box.xMin + face.box.xMax) / 2;
11856
+ var fCY = (face.box.yMin + face.box.yMax) / 2;
11857
+ // calculate thresholds
11858
+ var vTX = videoWidth * 0.125;
11859
+ var vTY = videoHeight * 0.125;
11860
+ var fTW = face.box.width * 0.2;
11861
+ var fTH = face.box.height * 0.2;
11862
+ var nose = face.keypoints[2]; //.find((k) => k.name === 'noseTip')
11863
+ if (nose) {
11864
+ faceLookingAway = Math.abs(fCX - nose.x) > fTW || Math.abs(fCY - nose.y) > fTH;
11865
+ var faceNotCenteredHorizontally = Math.abs(vCX - fCX) > vTX;
11866
+ var faceNotCenteredVertically = Math.abs(vCY + 50 - fCY) > vTY;
11867
+ faceNotCentered = faceNotCenteredHorizontally || requireVerticalFaceCentering && faceNotCenteredVertically;
11868
+ }
11869
+ var isMobile = videoWidth < videoHeight;
11870
+ var tooCloseMultiple = 1.5;
11871
+ var tooFarMultiple = isMobile ? 6 : 7;
11872
+ faceTooClose = face.box.width > videoWidth / tooCloseMultiple;
11873
+ faceTooFar = face.box.width < videoWidth / tooFarMultiple;
11874
+ }
11875
+ var faceInGuides = !faceNotDetected && !faceNotCentered && !faceLookingAway && !faceTooClose && !faceTooFar;
11876
+ if (lastFaceDetectionTime > 0) {
11877
+ trackFramesNeeded(500 / lastFaceDetectionTime);
11878
+ }
11879
+ var faceIsStable = false;
11880
+ if (faceInGuides) {
11881
+ var framesNeeded = Math.ceil(average(framesNeededSamples));
11882
+ trackFace(face, framesNeeded);
11883
+ faceIsStable = lastNFaces.length >= framesNeeded && !lastNPairs.some(function (pair) {
11884
+ return pair.iou < stabilityThreshold;
11885
+ });
11886
+ }
11887
+ var faceReady = faceInGuides && faceIsStable;
11888
+ return {
11889
+ face: face,
11890
+ faceNotDetected: faceNotDetected,
11891
+ faceNotCentered: faceNotCentered,
11892
+ faceLookingAway: faceLookingAway,
11893
+ faceTooClose: faceTooClose,
11894
+ faceTooFar: faceTooFar,
11895
+ faceReady: faceReady,
11896
+ faceReadyAt: faceReady ? new Date() : null,
11897
+ faceIsStable: faceIsStable
11898
+ };
11899
+ }
11900
+ function testFaceDetectionAgainstKnownImage(detector) {
11901
+ return new Promise(function (resolve, reject) {
11902
+ var img = new Image();
11903
+ img.crossOrigin = 'anonymous';
11904
+ img.onload = function () {
11905
+ var prediction = detector.detectForVideo(img, performance.now());
11906
+ if (prediction.detections.length > 0) {
11907
+ debug('face detection test result', prediction.detections);
11908
+ resolve(void 0);
11909
+ } else {
11910
+ warn('face detection test failed');
11911
+ reject(new Error('testFaceDetectionAgainstKnownImage failed to predict'));
11912
+ }
11913
+ };
11914
+ img.onerror = function () {
11915
+ return reject(new Error('testFaceDetectionAgainstKnownImage failed to load image'));
11916
+ };
11917
+ img.src = "".concat(DEFAULT_CDN_URL, "/head-test.jpg");
11918
+ });
11532
11919
  }
11533
- var templateObject_1$p, templateObject_2$m, templateObject_3$g;
11534
-
11535
- var FaceCaptureGuideContainer = styled__default.default.div(templateObject_1$o || (templateObject_1$o = __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"])));
11536
- 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"])));
11537
- var FaceCaptureGuideOverlay = function FaceCaptureGuideOverlay(_a) {
11538
- var _b = _a.classNames,
11539
- classNames = _b === void 0 ? {} : _b,
11540
- _c = _a.status,
11541
- status = _c === void 0 ? 'ready' : _c,
11542
- _d = _a.borderWidth,
11543
- borderWidth = _d === void 0 ? 5 : _d,
11544
- _e = _a.borderColor,
11545
- borderColor = _e === void 0 ? 'white' : _e,
11546
- _f = _a.borderOpacity,
11547
- borderOpacity = _f === void 0 ? 0.8 : _f;
11548
- return /*#__PURE__*/React__namespace.default.createElement(FaceCaptureGuideContainer, {
11549
- className: classNames.container
11550
- }, /*#__PURE__*/React__namespace.default.createElement(FaceCaptureGuideInner, null, /*#__PURE__*/React__namespace.default.createElement(SelfieCaptureAnimatedMaskWithStatus, {
11551
- status: status,
11552
- borderColor: borderColor,
11553
- borderWidth: borderWidth,
11554
- borderOpacity: borderOpacity,
11555
- verticalAlign: "center"
11556
- })));
11557
- };
11558
- var templateObject_1$o, templateObject_2$l;
11559
11920
 
11560
11921
  var SelfieGuidanceModelsContext = /*#__PURE__*/React.createContext({
11561
11922
  start: function start() {