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
package/dist/sdk2.esm.js CHANGED
@@ -7,7 +7,7 @@ import { createPortal } from 'react-dom';
7
7
  import { useTranslation, initReactI18next } from 'react-i18next';
8
8
  import { Upload } from 'tus-js-client';
9
9
  import SparkMD5 from 'spark-md5';
10
- import { ImageSegmenter, FilesetResolver, ImageClassifier, FaceDetector, ObjectDetector } from '@mediapipe/tasks-vision';
10
+ import { ImageSegmenter, FilesetResolver, ObjectDetector, ImageClassifier, FaceDetector } from '@mediapipe/tasks-vision';
11
11
  import { useStore, createStore, create } from 'zustand';
12
12
  import LanguageDetector from 'i18next-browser-languagedetector';
13
13
  import i18n from 'i18next';
@@ -205,7 +205,7 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
205
205
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
206
206
  };
207
207
 
208
- var webSdkVersion = '2.3.88';
208
+ var webSdkVersion = '2.3.90';
209
209
 
210
210
  function getPlatform() {
211
211
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -466,27 +466,27 @@ var GuidanceMessageContainer = function GuidanceMessageContainer(props) {
466
466
  if (!portalLocation) return element;
467
467
  return /*#__PURE__*/createPortal(element, portalLocation);
468
468
  };
469
- var GuidanceMessage = styled.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) {
469
+ var GuidanceMessage = styled.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) {
470
470
  var _a, _b, _c, _d, _e, _f;
471
471
  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';
472
472
  }, function (props) {
473
473
  var _a, _b, _c, _d, _e, _f;
474
474
  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';
475
475
  });
476
- var templateObject_1$P, templateObject_2$I;
476
+ var templateObject_1$P, templateObject_2$J;
477
477
 
478
478
  var wavesAnimation = 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"])));
479
- var progressBarAnimation = 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"])));
479
+ var progressBarAnimation = 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"])));
480
480
  var dualRingSpinnerAnimation = 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"])));
481
481
  var progressBorderAnimation = keyframes(templateObject_4$o || (templateObject_4$o = __makeTemplateObject(["\n to {\n stroke-dashoffset: 0;\n }\n"], ["\n to {\n stroke-dashoffset: 0;\n }\n"])));
482
- var templateObject_1$O, templateObject_2$H, templateObject_3$u, templateObject_4$o;
482
+ var templateObject_1$O, templateObject_2$I, templateObject_3$u, templateObject_4$o;
483
483
 
484
484
  var OverlayContainer = styled.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) {
485
485
  return props.theme.background ? "".concat(props.theme.background) : "white";
486
486
  }, function (props) {
487
487
  return props.theme.textColor ? "color: ".concat(props.theme.textColor, ";") : "";
488
488
  });
