idmission-web-sdk 2.3.88 → 2.3.90

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) 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 +8 -0
  18. package/dist/components/submission/SubmissionProvider.d.ts.map +1 -1
  19. package/dist/components/submission/types.d.ts +4 -0
  20. package/dist/components/submission/types.d.ts.map +1 -1
  21. package/dist/components/video_signature_capture/VideoSignatureCapture.d.ts.map +1 -1
  22. package/dist/components/video_signature_capture/VideoSignatureContext.d.ts +7 -2
  23. package/dist/components/video_signature_capture/VideoSignatureContext.d.ts.map +1 -1
  24. package/dist/components/video_signature_capture/VideoSignatureGuides.d.ts.map +1 -1
  25. package/dist/components/video_signature_capture/VideoSignaturePad.d.ts.map +1 -1
  26. package/dist/components/video_signature_capture/VideoSignatureWizard.d.ts +1 -1
  27. package/dist/components/video_signature_capture/VideoSignatureWizard.d.ts.map +1 -1
  28. package/dist/lib/camera/useVideoRecorder.d.ts.map +1 -1
  29. package/dist/lib/models/BarcodeReadability.d.ts +50 -0
  30. package/dist/lib/models/BarcodeReadability.d.ts.map +1 -0
  31. package/dist/lib/models/DocumentDetection.d.ts +1 -0
  32. package/dist/lib/models/DocumentDetection.d.ts.map +1 -1
  33. package/dist/lib/models/Focus.d.ts.map +1 -1
  34. package/dist/lib/models/defaults/BarcodeReadability.d.ts +2 -0
  35. package/dist/lib/models/defaults/BarcodeReadability.d.ts.map +1 -0
  36. package/dist/lib/models/defaults/index.d.ts +7 -0
  37. package/dist/lib/models/defaults/index.d.ts.map +1 -1
  38. package/dist/lib/models/preloadModels.d.ts +9 -5
  39. package/dist/lib/models/preloadModels.d.ts.map +1 -1
  40. package/dist/lib/utils/blobs.d.ts +3 -0
  41. package/dist/lib/utils/blobs.d.ts.map +1 -0
  42. package/dist/lib/utils/cropping.d.ts +3 -1
  43. package/dist/lib/utils/cropping.d.ts.map +1 -1
  44. package/dist/sdk2.cjs.development.js +1759 -1151
  45. package/dist/sdk2.cjs.development.js.map +1 -1
  46. package/dist/sdk2.cjs.production.js +1 -1
  47. package/dist/sdk2.cjs.production.js.map +1 -1
  48. package/dist/sdk2.esm.js +1760 -1152
  49. package/dist/sdk2.esm.js.map +1 -1
  50. package/dist/sdk2.umd.development.js +1759 -1151
  51. package/dist/sdk2.umd.development.js.map +1 -1
  52. package/dist/sdk2.umd.production.js +1 -1
  53. package/dist/sdk2.umd.production.js.map +1 -1
  54. package/dist/version.d.ts +1 -1
  55. 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.88';
239
+ var webSdkVersion = '2.3.90';
240
240
 