489
- var OverlayInner$2 = styled.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) {
489
+ var OverlayInner$2 = styled.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) {
490
490
  var _a;
491
491
  return (_a = props.theme.textAlign) !== null && _a !== void 0 ? _a : 'center';
492
492
  }, function (props) {
@@ -534,7 +534,7 @@ var LoadingOverlayLoadingListItem = styled.li(templateObject_19 || (templateObje
534
534
  var LoadingOverlayProgressContainer = styled.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"])));
535
535
  var LoadingOverlayCustomLoadingGraphic = styled.img(templateObject_21 || (templateObject_21 = __makeTemplateObject(["\n transform-style: preserve-3d;\n"], ["\n transform-style: preserve-3d;\n"])));
536
536
  var LoadingOverlayContinueButtonContainer = styled.div(templateObject_22 || (templateObject_22 = __makeTemplateObject(["\n display: flex;\n"], ["\n display: flex;\n"])));
537
- 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;
537
+ 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;
538
538
 
539
539
  var GeolocationAccessDeniedOverlay = function GeolocationAccessDeniedOverlay(_a) {
540
540
  var accessBlockedImageUrl = _a.accessBlockedImageUrl;
@@ -1103,6 +1103,11 @@ var SubmissionContext = /*#__PURE__*/createContext({
1103
1103
  idFrontImage: null,
1104
1104
  idBackImage: null,
1105
1105
  passportImage: null,
1106
+ idFrontIrImage: null,
1107
+ idBackIrImage: null,
1108
+ idFrontUvImage: null,
1109
+ idBackUvImage: null,
1110
+ idBarcodeImage: null,
1106
1111
  selfieImage: null,
1107
1112
  signatureData: null,
1108
1113
  signatureVideoUrl: null,
@@ -1133,6 +1138,9 @@ var SubmissionContext = /*#__PURE__*/createContext({
1133
1138
  setIdBackUvImage: function setIdBackUvImage() {
1134
1139
  return null;
1135
1140
  },
1141
+ setIdBarcodeImage: function setIdBarcodeImage() {
1142
+ return null;
1143
+ },
1136
1144
  setSelfieImage: function setSelfieImage() {
1137
1145
  return null;
1138
1146
  },
@@ -1145,6 +1153,12 @@ var SubmissionContext = /*#__PURE__*/createContext({
1145
1153
  setIdCaptureVideoUrl: function setIdCaptureVideoUrl() {
1146
1154
  return null;
1147
1155
  },
1156
+ setSignatureStartTimestamp: function setSignatureStartTimestamp() {
1157
+ return null;
1158
+ },
1159
+ setSignatureEndTimestamp: function setSignatureEndTimestamp() {
1160
+ return null;
1161
+ },
1148
1162
  setIdCaptureVideoIdFrontImage: function setIdCaptureVideoIdFrontImage() {
1149
1163
  return null;
1150
1164
  },
@@ -1300,53 +1314,62 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1300
1314
  passportImage = _13[0],
1301
1315
  setPassportImage = _13[1];
1302
1316
  var _14 = useState(null),
1303
- selfieImage = _14[0],
1304
- setSelfieImage = _14[1];
1317
+ idBarcodeImage = _14[0],
1318
+ setIdBarcodeImage = _14[1];
1305
1319
  var _15 = useState(null),
1306
- signatureData = _15[0],
1307
- setSignatureData = _15[1];
1320
+ selfieImage = _15[0],
1321
+ setSelfieImage = _15[1];
1308
1322
  var _16 = useState(null),
1309
- signatureVideoUrl = _16[0],
1310
- setSignatureVideoUrl = _16[1];
1323
+ signatureData = _16[0],
1324
+ setSignatureData = _16[1];
1311
1325
  var _17 = useState(null),
1312
- idCaptureVideoUrl = _17[0],
1313
- setIdCaptureVideoUrl = _17[1];
1326
+ signatureVideoUrl = _17[0],
1327
+ setSignatureVideoUrl = _17[1];
1314
1328
  var _18 = useState(null),
1315
- idCaptureVideoIdFrontImage = _18[0],
1316
- setIdCaptureVideoIdFrontImage = _18[1];
1329
+ signatureStartTimestamp = _18[0],
1330
+ setSignatureStartTimestamp = _18[1];
1317
1331
  var _19 = useState(null),
1318
- idCaptureVideoIdBackImage = _19[0],
1319
- setIdCaptureVideoIdBackImage = _19[1];
1332
+ signatureEndTimestamp = _19[0],
1333
+ setSignatureEndTimestamp = _19[1];
1320
1334
  var _20 = useState(null),
1321
- idCaptureVideoAudioUrl = _20[0],
1322
- setIdCaptureVideoAudioUrl = _20[1];
1335
+ idCaptureVideoUrl = _20[0],
1336
+ setIdCaptureVideoUrl = _20[1];
1323
1337
  var _21 = useState(null),
1324
- idCaptureVideoAudioStartsAt = _21[0],
1325
- setIdCaptureVideoAudioStartsAt = _21[1];
1338
+ idCaptureVideoIdFrontImage = _21[0],
1339
+ setIdCaptureVideoIdFrontImage = _21[1];
1326
1340
  var _22 = useState(null),
1327
- expectedAudioText = _22[0],
1328
- setExpectedAudioText = _22[1];
1341
+ idCaptureVideoIdBackImage = _22[0],
1342
+ setIdCaptureVideoIdBackImage = _22[1];
1329
1343
  var _23 = useState(null),
1330
- additionalDocuments = _23[0],
1331
- setAdditionalDocuments = _23[1];
1344
+ idCaptureVideoAudioUrl = _23[0],
1345
+ setIdCaptureVideoAudioUrl = _23[1];
1332
1346
  var _24 = useState(null),
1333
- geolocationResult = _24[0],
1334
- setGeolocationResult = _24[1];
1335
- var _25 = useState(0),
1336
- geolocationAttempts = _25[0],
1337
- setGeolocationAttempts = _25[1];
1338
- var _26 = useState(false),
1339
- geolocationBlocked = _26[0],
1340
- setGeolocationBlocked = _26[1];
1341
- var _27 = useState([]),
1342
- idFrontCaptureAttempts = _27[0],
1343
- setIdFrontCaptureAttempts = _27[1];
1344
- var _28 = useState([]),
1345
- idBackCaptureAttempts = _28[0],
1346
- setIdBackCaptureAttempts = _28[1];
1347
- var _29 = useState([]),
1348
- selfieCaptureAttempts = _29[0],
1349
- setSelfieCaptureAttempts = _29[1];
1347
+ idCaptureVideoAudioStartsAt = _24[0],
1348
+ setIdCaptureVideoAudioStartsAt = _24[1];
1349
+ var _25 = useState(null),
1350
+ expectedAudioText = _25[0],
1351
+ setExpectedAudioText = _25[1];
1352
+ var _26 = useState(null),
1353
+ additionalDocuments = _26[0],
1354
+ setAdditionalDocuments = _26[1];
1355
+ var _27 = useState(null),
1356
+ geolocationResult = _27[0],
1357
+ setGeolocationResult = _27[1];
1358
+ var _28 = useState(0),
1359
+ geolocationAttempts = _28[0],
1360
+ setGeolocationAttempts = _28[1];
1361
+ var _29 = useState(false),
1362
+ geolocationBlocked = _29[0],
1363
+ setGeolocationBlocked = _29[1];
1364
+ var _30 = useState([]),
1365
+ idFrontCaptureAttempts = _30[0],
1366
+ setIdFrontCaptureAttempts = _30[1];
1367
+ var _31 = useState([]),
1368
+ idBackCaptureAttempts = _31[0],
1369
+ setIdBackCaptureAttempts = _31[1];
1370
+ var _32 = useState([]),
1371
+ selfieCaptureAttempts = _32[0],
1372
+ setSelfieCaptureAttempts = _32[1];
1350
1373
  var logIdFrontCaptureAttempt = useCallback(function (attempt) {
1351
1374
  setIdFrontCaptureAttempts(function (attempts) {
1352
1375
  return __spreadArray(__spreadArray([], attempts, true), [attempt], false);
@@ -1472,6 +1495,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1472
1495
  idFrontImage: idFrontImage,
1473
1496
  idBackImage: idBackImage,
1474
1497
  passportImage: passportImage,
1498
+ idBarcodeImage: idBarcodeImage,
1475
1499
  selfieImage: selfieImage
1476
1500
  };
1477
1501
  _a = signatureVideoUrl;
@@ -1577,6 +1601,9 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1577
1601
  if (documents.passportImage) {
1578
1602
  submissionRequest.customerData.idData.idImageFront = documents.passportImage;
1579
1603
  }
1604
+ if (documents.idBarcodeImage) {
1605
+ submissionRequest.customerData.idData.idBarcodeImage = documents.idBarcodeImage;
1606
+ }
1580
1607
  if (documents.idFrontIrImage) {
1581
1608
  submissionRequest.customerData.idData.idFrontIrImage = documents.idFrontIrImage;
1582
1609
  }
@@ -1623,6 +1650,12 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1623
1650
  submissionRequest.customerData.signatureData.signatureVideo = documents.signatureVideo;
1624
1651
  }
1625
1652
  }
1653
+ if (signatureStartTimestamp) {
1654
+ submissionRequest.customerData.signatureStartTimestamp = signatureStartTimestamp;
1655
+ }
1656
+ if (signatureEndTimestamp) {
1657
+ submissionRequest.customerData.signatureEndTimestamp = signatureEndTimestamp;
1658
+ }
1626
1659
  if (additionalDocuments) {
1627
1660
  submissionRequest.customerData.additionalDocuments = additionalDocuments.map(function (d) {
1628
1661
  return _assign(_assign({}, d), {
@@ -1665,7 +1698,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1665
1698
  }
1666
1699
  });
1667
1700
  });
1668
- }, [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]);
1701
+ }, [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]);
1669
1702
  var defaultOnSubmit = useCallback(function () {
1670
1703
  return __awaiter(void 0, void 0, void 0, function () {
1671
1704
  var submissionResponse_1, payload, host, endpoint, response, statusMessage, submissionResponse_2, e_1, err;
@@ -1943,6 +1976,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1943
1976
  idFrontUvImage: idFrontUvImage,
1944
1977
  idBackUvImage: idBackUvImage,
1945
1978
  passportImage: passportImage,
1979
+ idBarcodeImage: idBarcodeImage,
1946
1980
  selfieImage: selfieImage,
1947
1981
  signatureData: signatureData,
1948
1982
  signatureVideoUrl: signatureVideoUrl,
@@ -1959,9 +1993,12 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1959
1993
  setIdBackIrImage: setIdBackIrImage,
1960
1994
  setIdFrontUvImage: setIdFrontUvImage,
1961
1995
  setIdBackUvImage: setIdBackUvImage,
1996
+ setIdBarcodeImage: setIdBarcodeImage,
1962
1997
  setSelfieImage: setSelfieImage,
1963
1998
  setSignatureData: setSignatureData,
1964
1999
  setSignatureVideoUrl: setSignatureVideoUrl,
2000
+ setSignatureStartTimestamp: setSignatureStartTimestamp,
2001
+ setSignatureEndTimestamp: setSignatureEndTimestamp,
1965
2002
  setIdCaptureVideoUrl: setIdCaptureVideoUrl,
1966
2003
  setIdCaptureVideoIdFrontImage: setIdCaptureVideoIdFrontImage,
1967
2004
  setIdCaptureVideoIdBackImage: setIdCaptureVideoIdBackImage,
@@ -1977,7 +2014,7 @@ var SubmissionProvider = function SubmissionProvider(_a) {
1977
2014
  checkLiveness: checkLiveness,
1978
2015
  retryLocationAccess: retryLocationAccess
1979
2016
  };
1980
- }, [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]);
2017
+ }, [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]);
1981
2018
  return /*#__PURE__*/React__default.createElement(SubmissionContext.Provider, {
1982
2019
  value: value
1983
2020
  }, geolocationRequired && geolocationBlocked ? ( /*#__PURE__*/React__default.createElement(GeolocationAccessDeniedOverlay, null)) : children, submissionError && ( /*#__PURE__*/React__default.createElement(SubmissionErrorOverlay, {
@@ -2171,97 +2208,6 @@ function preloadVisionRuntime() {
2171
2208
  });
2172
2209
  }
2173
2210
 
2174
- function getFrameDimensions(frame) {
2175
- var frameWidth = frame.width,
2176
- frameHeight = frame.height;
2177
- if (frame instanceof HTMLImageElement) {
2178
- frameWidth = frame.naturalWidth;
2179
- frameHeight = frame.naturalHeight;
2180
- }
2181
- if (frame instanceof HTMLVideoElement) {
2182
- frameWidth = frame.videoWidth;
2183
- frameHeight = frame.videoHeight;
2184
- }
2185
- return [frameWidth, frameHeight];
2186
- }
2187
-
2188
- var InvisibleCanvas = styled.canvas(templateObject_1$M || (templateObject_1$M = __makeTemplateObject(["\n display: none;\n"], ["\n display: none;\n"])));
2189
- function drawToCanvas(canvas, frame, width, height) {
2190
- if (!canvas) return;
2191
- var ctx = canvas.getContext('2d');
2192
- if (!ctx) return;
2193
- if (!width || !height) {
2194
- var _a = getFrameDimensions(frame),
2195
- frameWidth = _a[0],
2196
- frameHeight = _a[1];
2197
- width || (width = frameWidth);
2198
- height || (height = frameHeight);
2199
- }
2200
- canvas.width = width;
2201
- canvas.height = height;
2202
- ctx.drawImage(frame, 0, 0, width, height);
2203
- }
2204
- function clearCanvas(canvas) {
2205
- var _a;
2206
- (_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);
2207
- }
2208
- var templateObject_1$M;
2209
-
2210
- function cropToShoulders(rawCanvas, cropCanvas, resizeCanvas, frame, face, quality, maxHeight) {
2211
- var _a;
2212
- if (quality === void 0) {
2213
- quality = 0.92;
2214
- }
2215
- if (!rawCanvas || !cropCanvas || !resizeCanvas) return '';
2216
- var rawCtx = rawCanvas.getContext('2d');
2217
- var cropCtx = cropCanvas.getContext('2d');
2218
- var resizeCtx = resizeCanvas.getContext('2d');
2219
- if (!rawCtx || !cropCtx || !resizeCtx) throw new Error('could not get 2d context');
2220
- rawCanvas.width = frame.width;
2221
- rawCanvas.height = frame.height;
2222
- rawCtx.putImageData(frame, 0, 0);
2223
- if (frame.height > frame.width) {
2224
- cropCanvas.width = frame.width;
2225
- cropCanvas.height = frame.height;
2226
- cropCtx.drawImage(rawCanvas, 0, 0, cropCanvas.width, cropCanvas.height);
2227
- } else {
2228
- var _b = (_a = face === null || face === void 0 ? void 0 : face.box) !== null && _a !== void 0 ? _a : {
2229
- xMin: 0,
2230
- width: frame.width
2231
- },
2232
- xMin = _b.xMin,
2233
- width = _b.width;
2234
- var desiredWidth = frame.height * 0.6;
2235
- var faceCenterX = xMin + width / 2;
2236
- var xPos = Math.max(0, faceCenterX - desiredWidth / 2);
2237
- cropCanvas.width = desiredWidth;
2238
- cropCanvas.height = frame.height;
2239
- cropCtx.drawImage(rawCanvas, xPos, 0, cropCanvas.width, cropCanvas.height, 0, 0, cropCanvas.width, cropCanvas.height);
2240
- }
2241
- resizeCanvas.height = maxHeight !== null && maxHeight !== void 0 ? maxHeight : cropCanvas.height;
2242
- resizeCanvas.width = cropCanvas.width * (resizeCanvas.height / cropCanvas.height);
2243
- resizeCtx === null || resizeCtx === void 0 ? void 0 : resizeCtx.drawImage(cropCanvas, 0, 0, resizeCanvas.width, resizeCanvas.height);
2244
- var dataURL = resizeCanvas.toDataURL('image/jpeg', quality);
2245
- log('cropToShoulders size', new TextEncoder().encode(dataURL).length);
2246
- clearCanvas(rawCanvas);
2247
- clearCanvas(cropCanvas);
2248
- clearCanvas(resizeCanvas);
2249
- return dataURL;
2250
- }
2251
- function cropToDetectedObjectBox(frame, box, canvas) {
2252
- canvas || (canvas = document.createElement('canvas'));
2253
- var ctx = canvas.getContext('2d');
2254
- if (!ctx) throw new Error('could not get 2d context');
2255
- var xMin = box.xMin,
2256
- yMin = box.yMin,
2257
- width = box.width,
2258
- height = box.height;
2259
- canvas.width = width;
2260
- canvas.height = height;
2261
- ctx.drawImage(frame, xMin, yMin, width, height, 0, 0, width, height);
2262
- return canvas;
2263
- }
2264
-
2265
2211
  var defaultImageSegmenterModelPath = 'https://websdk-cdn-dev.idmission.com/assets/models/selfiesegmenter20240524/selfie_segmenter.tflite';
2266
2212
  var imageSegmenterModelSizeInBytes = 256440.32;
2267
2213
  // 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
@@ -2391,6 +2337,192 @@ function giveUpAfter(maxTime) {
2391
2337
  });
2392
2338
  }
2393
2339
 
2340
+ var DEFAULT_CDN_URL = 'https://websdk-cdn-dev.idmission.com/assets';
2341
+
2342
+ var defaultDocumentDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/DocumentDetector/DocumentDetector-20250815_115859.tflite");
2343
+
2344
+ var defaultFocusModelPath = "".concat(DEFAULT_CDN_URL, "/models/Focus/Focus-20241008_102708.tflite");
2345
+
2346
+ var defaultFaceDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/FaceDetector/FaceDetector-20250820_154546.tflite");
2347
+
2348
+ var defaultBarcodeReadabilityModelPath = "".concat(DEFAULT_CDN_URL, "/models/BarcodeReadability/BarcodeReadability-20250815_120417.tflite");
2349
+
2350
+ var defaultModelPaths = {
2351
+ documentDetector: defaultDocumentDetectorModelPath,
2352
+ focus: defaultFocusModelPath,
2353
+ faceDetection: defaultFaceDetectorModelPath,
2354
+ barcodeReadability: defaultBarcodeReadabilityModelPath
2355
+ };
2356
+
2357
+ var preloadModels = function preloadModels(_a) {
2358
+ return __awaiter(void 0, [_a], void 0, function (_b) {
2359
+ var preloadTasks;
2360
+ var _c = _b.documentDetectionModel,
2361
+ documentDetectionModel = _c === void 0 ? true : _c,
2362
+ _d = _b.focusModel,
2363
+ focusModel = _d === void 0 ? true : _d,
2364
+ _e = _b.faceDetectionModel,
2365
+ faceDetectionModel = _e === void 0 ? true : _e,
2366
+ _f = _b.barcodeReadabilityModel,
2367
+ barcodeReadabilityModel = _f === void 0 ? true : _f;
2368
+ return __generator(this, function (_g) {
2369
+ switch (_g.label) {
2370
+ case 0:
2371
+ return [4 /*yield*/, probeModelCapabilities()];
2372
+ case 1:
2373
+ _g.sent();
2374
+ preloadTasks = [];
2375
+ if (documentDetectionModel) {
2376
+ preloadTasks.push(preloadDocumentDetectorDependencies);
2377
+ }
2378
+ if (focusModel) {
2379
+ preloadTasks.push(preloadFocusModelDependencies);
2380
+ }
2381
+ if (faceDetectionModel) {
2382
+ preloadTasks.push(preloadFaceDetectorDependencies);
2383
+ }
2384
+ if (barcodeReadabilityModel) {
2385
+ preloadTasks.push(preloadBarcodeReadabilityModelDependencies);
2386
+ }
2387
+ return [4 /*yield*/, Promise.all(preloadTasks)];
2388
+ case 2:
2389
+ _g.sent();
2390
+ return [2 /*return*/];
2391
+ }
2392
+ });
2393
+ });
2394
+ };
2395
+ var progressByUrl = {};
2396
+ var progressByUseCase = {
2397
+ visionRuntime: {
2398
+ loaded: 0,
2399
+ total: 0
2400
+ },
2401
+ documentDetector: {
2402
+ loaded: 0,
2403
+ total: 0
2404
+ },
2405
+ focus: {
2406
+ loaded: 0,
2407
+ total: 0
2408
+ },
2409
+ faceDetection: {
2410
+ loaded: 0,
2411
+ total: 0
2412
+ },
2413
+ barcodeReadability: {
2414
+ loaded: 0,
2415
+ total: 0
2416
+ }
2417
+ };
2418
+ function preloadDependency(url) {
2419
+ return __awaiter(this, void 0, void 0, function () {
2420
+ return __generator(this, function (_a) {
2421
+ return [2 /*return*/, new Promise(function (resolve, reject) {
2422
+ var req = new XMLHttpRequest();
2423
+ req.addEventListener('progress', function (event) {
2424
+ if (!event.lengthComputable) return;
2425
+ progressByUrl[url] = event;
2426
+ document.dispatchEvent(new CustomEvent('idmission.preloadProgress', {
2427
+ detail: {
2428
+ url: url,
2429
+ loaded: event.loaded,
2430
+ total: event.total
2431
+ }
2432
+ }));
2433
+ });
2434
+ req.addEventListener('loadend', function () {
2435
+ resolve(req.readyState === 4 && req.status === 200);
2436
+ });
2437
+ req.addEventListener('error', reject);
2438
+ req.open('GET', url, true);
2439
+ req.send();
2440
+ })];
2441
+ });
2442
+ });
2443
+ }
2444
+ var modelsPreloading = {
2445
+ documentDetector: false,
2446
+ focus: false,
2447
+ faceDetection: false,
2448
+ barcodeReadability: false
2449
+ };
2450
+ var preloadDocumentDetectorDependencies = function preloadDocumentDetectorDependencies() {
2451
+ return preloadModelDependencies('documentDetector');
2452
+ };
2453
+ var preloadFocusModelDependencies = function preloadFocusModelDependencies() {
2454
+ return preloadModelDependencies('focus');
2455
+ };
2456
+ var preloadFaceDetectorDependencies = function preloadFaceDetectorDependencies() {
2457
+ return preloadModelDependencies('faceDetection');
2458
+ };
2459
+ var preloadBarcodeReadabilityModelDependencies = function preloadBarcodeReadabilityModelDependencies() {
2460
+ return preloadModelDependencies('barcodeReadability');
2461
+ };
2462
+ function preloadModelDependencies(model) {
2463
+ return __awaiter(this, void 0, void 0, function () {
2464
+ function handleModelDownloadProgress(event) {
2465
+ var detail = event.detail;
2466
+ if (!dependencies.includes(detail.url)) return;
2467
+ progressByUseCase[model] = sumUpProgressForDependencies(dependencies);
2468
+ document.dispatchEvent(new CustomEvent("idmission.preloadProgress.".concat(model), {
2469
+ detail: progressByUseCase[model]
2470
+ }));
2471
+ }
2472
+ var dependencies;
2473
+ return __generator(this, function (_a) {
2474
+ switch (_a.label) {
2475
+ case 0:
2476
+ if (modelsPreloading[model]) return [2 /*return*/, new Promise(function (resolve) {
2477
+ var i = setInterval(function () {
2478
+ if (!modelsPreloading[model]) {
2479
+ clearInterval(i);
2480
+ resolve();
2481
+ }
2482
+ }, 100);
2483
+ })];
2484
+ modelsPreloading[model] = true;
2485
+ return [4 /*yield*/, probeModelCapabilities()];
2486
+ case 1:
2487
+ _a.sent();
2488
+ if (modelCapabilities.delegate === 'NONE') {
2489
+ throw new Error("No available delegate for ".concat(model, " model."));
2490
+ }
2491
+ dependencies = [defaultModelPaths[model]];
2492
+ document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
2493
+ _a.label = 2;
2494
+ case 2:
2495
+ _a.trys.push([2,, 4, 5]);
2496
+ return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
2497
+ case 3:
2498
+ _a.sent();
2499
+ return [3 /*break*/, 5];
2500
+ case 4:
2501
+ document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
2502
+ modelsPreloading[model] = false;
2503
+ return [7 /*endfinally*/];
2504
+ case 5:
2505
+ return [2 /*return*/];
2506
+ }
2507
+ });
2508
+ });
2509
+ }
2510
+ function progressToPercentage(progress) {
2511
+ return progress.total > 0 ? Math.round(100.0 * progress.loaded / progress.total) : 0;
2512
+ }
2513
+ function sumUpProgressForDependencies(dependencies) {
2514
+ return dependencies.reduce(function (result, dependency) {
2515
+ var dependencyProgress = progressByUrl[dependency];
2516
+ if (!dependencyProgress) return result;
2517
+ result.loaded += dependencyProgress.loaded;
2518
+ result.total += dependencyProgress.total;
2519
+ return result;
2520
+ }, {
2521
+ loaded: 0,
2522
+ total: 0
2523
+ });
2524
+ }
2525
+
2394
2526
  function convertBoundingBox(box) {
2395
2527
  var _a, _b, _c, _d, _e, _f, _g, _h;
2396
2528
  return {
@@ -2445,785 +2577,6 @@ function average(arr) {
2445
2577
  return sum / len;
2446
2578
  }
2447
2579
 
2448
- var DEFAULT_CDN_URL = 'https://websdk-cdn-dev.idmission.com/assets';
2449
-
2450
- var defaultDocumentDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/DocumentDetector/DocumentDetector-20250815_115859.tflite");
2451
-
2452
- var defaultFocusModelPath = "".concat(DEFAULT_CDN_URL, "/models/Focus/Focus-20241008_102708.tflite");
2453
-
2454
- var defaultFaceDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/FaceDetector/FaceDetector-20250820_154546.tflite");
2455
-
2456
- var defaultFocusModelLoadTimeoutMs = 45000;
2457
- var defaultFocusThresholds = {
2458
- idCardFront: {
2459
- desktop: 0,
2460
- mobile: 0.3
2461
- },
2462
- idCardBack: {
2463
- desktop: 0,
2464
- mobile: 0.3
2465
- },
2466
- passport: {
2467
- desktop: 0,
2468
- mobile: 0.3
2469
- },
2470
- singlePage: {
2471
- desktop: 0,
2472
- mobile: 0.3
2473
- }
2474
- };
2475
- var classifier = null;
2476
- var classifierSettings = null;
2477
- function loadFocusModel() {
2478
- return __awaiter(this, arguments, void 0, function (modelAssetPath) {
2479
- var _a, _b;
2480
- if (modelAssetPath === void 0) {
2481
- modelAssetPath = defaultFocusModelPath;
2482
- }
2483
- return __generator(this, function (_c) {
2484
- switch (_c.label) {
2485
- case 0:
2486
- if (classifier && (classifierSettings === null || classifierSettings === void 0 ? void 0 : classifierSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier];
2487
- closeFocusModel();
2488
- return [4 /*yield*/, preloadFocusModelDependencies()];
2489
- case 1:
2490
- _c.sent();
2491
- if (modelCapabilities.delegate === 'NONE') {
2492
- throw new Error('No available delegate for focus detector.');
2493
- }
2494
- _b = (_a = ImageClassifier).createFromOptions;
2495
- return [4 /*yield*/, FilesetResolver.forVisionTasks(visionTasksBasePath)];
2496
- case 2:
2497
- return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
2498
- baseOptions: {
2499
- modelAssetPath: modelAssetPath,
2500
- delegate: modelCapabilities.delegate
2501
- },
2502
- // canvas: document.createElement('canvas'),
2503
- runningMode: 'VIDEO'
2504
- }])];
2505
- case 3:
2506
- classifier = _c.sent();
2507
- classifierSettings = {
2508
- modelAssetPath: modelAssetPath
2509
- };
2510
- return [2 /*return*/, classifier];
2511
- }
2512
- });
2513
- });
2514
- }
2515
- function closeFocusModel() {
2516
- classifier === null || classifier === void 0 ? void 0 : classifier.close();
2517
- classifier = null;
2518
- classifierSettings = null;
2519
- }
2520
- function useLoadFocusModel(_a) {
2521
- var _b = _a.modelPath,
2522
- modelPath = _b === void 0 ? defaultFocusModelPath : _b,
2523
- _c = _a.modelLoadTimeoutMs,
2524
- modelLoadTimeoutMs = _c === void 0 ? defaultFocusModelLoadTimeoutMs : _c,
2525
- onModelError = _a.onModelError,
2526
- videoRef = _a.videoRef,
2527
- _d = _a.shouldLoadModels,
2528
- shouldLoadModels = _d === void 0 ? true : _d;
2529
- var _e = useState('not-started'),
2530
- modelLoadState = _e[0],
2531
- setModelLoadState = _e[1];
2532
- var _f = useState(0),
2533
- modelDownloadProgress = _f[0],
2534
- setModelDownloadProgress = _f[1];
2535
- var _g = useState(null),
2536
- modelWarmingStartedAt = _g[0],
2537
- setModelWarmingStartedAt = _g[1];
2538
- var _h = useState(null),
2539
- modelError = _h[0],
2540
- setModelError = _h[1];
2541
- useEffect(function loadModel() {
2542
- var _this = this;
2543
- if (!shouldLoadModels) return;
2544
- setModelLoadState('downloading');
2545
- setModelWarmingStartedAt(null);
2546
- function handleDownloadProgress(event) {
2547
- setModelDownloadProgress(progressToPercentage(event.detail));
2548
- }
2549
- document.addEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
2550
- var modelLoadTimeout = setTimeout(function () {
2551
- setModelError(new Error('Model loading time limit exceeded.'));
2552
- }, modelLoadTimeoutMs);
2553
- var cancelVideoReady = function cancelVideoReady() {};
2554
- loadFocusModel(modelPath).then(function (loadedModel) {
2555
- return __awaiter(_this, void 0, void 0, function () {
2556
- var _a, videoReady, cancel, cancelled;
2557
- return __generator(this, function (_b) {
2558
- switch (_b.label) {
2559
- case 0:
2560
- setModelDownloadProgress(100);
2561
- clearTimeout(modelLoadTimeout);
2562
- setModelLoadState('warming');
2563
- setModelWarmingStartedAt(new Date().getTime());
2564
- _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
2565
- cancelled = false;
2566
- cancelVideoReady = function cancelVideoReady() {
2567
- cancelled = true;
2568
- cancel();
2569
- };
2570
- return [4 /*yield*/, videoReady];
2571
- case 1:
2572
- _b.sent();
2573
- setTimeout(function () {
2574
- if (cancelled) return;
2575
- loadedModel.classifyForVideo(videoRef.current, performance.now());
2576
- setModelLoadState('ready');
2577
- }, 500);
2578
- return [2 /*return*/];
2579
- }
2580
- });
2581
- });
2582
- })["catch"](function (e) {
2583
- setModelError(e);
2584
- setModelLoadState('error');
2585
- })["finally"](function () {
2586
- clearTimeout(modelLoadTimeout);
2587
- });
2588
- return function () {
2589
- log('unloading focus model');
2590
- cancelVideoReady();
2591
- closeFocusModel();
2592
- clearTimeout(modelLoadTimeout);
2593
- document.removeEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
2594
- };
2595
- }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
2596
- useEffect(function handleModelError() {
2597
- if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
2598
- }, [modelError, onModelError]);
2599
- return useMemo(function () {
2600
- return {
2601
- ready: modelLoadState === 'ready',
2602
- modelLoadState: modelLoadState,
2603
- modelDownloadProgress: modelDownloadProgress,
2604
- modelWarmingStartedAt: modelWarmingStartedAt,
2605
- modelError: modelError
2606
- };
2607
- }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
2608
- }
2609
- var lastFocusPredictionAt = 0;
2610
- var lastFocusPredictionTime = 0;
2611
- function setLastFocusPredictionAt(time) {
2612
- lastFocusPredictionTime = time - lastFocusPredictionAt;
2613
- lastFocusPredictionAt = time;
2614
- }
2615
- function makeFocusModelPrediction(imageData, cropCanvas, rotateCanvas, box) {
2616
- var _a, _b, _c, _d, _e;
2617
- if (!classifier) return null;
2618
- var startedAt = new Date();
2619
- var image = cropIfNecessary(imageData, cropCanvas, rotateCanvas, box);
2620
- var result = classifier.classifyForVideo(image, performance.now());
2621
- 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) {
2622
- return c.categoryName === 'focused';
2623
- })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
2624
- var predictionTime = new Date().getTime() - startedAt.getTime();
2625
- return {
2626
- score: score,
2627
- predictionTime: predictionTime
2628
- };
2629
- }
2630
- function cropIfNecessary(imageData, cropCanvas, rotateCanvas, box) {
2631
- if (!box) return imageData;
2632
- var cropped = cropToDetectedObjectBox(imageData, box, cropCanvas);
2633
- var _a = [box.width, box.height],
2634
- bw = _a[0],
2635
- bh = _a[1];
2636
- if (bh <= bw) return cropped;
2637
- var ctx = rotateCanvas.getContext('2d');
2638
- if (!ctx) return cropped;
2639
- rotateCanvas.width = bh;
2640
- rotateCanvas.height = bw;
2641
- ctx.clearRect(0, 0, rotateCanvas.width, rotateCanvas.height);
2642
- ctx.translate(rotateCanvas.width / 2, rotateCanvas.height / 2);
2643
- ctx.rotate(1.5708); // 90 deg in radians
2644
- ctx.drawImage(cropped, -bw / 2, -bh / 2);
2645
- return rotateCanvas;
2646
- }
2647
-
2648
- var defaultSelfieCaptureModelLoadTimeoutMs = 45000;
2649
- var detector$1 = null;
2650
- var detectorSettings$1 = null;
2651
- function loadFaceDetector() {
2652
- return __awaiter(this, arguments, void 0, function (modelAssetPath) {
2653
- var _a, _b;
2654
- if (modelAssetPath === void 0) {
2655
- modelAssetPath = defaultFaceDetectorModelPath;
2656
- }
2657
- return __generator(this, function (_c) {
2658
- switch (_c.label) {
2659
- case 0:
2660
- if (detector$1 && (detectorSettings$1 === null || detectorSettings$1 === void 0 ? void 0 : detectorSettings$1.modelAssetPath) === modelAssetPath) return [2 /*return*/, detector$1];
2661
- closeFaceDetector();
2662
- return [4 /*yield*/, preloadFaceDetectorDependencies()];
2663
- case 1:
2664
- _c.sent();
2665
- if (modelCapabilities.delegate === 'NONE') {
2666
- throw new Error('No available delegate for face detector.');
2667
- }
2668
- _b = (_a = FaceDetector).createFromOptions;
2669
- return [4 /*yield*/, FilesetResolver.forVisionTasks(visionTasksBasePath)];
2670
- case 2:
2671
- return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
2672
- // canvas: document.createElement('canvas'),
2673
- baseOptions: {
2674
- modelAssetPath: modelAssetPath,
2675
- delegate: modelCapabilities.delegate
2676
- },
2677
- runningMode: 'VIDEO'
2678
- }])];
2679
- case 3:
2680
- detector$1 = _c.sent();
2681
- detectorSettings$1 = {
2682
- modelAssetPath: modelAssetPath
2683
- };
2684
- return [2 /*return*/, detector$1];
2685
- }
2686
- });
2687
- });
2688
- }
2689
- function closeFaceDetector() {
2690
- detector$1 === null || detector$1 === void 0 ? void 0 : detector$1.close();
2691
- detector$1 = null;
2692
- detectorSettings$1 = null;
2693
- }
2694
- function useLoadFaceDetector(_a) {
2695
- var onModelError = _a.onModelError,
2696
- _b = _a.modelLoadTimeoutMs,
2697
- modelLoadTimeoutMs = _b === void 0 ? defaultSelfieCaptureModelLoadTimeoutMs : _b,
2698
- videoRef = _a.videoRef;
2699
- var _c = useState('not-started'),
2700
- modelLoadState = _c[0],
2701
- setModelLoadState = _c[1];
2702
- var _d = useState(0),
2703
- modelDownloadProgress = _d[0],
2704
- setModelDownloadProgress = _d[1];
2705
- var _e = useState(null),
2706
- modelWarmingStartedAt = _e[0],
2707
- setModelWarmingStartedAt = _e[1];
2708
- var _f = useState(null),
2709
- modelError = _f[0],
2710
- setModelError = _f[1];
2711
- useEffect(function loadModel() {
2712
- var _this = this;
2713
- setModelLoadState('downloading');
2714
- setModelWarmingStartedAt(null);
2715
- var modelLoadTimeout = setTimeout(function () {
2716
- setModelError(new Error('Model loading time limit exceeded.'));
2717
- }, modelLoadTimeoutMs);
2718
- function handleDownloadProgress(event) {
2719
- setModelDownloadProgress(progressToPercentage(event.detail));
2720
- }
2721
- document.addEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
2722
- var cancelVideoReady = function cancelVideoReady() {};
2723
- loadFaceDetector().then(function (model) {
2724
- return __awaiter(_this, void 0, void 0, function () {
2725
- var _a, videoReady, cancel, cancelled;
2726
- return __generator(this, function (_b) {
2727
- switch (_b.label) {
2728
- case 0:
2729
- setModelDownloadProgress(100);
2730
- clearTimeout(modelLoadTimeout);
2731
- setModelLoadState('warming');
2732
- setModelWarmingStartedAt(new Date().getTime());
2733
- return [4 /*yield*/, testFaceDetectionAgainstKnownImage(model)];
2734
- case 1:
2735
- _b.sent();
2736
- _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
2737
- cancelled = false;
2738
- cancelVideoReady = function cancelVideoReady() {
2739
- cancelled = true;
2740
- cancel();
2741
- };
2742
- return [4 /*yield*/, videoReady];
2743
- case 2:
2744
- _b.sent();
2745
- if (cancelled) return [2 /*return*/];
2746
- model.detectForVideo(videoRef.current, performance.now());
2747
- setModelLoadState('ready');
2748
- return [2 /*return*/];
2749
- }
2750
- });
2751
- });
2752
- })["catch"](function (e) {
2753
- setModelError(e);
2754
- setModelLoadState('error');
2755
- })["finally"](function () {
2756
- clearTimeout(modelLoadTimeout);
2757
- });
2758
- return function () {
2759
- log('unloading face detection model');
2760
- cancelVideoReady();
2761
- closeFaceDetector();
2762
- clearTimeout(modelLoadTimeout);
2763
- document.removeEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
2764
- };
2765
- }, [modelLoadTimeoutMs, videoRef]);
2766
- useEffect(function handleModelError() {
2767
- if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
2768
- }, [modelError, onModelError]);
2769
- return useMemo(function () {
2770
- return {
2771
- ready: modelLoadState === 'ready',
2772
- modelLoadState: modelLoadState,
2773
- modelDownloadProgress: modelDownloadProgress,
2774
- modelWarmingStartedAt: modelWarmingStartedAt,
2775
- modelError: modelError
2776
- };
2777
- }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
2778
- }
2779
- var lastFaceDetectionAt = 0;
2780
- var lastFaceDetectionTime = 0;
2781
- function setLastFaceDetectionAt(time) {
2782
- lastFaceDetectionTime = time - lastFaceDetectionAt;
2783
- lastFaceDetectionAt = time;
2784
- }
2785
- var framesNeededSamples$1 = [];
2786
- function trackFramesNeeded$1(value, bufferLength) {
2787
- if (bufferLength === void 0) {
2788
- bufferLength = 25;
2789
- }
2790
- framesNeededSamples$1.unshift(value);
2791
- if (framesNeededSamples$1.length > bufferLength) framesNeededSamples$1.length = bufferLength;
2792
- }
2793
- var lastNFaces = [];
2794
- var lastNFacePairs = [];
2795
- var lastNNoses = [];
2796
- var lastNNosePairs = [];
2797
- function trackFace(face, framesNeeded, frameWidth, frameHeight) {
2798
- if (framesNeeded === void 0) {
2799
- framesNeeded = 12;
2800
- }
2801
- var nose = face.keypoints[2];
2802
- if (!nose) return;
2803
- lastNFaces.unshift(face);
2804
- lastNNoses.unshift(nose);
2805
- if (lastNFaces.length > framesNeeded) lastNFaces.length = framesNeeded;
2806
- if (lastNNoses.length > framesNeeded) lastNNoses.length = framesNeeded;
2807
- if (lastNFaces.length > 1) {
2808
- var lastFace = lastNFaces[1];
2809
- var iou = calculateIoU(face.box, lastFace.box);
2810
- lastNFacePairs.unshift({
2811
- a: face,
2812
- b: lastFace,
2813
- iou: iou
2814
- });
2815
- if (lastNFacePairs.length > framesNeeded - 1) lastNFacePairs.length = framesNeeded - 1;
2816
- }
2817
- if (lastNNoses.length > 1) {
2818
- var lastNose = lastNNoses[1];
2819
- var noseDistance = Math.sqrt(Math.pow((nose.x - lastNose.x) / frameWidth, 2) + Math.pow((nose.y - lastNose.y) / frameHeight, 2));
2820
- lastNNosePairs.unshift({
2821
- a: nose,
2822
- b: lastNose,
2823
- distance: noseDistance
2824
- });
2825
- if (lastNNosePairs.length > framesNeeded - 1) lastNNosePairs.length = framesNeeded - 1;
2826
- }
2827
- }
2828
- function makeFaceDetectorPrediction(imageData) {
2829
- if (!detector$1) return null;
2830
- var prediction = detector$1.detectForVideo(imageData, performance.now());
2831
- var faces = prediction.detections.map(function (d) {
2832
- return {
2833
- box: convertBoundingBox(d.boundingBox),
2834
- keypoints: d.keypoints.map(function (k) {
2835
- var _a;
2836
- return _assign(_assign({}, k), {
2837
- x: k.x * imageData.width,
2838
- y: k.y * imageData.height,
2839
- name: (_a = k.label) !== null && _a !== void 0 ? _a : ''
2840
- });
2841
- })
2842
- };
2843
- });
2844
- return _assign(_assign({}, prediction), {
2845
- faces: faces
2846
- });
2847
- }
2848
- function processFaceDetectorPrediction(_a) {
2849
- var faces = _a.faces,
2850
- videoWidth = _a.videoWidth,
2851
- videoHeight = _a.videoHeight,
2852
- _b = _a.requireVerticalFaceCentering,
2853
- requireVerticalFaceCentering = _b === void 0 ? true : _b,
2854
- _c = _a.stabilityThreshold,
2855
- stabilityThreshold = _c === void 0 ? 0.7 : _c,
2856
- _d = _a.noseDistanceThreshold,
2857
- noseDistanceThreshold = _d === void 0 ? 0.025 : _d,
2858
- _e = _a.xBoundary,
2859
- xBoundary = _e === void 0 ? 0.01 : _e,
2860
- // this represents the edge that the sides of the face box should not cross -- 1% of video width
2861
- _f = _a.yBoundary,
2862
- // this represents the edge that the sides of the face box should not cross -- 1% of video width
2863
- yBoundary = _f === void 0 ? 0.01 : _f,
2864
- // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
2865
- _g = _a.xCentroidBoundary,
2866
- // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
2867
- xCentroidBoundary = _g === void 0 ? 0.125 : _g,
2868
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
2869
- _h = _a.yCentroidBoundary,
2870
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
2871
- yCentroidBoundary = _h === void 0 ? 0.125 : _h,
2872
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
2873
- _j = _a.foreheadRatio,
2874
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
2875
- foreheadRatio = _j === void 0 ? 0.275 : _j,
2876
- // 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.
2877
- _k = _a.noseTrackingThreshold,
2878
- // 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.
2879
- noseTrackingThreshold = _k === void 0 ? 0.2 : _k,
2880
- // 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
2881
- minCaptureBrightnessThreshold = _a.minCaptureBrightnessThreshold,
2882
- minCaptureRangeThreshold = _a.minCaptureRangeThreshold,
2883
- minCaptureVarianceThreshold = _a.minCaptureVarianceThreshold,
2884
- brightness = _a.brightness,
2885
- range = _a.range,
2886
- variance = _a.variance;
2887
- var face = faces[0];
2888
- var faceNotDetected = faces.length === 0;
2889
- var faceNotCentered = false,
2890
- faceLookingAway = false,
2891
- faceTooClose = false,
2892
- faceTooFar = false,
2893
- faceVisibilityTooLow = false;
2894
- var hasAnyThreshold = minCaptureBrightnessThreshold !== undefined || minCaptureRangeThreshold !== undefined || minCaptureVarianceThreshold !== undefined;
2895
- if (hasAnyThreshold) {
2896
- var tooDark = minCaptureBrightnessThreshold !== undefined && brightness !== undefined && brightness < minCaptureBrightnessThreshold;
2897
- var tooLowRange = minCaptureRangeThreshold !== undefined && range !== undefined && range < minCaptureRangeThreshold;
2898
- var tooLowVariance = minCaptureVarianceThreshold !== undefined && variance !== undefined && variance < minCaptureVarianceThreshold;
2899
- faceVisibilityTooLow = !!(tooDark || tooLowRange || tooLowVariance);
2900
- }
2901
- if (face && !faceVisibilityTooLow) {
2902
- // calculate frame centroids
2903
- var frameCX = videoWidth / 2;
2904
- var frameCY = videoHeight / 2;
2905
- // calculate head bounding box, with forehead extension
2906
- var foreheadSize = face.box.height * foreheadRatio;
2907
- var headXMin = face.box.xMin;
2908
- var headXMax = face.box.xMax;
2909
- var headYMin = face.box.yMin - foreheadSize;
2910
- var headYMax = face.box.yMax;
2911
- // calculate head centroids
2912
- var headCX = (headXMin + headXMax) / 2;
2913
- var headCY = (headYMin + headYMax) / 2;
2914
- // calculate thresholds
2915
- var vTX = videoWidth * xBoundary;
2916
- var vTY = videoHeight * yBoundary;
2917
- var vCTX = videoWidth * xCentroidBoundary;
2918
- var vCTY = videoHeight * yCentroidBoundary;
2919
- var faceNotCenteredHorizontally = Math.abs(frameCX - headCX) > vCTX;
2920
- var faceNotCenteredVertically = Math.abs(frameCY - headCY) > vCTY;
2921
- var faceViolatesHorizontalBoundary = headXMin < vTX || headXMax > videoWidth - vTX;
2922
- var faceViolatesVerticalBoundary = headYMin < vTY || headYMax > videoHeight - vTY;
2923
- faceNotCentered = faceViolatesHorizontalBoundary || faceViolatesVerticalBoundary || faceNotCenteredHorizontally || requireVerticalFaceCentering && faceNotCenteredVertically;
2924
- var isMobile = videoWidth < videoHeight;
2925
- var tooCloseMultiple = 1.5;
2926
- var tooFarMultiple = isMobile ? 6 : 7;
2927
- faceTooClose = face.box.width > videoWidth / tooCloseMultiple;
2928
- faceTooFar = face.box.width < videoWidth / tooFarMultiple;
2929
- var nose = face.keypoints[2];
2930
- var fTW = face.box.width * noseTrackingThreshold;
2931
- var fTH = face.box.height * noseTrackingThreshold;
2932
- faceLookingAway = !nose || Math.abs(headCX - nose.x) > fTW || Math.abs(headCY - nose.y) > fTH;
2933
- }
2934
- var faceInGuides = !faceNotDetected && !faceNotCentered && !faceLookingAway && !faceTooClose && !faceTooFar;
2935
- if (lastFaceDetectionTime > 0) {
2936
- trackFramesNeeded$1(500 / lastFaceDetectionTime);
2937
- }
2938
- var faceIsStable = false,
2939
- noseIsStable = false;
2940
- if (faceInGuides && !faceVisibilityTooLow) {
2941
- var framesNeeded = Math.max(Math.ceil(average(framesNeededSamples$1)), 5);
2942
- trackFace(face, framesNeeded, videoWidth, videoHeight);
2943
- faceIsStable = lastNFaces.length >= framesNeeded && !lastNFacePairs.some(function (pair) {
2944
- return pair.iou < stabilityThreshold;
2945
- });
2946
- noseIsStable = lastNNoses.length >= framesNeeded && !lastNNosePairs.some(function (pair) {
2947
- return pair.distance > noseDistanceThreshold;
2948
- });
2949
- }
2950
- var faceReady = faceInGuides && faceIsStable && noseIsStable && !faceVisibilityTooLow;
2951
- return {
2952
- face: face,
2953
- faceNotDetected: faceNotDetected,
2954
- faceNotCentered: faceNotCentered,
2955
- faceLookingAway: faceLookingAway,
2956
- faceTooClose: faceTooClose,
2957
- faceTooFar: faceTooFar,
2958
- faceReady: faceReady,
2959
- faceReadyAt: faceReady ? new Date() : null,
2960
- faceIsStable: faceIsStable,
2961
- noseIsStable: noseIsStable,
2962
- faceVisibilityTooLow: faceVisibilityTooLow
2963
- };
2964
- }
2965
- function testFaceDetectionAgainstKnownImage(detector) {
2966
- return new Promise(function (resolve, reject) {
2967
- var img = new Image();
2968
- img.crossOrigin = 'anonymous';
2969
- img.onload = function () {
2970
- var prediction = detector.detectForVideo(img, performance.now());
2971
- if (prediction.detections.length > 0) {
2972
- debug('face detection test result', prediction.detections);
2973
- resolve(void 0);
2974
- } else {
2975
- warn('face detection test failed');
2976
- reject(new Error('testFaceDetectionAgainstKnownImage failed to predict'));
2977
- }
2978
- };
2979
- img.onerror = function () {
2980
- return reject(new Error('testFaceDetectionAgainstKnownImage failed to load image'));
2981
- };
2982
- img.src = "".concat(DEFAULT_CDN_URL, "/head-test.jpg");
2983
- });
2984
- }
2985
-
2986
- var preloadModels = function preloadModels(_a) {
2987
- return __awaiter(void 0, [_a], void 0, function (_b) {
2988
- var preloadTasks;
2989
- var _c = _b.documentDetectionModel,
2990
- documentDetectionModel = _c === void 0 ? true : _c,
2991
- _d = _b.focusModel,
2992
- focusModel = _d === void 0 ? true : _d,
2993
- _e = _b.faceDetectionModel,
2994
- faceDetectionModel = _e === void 0 ? true : _e;
2995
- return __generator(this, function (_f) {
2996
- switch (_f.label) {
2997
- case 0:
2998
- return [4 /*yield*/, probeModelCapabilities()];
2999
- case 1:
3000
- _f.sent();
3001
- preloadTasks = [];
3002
- if (documentDetectionModel) {
3003
- preloadTasks.push(preloadDocumentDetectorDependencies);
3004
- }
3005
- if (focusModel) {
3006
- preloadTasks.push(preloadFocusModelDependencies);
3007
- }
3008
- if (faceDetectionModel) {
3009
- preloadTasks.push(preloadFaceDetectorDependencies);
3010
- }
3011
- return [4 /*yield*/, Promise.all(preloadTasks)];
3012
- case 2:
3013
- _f.sent();
3014
- return [2 /*return*/];
3015
- }
3016
- });
3017
- });
3018
- };
3019
- var progressByUrl = {};
3020
- var progressByUseCase = {
3021
- visionRuntime: {
3022
- loaded: 0,
3023
- total: 0
3024
- },
3025
- documentDetection: {
3026
- loaded: 0,
3027
- total: 0
3028
- },
3029
- focus: {
3030
- loaded: 0,
3031
- total: 0
3032
- },
3033
- faceDetection: {
3034
- loaded: 0,
3035
- total: 0
3036
- }
3037
- };
3038
- function preloadDependency(url) {
3039
- return __awaiter(this, void 0, void 0, function () {
3040
- return __generator(this, function (_a) {
3041
- return [2 /*return*/, new Promise(function (resolve, reject) {
3042
- var req = new XMLHttpRequest();
3043
- req.addEventListener('progress', function (event) {
3044
- if (!event.lengthComputable) return;
3045
- progressByUrl[url] = event;
3046
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress', {
3047
- detail: {
3048
- url: url,
3049
- loaded: event.loaded,
3050
- total: event.total
3051
- }
3052
- }));
3053
- });
3054
- req.addEventListener('loadend', function () {
3055
- resolve(req.readyState === 4 && req.status === 200);
3056
- });
3057
- req.addEventListener('error', reject);
3058
- req.open('GET', url, true);
3059
- req.send();
3060
- })];
3061
- });
3062
- });
3063
- }
3064
- var documentDetectorPreloading = false,
3065
- focusModelPreloading = false,
3066
- faceDetectorPreloading = false;
3067
- function preloadDocumentDetectorDependencies() {
3068
- return __awaiter(this, void 0, void 0, function () {
3069
- function handleDownloadProgress(event) {
3070
- var detail = event.detail;
3071
- if (!dependencies.includes(detail.url)) return;
3072
- progressByUseCase.documentDetection = sumUpProgressForDependencies(dependencies);
3073
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.documentDetection', {
3074
- detail: progressByUseCase.documentDetection
3075
- }));
3076
- }
3077
- var dependencies;
3078
- return __generator(this, function (_a) {
3079
- switch (_a.label) {
3080
- case 0:
3081
- if (documentDetectorPreloading) return [2 /*return*/, new Promise(function (resolve) {
3082
- var i = setInterval(function () {
3083
- if (!documentDetectorPreloading) {
3084
- clearInterval(i);
3085
- resolve();
3086
- }
3087
- }, 100);
3088
- })];
3089
- documentDetectorPreloading = true;
3090
- return [4 /*yield*/, probeModelCapabilities()];
3091
- case 1:
3092
- _a.sent();
3093
- if (modelCapabilities.delegate === 'NONE') {
3094
- throw new Error('No available delegate for document detector.');
3095
- }
3096
- dependencies = [defaultDocumentDetectorModelPath];
3097
- document.addEventListener('idmission.preloadProgress', handleDownloadProgress);
3098
- _a.label = 2;
3099
- case 2:
3100
- _a.trys.push([2,, 4, 5]);
3101
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
3102
- case 3:
3103
- _a.sent();
3104
- return [3 /*break*/, 5];
3105
- case 4:
3106
- document.removeEventListener('idmission.preloadProgress', handleDownloadProgress);
3107
- documentDetectorPreloading = false;
3108
- return [7 /*endfinally*/];
3109
- case 5:
3110
- return [2 /*return*/];
3111
- }
3112
- });
3113
- });
3114
- }
3115
- function preloadFocusModelDependencies() {
3116
- return __awaiter(this, void 0, void 0, function () {
3117
- function handleModelDownloadProgress(event) {
3118
- var detail = event.detail;
3119
- if (!dependencies.includes(detail.url)) return;
3120
- progressByUseCase.focus = sumUpProgressForDependencies(dependencies);
3121
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.focus', {
3122
- detail: progressByUseCase.focus
3123
- }));
3124
- }
3125
- var dependencies;
3126
- return __generator(this, function (_a) {
3127
- switch (_a.label) {
3128
- case 0:
3129
- if (focusModelPreloading) return [2 /*return*/, new Promise(function (resolve) {
3130
- var i = setInterval(function () {
3131
- if (!focusModelPreloading) {
3132
- clearInterval(i);
3133
- resolve();
3134
- }
3135
- }, 100);
3136
- })];
3137
- focusModelPreloading = true;
3138
- return [4 /*yield*/, probeModelCapabilities()];
3139
- case 1:
3140
- _a.sent();
3141
- if (modelCapabilities.delegate === 'NONE') {
3142
- throw new Error('No available delegate for document detector.');
3143
- }
3144
- dependencies = [defaultFocusModelPath];
3145
- document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3146
- _a.label = 2;
3147
- case 2:
3148
- _a.trys.push([2,, 4, 5]);
3149
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
3150
- case 3:
3151
- _a.sent();
3152
- return [3 /*break*/, 5];
3153
- case 4:
3154
- document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3155
- focusModelPreloading = false;
3156
- return [7 /*endfinally*/];
3157
- case 5:
3158
- return [2 /*return*/];
3159
- }
3160
- });
3161
- });
3162
- }
3163
- function preloadFaceDetectorDependencies() {
3164
- return __awaiter(this, void 0, void 0, function () {
3165
- function handleModelDownloadProgress(event) {
3166
- var detail = event.detail;
3167
- if (!dependencies.includes(detail.url)) return;
3168
- progressByUseCase.faceDetection = sumUpProgressForDependencies(dependencies);
3169
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.faceDetection', {
3170
- detail: progressByUseCase.faceDetection
3171
- }));
3172
- }
3173
- var dependencies;
3174
- return __generator(this, function (_a) {
3175
- switch (_a.label) {
3176
- case 0:
3177
- if (faceDetectorPreloading) return [2 /*return*/, new Promise(function (resolve) {
3178
- var i = setInterval(function () {
3179
- if (!faceDetectorPreloading) {
3180
- clearInterval(i);
3181
- resolve();
3182
- }
3183
- }, 100);
3184
- })];
3185
- faceDetectorPreloading = true;
3186
- return [4 /*yield*/, probeModelCapabilities()];
3187
- case 1:
3188
- _a.sent();
3189
- if (modelCapabilities.delegate === 'NONE') {
3190
- throw new Error('No available delegate for document detector.');
3191
- }
3192
- dependencies = [defaultFaceDetectorModelPath];
3193
- document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3194
- _a.label = 2;
3195
- case 2:
3196
- _a.trys.push([2,, 4, 5]);
3197
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
3198
- case 3:
3199
- _a.sent();
3200
- return [3 /*break*/, 5];
3201
- case 4:
3202
- document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
3203
- faceDetectorPreloading = false;
3204
- return [7 /*endfinally*/];
3205
- case 5:
3206
- return [2 /*return*/];
3207
- }
3208
- });
3209
- });
3210
- }
3211
- function progressToPercentage(progress) {
3212
- return progress.total > 0 ? Math.round(100.0 * progress.loaded / progress.total) : 0;
3213
- }
3214
- function sumUpProgressForDependencies(dependencies) {
3215
- return dependencies.reduce(function (result, dependency) {
3216
- var dependencyProgress = progressByUrl[dependency];
3217
- if (!dependencyProgress) return result;
3218
- result.loaded += dependencyProgress.loaded;
3219
- result.total += dependencyProgress.total;
3220
- return result;
3221
- }, {
3222
- loaded: 0,
3223
- total: 0
3224
- });
3225
- }
3226
-
3227
2580
  var defaultDocumentDetectionScoreThreshold = 0.1;
3228
2581
  var defaultDocumentDetectionModelLoadTimeoutMs = 45000;
3229
2582
  var defaultDocumentDetectionThresholds = {
@@ -3245,8 +2598,8 @@ var documentTypeDisplayNames = {
3245
2598
  singlePage: 'Single page',
3246
2599
  none: 'None'
3247
2600
  };
3248
- var detector = null;
3249
- var detectorSettings = null;
2601
+ var detector$1 = null;
2602
+ var detectorSettings$1 = null;
3250
2603
  function loadDocumentDetector() {
3251
2604
  return __awaiter(this, arguments, void 0, function (modelAssetPath, scoreThreshold) {
3252
2605
  var _a, _b;
@@ -3259,7 +2612,7 @@ function loadDocumentDetector() {
3259
2612
  return __generator(this, function (_c) {
3260
2613
  switch (_c.label) {
3261
2614
  case 0:
3262
- 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];
2615
+ 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];
3263
2616
  closeDocumentDetector();
3264
2617
  return [4 /*yield*/, preloadDocumentDetectorDependencies()];
3265
2618
  case 1:
@@ -3280,20 +2633,20 @@ function loadDocumentDetector() {
3280
2633
  runningMode: 'VIDEO'
3281
2634
  }])];
3282
2635
  case 3:
3283
- detector = _c.sent();
3284
- detectorSettings = {
2636
+ detector$1 = _c.sent();
2637
+ detectorSettings$1 = {
3285
2638
  modelAssetPath: modelAssetPath,
3286
2639
  scoreThreshold: scoreThreshold
3287
2640
  };
3288
- return [2 /*return*/, detector];
2641
+ return [2 /*return*/, detector$1];
3289
2642
  }
3290
2643
  });
3291
2644
  });
3292
2645
  }
3293
2646
  function closeDocumentDetector() {
3294
- detector === null || detector === void 0 ? void 0 : detector.close();
3295
- detector = null;
3296
- detectorSettings = null;
2647
+ detector$1 === null || detector$1 === void 0 ? void 0 : detector$1.close();
2648
+ detector$1 = null;
2649
+ detectorSettings$1 = null;
3297
2650
  }