241
241
  function getPlatform() {
242
242
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -497,27 +497,27 @@ var GuidanceMessageContainer = function GuidanceMessageContainer(props) {
497
497
  if (!portalLocation) return element;
498
498
  return /*#__PURE__*/reactDom.createPortal(element, portalLocation);
499
499
  };
500
- var GuidanceMessage = styled__default.default.div(templateObject_2$I || (templateObject_2$I = __makeTemplateObject(["\n margin-left: auto;\n margin-right: auto;\n background: ", ";\n color: ", ";\n border-radius: 8px;\n z-index: 10001;\n padding: 16px 24px;\n font-size: 18px;\n font-weight: bold;\n box-shadow:\n 0 1px 3px 0 rgb(0 0 0 / 0.1),\n 0 1px 2px -1px rgb(0 0 0 / 0.1);\n"], ["\n margin-left: auto;\n margin-right: auto;\n background: ", ";\n color: ", ";\n border-radius: 8px;\n z-index: 10001;\n padding: 16px 24px;\n font-size: 18px;\n font-weight: bold;\n box-shadow:\n 0 1px 3px 0 rgb(0 0 0 / 0.1),\n 0 1px 2px -1px rgb(0 0 0 / 0.1);\n"])), function (props) {
500
+ var GuidanceMessage = styled__default.default.div(templateObject_2$J || (templateObject_2$J = __makeTemplateObject(["\n margin-left: auto;\n margin-right: auto;\n background: ", ";\n color: ", ";\n border-radius: 8px;\n z-index: 10001;\n padding: 16px 24px;\n font-size: 18px;\n font-weight: bold;\n box-shadow:\n 0 1px 3px 0 rgb(0 0 0 / 0.1),\n 0 1px 2px -1px rgb(0 0 0 / 0.1);\n"], ["\n margin-left: auto;\n margin-right: auto;\n background: ", ";\n color: ", ";\n border-radius: 8px;\n z-index: 10001;\n padding: 16px 24px;\n font-size: 18px;\n font-weight: bold;\n box-shadow:\n 0 1px 3px 0 rgb(0 0 0 / 0.1),\n 0 1px 2px -1px rgb(0 0 0 / 0.1);\n"])), function (props) {
501
501
  var _a, _b, _c, _d, _e, _f;
502
502
  return (_f = (_a = props.$background) !== null && _a !== void 0 ? _a : (_e = (_c = (_b = props.theme) === null || _b === void 0 ? void 0 : _b.guidanceMessages) === null || _c === void 0 ? void 0 : _c[(_d = props.$variant) !== null && _d !== void 0 ? _d : 'default']) === null || _e === void 0 ? void 0 : _e.backgroundColor) !== null && _f !== void 0 ? _f : 'white';
503
503
  }, function (props) {
504
504
  var _a, _b, _c, _d, _e, _f;
505
505
  return (_f = (_a = props.$textColor) !== null && _a !== void 0 ? _a : (_e = (_c = (_b = props.theme) === null || _b === void 0 ? void 0 : _b.guidanceMessages) === null || _c === void 0 ? void 0 : _c[(_d = props.$variant) !== null && _d !== void 0 ? _d : 'default']) === null || _e === void 0 ? void 0 : _e.textColor) !== null && _f !== void 0 ? _f : 'black';
506
506
  });
507
- var templateObject_1$P, templateObject_2$I;
507
+ var templateObject_1$P, templateObject_2$J;
508
508
 
509
509
  var wavesAnimation = styled.keyframes(templateObject_1$O || (templateObject_1$O = __makeTemplateObject(["\n 0% {\n opacity: 0;\n transform: scale3d(1, 1, 1);\n }\n 80% {\n opacity: 1;\n }\n 100% {\n transform: scale3d(2, 2, 1);\n opacity: 0;\n }\n"], ["\n 0% {\n opacity: 0;\n transform: scale3d(1, 1, 1);\n }\n 80% {\n opacity: 1;\n }\n 100% {\n transform: scale3d(2, 2, 1);\n opacity: 0;\n }\n"])));
510
- var progressBarAnimation = styled.keyframes(templateObject_2$H || (templateObject_2$H = __makeTemplateObject(["\n 0% {\n width: 0;\n }\n 100% {\n width: 100%;\n }\n"], ["\n 0% {\n width: 0;\n }\n 100% {\n width: 100%;\n }\n"])));
510
+ var progressBarAnimation = styled.keyframes(templateObject_2$I || (templateObject_2$I = __makeTemplateObject(["\n 0% {\n width: 0;\n }\n 100% {\n width: 100%;\n }\n"], ["\n 0% {\n width: 0;\n }\n 100% {\n width: 100%;\n }\n"])));
511
511
  var dualRingSpinnerAnimation = styled.keyframes(templateObject_3$u || (templateObject_3$u = __makeTemplateObject(["\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n"], ["\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n"])));
512
512
  var progressBorderAnimation = styled.keyframes(templateObject_4$o || (templateObject_4$o = __makeTemplateObject(["\n to {\n stroke-dashoffset: 0;\n }\n"], ["\n to {\n stroke-dashoffset: 0;\n }\n"])));
513
- var templateObject_1$O, templateObject_2$H, templateObject_3$u, templateObject_4$o;
513
+ var templateObject_1$O, templateObject_2$I, templateObject_3$u, templateObject_4$o;
514
514
 
515
515
  var OverlayContainer = styled__default.default.div(templateObject_1$N || (templateObject_1$N = __makeTemplateObject(["\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n display: flex;\n flex-direction: column;\n\n overflow-x: hidden;\n overflow-y: auto;\n\n background: ", ";\n ", "\n\n z-index: 10000;\n"], ["\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n\n display: flex;\n flex-direction: column;\n\n overflow-x: hidden;\n overflow-y: auto;\n\n background: ", ";\n ", "\n\n z-index: 10000;\n"])), function (props) {
516
516
  return props.theme.background ? "".concat(props.theme.background) : "white";
517
517
  }, function (props) {
518
518
  return props.theme.textColor ? "color: ".concat(props.theme.textColor, ";") : "";
519
519
  });
520
- var OverlayInner$2 = styled__default.default.div(templateObject_2$G || (templateObject_2$G = __makeTemplateObject(["\n text-align: ", ";\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n width: 100%;\n height: 100%;\n ", "\n"], ["\n text-align: ", ";\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n width: 100%;\n height: 100%;\n ", "\n"])), function (props) {
520
+ var OverlayInner$2 = styled__default.default.div(templateObject_2$H || (templateObject_2$H = __makeTemplateObject(["\n text-align: ", ";\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n width: 100%;\n height: 100%;\n ", "\n"], ["\n text-align: ", ";\n display: flex;\n flex-direction: column;\n flex-wrap: nowrap;\n width: 100%;\n height: 100%;\n ", "\n"])), function (props) {
521
521
  var _a;
522
522
  return (_a = props.theme.textAlign) !== null && _a !== void 0 ? _a : 'center';
523
523
  }, function (props) {
@@ -565,7 +565,7 @@ var LoadingOverlayLoadingListItem = styled__default.default.li(templateObject_19
565
565
  var LoadingOverlayProgressContainer = styled__default.default.div(templateObject_20 || (templateObject_20 = __makeTemplateObject(["\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n"], ["\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n"])));
566
566
  var LoadingOverlayCustomLoadingGraphic = styled__default.default.img(templateObject_21 || (templateObject_21 = __makeTemplateObject(["\n transform-style: preserve-3d;\n"], ["\n transform-style: preserve-3d;\n"])));
567
567
  var LoadingOverlayContinueButtonContainer = styled__default.default.div(templateObject_22 || (templateObject_22 = __makeTemplateObject(["\n display: flex;\n"], ["\n display: flex;\n"])));
568
- var templateObject_1$N, templateObject_2$G, templateObject_3$t, templateObject_4$n, templateObject_5$f, templateObject_6$9, templateObject_7$5, templateObject_8$4, templateObject_9$2, templateObject_10$1, templateObject_11$1, templateObject_12$1, templateObject_13$1, templateObject_14, templateObject_15, templateObject_16, templateObject_17, templateObject_18, templateObject_19, templateObject_20, templateObject_21, templateObject_22;
568
+ var templateObject_1$N, templateObject_2$H, templateObject_3$t, templateObject_4$n, templateObject_5$f, templateObject_6$9, templateObject_7$5, templateObject_8$4, templateObject_9$2, templateObject_10$1, templateObject_11$1, templateObject_12$1, templateObject_13$1, templateObject_14, templateObject_15, templateObject_16, templateObject_17, templateObject_18, templateObject_19, templateObject_20, templateObject_21, templateObject_22;
569
569
 
570
570
  var GeolocationAccessDeniedOverlay = function GeolocationAccessDeniedOverlay(_a) {
571
571
  var accessBlockedImageUrl = _a.accessBlockedImageUrl;
@@ -1134,6 +1134,11 @@ var SubmissionContext = /*#__PURE__*/React.createContext({
1134
1134
  idFrontImage: null,
1135
1135
  idBackImage: null,
1136
1136
  passportImage: null,
1137
+ idFrontIrImage: null,
1138
+ idBackIrImage: null,
1139
+ idFrontUvImage: null,
1140
+ idBackUvImage: null,
1141
+ idBarcodeImage: null,
1137
1142
  selfieImage: null,
1138
1143
  signatureData: null,
1139
1144
  signatureVideoUrl: null,
@@ -1164,6 +1169,9 @@ var SubmissionContext = /*#__PURE__*/React.createContext({
1164
1169
  setIdBackUvImage: function setIdBackUvImage() {
1165
1170
  return null;
1166
1171
  },
1172
+ setIdBarcodeImage: function setIdBarcodeImage() {
1173
+ return null;
1174
+ },
1167
1175
  setSelfieImage: function setSelfieImage() {
1168
1176
  return null;
1169
1177
  },
@@ -1176,6 +1184,12 @@ var SubmissionContext = /*#__PURE__*/React.createContext({
1176
1184
  setIdCaptureVideoUrl: function setIdCaptureVideoUrl() {
1177
1185
  return null;
1178
1186
  },
1187
+ setSignatureStartTimestamp: function setSignatureStartTimestamp() {
1188
+ return null;
1189
+ },
1190
+ setSignatureEndTimestamp: function setSignatureEndTimestamp() {
1191
+ return null;
1192
+ },
1179
1193
  setIdCaptureVideoIdFrontImage: function setIdCaptureVideoIdFrontImage() {
1180
1194
  return null;
1181
1195
  },
@@ -1331,53 +1345,62 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1331
1345
  passportImage = _13[0],
1332
1346
  setPassportImage = _13[1];
1333
1347
  var _14 = React.useState(null),
1334
- selfieImage = _14[0],
1335
- setSelfieImage = _14[1];
1348
+ idBarcodeImage = _14[0],
1349
+ setIdBarcodeImage = _14[1];
1336
1350
  var _15 = React.useState(null),
1337
- signatureData = _15[0],
1338
- setSignatureData = _15[1];
1351
+ selfieImage = _15[0],
1352
+ setSelfieImage = _15[1];
1339
1353
  var _16 = React.useState(null),
1340
- signatureVideoUrl = _16[0],
1341
- setSignatureVideoUrl = _16[1];
1354
+ signatureData = _16[0],
1355
+ setSignatureData = _16[1];
1342
1356
  var _17 = React.useState(null),
1343
- idCaptureVideoUrl = _17[0],
1344
- setIdCaptureVideoUrl = _17[1];
1357
+ signatureVideoUrl = _17[0],
1358
+ setSignatureVideoUrl = _17[1];
1345
1359
  var _18 = React.useState(null),
1346
- idCaptureVideoIdFrontImage = _18[0],
1347
- setIdCaptureVideoIdFrontImage = _18[1];
1360
+ signatureStartTimestamp = _18[0],
1361
+ setSignatureStartTimestamp = _18[1];
1348
1362
  var _19 = React.useState(null),
1349
- idCaptureVideoIdBackImage = _19[0],
1350
- setIdCaptureVideoIdBackImage = _19[1];
1363
+ signatureEndTimestamp = _19[0],
1364
+ setSignatureEndTimestamp = _19[1];
1351
1365
  var _20 = React.useState(null),
1352
- idCaptureVideoAudioUrl = _20[0],
1353
- setIdCaptureVideoAudioUrl = _20[1];
1366
+ idCaptureVideoUrl = _20[0],
1367
+ setIdCaptureVideoUrl = _20[1];
1354
1368
  var _21 = React.useState(null),
1355
- idCaptureVideoAudioStartsAt = _21[0],
1356
- setIdCaptureVideoAudioStartsAt = _21[1];
1369
+ idCaptureVideoIdFrontImage = _21[0],
1370
+ setIdCaptureVideoIdFrontImage = _21[1];
1357
1371
  var _22 = React.useState(null),
1358
- expectedAudioText = _22[0],
1359
- setExpectedAudioText = _22[1];
1372
+ idCaptureVideoIdBackImage = _22[0],
1373
+ setIdCaptureVideoIdBackImage = _22[1];
1360
1374
  var _23 = React.useState(null),
1361
- additionalDocuments = _23[0],
1362
- setAdditionalDocuments = _23[1];
1375
+ idCaptureVideoAudioUrl = _23[0],
1376
+ setIdCaptureVideoAudioUrl = _23[1];
1363
1377
  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];
1375
- var _28 = React.useState([]),
1376
- idBackCaptureAttempts = _28[0],
1377
- setIdBackCaptureAttempts = _28[1];
1378
- var _29 = React.useState([]),
1379
- selfieCaptureAttempts = _29[0],
1380
- setSelfieCaptureAttempts = _29[1];
1378
+ idCaptureVideoAudioStartsAt = _24[0],
1379
+ setIdCaptureVideoAudioStartsAt = _24[1];
1380
+ var _25 = React.useState(null),
1381
+ expectedAudioText = _25[0],
1382
+ setExpectedAudioText = _25[1];
1383
+ var _26 = React.useState(null),
1384
+ additionalDocuments = _26[0],
1385
+ setAdditionalDocuments = _26[1];
1386
+ var _27 = React.useState(null),
1387
+ geolocationResult = _27[0],
1388
+ setGeolocationResult = _27[1];
1389
+ var _28 = React.useState(0),
1390
+ geolocationAttempts = _28[0],
1391
+ setGeolocationAttempts = _28[1];
1392
+ var _29 = React.useState(false),
1393
+ geolocationBlocked = _29[0],
1394
+ setGeolocationBlocked = _29[1];
1395
+ var _30 = React.useState([]),
1396
+ idFrontCaptureAttempts = _30[0],
1397
+ setIdFrontCaptureAttempts = _30[1];
1398
+ var _31 = React.useState([]),
1399
+ idBackCaptureAttempts = _31[0],
1400
+ setIdBackCaptureAttempts = _31[1];
1401
+ var _32 = React.useState([]),
1402
+ selfieCaptureAttempts = _32[0],
1403
+ setSelfieCaptureAttempts = _32[1];
1381
1404
  var logIdFrontCaptureAttempt = React.useCallback(function (attempt) {
1382
1405
  setIdFrontCaptureAttempts(function (attempts) {
1383
1406
  return __spreadArray(__spreadArray([], attempts, true), [attempt], false);
@@ -1503,6 +1526,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1503
1526
  idFrontImage: idFrontImage,
1504
1527
  idBackImage: idBackImage,
1505
1528
  passportImage: passportImage,
1529
+ idBarcodeImage: idBarcodeImage,
1506
1530
  selfieImage: selfieImage
1507
1531
  };
1508
1532
  _a = signatureVideoUrl;
@@ -1608,6 +1632,9 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1608
1632
  if (documents.passportImage) {
1609
1633
  submissionRequest.customerData.idData.idImageFront = documents.passportImage;
1610
1634
  }
1635
+ if (documents.idBarcodeImage) {
1636
+ submissionRequest.customerData.idData.idBarcodeImage = documents.idBarcodeImage;
1637
+ }
1611
1638
  if (documents.idFrontIrImage) {
1612
1639
  submissionRequest.customerData.idData.idFrontIrImage = documents.idFrontIrImage;
1613
1640
  }
@@ -1654,6 +1681,12 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1654
1681
  submissionRequest.customerData.signatureData.signatureVideo = documents.signatureVideo;
1655
1682
  }
1656
1683
  }
1684
+ if (signatureStartTimestamp) {
1685
+ submissionRequest.customerData.signatureStartTimestamp = signatureStartTimestamp;
1686
+ }
1687
+ if (signatureEndTimestamp) {
1688
+ submissionRequest.customerData.signatureEndTimestamp = signatureEndTimestamp;
1689
+ }
1657
1690
  if (additionalDocuments) {
1658
1691
  submissionRequest.customerData.additionalDocuments = additionalDocuments.map(function (d) {
1659
1692
  return _assign(_assign({}, d), {
@@ -1696,7 +1729,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1696
1729
  }
1697
1730
  });
1698
1731
  });
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]);
1732
+ }, [additionalDocuments, bypassAgeValidation, bypassNameMatching, cardData, clientRequestID, companyId, customerDataMatchConfig, deduplicationEnabled, deduplicationSynchronous, documentServiceUrl, enrollmentId, expectedAudioText, geolocationResult, idBackCaptureAttempts, idBackImage, idBackImageRequired, idBackIrImage, idBackUvImage, idBarcodeImage, idCaptureVideoAudioStartsAt, idCaptureVideoAudioUrl, idCaptureVideoIdBackImage, idCaptureVideoIdFrontImage, idCaptureVideoUrl, idCardForFaceMatch, idData, idFrontCaptureAttempts, idFrontImage, idFrontIrImage, idFrontUvImage, idImageResolutionCheck, jobId, manualReviewRequired, needImmediateResponse, passportImage, personalData, selfieCaptureAttempts, selfieImage, signatureData, signatureEndTimestamp, signatureStartTimestamp, signatureVideoUrl, uploadDocument, verifyIdWithExternalDatabases, webhooksClientTraceId, webhooksEnabled, webhooksFireOnReview, webhooksFireOnReviewURL, webhooksSendInputImages, webhooksSendProcessedImages, webhooksStripSpecialCharacters, webhooksURL]);
1700
1733
  var defaultOnSubmit = React.useCallback(function () {
1701
1734
  return __awaiter(void 0, void 0, void 0, function () {
1702
1735
  var submissionResponse_1, payload, host, endpoint, response, statusMessage, submissionResponse_2, e_1, err;
@@ -1974,6 +2007,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1974
2007
  idFrontUvImage: idFrontUvImage,
1975
2008
  idBackUvImage: idBackUvImage,
1976
2009
  passportImage: passportImage,
2010
+ idBarcodeImage: idBarcodeImage,
1977
2011
  selfieImage: selfieImage,
1978
2012
  signatureData: signatureData,
1979
2013
  signatureVideoUrl: signatureVideoUrl,
@@ -1990,9 +2024,12 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1990
2024
  setIdBackIrImage: setIdBackIrImage,
1991
2025
  setIdFrontUvImage: setIdFrontUvImage,
1992
2026
  setIdBackUvImage: setIdBackUvImage,
2027
+ setIdBarcodeImage: setIdBarcodeImage,
1993
2028
  setSelfieImage: setSelfieImage,
1994
2029
  setSignatureData: setSignatureData,
1995
2030
  setSignatureVideoUrl: setSignatureVideoUrl,
2031
+ setSignatureStartTimestamp: setSignatureStartTimestamp,
2032
+ setSignatureEndTimestamp: setSignatureEndTimestamp,
1996
2033
  setIdCaptureVideoUrl: setIdCaptureVideoUrl,
1997
2034
  setIdCaptureVideoIdFrontImage: setIdCaptureVideoIdFrontImage,
1998
2035
  setIdCaptureVideoIdBackImage: setIdCaptureVideoIdBackImage,
@@ -2008,7 +2045,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
2008
2045
  checkLiveness: checkLiveness,
2009
2046
  retryLocationAccess: retryLocationAccess
2010
2047
  };
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]);
2048
+ }, [additionalDocuments, checkLiveness, environment, idBackImage, idBackIrImage, idBackUvImage, idBarcodeImage, idCaptureVideoAudioStartsAt, idCaptureVideoAudioUrl, idCaptureVideoIdBackImage, idCaptureVideoIdFrontImage, idCaptureVideoUrl, idFrontImage, idFrontIrImage, idFrontUvImage, livenessCheckRequest, logIdBackCaptureAttempt, logIdFrontCaptureAttempt, logSelfieCaptureAttempt, passportImage, retryLocationAccess, selfieImage, signatureData, signatureVideoUrl, submissionError, submissionRequest, submissionResponse, submissionStatus, submit, uploadDocument]);
2012
2049
  return /*#__PURE__*/React__namespace.default.createElement(SubmissionContext.Provider, {
2013
2050
  value: value
2014
2051
  }, geolocationRequired && geolocationBlocked ? ( /*#__PURE__*/React__namespace.default.createElement(GeolocationAccessDeniedOverlay, null)) : children, submissionError && ( /*#__PURE__*/React__namespace.default.createElement(SubmissionErrorOverlay, {
@@ -2202,97 +2239,6 @@ function preloadVisionRuntime() {
2202
2239
  });
2203
2240
  }
2204
2241
 
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$M || (templateObject_1$M = __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$M;
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
2242
  var defaultImageSegmenterModelPath = 'https://websdk-cdn-dev.idmission.com/assets/models/selfiesegmenter20240524/selfie_segmenter.tflite';
2297
2243
  var imageSegmenterModelSizeInBytes = 256440.32;
2298
2244
  // The idea here is that we globally set a cache key based on the time at page load. That way our built-in speed test
@@ -2422,6 +2368,192 @@ function giveUpAfter(maxTime) {
2422
2368
  });
2423
2369
  }
2424
2370
 
2371
+ var DEFAULT_CDN_URL = 'https://websdk-cdn-dev.idmission.com/assets';
2372
+
2373
+ var defaultDocumentDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/DocumentDetector/DocumentDetector-20250815_115859.tflite");
2374
+
2375
+ var defaultFocusModelPath = "".concat(DEFAULT_CDN_URL, "/models/Focus/Focus-20241008_102708.tflite");
2376
+
2377
+ var defaultFaceDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/FaceDetector/FaceDetector-20250820_154546.tflite");
2378
+
2379
+ var defaultBarcodeReadabilityModelPath = "".concat(DEFAULT_CDN_URL, "/models/BarcodeReadability/BarcodeReadability-20250815_120417.tflite");
2380
+
2381
+ var defaultModelPaths = {
2382
+ documentDetector: defaultDocumentDetectorModelPath,
2383
+ focus: defaultFocusModelPath,
2384
+ faceDetection: defaultFaceDetectorModelPath,
2385
+ barcodeReadability: defaultBarcodeReadabilityModelPath
2386
+ };
2387
+
2388
+ var preloadModels = function preloadModels(_a) {
2389
+ return __awaiter(void 0, [_a], void 0, function (_b) {
2390
+ var preloadTasks;
2391
+ var _c = _b.documentDetectionModel,
2392
+ documentDetectionModel = _c === void 0 ? true : _c,
2393
+ _d = _b.focusModel,
2394
+ focusModel = _d === void 0 ? true : _d,
2395
+ _e = _b.faceDetectionModel,
2396
+ faceDetectionModel = _e === void 0 ? true : _e,
2397
+ _f = _b.barcodeReadabilityModel,
2398
+ barcodeReadabilityModel = _f === void 0 ? true : _f;
2399
+ return __generator(this, function (_g) {
2400
+ switch (_g.label) {
2401
+ case 0:
2402
+ return [4 /*yield*/, probeModelCapabilities()];
2403
+ case 1:
2404
+ _g.sent();
2405
+ preloadTasks = [];
2406
+ if (documentDetectionModel) {
2407
+ preloadTasks.push(preloadDocumentDetectorDependencies);
2408
+ }
2409
+ if (focusModel) {
2410
+ preloadTasks.push(preloadFocusModelDependencies);
2411
+ }
2412
+ if (faceDetectionModel) {
2413
+ preloadTasks.push(preloadFaceDetectorDependencies);
2414
+ }
2415
+ if (barcodeReadabilityModel) {
2416
+ preloadTasks.push(preloadBarcodeReadabilityModelDependencies);
2417
+ }
2418
+ return [4 /*yield*/, Promise.all(preloadTasks)];
2419
+ case 2:
2420
+ _g.sent();
2421
+ return [2 /*return*/];
2422
+ }
2423
+ });
2424
+ });
2425
+ };
2426
+ var progressByUrl = {};
2427
+ var progressByUseCase = {
2428
+ visionRuntime: {
2429
+ loaded: 0,
2430
+ total: 0
2431
+ },
2432
+ documentDetector: {
2433
+ loaded: 0,
2434
+ total: 0
2435
+ },
2436
+ focus: {
2437
+ loaded: 0,
2438
+ total: 0
2439
+ },
2440
+ faceDetection: {
2441
+ loaded: 0,
2442
+ total: 0
2443
+ },
2444
+ barcodeReadability: {
2445
+ loaded: 0,
2446
+ total: 0
2447
+ }
2448
+ };
2449
+ function preloadDependency(url) {
2450
+ return __awaiter(this, void 0, void 0, function () {
2451
+ return __generator(this, function (_a) {
2452
+ return [2 /*return*/, new Promise(function (resolve, reject) {
2453
+ var req = new XMLHttpRequest();
2454
+ req.addEventListener('progress', function (event) {
2455
+ if (!event.lengthComputable) return;
2456
+ progressByUrl[url] = event;
2457
+ document.dispatchEvent(new CustomEvent('idmission.preloadProgress', {
2458
+ detail: {
2459
+ url: url,
2460
+ loaded: event.loaded,
2461
+ total: event.total
2462
+ }
2463
+ }));
2464
+ });
2465
+ req.addEventListener('loadend', function () {
2466
+ resolve(req.readyState === 4 && req.status === 200);
2467
+ });
2468
+ req.addEventListener('error', reject);
2469
+ req.open('GET', url, true);
2470
+ req.send();
2471
+ })];
2472
+ });
2473
+ });
2474
+ }
2475
+ var modelsPreloading = {
2476
+ documentDetector: false,
2477
+ focus: false,
2478
+ faceDetection: false,
2479
+ barcodeReadability: false
2480
+ };
2481
+ var preloadDocumentDetectorDependencies = function preloadDocumentDetectorDependencies() {
2482
+ return preloadModelDependencies('documentDetector');
2483
+ };
2484
+ var preloadFocusModelDependencies = function preloadFocusModelDependencies() {
2485
+ return preloadModelDependencies('focus');
2486
+ };
2487
+ var preloadFaceDetectorDependencies = function preloadFaceDetectorDependencies() {
2488
+ return preloadModelDependencies('faceDetection');
2489
+ };
2490
+ var preloadBarcodeReadabilityModelDependencies = function preloadBarcodeReadabilityModelDependencies() {
2491
+ return preloadModelDependencies('barcodeReadability');
2492
+ };
2493
+ function preloadModelDependencies(model) {
2494
+ return __awaiter(this, void 0, void 0, function () {
2495
+ function handleModelDownloadProgress(event) {
2496
+ var detail = event.detail;
2497
+ if (!dependencies.includes(detail.url)) return;
2498
+ progressByUseCase[model] = sumUpProgressForDependencies(dependencies);
2499
+ document.dispatchEvent(new CustomEvent("idmission.preloadProgress.".concat(model), {
2500
+ detail: progressByUseCase[model]
2501
+ }));
2502
+ }
2503
+ var dependencies;
2504
+ return __generator(this, function (_a) {
2505
+ switch (_a.label) {
2506
+ case 0:
2507
+ if (modelsPreloading[model]) return [2 /*return*/, new Promise(function (resolve) {
2508
+ var i = setInterval(function () {
2509
+ if (!modelsPreloading[model]) {
2510
+ clearInterval(i);
2511
+ resolve();
2512
+ }
2513
+ }, 100);
2514
+ })];
2515
+ modelsPreloading[model] = true;
2516
+ return [4 /*yield*/, probeModelCapabilities()];
2517
+ case 1:
2518
+ _a.sent();
2519
+ if (modelCapabilities.delegate === 'NONE') {
2520
+ throw new Error("No available delegate for ".concat(model, " model."));
2521
+ }
2522
+ dependencies = [defaultModelPaths[model]];
2523
+ document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
2524
+ _a.label = 2;
2525
+ case 2:
2526
+ _a.trys.push([2,, 4, 5]);
2527
+ return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
2528
+ case 3:
2529
+ _a.sent();
2530
+ return [3 /*break*/, 5];
2531
+ case 4:
2532
+ document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
2533
+ modelsPreloading[model] = false;
2534
+ return [7 /*endfinally*/];
2535
+ case 5:
2536
+ return [2 /*return*/];
2537
+ }
2538
+ });
2539
+ });
2540
+ }
2541
+ function progressToPercentage(progress) {
2542
+ return progress.total > 0 ? Math.round(100.0 * progress.loaded / progress.total) : 0;
2543
+ }
2544
+ function sumUpProgressForDependencies(dependencies) {
2545
+ return dependencies.reduce(function (result, dependency) {
2546
+ var dependencyProgress = progressByUrl[dependency];
2547
+ if (!dependencyProgress) return result;
2548
+ result.loaded += dependencyProgress.loaded;
2549
+ result.total += dependencyProgress.total;
2550
+ return result;
2551
+ }, {
2552
+ loaded: 0,
2553
+ total: 0
2554
+ });
2555
+ }
2556
+
2425
2557
  function convertBoundingBox(box) {
2426
2558
  var _a, _b, _c, _d, _e, _f, _g, _h;
2427
2559
  return {
@@ -2476,785 +2608,6 @@ function average(arr) {
2476
2608
  return sum / len;
2477
2609
  }
2478
2610
 
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/FaceDetector/FaceDetector-20250820_154546.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
2504
- }
2505
- };
2506
- var classifier = null;
2507
- var classifierSettings = null;
2508
- function loadFocusModel() {
2509
- return __awaiter(this, arguments, void 0, function (modelAssetPath) {
2510
- var _a, _b;
2511
- if (modelAssetPath === void 0) {
2512
- modelAssetPath = defaultFocusModelPath;
2513
- }
2514
- return __generator(this, function (_c) {
2515
- switch (_c.label) {
2516
- 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()];
2520
- case 1:
2521
- _c.sent();
2522
- if (modelCapabilities.delegate === 'NONE') {
2523
- throw new Error('No available delegate for focus detector.');
2524
- }
2525
- _b = (_a = tasksVision.ImageClassifier).createFromOptions;
2526
- return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
2527
- case 2:
2528
- return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
2529
- baseOptions: {
2530
- modelAssetPath: modelAssetPath,
2531
- delegate: modelCapabilities.delegate
2532
- },
2533
- // canvas: document.createElement('canvas'),
2534
- runningMode: 'VIDEO'
2535
- }])];
2536
- case 3:
2537
- classifier = _c.sent();
2538
- classifierSettings = {
2539
- modelAssetPath: modelAssetPath
2540
- };
2541
- return [2 /*return*/, classifier];
2542
- }
2543
- });
2544
- });
2545
- }
2546
- function closeFocusModel() {
2547
- classifier === null || classifier === void 0 ? void 0 : classifier.close();
2548
- classifier = null;
2549
- classifierSettings = null;
2550
- }
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,
2556
- 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];
2566
- var _g = React.useState(null),
2567
- modelWarmingStartedAt = _g[0],
2568
- setModelWarmingStartedAt = _g[1];
2569
- var _h = React.useState(null),
2570
- modelError = _h[0],
2571
- setModelError = _h[1];
2572
- React.useEffect(function loadModel() {
2573
- var _this = this;
2574
- if (!shouldLoadModels) return;
2575
- setModelLoadState('downloading');
2576
- setModelWarmingStartedAt(null);
2577
- function handleDownloadProgress(event) {
2578
- setModelDownloadProgress(progressToPercentage(event.detail));
2579
- }
2580
- document.addEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
2581
- var modelLoadTimeout = setTimeout(function () {
2582
- setModelError(new Error('Model loading time limit exceeded.'));
2583
- }, modelLoadTimeoutMs);
2584
- var cancelVideoReady = function cancelVideoReady() {};
2585
- loadFocusModel(modelPath).then(function (loadedModel) {
2586
- return __awaiter(_this, void 0, void 0, function () {
2587
- var _a, videoReady, cancel, cancelled;
2588
- return __generator(this, function (_b) {
2589
- switch (_b.label) {
2590
- case 0:
2591
- setModelDownloadProgress(100);
2592
- clearTimeout(modelLoadTimeout);
2593
- setModelLoadState('warming');
2594
- setModelWarmingStartedAt(new Date().getTime());
2595
- _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
2596
- cancelled = false;
2597
- cancelVideoReady = function cancelVideoReady() {
2598
- cancelled = true;
2599
- cancel();
2600
- };
2601
- return [4 /*yield*/, videoReady];
2602
- case 1:
2603
- _b.sent();
2604
- setTimeout(function () {
2605
- if (cancelled) return;
2606
- loadedModel.classifyForVideo(videoRef.current, performance.now());
2607
- setModelLoadState('ready');
2608
- }, 500);
2609
- return [2 /*return*/];
2610
- }
2611
- });
2612
- });
2613
- })["catch"](function (e) {
2614
- setModelError(e);
2615
- setModelLoadState('error');
2616
- })["finally"](function () {
2617
- clearTimeout(modelLoadTimeout);
2618
- });
2619
- return function () {
2620
- log('unloading focus model');
2621
- cancelVideoReady();
2622
- closeFocusModel();
2623
- clearTimeout(modelLoadTimeout);
2624
- document.removeEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
2625
- };
2626
- }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
2627
- React.useEffect(function handleModelError() {
2628
- if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
2629
- }, [modelError, onModelError]);
2630
- return React.useMemo(function () {
2631
- return {
2632
- ready: modelLoadState === 'ready',
2633
- modelLoadState: modelLoadState,
2634
- modelDownloadProgress: modelDownloadProgress,
2635
- modelWarmingStartedAt: modelWarmingStartedAt,
2636
- modelError: modelError
2637
- };
2638
- }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
2639
- }
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];
2716
- }
2717
- });
2718
- });
2719
- }
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;
2815
- }
2816
- var framesNeededSamples$1 = [];
2817
- function trackFramesNeeded$1(value, bufferLength) {
2818
- if (bufferLength === void 0) {
2819
- bufferLength = 25;
2820
- }
2821
- framesNeededSamples$1.unshift(value);
2822
- if (framesNeededSamples$1.length > bufferLength) framesNeededSamples$1.length = bufferLength;
2823
- }
2824
- var lastNFaces = [];
2825
- var lastNFacePairs = [];
2826
- var lastNNoses = [];
2827
- var lastNNosePairs = [];
2828
- function trackFace(face, framesNeeded, frameWidth, frameHeight) {
2829
- if (framesNeeded === void 0) {
2830
- framesNeeded = 12;
2831
- }
2832
- var nose = face.keypoints[2];
2833
- if (!nose) return;
2834
- lastNFaces.unshift(face);
2835
- lastNNoses.unshift(nose);
2836
- if (lastNFaces.length > framesNeeded) lastNFaces.length = framesNeeded;
2837
- if (lastNNoses.length > framesNeeded) lastNNoses.length = framesNeeded;
2838
- if (lastNFaces.length > 1) {
2839
- var lastFace = lastNFaces[1];
2840
- var iou = calculateIoU(face.box, lastFace.box);
2841
- lastNFacePairs.unshift({
2842
- a: face,
2843
- b: lastFace,
2844
- iou: iou
2845
- });
2846
- if (lastNFacePairs.length > framesNeeded - 1) lastNFacePairs.length = framesNeeded - 1;
2847
- }
2848
- if (lastNNoses.length > 1) {
2849
- var lastNose = lastNNoses[1];
2850
- var noseDistance = Math.sqrt(Math.pow((nose.x - lastNose.x) / frameWidth, 2) + Math.pow((nose.y - lastNose.y) / frameHeight, 2));
2851
- lastNNosePairs.unshift({
2852
- a: nose,
2853
- b: lastNose,
2854
- distance: noseDistance
2855
- });
2856
- if (lastNNosePairs.length > framesNeeded - 1) lastNNosePairs.length = framesNeeded - 1;
2857
- }
2858
- }
2859
- function makeFaceDetectorPrediction(imageData) {
2860
- if (!detector$1) return null;
2861
- var prediction = detector$1.detectForVideo(imageData, performance.now());
2862
- var faces = prediction.detections.map(function (d) {
2863
- return {
2864
- box: convertBoundingBox(d.boundingBox),
2865
- keypoints: d.keypoints.map(function (k) {
2866
- var _a;
2867
- return _assign(_assign({}, k), {
2868
- x: k.x * imageData.width,
2869
- y: k.y * imageData.height,
2870
- name: (_a = k.label) !== null && _a !== void 0 ? _a : ''
2871
- });
2872
- })
2873
- };
2874
- });
2875
- return _assign(_assign({}, prediction), {
2876
- faces: faces
2877
- });
2878
- }
2879
- function processFaceDetectorPrediction(_a) {
2880
- var faces = _a.faces,
2881
- videoWidth = _a.videoWidth,
2882
- videoHeight = _a.videoHeight,
2883
- _b = _a.requireVerticalFaceCentering,
2884
- requireVerticalFaceCentering = _b === void 0 ? true : _b,
2885
- _c = _a.stabilityThreshold,
2886
- stabilityThreshold = _c === void 0 ? 0.7 : _c,
2887
- _d = _a.noseDistanceThreshold,
2888
- noseDistanceThreshold = _d === void 0 ? 0.025 : _d,
2889
- _e = _a.xBoundary,
2890
- xBoundary = _e === void 0 ? 0.01 : _e,
2891
- // this represents the edge that the sides of the face box should not cross -- 1% of video width
2892
- _f = _a.yBoundary,
2893
- // this represents the edge that the sides of the face box should not cross -- 1% of video width
2894
- yBoundary = _f === void 0 ? 0.01 : _f,
2895
- // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
2896
- _g = _a.xCentroidBoundary,
2897
- // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
2898
- xCentroidBoundary = _g === void 0 ? 0.125 : _g,
2899
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
2900
- _h = _a.yCentroidBoundary,
2901
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
2902
- yCentroidBoundary = _h === void 0 ? 0.125 : _h,
2903
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
2904
- _j = _a.foreheadRatio,
2905
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
2906
- foreheadRatio = _j === void 0 ? 0.275 : _j,
2907
- // we found that the bounding box ends at the brow and misses the forehead. this ratio represents how much we should extend the box to include the forehead.
2908
- _k = _a.noseTrackingThreshold,
2909
- // we found that the bounding box ends at the brow and misses the forehead. this ratio represents how much we should extend the box to include the forehead.
2910
- noseTrackingThreshold = _k === void 0 ? 0.2 : _k,
2911
- // this represents the maximum distance that the nose can be from the center of the face box -- 20% of the face box width or height
2912
- minCaptureBrightnessThreshold = _a.minCaptureBrightnessThreshold,
2913
- minCaptureRangeThreshold = _a.minCaptureRangeThreshold,
2914
- minCaptureVarianceThreshold = _a.minCaptureVarianceThreshold,
2915
- brightness = _a.brightness,
2916
- range = _a.range,
2917
- variance = _a.variance;
2918
- var face = faces[0];
2919
- var faceNotDetected = faces.length === 0;
2920
- var faceNotCentered = false,
2921
- faceLookingAway = false,
2922
- faceTooClose = false,
2923
- faceTooFar = false,
2924
- faceVisibilityTooLow = false;
2925
- var hasAnyThreshold = minCaptureBrightnessThreshold !== undefined || minCaptureRangeThreshold !== undefined || minCaptureVarianceThreshold !== undefined;
2926
- if (hasAnyThreshold) {
2927
- var tooDark = minCaptureBrightnessThreshold !== undefined && brightness !== undefined && brightness < minCaptureBrightnessThreshold;
2928
- var tooLowRange = minCaptureRangeThreshold !== undefined && range !== undefined && range < minCaptureRangeThreshold;
2929
- var tooLowVariance = minCaptureVarianceThreshold !== undefined && variance !== undefined && variance < minCaptureVarianceThreshold;
2930
- faceVisibilityTooLow = !!(tooDark || tooLowRange || tooLowVariance);
2931
- }
2932
- if (face && !faceVisibilityTooLow) {
2933
- // calculate frame centroids
2934
- var frameCX = videoWidth / 2;
2935
- var frameCY = videoHeight / 2;
2936
- // calculate head bounding box, with forehead extension
2937
- var foreheadSize = face.box.height * foreheadRatio;
2938
- var headXMin = face.box.xMin;
2939
- var headXMax = face.box.xMax;
2940
- var headYMin = face.box.yMin - foreheadSize;
2941
- var headYMax = face.box.yMax;
2942
- // calculate head centroids
2943
- var headCX = (headXMin + headXMax) / 2;
2944
- var headCY = (headYMin + headYMax) / 2;
2945
- // calculate thresholds
2946
- var vTX = videoWidth * xBoundary;
2947
- var vTY = videoHeight * yBoundary;
2948
- var vCTX = videoWidth * xCentroidBoundary;
2949
- var vCTY = videoHeight * yCentroidBoundary;
2950
- var faceNotCenteredHorizontally = Math.abs(frameCX - headCX) > vCTX;
2951
- var faceNotCenteredVertically = Math.abs(frameCY - headCY) > vCTY;
2952
- var faceViolatesHorizontalBoundary = headXMin < vTX || headXMax > videoWidth - vTX;
2953
- var faceViolatesVerticalBoundary = headYMin < vTY || headYMax > videoHeight - vTY;
2954
- faceNotCentered = faceViolatesHorizontalBoundary || faceViolatesVerticalBoundary || faceNotCenteredHorizontally || requireVerticalFaceCentering && faceNotCenteredVertically;
2955
- var isMobile = videoWidth < videoHeight;
2956
- var tooCloseMultiple = 1.5;
2957
- var tooFarMultiple = isMobile ? 6 : 7;
2958
- faceTooClose = face.box.width > videoWidth / tooCloseMultiple;
2959
- faceTooFar = face.box.width < videoWidth / tooFarMultiple;
2960
- var nose = face.keypoints[2];
2961
- var fTW = face.box.width * noseTrackingThreshold;
2962
- var fTH = face.box.height * noseTrackingThreshold;
2963
- faceLookingAway = !nose || Math.abs(headCX - nose.x) > fTW || Math.abs(headCY - nose.y) > fTH;
2964
- }
2965
- var faceInGuides = !faceNotDetected && !faceNotCentered && !faceLookingAway && !faceTooClose && !faceTooFar;
2966
- if (lastFaceDetectionTime > 0) {
2967
- trackFramesNeeded$1(500 / lastFaceDetectionTime);
2968
- }
2969
- var faceIsStable = false,
2970
- noseIsStable = false;
2971
- if (faceInGuides && !faceVisibilityTooLow) {
2972
- var framesNeeded = Math.max(Math.ceil(average(framesNeededSamples$1)), 5);
2973
- trackFace(face, framesNeeded, videoWidth, videoHeight);
2974
- faceIsStable = lastNFaces.length >= framesNeeded && !lastNFacePairs.some(function (pair) {
2975
- return pair.iou < stabilityThreshold;
2976
- });
2977
- noseIsStable = lastNNoses.length >= framesNeeded && !lastNNosePairs.some(function (pair) {
2978
- return pair.distance > noseDistanceThreshold;
2979
- });
2980
- }
2981
- var faceReady = faceInGuides && faceIsStable && noseIsStable && !faceVisibilityTooLow;
2982
- return {
2983
- face: face,
2984
- faceNotDetected: faceNotDetected,
2985
- faceNotCentered: faceNotCentered,
2986
- faceLookingAway: faceLookingAway,
2987
- faceTooClose: faceTooClose,
2988
- faceTooFar: faceTooFar,
2989
- faceReady: faceReady,
2990
- faceReadyAt: faceReady ? new Date() : null,
2991
- faceIsStable: faceIsStable,
2992
- noseIsStable: noseIsStable,
2993
- faceVisibilityTooLow: faceVisibilityTooLow
2994
- };
2995
- }
2996
- function testFaceDetectionAgainstKnownImage(detector) {
2997
- return new Promise(function (resolve, reject) {
2998
- var img = new Image();
2999
- img.crossOrigin = 'anonymous';
3000
- img.onload = function () {
3001
- var prediction = detector.detectForVideo(img, performance.now());
3002
- if (prediction.detections.length > 0) {
3003
- debug('face detection test result', prediction.detections);
3004
- resolve(void 0);
3005
- } else {
3006
- warn('face detection test failed');
3007
- reject(new Error('testFaceDetectionAgainstKnownImage failed to predict'));
3008
- }
3009
- };
3010
- img.onerror = function () {
3011
- return reject(new Error('testFaceDetectionAgainstKnownImage failed to load image'));
3012
- };
3013
- img.src = "".concat(DEFAULT_CDN_URL, "/head-test.jpg");
3014
- });
3015
- }
3016
-
3017
- var preloadModels = function preloadModels(_a) {
3018
- return __awaiter(void 0, [_a], void 0, function (_b) {
3019
- var preloadTasks;
3020
- var _c = _b.documentDetectionModel,
3021
- documentDetectionModel = _c === void 0 ? true : _c,
3022
- _d = _b.focusModel,
3023
- focusModel = _d === void 0 ? true : _d,
3024
- _e = _b.faceDetectionModel,
3025
- faceDetectionModel = _e === void 0 ? true : _e;
3026
- return __generator(this, function (_f) {
3027
- switch (_f.label) {
3028
- case 0:
3029
- return [4 /*yield*/, probeModelCapabilities()];
3030
- case 1:
3031
- _f.sent();
3032
- preloadTasks = [];
3033
- if (documentDetectionModel) {
3034
- preloadTasks.push(preloadDocumentDetectorDependencies);
3035
- }
3036
- if (focusModel) {
3037
- preloadTasks.push(preloadFocusModelDependencies);
3038
- }
3039
- if (faceDetectionModel) {
3040
- preloadTasks.push(preloadFaceDetectorDependencies);
3041
- }
3042
- return [4 /*yield*/, Promise.all(preloadTasks)];
3043
- case 2:
3044
- _f.sent();
3045
- return [2 /*return*/];
3046
- }
3047
- });
3048
- });
3049
- };
3050
- var progressByUrl = {};
3051
- var progressByUseCase = {
3052
- visionRuntime: {
3053
- loaded: 0,
3054
- total: 0
3055
- },
3056
- documentDetection: {
3057
- loaded: 0,
3058
- total: 0
3059
- },
3060
- focus: {
3061
- loaded: 0,
3062
- total: 0
3063
- },
3064
- faceDetection: {
3065
- loaded: 0,
3066
- total: 0
3067
- }
3068
- };
3069
- function preloadDependency(url) {
3070
- return __awaiter(this, void 0, void 0, function () {
3071
- return __generator(this, function (_a) {
3072
- return [2 /*return*/, new Promise(function (resolve, reject) {
3073
- var req = new XMLHttpRequest();
3074
- req.addEventListener('progress', function (event) {
3075
- if (!event.lengthComputable) return;
3076
- progressByUrl[url] = event;
3077
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress', {
3078
- detail: {
3079
- url: url,
3080
- loaded: event.loaded,
3081
- total: event.total
3082
- }
3083
- }));
3084
- });
3085
- req.addEventListener('loadend', function () {
3086
- resolve(req.readyState === 4 && req.status === 200);
3087
- });
3088
- req.addEventListener('error', reject);
3089
- req.open('GET', url, true);
3090
- req.send();
3091
- })];
3092
- });
3093
- });
3094
- }
3095
- var documentDetectorPreloading = false,
3096
- focusModelPreloading = false,
3097
- faceDetectorPreloading = false;
3098
- function preloadDocumentDetectorDependencies() {
3099
- return __awaiter(this, void 0, void 0, function () {
3100
- function handleDownloadProgress(event) {
3101
- var detail = event.detail;
3102
- if (!dependencies.includes(detail.url)) return;
3103
- progressByUseCase.documentDetection = sumUpProgressForDependencies(dependencies);
3104
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.documentDetection', {
3105
- detail: progressByUseCase.documentDetection
3106
- }));
3107
- }
3108
- var dependencies;
3109
- return __generator(this, function (_a) {
3110
- switch (_a.label) {
3111
- case 0:
3112
- if (documentDetectorPreloading) return [2 /*return*/, new Promise(function (resolve) {
3113
- var i = setInterval(function () {
3114
- if (!documentDetectorPreloading) {
3115
- clearInterval(i);
3116
- resolve();
3117
- }
3118
- }, 100);
3119
- })];
3120
- documentDetectorPreloading = true;
3121
- return [4 /*yield*/, probeModelCapabilities()];
3122
- case 1:
3123
- _a.sent();
3124
- if (modelCapabilities.delegate === 'NONE') {
3125
- throw new Error('No available delegate for document detector.');
3126
- }
3127
- dependencies = [defaultDocumentDetectorModelPath];
3128
- document.addEventListener('idmission.preloadProgress', handleDownloadProgress);
3129
- _a.label = 2;
3130
- case 2:
3131
- _a.trys.push([2,, 4, 5]);
3132
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
3133
- case 3:
3134
- _a.sent();
3135
- return [3 /*break*/, 5];
3136
- case 4:
3137
- document.removeEventListener('idmission.preloadProgress', handleDownloadProgress);
3138
- documentDetectorPreloading = false;
3139
- return [7 /*endfinally*/];
3140
- case 5:
3141
- return [2 /*return*/];
3142
- }
3143
- });
3144
- });
3145
- }
3146
- function preloadFocusModelDependencies() {
3147
- return __awaiter(this, void 0, void 0, function () {
3148
- function handleModelDownloadProgress(event) {
3149
- var detail = event.detail;
3150
- if (!dependencies.includes(detail.url)) return;
3151
- progressByUseCase.focus = sumUpProgressForDependencies(dependencies);
3152
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.focus', {
3153
- detail: progressByUseCase.focus
3154
- }));
3155
- }
3156
- var dependencies;
3157
- return __generator(this, function (_a) {
3158
- switch (_a.label) {
3159
- case 0:
3160
- if (focusModelPreloading) return [2 /*return*/, new Promise(function (resolve) {
3161
- var i = setInterval(function () {
3162
- if (!focusModelPreloading) {
3163
- clearInterval(i);
3164
- resolve();
3165
- }
3166
- }, 100);
3167
- })];
3168
- focusModelPreloading = true;
3169
- return [4 /*yield*/, probeModelCapabilities()];
3170
- case 1:
3171
- _a.sent();
3172
- if (modelCapabilities.delegate === 'NONE') {
3173
- throw new Error('No available delegate for document detector.');
3174
- }
3175
- dependencies = [defaultFocusModelPath];
3176
- document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3177
- _a.label = 2;
3178
- case 2:
3179
- _a.trys.push([2,, 4, 5]);
3180
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
3181
- case 3:
3182
- _a.sent();
3183
- return [3 /*break*/, 5];
3184
- case 4:
3185
- document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3186
- focusModelPreloading = false;
3187
- return [7 /*endfinally*/];
3188
- case 5:
3189
- return [2 /*return*/];
3190
- }
3191
- });
3192
- });
3193
- }
3194
- function preloadFaceDetectorDependencies() {
3195
- return __awaiter(this, void 0, void 0, function () {
3196
- function handleModelDownloadProgress(event) {
3197
- var detail = event.detail;
3198
- if (!dependencies.includes(detail.url)) return;
3199
- progressByUseCase.faceDetection = sumUpProgressForDependencies(dependencies);
3200
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.faceDetection', {
3201
- detail: progressByUseCase.faceDetection
3202
- }));
3203
- }
3204
- var dependencies;
3205
- return __generator(this, function (_a) {
3206
- switch (_a.label) {
3207
- case 0:
3208
- if (faceDetectorPreloading) return [2 /*return*/, new Promise(function (resolve) {
3209
- var i = setInterval(function () {
3210
- if (!faceDetectorPreloading) {
3211
- clearInterval(i);
3212
- resolve();
3213
- }
3214
- }, 100);
3215
- })];
3216
- faceDetectorPreloading = true;
3217
- return [4 /*yield*/, probeModelCapabilities()];
3218
- case 1:
3219
- _a.sent();
3220
- if (modelCapabilities.delegate === 'NONE') {
3221
- throw new Error('No available delegate for document detector.');
3222
- }
3223
- dependencies = [defaultFaceDetectorModelPath];
3224
- document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3225
- _a.label = 2;
3226
- case 2:
3227
- _a.trys.push([2,, 4, 5]);
3228
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
3229
- case 3:
3230
- _a.sent();
3231
- return [3 /*break*/, 5];
3232
- case 4:
3233
- document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3234
- faceDetectorPreloading = false;
3235
- return [7 /*endfinally*/];
3236
- case 5:
3237
- return [2 /*return*/];
3238
- }
3239
- });
3240
- });
3241
- }
3242
- function progressToPercentage(progress) {
3243
- return progress.total > 0 ? Math.round(100.0 * progress.loaded / progress.total) : 0;
3244
- }
3245
- function sumUpProgressForDependencies(dependencies) {
3246
- return dependencies.reduce(function (result, dependency) {
3247
- var dependencyProgress = progressByUrl[dependency];
3248
- if (!dependencyProgress) return result;
3249
- result.loaded += dependencyProgress.loaded;
3250
- result.total += dependencyProgress.total;
3251
- return result;
3252
- }, {
3253
- loaded: 0,
3254
- total: 0
3255
- });
3256
- }
3257
-
3258
2611
  var defaultDocumentDetectionScoreThreshold = 0.1;