3298
2651
  function useLoadDocumentDetector(_a) {
3299
2652
  var _b = _a.shouldLoadModels,
@@ -3326,7 +2679,7 @@ function useLoadDocumentDetector(_a) {
3326
2679
  function handleDownloadProgress(event) {
3327
2680
  setModelDownloadProgress(progressToPercentage(event.detail));
3328
2681
  }
3329
- document.addEventListener('idmission.preloadProgress.documentDetection', handleDownloadProgress);
2682
+ document.addEventListener('idmission.preloadProgress.documentDetector', handleDownloadProgress);
3330
2683
  var modelLoadTimeout = setTimeout(function () {
3331
2684
  setModelError(new Error('Model loading time limit exceeded.'));
3332
2685
  }, modelLoadTimeoutMs);
@@ -3339,7 +2692,7 @@ function useLoadDocumentDetector(_a) {
3339
2692
  case 0:
3340
2693
  setModelDownloadProgress(100);
3341
2694
  setModelLoadState('warming');
3342
- setModelWarmingStartedAt(new Date().getTime());
2695
+ setModelWarmingStartedAt(performance.now());
3343
2696
  clearTimeout(modelLoadTimeout);
3344
2697
  return [4 /*yield*/, testDocumentDetectionAgainstKnownImage(model)];
3345
2698
  case 1:
@@ -3373,7 +2726,7 @@ function useLoadDocumentDetector(_a) {
3373
2726
  cancelVideoReady();
3374
2727
  closeDocumentDetector();
3375
2728
  clearTimeout(modelLoadTimeout);
3376
- document.removeEventListener('idmission.preloadProgress.documentDetection', handleDownloadProgress);
2729
+ document.removeEventListener('idmission.preloadProgress.documentDetector', handleDownloadProgress);
3377
2730
  };
3378
2731
  }, [shouldLoadModels, modelLoadTimeoutMs, modelPath, scoreThreshold, videoRef]);
3379
2732
  useEffect(function handleModelError() {
@@ -3394,13 +2747,13 @@ function makeDocumentDetectorPrediction(frame) {
3394
2747
  return __awaiter(this, void 0, void 0, function () {
3395
2748
  var startedAt, prediction, time, frameWidth, frameHeight;
3396
2749
  return __generator(this, function (_a) {
3397
- if (!detector) return [2 /*return*/, null];
3398
- startedAt = new Date();
2750
+ if (!detector$1) return [2 /*return*/, null];
2751
+ startedAt = performance.now();
3399
2752
  // Detectors can throw errors, for example when using custom URLs that
3400
2753
  // contain a model that doesn't provide the expected output.
3401
2754
  try {
3402
- prediction = detector.detectForVideo(frame, performance.now());
3403
- time = new Date().getTime() - startedAt.getTime();
2755
+ prediction = detector$1.detectForVideo(frame, performance.now());
2756
+ time = performance.now() - startedAt;
3404
2757
  frameWidth = frame.width;
3405
2758
  frameHeight = frame.height;
3406
2759
  return [2 /*return*/, _assign(_assign({}, prediction), {
@@ -3421,13 +2774,13 @@ function setLastDetectionAt(time) {
3421
2774
  lastDetectionTime = time - lastDetectionAt;
3422
2775
  lastDetectionAt = time;
3423
2776
  }
3424
- var framesNeededSamples = [];
3425
- function trackFramesNeeded(value, bufferLength) {
2777
+ var framesNeededSamples$1 = [];
2778
+ function trackFramesNeeded$1(value, bufferLength) {
3426
2779
  if (bufferLength === void 0) {
3427
2780
  bufferLength = 25;
3428
2781
  }
3429
- framesNeededSamples.unshift(value);
3430
- if (framesNeededSamples.length > bufferLength) framesNeededSamples.length = bufferLength;
2782
+ framesNeededSamples$1.unshift(value);
2783
+ if (framesNeededSamples$1.length > bufferLength) framesNeededSamples$1.length = bufferLength;
3431
2784
  }
3432
2785
  var lastNBoxes = [];
3433
2786
  var lastNPairs = [];
@@ -3533,7 +2886,7 @@ function processDocumentDetectorPrediction(prediction, thresholds, boundaries) {
3533
2886
  }
3534
2887
  var documentInBounds = !!bestDocument;
3535
2888
  if (lastDetectionTime > 0) {
3536
- trackFramesNeeded(1000 / lastDetectionTime);
2889
+ trackFramesNeeded$1(1000 / lastDetectionTime);
3537
2890
  }
3538
2891
  var documentIsStable = false;
3539
2892
  var documentTooClose = false;
@@ -3545,13 +2898,19 @@ function processDocumentDetectorPrediction(prediction, thresholds, boundaries) {
3545
2898
  if (detectionThresholdMet && documentInBounds && !documentTooClose) {
3546
2899
  var thresholdSet = (_p = thresholds.stability) !== null && _p !== void 0 ? _p : defaultDocumentDetectionThresholds.stability;
3547
2900
  var threshold_1 = thresholdSet[detectedDocumentType];
3548
- var framesNeeded = Math.ceil(average(framesNeededSamples));
2901
+ var framesNeeded = Math.ceil(average(framesNeededSamples$1));
3549
2902
  trackBox(bestDocument.box, framesNeeded);
3550
2903
  documentIsStable = lastNBoxes.length >= framesNeeded && !lastNPairs.some(function (pair) {
3551
2904
  return pair.iou < threshold_1;
3552
2905
  });
3553
2906
  }
3554
2907
  }
2908
+ var bestPDF417;
2909
+ if (detectedObjects.length > 0) {
2910
+ bestPDF417 = detectedObjects.find(function (obj) {
2911
+ return obj.label === 'PDF417';
2912
+ });
2913
+ }
3555
2914
  return {
3556
2915
  prediction: prediction,
3557
2916
  detectedObjects: detectedObjects,
@@ -3568,6 +2927,7 @@ function processDocumentDetectorPrediction(prediction, thresholds, boundaries) {
3568
2927
  singlePageDetectionScore: singlePageDetectionScore,
3569
2928
  singlePageDetectionThresholdMet: singlePageDetectionThresholdMet,
3570
2929
  bestDocument: bestDocument,
2930
+ bestPDF417: bestPDF417,
3571
2931
  documentInBounds: documentInBounds,
3572
2932
  documentTooClose: documentTooClose,
3573
2933
  documentIsStable: documentIsStable,
@@ -3611,6 +2971,43 @@ function testDocumentDetectionAgainstKnownImage(detector) {
3611
2971
  });
3612
2972
  }
3613
2973
 
2974
+ function getFrameDimensions(frame) {
2975
+ var frameWidth = frame.width,
2976
+ frameHeight = frame.height;
2977
+ if (frame instanceof HTMLImageElement) {
2978
+ frameWidth = frame.naturalWidth;
2979
+ frameHeight = frame.naturalHeight;
2980
+ }
2981
+ if (frame instanceof HTMLVideoElement) {
2982
+ frameWidth = frame.videoWidth;
2983
+ frameHeight = frame.videoHeight;
2984
+ }
2985
+ return [frameWidth, frameHeight];
2986
+ }
2987
+
2988
+ var InvisibleCanvasContainer = styled.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"])));
2989
+ var InvisibleCanvas = styled.canvas(templateObject_2$G || (templateObject_2$G = __makeTemplateObject(["\n display: none;\n"], ["\n display: none;\n"])));
2990
+ function drawToCanvas(canvas, frame, width, height) {
2991
+ if (!canvas) return;
2992
+ var ctx = canvas.getContext('2d');
2993
+ if (!ctx) return;
2994
+ if (!width || !height) {
2995
+ var _a = getFrameDimensions(frame),
2996
+ frameWidth = _a[0],
2997
+ frameHeight = _a[1];
2998
+ width || (width = frameWidth);
2999
+ height || (height = frameHeight);
3000
+ }
3001
+ canvas.width = width;
3002
+ canvas.height = height;
3003
+ ctx.drawImage(frame, 0, 0, width, height);
3004
+ }
3005
+ function clearCanvas(canvas) {
3006
+ var _a;
3007
+ (_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);
3008
+ }
3009
+ var templateObject_1$M, templateObject_2$G;
3010
+
3614
3011
  function useFrameLoop(fn, options) {
3615
3012
  if (options === void 0) {
3616
3013
  options = {};
@@ -5574,13 +4971,278 @@ function DocumentDetectionModelProvider(_a) {
5574
4971
  documentDetectionLastPredictionCanvas: lastPredictionCanvas,
5575
4972
  clearDocumentDetectionLastPredictionCanvas: clearDocumentDetectionLastPredictionCanvas
5576
4973
  };
5577
- }, [start, stop, load, modelLoadState, modelWarmingStartedAt, modelError, modelDownloadProgress, onDocumentDetected, documentDetectionThresholds, documentDetectionBoundaries, clearDocumentDetectionLastPredictionCanvas]);
5578
- return /*#__PURE__*/React.createElement(DocumentDetectionModelContext.Provider, {
5579
- value: value
5580
- }, /*#__PURE__*/React.createElement(InvisibleCanvas, {
5581
- key: canvasKey,
5582
- ref: lastPredictionCanvas
5583
- }), children);
4974
+ }, [start, stop, load, modelLoadState, modelWarmingStartedAt, modelError, modelDownloadProgress, onDocumentDetected, documentDetectionThresholds, documentDetectionBoundaries, clearDocumentDetectionLastPredictionCanvas]);
4975
+ return /*#__PURE__*/React.createElement(DocumentDetectionModelContext.Provider, {
4976
+ value: value
4977
+ }, /*#__PURE__*/React.createElement(InvisibleCanvas, {
4978
+ key: canvasKey,
4979
+ ref: lastPredictionCanvas
4980
+ }), children);
4981
+ }
4982
+
4983
+ function cropToShoulders(rawCanvas, cropCanvas, resizeCanvas, frame, face, quality, maxHeight) {
4984
+ var _a;
4985
+ if (quality === void 0) {
4986
+ quality = 0.92;
4987
+ }
4988
+ if (!rawCanvas || !cropCanvas || !resizeCanvas) return '';
4989
+ var rawCtx = rawCanvas.getContext('2d');
4990
+ var cropCtx = cropCanvas.getContext('2d');
4991
+ var resizeCtx = resizeCanvas.getContext('2d');
4992
+ if (!rawCtx || !cropCtx || !resizeCtx) throw new Error('could not get 2d context');
4993
+ rawCanvas.width = frame.width;
4994
+ rawCanvas.height = frame.height;
4995
+ rawCtx.putImageData(frame, 0, 0);
4996
+ if (frame.height > frame.width) {
4997
+ cropCanvas.width = frame.width;
4998
+ cropCanvas.height = frame.height;
4999
+ cropCtx.drawImage(rawCanvas, 0, 0, cropCanvas.width, cropCanvas.height);
5000
+ } else {
5001
+ var _b = (_a = face === null || face === void 0 ? void 0 : face.box) !== null && _a !== void 0 ? _a : {
5002
+ xMin: 0,
5003
+ width: frame.width
5004
+ },
5005
+ xMin = _b.xMin,
5006
+ width = _b.width;
5007
+ var desiredWidth = frame.height * 0.6;
5008
+ var faceCenterX = xMin + width / 2;
5009
+ var xPos = Math.max(0, faceCenterX - desiredWidth / 2);
5010
+ cropCanvas.width = desiredWidth;
5011
+ cropCanvas.height = frame.height;
5012
+ cropCtx.drawImage(rawCanvas, xPos, 0, cropCanvas.width, cropCanvas.height, 0, 0, cropCanvas.width, cropCanvas.height);
5013
+ }
5014
+ resizeCanvas.height = maxHeight !== null && maxHeight !== void 0 ? maxHeight : cropCanvas.height;
5015
+ resizeCanvas.width = cropCanvas.width * (resizeCanvas.height / cropCanvas.height);
5016
+ resizeCtx === null || resizeCtx === void 0 ? void 0 : resizeCtx.drawImage(cropCanvas, 0, 0, resizeCanvas.width, resizeCanvas.height);
5017
+ var dataURL = resizeCanvas.toDataURL('image/jpeg', quality);
5018
+ log('cropToShoulders size', new TextEncoder().encode(dataURL).length);
5019
+ clearCanvas(rawCanvas);
5020
+ clearCanvas(cropCanvas);
5021
+ clearCanvas(resizeCanvas);
5022
+ return dataURL;
5023
+ }
5024
+ function cropToDetectedObjectBox(frame, box, canvas, padding) {
5025
+ if (padding === void 0) {
5026
+ padding = 0;
5027
+ }
5028
+ canvas || (canvas = document.createElement('canvas'));
5029
+ var ctx = canvas.getContext('2d');
5030
+ if (!ctx) throw new Error('could not get 2d context');
5031
+ var xMin = box.xMin,
5032
+ yMin = box.yMin,
5033
+ width = box.width,
5034
+ height = box.height;
5035
+ canvas.width = width + padding * 2;
5036
+ canvas.height = height + padding * 2;
5037
+ ctx.drawImage(frame, xMin - padding, yMin - padding, width + padding * 2, height + padding * 2, 0, 0, canvas.width, canvas.height);
5038
+ return canvas;
5039
+ }
5040
+ function cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box, padding) {
5041
+ if (padding === void 0) {
5042
+ padding = 0;
5043
+ }
5044
+ if (!box) return imageData;
5045
+ var cropped = cropToDetectedObjectBox(imageData, box, cropCanvas, padding);
5046
+ var _a = [box.width, box.height],
5047
+ bw = _a[0],
5048
+ bh = _a[1];
5049
+ if (bh <= bw) return cropped;
5050
+ var ctx = rotateCanvas.getContext('2d');
5051
+ if (!ctx) return cropped;
5052
+ rotateCanvas.width = bh;
5053
+ rotateCanvas.height = bw;
5054
+ ctx.clearRect(0, 0, rotateCanvas.width, rotateCanvas.height);
5055
+ ctx.translate(rotateCanvas.width / 2, rotateCanvas.height / 2);
5056
+ ctx.rotate(1.5708); // 90 deg in radians
5057
+ ctx.drawImage(cropped, -bw / 2, -bh / 2);
5058
+ return rotateCanvas;
5059
+ }
5060
+ function resizeIfNecessary(imageData, resizeCanvas, maxWidth) {
5061
+ var width = imageData.width,
5062
+ height = imageData.height;
5063
+ if (width <= maxWidth) return imageData;
5064
+ var resizeCtx = resizeCanvas.getContext('2d');
5065
+ if (!resizeCtx) return imageData;
5066
+ var scale = maxWidth / width;
5067
+ resizeCanvas.width = maxWidth;
5068
+ resizeCanvas.height = height * scale;
5069
+ resizeCtx.drawImage(imageData, 0, 0, resizeCanvas.width, resizeCanvas.height);
5070
+ return resizeCanvas;
5071
+ }
5072
+
5073
+ var defaultFocusModelLoadTimeoutMs = 45000;
5074
+ var defaultFocusThresholds = {
5075
+ idCardFront: {
5076
+ desktop: 0,
5077
+ mobile: 0.3
5078
+ },
5079
+ idCardBack: {
5080
+ desktop: 0,
5081
+ mobile: 0.3
5082
+ },
5083
+ passport: {
5084
+ desktop: 0,
5085
+ mobile: 0.3
5086
+ },
5087
+ singlePage: {
5088
+ desktop: 0,
5089
+ mobile: 0.3
5090
+ }
5091
+ };
5092
+ var classifier$1 = null;
5093
+ var classifierSettings$1 = null;
5094
+ function loadFocusModel() {
5095
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
5096
+ var _a, _b;
5097
+ if (modelAssetPath === void 0) {
5098
+ modelAssetPath = defaultFocusModelPath;
5099
+ }
5100
+ return __generator(this, function (_c) {
5101
+ switch (_c.label) {
5102
+ case 0:
5103
+ if (classifier$1 && (classifierSettings$1 === null || classifierSettings$1 === void 0 ? void 0 : classifierSettings$1.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier$1];
5104
+ closeFocusModel();
5105
+ return [4 /*yield*/, preloadFocusModelDependencies()];
5106
+ case 1:
5107
+ _c.sent();
5108
+ if (modelCapabilities.delegate === 'NONE') {
5109
+ throw new Error('No available delegate for focus detector.');
5110
+ }
5111
+ _b = (_a = ImageClassifier).createFromOptions;
5112
+ return [4 /*yield*/, FilesetResolver.forVisionTasks(visionTasksBasePath)];
5113
+ case 2:
5114
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
5115
+ baseOptions: {
5116
+ modelAssetPath: modelAssetPath,
5117
+ delegate: modelCapabilities.delegate
5118
+ },
5119
+ // canvas: document.createElement('canvas'),
5120
+ runningMode: 'VIDEO'
5121
+ }])];
5122
+ case 3:
5123
+ classifier$1 = _c.sent();
5124
+ classifierSettings$1 = {
5125
+ modelAssetPath: modelAssetPath
5126
+ };
5127
+ return [2 /*return*/, classifier$1];
5128
+ }
5129
+ });
5130
+ });
5131
+ }
5132
+ function closeFocusModel() {
5133
+ classifier$1 === null || classifier$1 === void 0 ? void 0 : classifier$1.close();
5134
+ classifier$1 = null;
5135
+ classifierSettings$1 = null;
5136
+ }
5137
+ function useLoadFocusModel(_a) {
5138
+ var _b = _a.modelPath,
5139
+ modelPath = _b === void 0 ? defaultFocusModelPath : _b,
5140
+ _c = _a.modelLoadTimeoutMs,
5141
+ modelLoadTimeoutMs = _c === void 0 ? defaultFocusModelLoadTimeoutMs : _c,
5142
+ onModelError = _a.onModelError,
5143
+ videoRef = _a.videoRef,
5144
+ _d = _a.shouldLoadModels,
5145
+ shouldLoadModels = _d === void 0 ? true : _d;
5146
+ var _e = useState('not-started'),
5147
+ modelLoadState = _e[0],
5148
+ setModelLoadState = _e[1];
5149
+ var _f = useState(0),
5150
+ modelDownloadProgress = _f[0],
5151
+ setModelDownloadProgress = _f[1];
5152
+ var _g = useState(null),
5153
+ modelWarmingStartedAt = _g[0],
5154
+ setModelWarmingStartedAt = _g[1];
5155
+ var _h = useState(null),
5156
+ modelError = _h[0],
5157
+ setModelError = _h[1];
5158
+ useEffect(function loadModel() {
5159
+ var _this = this;
5160
+ if (!shouldLoadModels) return;
5161
+ setModelLoadState('downloading');
5162
+ setModelWarmingStartedAt(null);
5163
+ function handleDownloadProgress(event) {
5164
+ setModelDownloadProgress(progressToPercentage(event.detail));
5165
+ }
5166
+ document.addEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
5167
+ var modelLoadTimeout = setTimeout(function () {
5168
+ setModelError(new Error('Model loading time limit exceeded.'));
5169
+ }, modelLoadTimeoutMs);
5170
+ var cancelVideoReady = function cancelVideoReady() {};
5171
+ loadFocusModel(modelPath).then(function (loadedModel) {
5172
+ return __awaiter(_this, void 0, void 0, function () {
5173
+ var _a, videoReady, cancel, cancelled;
5174
+ return __generator(this, function (_b) {
5175
+ switch (_b.label) {
5176
+ case 0:
5177
+ setModelDownloadProgress(100);
5178
+ clearTimeout(modelLoadTimeout);
5179
+ setModelLoadState('warming');
5180
+ setModelWarmingStartedAt(performance.now());
5181
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
5182
+ cancelled = false;
5183
+ cancelVideoReady = function cancelVideoReady() {
5184
+ cancelled = true;
5185
+ cancel();
5186
+ };
5187
+ return [4 /*yield*/, videoReady];
5188
+ case 1:
5189
+ _b.sent();
5190
+ setTimeout(function () {
5191
+ if (cancelled) return;
5192
+ loadedModel.classifyForVideo(videoRef.current, performance.now());
5193
+ setModelLoadState('ready');
5194
+ }, 500);
5195
+ return [2 /*return*/];
5196
+ }
5197
+ });
5198
+ });
5199
+ })["catch"](function (e) {
5200
+ setModelError(e);
5201
+ setModelLoadState('error');
5202
+ })["finally"](function () {
5203
+ clearTimeout(modelLoadTimeout);
5204
+ });
5205
+ return function () {
5206
+ log('unloading focus model');
5207
+ cancelVideoReady();
5208
+ closeFocusModel();
5209
+ clearTimeout(modelLoadTimeout);
5210
+ document.removeEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
5211
+ };
5212
+ }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
5213
+ useEffect(function handleModelError() {
5214
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
5215
+ }, [modelError, onModelError]);
5216
+ return useMemo(function () {
5217
+ return {
5218
+ ready: modelLoadState === 'ready',
5219
+ modelLoadState: modelLoadState,
5220
+ modelDownloadProgress: modelDownloadProgress,
5221
+ modelWarmingStartedAt: modelWarmingStartedAt,
5222
+ modelError: modelError
5223
+ };
5224
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
5225
+ }
5226
+ var lastFocusPredictionAt = 0;
5227
+ var lastFocusPredictionTime = 0;
5228
+ function setLastFocusPredictionAt(time) {
5229
+ lastFocusPredictionTime = time - lastFocusPredictionAt;
5230
+ lastFocusPredictionAt = time;
5231
+ }
5232
+ function makeFocusModelPrediction(imageData, cropCanvas, rotateCanvas, box) {
5233
+ var _a, _b, _c, _d, _e;
5234
+ if (!classifier$1) return null;
5235
+ var startedAt = performance.now();
5236
+ var image = cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box);
5237
+ var result = classifier$1.classifyForVideo(image, performance.now());
5238
+ 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) {
5239
+ return c.categoryName === 'focused';
5240
+ })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
5241
+ var predictionTime = performance.now() - startedAt;
5242
+ return {
5243
+ score: score,
5244
+ predictionTime: predictionTime
5245
+ };
5584
5246
  }
5585
5247
 
5586
5248
  var FocusModelContext = /*#__PURE__*/createContext({
@@ -5657,7 +5319,7 @@ function FocusModelProvider(_a) {
5657
5319
  }, [focusThresholds, load, makeFocusPrediction, modelDownloadProgress, modelError, modelLoadState, modelWarmingStartedAt]);
5658
5320
  return /*#__PURE__*/React__default.createElement(FocusModelContext.Provider, {
5659
5321
  value: value
5660
- }, /*#__PURE__*/React__default.createElement(InvisibleCanvas, {
5322
+ }, /*#__PURE__*/React__default.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React__default.createElement(InvisibleCanvas, {
5661
5323
  ref: rotateCanvas,
5662
5324
  style: showCanvases ? {
5663
5325
  display: 'block'
@@ -5667,7 +5329,7 @@ function FocusModelProvider(_a) {
5667
5329
  style: showCanvases ? {
5668
5330
  display: 'block'
5669
5331
  } : undefined
5670
- }), children);
5332
+ })), children);
5671
5333
  }
5672
5334
 
5673
5335
  function _isNavigatorDefined() {
@@ -5702,7 +5364,379 @@ function evaluateIsMobile(nav) {
5702
5364
  return false;
5703
5365
  }
5704
5366
 
5367
+ var defaultBarcodeReadabilityModelLoadTimeoutMs = 45000;
5368
+ var classifier = null;
5369
+ var classifierSettings = null;
5370
+ function loadBarcodeReadabilityModel() {
5371
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
5372
+ var _a, _b;
5373
+ if (modelAssetPath === void 0) {
5374
+ modelAssetPath = defaultBarcodeReadabilityModelPath;
5375
+ }
5376
+ return __generator(this, function (_c) {
5377
+ switch (_c.label) {
5378
+ case 0:
5379
+ if (classifier && (classifierSettings === null || classifierSettings === void 0 ? void 0 : classifierSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier];
5380
+ closeBarcodeReadabilityModel();
5381
+ return [4 /*yield*/, preloadBarcodeReadabilityModelDependencies()];
5382
+ case 1:
5383
+ _c.sent();
5384
+ if (modelCapabilities.delegate === 'NONE') {
5385
+ throw new Error('No available delegate for barcode readability model.');
5386
+ }
5387
+ _b = (_a = ImageClassifier).createFromOptions;
5388
+ return [4 /*yield*/, FilesetResolver.forVisionTasks(visionTasksBasePath)];
5389
+ case 2:
5390
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
5391
+ baseOptions: {
5392
+ modelAssetPath: modelAssetPath,
5393
+ delegate: 'CPU'
5394
+ },
5395
+ runningMode: 'VIDEO',
5396
+ maxResults: 1
5397
+ }])];
5398
+ case 3:
5399
+ classifier = _c.sent();
5400
+ classifierSettings = {
5401
+ modelAssetPath: modelAssetPath
5402
+ };
5403
+ return [2 /*return*/, classifier];
5404
+ }
5405
+ });
5406
+ });
5407
+ }
5408
+ function closeBarcodeReadabilityModel() {
5409
+ classifier === null || classifier === void 0 ? void 0 : classifier.close();
5410
+ classifier = null;
5411
+ classifierSettings = null;
5412
+ }
5413
+ function useLoadBarcodeReadabilityModel(_a) {
5414
+ var _b = _a.modelPath,
5415
+ modelPath = _b === void 0 ? defaultBarcodeReadabilityModelPath : _b,
5416
+ _c = _a.modelLoadTimeoutMs,
5417
+ modelLoadTimeoutMs = _c === void 0 ? defaultBarcodeReadabilityModelLoadTimeoutMs : _c,
5418
+ onModelError = _a.onModelError,
5419
+ videoRef = _a.videoRef,
5420
+ _d = _a.shouldLoadModels,
5421
+ shouldLoadModels = _d === void 0 ? true : _d;
5422
+ var _e = useState('not-started'),
5423
+ modelLoadState = _e[0],
5424
+ setModelLoadState = _e[1];
5425
+ var _f = useState(0),
5426
+ modelDownloadProgress = _f[0],
5427
+ setModelDownloadProgress = _f[1];
5428
+ var _g = useState(null),
5429
+ modelWarmingStartedAt = _g[0],
5430
+ setModelWarmingStartedAt = _g[1];
5431
+ var _h = useState(null),
5432
+ modelError = _h[0],
5433
+ setModelError = _h[1];
5434
+ useEffect(function loadModel() {
5435
+ var _this = this;
5436
+ if (!shouldLoadModels) return;
5437
+ setModelLoadState('downloading');
5438
+ setModelWarmingStartedAt(null);
5439
+ function handleDownloadProgress(event) {
5440
+ setModelDownloadProgress(progressToPercentage(event.detail));
5441
+ }
5442
+ document.addEventListener('idmission.preloadProgress.barcodeReadability', handleDownloadProgress);
5443
+ var modelLoadTimeout = setTimeout(function () {
5444
+ setModelError(new Error('Model loading time limit exceeded.'));
5445
+ }, modelLoadTimeoutMs);
5446
+ var cancelVideoReady = function cancelVideoReady() {};
5447
+ loadBarcodeReadabilityModel(modelPath).then(function (loadedModel) {
5448
+ return __awaiter(_this, void 0, void 0, function () {
5449
+ var _a, videoReady, cancel, cancelled;
5450
+ return __generator(this, function (_b) {
5451
+ switch (_b.label) {
5452
+ case 0:
5453
+ setModelDownloadProgress(100);
5454
+ clearTimeout(modelLoadTimeout);
5455
+ setModelLoadState('warming');
5456
+ setModelWarmingStartedAt(new Date().getTime());
5457
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
5458
+ cancelled = false;
5459
+ cancelVideoReady = function cancelVideoReady() {
5460
+ cancelled = true;
5461
+ cancel();
5462
+ };
5463
+ return [4 /*yield*/, videoReady];
5464
+ case 1:
5465
+ _b.sent();
5466
+ setTimeout(function () {
5467
+ if (cancelled) return;
5468
+ loadedModel.classifyForVideo(videoRef.current, performance.now());
5469
+ setModelLoadState('ready');
5470
+ }, 500);
5471
+ return [2 /*return*/];
5472
+ }
5473
+ });
5474
+ });
5475
+ })["catch"](function (e) {
5476
+ setModelError(e);
5477
+ setModelLoadState('error');
5478
+ })["finally"](function () {
5479
+ clearTimeout(modelLoadTimeout);
5480
+ });
5481
+ return function () {
5482
+ log('unloading barcode readability model');
5483
+ cancelVideoReady();
5484
+ closeBarcodeReadabilityModel();
5485
+ clearTimeout(modelLoadTimeout);
5486
+ document.removeEventListener('idmission.preloadProgress.barcodeReadability', handleDownloadProgress);
5487
+ };
5488
+ }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
5489
+ useEffect(function handleModelError() {
5490
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
5491
+ }, [modelError, onModelError]);
5492
+ return useMemo(function () {
5493
+ return {
5494
+ ready: modelLoadState === 'ready',
5495
+ modelLoadState: modelLoadState,
5496
+ modelDownloadProgress: modelDownloadProgress,
5497
+ modelWarmingStartedAt: modelWarmingStartedAt,
5498
+ modelError: modelError
5499
+ };
5500
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
5501
+ }
5502
+ var lastBarcodeReadabilityPredictionAt = 0;
5503
+ var lastBarcodeReadabilityPredictionTime = 0;
5504
+ function setLastBarcodeReadabilityPredictionAt(time) {
5505
+ lastBarcodeReadabilityPredictionTime = time - lastBarcodeReadabilityPredictionAt;
5506
+ lastBarcodeReadabilityPredictionAt = time;
5507
+ }
5508
+ function makeBarcodeReadabilityModelPrediction(imageData, cropCanvas, rotateCanvas, resizeCanvas, box) {
5509
+ var _a, _b, _c, _d, _e;
5510
+ if (!classifier) return null;
5511
+ var startedAt = performance.now();
5512
+ var image = cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box);
5513
+ var resized = resizeIfNecessary(image, resizeCanvas, 500);
5514
+ var result = classifier.classifyForVideo(resized, performance.now());
5515
+ 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) {
5516
+ return c.categoryName === 'blurry';
5517
+ })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
5518
+ debug('barcode prediction', "".concat(performance.now() - startedAt, "ms"), score);
5519
+ var predictionTime = performance.now() - startedAt;
5520
+ return {
5521
+ score: score,
5522
+ predictionTime: predictionTime
5523
+ };
5524
+ }
5525
+
5526
+ var BarcodeReadabilityModelContext = /*#__PURE__*/createContext({
5527
+ loadBarcodeReadabilityModel: function loadBarcodeReadabilityModel() {
5528
+ return null;
5529
+ },
5530
+ barcodeReadabilityModelState: 'not-started',
5531
+ barcodeReadabilityModelDownloadProgress: 0,
5532
+ barcodeReadabilityModelWarmingStartedAt: null,
5533
+ barcodeReadabilityModelError: null,
5534
+ barcodeReadabilityThresholds: {},
5535
+ setBarcodeReadabilityThresholds: function setBarcodeReadabilityThresholds() {
5536
+ return null;
5537
+ },
5538
+ makeBarcodeReadabilityPrediction: function makeBarcodeReadabilityPrediction() {
5539
+ return null;
5540
+ },
5541
+ barcodeReadabilityPredictionTime: 0
5542
+ });
5543
+ function BarcodeReadabilityModelProvider(_a) {
5544
+ var children = _a.children,
5545
+ _b = _a.barcodeReadabilityModelPath,
5546
+ barcodeReadabilityModelPath = _b === void 0 ? defaultBarcodeReadabilityModelPath : _b,
5547
+ _c = _a.barcodeReadabilityModelLoadTimeoutMs,
5548
+ barcodeReadabilityModelLoadTimeoutMs = _c === void 0 ? defaultBarcodeReadabilityModelLoadTimeoutMs : _c,
5549
+ onBarcodeReadabilityModelError = _a.onBarcodeReadabilityModelError,
5550
+ _d = _a.showCanvases,
5551
+ showCanvases = _d === void 0 ? false : _d,
5552
+ _e = _a.shouldLoadModels,
5553
+ shouldLoadModelsProp = _e === void 0 ? true : _e;
5554
+ var cropCanvas = useRef(null);
5555
+ var rotateCanvas = useRef(null);
5556
+ var resizeCanvas = useRef(null);
5557
+ var _f = useState({}),
5558
+ barcodeReadabilityThresholds = _f[0],
5559
+ setBarcodeReadabilityThresholds = _f[1];
5560
+ var videoRef = useCameraStore().videoRef;
5561
+ var _g = useState(shouldLoadModelsProp),
5562
+ shouldLoadModels = _g[0],
5563
+ setShouldLoadModels = _g[1];
5564
+ var load = useCallback(function () {
5565
+ return setShouldLoadModels(true);
5566
+ }, []);
5567
+ var _h = useLoadBarcodeReadabilityModel({
5568
+ modelPath: barcodeReadabilityModelPath,
5569
+ modelLoadTimeoutMs: barcodeReadabilityModelLoadTimeoutMs,
5570
+ onModelError: onBarcodeReadabilityModelError,
5571
+ videoRef: videoRef,
5572
+ shouldLoadModels: shouldLoadModels
5573
+ }),
5574
+ ready = _h.ready,
5575
+ modelLoadState = _h.modelLoadState,
5576
+ modelDownloadProgress = _h.modelDownloadProgress,
5577
+ modelWarmingStartedAt = _h.modelWarmingStartedAt,
5578
+ modelError = _h.modelError;
5579
+ var makeBarcodeReadabilityPrediction = useCallback(function (imageData, box) {
5580
+ if (!ready) return null;
5581
+ var prediction = makeBarcodeReadabilityModelPrediction(imageData, cropCanvas.current, rotateCanvas.current, resizeCanvas.current, box);
5582
+ if (!prediction) return null;
5583
+ setLastBarcodeReadabilityPredictionAt(prediction.predictionTime);
5584
+ return prediction;
5585
+ }, [ready]);
5586
+ var value = useMemo(function () {
5587
+ return {
5588
+ loadBarcodeReadabilityModel: load,
5589
+ barcodeReadabilityModelState: modelLoadState,
5590
+ barcodeReadabilityModelDownloadProgress: modelDownloadProgress,
5591
+ barcodeReadabilityModelWarmingStartedAt: modelWarmingStartedAt,
5592
+ barcodeReadabilityModelError: modelError,
5593
+ makeBarcodeReadabilityPrediction: makeBarcodeReadabilityPrediction,
5594
+ barcodeReadabilityPredictionTime: lastBarcodeReadabilityPredictionTime,
5595
+ barcodeReadabilityThresholds: barcodeReadabilityThresholds,
5596
+ setBarcodeReadabilityThresholds: setBarcodeReadabilityThresholds
5597
+ };
5598
+ }, [barcodeReadabilityThresholds, load, makeBarcodeReadabilityPrediction, modelDownloadProgress, modelError, modelLoadState, modelWarmingStartedAt]);
5599
+ return /*#__PURE__*/React__default.createElement(BarcodeReadabilityModelContext.Provider, {
5600
+ value: value
5601
+ }, /*#__PURE__*/React__default.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React__default.createElement(InvisibleCanvas, {
5602
+ ref: rotateCanvas
5603
+ }), /*#__PURE__*/React__default.createElement(InvisibleCanvas, {
5604
+ ref: cropCanvas
5605
+ }), /*#__PURE__*/React__default.createElement(InvisibleCanvas, {
5606
+ ref: resizeCanvas,
5607
+ style: showCanvases ? {
5608
+ display: 'block'
5609
+ } : undefined
5610
+ })), children);
5611
+ }
5612
+ function useBarcodeReadabilityModelContext() {
5613
+ var context = useContext(BarcodeReadabilityModelContext);
5614
+ if (!context) {
5615
+ throw new Error('useBarcodeReadabilityModelContext must be used within a BarcodeReadabilityModelProvider');
5616
+ }
5617
+ return context;
5618
+ }
5619
+
5705
5620
  var onMobile = isMobile();