3259
2612
  var defaultDocumentDetectionModelLoadTimeoutMs = 45000;
3260
2613
  var defaultDocumentDetectionThresholds = {
@@ -3276,8 +2629,8 @@ var documentTypeDisplayNames = {
3276
2629
  singlePage: 'Single page',
3277
2630
  none: 'None'
3278
2631
  };
3279
- var detector = null;
3280
- var detectorSettings = null;
2632
+ var detector$1 = null;
2633
+ var detectorSettings$1 = null;
3281
2634
  function loadDocumentDetector() {
3282
2635
  return __awaiter(this, arguments, void 0, function (modelAssetPath, scoreThreshold) {
3283
2636
  var _a, _b;
@@ -3290,7 +2643,7 @@ function loadDocumentDetector() {
3290
2643
  return __generator(this, function (_c) {
3291
2644
  switch (_c.label) {
3292
2645
  case 0:
3293
- 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];
2646
+ if (detector$1 && (detectorSettings$1 === null || detectorSettings$1 === void 0 ? void 0 : detectorSettings$1.modelAssetPath) === modelAssetPath && (detectorSettings$1 === null || detectorSettings$1 === void 0 ? void 0 : detectorSettings$1.scoreThreshold) === scoreThreshold) return [2 /*return*/, detector$1];
3294
2647
  closeDocumentDetector();
3295
2648
  return [4 /*yield*/, preloadDocumentDetectorDependencies()];
3296
2649
  case 1:
@@ -3311,20 +2664,20 @@ function loadDocumentDetector() {
3311
2664
  runningMode: 'VIDEO'
3312
2665
  }])];
3313
2666
  case 3:
3314
- detector = _c.sent();
3315
- detectorSettings = {
2667
+ detector$1 = _c.sent();
2668
+ detectorSettings$1 = {
3316
2669
  modelAssetPath: modelAssetPath,
3317
2670
  scoreThreshold: scoreThreshold
3318
2671
  };
3319
- return [2 /*return*/, detector];
2672
+ return [2 /*return*/, detector$1];
3320
2673
  }
3321
2674
  });
3322
2675
  });
3323
2676
  }
3324
2677
  function closeDocumentDetector() {
3325
- detector === null || detector === void 0 ? void 0 : detector.close();
3326
- detector = null;
3327
- detectorSettings = null;
2678
+ detector$1 === null || detector$1 === void 0 ? void 0 : detector$1.close();
2679
+ detector$1 = null;
2680
+ detectorSettings$1 = null;
3328
2681
  }