5621
+ /**
5622
+ * Analyzes barcode readability for a detected document
5623
+ * @param prediction The document detection prediction
5624
+ * @param lastPredictionCanvas The canvas containing the original frame
5625
+ * @param croppedDocumentCanvas Canvas for storing cropped document
5626
+ * @param bestBarcodeCanvas Canvas for storing best barcode crop
5627
+ * @param currentBestBarcodeScore Current best barcode score
5628
+ * @param documentDetectionThresholds Thresholds for document detection
5629
+ * @param makeBarcodeReadabilityPrediction Function to make barcode readability predictions
5630
+ * @param barcodeReadabilityThresholds Thresholds for barcode readability
5631
+ * @returns Object containing barcode analysis results
5632
+ */
5633
+ function analyzeBarcodeReadability(prediction, lastPredictionCanvas, croppedDocumentCanvas, bestBarcodeCanvas, currentBestBarcodeScore, documentDetectionThresholds, makeBarcodeReadabilityPrediction, barcodeReadabilityThreshold) {
5634
+ return __awaiter(this, void 0, void 0, function () {
5635
+ var pdf417PredictionTime, pdf417PredictionScore, pdf417PredictionThresholdMet, newBestBarcodeScore, newBestBarcodeDetails, documentCroppedPrediction, processedCroppedPrediction, pdf417Prediction;
5636
+ var _a;
5637
+ return __generator(this, function (_b) {
5638
+ switch (_b.label) {
5639
+ case 0:
5640
+ pdf417PredictionTime = 0;
5641
+ pdf417PredictionScore = 0;
5642
+ pdf417PredictionThresholdMet = false;
5643
+ if (!prediction.bestDocument || !((_a = prediction.bestPDF417) === null || _a === void 0 ? void 0 : _a.box) || !bestBarcodeCanvas) {
5644
+ return [2 /*return*/, {
5645
+ pdf417PredictionTime: pdf417PredictionTime,
5646
+ pdf417PredictionScore: pdf417PredictionScore,
5647
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet,
5648
+ newBestBarcodeScore: newBestBarcodeScore,
5649
+ newBestBarcodeDetails: newBestBarcodeDetails
5650
+ }];
5651
+ }
5652
+ /**
5653
+ * Step 1: Crop the full frame to just the document area
5654
+ * This removes background noise and focuses analysis on the document
5655
+ */
5656
+ cropToDetectedObjectBox(lastPredictionCanvas, prediction.bestDocument.box, croppedDocumentCanvas);
5657
+ return [4 /*yield*/, makeDocumentDetectorPrediction(croppedDocumentCanvas)];
5658
+ case 1:
5659
+ documentCroppedPrediction = _b.sent();
5660
+ if (!documentCroppedPrediction) {
5661
+ // error occurred during prediction (error logged by callee)
5662
+ return [2 /*return*/, {
5663
+ pdf417PredictionTime: pdf417PredictionTime,
5664
+ pdf417PredictionScore: pdf417PredictionScore,
5665
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet,
5666
+ newBestBarcodeScore: newBestBarcodeScore,
5667
+ newBestBarcodeDetails: newBestBarcodeDetails
5668
+ }];
5669
+ }
5670
+ processedCroppedPrediction = processDocumentDetectorPrediction(documentCroppedPrediction, documentDetectionThresholds);
5671
+ if (processedCroppedPrediction.bestPDF417) {
5672
+ pdf417Prediction = makeBarcodeReadabilityPrediction(croppedDocumentCanvas, processedCroppedPrediction.bestPDF417.box);
5673
+ if (pdf417Prediction) {
5674
+ pdf417PredictionTime = pdf417Prediction.predictionTime;
5675
+ pdf417PredictionScore = pdf417Prediction.score;
5676
+ if (pdf417Prediction.score > currentBestBarcodeScore) {
5677
+ /**
5678
+ * Step 5: Update best barcode
5679
+ */
5680
+ newBestBarcodeScore = pdf417Prediction.score;
5681
+ newBestBarcodeDetails = {
5682
+ boundingBox: prediction.bestPDF417.box,
5683
+ score: pdf417Prediction.score
5684
+ };
5685
+ if (pdf417PredictionScore >= barcodeReadabilityThreshold) {
5686
+ pdf417PredictionThresholdMet = true;
5687
+ }
5688
+ cropToDetectedObjectBox(croppedDocumentCanvas, processedCroppedPrediction.bestPDF417.box, bestBarcodeCanvas, 16);
5689
+ }
5690
+ }
5691
+ }
5692
+ return [2 /*return*/, {
5693
+ pdf417PredictionTime: pdf417PredictionTime,
5694
+ pdf417PredictionScore: pdf417PredictionScore,
5695
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet,
5696
+ newBestBarcodeScore: newBestBarcodeScore,
5697
+ newBestBarcodeDetails: newBestBarcodeDetails
5698
+ }];
5699
+ }
5700
+ });
5701
+ });
5702
+ }
5703
+ /**
5704
+ * Calculates the barcode readability threshold for a given document type
5705
+ * @param detectedDocumentType The type of document detected
5706
+ * @param barcodeReadabilityThresholds The threshold configuration object
5707
+ * @returns The appropriate threshold value for the current platform (mobile/desktop)
5708
+ */
5709
+ function calculateBarcodeReadabilityThreshold(detectedDocumentType, barcodeReadabilityThresholds) {
5710
+ var barcodeReadabilityThresholdSet = detectedDocumentType in barcodeReadabilityThresholds ? barcodeReadabilityThresholds[detectedDocumentType] : undefined;
5711
+ if (barcodeReadabilityThresholdSet) {
5712
+ return onMobile ? barcodeReadabilityThresholdSet.mobile || 0 : barcodeReadabilityThresholdSet.desktop || 0;
5713
+ }
5714
+ return 0;
5715
+ }
5716
+ /**
5717
+ * Hook that calculates the barcode readability threshold for a given document type
5718
+ */
5719
+ function useBarcodeReadabilityThreshold() {
5720
+ var barcodeReadabilityThresholds = useBarcodeReadabilityModelContext().barcodeReadabilityThresholds;
5721
+ return useCallback(function (detectedDocumentType) {
5722
+ return calculateBarcodeReadabilityThreshold(detectedDocumentType, barcodeReadabilityThresholds);
5723
+ }, [barcodeReadabilityThresholds]);
5724
+ }
5725
+ function useBarcodeReadabilityAnalysis() {
5726
+ var _this = this;
5727
+ var documentDetectionThresholds = useContext(DocumentDetectionModelContext).documentDetectionThresholds;
5728
+ var makeBarcodeReadabilityPrediction = useBarcodeReadabilityModelContext().makeBarcodeReadabilityPrediction;
5729
+ var getBarcodeReadabilityThreshold = useBarcodeReadabilityThreshold();
5730
+ return useCallback(function (prediction, lastPredictionCanvas, croppedDocumentCanvas, bestBarcodeCanvas, currentBestBarcodeScore) {
5731
+ return __awaiter(_this, void 0, void 0, function () {
5732
+ var barcodeReadabilityThreshold;
5733
+ return __generator(this, function (_a) {
5734
+ barcodeReadabilityThreshold = getBarcodeReadabilityThreshold(prediction.detectedDocumentType);
5735
+ return [2 /*return*/, analyzeBarcodeReadability(prediction, lastPredictionCanvas, croppedDocumentCanvas, bestBarcodeCanvas, currentBestBarcodeScore, documentDetectionThresholds, makeBarcodeReadabilityPrediction, barcodeReadabilityThreshold)];
5736
+ });
5737
+ });
5738
+ }, [documentDetectionThresholds, makeBarcodeReadabilityPrediction, getBarcodeReadabilityThreshold]);
5739
+ }
5706
5740
  var defaultIdCaptureThresholds = {
5707
5741
  detection: defaultDocumentDetectionThresholds,
5708
5742
  focus: defaultFocusThresholds
@@ -5735,6 +5769,7 @@ var IdCaptureModelsContext = /*#__PURE__*/createContext({
5735
5769
  },
5736
5770
  detectionTime: 0,
5737
5771
  focusPredictionTime: 0,
5772
+ barcodeReadabilityPredictionTime: 0,
5738
5773
  bestFrameDetails: {
5739
5774
  current: null
5740
5775
  },
@@ -5744,55 +5779,80 @@ var IdCaptureModelsContext = /*#__PURE__*/createContext({
5744
5779
  resetBestFrame: function resetBestFrame() {
5745
5780
  return null;
5746
5781
  },
5782
+ bestBarcodeDetails: {
5783
+ current: null
5784
+ },
5785
+ getBestBarcode: function getBestBarcode() {
5786
+ return null;
5787
+ },
5747
5788
  requiredDocumentType: 'none',
5748
5789
  setRequiredDocumentType: function setRequiredDocumentType() {
5749
5790
  return null;
5750
5791
  }
5751
5792
  });
5752
5793
  function IdCaptureModelsProviderInner(_a) {
5794
+ var _b;
5753
5795
  var children = _a.children,
5754
5796
  onModelError = _a.onModelError,
5755
- _b = _a.allowSinglePageIdCapture,
5756
- allowSinglePageIdCapture = _b === void 0 ? false : _b;
5757
- var _c = useContext(DocumentDetectionModelContext),
5758
- documentDetectionModelState = _c.documentDetectionModelState,
5759
- documentDetectionModelDownloadProgress = _c.documentDetectionModelDownloadProgress,
5760
- documentDetectionModelWarmingStartedAt = _c.documentDetectionModelWarmingStartedAt,
5761
- startDocumentDetection = _c.startDocumentDetection,
5762
- stopDocumentDetection = _c.stopDocumentDetection,
5763
- loadDocumentDetectionModel = _c.loadDocumentDetectionModel,
5764
- lastPredictionCanvas = _c.documentDetectionLastPredictionCanvas,
5765
- clearDocumentDetectionLastPredictionCanvas = _c.clearDocumentDetectionLastPredictionCanvas,
5766
- onDocumentDetected = _c.onDocumentDetected,
5767
- detectionTime = _c.detectionTime,
5768
- documentDetectionThresholds = _c.documentDetectionThresholds,
5769
- setDocumentDetectionThresholds = _c.setDocumentDetectionThresholds,
5770
- documentDetectionBoundaries = _c.documentDetectionBoundaries,
5771
- setDocumentDetectionBoundaries = _c.setDocumentDetectionBoundaries,
5772
- documentDetectionModelError = _c.documentDetectionModelError;
5773
- var _d = useContext(FocusModelContext),
5774
- loadFocusModel = _d.loadFocusModel,
5775
- focusModelState = _d.focusModelState,
5776
- focusModelDownloadProgress = _d.focusModelDownloadProgress,
5777
- focusModelWarmingStartedAt = _d.focusModelWarmingStartedAt,
5778
- makeFocusPrediction = _d.makeFocusPrediction,
5779
- focusThresholds = _d.focusThresholds,
5780
- setFocusThresholds = _d.setFocusThresholds,
5781
- focusPredictionTime = _d.focusPredictionTime,
5782
- focusModelError = _d.focusModelError;
5797
+ _c = _a.allowSinglePageIdCapture,
5798
+ allowSinglePageIdCapture = _c === void 0 ? false : _c,
5799
+ _d = _a.enableBarcodeReadabilityModel,
5800
+ enableBarcodeReadabilityModel = _d === void 0 ? true : _d;
5801
+ var _e = useContext(DocumentDetectionModelContext),
5802
+ documentDetectionModelState = _e.documentDetectionModelState,
5803
+ documentDetectionModelDownloadProgress = _e.documentDetectionModelDownloadProgress,
5804
+ documentDetectionModelWarmingStartedAt = _e.documentDetectionModelWarmingStartedAt,
5805
+ startDocumentDetection = _e.startDocumentDetection,
5806
+ stopDocumentDetection = _e.stopDocumentDetection,
5807
+ loadDocumentDetectionModel = _e.loadDocumentDetectionModel,
5808
+ lastPredictionCanvas = _e.documentDetectionLastPredictionCanvas,
5809
+ clearDocumentDetectionLastPredictionCanvas = _e.clearDocumentDetectionLastPredictionCanvas,
5810
+ onDocumentDetected = _e.onDocumentDetected,
5811
+ detectionTime = _e.detectionTime,
5812
+ documentDetectionThresholds = _e.documentDetectionThresholds,
5813
+ setDocumentDetectionThresholds = _e.setDocumentDetectionThresholds,
5814
+ documentDetectionBoundaries = _e.documentDetectionBoundaries,
5815
+ setDocumentDetectionBoundaries = _e.setDocumentDetectionBoundaries,
5816
+ documentDetectionModelError = _e.documentDetectionModelError;
5817
+ var _f = useContext(FocusModelContext),
5818
+ loadFocusModel = _f.loadFocusModel,
5819
+ focusModelState = _f.focusModelState,
5820
+ focusModelDownloadProgress = _f.focusModelDownloadProgress,
5821
+ focusModelWarmingStartedAt = _f.focusModelWarmingStartedAt,
5822
+ makeFocusPrediction = _f.makeFocusPrediction,
5823
+ focusThresholds = _f.focusThresholds,
5824
+ setFocusThresholds = _f.setFocusThresholds,
5825
+ focusPredictionTime = _f.focusPredictionTime,
5826
+ focusModelError = _f.focusModelError;
5827
+ var _g = useBarcodeReadabilityModelContext(),
5828
+ loadBarcodeReadabilityModel = _g.loadBarcodeReadabilityModel,
5829
+ barcodeReadabilityModelState = _g.barcodeReadabilityModelState,
5830
+ barcodeReadabilityModelDownloadProgress = _g.barcodeReadabilityModelDownloadProgress,
5831
+ barcodeReadabilityModelWarmingStartedAt = _g.barcodeReadabilityModelWarmingStartedAt,
5832
+ makeBarcodeReadabilityPrediction = _g.makeBarcodeReadabilityPrediction,
5833
+ barcodeReadabilityThresholds = _g.barcodeReadabilityThresholds,
5834
+ setBarcodeReadabilityThresholds = _g.setBarcodeReadabilityThresholds,
5835
+ barcodeReadabilityPredictionTime = _g.barcodeReadabilityPredictionTime,
5836
+ barcodeReadabilityModelError = _g.barcodeReadabilityModelError;
5783
5837
  var onPredictionHandler = useRef();
5784
5838
  var bestFrameDetails = useRef(null);
5839
+ var bestBarcodeDetails = useRef(null);
5785
5840
  var bestPredictionCanvas = useRef(null);
5841
+ var bestBarcodeCanvas = useRef(null);
5842
+ var croppedDocumentCanvas = useRef(null);
5786
5843
  var bestFocusScore = useRef(0);
5844
+ var bestBarcodeScore = useRef(0);
5787
5845
  var stopDetection = useRef(0);
5788
- var _e = useState('none'),
5789
- requiredDocumentType = _e[0],
5790
- setRequiredDocumentType = _e[1];
5846
+ var analyzeBarcodeReadability = useBarcodeReadabilityAnalysis();
5847
+ var _h = useState('none'),
5848
+ requiredDocumentType = _h[0],
5849
+ setRequiredDocumentType = _h[1];
5791
5850
  var thresholds = useMemo(function () {
5792
5851
  return _assign(_assign({}, documentDetectionThresholds), {
5793
- focus: focusThresholds
5852
+ focus: focusThresholds,
5853
+ barcodeReadability: barcodeReadabilityThresholds
5794
5854
  });
5795
- }, [documentDetectionThresholds, focusThresholds]);
5855
+ }, [documentDetectionThresholds, focusThresholds, barcodeReadabilityThresholds]);
5796
5856
  var setThresholds = useCallback(function (thresholds) {
5797
5857
  if (thresholds.detection) {
5798
5858
  setDocumentDetectionThresholds(thresholds.detection);
@@ -5800,57 +5860,87 @@ function IdCaptureModelsProviderInner(_a) {
5800
5860
  if (thresholds.focus) {
5801
5861
  setFocusThresholds(thresholds.focus);
5802
5862
  }
5803
- }, [setDocumentDetectionThresholds, setFocusThresholds]);
5863
+ if (thresholds.barcodeReadability) {
5864
+ setBarcodeReadabilityThresholds(thresholds.barcodeReadability);
5865
+ }
5866
+ }, [setBarcodeReadabilityThresholds, setDocumentDetectionThresholds, setFocusThresholds]);
5804
5867
  useEffect(function handleDetections() {
5805
5868
  var _this = this;
5806
5869
  onDocumentDetected(function (prediction) {
5807
5870
  return __awaiter(_this, void 0, void 0, function () {
5808
- var stopDetectionAtStart, focusPredictionTime, focusScore, focusThresholdMet, isSinglePage, isRequiredDocumentType, focusPrediction, focusThresholdSet, focusThreshold;
5871
+ var stopDetectionAtStart, focusPredictionTime, focusScore, focusThresholdMet, pdf417PredictionTime, pdf417PredictionScore, pdf417PredictionThresholdMet, isSinglePage, isRequiredDocumentType, focusPrediction, focusThresholdSet, focusThreshold, barcodeAnalysisResult;
5809
5872
  var _a, _b, _c, _d, _e, _f, _g;
5810
5873
  return __generator(this, function (_h) {
5811
- if (!lastPredictionCanvas.current) return [2 /*return*/];
5812
- stopDetectionAtStart = stopDetection.current;
5813
- focusPredictionTime = 0, focusScore = 0, focusThresholdMet = false;
5814
- isSinglePage = prediction.detectedDocumentType === 'singlePage';
5815
- if (!allowSinglePageIdCapture && isSinglePage) {
5816
- prediction.detectedDocumentType = 'passport';
5817
- prediction.passportDetectionScore = prediction.singlePageDetectionScore;
5818
- prediction.passportDetectionThresholdMet = prediction.singlePageDetectionThresholdMet;
5819
- prediction.singlePageDetectionScore = 0;
5820
- prediction.singlePageDetectionThresholdMet = false;
5821
- }
5822
- 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'));
5823
- if (isRequiredDocumentType && prediction.detectedDocumentType !== 'none' && prediction.detectionThresholdMet && prediction.documentInBounds && !prediction.documentTooClose && prediction.documentIsStable) {
5824
- focusPrediction = makeFocusPrediction(lastPredictionCanvas.current, (_c = prediction.bestDocument) === null || _c === void 0 ? void 0 : _c.box);
5825
- if (focusPrediction) {
5826
- focusScore = focusPrediction.score;
5827
- focusPredictionTime = focusPrediction.predictionTime;
5828
- }
5829
- focusThresholdSet = (_d = thresholds.focus) === null || _d === void 0 ? void 0 : _d[prediction.detectedDocumentType];
5830
- 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;
5831
- focusThresholdMet = focusScore >= focusThreshold;
5832
- if (bestFocusScore.current <= focusScore && stopDetectionAtStart === stopDetection.current) {
5833
- bestFocusScore.current = focusScore;
5834
- drawToCanvas(bestPredictionCanvas.current, lastPredictionCanvas.current);
5835
- bestFrameDetails.current = {
5836
- boundingBox: (_f = prediction.bestDocument) === null || _f === void 0 ? void 0 : _f.box,
5837
- documentType: prediction.detectedDocumentType,
5838
- detectionScore: prediction.detectionScore,
5839
- focusScore: focusScore
5840
- };
5841
- }
5874
+ switch (_h.label) {
5875
+ case 0:
5876
+ if (!lastPredictionCanvas.current) return [2 /*return*/];
5877
+ stopDetectionAtStart = stopDetection.current;
5878
+ focusPredictionTime = 0, focusScore = 0, focusThresholdMet = false, pdf417PredictionTime = 0, pdf417PredictionScore = 0, pdf417PredictionThresholdMet = false;
5879
+ isSinglePage = prediction.detectedDocumentType === 'singlePage';
5880
+ if (!allowSinglePageIdCapture && isSinglePage) {
5881
+ prediction.detectedDocumentType = 'passport';
5882
+ prediction.passportDetectionScore = prediction.singlePageDetectionScore;
5883
+ prediction.passportDetectionThresholdMet = prediction.singlePageDetectionThresholdMet;
5884
+ prediction.singlePageDetectionScore = 0;
5885
+ prediction.singlePageDetectionThresholdMet = false;
5886
+ }
5887
+ 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'));
5888
+ if (!(isRequiredDocumentType && prediction.detectedDocumentType !== 'none' && prediction.detectionThresholdMet && prediction.documentInBounds && !prediction.documentTooClose && prediction.documentIsStable)) return [3 /*break*/, 2];
5889
+ focusPrediction = makeFocusPrediction(lastPredictionCanvas.current, (_c = prediction.bestDocument) === null || _c === void 0 ? void 0 : _c.box);
5890
+ if (focusPrediction) {
5891
+ focusScore = focusPrediction.score;
5892
+ focusPredictionTime = focusPrediction.predictionTime;
5893
+ }
5894
+ focusThresholdSet = (_d = thresholds.focus) === null || _d === void 0 ? void 0 : _d[prediction.detectedDocumentType];
5895
+ 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;
5896
+ focusThresholdMet = focusScore >= focusThreshold;
5897
+ if (!(stopDetectionAtStart === stopDetection.current)) return [3 /*break*/, 2];
5898
+ if (bestFocusScore.current <= focusScore) {
5899
+ bestFocusScore.current = focusScore;
5900
+ drawToCanvas(bestPredictionCanvas.current, lastPredictionCanvas.current);
5901
+ bestFrameDetails.current = {
5902
+ boundingBox: (_f = prediction.bestDocument) === null || _f === void 0 ? void 0 : _f.box,
5903
+ documentType: prediction.detectedDocumentType,
5904
+ detectionScore: prediction.detectionScore,
5905
+ focusScore: focusScore
5906
+ };
5907
+ }
5908
+ if (!(enableBarcodeReadabilityModel && prediction.bestDocument && prediction.bestPDF417 && croppedDocumentCanvas.current)) return [3 /*break*/, 2];
5909
+ return [4 /*yield*/, analyzeBarcodeReadability(prediction, lastPredictionCanvas.current, croppedDocumentCanvas.current, bestBarcodeCanvas.current, bestBarcodeScore.current)];
5910
+ case 1:
5911
+ barcodeAnalysisResult = _h.sent();
5912
+ pdf417PredictionTime = barcodeAnalysisResult.pdf417PredictionTime;
5913
+ pdf417PredictionScore = barcodeAnalysisResult.pdf417PredictionScore;
5914
+ pdf417PredictionThresholdMet = barcodeAnalysisResult.pdf417PredictionThresholdMet;
5915
+ if (barcodeAnalysisResult.newBestBarcodeScore) {
5916
+ bestBarcodeScore.current = barcodeAnalysisResult.newBestBarcodeScore;
5917
+ }
5918
+ if (barcodeAnalysisResult.newBestBarcodeDetails) {
5919
+ bestBarcodeDetails.current = barcodeAnalysisResult.newBestBarcodeDetails;
5920
+ }
5921
+ _h.label = 2;
5922
+ case 2:
5923
+ /**
5924
+ * @note
5925
+ * This should ALWAYS be called.
5926
+ * Do not return early from this function unless
5927
+ * lastPredictionCanvas.current is not set
5928
+ */
5929
+ (_g = onPredictionHandler.current) === null || _g === void 0 ? void 0 : _g.call(onPredictionHandler, _assign(_assign({}, prediction), {
5930
+ focusScore: focusScore,
5931
+ focusPredictionTime: focusPredictionTime,
5932
+ focusThresholdMet: focusThresholdMet,
5933
+ pdf417PredictionTime: pdf417PredictionTime,
5934
+ pdf417PredictionScore: pdf417PredictionScore,
5935
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet
5936
+ }));
5937
+ return [2 /*return*/];
5842
5938
  }
5843
- (_g = onPredictionHandler.current) === null || _g === void 0 ? void 0 : _g.call(onPredictionHandler, _assign(_assign({}, prediction), {
5844
- focusScore: focusScore,
5845
- focusPredictionTime: focusPredictionTime,
5846
- focusThresholdMet: focusThresholdMet
5847
- }));
5848
- return [2 /*return*/];
5849
5939
  });
5850
5940
  });
5851
5941
  });
5852
- }, [allowSinglePageIdCapture, lastPredictionCanvas, makeFocusPrediction, onDocumentDetected, requiredDocumentType, thresholds.focus]);
5853
- var modelError = documentDetectionModelError !== null && documentDetectionModelError !== void 0 ? documentDetectionModelError : focusModelError;
5942
+ }, [allowSinglePageIdCapture, analyzeBarcodeReadability, barcodeReadabilityThresholds, enableBarcodeReadabilityModel, lastPredictionCanvas, makeBarcodeReadabilityPrediction, makeFocusPrediction, onDocumentDetected, requiredDocumentType, thresholds.focus]);
5943
+ var modelError = (_b = documentDetectionModelError !== null && documentDetectionModelError !== void 0 ? documentDetectionModelError : focusModelError) !== null && _b !== void 0 ? _b : barcodeReadabilityModelError;
5854
5944
  useEffect(function handleModelErrors() {
5855
5945
  if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
5856
5946
  }, [modelError, onModelError]);
@@ -5863,9 +5953,15 @@ function IdCaptureModelsProviderInner(_a) {
5863
5953
  canvas: bestPredictionCanvas.current
5864
5954
  });
5865
5955
  }, []);
5866
- var _f = useState(0),
5867
- canvasKey = _f[0],
5868
- setCanvasKey = _f[1];
5956
+ var getBestBarcode = useCallback(function () {
5957
+ if (!bestBarcodeDetails.current || !bestBarcodeCanvas.current) return null;
5958
+ return _assign(_assign({}, bestBarcodeDetails.current), {
5959
+ canvas: bestBarcodeCanvas.current
5960
+ });
5961
+ }, []);
5962
+ var _j = useState(0),
5963
+ canvasKey = _j[0],
5964
+ setCanvasKey = _j[1];
5869
5965
  var resetBestFrame = useCallback(function () {
5870
5966
  stopDetection.current += 1;
5871
5967
  setCanvasKey(function (n) {
@@ -5881,16 +5977,45 @@ function IdCaptureModelsProviderInner(_a) {
5881
5977
  var load = useCallback(function () {
5882
5978
  loadDocumentDetectionModel();
5883
5979
  loadFocusModel();
5884
- }, [loadDocumentDetectionModel, loadFocusModel]);
5885
- var ready = documentDetectionModelState === 'ready' && focusModelState === 'ready';
5886
- var modelLoadState = ready ? 'ready' : documentDetectionModelState === 'warming' || focusModelState === 'warming' ? 'warming' : focusModelState === 'downloading' || documentDetectionModelState === 'downloading' ? 'downloading' : 'not-started';
5887
- var modelWarmingStartedAt = !documentDetectionModelWarmingStartedAt && !focusModelWarmingStartedAt ? null : Math.min.apply(Math, [documentDetectionModelWarmingStartedAt, focusModelWarmingStartedAt].filter(function (v) {
5888
- return v !== null;
5889
- }));
5980
+ if (enableBarcodeReadabilityModel) loadBarcodeReadabilityModel();
5981
+ }, [enableBarcodeReadabilityModel, loadBarcodeReadabilityModel, loadDocumentDetectionModel, loadFocusModel]);
5982
+ var _k = useMemo(function () {
5983
+ var modelStates = [documentDetectionModelState, focusModelState];
5984
+ var modelWarmingStartedAts = [documentDetectionModelWarmingStartedAt, focusModelWarmingStartedAt];
5985
+ var modelDownloadProgresses = [documentDetectionModelDownloadProgress, focusModelDownloadProgress];
5986
+ if (enableBarcodeReadabilityModel) {
5987
+ modelStates.push(barcodeReadabilityModelState);
5988
+ modelWarmingStartedAts.push(barcodeReadabilityModelWarmingStartedAt);
5989
+ modelDownloadProgresses.push(barcodeReadabilityModelDownloadProgress);
5990
+ }
5991
+ var ready = modelStates.every(function (state) {
5992
+ return state === 'ready';
5993
+ });
5994
+ return {
5995
+ ready: ready,
5996
+ modelLoadState: ready ? 'ready' : modelStates.some(function (state) {
5997
+ return state === 'warming';
5998
+ }) ? 'warming' : modelStates.some(function (state) {
5999
+ return state === 'downloading';
6000
+ }) ? 'downloading' : 'not-started',
6001
+ modelWarmingStartedAt: modelWarmingStartedAts.every(function (v) {
6002
+ return v === null;
6003
+ }) ? null : Math.min.apply(Math, modelWarmingStartedAts.filter(function (v) {
6004
+ return v !== null;
6005
+ })),
6006
+ modelDownloadProgress: modelDownloadProgresses.reduce(function (a, b) {
6007
+ return a + b;
6008
+ }, 0) / modelDownloadProgresses.length
6009
+ };
6010
+ }, [barcodeReadabilityModelDownloadProgress, barcodeReadabilityModelState, barcodeReadabilityModelWarmingStartedAt, documentDetectionModelDownloadProgress, documentDetectionModelState, documentDetectionModelWarmingStartedAt, enableBarcodeReadabilityModel, focusModelDownloadProgress, focusModelState, focusModelWarmingStartedAt]),
6011
+ ready = _k.ready,
6012
+ modelLoadState = _k.modelLoadState,
6013
+ modelWarmingStartedAt = _k.modelWarmingStartedAt,
6014
+ modelDownloadProgress = _k.modelDownloadProgress;
5890
6015
  var value = useMemo(function () {
5891
6016
  return {
5892
6017
  ready: ready,
5893
- modelDownloadProgress: (documentDetectionModelDownloadProgress + focusModelDownloadProgress) / 2,
6018
+ modelDownloadProgress: modelDownloadProgress,
5894
6019
  modelLoadState: modelLoadState,
5895
6020
  modelWarmingStartedAt: modelWarmingStartedAt,
5896
6021
  modelError: modelError,
@@ -5904,24 +6029,35 @@ function IdCaptureModelsProviderInner(_a) {
5904
6029
  onPredictionMade: onPredictionMade,
5905
6030
  detectionTime: detectionTime,
5906
6031
  focusPredictionTime: focusPredictionTime,
6032
+ barcodeReadabilityPredictionTime: barcodeReadabilityPredictionTime,
5907
6033
  getBestFrame: getBestFrame,
5908
6034
  resetBestFrame: resetBestFrame,
5909
6035
  bestFrameDetails: bestFrameDetails,
6036
+ bestBarcodeDetails: bestBarcodeDetails,
6037
+ getBestBarcode: getBestBarcode,
5910
6038
  requiredDocumentType: requiredDocumentType,
5911
6039
  setRequiredDocumentType: setRequiredDocumentType
5912
6040
  };
5913
- }, [detectionTime, documentDetectionBoundaries, documentDetectionModelDownloadProgress, focusModelDownloadProgress, focusPredictionTime, getBestFrame, load, modelLoadState, modelError, modelWarmingStartedAt, onPredictionMade, ready, requiredDocumentType, resetBestFrame, setDocumentDetectionBoundaries, setThresholds, startDocumentDetection, stopDocumentDetection, thresholds]);
6041
+ }, [ready, modelDownloadProgress, modelLoadState, modelWarmingStartedAt, modelError, startDocumentDetection, stopDocumentDetection, load, thresholds, setThresholds, documentDetectionBoundaries, setDocumentDetectionBoundaries, onPredictionMade, detectionTime, focusPredictionTime, barcodeReadabilityPredictionTime, getBestFrame, resetBestFrame, getBestBarcode, requiredDocumentType]);
5914
6042
  return /*#__PURE__*/React__default.createElement(IdCaptureModelsContext.Provider, {
5915
6043
  value: value
5916
- }, /*#__PURE__*/React__default.createElement(InvisibleCanvas, {
5917
- key: canvasKey,
6044
+ }, /*#__PURE__*/React__default.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React__default.createElement(InvisibleCanvas, {
6045
+ key: "bf-".concat(canvasKey),
5918
6046
  ref: bestPredictionCanvas
5919
- }), children);
6047
+ }), /*#__PURE__*/React__default.createElement(InvisibleCanvas, {
6048
+ key: "bb-".concat(canvasKey),
6049
+ ref: bestBarcodeCanvas
6050
+ }), /*#__PURE__*/React__default.createElement(InvisibleCanvas, {
6051
+ key: "cd-".concat(canvasKey),
6052
+ ref: croppedDocumentCanvas
6053
+ })), children);
5920
6054
  }
5921
6055
  function IdCaptureModelsProvider(_a) {
5922
6056
  var children = _a.children,
5923
6057
  props = __rest(_a, ["children"]);
5924
- return /*#__PURE__*/React__default.createElement(DocumentDetectionModelProvider, _assign({}, props), /*#__PURE__*/React__default.createElement(FocusModelProvider, _assign({}, props), /*#__PURE__*/React__default.createElement(IdCaptureModelsProviderInner, _assign({}, props), children)));
6058
+ return /*#__PURE__*/React__default.createElement(DocumentDetectionModelProvider, _assign({}, props), /*#__PURE__*/React__default.createElement(FocusModelProvider, _assign({}, props), /*#__PURE__*/React__default.createElement(BarcodeReadabilityModelProvider, _assign({}, props, {
6059
+ shouldLoadModels: props.enableBarcodeReadabilityModel
6060
+ }), /*#__PURE__*/React__default.createElement(IdCaptureModelsProviderInner, _assign({}, props), children))));
5925
6061
  }
5926
6062
  function useIdCaptureModelsContext() {
5927
6063
  var context = useContext(IdCaptureModelsContext);
@@ -5931,7 +6067,7 @@ function useIdCaptureModelsContext() {
5931
6067
  return context;
5932
6068
  }
5933
6069
 
5934
- var CapturedDocumentTypeValues = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'selfie', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
6070
+ var CapturedDocumentTypeValues = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'selfie', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage', 'idBarcodeImage'];
5935
6071
 
5936
6072
  var acceptedDocumentTypesForIdCaptureRequirementOption = {
5937
6073
  idCardFront: ['idCardFront'],
@@ -6017,6 +6153,7 @@ var initialState$5 = {
6017
6153
  capturing: false,
6018
6154
  captureFailed: false,
6019
6155
  imageUrl: null,
6156
+ idBarcodeImage: null,
6020
6157
  captureState: 'initializing',
6021
6158
  capturedDocuments: {},
6022
6159
  captureRequirement: 'idCardOrPassport',
@@ -6296,6 +6433,17 @@ var _reducer = function reducer(state, action) {
6296
6433
  }
6297
6434
  return newState;
6298
6435
  }
6436
+ case 'barcodeCaptured':
6437
+ return _reducer(state, {
6438
+ type: 'documentCaptured',
6439
+ payload: {
6440
+ imageData: action.payload.imageUrl,
6441
+ documentType: 'idBarcodeImage',
6442
+ width: 0,
6443
+ height: 0,
6444
+ barcodeReadabilityScore: action.payload.barcodeReadabilityScore
6445
+ }
6446
+ });
6299
6447
  case 'flipRequestCompleted':
6300
6448
  return _assign(_assign({}, state), {
6301
6449
  captureState: 'capturing',
@@ -6787,12 +6935,13 @@ var IdCapture = function IdCapture(_a) {
6787
6935
  height = _q === void 0 ? 1 : _q;
6788
6936
  var state = useIdCaptureStore();
6789
6937
  var isRearFacing = useCameraStore().isRearFacing;
6790
- var _r = useContext(IdCaptureModelsContext),
6938
+ var _r = useIdCaptureModelsContext(),
6791
6939
  modelsReady = _r.ready,
6792
6940
  setThresholds = _r.setThresholds,
6793
6941
  detectionTime = _r.detectionTime,
6794
6942
  focusPredictionTime = _r.focusPredictionTime,
6795
- getBestFrame = _r.getBestFrame;
6943
+ getBestFrame = _r.getBestFrame,
6944
+ getBestBarcode = _r.getBestBarcode;
6796
6945
  useEffect(function () {
6797
6946
  return dispatchIdCaptureAction({
6798
6947
  type: 'captureInitialized'
@@ -6831,6 +6980,16 @@ var IdCapture = function IdCapture(_a) {
6831
6980
  });
6832
6981
  return;
6833
6982
  }
6983
+ var bestBarcode = getBestBarcode();
6984
+ if (bestBarcode) {
6985
+ dispatchIdCaptureAction({
6986
+ type: 'barcodeCaptured',
6987
+ payload: {
6988
+ imageUrl: bestBarcode.canvas.toDataURL('image/jpeg', 0.95),
6989
+ barcodeReadabilityScore: bestBarcode.score
6990
+ }
6991
+ });
6992
+ }
6834
6993
  var canvas = bestFrame.canvas,
6835
6994
  documentType = bestFrame.documentType,
6836
6995
  boundingBox = bestFrame.boundingBox,
@@ -6847,21 +7006,22 @@ var IdCapture = function IdCapture(_a) {
6847
7006
  });
6848
7007
  var capturedDocumentType = documentType;
6849
7008
  setTimeout(function () {
6850
- var _a;
6851
- var captureTime = new Date().getTime() - ((_a = state.captureStartedAt) !== null && _a !== void 0 ? _a : new Date()).getTime();
7009
+ var _a, _b;
7010
+ var captureTime = performance.now() - ((_a = state.captureStartedAt) !== null && _a !== void 0 ? _a : new Date()).getTime();
6852
7011
  var metadata = {
6853
7012
  autoCapture: 'Y',
6854
7013
  captureTime: captureTime,
6855
7014
  boundingBox: boundingBox,
6856
7015
  bestDetectionScore: detectionScore,
6857
- bestFocusScore: focusScore
7016
+ bestFocusScore: focusScore,
7017
+ bestBarcodeScore: (_b = bestBarcode === null || bestBarcode === void 0 ? void 0 : bestBarcode.score) !== null && _b !== void 0 ? _b : 0
6858
7018
  };
6859
7019
  onCapture === null || onCapture === void 0 ? void 0 : onCapture(imageUrl, width, height, capturedDocumentType, metadata);
6860
7020
  dispatchIdCaptureAction({
6861
7021
  type: 'captured'
6862
7022
  });
6863
7023
  }, 0);
6864
- }, [getBestFrame, onCapture, shouldCapture, state.captureStartedAt, state.requestedDocumentType]);
7024
+ }, [getBestBarcode, getBestFrame, onCapture, shouldCapture, state.captureStartedAt, state.requestedDocumentType]);
6865
7025
  var theme = useTheme();
6866
7026
  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');
6867
7027
  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');
@@ -7661,7 +7821,7 @@ var IdCaptureLoadingOverlayDefault = function IdCaptureLoadingOverlayDefault(_a)
7661
7821
  };
7662
7822
  }, [ready]);
7663
7823
  var imageRef = useRef(null);
7664
- var timeSinceWarmingStarted = modelWarmingStartedAt ? new Date().getTime() - modelWarmingStartedAt : 0;
7824
+ var timeSinceWarmingStarted = modelWarmingStartedAt ? performance.now() - modelWarmingStartedAt : 0;
7665
7825
  var warmingProgress = timeSinceWarmingStarted / 5000.0;
7666
7826
  var modelLoadProgress = modelsReady ? 100 : modelDownloadProgress * 0.5 + warmingProgress * 49.0;
7667
7827
  useLoadProgressHooks({
@@ -7999,7 +8159,7 @@ var Card = styled.div(templateObject_1$D || (templateObject_1$D = __makeTemplate
7999
8159
  var FlexCard = styled(Card)(templateObject_2$y || (templateObject_2$y = __makeTemplateObject(["\n display: flex;\n flex-direction: column;\n"], ["\n display: flex;\n flex-direction: column;\n"])));
8000
8160
  var templateObject_1$D, templateObject_2$y;
8001
8161
 
8002
- var imageDisplayOrder = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
8162
+ var imageDisplayOrder = ['idCardFront', 'idCardBack', 'idBarcodeImage', 'passport', 'singlePage', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
8003
8163
  var IdCaptureSuccess = function IdCaptureSuccess(_a) {
8004
8164
  var capturedDocuments = _a.capturedDocuments,
8005
8165
  onSubmitClick = _a.onSubmitClick,
@@ -8041,7 +8201,7 @@ var IdCaptureSuccess = function IdCaptureSuccess(_a) {
8041
8201
  image: doc,
8042
8202
  className: classNames.image,
8043
8203
  alt: doc.documentType
8044
- }), debugMode && ( /*#__PURE__*/React__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)))));
8204
+ }), debugMode && ( /*#__PURE__*/React__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)))));
8045
8205
  }))), /*#__PURE__*/React__default.createElement(ButtonsColumn, {
8046
8206
  className: classNames.buttonsRow
8047
8207
  }, /*#__PURE__*/React__default.createElement(WideButton, {
@@ -10663,7 +10823,7 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10663
10823
  var _6 = useState(false),
10664
10824
  overlayDismissed = _6[0],
10665
10825
  setOverlayDismissed = _6[1];
10666
- var _7 = useContext(SubmissionContext),
10826
+ var _7 = useSubmissionContext(),
10667
10827
  submissionStatus = _7.submissionStatus,
10668
10828
  setIdFrontImage = _7.setIdFrontImage,
10669
10829
  setIdBackImage = _7.setIdBackImage,
@@ -10672,6 +10832,7 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10672
10832
  setIdBackIrImage = _7.setIdBackIrImage,
10673
10833
  setIdFrontUvImage = _7.setIdFrontUvImage,
10674
10834
  setIdBackUvImage = _7.setIdBackUvImage,
10835
+ setIdBarcodeImage = _7.setIdBarcodeImage,
10675
10836
  logIdFrontCaptureAttempt = _7.logIdFrontCaptureAttempt,
10676
10837
  logIdBackCaptureAttempt = _7.logIdBackCaptureAttempt;
10677
10838
  var _8 = useIdCaptureModelsContext(),
@@ -10772,7 +10933,7 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10772
10933
  });
10773
10934
  }, [logCaptureMetadata, onDocumentCaptured]);
10774
10935
  var onSubmitClick = useCallback(function () {
10775
- var _a, _b, _c, _d, _e, _f, _g, _h;
10936
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
10776
10937
  var docs = state.capturedDocuments;
10777
10938
  var submission = {
10778
10939
  idFrontImage: maybeDataUrlToBase64Sync((_a = docs.idCardFront) === null || _a === void 0 ? void 0 : _a.imageData),
@@ -10782,7 +10943,8 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10782
10943
  idFrontIrImage: maybeDataUrlToBase64Sync((_e = docs.idFrontIrImage) === null || _e === void 0 ? void 0 : _e.imageData),
10783
10944
  idBackIrImage: maybeDataUrlToBase64Sync((_f = docs.idBackIrImage) === null || _f === void 0 ? void 0 : _f.imageData),
10784
10945
  idFrontUvImage: maybeDataUrlToBase64Sync((_g = docs.idFrontUvImage) === null || _g === void 0 ? void 0 : _g.imageData),
10785
- idBackUvImage: maybeDataUrlToBase64Sync((_h = docs.idBackUvImage) === null || _h === void 0 ? void 0 : _h.imageData)
10946
+ idBackUvImage: maybeDataUrlToBase64Sync((_h = docs.idBackUvImage) === null || _h === void 0 ? void 0 : _h.imageData),
10947
+ idBarcodeImage: maybeDataUrlToBase64Sync((_j = docs.idBarcodeImage) === null || _j === void 0 ? void 0 : _j.imageData)
10786
10948
  };
10787
10949
  if (submission.idFrontImage) setIdFrontImage(submission.idFrontImage);
10788
10950
  if (submission.idBackImage) setIdBackImage(submission.idBackImage);
@@ -10792,11 +10954,12 @@ var IdCaptureWizard = function IdCaptureWizard(_a) {
10792
10954
  if (submission.idBackIrImage) setIdBackIrImage(submission.idBackIrImage);
10793
10955
  if (submission.idFrontUvImage) setIdFrontUvImage(submission.idFrontUvImage);
10794
10956
  if (submission.idBackUvImage) setIdBackUvImage(submission.idBackUvImage);
10957
+ if (submission.idBarcodeImage) setIdBarcodeImage(submission.idBarcodeImage);
10795
10958
  if (releaseCameraAccessOnExit) releaseCameraAccess();
10796
10959
  setTimeout(function () {
10797
10960
  return onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(submission);
10798
10961
  }, 0);
10799
- }, [onSuccess, releaseCameraAccess, releaseCameraAccessOnExit, setIdBackImage, setIdBackIrImage, setIdBackUvImage, setIdFrontImage, setIdFrontIrImage, setIdFrontUvImage, setPassportImage, state.capturedDocuments]);
10962
+ }, [onSuccess, releaseCameraAccess, releaseCameraAccessOnExit, setIdBarcodeImage, setIdBackImage, setIdBackIrImage, setIdBackUvImage, setIdFrontImage, setIdFrontIrImage, setIdFrontUvImage, setPassportImage, state.capturedDocuments]);
10800
10963
  var showSuccessScreen = useShowSuccessScreen(skipSuccessScreen, state.captureState === 'complete', onSubmitClick);