3329
2682
  function useLoadDocumentDetector(_a) {
3330
2683
  var _b = _a.shouldLoadModels,
@@ -3357,7 +2710,7 @@ function useLoadDocumentDetector(_a) {
3357
2710
  function handleDownloadProgress(event) {
3358
2711
  setModelDownloadProgress(progressToPercentage(event.detail));
3359
2712
  }
3360
- document.addEventListener('idmission.preloadProgress.documentDetection', handleDownloadProgress);
2713
+ document.addEventListener('idmission.preloadProgress.documentDetector', handleDownloadProgress);
3361
2714
  var modelLoadTimeout = setTimeout(function () {
3362
2715
  setModelError(new Error('Model loading time limit exceeded.'));
3363
2716
  }, modelLoadTimeoutMs);
@@ -3370,7 +2723,7 @@ function useLoadDocumentDetector(_a) {
3370
2723
  case 0:
3371
2724
  setModelDownloadProgress(100);
3372
2725
  setModelLoadState('warming');
3373
- setModelWarmingStartedAt(new Date().getTime());
2726
+ setModelWarmingStartedAt(performance.now());
3374
2727
  clearTimeout(modelLoadTimeout);
3375
2728
  return [4 /*yield*/, testDocumentDetectionAgainstKnownImage(model)];
3376
2729
  case 1:
@@ -3404,7 +2757,7 @@ function useLoadDocumentDetector(_a) {
3404
2757
  cancelVideoReady();
3405
2758
  closeDocumentDetector();
3406
2759
  clearTimeout(modelLoadTimeout);
3407
- document.removeEventListener('idmission.preloadProgress.documentDetection', handleDownloadProgress);
2760
+ document.removeEventListener('idmission.preloadProgress.documentDetector', handleDownloadProgress);
3408
2761
  };
3409
2762
  }, [shouldLoadModels, modelLoadTimeoutMs, modelPath, scoreThreshold, videoRef]);
3410
2763
  React.useEffect(function handleModelError() {
@@ -3425,13 +2778,13 @@ function makeDocumentDetectorPrediction(frame) {
3425
2778
  return __awaiter(this, void 0, void 0, function () {
3426
2779
  var startedAt, prediction, time, frameWidth, frameHeight;
3427
2780
  return __generator(this, function (_a) {
3428
- if (!detector) return [2 /*return*/, null];
3429
- startedAt = new Date();
2781
+ if (!detector$1) return [2 /*return*/, null];
2782
+ startedAt = performance.now();
3430
2783
  // Detectors can throw errors, for example when using custom URLs that
3431
2784
  // contain a model that doesn't provide the expected output.
3432
2785
  try {
3433
- prediction = detector.detectForVideo(frame, performance.now());
3434
- time = new Date().getTime() - startedAt.getTime();
2786
+ prediction = detector$1.detectForVideo(frame, performance.now());
2787
+ time = performance.now() - startedAt;
3435
2788
  frameWidth = frame.width;
3436
2789
  frameHeight = frame.height;
3437
2790
  return [2 /*return*/, _assign(_assign({}, prediction), {
@@ -3452,13 +2805,13 @@ function setLastDetectionAt(time) {
3452
2805
  lastDetectionTime = time - lastDetectionAt;
3453
2806
  lastDetectionAt = time;
3454
2807
  }
3455
- var framesNeededSamples = [];
3456
- function trackFramesNeeded(value, bufferLength) {
2808
+ var framesNeededSamples$1 = [];
2809
+ function trackFramesNeeded$1(value, bufferLength) {
3457
2810
  if (bufferLength === void 0) {
3458
2811
  bufferLength = 25;
3459
2812
  }
3460
- framesNeededSamples.unshift(value);
3461
- if (framesNeededSamples.length > bufferLength) framesNeededSamples.length = bufferLength;
2813
+ framesNeededSamples$1.unshift(value);
2814
+ if (framesNeededSamples$1.length > bufferLength) framesNeededSamples$1.length = bufferLength;
3462
2815
  }
3463
2816
  var lastNBoxes = [];
3464
2817
  var lastNPairs = [];
@@ -3564,7 +2917,7 @@ function processDocumentDetectorPrediction(prediction, thresholds, boundaries) {
3564
2917
  }
3565
2918
  var documentInBounds = !!bestDocument;
3566
2919
  if (lastDetectionTime > 0) {
3567
- trackFramesNeeded(1000 / lastDetectionTime);
2920
+ trackFramesNeeded$1(1000 / lastDetectionTime);
3568
2921
  }
3569
2922
  var documentIsStable = false;
3570
2923
  var documentTooClose = false;
@@ -3576,13 +2929,19 @@ function processDocumentDetectorPrediction(prediction, thresholds, boundaries) {
3576
2929
  if (detectionThresholdMet && documentInBounds && !documentTooClose) {
3577
2930
  var thresholdSet = (_p = thresholds.stability) !== null && _p !== void 0 ? _p : defaultDocumentDetectionThresholds.stability;
3578
2931
  var threshold_1 = thresholdSet[detectedDocumentType];
3579
- var framesNeeded = Math.ceil(average(framesNeededSamples));
2932
+ var framesNeeded = Math.ceil(average(framesNeededSamples$1));
3580
2933
  trackBox(bestDocument.box, framesNeeded);
3581
2934
  documentIsStable = lastNBoxes.length >= framesNeeded && !lastNPairs.some(function (pair) {
3582
2935
  return pair.iou < threshold_1;
3583
2936
  });
3584
2937
  }
3585
2938
  }
2939
+ var bestPDF417;
2940
+ if (detectedObjects.length > 0) {
2941
+ bestPDF417 = detectedObjects.find(function (obj) {
2942
+ return obj.label === 'PDF417';
2943
+ });
2944
+ }
3586
2945
  return {
3587
2946
  prediction: prediction,
3588
2947
  detectedObjects: detectedObjects,
@@ -3599,6 +2958,7 @@ function processDocumentDetectorPrediction(prediction, thresholds, boundaries) {
3599
2958
  singlePageDetectionScore: singlePageDetectionScore,
3600
2959
  singlePageDetectionThresholdMet: singlePageDetectionThresholdMet,
3601
2960
  bestDocument: bestDocument,
2961
+ bestPDF417: bestPDF417,
3602
2962
  documentInBounds: documentInBounds,
3603
2963
  documentTooClose: documentTooClose,
3604
2964
  documentIsStable: documentIsStable,
@@ -3642,6 +3002,43 @@ function testDocumentDetectionAgainstKnownImage(detector) {
3642
3002
  });
3643
3003
  }
3644
3004
 
3005
+ function getFrameDimensions(frame) {
3006
+ var frameWidth = frame.width,
3007
+ frameHeight = frame.height;
3008
+ if (frame instanceof HTMLImageElement) {
3009
+ frameWidth = frame.naturalWidth;
3010
+ frameHeight = frame.naturalHeight;
3011
+ }
3012
+ if (frame instanceof HTMLVideoElement) {
3013
+ frameWidth = frame.videoWidth;
3014
+ frameHeight = frame.videoHeight;
3015
+ }
3016
+ return [frameWidth, frameHeight];
3017
+ }
3018
+
3019
+ var InvisibleCanvasContainer = styled__default.default.div(templateObject_1$M || (templateObject_1$M = __makeTemplateObject(["\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n pointer-events: none;\n user-select: none;\n"], ["\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n pointer-events: none;\n user-select: none;\n"])));
3020
+ var InvisibleCanvas = styled__default.default.canvas(templateObject_2$G || (templateObject_2$G = __makeTemplateObject(["\n display: none;\n"], ["\n display: none;\n"])));
3021
+ function drawToCanvas(canvas, frame, width, height) {
3022
+ if (!canvas) return;
3023
+ var ctx = canvas.getContext('2d');
3024
+ if (!ctx) return;
3025
+ if (!width || !height) {
3026
+ var _a = getFrameDimensions(frame),
3027
+ frameWidth = _a[0],
3028
+ frameHeight = _a[1];
3029
+ width || (width = frameWidth);
3030
+ height || (height = frameHeight);
3031
+ }
3032
+ canvas.width = width;
3033
+ canvas.height = height;
3034
+ ctx.drawImage(frame, 0, 0, width, height);
3035
+ }
3036
+ function clearCanvas(canvas) {
3037
+ var _a;
3038
+ (_a = canvas === null || canvas === void 0 ? void 0 : canvas.getContext('2d')) === null || _a === void 0 ? void 0 : _a.clearRect(0, 0, canvas === null || canvas === void 0 ? void 0 : canvas.width, canvas === null || canvas === void 0 ? void 0 : canvas.height);
3039
+ }
3040
+ var templateObject_1$M, templateObject_2$G;
3041
+
3645
3042
  function useFrameLoop(fn, options) {
3646
3043
  if (options === void 0) {
3647
3044
  options = {};
@@ -5605,13 +5002,278 @@ function DocumentDetectionModelProvider(_a) {
5605
5002
  documentDetectionLastPredictionCanvas: lastPredictionCanvas,
5606
5003
  clearDocumentDetectionLastPredictionCanvas: clearDocumentDetectionLastPredictionCanvas
5607
5004
  };
5608
- }, [start, stop, load, modelLoadState, modelWarmingStartedAt, modelError, modelDownloadProgress, onDocumentDetected, documentDetectionThresholds, documentDetectionBoundaries, clearDocumentDetectionLastPredictionCanvas]);
5609
- return /*#__PURE__*/React__namespace.createElement(DocumentDetectionModelContext.Provider, {
5610
- value: value
5611
- }, /*#__PURE__*/React__namespace.createElement(InvisibleCanvas, {
5612
- key: canvasKey,
5613
- ref: lastPredictionCanvas
5614
- }), children);
5005
+ }, [start, stop, load, modelLoadState, modelWarmingStartedAt, modelError, modelDownloadProgress, onDocumentDetected, documentDetectionThresholds, documentDetectionBoundaries, clearDocumentDetectionLastPredictionCanvas]);
5006
+ return /*#__PURE__*/React__namespace.createElement(DocumentDetectionModelContext.Provider, {
5007
+ value: value
5008
+ }, /*#__PURE__*/React__namespace.createElement(InvisibleCanvas, {
5009
+ key: canvasKey,
5010
+ ref: lastPredictionCanvas
5011
+ }), children);
5012
+ }
5013
+
5014
+ function cropToShoulders(rawCanvas, cropCanvas, resizeCanvas, frame, face, quality, maxHeight) {
5015
+ var _a;
5016
+ if (quality === void 0) {
5017
+ quality = 0.92;
5018
+ }
5019
+ if (!rawCanvas || !cropCanvas || !resizeCanvas) return '';
5020
+ var rawCtx = rawCanvas.getContext('2d');
5021
+ var cropCtx = cropCanvas.getContext('2d');
5022
+ var resizeCtx = resizeCanvas.getContext('2d');
5023
+ if (!rawCtx || !cropCtx || !resizeCtx) throw new Error('could not get 2d context');
5024
+ rawCanvas.width = frame.width;
5025
+ rawCanvas.height = frame.height;
5026
+ rawCtx.putImageData(frame, 0, 0);
5027
+ if (frame.height > frame.width) {
5028
+ cropCanvas.width = frame.width;
5029
+ cropCanvas.height = frame.height;
5030
+ cropCtx.drawImage(rawCanvas, 0, 0, cropCanvas.width, cropCanvas.height);
5031
+ } else {
5032
+ var _b = (_a = face === null || face === void 0 ? void 0 : face.box) !== null && _a !== void 0 ? _a : {
5033
+ xMin: 0,
5034
+ width: frame.width
5035
+ },
5036
+ xMin = _b.xMin,
5037
+ width = _b.width;
5038
+ var desiredWidth = frame.height * 0.6;
5039
+ var faceCenterX = xMin + width / 2;
5040
+ var xPos = Math.max(0, faceCenterX - desiredWidth / 2);
5041
+ cropCanvas.width = desiredWidth;
5042
+ cropCanvas.height = frame.height;
5043
+ cropCtx.drawImage(rawCanvas, xPos, 0, cropCanvas.width, cropCanvas.height, 0, 0, cropCanvas.width, cropCanvas.height);
5044
+ }
5045
+ resizeCanvas.height = maxHeight !== null && maxHeight !== void 0 ? maxHeight : cropCanvas.height;
5046
+ resizeCanvas.width = cropCanvas.width * (resizeCanvas.height / cropCanvas.height);
5047
+ resizeCtx === null || resizeCtx === void 0 ? void 0 : resizeCtx.drawImage(cropCanvas, 0, 0, resizeCanvas.width, resizeCanvas.height);
5048
+ var dataURL = resizeCanvas.toDataURL('image/jpeg', quality);
5049
+ log('cropToShoulders size', new TextEncoder().encode(dataURL).length);
5050
+ clearCanvas(rawCanvas);
5051
+ clearCanvas(cropCanvas);
5052
+ clearCanvas(resizeCanvas);
5053
+ return dataURL;
5054
+ }
5055
+ function cropToDetectedObjectBox(frame, box, canvas, padding) {
5056
+ if (padding === void 0) {
5057
+ padding = 0;
5058
+ }
5059
+ canvas || (canvas = document.createElement('canvas'));
5060
+ var ctx = canvas.getContext('2d');
5061
+ if (!ctx) throw new Error('could not get 2d context');
5062
+ var xMin = box.xMin,
5063
+ yMin = box.yMin,
5064
+ width = box.width,
5065
+ height = box.height;
5066
+ canvas.width = width + padding * 2;
5067
+ canvas.height = height + padding * 2;
5068
+ ctx.drawImage(frame, xMin - padding, yMin - padding, width + padding * 2, height + padding * 2, 0, 0, canvas.width, canvas.height);
5069
+ return canvas;
5070
+ }
5071
+ function cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box, padding) {
5072
+ if (padding === void 0) {
5073
+ padding = 0;
5074
+ }
5075
+ if (!box) return imageData;
5076
+ var cropped = cropToDetectedObjectBox(imageData, box, cropCanvas, padding);
5077
+ var _a = [box.width, box.height],
5078
+ bw = _a[0],
5079
+ bh = _a[1];
5080
+ if (bh <= bw) return cropped;
5081
+ var ctx = rotateCanvas.getContext('2d');
5082
+ if (!ctx) return cropped;
5083
+ rotateCanvas.width = bh;
5084
+ rotateCanvas.height = bw;
5085
+ ctx.clearRect(0, 0, rotateCanvas.width, rotateCanvas.height);
5086
+ ctx.translate(rotateCanvas.width / 2, rotateCanvas.height / 2);
5087
+ ctx.rotate(1.5708); // 90 deg in radians
5088
+ ctx.drawImage(cropped, -bw / 2, -bh / 2);
5089
+ return rotateCanvas;
5090
+ }
5091
+ function resizeIfNecessary(imageData, resizeCanvas, maxWidth) {
5092
+ var width = imageData.width,
5093
+ height = imageData.height;
5094
+ if (width <= maxWidth) return imageData;
5095
+ var resizeCtx = resizeCanvas.getContext('2d');
5096
+ if (!resizeCtx) return imageData;
5097
+ var scale = maxWidth / width;
5098
+ resizeCanvas.width = maxWidth;
5099
+ resizeCanvas.height = height * scale;
5100
+ resizeCtx.drawImage(imageData, 0, 0, resizeCanvas.width, resizeCanvas.height);
5101
+ return resizeCanvas;
5102
+ }
5103
+
5104
+ var defaultFocusModelLoadTimeoutMs = 45000;
5105
+ var defaultFocusThresholds = {
5106
+ idCardFront: {
5107
+ desktop: 0,
5108
+ mobile: 0.3
5109
+ },
5110
+ idCardBack: {
5111
+ desktop: 0,
5112
+ mobile: 0.3
5113
+ },
5114
+ passport: {
5115
+ desktop: 0,
5116
+ mobile: 0.3
5117
+ },
5118
+ singlePage: {
5119
+ desktop: 0,
5120
+ mobile: 0.3
5121
+ }
5122
+ };
5123
+ var classifier$1 = null;
5124
+ var classifierSettings$1 = null;
5125
+ function loadFocusModel() {
5126
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
5127
+ var _a, _b;
5128
+ if (modelAssetPath === void 0) {
5129
+ modelAssetPath = defaultFocusModelPath;
5130
+ }
5131
+ return __generator(this, function (_c) {
5132
+ switch (_c.label) {
5133
+ case 0:
5134
+ if (classifier$1 && (classifierSettings$1 === null || classifierSettings$1 === void 0 ? void 0 : classifierSettings$1.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier$1];
5135
+ closeFocusModel();
5136
+ return [4 /*yield*/, preloadFocusModelDependencies()];
5137
+ case 1:
5138
+ _c.sent();
5139
+ if (modelCapabilities.delegate === 'NONE') {
5140
+ throw new Error('No available delegate for focus detector.');
5141
+ }
5142
+ _b = (_a = tasksVision.ImageClassifier).createFromOptions;
5143
+ return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
5144
+ case 2:
5145
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
5146
+ baseOptions: {
5147
+ modelAssetPath: modelAssetPath,
5148
+ delegate: modelCapabilities.delegate
5149
+ },
5150
+ // canvas: document.createElement('canvas'),
5151
+ runningMode: 'VIDEO'
5152
+ }])];
5153
+ case 3:
5154
+ classifier$1 = _c.sent();
5155
+ classifierSettings$1 = {
5156
+ modelAssetPath: modelAssetPath
5157
+ };
5158
+ return [2 /*return*/, classifier$1];
5159
+ }
5160
+ });
5161
+ });
5162
+ }
5163
+ function closeFocusModel() {
5164
+ classifier$1 === null || classifier$1 === void 0 ? void 0 : classifier$1.close();
5165
+ classifier$1 = null;
5166
+ classifierSettings$1 = null;
5167
+ }
5168
+ function useLoadFocusModel(_a) {
5169
+ var _b = _a.modelPath,
5170
+ modelPath = _b === void 0 ? defaultFocusModelPath : _b,
5171
+ _c = _a.modelLoadTimeoutMs,
5172
+ modelLoadTimeoutMs = _c === void 0 ? defaultFocusModelLoadTimeoutMs : _c,
5173
+ onModelError = _a.onModelError,
5174
+ videoRef = _a.videoRef,
5175
+ _d = _a.shouldLoadModels,
5176
+ shouldLoadModels = _d === void 0 ? true : _d;
5177
+ var _e = React.useState('not-started'),
5178
+ modelLoadState = _e[0],
5179
+ setModelLoadState = _e[1];
5180
+ var _f = React.useState(0),
5181
+ modelDownloadProgress = _f[0],
5182
+ setModelDownloadProgress = _f[1];
5183
+ var _g = React.useState(null),
5184
+ modelWarmingStartedAt = _g[0],
5185
+ setModelWarmingStartedAt = _g[1];
5186
+ var _h = React.useState(null),
5187
+ modelError = _h[0],
5188
+ setModelError = _h[1];
5189
+ React.useEffect(function loadModel() {
5190
+ var _this = this;
5191
+ if (!shouldLoadModels) return;
5192
+ setModelLoadState('downloading');
5193
+ setModelWarmingStartedAt(null);
5194
+ function handleDownloadProgress(event) {
5195
+ setModelDownloadProgress(progressToPercentage(event.detail));
5196
+ }
5197
+ document.addEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
5198
+ var modelLoadTimeout = setTimeout(function () {
5199
+ setModelError(new Error('Model loading time limit exceeded.'));
5200
+ }, modelLoadTimeoutMs);
5201
+ var cancelVideoReady = function cancelVideoReady() {};
5202
+ loadFocusModel(modelPath).then(function (loadedModel) {
5203
+ return __awaiter(_this, void 0, void 0, function () {
5204
+ var _a, videoReady, cancel, cancelled;
5205
+ return __generator(this, function (_b) {
5206
+ switch (_b.label) {
5207
+ case 0:
5208
+ setModelDownloadProgress(100);
5209
+ clearTimeout(modelLoadTimeout);
5210
+ setModelLoadState('warming');
5211
+ setModelWarmingStartedAt(performance.now());
5212
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
5213
+ cancelled = false;
5214
+ cancelVideoReady = function cancelVideoReady() {
5215
+ cancelled = true;
5216
+ cancel();
5217
+ };
5218
+ return [4 /*yield*/, videoReady];
5219
+ case 1:
5220
+ _b.sent();
5221
+ setTimeout(function () {
5222
+ if (cancelled) return;
5223
+ loadedModel.classifyForVideo(videoRef.current, performance.now());
5224
+ setModelLoadState('ready');
5225
+ }, 500);
5226
+ return [2 /*return*/];
5227
+ }
5228
+ });
5229
+ });
5230
+ })["catch"](function (e) {
5231
+ setModelError(e);
5232
+ setModelLoadState('error');
5233
+ })["finally"](function () {
5234
+ clearTimeout(modelLoadTimeout);
5235
+ });
5236
+ return function () {
5237
+ log('unloading focus model');
5238
+ cancelVideoReady();
5239
+ closeFocusModel();
5240
+ clearTimeout(modelLoadTimeout);
5241
+ document.removeEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
5242
+ };
5243
+ }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
5244
+ React.useEffect(function handleModelError() {
5245
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
5246
+ }, [modelError, onModelError]);
5247
+ return React.useMemo(function () {
5248
+ return {
5249
+ ready: modelLoadState === 'ready',
5250
+ modelLoadState: modelLoadState,
5251
+ modelDownloadProgress: modelDownloadProgress,
5252
+ modelWarmingStartedAt: modelWarmingStartedAt,
5253
+ modelError: modelError
5254
+ };
5255
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
5256
+ }
5257
+ var lastFocusPredictionAt = 0;
5258
+ var lastFocusPredictionTime = 0;
5259
+ function setLastFocusPredictionAt(time) {
5260
+ lastFocusPredictionTime = time - lastFocusPredictionAt;
5261
+ lastFocusPredictionAt = time;
5262
+ }
5263
+ function makeFocusModelPrediction(imageData, cropCanvas, rotateCanvas, box) {
5264
+ var _a, _b, _c, _d, _e;
5265
+ if (!classifier$1) return null;
5266
+ var startedAt = performance.now();
5267
+ var image = cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box);
5268
+ var result = classifier$1.classifyForVideo(image, performance.now());
5269
+ var score = (_e = (_d = (_c = (_b = (_a = result === null || result === void 0 ? void 0 : result.classifications) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.categories) === null || _c === void 0 ? void 0 : _c.find(function (c) {
5270
+ return c.categoryName === 'focused';
5271
+ })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
5272
+ var predictionTime = performance.now() - startedAt;
5273
+ return {
5274
+ score: score,
5275
+ predictionTime: predictionTime
5276
+ };
5615
5277
  }
5616
5278
 
5617
5279
  var FocusModelContext = /*#__PURE__*/React.createContext({
@@ -5688,7 +5350,7 @@ function FocusModelProvider(_a) {
5688
5350
  }, [focusThresholds, load, makeFocusPrediction, modelDownloadProgress, modelError, modelLoadState, modelWarmingStartedAt]);
5689
5351
  return /*#__PURE__*/React__namespace.default.createElement(FocusModelContext.Provider, {
5690
5352
  value: value
5691
- }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5353
+ }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5692
5354
  ref: rotateCanvas,
5693
5355
  style: showCanvases ? {
5694
5356
  display: 'block'
@@ -5698,7 +5360,7 @@ function FocusModelProvider(_a) {
5698
5360
  style: showCanvases ? {
5699
5361
  display: 'block'
5700
5362
  } : undefined
5701
- }), children);
5363
+ })), children);
5702
5364
  }
5703
5365
 
5704
5366
  function _isNavigatorDefined() {
@@ -5733,7 +5395,379 @@ function evaluateIsMobile(nav) {
5733
5395
  return false;
5734
5396
  }
5735
5397
 
5398
+ var defaultBarcodeReadabilityModelLoadTimeoutMs = 45000;
5399
+ var classifier = null;
5400
+ var classifierSettings = null;
5401
+ function loadBarcodeReadabilityModel() {
5402
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
5403
+ var _a, _b;
5404
+ if (modelAssetPath === void 0) {
5405
+ modelAssetPath = defaultBarcodeReadabilityModelPath;
5406
+ }
5407
+ return __generator(this, function (_c) {
5408
+ switch (_c.label) {
5409
+ case 0:
5410
+ if (classifier && (classifierSettings === null || classifierSettings === void 0 ? void 0 : classifierSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier];
5411
+ closeBarcodeReadabilityModel();
5412
+ return [4 /*yield*/, preloadBarcodeReadabilityModelDependencies()];
5413
+ case 1:
5414
+ _c.sent();
5415
+ if (modelCapabilities.delegate === 'NONE') {
5416
+ throw new Error('No available delegate for barcode readability model.');
5417
+ }
5418
+ _b = (_a = tasksVision.ImageClassifier).createFromOptions;
5419
+ return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
5420
+ case 2:
5421
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
5422
+ baseOptions: {
5423
+ modelAssetPath: modelAssetPath,
5424
+ delegate: 'CPU'
5425
+ },
5426
+ runningMode: 'VIDEO',
5427
+ maxResults: 1
5428
+ }])];
5429
+ case 3:
5430
+ classifier = _c.sent();
5431
+ classifierSettings = {
5432
+ modelAssetPath: modelAssetPath
5433
+ };
5434
+ return [2 /*return*/, classifier];
5435
+ }
5436
+ });
5437
+ });
5438
+ }
5439
+ function closeBarcodeReadabilityModel() {
5440
+ classifier === null || classifier === void 0 ? void 0 : classifier.close();
5441
+ classifier = null;
5442
+ classifierSettings = null;
5443
+ }
5444
+ function useLoadBarcodeReadabilityModel(_a) {
5445
+ var _b = _a.modelPath,
5446
+ modelPath = _b === void 0 ? defaultBarcodeReadabilityModelPath : _b,
5447
+ _c = _a.modelLoadTimeoutMs,
5448
+ modelLoadTimeoutMs = _c === void 0 ? defaultBarcodeReadabilityModelLoadTimeoutMs : _c,
5449
+ onModelError = _a.onModelError,
5450
+ videoRef = _a.videoRef,
5451
+ _d = _a.shouldLoadModels,
5452
+ shouldLoadModels = _d === void 0 ? true : _d;
5453
+ var _e = React.useState('not-started'),
5454
+ modelLoadState = _e[0],
5455
+ setModelLoadState = _e[1];
5456
+ var _f = React.useState(0),
5457
+ modelDownloadProgress = _f[0],
5458
+ setModelDownloadProgress = _f[1];
5459
+ var _g = React.useState(null),
5460
+ modelWarmingStartedAt = _g[0],
5461
+ setModelWarmingStartedAt = _g[1];
5462
+ var _h = React.useState(null),
5463
+ modelError = _h[0],
5464
+ setModelError = _h[1];
5465
+ React.useEffect(function loadModel() {
5466
+ var _this = this;
5467
+ if (!shouldLoadModels) return;
5468
+ setModelLoadState('downloading');
5469
+ setModelWarmingStartedAt(null);
5470
+ function handleDownloadProgress(event) {
5471
+ setModelDownloadProgress(progressToPercentage(event.detail));
5472
+ }
5473
+ document.addEventListener('idmission.preloadProgress.barcodeReadability', handleDownloadProgress);
5474
+ var modelLoadTimeout = setTimeout(function () {
5475
+ setModelError(new Error('Model loading time limit exceeded.'));
5476
+ }, modelLoadTimeoutMs);
5477
+ var cancelVideoReady = function cancelVideoReady() {};
5478
+ loadBarcodeReadabilityModel(modelPath).then(function (loadedModel) {
5479
+ return __awaiter(_this, void 0, void 0, function () {
5480
+ var _a, videoReady, cancel, cancelled;
5481
+ return __generator(this, function (_b) {
5482
+ switch (_b.label) {
5483
+ case 0:
5484
+ setModelDownloadProgress(100);
5485
+ clearTimeout(modelLoadTimeout);
5486
+ setModelLoadState('warming');
5487
+ setModelWarmingStartedAt(new Date().getTime());
5488
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
5489
+ cancelled = false;
5490
+ cancelVideoReady = function cancelVideoReady() {
5491
+ cancelled = true;
5492
+ cancel();
5493
+ };
5494
+ return [4 /*yield*/, videoReady];
5495
+ case 1:
5496
+ _b.sent();
5497
+ setTimeout(function () {
5498
+ if (cancelled) return;
5499
+ loadedModel.classifyForVideo(videoRef.current, performance.now());
5500
+ setModelLoadState('ready');
5501
+ }, 500);
5502
+ return [2 /*return*/];
5503
+ }
5504
+ });
5505
+ });
5506
+ })["catch"](function (e) {
5507
+ setModelError(e);
5508
+ setModelLoadState('error');
5509
+ })["finally"](function () {
5510
+ clearTimeout(modelLoadTimeout);
5511
+ });
5512
+ return function () {
5513
+ log('unloading barcode readability model');
5514
+ cancelVideoReady();
5515
+ closeBarcodeReadabilityModel();
5516
+ clearTimeout(modelLoadTimeout);
5517
+ document.removeEventListener('idmission.preloadProgress.barcodeReadability', handleDownloadProgress);
5518
+ };
5519
+ }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
5520
+ React.useEffect(function handleModelError() {
5521
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
5522
+ }, [modelError, onModelError]);
5523
+ return React.useMemo(function () {
5524
+ return {
5525
+ ready: modelLoadState === 'ready',
5526
+ modelLoadState: modelLoadState,
5527
+ modelDownloadProgress: modelDownloadProgress,
5528
+ modelWarmingStartedAt: modelWarmingStartedAt,
5529
+ modelError: modelError
5530
+ };
5531
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
5532
+ }
5533
+ var lastBarcodeReadabilityPredictionAt = 0;
5534
+ var lastBarcodeReadabilityPredictionTime = 0;
5535
+ function setLastBarcodeReadabilityPredictionAt(time) {
5536
+ lastBarcodeReadabilityPredictionTime = time - lastBarcodeReadabilityPredictionAt;
5537
+ lastBarcodeReadabilityPredictionAt = time;
5538
+ }
5539
+ function makeBarcodeReadabilityModelPrediction(imageData, cropCanvas, rotateCanvas, resizeCanvas, box) {
5540
+ var _a, _b, _c, _d, _e;
5541
+ if (!classifier) return null;
5542
+ var startedAt = performance.now();
5543
+ var image = cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box);
5544
+ var resized = resizeIfNecessary(image, resizeCanvas, 500);
5545
+ var result = classifier.classifyForVideo(resized, performance.now());
5546
+ var score = (_e = (_d = (_c = (_b = (_a = result === null || result === void 0 ? void 0 : result.classifications) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.categories) === null || _c === void 0 ? void 0 : _c.find(function (c) {
5547
+ return c.categoryName === 'blurry';
5548
+ })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
5549
+ debug('barcode prediction', "".concat(performance.now() - startedAt, "ms"), score);
5550
+ var predictionTime = performance.now() - startedAt;
5551
+ return {
5552
+ score: score,
5553
+ predictionTime: predictionTime
5554
+ };
5555
+ }
5556
+
5557
+ var BarcodeReadabilityModelContext = /*#__PURE__*/React.createContext({
5558
+ loadBarcodeReadabilityModel: function loadBarcodeReadabilityModel() {
5559
+ return null;
5560
+ },
5561
+ barcodeReadabilityModelState: 'not-started',
5562
+ barcodeReadabilityModelDownloadProgress: 0,
5563
+ barcodeReadabilityModelWarmingStartedAt: null,
5564
+ barcodeReadabilityModelError: null,
5565
+ barcodeReadabilityThresholds: {},
5566
+ setBarcodeReadabilityThresholds: function setBarcodeReadabilityThresholds() {
5567
+ return null;
5568
+ },
5569
+ makeBarcodeReadabilityPrediction: function makeBarcodeReadabilityPrediction() {
5570
+ return null;
5571
+ },
5572
+ barcodeReadabilityPredictionTime: 0
5573
+ });
5574
+ function BarcodeReadabilityModelProvider(_a) {
5575
+ var children = _a.children,
5576
+ _b = _a.barcodeReadabilityModelPath,
5577
+ barcodeReadabilityModelPath = _b === void 0 ? defaultBarcodeReadabilityModelPath : _b,
5578
+ _c = _a.barcodeReadabilityModelLoadTimeoutMs,
5579
+ barcodeReadabilityModelLoadTimeoutMs = _c === void 0 ? defaultBarcodeReadabilityModelLoadTimeoutMs : _c,
5580
+ onBarcodeReadabilityModelError = _a.onBarcodeReadabilityModelError,
5581
+ _d = _a.showCanvases,
5582
+ showCanvases = _d === void 0 ? false : _d,
5583
+ _e = _a.shouldLoadModels,
5584
+ shouldLoadModelsProp = _e === void 0 ? true : _e;
5585
+ var cropCanvas = React.useRef(null);
5586
+ var rotateCanvas = React.useRef(null);
5587
+ var resizeCanvas = React.useRef(null);
5588
+ var _f = React.useState({}),
5589
+ barcodeReadabilityThresholds = _f[0],
5590
+ setBarcodeReadabilityThresholds = _f[1];
5591
+ var videoRef = useCameraStore().videoRef;
5592
+ var _g = React.useState(shouldLoadModelsProp),
5593
+ shouldLoadModels = _g[0],
5594
+ setShouldLoadModels = _g[1];
5595
+ var load = React.useCallback(function () {
5596
+ return setShouldLoadModels(true);
5597
+ }, []);
5598
+ var _h = useLoadBarcodeReadabilityModel({
5599
+ modelPath: barcodeReadabilityModelPath,
5600
+ modelLoadTimeoutMs: barcodeReadabilityModelLoadTimeoutMs,
5601
+ onModelError: onBarcodeReadabilityModelError,
5602
+ videoRef: videoRef,
5603
+ shouldLoadModels: shouldLoadModels
5604
+ }),
5605
+ ready = _h.ready,
5606
+ modelLoadState = _h.modelLoadState,
5607
+ modelDownloadProgress = _h.modelDownloadProgress,
5608
+ modelWarmingStartedAt = _h.modelWarmingStartedAt,
5609
+ modelError = _h.modelError;
5610
+ var makeBarcodeReadabilityPrediction = React.useCallback(function (imageData, box) {
5611
+ if (!ready) return null;
5612
+ var prediction = makeBarcodeReadabilityModelPrediction(imageData, cropCanvas.current, rotateCanvas.current, resizeCanvas.current, box);
5613
+ if (!prediction) return null;
5614
+ setLastBarcodeReadabilityPredictionAt(prediction.predictionTime);
5615
+ return prediction;
5616
+ }, [ready]);
5617
+ var value = React.useMemo(function () {
5618
+ return {
5619
+ loadBarcodeReadabilityModel: load,
5620
+ barcodeReadabilityModelState: modelLoadState,
5621
+ barcodeReadabilityModelDownloadProgress: modelDownloadProgress,
5622
+ barcodeReadabilityModelWarmingStartedAt: modelWarmingStartedAt,
5623
+ barcodeReadabilityModelError: modelError,
5624
+ makeBarcodeReadabilityPrediction: makeBarcodeReadabilityPrediction,
5625
+ barcodeReadabilityPredictionTime: lastBarcodeReadabilityPredictionTime,
5626
+ barcodeReadabilityThresholds: barcodeReadabilityThresholds,
5627
+ setBarcodeReadabilityThresholds: setBarcodeReadabilityThresholds
5628
+ };
5629
+ }, [barcodeReadabilityThresholds, load, makeBarcodeReadabilityPrediction, modelDownloadProgress, modelError, modelLoadState, modelWarmingStartedAt]);
5630
+ return /*#__PURE__*/React__namespace.default.createElement(BarcodeReadabilityModelContext.Provider, {
5631
+ value: value
5632
+ }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5633
+ ref: rotateCanvas
5634
+ }), /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5635
+ ref: cropCanvas
5636
+ }), /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5637
+ ref: resizeCanvas,
5638
+ style: showCanvases ? {
5639
+ display: 'block'
5640
+ } : undefined
5641
+ })), children);
5642
+ }
5643
+ function useBarcodeReadabilityModelContext() {
5644
+ var context = React.useContext(BarcodeReadabilityModelContext);
5645
+ if (!context) {
5646
+ throw new Error('useBarcodeReadabilityModelContext must be used within a BarcodeReadabilityModelProvider');
5647
+ }
5648
+ return context;
5649
+ }
5650
+
5736
5651
  var onMobile = isMobile();