10801
10964
  var onRetryClick = useCallback(function () {
10802
10965
  return dispatchIdCaptureAction({
@@ -11586,59 +11749,397 @@ function SelfieCaptureAnimatedMask(_a) {
11586
11749
  fill: "white"
11587
11750
  }))))));
11588
11751
  }
11589
- function SelfieCaptureAnimatedMaskWithStatus(_a) {
11590
- var _b = _a.status,
11591
- status = _b === void 0 ? 'ready' : _b,
11592
- props = __rest(_a, ["status"]);
11593
- var _c = useState(1),
11594
- frame = _c[0],
11595
- setFrame = _c[1];
11596
- useEffect(function () {
11597
- if (status !== 'processing') {
11598
- setFrame(0);
11599
- return;
11600
- }
11601
- setFrame(1);
11602
- var interval = setInterval(function () {
11603
- setFrame(function (n) {
11604
- return (n + 1) % 6;
11605
- });
11606
- }, 250);
11607
- return function () {
11608
- clearInterval(interval);
11752
+ function SelfieCaptureAnimatedMaskWithStatus(_a) {
11753
+ var _b = _a.status,
11754
+ status = _b === void 0 ? 'ready' : _b,
11755
+ props = __rest(_a, ["status"]);
11756
+ var _c = useState(1),
11757
+ frame = _c[0],
11758
+ setFrame = _c[1];
11759
+ useEffect(function () {
11760
+ if (status !== 'processing') {
11761
+ setFrame(0);
11762
+ return;
11763
+ }
11764
+ setFrame(1);
11765
+ var interval = setInterval(function () {
11766
+ setFrame(function (n) {
11767
+ return (n + 1) % 6;
11768
+ });
11769
+ }, 250);
11770
+ return function () {
11771
+ clearInterval(interval);
11772
+ };
11773
+ }, [status]);
11774
+ return /*#__PURE__*/React__default.createElement(SelfieCaptureAnimatedMask, _assign({}, props, {
11775
+ frame: frame,
11776
+ status: status
11777
+ }));
11778
+ }
11779
+ var templateObject_1$o, templateObject_2$m, templateObject_3$g;
11780
+
11781
+ var FaceCaptureGuideContainer = styled.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"])));
11782
+ var FaceCaptureGuideInner = styled.div(templateObject_2$l || (templateObject_2$l = __makeTemplateObject(["\n position: relative;\n height: 60%;\n"], ["\n position: relative;\n height: 60%;\n"])));
11783
+ var FaceCaptureGuideOverlay = function FaceCaptureGuideOverlay(_a) {
11784
+ var _b = _a.classNames,
11785
+ classNames = _b === void 0 ? {} : _b,
11786
+ _c = _a.status,
11787
+ status = _c === void 0 ? 'ready' : _c,
11788
+ _d = _a.borderWidth,
11789
+ borderWidth = _d === void 0 ? 5 : _d,
11790
+ _e = _a.borderColor,
11791
+ borderColor = _e === void 0 ? 'white' : _e,
11792
+ _f = _a.borderOpacity,
11793
+ borderOpacity = _f === void 0 ? 0.8 : _f;
11794
+ return /*#__PURE__*/React__default.createElement(FaceCaptureGuideContainer, {
11795
+ className: classNames.container
11796
+ }, /*#__PURE__*/React__default.createElement(FaceCaptureGuideInner, null, /*#__PURE__*/React__default.createElement(SelfieCaptureAnimatedMaskWithStatus, {
11797
+ status: status,
11798
+ borderColor: borderColor,
11799
+ borderWidth: borderWidth,
11800
+ borderOpacity: borderOpacity,
11801
+ verticalAlign: "center"
11802
+ })));
11803
+ };
11804
+ var templateObject_1$n, templateObject_2$l;
11805
+
11806
+ var defaultSelfieCaptureModelLoadTimeoutMs = 45000;
11807
+ var detector = null;
11808
+ var detectorSettings = null;
11809
+ function loadFaceDetector() {
11810
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
11811
+ var _a, _b;
11812
+ if (modelAssetPath === void 0) {
11813
+ modelAssetPath = defaultFaceDetectorModelPath;
11814
+ }
11815
+ return __generator(this, function (_c) {
11816
+ switch (_c.label) {
11817
+ case 0:
11818
+ if (detector && (detectorSettings === null || detectorSettings === void 0 ? void 0 : detectorSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, detector];
11819
+ closeFaceDetector();
11820
+ return [4 /*yield*/, preloadFaceDetectorDependencies()];
11821
+ case 1:
11822
+ _c.sent();
11823
+ if (modelCapabilities.delegate === 'NONE') {
11824
+ throw new Error('No available delegate for face detector.');
11825
+ }
11826
+ _b = (_a = FaceDetector).createFromOptions;
11827
+ return [4 /*yield*/, FilesetResolver.forVisionTasks(visionTasksBasePath)];
11828
+ case 2:
11829
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
11830
+ // canvas: document.createElement('canvas'),
11831
+ baseOptions: {
11832
+ modelAssetPath: modelAssetPath,
11833
+ delegate: modelCapabilities.delegate
11834
+ },
11835
+ runningMode: 'VIDEO'
11836
+ }])];
11837
+ case 3:
11838
+ detector = _c.sent();
11839
+ detectorSettings = {
11840
+ modelAssetPath: modelAssetPath
11841
+ };
11842
+ return [2 /*return*/, detector];
11843
+ }
11844
+ });
11845
+ });
11846
+ }
11847
+ function closeFaceDetector() {
11848
+ detector === null || detector === void 0 ? void 0 : detector.close();
11849
+ detector = null;
11850
+ detectorSettings = null;
11851
+ }
11852
+ function useLoadFaceDetector(_a) {
11853
+ var onModelError = _a.onModelError,
11854
+ _b = _a.modelLoadTimeoutMs,
11855
+ modelLoadTimeoutMs = _b === void 0 ? defaultSelfieCaptureModelLoadTimeoutMs : _b,
11856
+ videoRef = _a.videoRef;
11857
+ var _c = useState('not-started'),
11858
+ modelLoadState = _c[0],
11859
+ setModelLoadState = _c[1];
11860
+ var _d = useState(0),
11861
+ modelDownloadProgress = _d[0],
11862
+ setModelDownloadProgress = _d[1];
11863
+ var _e = useState(null),
11864
+ modelWarmingStartedAt = _e[0],
11865
+ setModelWarmingStartedAt = _e[1];
11866
+ var _f = useState(null),
11867
+ modelError = _f[0],
11868
+ setModelError = _f[1];
11869
+ useEffect(function loadModel() {
11870
+ var _this = this;
11871
+ setModelLoadState('downloading');
11872
+ setModelWarmingStartedAt(null);
11873
+ var modelLoadTimeout = setTimeout(function () {
11874
+ setModelError(new Error('Model loading time limit exceeded.'));
11875
+ }, modelLoadTimeoutMs);
11876
+ function handleDownloadProgress(event) {
11877
+ setModelDownloadProgress(progressToPercentage(event.detail));
11878
+ }
11879
+ document.addEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
11880
+ var cancelVideoReady = function cancelVideoReady() {};
11881
+ loadFaceDetector().then(function (model) {
11882
+ return __awaiter(_this, void 0, void 0, function () {
11883
+ var _a, videoReady, cancel, cancelled;
11884
+ return __generator(this, function (_b) {
11885
+ switch (_b.label) {
11886
+ case 0:
11887
+ setModelDownloadProgress(100);
11888
+ clearTimeout(modelLoadTimeout);
11889
+ setModelLoadState('warming');
11890
+ setModelWarmingStartedAt(performance.now());
11891
+ return [4 /*yield*/, testFaceDetectionAgainstKnownImage(model)];
11892
+ case 1:
11893
+ _b.sent();
11894
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
11895
+ cancelled = false;
11896
+ cancelVideoReady = function cancelVideoReady() {
11897
+ cancelled = true;
11898
+ cancel();
11899
+ };
11900
+ return [4 /*yield*/, videoReady];
11901
+ case 2:
11902
+ _b.sent();
11903
+ if (cancelled) return [2 /*return*/];
11904
+ model.detectForVideo(videoRef.current, performance.now());
11905
+ setModelLoadState('ready');
11906
+ return [2 /*return*/];
11907
+ }
11908
+ });
11909
+ });
11910
+ })["catch"](function (e) {
11911
+ setModelError(e);
11912
+ setModelLoadState('error');
11913
+ })["finally"](function () {
11914
+ clearTimeout(modelLoadTimeout);
11915
+ });
11916
+ return function () {
11917
+ log('unloading face detection model');
11918
+ cancelVideoReady();
11919
+ closeFaceDetector();
11920
+ clearTimeout(modelLoadTimeout);
11921
+ document.removeEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
11922
+ };
11923
+ }, [modelLoadTimeoutMs, videoRef]);
11924
+ useEffect(function handleModelError() {
11925
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
11926
+ }, [modelError, onModelError]);
11927
+ return useMemo(function () {
11928
+ return {
11929
+ ready: modelLoadState === 'ready',
11930
+ modelLoadState: modelLoadState,
11931
+ modelDownloadProgress: modelDownloadProgress,
11932
+ modelWarmingStartedAt: modelWarmingStartedAt,
11933
+ modelError: modelError
11934
+ };
11935
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
11936
+ }
11937
+ var lastFaceDetectionAt = 0;
11938
+ var lastFaceDetectionTime = 0;
11939
+ function setLastFaceDetectionAt(time) {
11940
+ lastFaceDetectionTime = time - lastFaceDetectionAt;
11941
+ lastFaceDetectionAt = time;
11942
+ }
11943
+ var framesNeededSamples = [];
11944
+ function trackFramesNeeded(value, bufferLength) {
11945
+ if (bufferLength === void 0) {
11946
+ bufferLength = 25;
11947
+ }
11948
+ framesNeededSamples.unshift(value);
11949
+ if (framesNeededSamples.length > bufferLength) framesNeededSamples.length = bufferLength;
11950
+ }
11951
+ var lastNFaces = [];
11952
+ var lastNFacePairs = [];
11953
+ var lastNNoses = [];
11954
+ var lastNNosePairs = [];
11955
+ function trackFace(face, framesNeeded, frameWidth, frameHeight) {
11956
+ if (framesNeeded === void 0) {
11957
+ framesNeeded = 12;
11958
+ }
11959
+ var nose = face.keypoints[2];
11960
+ if (!nose) return;
11961
+ lastNFaces.unshift(face);
11962
+ lastNNoses.unshift(nose);
11963
+ if (lastNFaces.length > framesNeeded) lastNFaces.length = framesNeeded;
11964
+ if (lastNNoses.length > framesNeeded) lastNNoses.length = framesNeeded;
11965
+ if (lastNFaces.length > 1) {
11966
+ var lastFace = lastNFaces[1];
11967
+ var iou = calculateIoU(face.box, lastFace.box);
11968
+ lastNFacePairs.unshift({
11969
+ a: face,
11970
+ b: lastFace,
11971
+ iou: iou
11972
+ });
11973
+ if (lastNFacePairs.length > framesNeeded - 1) lastNFacePairs.length = framesNeeded - 1;
11974
+ }
11975
+ if (lastNNoses.length > 1) {
11976
+ var lastNose = lastNNoses[1];
11977
+ var noseDistance = Math.sqrt(Math.pow((nose.x - lastNose.x) / frameWidth, 2) + Math.pow((nose.y - lastNose.y) / frameHeight, 2));
11978
+ lastNNosePairs.unshift({
11979
+ a: nose,
11980
+ b: lastNose,
11981
+ distance: noseDistance
11982
+ });
11983
+ if (lastNNosePairs.length > framesNeeded - 1) lastNNosePairs.length = framesNeeded - 1;
11984
+ }
11985
+ }
11986
+ function makeFaceDetectorPrediction(imageData) {
11987
+ if (!detector) return null;
11988
+ var prediction = detector.detectForVideo(imageData, performance.now());
11989
+ var faces = prediction.detections.map(function (d) {
11990
+ return {
11991
+ box: convertBoundingBox(d.boundingBox),
11992
+ keypoints: d.keypoints.map(function (k) {
11993
+ var _a;
11994
+ return _assign(_assign({}, k), {
11995
+ x: k.x * imageData.width,
11996
+ y: k.y * imageData.height,
11997
+ name: (_a = k.label) !== null && _a !== void 0 ? _a : ''
11998
+ });
11999
+ })
11609
12000
  };
11610
- }, [status]);
11611
- return /*#__PURE__*/React__default.createElement(SelfieCaptureAnimatedMask, _assign({}, props, {
11612
- frame: frame,
11613
- status: status
11614
- }));
12001
+ });
12002
+ return _assign(_assign({}, prediction), {
12003
+ faces: faces
12004
+ });
12005
+ }
12006
+ function processFaceDetectorPrediction(_a) {
12007
+ var faces = _a.faces,
12008
+ videoWidth = _a.videoWidth,
12009
+ videoHeight = _a.videoHeight,
12010
+ _b = _a.requireVerticalFaceCentering,
12011
+ requireVerticalFaceCentering = _b === void 0 ? true : _b,
12012
+ _c = _a.stabilityThreshold,
12013
+ stabilityThreshold = _c === void 0 ? 0.7 : _c,
12014
+ _d = _a.noseDistanceThreshold,
12015
+ noseDistanceThreshold = _d === void 0 ? 0.025 : _d,
12016
+ _e = _a.xBoundary,
12017
+ xBoundary = _e === void 0 ? 0.01 : _e,
12018
+ // this represents the edge that the sides of the face box should not cross -- 1% of video width
12019
+ _f = _a.yBoundary,
12020
+ // this represents the edge that the sides of the face box should not cross -- 1% of video width
12021
+ yBoundary = _f === void 0 ? 0.01 : _f,
12022
+ // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
12023
+ _g = _a.xCentroidBoundary,
12024
+ // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
12025
+ xCentroidBoundary = _g === void 0 ? 0.125 : _g,
12026
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
12027
+ _h = _a.yCentroidBoundary,
12028
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
12029
+ yCentroidBoundary = _h === void 0 ? 0.125 : _h,
12030
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
12031
+ _j = _a.foreheadRatio,
12032
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
12033
+ foreheadRatio = _j === void 0 ? 0.275 : _j,
12034
+ // 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.
12035
+ _k = _a.noseTrackingThreshold,
12036
+ // 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.
12037
+ noseTrackingThreshold = _k === void 0 ? 0.2 : _k,
12038
+ // 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
12039
+ minCaptureBrightnessThreshold = _a.minCaptureBrightnessThreshold,
12040
+ minCaptureRangeThreshold = _a.minCaptureRangeThreshold,
12041
+ minCaptureVarianceThreshold = _a.minCaptureVarianceThreshold,
12042
+ brightness = _a.brightness,
12043
+ range = _a.range,
12044
+ variance = _a.variance;
12045
+ var face = faces[0];
12046
+ var faceNotDetected = faces.length === 0;
12047
+ var faceNotCentered = false,
12048
+ faceLookingAway = false,
12049
+ faceTooClose = false,
12050
+ faceTooFar = false,
12051
+ faceVisibilityTooLow = false;
12052
+ var hasAnyThreshold = minCaptureBrightnessThreshold !== undefined || minCaptureRangeThreshold !== undefined || minCaptureVarianceThreshold !== undefined;
12053
+ if (hasAnyThreshold) {
12054
+ var tooDark = minCaptureBrightnessThreshold !== undefined && brightness !== undefined && brightness < minCaptureBrightnessThreshold;
12055
+ var tooLowRange = minCaptureRangeThreshold !== undefined && range !== undefined && range < minCaptureRangeThreshold;
12056
+ var tooLowVariance = minCaptureVarianceThreshold !== undefined && variance !== undefined && variance < minCaptureVarianceThreshold;
12057
+ faceVisibilityTooLow = !!(tooDark || tooLowRange || tooLowVariance);
12058
+ }
12059
+ if (face && !faceVisibilityTooLow) {
12060
+ // calculate frame centroids
12061
+ var frameCX = videoWidth / 2;
12062
+ var frameCY = videoHeight / 2;
12063
+ // calculate head bounding box, with forehead extension
12064
+ var foreheadSize = face.box.height * foreheadRatio;
12065
+ var headXMin = face.box.xMin;
12066
+ var headXMax = face.box.xMax;
12067
+ var headYMin = face.box.yMin - foreheadSize;
12068
+ var headYMax = face.box.yMax;
12069
+ // calculate head centroids
12070
+ var headCX = (headXMin + headXMax) / 2;
12071
+ var headCY = (headYMin + headYMax) / 2;
12072
+ // calculate thresholds
12073
+ var vTX = videoWidth * xBoundary;
12074
+ var vTY = videoHeight * yBoundary;
12075
+ var vCTX = videoWidth * xCentroidBoundary;
12076
+ var vCTY = videoHeight * yCentroidBoundary;
12077
+ var faceNotCenteredHorizontally = Math.abs(frameCX - headCX) > vCTX;
12078
+ var faceNotCenteredVertically = Math.abs(frameCY - headCY) > vCTY;
12079
+ var faceViolatesHorizontalBoundary = headXMin < vTX || headXMax > videoWidth - vTX;
12080
+ var faceViolatesVerticalBoundary = headYMin < vTY || headYMax > videoHeight - vTY;
12081
+ faceNotCentered = faceViolatesHorizontalBoundary || faceViolatesVerticalBoundary || faceNotCenteredHorizontally || requireVerticalFaceCentering && faceNotCenteredVertically;
12082
+ var isMobile = videoWidth < videoHeight;
12083
+ var tooCloseMultiple = 1.5;
12084
+ var tooFarMultiple = isMobile ? 6 : 7;
12085
+ faceTooClose = face.box.width > videoWidth / tooCloseMultiple;
12086
+ faceTooFar = face.box.width < videoWidth / tooFarMultiple;
12087
+ var nose = face.keypoints[2];
12088
+ var fTW = face.box.width * noseTrackingThreshold;
12089
+ var fTH = face.box.height * noseTrackingThreshold;
12090
+ faceLookingAway = !nose || Math.abs(headCX - nose.x) > fTW || Math.abs(headCY - nose.y) > fTH;
12091
+ }
12092
+ var faceInGuides = !faceNotDetected && !faceNotCentered && !faceLookingAway && !faceTooClose && !faceTooFar;
12093
+ if (lastFaceDetectionTime > 0) {
12094
+ trackFramesNeeded(500 / lastFaceDetectionTime);
12095
+ }
12096
+ var faceIsStable = false,
12097
+ noseIsStable = false;
12098
+ if (faceInGuides && !faceVisibilityTooLow) {
12099
+ var framesNeeded = Math.max(Math.ceil(average(framesNeededSamples)), 5);
12100
+ trackFace(face, framesNeeded, videoWidth, videoHeight);
12101
+ faceIsStable = lastNFaces.length >= framesNeeded && !lastNFacePairs.some(function (pair) {
12102
+ return pair.iou < stabilityThreshold;
12103
+ });
12104
+ noseIsStable = lastNNoses.length >= framesNeeded && !lastNNosePairs.some(function (pair) {
12105
+ return pair.distance > noseDistanceThreshold;
12106
+ });
12107
+ }
12108
+ var faceReady = faceInGuides && faceIsStable && noseIsStable && !faceVisibilityTooLow;
12109
+ return {
12110
+ face: face,
12111
+ faceNotDetected: faceNotDetected,
12112
+ faceNotCentered: faceNotCentered,
12113
+ faceLookingAway: faceLookingAway,
12114
+ faceTooClose: faceTooClose,
12115
+ faceTooFar: faceTooFar,
12116
+ faceReady: faceReady,
12117
+ faceReadyAt: faceReady ? new Date() : null,
12118
+ faceIsStable: faceIsStable,
12119
+ noseIsStable: noseIsStable,
12120
+ faceVisibilityTooLow: faceVisibilityTooLow
12121
+ };
12122
+ }
12123
+ function testFaceDetectionAgainstKnownImage(detector) {
12124
+ return new Promise(function (resolve, reject) {
12125
+ var img = new Image();
12126
+ img.crossOrigin = 'anonymous';
12127
+ img.onload = function () {
12128
+ var prediction = detector.detectForVideo(img, performance.now());
12129
+ if (prediction.detections.length > 0) {
12130
+ debug('face detection test result', prediction.detections);
12131
+ resolve(void 0);
12132
+ } else {
12133
+ warn('face detection test failed');
12134
+ reject(new Error('testFaceDetectionAgainstKnownImage failed to predict'));
12135
+ }
12136
+ };
12137
+ img.onerror = function () {
12138
+ return reject(new Error('testFaceDetectionAgainstKnownImage failed to load image'));
12139
+ };
12140
+ img.src = "".concat(DEFAULT_CDN_URL, "/head-test.jpg");
12141
+ });
11615
12142
  }
11616
- var templateObject_1$o, templateObject_2$m, templateObject_3$g;
11617
-
11618
- var FaceCaptureGuideContainer = styled.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"])));
11619
- var FaceCaptureGuideInner = styled.div(templateObject_2$l || (templateObject_2$l = __makeTemplateObject(["\n position: relative;\n height: 60%;\n"], ["\n position: relative;\n height: 60%;\n"])));
11620
- var FaceCaptureGuideOverlay = function FaceCaptureGuideOverlay(_a) {
11621
- var _b = _a.classNames,
11622
- classNames = _b === void 0 ? {} : _b,
11623
- _c = _a.status,
11624
- status = _c === void 0 ? 'ready' : _c,
11625
- _d = _a.borderWidth,
11626
- borderWidth = _d === void 0 ? 5 : _d,
11627
- _e = _a.borderColor,
11628
- borderColor = _e === void 0 ? 'white' : _e,
11629
- _f = _a.borderOpacity,
11630
- borderOpacity = _f === void 0 ? 0.8 : _f;
11631
- return /*#__PURE__*/React__default.createElement(FaceCaptureGuideContainer, {
11632
- className: classNames.container
11633
- }, /*#__PURE__*/React__default.createElement(FaceCaptureGuideInner, null, /*#__PURE__*/React__default.createElement(SelfieCaptureAnimatedMaskWithStatus, {
11634
- status: status,
11635
- borderColor: borderColor,
11636
- borderWidth: borderWidth,
11637
- borderOpacity: borderOpacity,
11638
- verticalAlign: "center"
11639
- })));
11640
- };
11641
- var templateObject_1$n, templateObject_2$l;
11642
12143
 
11643
12144
  function detectBrightnessAndContrast(frame, brightnessAverager) {
11644
12145
  var ctx = frame.getContext('2d');
@@ -12932,7 +13433,7 @@ var SelfieCaptureLoadingOverlayDefault = function SelfieCaptureLoadingOverlayDef
12932
13433
  });