5652
+ /**
5653
+ * Analyzes barcode readability for a detected document
5654
+ * @param prediction The document detection prediction
5655
+ * @param lastPredictionCanvas The canvas containing the original frame
5656
+ * @param croppedDocumentCanvas Canvas for storing cropped document
5657
+ * @param bestBarcodeCanvas Canvas for storing best barcode crop
5658
+ * @param currentBestBarcodeScore Current best barcode score
5659
+ * @param documentDetectionThresholds Thresholds for document detection
5660
+ * @param makeBarcodeReadabilityPrediction Function to make barcode readability predictions
5661
+ * @param barcodeReadabilityThresholds Thresholds for barcode readability
5662
+ * @returns Object containing barcode analysis results
5663
+ */
5664
+ function analyzeBarcodeReadability(prediction, lastPredictionCanvas, croppedDocumentCanvas, bestBarcodeCanvas, currentBestBarcodeScore, documentDetectionThresholds, makeBarcodeReadabilityPrediction, barcodeReadabilityThreshold) {
5665
+ return __awaiter(this, void 0, void 0, function () {
5666
+ var pdf417PredictionTime, pdf417PredictionScore, pdf417PredictionThresholdMet, newBestBarcodeScore, newBestBarcodeDetails, documentCroppedPrediction, processedCroppedPrediction, pdf417Prediction;
5667
+ var _a;
5668
+ return __generator(this, function (_b) {
5669
+ switch (_b.label) {
5670
+ case 0:
5671
+ pdf417PredictionTime = 0;
5672
+ pdf417PredictionScore = 0;
5673
+ pdf417PredictionThresholdMet = false;
5674
+ if (!prediction.bestDocument || !((_a = prediction.bestPDF417) === null || _a === void 0 ? void 0 : _a.box) || !bestBarcodeCanvas) {
5675
+ return [2 /*return*/, {
5676
+ pdf417PredictionTime: pdf417PredictionTime,
5677
+ pdf417PredictionScore: pdf417PredictionScore,
5678
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet,
5679
+ newBestBarcodeScore: newBestBarcodeScore,
5680
+ newBestBarcodeDetails: newBestBarcodeDetails
5681
+ }];
5682
+ }
5683
+ /**
5684
+ * Step 1: Crop the full frame to just the document area
5685
+ * This removes background noise and focuses analysis on the document
5686
+ */
5687
+ cropToDetectedObjectBox(lastPredictionCanvas, prediction.bestDocument.box, croppedDocumentCanvas);
5688
+ return [4 /*yield*/, makeDocumentDetectorPrediction(croppedDocumentCanvas)];
5689
+ case 1:
5690
+ documentCroppedPrediction = _b.sent();
5691
+ if (!documentCroppedPrediction) {
5692
+ // error occurred during prediction (error logged by callee)
5693
+ return [2 /*return*/, {
5694
+ pdf417PredictionTime: pdf417PredictionTime,
5695
+ pdf417PredictionScore: pdf417PredictionScore,
5696
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet,
5697
+ newBestBarcodeScore: newBestBarcodeScore,
5698
+ newBestBarcodeDetails: newBestBarcodeDetails
5699
+ }];
5700
+ }
5701
+ processedCroppedPrediction = processDocumentDetectorPrediction(documentCroppedPrediction, documentDetectionThresholds);
5702
+ if (processedCroppedPrediction.bestPDF417) {
5703
+ pdf417Prediction = makeBarcodeReadabilityPrediction(croppedDocumentCanvas, processedCroppedPrediction.bestPDF417.box);
5704
+ if (pdf417Prediction) {
5705
+ pdf417PredictionTime = pdf417Prediction.predictionTime;
5706
+ pdf417PredictionScore = pdf417Prediction.score;
5707
+ if (pdf417Prediction.score > currentBestBarcodeScore) {
5708
+ /**
5709
+ * Step 5: Update best barcode
5710
+ */
5711
+ newBestBarcodeScore = pdf417Prediction.score;
5712
+ newBestBarcodeDetails = {
5713
+ boundingBox: prediction.bestPDF417.box,
5714
+ score: pdf417Prediction.score
5715
+ };
5716
+ if (pdf417PredictionScore >= barcodeReadabilityThreshold) {
5717
+ pdf417PredictionThresholdMet = true;
5718
+ }
5719
+ cropToDetectedObjectBox(croppedDocumentCanvas, processedCroppedPrediction.bestPDF417.box, bestBarcodeCanvas, 16);
5720
+ }
5721
+ }
5722
+ }
5723
+ return [2 /*return*/, {
5724
+ pdf417PredictionTime: pdf417PredictionTime,
5725
+ pdf417PredictionScore: pdf417PredictionScore,
5726
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet,
5727
+ newBestBarcodeScore: newBestBarcodeScore,
5728
+ newBestBarcodeDetails: newBestBarcodeDetails
5729
+ }];
5730
+ }
5731
+ });
5732
+ });
5733
+ }
5734
+ /**
5735
+ * Calculates the barcode readability threshold for a given document type
5736
+ * @param detectedDocumentType The type of document detected
5737
+ * @param barcodeReadabilityThresholds The threshold configuration object
5738
+ * @returns The appropriate threshold value for the current platform (mobile/desktop)
5739
+ */
5740
+ function calculateBarcodeReadabilityThreshold(detectedDocumentType, barcodeReadabilityThresholds) {
5741
+ var barcodeReadabilityThresholdSet = detectedDocumentType in barcodeReadabilityThresholds ? barcodeReadabilityThresholds[detectedDocumentType] : undefined;
5742
+ if (barcodeReadabilityThresholdSet) {
5743
+ return onMobile ? barcodeReadabilityThresholdSet.mobile || 0 : barcodeReadabilityThresholdSet.desktop || 0;
5744
+ }
5745
+ return 0;
5746
+ }
5747
+ /**
5748
+ * Hook that calculates the barcode readability threshold for a given document type
5749
+ */
5750
+ function useBarcodeReadabilityThreshold() {
5751
+ var barcodeReadabilityThresholds = useBarcodeReadabilityModelContext().barcodeReadabilityThresholds;
5752
+ return React.useCallback(function (detectedDocumentType) {
5753
+ return calculateBarcodeReadabilityThreshold(detectedDocumentType, barcodeReadabilityThresholds);
5754
+ }, [barcodeReadabilityThresholds]);
5755
+ }
5756
+ function useBarcodeReadabilityAnalysis() {
5757
+ var _this = this;
5758
+ var documentDetectionThresholds = React.useContext(DocumentDetectionModelContext).documentDetectionThresholds;
5759
+ var makeBarcodeReadabilityPrediction = useBarcodeReadabilityModelContext().makeBarcodeReadabilityPrediction;
5760
+ var getBarcodeReadabilityThreshold = useBarcodeReadabilityThreshold();
5761
+ return React.useCallback(function (prediction, lastPredictionCanvas, croppedDocumentCanvas, bestBarcodeCanvas, currentBestBarcodeScore) {
5762
+ return __awaiter(_this, void 0, void 0, function () {
5763
+ var barcodeReadabilityThreshold;
5764
+ return __generator(this, function (_a) {
5765
+ barcodeReadabilityThreshold = getBarcodeReadabilityThreshold(prediction.detectedDocumentType);
5766
+ return [2 /*return*/, analyzeBarcodeReadability(prediction, lastPredictionCanvas, croppedDocumentCanvas, bestBarcodeCanvas, currentBestBarcodeScore, documentDetectionThresholds, makeBarcodeReadabilityPrediction, barcodeReadabilityThreshold)];
5767
+ });
5768
+ });
5769
+ }, [documentDetectionThresholds, makeBarcodeReadabilityPrediction, getBarcodeReadabilityThreshold]);
5770
+ }
5737
5771
  var defaultIdCaptureThresholds = {
5738
5772
  detection: defaultDocumentDetectionThresholds,
5739
5773
  focus: defaultFocusThresholds
@@ -5766,6 +5800,7 @@ var IdCaptureModelsContext = /*#__PURE__*/React.createContext({
5766
5800
  },
5767
5801
  detectionTime: 0,
5768
5802
  focusPredictionTime: 0,
5803
+ barcodeReadabilityPredictionTime: 0,
5769
5804
  bestFrameDetails: {
5770
5805
  current: null
5771
5806
  },
@@ -5775,55 +5810,80 @@ var IdCaptureModelsContext = /*#__PURE__*/React.createContext({
5775
5810
  resetBestFrame: function resetBestFrame() {
5776
5811
  return null;
5777
5812
  },
5813
+ bestBarcodeDetails: {
5814
+ current: null
5815
+ },
5816
+ getBestBarcode: function getBestBarcode() {
5817
+ return null;
5818
+ },
5778
5819
  requiredDocumentType: 'none',
5779
5820
  setRequiredDocumentType: function setRequiredDocumentType() {
5780
5821
  return null;
5781
5822
  }
5782
5823
  });
5783
5824
  function IdCaptureModelsProviderInner(_a) {
5825
+ var _b;
5784
5826
  var children = _a.children,
5785
5827
  onModelError = _a.onModelError,
5786
- _b = _a.allowSinglePageIdCapture,
5787
- allowSinglePageIdCapture = _b === void 0 ? false : _b;
5788
- var _c = React.useContext(DocumentDetectionModelContext),
5789
- documentDetectionModelState = _c.documentDetectionModelState,
5790
- documentDetectionModelDownloadProgress = _c.documentDetectionModelDownloadProgress,
5791
- documentDetectionModelWarmingStartedAt = _c.documentDetectionModelWarmingStartedAt,
5792
- startDocumentDetection = _c.startDocumentDetection,
5793
- stopDocumentDetection = _c.stopDocumentDetection,
5794
- loadDocumentDetectionModel = _c.loadDocumentDetectionModel,
5795
- lastPredictionCanvas = _c.documentDetectionLastPredictionCanvas,
5796
- clearDocumentDetectionLastPredictionCanvas = _c.clearDocumentDetectionLastPredictionCanvas,
5797
- onDocumentDetected = _c.onDocumentDetected,
5798
- detectionTime = _c.detectionTime,
5799
- documentDetectionThresholds = _c.documentDetectionThresholds,
5800
- setDocumentDetectionThresholds = _c.setDocumentDetectionThresholds,
5801
- documentDetectionBoundaries = _c.documentDetectionBoundaries,
5802
- setDocumentDetectionBoundaries = _c.setDocumentDetectionBoundaries,
5803
- documentDetectionModelError = _c.documentDetectionModelError;
5804
- var _d = React.useContext(FocusModelContext),
5805
- loadFocusModel = _d.loadFocusModel,
5806
- focusModelState = _d.focusModelState,
5807
- focusModelDownloadProgress = _d.focusModelDownloadProgress,
5808
- focusModelWarmingStartedAt = _d.focusModelWarmingStartedAt,
5809
- makeFocusPrediction = _d.makeFocusPrediction,
5810
- focusThresholds = _d.focusThresholds,
5811
- setFocusThresholds = _d.setFocusThresholds,
5812
- focusPredictionTime = _d.focusPredictionTime,
5813
- focusModelError = _d.focusModelError;
5828
+ _c = _a.allowSinglePageIdCapture,
5829
+ allowSinglePageIdCapture = _c === void 0 ? false : _c,
5830
+ _d = _a.enableBarcodeReadabilityModel,
5831
+ enableBarcodeReadabilityModel = _d === void 0 ? true : _d;
5832
+ var _e = React.useContext(DocumentDetectionModelContext),
5833
+ documentDetectionModelState = _e.documentDetectionModelState,
5834
+ documentDetectionModelDownloadProgress = _e.documentDetectionModelDownloadProgress,
5835
+ documentDetectionModelWarmingStartedAt = _e.documentDetectionModelWarmingStartedAt,
5836
+ startDocumentDetection = _e.startDocumentDetection,
5837
+ stopDocumentDetection = _e.stopDocumentDetection,
5838
+ loadDocumentDetectionModel = _e.loadDocumentDetectionModel,
5839
+ lastPredictionCanvas = _e.documentDetectionLastPredictionCanvas,
5840
+ clearDocumentDetectionLastPredictionCanvas = _e.clearDocumentDetectionLastPredictionCanvas,
5841
+ onDocumentDetected = _e.onDocumentDetected,
5842
+ detectionTime = _e.detectionTime,
5843
+ documentDetectionThresholds = _e.documentDetectionThresholds,
5844
+ setDocumentDetectionThresholds = _e.setDocumentDetectionThresholds,
5845
+ documentDetectionBoundaries = _e.documentDetectionBoundaries,
5846
+ setDocumentDetectionBoundaries = _e.setDocumentDetectionBoundaries,
5847
+ documentDetectionModelError = _e.documentDetectionModelError;
5848
+ var _f = React.useContext(FocusModelContext),
5849
+ loadFocusModel = _f.loadFocusModel,
5850
+ focusModelState = _f.focusModelState,
5851
+ focusModelDownloadProgress = _f.focusModelDownloadProgress,
5852
+ focusModelWarmingStartedAt = _f.focusModelWarmingStartedAt,
5853
+ makeFocusPrediction = _f.makeFocusPrediction,
5854
+ focusThresholds = _f.focusThresholds,
5855
+ setFocusThresholds = _f.setFocusThresholds,
5856
+ focusPredictionTime = _f.focusPredictionTime,
5857
+ focusModelError = _f.focusModelError;
5858
+ var _g = useBarcodeReadabilityModelContext(),
5859
+ loadBarcodeReadabilityModel = _g.loadBarcodeReadabilityModel,
5860
+ barcodeReadabilityModelState = _g.barcodeReadabilityModelState,
5861
+ barcodeReadabilityModelDownloadProgress = _g.barcodeReadabilityModelDownloadProgress,
5862
+ barcodeReadabilityModelWarmingStartedAt = _g.barcodeReadabilityModelWarmingStartedAt,
5863
+ makeBarcodeReadabilityPrediction = _g.makeBarcodeReadabilityPrediction,
5864
+ barcodeReadabilityThresholds = _g.barcodeReadabilityThresholds,
5865
+ setBarcodeReadabilityThresholds = _g.setBarcodeReadabilityThresholds,
5866
+ barcodeReadabilityPredictionTime = _g.barcodeReadabilityPredictionTime,
5867
+ barcodeReadabilityModelError = _g.barcodeReadabilityModelError;
5814
5868
  var onPredictionHandler = React.useRef();
5815
5869
  var bestFrameDetails = React.useRef(null);
5870
+ var bestBarcodeDetails = React.useRef(null);
5816
5871
  var bestPredictionCanvas = React.useRef(null);
5872
+ var bestBarcodeCanvas = React.useRef(null);
5873
+ var croppedDocumentCanvas = React.useRef(null);
5817
5874
  var bestFocusScore = React.useRef(0);
5875
+ var bestBarcodeScore = React.useRef(0);
5818
5876
  var stopDetection = React.useRef(0);
5819
- var _e = React.useState('none'),
5820
- requiredDocumentType = _e[0],
5821
- setRequiredDocumentType = _e[1];
5877
+ var analyzeBarcodeReadability = useBarcodeReadabilityAnalysis();
5878
+ var _h = React.useState('none'),
5879
+ requiredDocumentType = _h[0],
5880
+ setRequiredDocumentType = _h[1];
5822
5881
  var thresholds = React.useMemo(function () {
5823
5882
  return _assign(_assign({}, documentDetectionThresholds), {
5824
- focus: focusThresholds
5883
+ focus: focusThresholds,
5884
+ barcodeReadability: barcodeReadabilityThresholds
5825
5885
  });
5826
- }, [documentDetectionThresholds, focusThresholds]);
5886
+ }, [documentDetectionThresholds, focusThresholds, barcodeReadabilityThresholds]);
5827
5887
  var setThresholds = React.useCallback(function (thresholds) {
5828
5888
  if (thresholds.detection) {
5829
5889
  setDocumentDetectionThresholds(thresholds.detection);
@@ -5831,57 +5891,87 @@ function IdCaptureModelsProviderInner(_a) {
5831
5891
  if (thresholds.focus) {
5832
5892
  setFocusThresholds(thresholds.focus);
5833
5893
  }
5834
- }, [setDocumentDetectionThresholds, setFocusThresholds]);
5894
+ if (thresholds.barcodeReadability) {
5895
+ setBarcodeReadabilityThresholds(thresholds.barcodeReadability);
5896
+ }
5897
+ }, [setBarcodeReadabilityThresholds, setDocumentDetectionThresholds, setFocusThresholds]);
5835
5898
  React.useEffect(function handleDetections() {
5836
5899
  var _this = this;
5837
5900
  onDocumentDetected(function (prediction) {
5838
5901
  return __awaiter(_this, void 0, void 0, function () {
5839
- var stopDetectionAtStart, focusPredictionTime, focusScore, focusThresholdMet, isSinglePage, isRequiredDocumentType, focusPrediction, focusThresholdSet, focusThreshold;
5902
+ var stopDetectionAtStart, focusPredictionTime, focusScore, focusThresholdMet, pdf417PredictionTime, pdf417PredictionScore, pdf417PredictionThresholdMet, isSinglePage, isRequiredDocumentType, focusPrediction, focusThresholdSet, focusThreshold, barcodeAnalysisResult;
5840
5903
  var _a, _b, _c, _d, _e, _f, _g;
5841
5904
  return __generator(this, function (_h) {
5842
- if (!lastPredictionCanvas.current) return [2 /*return*/];
5843
- stopDetectionAtStart = stopDetection.current;
5844
- focusPredictionTime = 0, focusScore = 0, focusThresholdMet = false;
5845
- isSinglePage = prediction.detectedDocumentType === 'singlePage';
5846
- if (!allowSinglePageIdCapture && isSinglePage) {
5847
- prediction.detectedDocumentType = 'passport';
5848
- prediction.passportDetectionScore = prediction.singlePageDetectionScore;
5849
- prediction.passportDetectionThresholdMet = prediction.singlePageDetectionThresholdMet;
5850
- prediction.singlePageDetectionScore = 0;
5851
- prediction.singlePageDetectionThresholdMet = false;
5852
- }
5853
- isRequiredDocumentType = requiredDocumentType === 'none' || prediction.detectedDocumentType === requiredDocumentType || ((_a = requiredDocumentType.includes) === null || _a === void 0 ? void 0 : _a.call(requiredDocumentType, prediction.detectedDocumentType)) || allowSinglePageIdCapture && isSinglePage && ((_b = requiredDocumentType.includes) === null || _b === void 0 ? void 0 : _b.call(requiredDocumentType, 'idCardFront'));
5854
- if (isRequiredDocumentType && prediction.detectedDocumentType !== 'none' && prediction.detectionThresholdMet && prediction.documentInBounds && !prediction.documentTooClose && prediction.documentIsStable) {
5855
- focusPrediction = makeFocusPrediction(lastPredictionCanvas.current, (_c = prediction.bestDocument) === null || _c === void 0 ? void 0 : _c.box);
5856
- if (focusPrediction) {
5857
- focusScore = focusPrediction.score;
5858
- focusPredictionTime = focusPrediction.predictionTime;
5859
- }
5860
- focusThresholdSet = (_d = thresholds.focus) === null || _d === void 0 ? void 0 : _d[prediction.detectedDocumentType];
5861
- 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;
5862
- focusThresholdMet = focusScore >= focusThreshold;
5863
- if (bestFocusScore.current <= focusScore && stopDetectionAtStart === stopDetection.current) {
5864
- bestFocusScore.current = focusScore;
5865
- drawToCanvas(bestPredictionCanvas.current, lastPredictionCanvas.current);
5866
- bestFrameDetails.current = {
5867
- boundingBox: (_f = prediction.bestDocument) === null || _f === void 0 ? void 0 : _f.box,
5868
- documentType: prediction.detectedDocumentType,
5869
- detectionScore: prediction.detectionScore,
5870
- focusScore: focusScore
5871
- };
5872
- }
5905
+ switch (_h.label) {
5906
+ case 0:
5907
+ if (!lastPredictionCanvas.current) return [2 /*return*/];
5908
+ stopDetectionAtStart = stopDetection.current;
5909
+ focusPredictionTime = 0, focusScore = 0, focusThresholdMet = false, pdf417PredictionTime = 0, pdf417PredictionScore = 0, pdf417PredictionThresholdMet = false;
5910
+ isSinglePage = prediction.detectedDocumentType === 'singlePage';
5911
+ if (!allowSinglePageIdCapture && isSinglePage) {
5912
+ prediction.detectedDocumentType = 'passport';
5913
+ prediction.passportDetectionScore = prediction.singlePageDetectionScore;
5914
+ prediction.passportDetectionThresholdMet = prediction.singlePageDetectionThresholdMet;
5915
+ prediction.singlePageDetectionScore = 0;
5916
+ prediction.singlePageDetectionThresholdMet = false;
5917
+ }
5918
+ isRequiredDocumentType = requiredDocumentType === 'none' || prediction.detectedDocumentType === requiredDocumentType || ((_a = requiredDocumentType.includes) === null || _a === void 0 ? void 0 : _a.call(requiredDocumentType, prediction.detectedDocumentType)) || allowSinglePageIdCapture && isSinglePage && ((_b = requiredDocumentType.includes) === null || _b === void 0 ? void 0 : _b.call(requiredDocumentType, 'idCardFront'));
5919
+ if (!(isRequiredDocumentType && prediction.detectedDocumentType !== 'none' && prediction.detectionThresholdMet && prediction.documentInBounds && !prediction.documentTooClose && prediction.documentIsStable)) return [3 /*break*/, 2];
5920
+ focusPrediction = makeFocusPrediction(lastPredictionCanvas.current, (_c = prediction.bestDocument) === null || _c === void 0 ? void 0 : _c.box);
5921
+ if (focusPrediction) {
5922
+ focusScore = focusPrediction.score;
5923
+ focusPredictionTime = focusPrediction.predictionTime;
5924
+ }
5925
+ focusThresholdSet = (_d = thresholds.focus) === null || _d === void 0 ? void 0 : _d[prediction.detectedDocumentType];
5926
+ focusThreshold = (_e = onMobile ? focusThresholdSet === null || focusThresholdSet === void 0 ? void 0 : focusThresholdSet.mobile : focusThresholdSet === null || focusThresholdSet === void 0 ? void 0 : focusThresholdSet.desktop) !== null && _e !== void 0 ? _e : 0;
5927
+ focusThresholdMet = focusScore >= focusThreshold;
5928
+ if (!(stopDetectionAtStart === stopDetection.current)) return [3 /*break*/, 2];
5929
+ if (bestFocusScore.current <= focusScore) {
5930
+ bestFocusScore.current = focusScore;
5931
+ drawToCanvas(bestPredictionCanvas.current, lastPredictionCanvas.current);
5932
+ bestFrameDetails.current = {
5933
+ boundingBox: (_f = prediction.bestDocument) === null || _f === void 0 ? void 0 : _f.box,
5934
+ documentType: prediction.detectedDocumentType,
5935
+ detectionScore: prediction.detectionScore,
5936
+ focusScore: focusScore
5937
+ };
5938
+ }
5939
+ if (!(enableBarcodeReadabilityModel && prediction.bestDocument && prediction.bestPDF417 && croppedDocumentCanvas.current)) return [3 /*break*/, 2];
5940
+ return [4 /*yield*/, analyzeBarcodeReadability(prediction, lastPredictionCanvas.current, croppedDocumentCanvas.current, bestBarcodeCanvas.current, bestBarcodeScore.current)];
5941
+ case 1:
5942
+ barcodeAnalysisResult = _h.sent();
5943
+ pdf417PredictionTime = barcodeAnalysisResult.pdf417PredictionTime;
5944
+ pdf417PredictionScore = barcodeAnalysisResult.pdf417PredictionScore;
5945
+ pdf417PredictionThresholdMet = barcodeAnalysisResult.pdf417PredictionThresholdMet;
5946
+ if (barcodeAnalysisResult.newBestBarcodeScore) {
5947
+ bestBarcodeScore.current = barcodeAnalysisResult.newBestBarcodeScore;
5948
+ }
5949
+ if (barcodeAnalysisResult.newBestBarcodeDetails) {
5950
+ bestBarcodeDetails.current = barcodeAnalysisResult.newBestBarcodeDetails;
5951
+ }
5952
+ _h.label = 2;
5953
+ case 2:
5954
+ /**
5955
+ * @note
5956
+ * This should ALWAYS be called.
5957
+ * Do not return early from this function unless
5958
+ * lastPredictionCanvas.current is not set
5959
+ */
5960
+ (_g = onPredictionHandler.current) === null || _g === void 0 ? void 0 : _g.call(onPredictionHandler, _assign(_assign({}, prediction), {
5961
+ focusScore: focusScore,
5962
+ focusPredictionTime: focusPredictionTime,
5963
+ focusThresholdMet: focusThresholdMet,
5964
+ pdf417PredictionTime: pdf417PredictionTime,
5965
+ pdf417PredictionScore: pdf417PredictionScore,
5966
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet
5967
+ }));
5968
+ return [2 /*return*/];
5873
5969
  }
5874
- (_g = onPredictionHandler.current) === null || _g === void 0 ? void 0 : _g.call(onPredictionHandler, _assign(_assign({}, prediction), {
5875
- focusScore: focusScore,
5876
- focusPredictionTime: focusPredictionTime,
5877
- focusThresholdMet: focusThresholdMet
5878
- }));
5879
- return [2 /*return*/];
5880
5970
  });
5881
5971
  });
5882
5972
  });
5883
- }, [allowSinglePageIdCapture, lastPredictionCanvas, makeFocusPrediction, onDocumentDetected, requiredDocumentType, thresholds.focus]);
5884
- var modelError = documentDetectionModelError !== null && documentDetectionModelError !== void 0 ? documentDetectionModelError : focusModelError;
5973
+ }, [allowSinglePageIdCapture, analyzeBarcodeReadability, barcodeReadabilityThresholds, enableBarcodeReadabilityModel, lastPredictionCanvas, makeBarcodeReadabilityPrediction, makeFocusPrediction, onDocumentDetected, requiredDocumentType, thresholds.focus]);
5974
+ var modelError = (_b = documentDetectionModelError !== null && documentDetectionModelError !== void 0 ? documentDetectionModelError : focusModelError) !== null && _b !== void 0 ? _b : barcodeReadabilityModelError;
5885
5975
  React.useEffect(function handleModelErrors() {
5886
5976
  if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
5887
5977
  }, [modelError, onModelError]);
@@ -5894,9 +5984,15 @@ function IdCaptureModelsProviderInner(_a) {
5894
5984
  canvas: bestPredictionCanvas.current
5895
5985
  });
5896
5986
  }, []);
5897
- var _f = React.useState(0),
5898
- canvasKey = _f[0],
5899
- setCanvasKey = _f[1];
5987
+ var getBestBarcode = React.useCallback(function () {
5988
+ if (!bestBarcodeDetails.current || !bestBarcodeCanvas.current) return null;
5989
+ return _assign(_assign({}, bestBarcodeDetails.current), {
5990
+ canvas: bestBarcodeCanvas.current
5991
+ });
5992
+ }, []);
5993
+ var _j = React.useState(0),
5994
+ canvasKey = _j[0],
5995
+ setCanvasKey = _j[1];
5900
5996
  var resetBestFrame = React.useCallback(function () {
5901
5997
  stopDetection.current += 1;
5902
5998
  setCanvasKey(function (n) {
@@ -5912,16 +6008,45 @@ function IdCaptureModelsProviderInner(_a) {
5912
6008
  var load = React.useCallback(function () {
5913
6009
  loadDocumentDetectionModel();
5914
6010
  loadFocusModel();
5915
- }, [loadDocumentDetectionModel, loadFocusModel]);
5916
- var ready = documentDetectionModelState === 'ready' && focusModelState === 'ready';
5917
- var modelLoadState = ready ? 'ready' : documentDetectionModelState === 'warming' || focusModelState === 'warming' ? 'warming' : focusModelState === 'downloading' || documentDetectionModelState === 'downloading' ? 'downloading' : 'not-started';
5918
- var modelWarmingStartedAt = !documentDetectionModelWarmingStartedAt && !focusModelWarmingStartedAt ? null : Math.min.apply(Math, [documentDetectionModelWarmingStartedAt, focusModelWarmingStartedAt].filter(function (v) {
5919
- return v !== null;
5920
- }));
6011
+ if (enableBarcodeReadabilityModel) loadBarcodeReadabilityModel();
6012
+ }, [enableBarcodeReadabilityModel, loadBarcodeReadabilityModel, loadDocumentDetectionModel, loadFocusModel]);
6013
+ var _k = React.useMemo(function () {
6014
+ var modelStates = [documentDetectionModelState, focusModelState];
6015
+ var modelWarmingStartedAts = [documentDetectionModelWarmingStartedAt, focusModelWarmingStartedAt];
6016
+ var modelDownloadProgresses = [documentDetectionModelDownloadProgress, focusModelDownloadProgress];
6017
+ if (enableBarcodeReadabilityModel) {
6018
+ modelStates.push(barcodeReadabilityModelState);
6019
+ modelWarmingStartedAts.push(barcodeReadabilityModelWarmingStartedAt);
6020
+ modelDownloadProgresses.push(barcodeReadabilityModelDownloadProgress);
6021
+ }
6022
+ var ready = modelStates.every(function (state) {
6023
+ return state === 'ready';
6024
+ });
6025
+ return {
6026
+ ready: ready,
6027
+ modelLoadState: ready ? 'ready' : modelStates.some(function (state) {
6028
+ return state === 'warming';
6029
+ }) ? 'warming' : modelStates.some(function (state) {
6030
+ return state === 'downloading';
6031
+ }) ? 'downloading' : 'not-started',
6032
+ modelWarmingStartedAt: modelWarmingStartedAts.every(function (v) {
6033
+ return v === null;
6034
+ }) ? null : Math.min.apply(Math, modelWarmingStartedAts.filter(function (v) {
6035
+ return v !== null;
6036
+ })),
6037
+ modelDownloadProgress: modelDownloadProgresses.reduce(function (a, b) {
6038
+ return a + b;
6039
+ }, 0) / modelDownloadProgresses.length
6040
+ };
6041
+ }, [barcodeReadabilityModelDownloadProgress, barcodeReadabilityModelState, barcodeReadabilityModelWarmingStartedAt, documentDetectionModelDownloadProgress, documentDetectionModelState, documentDetectionModelWarmingStartedAt, enableBarcodeReadabilityModel, focusModelDownloadProgress, focusModelState, focusModelWarmingStartedAt]),
6042
+ ready = _k.ready,
6043
+ modelLoadState = _k.modelLoadState,
6044
+ modelWarmingStartedAt = _k.modelWarmingStartedAt,
6045
+ modelDownloadProgress = _k.modelDownloadProgress;
5921
6046
  var value = React.useMemo(function () {
5922
6047
  return {
5923
6048
  ready: ready,
5924
- modelDownloadProgress: (documentDetectionModelDownloadProgress + focusModelDownloadProgress) / 2,
6049
+ modelDownloadProgress: modelDownloadProgress,
5925
6050
  modelLoadState: modelLoadState,
5926
6051
  modelWarmingStartedAt: modelWarmingStartedAt,
5927
6052
  modelError: modelError,
@@ -5935,24 +6060,35 @@ function IdCaptureModelsProviderInner(_a) {
5935
6060
  onPredictionMade: onPredictionMade,
5936
6061
  detectionTime: detectionTime,
5937
6062
  focusPredictionTime: focusPredictionTime,
6063
+ barcodeReadabilityPredictionTime: barcodeReadabilityPredictionTime,
5938
6064
  getBestFrame: getBestFrame,
5939
6065
  resetBestFrame: resetBestFrame,
5940
6066
  bestFrameDetails: bestFrameDetails,
6067
+ bestBarcodeDetails: bestBarcodeDetails,
6068
+ getBestBarcode: getBestBarcode,
5941
6069
  requiredDocumentType: requiredDocumentType,
5942
6070
  setRequiredDocumentType: setRequiredDocumentType
5943
6071
  };
5944
- }, [detectionTime, documentDetectionBoundaries, documentDetectionModelDownloadProgress, focusModelDownloadProgress, focusPredictionTime, getBestFrame, load, modelLoadState, modelError, modelWarmingStartedAt, onPredictionMade, ready, requiredDocumentType, resetBestFrame, setDocumentDetectionBoundaries, setThresholds, startDocumentDetection, stopDocumentDetection, thresholds]);
6072
+ }, [ready, modelDownloadProgress, modelLoadState, modelWarmingStartedAt, modelError, startDocumentDetection, stopDocumentDetection, load, thresholds, setThresholds, documentDetectionBoundaries, setDocumentDetectionBoundaries, onPredictionMade, detectionTime, focusPredictionTime, barcodeReadabilityPredictionTime, getBestFrame, resetBestFrame, getBestBarcode, requiredDocumentType]);
5945
6073
  return /*#__PURE__*/React__namespace.default.createElement(IdCaptureModelsContext.Provider, {
5946
6074
  value: value
5947
- }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
5948
- key: canvasKey,
6075
+ }, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
6076
+ key: "bf-".concat(canvasKey),
5949
6077
  ref: bestPredictionCanvas
5950
- }), children);
6078
+ }), /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
6079
+ key: "bb-".concat(canvasKey),
6080
+ ref: bestBarcodeCanvas
6081
+ }), /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
6082
+ key: "cd-".concat(canvasKey),
6083
+ ref: croppedDocumentCanvas
6084
+ })), children);
5951
6085
  }
5952
6086
  function IdCaptureModelsProvider(_a) {
5953
6087
  var children = _a.children,
5954
6088
  props = __rest(_a, ["children"]);
5955
- return /*#__PURE__*/React__namespace.default.createElement(DocumentDetectionModelProvider, _assign({}, props), /*#__PURE__*/React__namespace.default.createElement(FocusModelProvider, _assign({}, props), /*#__PURE__*/React__namespace.default.createElement(IdCaptureModelsProviderInner, _assign({}, props), children)));
6089
+ return /*#__PURE__*/React__namespace.default.createElement(DocumentDetectionModelProvider, _assign({}, props), /*#__PURE__*/React__namespace.default.createElement(FocusModelProvider, _assign({}, props), /*#__PURE__*/React__namespace.default.createElement(BarcodeReadabilityModelProvider, _assign({}, props, {
6090
+ shouldLoadModels: props.enableBarcodeReadabilityModel
6091
+ }), /*#__PURE__*/React__namespace.default.createElement(IdCaptureModelsProviderInner, _assign({}, props), children))));
5956
6092
  }
5957
6093
  function useIdCaptureModelsContext() {
5958
6094
  var context = React.useContext(IdCaptureModelsContext);
@@ -5962,7 +6098,7 @@ function useIdCaptureModelsContext() {
5962
6098
  return context;
5963
6099
  }
5964
6100
 
5965
- var CapturedDocumentTypeValues = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'selfie', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
6101
+ var CapturedDocumentTypeValues = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'selfie', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage', 'idBarcodeImage'];
5966
6102
 
5967
6103
  var acceptedDocumentTypesForIdCaptureRequirementOption = {
5968
6104
  idCardFront: ['idCardFront'],
@@ -6048,6 +6184,7 @@ var initialState$5 = {
6048
6184
  capturing: false,
6049
6185
  captureFailed: false,
6050
6186
  imageUrl: null,
6187
+ idBarcodeImage: null,
6051
6188
  captureState: 'initializing',
6052
6189
  capturedDocuments: {},
6053
6190
  captureRequirement: 'idCardOrPassport',
@@ -6327,6 +6464,17 @@ var _reducer = function reducer(state, action) {
6327
6464
  }
6328
6465
  return newState;
6329
6466
  }
6467
+ case 'barcodeCaptured':
6468
+ return _reducer(state, {
6469
+ type: 'documentCaptured',
6470
+ payload: {
6471
+ imageData: action.payload.imageUrl,
6472
+ documentType: 'idBarcodeImage',
6473
+ width: 0,
6474
+ height: 0,
6475
+ barcodeReadabilityScore: action.payload.barcodeReadabilityScore
6476
+ }
6477
+ });
6330
6478
  case 'flipRequestCompleted':
6331
6479
  return _assign(_assign({}, state), {
6332
6480
  captureState: 'capturing',
@@ -6818,12 +6966,13 @@ var IdCapture = function IdCapture(_a) {
6818
6966
  height = _q === void 0 ? 1 : _q;
6819
6967
  var state = useIdCaptureStore();
6820
6968
  var isRearFacing = useCameraStore().isRearFacing;
6821
- var _r = React.useContext(IdCaptureModelsContext),
6969
+ var _r = useIdCaptureModelsContext(),
6822
6970
  modelsReady = _r.ready,
6823
6971
  setThresholds = _r.setThresholds,
6824
6972
  detectionTime = _r.detectionTime,
6825
6973
  focusPredictionTime = _r.focusPredictionTime,
6826
- getBestFrame = _r.getBestFrame;
6974
+ getBestFrame = _r.getBestFrame,
6975
+ getBestBarcode = _r.getBestBarcode;
6827
6976
  React.useEffect(function () {
6828
6977
  return dispatchIdCaptureAction({
6829
6978
  type: 'captureInitialized'
@@ -6862,6 +7011,16 @@ var IdCapture = function IdCapture(_a) {
6862
7011
  });
6863
7012
  return;
6864
7013
  }
7014
+ var bestBarcode = getBestBarcode();
7015
+ if (bestBarcode) {
7016
+ dispatchIdCaptureAction({
7017
+ type: 'barcodeCaptured',
7018
+ payload: {
7019
+ imageUrl: bestBarcode.canvas.toDataURL('image/jpeg', 0.95),
7020
+ barcodeReadabilityScore: bestBarcode.score
7021
+ }
7022
+ });
7023
+ }
6865
7024
  var canvas = bestFrame.canvas,
6866
7025
  documentType = bestFrame.documentType,
6867
7026
  boundingBox = bestFrame.boundingBox,
@@ -6878,21 +7037,22 @@ var IdCapture = function IdCapture(_a) {
6878
7037
  });
6879
7038
  var capturedDocumentType = documentType;
6880
7039
  setTimeout(function () {
6881
- var _a;
6882
- var captureTime = new Date().getTime() - ((_a = state.captureStartedAt) !== null && _a !== void 0 ? _a : new Date()).getTime();
7040
+ var _a, _b;
7041
+ var captureTime = performance.now() - ((_a = state.captureStartedAt) !== null && _a !== void 0 ? _a : new Date()).getTime();
6883
7042
  var metadata = {
6884
7043
  autoCapture: 'Y',
6885
7044
  captureTime: captureTime,
6886
7045
  boundingBox: boundingBox,
6887
7046
  bestDetectionScore: detectionScore,
6888
- bestFocusScore: focusScore
7047
+ bestFocusScore: focusScore,
7048
+ bestBarcodeScore: (_b = bestBarcode === null || bestBarcode === void 0 ? void 0 : bestBarcode.score) !== null && _b !== void 0 ? _b : 0
6889
7049
  };
6890
7050
  onCapture === null || onCapture === void 0 ? void 0 : onCapture(imageUrl, width, height, capturedDocumentType, metadata);
6891
7051
  dispatchIdCaptureAction({
6892
7052
  type: 'captured'
6893
7053
  });
6894
7054
  }, 0);
6895
- }, [getBestFrame, onCapture, shouldCapture, state.captureStartedAt, state.requestedDocumentType]);
7055
+ }, [getBestBarcode, getBestFrame, onCapture, shouldCapture, state.captureStartedAt, state.requestedDocumentType]);
6896
7056
  var theme = styled.useTheme();
6897
7057
  colors.guideBoxUnsatisfiedColor || (colors.guideBoxUnsatisfiedColor = (_d = (_c = (_b = theme.idCapture) === null || _b === void 0 ? void 0 : _b.guideBox) === null || _c === void 0 ? void 0 : _c.unsatisfiedColor) !== null && _d !== void 0 ? _d : 'white');
6898
7058
  colors.guideBoxSatisfiedColor || (colors.guideBoxSatisfiedColor = (_g = (_f = (_e = theme.idCapture) === null || _e === void 0 ? void 0 : _e.guideBox) === null || _f === void 0 ? void 0 : _f.satisfiedColor) !== null && _g !== void 0 ? _g : 'green');
@@ -7692,7 +7852,7 @@ var IdCaptureLoadingOverlayDefault = function IdCaptureLoadingOverlayDefault(_a)
7692
7852
  };
7693
7853
  }, [ready]);
7694
7854
  var imageRef = React.useRef(null);
7695
- var timeSinceWarmingStarted = modelWarmingStartedAt ? new Date().getTime() - modelWarmingStartedAt : 0;
7855
+ var timeSinceWarmingStarted = modelWarmingStartedAt ? performance.now() - modelWarmingStartedAt : 0;
7696
7856
  var warmingProgress = timeSinceWarmingStarted / 5000.0;
7697
7857
  var modelLoadProgress = modelsReady ? 100 : modelDownloadProgress * 0.5 + warmingProgress * 49.0;
7698
7858
  useLoadProgressHooks({
@@ -8030,7 +8190,7 @@ var Card = styled__default.default.div(templateObject_1$D || (templateObject_1$D
8030
8190
  var FlexCard = styled__default.default(Card)(templateObject_2$y || (templateObject_2$y = __makeTemplateObject(["\n display: flex;\n flex-direction: column;\n"], ["\n display: flex;\n flex-direction: column;\n"])));
8031
8191
  var templateObject_1$D, templateObject_2$y;
8032
8192
 
8033
- var imageDisplayOrder = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
8193
+ var imageDisplayOrder = ['idCardFront', 'idCardBack', 'idBarcodeImage', 'passport', 'singlePage', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
8034
8194
  var IdCaptureSuccess = function IdCaptureSuccess(_a) {
8035
8195
  var capturedDocuments = _a.capturedDocuments,
8036
8196
  onSubmitClick = _a.onSubmitClick,
@@ -8072,7 +8232,7 @@ var IdCaptureSuccess = function IdCaptureSuccess(_a) {
8072
8232
  image: doc,
8073
8233
  className: classNames.image,
8074
8234
  alt: doc.documentType
8075
- }), debugMode && ( /*#__PURE__*/React__namespace.default.createElement(DebugPre, null, "Document Type: ".concat(doc.documentType, "\nDetection Score: ").concat(doc.detectionScore, "\nFocus Score: ").concat(doc.focusScore, "\nBounding Box: ").concat(JSON.stringify(doc.boundingBox)))));
8235
+ }), debugMode && ( /*#__PURE__*/React__namespace.default.createElement(DebugPre, null, name === 'idBarcodeImage' ? "Document Type: ".concat(doc.documentType, "\nReadability Score: ").concat(doc.barcodeReadabilityScore) : "Document Type: ".concat(doc.documentType, "\nDetection Score: ").concat(doc.detectionScore, "\nFocus Score: ").concat(doc.focusScore, "\nBounding Box: ").concat(JSON.stringify(doc.boundingBox)))));
8076
8236
  }))), /*#__PURE__*/React__namespace.default.createElement(ButtonsColumn, {
8077
8237
  className: classNames.buttonsRow
8078
8238
  }, /*#__PURE__*/React__namespace.default.createElement(WideButton, {
@@ -10694,7 +10854,7 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10694
10854
  var _6 = React.useState(false),
10695
10855
  overlayDismissed = _6[0],
10696
10856
  setOverlayDismissed = _6[1];
10697
- var _7 = React.useContext(SubmissionContext),
10857
+ var _7 = useSubmissionContext(),
10698
10858
  submissionStatus = _7.submissionStatus,
10699
10859
  setIdFrontImage = _7.setIdFrontImage,
10700
10860
  setIdBackImage = _7.setIdBackImage,
@@ -10703,6 +10863,7 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10703
10863
  setIdBackIrImage = _7.setIdBackIrImage,
10704
10864
  setIdFrontUvImage = _7.setIdFrontUvImage,
10705
10865
  setIdBackUvImage = _7.setIdBackUvImage,
10866
+ setIdBarcodeImage = _7.setIdBarcodeImage,
10706
10867
  logIdFrontCaptureAttempt = _7.logIdFrontCaptureAttempt,
10707
10868
  logIdBackCaptureAttempt = _7.logIdBackCaptureAttempt;
10708
10869
  var _8 = useIdCaptureModelsContext(),
@@ -10803,7 +10964,7 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10803
10964
  });
10804
10965
  }, [logCaptureMetadata, onDocumentCaptured]);
10805
10966
  var onSubmitClick = React.useCallback(function () {
10806
- var _a, _b, _c, _d, _e, _f, _g, _h;
10967
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
10807
10968
  var docs = state.capturedDocuments;
10808
10969
  var submission = {
10809
10970
  idFrontImage: maybeDataUrlToBase64Sync((_a = docs.idCardFront) === null || _a === void 0 ? void 0 : _a.imageData),
@@ -10813,7 +10974,8 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10813
10974
  idFrontIrImage: maybeDataUrlToBase64Sync((_e = docs.idFrontIrImage) === null || _e === void 0 ? void 0 : _e.imageData),
10814
10975
  idBackIrImage: maybeDataUrlToBase64Sync((_f = docs.idBackIrImage) === null || _f === void 0 ? void 0 : _f.imageData),
10815
10976
  idFrontUvImage: maybeDataUrlToBase64Sync((_g = docs.idFrontUvImage) === null || _g === void 0 ? void 0 : _g.imageData),
10816
- idBackUvImage: maybeDataUrlToBase64Sync((_h = docs.idBackUvImage) === null || _h === void 0 ? void 0 : _h.imageData)
10977
+ idBackUvImage: maybeDataUrlToBase64Sync((_h = docs.idBackUvImage) === null || _h === void 0 ? void 0 : _h.imageData),
10978
+ idBarcodeImage: maybeDataUrlToBase64Sync((_j = docs.idBarcodeImage) === null || _j === void 0 ? void 0 : _j.imageData)
10817
10979
  };
10818
10980
  if (submission.idFrontImage) setIdFrontImage(submission.idFrontImage);
10819
10981
  if (submission.idBackImage) setIdBackImage(submission.idBackImage);
@@ -10823,11 +10985,12 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10823
10985
  if (submission.idBackIrImage) setIdBackIrImage(submission.idBackIrImage);
10824
10986
  if (submission.idFrontUvImage) setIdFrontUvImage(submission.idFrontUvImage);
10825
10987
  if (submission.idBackUvImage) setIdBackUvImage(submission.idBackUvImage);
10988
+ if (submission.idBarcodeImage) setIdBarcodeImage(submission.idBarcodeImage);
10826
10989
  if (releaseCameraAccessOnExit) releaseCameraAccess();
10827
10990
  setTimeout(function () {
10828
10991
  return onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(submission);
10829
10992
  }, 0);
10830
- }, [onSuccess, releaseCameraAccess, releaseCameraAccessOnExit, setIdBackImage, setIdBackIrImage, setIdBackUvImage, setIdFrontImage, setIdFrontIrImage, setIdFrontUvImage, setPassportImage, state.capturedDocuments]);
10993
+ }, [onSuccess, releaseCameraAccess, releaseCameraAccessOnExit, setIdBarcodeImage, setIdBackImage, setIdBackIrImage, setIdBackUvImage, setIdFrontImage, setIdFrontIrImage, setIdFrontUvImage, setPassportImage, state.capturedDocuments]);
10831
10994
  var showSuccessScreen = useShowSuccessScreen(skipSuccessScreen, state.captureState === 'complete', onSubmitClick);