12933
13434
  }, 3000);
12934
13435
  }, []);
12935
- var timeSinceWarmingStarted = modelWarmingStartedAt ? new Date().getTime() - modelWarmingStartedAt : 0;
13436
+ var timeSinceWarmingStarted = modelWarmingStartedAt ? performance.now() - modelWarmingStartedAt : 0;
12936
13437
  var warmingProgress = timeSinceWarmingStarted / 5000.0;
12937
13438
  var _o = useState(false),
12938
13439
  overrideModelsReady = _o[0],
@@ -13785,6 +14286,16 @@ var Container$4 = styled.div(templateObject_1$c || (templateObject_1$c = __makeT
13785
14286
  var AcceptBtn$1 = styled(LoaderButton)(templateObject_2$b || (templateObject_2$b = __makeTemplateObject(["\n margin-left: auto;\n"], ["\n margin-left: auto;\n"])));
13786
14287
  var templateObject_1$c, templateObject_2$b;
13787
14288
 
14289
+ function isBlob(blobPart) {
14290
+ return typeof Blob !== 'undefined' && blobPart instanceof Blob;
14291
+ }
14292
+ function inferBlobType(blobPart) {
14293
+ var _a;
14294
+ if (!isBlob(blobPart)) return undefined;
14295
+ var t = ((_a = blobPart.type) !== null && _a !== void 0 ? _a : '').trim();
14296
+ return t.length > 0 ? t : undefined;
14297
+ }
14298
+
13788
14299
  var videoRecorder = null;
13789
14300
  var audioRecorder = null;
13790
14301
  var videoChunks = [];
@@ -13918,8 +14429,9 @@ var useVideoRecorder = function useVideoRecorder(mergeAVStreams) {
13918
14429
  useVideoRecorderStore.getState().clearRecordedData();
13919
14430
  }, []);
13920
14431
  var processVideo = useCallback(function () {
14432
+ var inferredType = inferBlobType(videoChunks[0]) || (videoRecorder === null || videoRecorder === void 0 ? void 0 : videoRecorder.mimeType) || 'video/mp4';
13921
14433
  var videoBlob = new Blob(videoChunks, {
13922
- type: 'video/mp4'
14434
+ type: inferredType
13923
14435
  });
13924
14436
  useVideoRecorderStore.setState({
13925
14437
  videoUrl: URL.createObjectURL(videoBlob),
@@ -13929,8 +14441,9 @@ var useVideoRecorder = function useVideoRecorder(mergeAVStreams) {
13929
14441
  setVideoRecorder(null);
13930
14442
  }, []);
13931
14443
  var processAudio = useCallback(function () {
14444
+ var inferredType = inferBlobType(audioChunks[0]) || (audioRecorder === null || audioRecorder === void 0 ? void 0 : audioRecorder.mimeType) || 'audio/mp4';
13932
14445
  var audioBlob = new Blob(audioChunks, {
13933
- type: 'audio/mp4'
14446
+ type: inferredType
13934
14447
  });
13935
14448
  useVideoRecorderStore.setState({
13936
14449
  audioUrl: URL.createObjectURL(audioBlob),
@@ -13970,6 +14483,7 @@ var useVideoRecorder = function useVideoRecorder(mergeAVStreams) {
13970
14483
  }, [audioRecordingIntentionallyStopped, audioRecordingStopped, audioUrl, isRecordingAudio, isRecordingVideo, videoRecordingIntentionallyStopped, videoRecordingStopped, videoUrl]);
13971
14484
  };
13972
14485
 
14486
+ var RECORDING_TIMESTAMP_PADDING_MS = 1000;
13973
14487
  var signatureRecorder = null;
13974
14488
  var signatureChunks = [];
13975
14489
  var videoSignatureInitialState = {
@@ -13982,7 +14496,6 @@ var videoSignatureInitialState = {
13982
14496
  clearRecordedData: function clearRecordedData() {
13983
14497
  return null;
13984
14498
  },
13985
- isRecording: false,
13986
14499
  signaturePad: {
13987
14500
  current: null
13988
14501
  },
@@ -14005,7 +14518,7 @@ var useVideoSignatureStore = create()(devtools(function (set, get) {
14005
14518
  if (!camera) throw new Error('Camera not found');
14006
14519
  // set our flag and clear whatever we have recorded so far.
14007
14520
  set({
14008
- isRecording: true
14521
+ recordingStartedAt: performance.now()
14009
14522
  });
14010
14523
  signatureChunks = [];
14011
14524
  // start recording video and audio
@@ -14019,27 +14532,52 @@ var useVideoSignatureStore = create()(devtools(function (set, get) {
14019
14532
  videoBitsPerSecond: 270000,
14020
14533
  audioBitsPerSecond: 32000
14021
14534
  });
14535
+ var hasFirstChunk = false;
14022
14536
  signatureRecorder.ondataavailable = function (event) {
14023
14537
  signatureChunks.push(event.data);
14538
+ if (!hasFirstChunk) {
14539
+ hasFirstChunk = true;
14540
+ set({
14541
+ firstChunkReceivedAt: performance.now(),
14542
+ lastChunkReceivedAt: performance.now()
14543
+ });
14544
+ } else {
14545
+ set({
14546
+ lastChunkReceivedAt: performance.now()
14547
+ });
14548
+ }
14024
14549
  };
14025
14550
  signatureRecorder.start(100);
14026
14551
  },
14027
14552
  stopRecording: function stopRecording(signatureData, imageUrl) {
14028
14553
  set({
14029
- isRecording: false
14554
+ firstChunkReceivedAt: undefined,
14555
+ recordingStoppedAt: performance.now()
14556
+ });
14557
+ waitForOneMoreChunk().then(function () {
14558
+ if (!signatureRecorder) return;
14559
+ signatureRecorder.stop();
14560
+ signatureRecorder.onstop = function () {
14561
+ var inferredType = inferBlobType(signatureChunks[0]) || (signatureRecorder === null || signatureRecorder === void 0 ? void 0 : signatureRecorder.mimeType) || 'video/mp4';
14562
+ var blob = new Blob(signatureChunks, {
14563
+ type: inferredType
14564
+ });
14565
+ signatureChunks = [];
14566
+ signatureRecorder = null;
14567
+ if (!signatureData) return;
14568
+ var _a = get(),
14569
+ onSignatureVideoCaptured = _a.onSignatureVideoCaptured,
14570
+ recordingStartedAt = _a.recordingStartedAt,
14571
+ signatureStartedAt = _a.signatureStartedAt,
14572
+ signatureEndedAt = _a.signatureEndedAt,
14573
+ lastChunkReceivedAt = _a.lastChunkReceivedAt;
14574
+ var endMs = Math.min(signatureEndedAt !== null && signatureEndedAt !== void 0 ? signatureEndedAt : Infinity, lastChunkReceivedAt !== null && lastChunkReceivedAt !== void 0 ? lastChunkReceivedAt : Infinity);
14575
+ var signatureStartTimestamp = signatureStartedAt && recordingStartedAt ? formatTimestamp(Math.max(0, signatureStartedAt - recordingStartedAt - RECORDING_TIMESTAMP_PADDING_MS)) : undefined;
14576
+ var signatureEndTimestamp = endMs !== Infinity && recordingStartedAt ? formatTimestamp(Math.min(endMs - recordingStartedAt + RECORDING_TIMESTAMP_PADDING_MS, lastChunkReceivedAt !== null && lastChunkReceivedAt !== void 0 ? lastChunkReceivedAt : Infinity)) : undefined;
14577
+ onSignatureVideoCaptured(blob, signatureData, imageUrl !== null && imageUrl !== void 0 ? imageUrl : null, signatureStartTimestamp, signatureEndTimestamp);
14578
+ };
14579
+ useVideoRecorderStore.getState().stopRecording();
14030
14580
  });
14031
- if (!signatureRecorder) return;
14032
- signatureRecorder.stop();
14033
- signatureRecorder.onstop = function () {
14034
- var blob = new Blob(signatureChunks, {
14035
- type: 'video/mp4'
14036
- });
14037
- signatureChunks = [];
14038
- signatureRecorder = null;
14039
- if (!signatureData) return;
14040
- get().onSignatureVideoCaptured(blob, signatureData, imageUrl !== null && imageUrl !== void 0 ? imageUrl : null);
14041
- };
14042
- useVideoRecorderStore.getState().stopRecording();
14043
14581
  },
14044
14582
  clearRecordedData: function clearRecordedData() {
14045
14583
  signatureChunks = [];
@@ -14048,13 +14586,42 @@ var useVideoSignatureStore = create()(devtools(function (set, get) {
14048
14586
  signatureRecorder === null || signatureRecorder === void 0 ? void 0 : signatureRecorder.stop();
14049
14587
  signatureRecorder = null;
14050
14588
  set({
14051
- isRecording: false,
14589
+ recordingStartedAt: undefined,
14590
+ recordingStoppedAt: undefined,
14591
+ firstChunkReceivedAt: undefined,
14592
+ lastChunkReceivedAt: undefined,
14052
14593
  signaturePadEmpty: true,
14053
- signatureValid: false
14594
+ signatureValid: false,
14595
+ signatureStartedAt: undefined,
14596
+ signatureEndedAt: undefined
14054
14597
  });
14055
14598
  }
14056
14599
  });
14057
14600
  }));
14601
+ function waitForOneMoreChunk(timeoutMs) {
14602
+ if (timeoutMs === void 0) {
14603
+ timeoutMs = 3000;
14604
+ }
14605
+ var start = performance.now();
14606
+ return new Promise(function (resolve) {
14607
+ var initialLastChunkReceivedAt = useVideoSignatureStore.getState().lastChunkReceivedAt;
14608
+ if (!initialLastChunkReceivedAt) return resolve();
14609
+ function gotAChunk() {
14610
+ var lastChunkReceivedAt = useVideoSignatureStore.getState().lastChunkReceivedAt;
14611
+ return performance.now() - start > timeoutMs || !lastChunkReceivedAt || !initialLastChunkReceivedAt || lastChunkReceivedAt > initialLastChunkReceivedAt;
14612
+ }
14613
+ setTimeout(function () {
14614
+ if (gotAChunk()) return resolve(); // check immediately
14615
+ // otherwise, check every 100ms
14616
+ var interval = setInterval(function () {
14617
+ if (gotAChunk()) {
14618
+ clearInterval(interval);
14619
+ resolve();
14620
+ }
14621
+ }, 100);
14622
+ }, 0);
14623
+ });
14624
+ }
14058
14625
  function VideoSignatureContextProvider(_a) {
14059
14626
  var _this = this;
14060
14627
  var _b, _c;
@@ -14073,7 +14640,14 @@ function VideoSignatureContextProvider(_a) {
14073
14640
  // clear recorded data when the component is mounted
14074
14641
  useVideoSignatureStore.getState().clearRecordedData();
14075
14642
  }, []);
14076
- var isRecording = useVideoSignatureStore().isRecording;
14643
+ var _e = useVideoSignatureStore(useShallow(function (state) {
14644
+ return {
14645
+ recordingStartedAt: state.recordingStartedAt,
14646
+ recordingStoppedAt: state.recordingStoppedAt
14647
+ };
14648
+ })),
14649
+ recordingStartedAt = _e.recordingStartedAt,
14650
+ recordingStoppedAt = _e.recordingStoppedAt;
14077
14651
  useFrameLoop(useCallback(function () {
14078
14652
  return __awaiter(_this, void 0, void 0, function () {
14079
14653
  var signaturePad, ctx, _a, w, h, isPortrait, rect;
@@ -14100,7 +14674,7 @@ function VideoSignatureContextProvider(_a) {
14100
14674
  });
14101
14675
  });
14102
14676
  }, [videoRef]), {
14103
- autoStart: isRecording,
14677
+ autoStart: !!recordingStartedAt && !recordingStoppedAt,
14104
14678
  throttleMs: 1000 / 24
14105
14679
  });
14106
14680
  return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, children, /*#__PURE__*/React__default.createElement(InvisibleCanvas, {
@@ -14109,6 +14683,17 @@ function VideoSignatureContextProvider(_a) {
14109
14683
  height: (_c = videoRef.current) === null || _c === void 0 ? void 0 : _c.videoHeight
14110
14684
  }));
14111
14685
  }
14686
+ function formatTimestamp(durationMs) {
14687
+ // should be in the format of 00:00:00:00 (hh:mm:ss:cs)
14688
+ var hours = Math.floor(durationMs / 3600000);
14689
+ var minutes = Math.floor(durationMs % 3600000 / 60000);
14690
+ var seconds = Math.floor(durationMs % 60000 / 1000);
14691
+ var milliseconds = durationMs % 1000;
14692
+ // Convert milliseconds to centiseconds (1/100th of a second)
14693
+ var centiseconds = Math.floor(milliseconds / 10);
14694
+ var csString = centiseconds.toString().padStart(2, '0');
14695
+ return "".concat(hours.toString().padStart(2, '0'), ":") + "".concat(minutes.toString().padStart(2, '0'), ":") + "".concat(seconds.toString().padStart(2, '0'), ":") + "".concat(csString);
14696
+ }
14112
14697
 
14113
14698
  function VideoSignaturePad(_a) {
14114
14699
  var onAcceptBtnClicked = _a.onAcceptBtnClicked,
@@ -14170,8 +14755,11 @@ function VideoSignaturePad(_a) {
14170
14755
  ref: signaturePad,
14171
14756
  canvasProps: canvasProps,
14172
14757
  onBegin: function onBegin() {
14173
- return useVideoSignatureStore.setState({
14174
- signaturePadEmpty: false
14758
+ return useVideoSignatureStore.setState(function (s) {
14759
+ return {
14760
+ signaturePadEmpty: false,
14761
+ signatureStartedAt: s.signatureStartedAt || performance.now()
14762
+ };
14175
14763
  });
14176
14764
  },
14177
14765
  onEnd: function onEnd() {
@@ -14181,7 +14769,8 @@ function VideoSignaturePad(_a) {
14181
14769
  return point;
14182
14770
  });
14183
14771
  useVideoSignatureStore.setState({
14184
- signatureValid: points.length >= minSignaturePadPoints
14772
+ signatureValid: points.length >= minSignaturePadPoints,
14773
+ signatureEndedAt: performance.now()
14185
14774
  });
14186
14775
  }
14187
14776
  }), !headTrackingSatisfied && !!verbiage.headTrackingUnsatisfiedText ? ( /*#__PURE__*/React__default.createElement(SignaturePadContentContainer, {
@@ -14248,6 +14837,12 @@ function VideoSignatureGuides(_a) {
14248
14837
  useEffect(function () {
14249
14838
  if (guideToDisplay) setMode(guideToDisplay);
14250
14839
  }, [guideToDisplay]);
14840
+ var firstChunkReceivedAt = useVideoSignatureStore(useShallow(function (state) {
14841
+ return {
14842
+ firstChunkReceivedAt: state.firstChunkReceivedAt
14843
+ };
14844
+ })).firstChunkReceivedAt;
14845
+ var signaturePadDisabled = requestedAction !== 'CAPTURE_SIGNATURE' || !firstChunkReceivedAt;
14251
14846
  return /*#__PURE__*/React__default.createElement(Container$3, {
14252
14847
  className: classNames.container
14253
14848
  }, /*#__PURE__*/React__default.createElement(Inner$1, {
@@ -14271,7 +14866,7 @@ function VideoSignatureGuides(_a) {
14271
14866
  }, /*#__PURE__*/React__default.createElement(VideoSignaturePad, {
14272
14867
  onAcceptBtnClicked: onAcceptBtnClicked,
14273
14868
  onClearBtnClicked: onClearBtnClicked,
14274
- disabled: requestedAction !== 'CAPTURE_SIGNATURE',
14869
+ disabled: signaturePadDisabled,
14275
14870
  headTrackingSatisfied: headTrackingSatisfied,
14276
14871
  minSignaturePadPoints: minSignaturePadPoints,
14277
14872
  classNames: classNames,
@@ -14328,9 +14923,11 @@ var VideoSignatureCapture = function VideoSignatureCapture(_a) {
14328
14923
  onHeadTrackingPredictionMade = _o.onPredictionMade,
14329
14924
  startHeadTracking = _o.start,
14330
14925
  stopHeadTracking = _o.stop;
14331
- var _p = useVideoSignatureStore(),
14332
- clearRecordedData = _p.clearRecordedData,
14333
- isRecording = _p.isRecording;
14926
+ var firstChunkReceivedAt = useVideoSignatureStore(useShallow(function (state) {
14927
+ return {
14928
+ firstChunkReceivedAt: state.firstChunkReceivedAt
14929
+ };
14930
+ })).firstChunkReceivedAt;
14334
14931
  useEffect(function () {
14335
14932
  useVideoSignatureStore.setState({
14336
14933
  onSignatureVideoCaptured: onSignatureVideoCaptured
@@ -14349,15 +14946,15 @@ var VideoSignatureCapture = function VideoSignatureCapture(_a) {
14349
14946
  var verbiage = useTranslations(rawVerbiage, {
14350
14947
  guidanceMessageText: 'Please sign the box below'
14351
14948
  });
14352
- var _q = useState(true),
14353
- headTrackingSatisfied = _q[0],
14354
- setHeadTrackingSatisfied = _q[1];
14355
- var _r = useState(null),
14356
- lastFace = _r[0],
14357
- setLastFace = _r[1];
14358
- var _s = useState(0),
14359
- numFramesWithoutFaces = _s[0],
14360
- setNumFramesWithoutFaces = _s[1];
14949
+ var _p = useState(true),
14950
+ headTrackingSatisfied = _p[0],
14951
+ setHeadTrackingSatisfied = _p[1];
14952
+ var _q = useState(null),
14953
+ lastFace = _q[0],
14954
+ setLastFace = _q[1];
14955
+ var _r = useState(0),
14956
+ numFramesWithoutFaces = _r[0],
14957
+ setNumFramesWithoutFaces = _r[1];
14361
14958
  onHeadTrackingPredictionMade(useThrottledCallback(useCallback(function (_a) {
14362
14959
  var face = _a.face;
14363
14960
  if (headTrackingDisabled) return;
@@ -14372,12 +14969,12 @@ var VideoSignatureCapture = function VideoSignatureCapture(_a) {
14372
14969
  return n + 1;
14373
14970
  });
14374
14971
  }, [headTrackingBoundaryPercentage, headTrackingBoundaryType, headTrackingDisabled, videoHeight, videoWidth]), 16));
14375
- var _t = useResizeObserver(),
14376
- ref = _t.ref,
14377
- _u = _t.width,
14378
- width = _u === void 0 ? 1 : _u,
14379
- _v = _t.height,
14380
- height = _v === void 0 ? 1 : _v;
14972
+ var _s = useResizeObserver(),
14973
+ ref = _s.ref,
14974
+ _t = _s.width,
14975
+ width = _t === void 0 ? 1 : _t,
14976
+ _u = _s.height,
14977
+ height = _u === void 0 ? 1 : _u;
14381
14978
  var debugScalingDetails = useDebugScalingDetails({
14382
14979
  enabled: debugMode,
14383
14980
  pageWidth: width,
@@ -14408,13 +15005,19 @@ var VideoSignatureCapture = function VideoSignatureCapture(_a) {
14408
15005
  classNames: classNames.guides,
14409
15006
  verbiage: rawVerbiage.guides,
14410
15007
  onClearBtnClicked: restartVideoOnSignaturePadCleared ? function () {
14411
- return setTimeout(clearRecordedData, 100);
14412
- } : undefined
15008
+ return setTimeout(function () {
15009
+ return useVideoSignatureStore.getState().clearRecordedData();
15010
+ }, 100);
15011
+ } : function () {
15012
+ return useVideoSignatureStore.setState({
15013
+ signatureStartedAt: undefined
15014
+ });
15015
+ }
14413
15016
  }), debugMode && ( /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement(ObjectDetectionDebugOverlayDiv, null, lastFace && ( /*#__PURE__*/React__default.createElement(SelfieCaptureFaceDebugBox, {
14414
15017
  face: lastFace,
14415
15018
  scaling: debugScalingDetails,
14416
15019
  color: headTrackingSatisfied ? 'green' : 'red'
14417
- }))), /*#__PURE__*/React__default.createElement(DebugStatsPane, null, "Video: ", videoWidth, "x", videoHeight, /*#__PURE__*/React__default.createElement("br", null), "Recording: ", isRecording ? 'true' : 'false'))), /*#__PURE__*/React__default.createElement(ExitCaptureButton, {
15020
+ }))), /*#__PURE__*/React__default.createElement(DebugStatsPane, null, "Video: ", videoWidth, "x", videoHeight, /*#__PURE__*/React__default.createElement("br", null), "Recording: ", firstChunkReceivedAt ? 'true' : 'false'))), /*#__PURE__*/React__default.createElement(ExitCaptureButton, {
14418
15021
  onClick: onExit,
14419
15022
  className: classNames.exitCaptureBtn
14420
15023
  }));
@@ -14745,6 +15348,8 @@ var VideoSignatureWizard = function VideoSignatureWizard(_a) {
14745
15348
  setSelfieImage = _u.setSelfieImage,
14746
15349
  setSignatureData = _u.setSignatureData,
14747
15350
  setSignatureVideoUrl = _u.setSignatureVideoUrl,
15351
+ setSignatureStartTimestamp = _u.setSignatureStartTimestamp,
15352
+ setSignatureEndTimestamp = _u.setSignatureEndTimestamp,
14748
15353
  logSelfieCaptureAttempt = _u.logSelfieCaptureAttempt,
14749
15354
  uploadDocument = _u.uploadDocument;
14750
15355
  var cameraAccessDenied = useCameraStore(useShallow(function (state) {
@@ -14804,12 +15409,14 @@ var VideoSignatureWizard = function VideoSignatureWizard(_a) {
14804
15409
  filetype: 'image/jpeg'
14805
15410
  }).then(onSelfieCaptured);
14806
15411
  }, [logCaptureMetadata, onSelfieCaptured, setSelfieImage, uploadDocument]);
14807
- var onSignatureCaptureCompleted = useCallback(function (videoData, signatureData, signatureImageData) {
15412
+ var onSignatureCaptureCompleted = useCallback(function (videoData, signatureData, signatureImageData, signatureStartTimestamp, signatureEndTimestamp) {
14808
15413
  setSignatureData(signatureData);
14809
15414
  setSignatureVideoUrl(URL.createObjectURL(videoData));
15415
+ if (signatureStartTimestamp) setSignatureStartTimestamp(signatureStartTimestamp);
15416
+ if (signatureEndTimestamp) setSignatureEndTimestamp(signatureEndTimestamp);
14810
15417
  setCaptureState('SUCCESS');
14811
- onVideoCaptured === null || onVideoCaptured === void 0 ? void 0 : onVideoCaptured(videoData, signatureData, signatureImageData);
14812
- }, [onVideoCaptured, setSignatureData, setSignatureVideoUrl]);
15418
+ onVideoCaptured === null || onVideoCaptured === void 0 ? void 0 : onVideoCaptured(videoData, signatureData, signatureImageData, signatureStartTimestamp, signatureEndTimestamp);
15419
+ }, [onVideoCaptured, setSignatureData, setSignatureEndTimestamp, setSignatureStartTimestamp, setSignatureVideoUrl]);
14813
15420
  var _x = useState(true),
14814
15421
  showLoadingOverlay = _x[0],
14815
15422
  setShowLoadingOverlay = _x[1];
@@ -14978,6 +15585,7 @@ function VideoSignatureWizardGuides(_a) {
14978
15585
  var onClearBtnClicked = useCallback(function () {
14979
15586
  var _a, _b;
14980
15587
  useVideoSignatureStore.setState({
15588
+ signatureStartedAt: undefined,
14981
15589
  signaturePadEmpty: true,
14982
15590
  signatureValid: false
14983
15591
  });