10832
10995
  var onRetryClick = React.useCallback(function () {
10833
10996
  return dispatchIdCaptureAction({
@@ -11617,59 +11780,397 @@ function SelfieCaptureAnimatedMask(_a) {
11617
11780
  fill: "white"
11618
11781
  }))))));
11619
11782
  }
11620
- function SelfieCaptureAnimatedMaskWithStatus(_a) {
11621
- var _b = _a.status,
11622
- status = _b === void 0 ? 'ready' : _b,
11623
- props = __rest(_a, ["status"]);
11624
- var _c = React.useState(1),
11625
- frame = _c[0],
11626
- setFrame = _c[1];
11627
- React.useEffect(function () {
11628
- if (status !== 'processing') {
11629
- setFrame(0);
11630
- return;
11631
- }
11632
- setFrame(1);
11633
- var interval = setInterval(function () {
11634
- setFrame(function (n) {
11635
- return (n + 1) % 6;
11636
- });
11637
- }, 250);
11638
- return function () {
11639
- clearInterval(interval);
11783
+ function SelfieCaptureAnimatedMaskWithStatus(_a) {
11784
+ var _b = _a.status,
11785
+ status = _b === void 0 ? 'ready' : _b,
11786
+ props = __rest(_a, ["status"]);
11787
+ var _c = React.useState(1),
11788
+ frame = _c[0],
11789
+ setFrame = _c[1];
11790
+ React.useEffect(function () {
11791
+ if (status !== 'processing') {
11792
+ setFrame(0);
11793
+ return;
11794
+ }
11795
+ setFrame(1);
11796
+ var interval = setInterval(function () {
11797
+ setFrame(function (n) {
11798
+ return (n + 1) % 6;
11799
+ });
11800
+ }, 250);
11801
+ return function () {
11802
+ clearInterval(interval);
11803
+ };
11804
+ }, [status]);
11805
+ return /*#__PURE__*/React__namespace.default.createElement(SelfieCaptureAnimatedMask, _assign({}, props, {
11806
+ frame: frame,
11807
+ status: status
11808
+ }));
11809
+ }
11810
+ var templateObject_1$o, templateObject_2$m, templateObject_3$g;
11811
+
11812
+ var FaceCaptureGuideContainer = styled__default.default.div(templateObject_1$n || (templateObject_1$n = __makeTemplateObject(["\n position: absolute;\n z-index: 1000;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n box-sizing: border-box;\n"], ["\n position: absolute;\n z-index: 1000;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n box-sizing: border-box;\n"])));
11813
+ var FaceCaptureGuideInner = styled__default.default.div(templateObject_2$l || (templateObject_2$l = __makeTemplateObject(["\n position: relative;\n height: 60%;\n"], ["\n position: relative;\n height: 60%;\n"])));
11814
+ var FaceCaptureGuideOverlay = function FaceCaptureGuideOverlay(_a) {
11815
+ var _b = _a.classNames,
11816
+ classNames = _b === void 0 ? {} : _b,
11817
+ _c = _a.status,
11818
+ status = _c === void 0 ? 'ready' : _c,
11819
+ _d = _a.borderWidth,
11820
+ borderWidth = _d === void 0 ? 5 : _d,
11821
+ _e = _a.borderColor,
11822
+ borderColor = _e === void 0 ? 'white' : _e,
11823
+ _f = _a.borderOpacity,
11824
+ borderOpacity = _f === void 0 ? 0.8 : _f;
11825
+ return /*#__PURE__*/React__namespace.default.createElement(FaceCaptureGuideContainer, {
11826
+ className: classNames.container
11827
+ }, /*#__PURE__*/React__namespace.default.createElement(FaceCaptureGuideInner, null, /*#__PURE__*/React__namespace.default.createElement(SelfieCaptureAnimatedMaskWithStatus, {
11828
+ status: status,
11829
+ borderColor: borderColor,
11830
+ borderWidth: borderWidth,
11831
+ borderOpacity: borderOpacity,
11832
+ verticalAlign: "center"
11833
+ })));
11834
+ };
11835
+ var templateObject_1$n, templateObject_2$l;
11836
+
11837
+ var defaultSelfieCaptureModelLoadTimeoutMs = 45000;
11838
+ var detector = null;
11839
+ var detectorSettings = null;
11840
+ function loadFaceDetector() {
11841
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
11842
+ var _a, _b;
11843
+ if (modelAssetPath === void 0) {
11844
+ modelAssetPath = defaultFaceDetectorModelPath;
11845
+ }
11846
+ return __generator(this, function (_c) {
11847
+ switch (_c.label) {
11848
+ case 0:
11849
+ if (detector && (detectorSettings === null || detectorSettings === void 0 ? void 0 : detectorSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, detector];
11850
+ closeFaceDetector();
11851
+ return [4 /*yield*/, preloadFaceDetectorDependencies()];
11852
+ case 1:
11853
+ _c.sent();
11854
+ if (modelCapabilities.delegate === 'NONE') {
11855
+ throw new Error('No available delegate for face detector.');
11856
+ }
11857
+ _b = (_a = tasksVision.FaceDetector).createFromOptions;
11858
+ return [4 /*yield*/, tasksVision.FilesetResolver.forVisionTasks(visionTasksBasePath)];
11859
+ case 2:
11860
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
11861
+ // canvas: document.createElement('canvas'),
11862
+ baseOptions: {
11863
+ modelAssetPath: modelAssetPath,
11864
+ delegate: modelCapabilities.delegate
11865
+ },
11866
+ runningMode: 'VIDEO'
11867
+ }])];
11868
+ case 3:
11869
+ detector = _c.sent();
11870
+ detectorSettings = {
11871
+ modelAssetPath: modelAssetPath
11872
+ };
11873
+ return [2 /*return*/, detector];
11874
+ }
11875
+ });
11876
+ });
11877
+ }
11878
+ function closeFaceDetector() {
11879
+ detector === null || detector === void 0 ? void 0 : detector.close();
11880
+ detector = null;
11881
+ detectorSettings = null;
11882
+ }
11883
+ function useLoadFaceDetector(_a) {
11884
+ var onModelError = _a.onModelError,
11885
+ _b = _a.modelLoadTimeoutMs,
11886
+ modelLoadTimeoutMs = _b === void 0 ? defaultSelfieCaptureModelLoadTimeoutMs : _b,
11887
+ videoRef = _a.videoRef;
11888
+ var _c = React.useState('not-started'),
11889
+ modelLoadState = _c[0],
11890
+ setModelLoadState = _c[1];
11891
+ var _d = React.useState(0),
11892
+ modelDownloadProgress = _d[0],
11893
+ setModelDownloadProgress = _d[1];
11894
+ var _e = React.useState(null),
11895
+ modelWarmingStartedAt = _e[0],
11896
+ setModelWarmingStartedAt = _e[1];
11897
+ var _f = React.useState(null),
11898
+ modelError = _f[0],
11899
+ setModelError = _f[1];
11900
+ React.useEffect(function loadModel() {
11901
+ var _this = this;
11902
+ setModelLoadState('downloading');
11903
+ setModelWarmingStartedAt(null);
11904
+ var modelLoadTimeout = setTimeout(function () {
11905
+ setModelError(new Error('Model loading time limit exceeded.'));
11906
+ }, modelLoadTimeoutMs);
11907
+ function handleDownloadProgress(event) {
11908
+ setModelDownloadProgress(progressToPercentage(event.detail));
11909
+ }
11910
+ document.addEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
11911
+ var cancelVideoReady = function cancelVideoReady() {};
11912
+ loadFaceDetector().then(function (model) {
11913
+ return __awaiter(_this, void 0, void 0, function () {
11914
+ var _a, videoReady, cancel, cancelled;
11915
+ return __generator(this, function (_b) {
11916
+ switch (_b.label) {
11917
+ case 0:
11918
+ setModelDownloadProgress(100);
11919
+ clearTimeout(modelLoadTimeout);
11920
+ setModelLoadState('warming');
11921
+ setModelWarmingStartedAt(performance.now());
11922
+ return [4 /*yield*/, testFaceDetectionAgainstKnownImage(model)];
11923
+ case 1:
11924
+ _b.sent();
11925
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
11926
+ cancelled = false;
11927
+ cancelVideoReady = function cancelVideoReady() {
11928
+ cancelled = true;
11929
+ cancel();
11930
+ };
11931
+ return [4 /*yield*/, videoReady];
11932
+ case 2:
11933
+ _b.sent();
11934
+ if (cancelled) return [2 /*return*/];
11935
+ model.detectForVideo(videoRef.current, performance.now());
11936
+ setModelLoadState('ready');
11937
+ return [2 /*return*/];
11938
+ }
11939
+ });
11940
+ });
11941
+ })["catch"](function (e) {
11942
+ setModelError(e);
11943
+ setModelLoadState('error');
11944
+ })["finally"](function () {
11945
+ clearTimeout(modelLoadTimeout);
11946
+ });
11947
+ return function () {
11948
+ log('unloading face detection model');
11949
+ cancelVideoReady();
11950
+ closeFaceDetector();
11951
+ clearTimeout(modelLoadTimeout);
11952
+ document.removeEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
11953
+ };
11954
+ }, [modelLoadTimeoutMs, videoRef]);
11955
+ React.useEffect(function handleModelError() {
11956
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
11957
+ }, [modelError, onModelError]);
11958
+ return React.useMemo(function () {
11959
+ return {
11960
+ ready: modelLoadState === 'ready',
11961
+ modelLoadState: modelLoadState,
11962
+ modelDownloadProgress: modelDownloadProgress,
11963
+ modelWarmingStartedAt: modelWarmingStartedAt,
11964
+ modelError: modelError
11965
+ };
11966
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
11967
+ }
11968
+ var lastFaceDetectionAt = 0;
11969
+ var lastFaceDetectionTime = 0;
11970
+ function setLastFaceDetectionAt(time) {
11971
+ lastFaceDetectionTime = time - lastFaceDetectionAt;
11972
+ lastFaceDetectionAt = time;
11973
+ }
11974
+ var framesNeededSamples = [];
11975
+ function trackFramesNeeded(value, bufferLength) {
11976
+ if (bufferLength === void 0) {
11977
+ bufferLength = 25;
11978
+ }
11979
+ framesNeededSamples.unshift(value);
11980
+ if (framesNeededSamples.length > bufferLength) framesNeededSamples.length = bufferLength;
11981
+ }
11982
+ var lastNFaces = [];
11983
+ var lastNFacePairs = [];
11984
+ var lastNNoses = [];
11985
+ var lastNNosePairs = [];
11986
+ function trackFace(face, framesNeeded, frameWidth, frameHeight) {
11987
+ if (framesNeeded === void 0) {
11988
+ framesNeeded = 12;
11989
+ }
11990
+ var nose = face.keypoints[2];
11991
+ if (!nose) return;
11992
+ lastNFaces.unshift(face);
11993
+ lastNNoses.unshift(nose);
11994
+ if (lastNFaces.length > framesNeeded) lastNFaces.length = framesNeeded;
11995
+ if (lastNNoses.length > framesNeeded) lastNNoses.length = framesNeeded;
11996
+ if (lastNFaces.length > 1) {
11997
+ var lastFace = lastNFaces[1];
11998
+ var iou = calculateIoU(face.box, lastFace.box);
11999
+ lastNFacePairs.unshift({
12000
+ a: face,
12001
+ b: lastFace,
12002
+ iou: iou
12003
+ });
12004
+ if (lastNFacePairs.length > framesNeeded - 1) lastNFacePairs.length = framesNeeded - 1;
12005
+ }
12006
+ if (lastNNoses.length > 1) {
12007
+ var lastNose = lastNNoses[1];
12008
+ var noseDistance = Math.sqrt(Math.pow((nose.x - lastNose.x) / frameWidth, 2) + Math.pow((nose.y - lastNose.y) / frameHeight, 2));
12009
+ lastNNosePairs.unshift({
12010
+ a: nose,
12011
+ b: lastNose,
12012
+ distance: noseDistance
12013
+ });
12014
+ if (lastNNosePairs.length > framesNeeded - 1) lastNNosePairs.length = framesNeeded - 1;
12015
+ }
12016
+ }
12017
+ function makeFaceDetectorPrediction(imageData) {
12018
+ if (!detector) return null;
12019
+ var prediction = detector.detectForVideo(imageData, performance.now());
12020
+ var faces = prediction.detections.map(function (d) {
12021
+ return {
12022
+ box: convertBoundingBox(d.boundingBox),
12023
+ keypoints: d.keypoints.map(function (k) {
12024
+ var _a;
12025
+ return _assign(_assign({}, k), {
12026
+ x: k.x * imageData.width,
12027
+ y: k.y * imageData.height,
12028
+ name: (_a = k.label) !== null && _a !== void 0 ? _a : ''
12029
+ });
12030
+ })
11640
12031
  };
11641
- }, [status]);
11642
- return /*#__PURE__*/React__namespace.default.createElement(SelfieCaptureAnimatedMask, _assign({}, props, {
11643
- frame: frame,
11644
- status: status
11645
- }));
12032
+ });
12033
+ return _assign(_assign({}, prediction), {
12034
+ faces: faces
12035
+ });
12036
+ }
12037
+ function processFaceDetectorPrediction(_a) {
12038
+ var faces = _a.faces,
12039
+ videoWidth = _a.videoWidth,
12040
+ videoHeight = _a.videoHeight,
12041
+ _b = _a.requireVerticalFaceCentering,
12042
+ requireVerticalFaceCentering = _b === void 0 ? true : _b,
12043
+ _c = _a.stabilityThreshold,
12044
+ stabilityThreshold = _c === void 0 ? 0.7 : _c,
12045
+ _d = _a.noseDistanceThreshold,
12046
+ noseDistanceThreshold = _d === void 0 ? 0.025 : _d,
12047
+ _e = _a.xBoundary,
12048
+ xBoundary = _e === void 0 ? 0.01 : _e,
12049
+ // this represents the edge that the sides of the face box should not cross -- 1% of video width
12050
+ _f = _a.yBoundary,
12051
+ // this represents the edge that the sides of the face box should not cross -- 1% of video width
12052
+ yBoundary = _f === void 0 ? 0.01 : _f,
12053
+ // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
12054
+ _g = _a.xCentroidBoundary,
12055
+ // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
12056
+ xCentroidBoundary = _g === void 0 ? 0.125 : _g,
12057
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
12058
+ _h = _a.yCentroidBoundary,
12059
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
12060
+ yCentroidBoundary = _h === void 0 ? 0.125 : _h,
12061
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
12062
+ _j = _a.foreheadRatio,
12063
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
12064
+ foreheadRatio = _j === void 0 ? 0.275 : _j,
12065
+ // we found that the bounding box ends at the brow and misses the forehead. this ratio represents how much we should extend the box to include the forehead.
12066
+ _k = _a.noseTrackingThreshold,
12067
+ // we found that the bounding box ends at the brow and misses the forehead. this ratio represents how much we should extend the box to include the forehead.
12068
+ noseTrackingThreshold = _k === void 0 ? 0.2 : _k,
12069
+ // this represents the maximum distance that the nose can be from the center of the face box -- 20% of the face box width or height
12070
+ minCaptureBrightnessThreshold = _a.minCaptureBrightnessThreshold,
12071
+ minCaptureRangeThreshold = _a.minCaptureRangeThreshold,
12072
+ minCaptureVarianceThreshold = _a.minCaptureVarianceThreshold,
12073
+ brightness = _a.brightness,
12074
+ range = _a.range,
12075
+ variance = _a.variance;
12076
+ var face = faces[0];
12077
+ var faceNotDetected = faces.length === 0;
12078
+ var faceNotCentered = false,
12079
+ faceLookingAway = false,
12080
+ faceTooClose = false,
12081
+ faceTooFar = false,
12082
+ faceVisibilityTooLow = false;
12083
+ var hasAnyThreshold = minCaptureBrightnessThreshold !== undefined || minCaptureRangeThreshold !== undefined || minCaptureVarianceThreshold !== undefined;
12084
+ if (hasAnyThreshold) {
12085
+ var tooDark = minCaptureBrightnessThreshold !== undefined && brightness !== undefined && brightness < minCaptureBrightnessThreshold;
12086
+ var tooLowRange = minCaptureRangeThreshold !== undefined && range !== undefined && range < minCaptureRangeThreshold;
12087
+ var tooLowVariance = minCaptureVarianceThreshold !== undefined && variance !== undefined && variance < minCaptureVarianceThreshold;
12088
+ faceVisibilityTooLow = !!(tooDark || tooLowRange || tooLowVariance);
12089
+ }
12090
+ if (face && !faceVisibilityTooLow) {
12091
+ // calculate frame centroids
12092
+ var frameCX = videoWidth / 2;
12093
+ var frameCY = videoHeight / 2;
12094
+ // calculate head bounding box, with forehead extension
12095
+ var foreheadSize = face.box.height * foreheadRatio;
12096
+ var headXMin = face.box.xMin;
12097
+ var headXMax = face.box.xMax;
12098
+ var headYMin = face.box.yMin - foreheadSize;
12099
+ var headYMax = face.box.yMax;
12100
+ // calculate head centroids
12101
+ var headCX = (headXMin + headXMax) / 2;
12102
+ var headCY = (headYMin + headYMax) / 2;
12103
+ // calculate thresholds
12104
+ var vTX = videoWidth * xBoundary;
12105
+ var vTY = videoHeight * yBoundary;
12106
+ var vCTX = videoWidth * xCentroidBoundary;
12107
+ var vCTY = videoHeight * yCentroidBoundary;
12108
+ var faceNotCenteredHorizontally = Math.abs(frameCX - headCX) > vCTX;
12109
+ var faceNotCenteredVertically = Math.abs(frameCY - headCY) > vCTY;
12110
+ var faceViolatesHorizontalBoundary = headXMin < vTX || headXMax > videoWidth - vTX;
12111
+ var faceViolatesVerticalBoundary = headYMin < vTY || headYMax > videoHeight - vTY;
12112
+ faceNotCentered = faceViolatesHorizontalBoundary || faceViolatesVerticalBoundary || faceNotCenteredHorizontally || requireVerticalFaceCentering && faceNotCenteredVertically;
12113
+ var isMobile = videoWidth < videoHeight;
12114
+ var tooCloseMultiple = 1.5;
12115
+ var tooFarMultiple = isMobile ? 6 : 7;
12116
+ faceTooClose = face.box.width > videoWidth / tooCloseMultiple;
12117
+ faceTooFar = face.box.width < videoWidth / tooFarMultiple;
12118
+ var nose = face.keypoints[2];
12119
+ var fTW = face.box.width * noseTrackingThreshold;
12120
+ var fTH = face.box.height * noseTrackingThreshold;
12121
+ faceLookingAway = !nose || Math.abs(headCX - nose.x) > fTW || Math.abs(headCY - nose.y) > fTH;
12122
+ }
12123
+ var faceInGuides = !faceNotDetected && !faceNotCentered && !faceLookingAway && !faceTooClose && !faceTooFar;
12124
+ if (lastFaceDetectionTime > 0) {
12125
+ trackFramesNeeded(500 / lastFaceDetectionTime);
12126
+ }
12127
+ var faceIsStable = false,
12128
+ noseIsStable = false;
12129
+ if (faceInGuides && !faceVisibilityTooLow) {
12130
+ var framesNeeded = Math.max(Math.ceil(average(framesNeededSamples)), 5);
12131
+ trackFace(face, framesNeeded, videoWidth, videoHeight);
12132
+ faceIsStable = lastNFaces.length >= framesNeeded && !lastNFacePairs.some(function (pair) {
12133
+ return pair.iou < stabilityThreshold;
12134
+ });
12135
+ noseIsStable = lastNNoses.length >= framesNeeded && !lastNNosePairs.some(function (pair) {
12136
+ return pair.distance > noseDistanceThreshold;
12137
+ });
12138
+ }
12139
+ var faceReady = faceInGuides && faceIsStable && noseIsStable && !faceVisibilityTooLow;
12140
+ return {
12141
+ face: face,
12142
+ faceNotDetected: faceNotDetected,
12143
+ faceNotCentered: faceNotCentered,
12144
+ faceLookingAway: faceLookingAway,
12145
+ faceTooClose: faceTooClose,
12146
+ faceTooFar: faceTooFar,
12147
+ faceReady: faceReady,
12148
+ faceReadyAt: faceReady ? new Date() : null,
12149
+ faceIsStable: faceIsStable,
12150
+ noseIsStable: noseIsStable,
12151
+ faceVisibilityTooLow: faceVisibilityTooLow
12152
+ };
12153
+ }
12154
+ function testFaceDetectionAgainstKnownImage(detector) {
12155
+ return new Promise(function (resolve, reject) {
12156
+ var img = new Image();
12157
+ img.crossOrigin = 'anonymous';
12158
+ img.onload = function () {
12159
+ var prediction = detector.detectForVideo(img, performance.now());
12160
+ if (prediction.detections.length > 0) {
12161
+ debug('face detection test result', prediction.detections);
12162
+ resolve(void 0);
12163
+ } else {
12164
+ warn('face detection test failed');
12165
+ reject(new Error('testFaceDetectionAgainstKnownImage failed to predict'));
12166
+ }
12167
+ };
12168
+ img.onerror = function () {
12169
+ return reject(new Error('testFaceDetectionAgainstKnownImage failed to load image'));
12170
+ };
12171
+ img.src = "".concat(DEFAULT_CDN_URL, "/head-test.jpg");
12172
+ });
11646
12173
  }
11647
- var templateObject_1$o, templateObject_2$m, templateObject_3$g;
11648
-
11649
- var FaceCaptureGuideContainer = styled__default.default.div(templateObject_1$n || (templateObject_1$n = __makeTemplateObject(["\n position: absolute;\n z-index: 1000;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n box-sizing: border-box;\n"], ["\n position: absolute;\n z-index: 1000;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 40px;\n box-sizing: border-box;\n"])));
11650
- 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"])));
11651
- var FaceCaptureGuideOverlay = function FaceCaptureGuideOverlay(_a) {
11652
- var _b = _a.classNames,
11653
- classNames = _b === void 0 ? {} : _b,
11654
- _c = _a.status,
11655
- status = _c === void 0 ? 'ready' : _c,
11656
- _d = _a.borderWidth,
11657
- borderWidth = _d === void 0 ? 5 : _d,
11658
- _e = _a.borderColor,
11659
- borderColor = _e === void 0 ? 'white' : _e,
11660
- _f = _a.borderOpacity,
11661
- borderOpacity = _f === void 0 ? 0.8 : _f;
11662
- return /*#__PURE__*/React__namespace.default.createElement(FaceCaptureGuideContainer, {
11663
- className: classNames.container
11664
- }, /*#__PURE__*/React__namespace.default.createElement(FaceCaptureGuideInner, null, /*#__PURE__*/React__namespace.default.createElement(SelfieCaptureAnimatedMaskWithStatus, {
11665
- status: status,
11666
- borderColor: borderColor,
11667
- borderWidth: borderWidth,
11668
- borderOpacity: borderOpacity,
11669
- verticalAlign: "center"
11670
- })));
11671
- };
11672
- var templateObject_1$n, templateObject_2$l;
11673
12174
 
11674
12175
  function detectBrightnessAndContrast(frame, brightnessAverager) {
11675
12176
  var ctx = frame.getContext('2d');
@@ -12963,7 +13464,7 @@ var SelfieCaptureLoadingOverlayDefault = function SelfieCaptureLoadingOverlayDef
12963
13464
  });
12964
13465
  }, 3000);
12965
13466
  }, []);
12966
- var timeSinceWarmingStarted = modelWarmingStartedAt ? new Date().getTime() - modelWarmingStartedAt : 0;
13467
+ var timeSinceWarmingStarted = modelWarmingStartedAt ? performance.now() - modelWarmingStartedAt : 0;
12967
13468
  var warmingProgress = timeSinceWarmingStarted / 5000.0;
12968
13469
  var _o = React.useState(false),
12969
13470
  overrideModelsReady = _o[0],
@@ -13816,6 +14317,16 @@ var Container$4 = styled__default.default.div(templateObject_1$c || (templateObj
13816
14317
  var AcceptBtn$1 = styled__default.default(LoaderButton)(templateObject_2$b || (templateObject_2$b = __makeTemplateObject(["\n margin-left: auto;\n"], ["\n margin-left: auto;\n"])));
13817
14318
  var templateObject_1$c, templateObject_2$b;
13818
14319
 
14320
+ function isBlob(blobPart) {
14321
+ return typeof Blob !== 'undefined' && blobPart instanceof Blob;
14322
+ }
14323
+ function inferBlobType(blobPart) {
14324
+ var _a;
14325
+ if (!isBlob(blobPart)) return undefined;
14326
+ var t = ((_a = blobPart.type) !== null && _a !== void 0 ? _a : '').trim();
14327
+ return t.length > 0 ? t : undefined;
14328
+ }
14329
+
13819
14330
  var videoRecorder = null;
13820
14331
  var audioRecorder = null;
13821
14332
  var videoChunks = [];
@@ -13949,8 +14460,9 @@ var useVideoRecorder = function useVideoRecorder(mergeAVStreams) {
13949
14460
  useVideoRecorderStore.getState().clearRecordedData();
13950
14461
  }, []);
13951
14462
  var processVideo = React.useCallback(function () {
14463
+ var inferredType = inferBlobType(videoChunks[0]) || (videoRecorder === null || videoRecorder === void 0 ? void 0 : videoRecorder.mimeType) || 'video/mp4';
13952
14464
  var videoBlob = new Blob(videoChunks, {
13953
- type: 'video/mp4'
14465
+ type: inferredType
13954
14466
  });
13955
14467
  useVideoRecorderStore.setState({
13956
14468
  videoUrl: URL.createObjectURL(videoBlob),
@@ -13960,8 +14472,9 @@ var useVideoRecorder = function useVideoRecorder(mergeAVStreams) {
13960
14472
  setVideoRecorder(null);
13961
14473
  }, []);
13962
14474
  var processAudio = React.useCallback(function () {
14475
+ var inferredType = inferBlobType(audioChunks[0]) || (audioRecorder === null || audioRecorder === void 0 ? void 0 : audioRecorder.mimeType) || 'audio/mp4';
13963
14476
  var audioBlob = new Blob(audioChunks, {
13964
- type: 'audio/mp4'
14477
+ type: inferredType
13965
14478
  });
13966
14479
  useVideoRecorderStore.setState({
13967
14480
  audioUrl: URL.createObjectURL(audioBlob),
@@ -14001,6 +14514,7 @@ var useVideoRecorder = function useVideoRecorder(mergeAVStreams) {
14001
14514
  }, [audioRecordingIntentionallyStopped, audioRecordingStopped, audioUrl, isRecordingAudio, isRecordingVideo, videoRecordingIntentionallyStopped, videoRecordingStopped, videoUrl]);
14002
14515
  };
14003
14516
 
14517
+ var RECORDING_TIMESTAMP_PADDING_MS = 1000;
14004
14518
  var signatureRecorder = null;
14005
14519
  var signatureChunks = [];
14006
14520
  var videoSignatureInitialState = {
@@ -14013,7 +14527,6 @@ var videoSignatureInitialState = {
14013
14527
  clearRecordedData: function clearRecordedData() {
14014
14528
  return null;
14015
14529
  },
14016
- isRecording: false,
14017
14530
  signaturePad: {
14018
14531
  current: null
14019
14532
  },
@@ -14036,7 +14549,7 @@ var useVideoSignatureStore = zustand.create()(middleware.devtools(function (set,
14036
14549
  if (!camera) throw new Error('Camera not found');
14037
14550
  // set our flag and clear whatever we have recorded so far.
14038
14551
  set({
14039
- isRecording: true
14552
+ recordingStartedAt: performance.now()
14040
14553
  });
14041
14554
  signatureChunks = [];
14042
14555
  // start recording video and audio
@@ -14050,27 +14563,52 @@ var useVideoSignatureStore = zustand.create()(middleware.devtools(function (set,
14050
14563
  videoBitsPerSecond: 270000,
14051
14564
  audioBitsPerSecond: 32000
14052
14565
  });
14566
+ var hasFirstChunk = false;
14053
14567
  signatureRecorder.ondataavailable = function (event) {
14054
14568
  signatureChunks.push(event.data);
14569
+ if (!hasFirstChunk) {
14570
+ hasFirstChunk = true;
14571
+ set({
14572
+ firstChunkReceivedAt: performance.now(),
14573
+ lastChunkReceivedAt: performance.now()
14574
+ });
14575
+ } else {
14576
+ set({
14577
+ lastChunkReceivedAt: performance.now()
14578
+ });
14579
+ }
14055
14580
  };
14056
14581
  signatureRecorder.start(100);
14057
14582
  },
14058
14583
  stopRecording: function stopRecording(signatureData, imageUrl) {
14059
14584
  set({
14060
- isRecording: false
14585
+ firstChunkReceivedAt: undefined,
14586
+ recordingStoppedAt: performance.now()
14587
+ });
14588
+ waitForOneMoreChunk().then(function () {
14589
+ if (!signatureRecorder) return;
14590
+ signatureRecorder.stop();
14591
+ signatureRecorder.onstop = function () {
14592
+ var inferredType = inferBlobType(signatureChunks[0]) || (signatureRecorder === null || signatureRecorder === void 0 ? void 0 : signatureRecorder.mimeType) || 'video/mp4';
14593
+ var blob = new Blob(signatureChunks, {
14594
+ type: inferredType
14595
+ });
14596
+ signatureChunks = [];
14597
+ signatureRecorder = null;
14598
+ if (!signatureData) return;
14599
+ var _a = get(),
14600
+ onSignatureVideoCaptured = _a.onSignatureVideoCaptured,
14601
+ recordingStartedAt = _a.recordingStartedAt,
14602
+ signatureStartedAt = _a.signatureStartedAt,
14603
+ signatureEndedAt = _a.signatureEndedAt,
14604
+ lastChunkReceivedAt = _a.lastChunkReceivedAt;
14605
+ var endMs = Math.min(signatureEndedAt !== null && signatureEndedAt !== void 0 ? signatureEndedAt : Infinity, lastChunkReceivedAt !== null && lastChunkReceivedAt !== void 0 ? lastChunkReceivedAt : Infinity);
14606
+ var signatureStartTimestamp = signatureStartedAt && recordingStartedAt ? formatTimestamp(Math.max(0, signatureStartedAt - recordingStartedAt - RECORDING_TIMESTAMP_PADDING_MS)) : undefined;
14607
+ var signatureEndTimestamp = endMs !== Infinity && recordingStartedAt ? formatTimestamp(Math.min(endMs - recordingStartedAt + RECORDING_TIMESTAMP_PADDING_MS, lastChunkReceivedAt !== null && lastChunkReceivedAt !== void 0 ? lastChunkReceivedAt : Infinity)) : undefined;
14608
+ onSignatureVideoCaptured(blob, signatureData, imageUrl !== null && imageUrl !== void 0 ? imageUrl : null, signatureStartTimestamp, signatureEndTimestamp);
14609
+ };
14610
+ useVideoRecorderStore.getState().stopRecording();
14061
14611
  });
14062
- if (!signatureRecorder) return;
14063
- signatureRecorder.stop();
14064
- signatureRecorder.onstop = function () {
14065
- var blob = new Blob(signatureChunks, {
14066
- type: 'video/mp4'
14067
- });
14068
- signatureChunks = [];
14069
- signatureRecorder = null;
14070
- if (!signatureData) return;
14071
- get().onSignatureVideoCaptured(blob, signatureData, imageUrl !== null && imageUrl !== void 0 ? imageUrl : null);
14072
- };
14073
- useVideoRecorderStore.getState().stopRecording();
14074
14612
  },
14075
14613
  clearRecordedData: function clearRecordedData() {
14076
14614
  signatureChunks = [];
@@ -14079,13 +14617,42 @@ var useVideoSignatureStore = zustand.create()(middleware.devtools(function (set,
14079
14617
  signatureRecorder === null || signatureRecorder === void 0 ? void 0 : signatureRecorder.stop();
14080
14618
  signatureRecorder = null;
14081
14619
  set({
14082
- isRecording: false,
14620
+ recordingStartedAt: undefined,
14621
+ recordingStoppedAt: undefined,
14622
+ firstChunkReceivedAt: undefined,
14623
+ lastChunkReceivedAt: undefined,
14083
14624
  signaturePadEmpty: true,
14084
- signatureValid: false
14625
+ signatureValid: false,
14626
+ signatureStartedAt: undefined,
14627
+ signatureEndedAt: undefined
14085
14628
  });
14086
14629
  }
14087
14630
  });
14088
14631
  }));
14632
+ function waitForOneMoreChunk(timeoutMs) {
14633
+ if (timeoutMs === void 0) {
14634
+ timeoutMs = 3000;
14635
+ }
14636
+ var start = performance.now();
14637
+ return new Promise(function (resolve) {
14638
+ var initialLastChunkReceivedAt = useVideoSignatureStore.getState().lastChunkReceivedAt;
14639
+ if (!initialLastChunkReceivedAt) return resolve();
14640
+ function gotAChunk() {
14641
+ var lastChunkReceivedAt = useVideoSignatureStore.getState().lastChunkReceivedAt;
14642
+ return performance.now() - start > timeoutMs || !lastChunkReceivedAt || !initialLastChunkReceivedAt || lastChunkReceivedAt > initialLastChunkReceivedAt;
14643
+ }
14644
+ setTimeout(function () {
14645
+ if (gotAChunk()) return resolve(); // check immediately
14646
+ // otherwise, check every 100ms
14647
+ var interval = setInterval(function () {
14648
+ if (gotAChunk()) {
14649
+ clearInterval(interval);
14650
+ resolve();
14651
+ }
14652
+ }, 100);
14653
+ }, 0);
14654
+ });
14655
+ }
14089
14656
  function VideoSignatureContextProvider(_a) {
14090
14657
  var _this = this;
14091
14658
  var _b, _c;
@@ -14104,7 +14671,14 @@ function VideoSignatureContextProvider(_a) {
14104
14671
  // clear recorded data when the component is mounted
14105
14672
  useVideoSignatureStore.getState().clearRecordedData();
14106
14673
  }, []);
14107
- var isRecording = useVideoSignatureStore().isRecording;
14674
+ var _e = useVideoSignatureStore(shallow.useShallow(function (state) {
14675
+ return {
14676
+ recordingStartedAt: state.recordingStartedAt,
14677
+ recordingStoppedAt: state.recordingStoppedAt
14678
+ };
14679
+ })),
14680
+ recordingStartedAt = _e.recordingStartedAt,
14681
+ recordingStoppedAt = _e.recordingStoppedAt;
14108
14682
  useFrameLoop(React.useCallback(function () {
14109
14683
  return __awaiter(_this, void 0, void 0, function () {
14110
14684
  var signaturePad, ctx, _a, w, h, isPortrait, rect;
@@ -14131,7 +14705,7 @@ function VideoSignatureContextProvider(_a) {
14131
14705
  });
14132
14706
  });
14133
14707
  }, [videoRef]), {
14134
- autoStart: isRecording,
14708
+ autoStart: !!recordingStartedAt && !recordingStoppedAt,
14135
14709
  throttleMs: 1000 / 24
14136
14710
  });
14137
14711
  return /*#__PURE__*/React__namespace.default.createElement(React__namespace.default.Fragment, null, children, /*#__PURE__*/React__namespace.default.createElement(InvisibleCanvas, {
@@ -14140,6 +14714,17 @@ function VideoSignatureContextProvider(_a) {
14140
14714
  height: (_c = videoRef.current) === null || _c === void 0 ? void 0 : _c.videoHeight
14141
14715
  }));
14142
14716
  }
14717
+ function formatTimestamp(durationMs) {
14718
+ // should be in the format of 00:00:00:00 (hh:mm:ss:cs)
14719
+ var hours = Math.floor(durationMs / 3600000);
14720
+ var minutes = Math.floor(durationMs % 3600000 / 60000);
14721
+ var seconds = Math.floor(durationMs % 60000 / 1000);
14722
+ var milliseconds = durationMs % 1000;
14723
+ // Convert milliseconds to centiseconds (1/100th of a second)
14724
+ var centiseconds = Math.floor(milliseconds / 10);
14725
+ var csString = centiseconds.toString().padStart(2, '0');
14726
+ return "".concat(hours.toString().padStart(2, '0'), ":") + "".concat(minutes.toString().padStart(2, '0'), ":") + "".concat(seconds.toString().padStart(2, '0'), ":") + "".concat(csString);
14727
+ }
14143
14728
 
14144
14729
  function VideoSignaturePad(_a) {
14145
14730
  var onAcceptBtnClicked = _a.onAcceptBtnClicked,
@@ -14201,8 +14786,11 @@ function VideoSignaturePad(_a) {
14201
14786
  ref: signaturePad,
14202
14787
  canvasProps: canvasProps,
14203
14788
  onBegin: function onBegin() {
14204
- return useVideoSignatureStore.setState({
14205
- signaturePadEmpty: false
14789
+ return useVideoSignatureStore.setState(function (s) {
14790
+ return {
14791
+ signaturePadEmpty: false,
14792
+ signatureStartedAt: s.signatureStartedAt || performance.now()
14793
+ };
14206
14794
  });
14207
14795
  },
14208
14796
  onEnd: function onEnd() {
@@ -14212,7 +14800,8 @@ function VideoSignaturePad(_a) {
14212
14800
  return point;
14213
14801
  });
14214
14802
  useVideoSignatureStore.setState({
14215
- signatureValid: points.length >= minSignaturePadPoints
14803
+ signatureValid: points.length >= minSignaturePadPoints,
14804
+ signatureEndedAt: performance.now()
14216
14805
  });
14217
14806
  }
14218
14807
  }), !headTrackingSatisfied && !!verbiage.headTrackingUnsatisfiedText ? ( /*#__PURE__*/React__namespace.default.createElement(SignaturePadContentContainer, {
@@ -14279,6 +14868,12 @@ function VideoSignatureGuides(_a) {
14279
14868
  React.useEffect(function () {
14280
14869
  if (guideToDisplay) setMode(guideToDisplay);
14281
14870
  }, [guideToDisplay]);
14871
+ var firstChunkReceivedAt = useVideoSignatureStore(shallow.useShallow(function (state) {
14872
+ return {
14873
+ firstChunkReceivedAt: state.firstChunkReceivedAt
14874
+ };
14875
+ })).firstChunkReceivedAt;
14876
+ var signaturePadDisabled = requestedAction !== 'CAPTURE_SIGNATURE' || !firstChunkReceivedAt;
14282
14877
  return /*#__PURE__*/React__namespace.default.createElement(Container$3, {
14283
14878
  className: classNames.container
14284
14879
  }, /*#__PURE__*/React__namespace.default.createElement(Inner$1, {
@@ -14302,7 +14897,7 @@ function VideoSignatureGuides(_a) {
14302
14897
  }, /*#__PURE__*/React__namespace.default.createElement(VideoSignaturePad, {
14303
14898
  onAcceptBtnClicked: onAcceptBtnClicked,
14304
14899
  onClearBtnClicked: onClearBtnClicked,
14305
- disabled: requestedAction !== 'CAPTURE_SIGNATURE',
14900
+ disabled: signaturePadDisabled,
14306
14901
  headTrackingSatisfied: headTrackingSatisfied,
14307
14902
  minSignaturePadPoints: minSignaturePadPoints,
14308
14903
  classNames: classNames,
@@ -14359,9 +14954,11 @@ var VideoSignatureCapture = function VideoSignatureCapture(_a) {
14359
14954
  onHeadTrackingPredictionMade = _o.onPredictionMade,
14360
14955
  startHeadTracking = _o.start,
14361
14956
  stopHeadTracking = _o.stop;
14362
- var _p = useVideoSignatureStore(),
14363
- clearRecordedData = _p.clearRecordedData,
14364
- isRecording = _p.isRecording;
14957
+ var firstChunkReceivedAt = useVideoSignatureStore(shallow.useShallow(function (state) {
14958
+ return {
14959
+ firstChunkReceivedAt: state.firstChunkReceivedAt
14960
+ };
14961
+ })).firstChunkReceivedAt;
14365
14962
  React.useEffect(function () {
14366
14963
  useVideoSignatureStore.setState({
14367
14964
  onSignatureVideoCaptured: onSignatureVideoCaptured
@@ -14380,15 +14977,15 @@ var VideoSignatureCapture = function VideoSignatureCapture(_a) {
14380
14977
  var verbiage = useTranslations(rawVerbiage, {
14381
14978
  guidanceMessageText: 'Please sign the box below'
14382
14979
  });
14383
- var _q = React.useState(true),
14384
- headTrackingSatisfied = _q[0],
14385
- setHeadTrackingSatisfied = _q[1];
14386
- var _r = React.useState(null),
14387
- lastFace = _r[0],
14388
- setLastFace = _r[1];
14389
- var _s = React.useState(0),
14390
- numFramesWithoutFaces = _s[0],
14391
- setNumFramesWithoutFaces = _s[1];
14980
+ var _p = React.useState(true),
14981
+ headTrackingSatisfied = _p[0],
14982
+ setHeadTrackingSatisfied = _p[1];
14983
+ var _q = React.useState(null),
14984
+ lastFace = _q[0],
14985
+ setLastFace = _q[1];
14986
+ var _r = React.useState(0),
14987
+ numFramesWithoutFaces = _r[0],
14988
+ setNumFramesWithoutFaces = _r[1];
14392
14989
  onHeadTrackingPredictionMade(useDebounce.useThrottledCallback(React.useCallback(function (_a) {
14393
14990
  var face = _a.face;
14394
14991
  if (headTrackingDisabled) return;
@@ -14403,12 +15000,12 @@ var VideoSignatureCapture = function VideoSignatureCapture(_a) {
14403
15000
  return n + 1;
14404
15001
  });
14405
15002
  }, [headTrackingBoundaryPercentage, headTrackingBoundaryType, headTrackingDisabled, videoHeight, videoWidth]), 16));
14406
- var _t = useResizeObserver(),
14407
- ref = _t.ref,
14408
- _u = _t.width,
14409
- width = _u === void 0 ? 1 : _u,
14410
- _v = _t.height,
14411
- height = _v === void 0 ? 1 : _v;
15003
+ var _s = useResizeObserver(),
15004
+ ref = _s.ref,
15005
+ _t = _s.width,
15006
+ width = _t === void 0 ? 1 : _t,
15007
+ _u = _s.height,
15008
+ height = _u === void 0 ? 1 : _u;
14412
15009
  var debugScalingDetails = useDebugScalingDetails({
14413
15010
  enabled: debugMode,
14414
15011
  pageWidth: width,
@@ -14439,13 +15036,19 @@ var VideoSignatureCapture = function VideoSignatureCapture(_a) {
14439
15036
  classNames: classNames.guides,
14440
15037
  verbiage: rawVerbiage.guides,
14441
15038
  onClearBtnClicked: restartVideoOnSignaturePadCleared ? function () {
14442
- return setTimeout(clearRecordedData, 100);
14443
- } : undefined
15039
+ return setTimeout(function () {
15040
+ return useVideoSignatureStore.getState().clearRecordedData();
15041
+ }, 100);
15042
+ } : function () {
15043
+ return useVideoSignatureStore.setState({
15044
+ signatureStartedAt: undefined
15045
+ });
15046
+ }
14444
15047
  }), debugMode && ( /*#__PURE__*/React__namespace.default.createElement(React__namespace.default.Fragment, null, /*#__PURE__*/React__namespace.default.createElement(ObjectDetectionDebugOverlayDiv, null, lastFace && ( /*#__PURE__*/React__namespace.default.createElement(SelfieCaptureFaceDebugBox, {
14445
15048
  face: lastFace,
14446
15049
  scaling: debugScalingDetails,
14447
15050
  color: headTrackingSatisfied ? 'green' : 'red'
14448
- }))), /*#__PURE__*/React__namespace.default.createElement(DebugStatsPane, null, "Video: ", videoWidth, "x", videoHeight, /*#__PURE__*/React__namespace.default.createElement("br", null), "Recording: ", isRecording ? 'true' : 'false'))), /*#__PURE__*/React__namespace.default.createElement(ExitCaptureButton, {
15051
+ }))), /*#__PURE__*/React__namespace.default.createElement(DebugStatsPane, null, "Video: ", videoWidth, "x", videoHeight, /*#__PURE__*/React__namespace.default.createElement("br", null), "Recording: ", firstChunkReceivedAt ? 'true' : 'false'))), /*#__PURE__*/React__namespace.default.createElement(ExitCaptureButton, {
14449
15052
  onClick: onExit,
14450
15053
  className: classNames.exitCaptureBtn
14451
15054
  }));
@@ -14776,6 +15379,8 @@ var VideoSignatureWizard = function VideoSignatureWizard(_a) {
14776
15379
  setSelfieImage = _u.setSelfieImage,
14777
15380
  setSignatureData = _u.setSignatureData,
14778
15381
  setSignatureVideoUrl = _u.setSignatureVideoUrl,
15382
+ setSignatureStartTimestamp = _u.setSignatureStartTimestamp,
15383
+ setSignatureEndTimestamp = _u.setSignatureEndTimestamp,
14779
15384
  logSelfieCaptureAttempt = _u.logSelfieCaptureAttempt,
14780
15385
  uploadDocument = _u.uploadDocument;
14781
15386
  var cameraAccessDenied = useCameraStore(shallow.useShallow(function (state) {
@@ -14835,12 +15440,14 @@ var VideoSignatureWizard = function VideoSignatureWizard(_a) {
14835
15440
  filetype: 'image/jpeg'
14836
15441
  }).then(onSelfieCaptured);
14837
15442
  }, [logCaptureMetadata, onSelfieCaptured, setSelfieImage, uploadDocument]);
14838
- var onSignatureCaptureCompleted = React.useCallback(function (videoData, signatureData, signatureImageData) {
15443
+ var onSignatureCaptureCompleted = React.useCallback(function (videoData, signatureData, signatureImageData, signatureStartTimestamp, signatureEndTimestamp) {
14839
15444
  setSignatureData(signatureData);
14840
15445
  setSignatureVideoUrl(URL.createObjectURL(videoData));
15446
+ if (signatureStartTimestamp) setSignatureStartTimestamp(signatureStartTimestamp);
15447
+ if (signatureEndTimestamp) setSignatureEndTimestamp(signatureEndTimestamp);
14841
15448
  setCaptureState('SUCCESS');
14842
- onVideoCaptured === null || onVideoCaptured === void 0 ? void 0 : onVideoCaptured(videoData, signatureData, signatureImageData);
14843
- }, [onVideoCaptured, setSignatureData, setSignatureVideoUrl]);
15449
+ onVideoCaptured === null || onVideoCaptured === void 0 ? void 0 : onVideoCaptured(videoData, signatureData, signatureImageData, signatureStartTimestamp, signatureEndTimestamp);
15450
+ }, [onVideoCaptured, setSignatureData, setSignatureEndTimestamp, setSignatureStartTimestamp, setSignatureVideoUrl]);
14844
15451
  var _x = React.useState(true),
14845
15452
  showLoadingOverlay = _x[0],
14846
15453
  setShowLoadingOverlay = _x[1];
@@ -15009,6 +15616,7 @@ function VideoSignatureWizardGuides(_a) {
15009
15616
  var onClearBtnClicked = React.useCallback(function () {
15010
15617
  var _a, _b;
15011
15618
  useVideoSignatureStore.setState({
15619
+ signatureStartedAt: undefined,
15012
15620
  signaturePadEmpty: true,
15013
15621
  signatureValid: false
15014
15622
  });