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
@@ -211,7 +211,7 @@
211
211
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
212
212
  };
213
213
 
214
- var webSdkVersion = '2.3.88';
214
+ var webSdkVersion = '2.3.90';
215
215
 
216
216
  function getPlatform() {
217
217
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -472,27 +472,27 @@
472
472
  if (!portalLocation) return element;
473
473
  return /*#__PURE__*/reactDom.createPortal(element, portalLocation);
474
474
  };
475
- 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) {
475
+ 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) {
476
476
  var _a, _b, _c, _d, _e, _f;
477
477
  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';
478
478
  }, function (props) {
479
479
  var _a, _b, _c, _d, _e, _f;
480
480
  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';
481
481
  });
482
- var templateObject_1$P, templateObject_2$I;
482
+ var templateObject_1$P, templateObject_2$J;
483
483
 
484
484
  var wavesAnimation = styled.keyframes(templateObject_1$O || (templateObject_1$O = __makeTemplateObject(["\n 0% {\n opacity: 0;\n transform: scale3d(1, 1, 1);\n }\n 80% {\n opacity: 1;\n }\n 100% {\n transform: scale3d(2, 2, 1);\n opacity: 0;\n }\n"], ["\n 0% {\n opacity: 0;\n transform: scale3d(1, 1, 1);\n }\n 80% {\n opacity: 1;\n }\n 100% {\n transform: scale3d(2, 2, 1);\n opacity: 0;\n }\n"])));
485
- var progressBarAnimation = styled.keyframes(templateObject_2$H || (templateObject_2$H = __makeTemplateObject(["\n 0% {\n width: 0;\n }\n 100% {\n width: 100%;\n }\n"], ["\n 0% {\n width: 0;\n }\n 100% {\n width: 100%;\n }\n"])));
485
+ var progressBarAnimation = styled.keyframes(templateObject_2$I || (templateObject_2$I = __makeTemplateObject(["\n 0% {\n width: 0;\n }\n 100% {\n width: 100%;\n }\n"], ["\n 0% {\n width: 0;\n }\n 100% {\n width: 100%;\n }\n"])));
486
486
  var dualRingSpinnerAnimation = styled.keyframes(templateObject_3$u || (templateObject_3$u = __makeTemplateObject(["\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n"], ["\n 0% {\n transform: rotate(0deg);\n }\n 100% {\n transform: rotate(360deg);\n }\n"])));
487
487
  var progressBorderAnimation = styled.keyframes(templateObject_4$o || (templateObject_4$o = __makeTemplateObject(["\n to {\n stroke-dashoffset: 0;\n }\n"], ["\n to {\n stroke-dashoffset: 0;\n }\n"])));
488
- var templateObject_1$O, templateObject_2$H, templateObject_3$u, templateObject_4$o;
488
+ var templateObject_1$O, templateObject_2$I, templateObject_3$u, templateObject_4$o;
489
489
 
490
490
  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) {
491
491
  return props.theme.background ? "".concat(props.theme.background) : "white";
492
492
  }, function (props) {
493
493
  return props.theme.textColor ? "color: ".concat(props.theme.textColor, ";") : "";
494
494
  });
495
- 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) {
495
+ 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) {
496
496
  var _a;
497
497
  return (_a = props.theme.textAlign) !== null && _a !== void 0 ? _a : 'center';
498
498
  }, function (props) {
@@ -540,7 +540,7 @@
540
540
  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"])));
541
541
  var LoadingOverlayCustomLoadingGraphic = styled.img(templateObject_21 || (templateObject_21 = __makeTemplateObject(["\n transform-style: preserve-3d;\n"], ["\n transform-style: preserve-3d;\n"])));
542
542
  var LoadingOverlayContinueButtonContainer = styled.div(templateObject_22 || (templateObject_22 = __makeTemplateObject(["\n display: flex;\n"], ["\n display: flex;\n"])));
543
- 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;
543
+ 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;
544
544
 
545
545
  function _extends() {
546
546
  return _extends = Object.assign ? Object.assign.bind() : function (n) {
@@ -2083,6 +2083,11 @@
2083
2083
  idFrontImage: null,
2084
2084
  idBackImage: null,
2085
2085
  passportImage: null,
2086
+ idFrontIrImage: null,
2087
+ idBackIrImage: null,
2088
+ idFrontUvImage: null,
2089
+ idBackUvImage: null,
2090
+ idBarcodeImage: null,
2086
2091
  selfieImage: null,
2087
2092
  signatureData: null,
2088
2093
  signatureVideoUrl: null,
@@ -2113,6 +2118,9 @@
2113
2118
  setIdBackUvImage: function setIdBackUvImage() {
2114
2119
  return null;
2115
2120
  },
2121
+ setIdBarcodeImage: function setIdBarcodeImage() {
2122
+ return null;
2123
+ },
2116
2124
  setSelfieImage: function setSelfieImage() {
2117
2125
  return null;
2118
2126
  },
@@ -2125,6 +2133,12 @@
2125
2133
  setIdCaptureVideoUrl: function setIdCaptureVideoUrl() {
2126
2134
  return null;
2127
2135
  },
2136
+ setSignatureStartTimestamp: function setSignatureStartTimestamp() {
2137
+ return null;
2138
+ },
2139
+ setSignatureEndTimestamp: function setSignatureEndTimestamp() {
2140
+ return null;
2141
+ },
2128
2142
  setIdCaptureVideoIdFrontImage: function setIdCaptureVideoIdFrontImage() {
2129
2143
  return null;
2130
2144
  },
@@ -2280,53 +2294,62 @@
2280
2294
  passportImage = _13[0],
2281
2295
  setPassportImage = _13[1];
2282
2296
  var _14 = React.useState(null),
2283
- selfieImage = _14[0],
2284
- setSelfieImage = _14[1];
2297
+ idBarcodeImage = _14[0],
2298
+ setIdBarcodeImage = _14[1];
2285
2299
  var _15 = React.useState(null),
2286
- signatureData = _15[0],
2287
- setSignatureData = _15[1];
2300
+ selfieImage = _15[0],
2301
+ setSelfieImage = _15[1];
2288
2302
  var _16 = React.useState(null),
2289
- signatureVideoUrl = _16[0],
2290
- setSignatureVideoUrl = _16[1];
2303
+ signatureData = _16[0],
2304
+ setSignatureData = _16[1];
2291
2305
  var _17 = React.useState(null),
2292
- idCaptureVideoUrl = _17[0],
2293
- setIdCaptureVideoUrl = _17[1];
2306
+ signatureVideoUrl = _17[0],
2307
+ setSignatureVideoUrl = _17[1];
2294
2308
  var _18 = React.useState(null),
2295
- idCaptureVideoIdFrontImage = _18[0],
2296
- setIdCaptureVideoIdFrontImage = _18[1];
2309
+ signatureStartTimestamp = _18[0],
2310
+ setSignatureStartTimestamp = _18[1];
2297
2311
  var _19 = React.useState(null),
2298
- idCaptureVideoIdBackImage = _19[0],
2299
- setIdCaptureVideoIdBackImage = _19[1];
2312
+ signatureEndTimestamp = _19[0],
2313
+ setSignatureEndTimestamp = _19[1];
2300
2314
  var _20 = React.useState(null),
2301
- idCaptureVideoAudioUrl = _20[0],
2302
- setIdCaptureVideoAudioUrl = _20[1];
2315
+ idCaptureVideoUrl = _20[0],
2316
+ setIdCaptureVideoUrl = _20[1];
2303
2317
  var _21 = React.useState(null),
2304
- idCaptureVideoAudioStartsAt = _21[0],
2305
- setIdCaptureVideoAudioStartsAt = _21[1];
2318
+ idCaptureVideoIdFrontImage = _21[0],
2319
+ setIdCaptureVideoIdFrontImage = _21[1];
2306
2320
  var _22 = React.useState(null),
2307
- expectedAudioText = _22[0],
2308
- setExpectedAudioText = _22[1];
2321
+ idCaptureVideoIdBackImage = _22[0],
2322
+ setIdCaptureVideoIdBackImage = _22[1];
2309
2323
  var _23 = React.useState(null),
2310
- additionalDocuments = _23[0],
2311
- setAdditionalDocuments = _23[1];
2324
+ idCaptureVideoAudioUrl = _23[0],
2325
+ setIdCaptureVideoAudioUrl = _23[1];
2312
2326
  var _24 = React.useState(null),
2313
- geolocationResult = _24[0],
2314
- setGeolocationResult = _24[1];
2315
- var _25 = React.useState(0),
2316
- geolocationAttempts = _25[0],
2317
- setGeolocationAttempts = _25[1];
2318
- var _26 = React.useState(false),
2319
- geolocationBlocked = _26[0],
2320
- setGeolocationBlocked = _26[1];
2321
- var _27 = React.useState([]),
2322
- idFrontCaptureAttempts = _27[0],
2323
- setIdFrontCaptureAttempts = _27[1];
2324
- var _28 = React.useState([]),
2325
- idBackCaptureAttempts = _28[0],
2326
- setIdBackCaptureAttempts = _28[1];
2327
- var _29 = React.useState([]),
2328
- selfieCaptureAttempts = _29[0],
2329
- setSelfieCaptureAttempts = _29[1];
2327
+ idCaptureVideoAudioStartsAt = _24[0],
2328
+ setIdCaptureVideoAudioStartsAt = _24[1];
2329
+ var _25 = React.useState(null),
2330
+ expectedAudioText = _25[0],
2331
+ setExpectedAudioText = _25[1];
2332
+ var _26 = React.useState(null),
2333
+ additionalDocuments = _26[0],
2334
+ setAdditionalDocuments = _26[1];
2335
+ var _27 = React.useState(null),
2336
+ geolocationResult = _27[0],
2337
+ setGeolocationResult = _27[1];
2338
+ var _28 = React.useState(0),
2339
+ geolocationAttempts = _28[0],
2340
+ setGeolocationAttempts = _28[1];
2341
+ var _29 = React.useState(false),
2342
+ geolocationBlocked = _29[0],
2343
+ setGeolocationBlocked = _29[1];
2344
+ var _30 = React.useState([]),
2345
+ idFrontCaptureAttempts = _30[0],
2346
+ setIdFrontCaptureAttempts = _30[1];
2347
+ var _31 = React.useState([]),
2348
+ idBackCaptureAttempts = _31[0],
2349
+ setIdBackCaptureAttempts = _31[1];
2350
+ var _32 = React.useState([]),
2351
+ selfieCaptureAttempts = _32[0],
2352
+ setSelfieCaptureAttempts = _32[1];
2330
2353
  var logIdFrontCaptureAttempt = React.useCallback(function (attempt) {
2331
2354
  setIdFrontCaptureAttempts(function (attempts) {
2332
2355
  return __spreadArray(__spreadArray([], attempts, true), [attempt], false);
@@ -2452,6 +2475,7 @@
2452
2475
  idFrontImage: idFrontImage,
2453
2476
  idBackImage: idBackImage,
2454
2477
  passportImage: passportImage,
2478
+ idBarcodeImage: idBarcodeImage,
2455
2479
  selfieImage: selfieImage
2456
2480
  };
2457
2481
  _a = signatureVideoUrl;
@@ -2557,6 +2581,9 @@
2557
2581
  if (documents.passportImage) {
2558
2582
  submissionRequest.customerData.idData.idImageFront = documents.passportImage;
2559
2583
  }
2584
+ if (documents.idBarcodeImage) {
2585
+ submissionRequest.customerData.idData.idBarcodeImage = documents.idBarcodeImage;
2586
+ }
2560
2587
  if (documents.idFrontIrImage) {
2561
2588
  submissionRequest.customerData.idData.idFrontIrImage = documents.idFrontIrImage;
2562
2589
  }
@@ -2603,6 +2630,12 @@
2603
2630
  submissionRequest.customerData.signatureData.signatureVideo = documents.signatureVideo;
2604
2631
  }
2605
2632
  }
2633
+ if (signatureStartTimestamp) {
2634
+ submissionRequest.customerData.signatureStartTimestamp = signatureStartTimestamp;
2635
+ }
2636
+ if (signatureEndTimestamp) {
2637
+ submissionRequest.customerData.signatureEndTimestamp = signatureEndTimestamp;
2638
+ }
2606
2639
  if (additionalDocuments) {
2607
2640
  submissionRequest.customerData.additionalDocuments = additionalDocuments.map(function (d) {
2608
2641
  return _assign(_assign({}, d), {
@@ -2645,7 +2678,7 @@
2645
2678
  }
2646
2679
  });
2647
2680
  });
2648
- }, [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]);
2681
+ }, [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]);
2649
2682
  var defaultOnSubmit = React.useCallback(function () {
2650
2683
  return __awaiter(void 0, void 0, void 0, function () {
2651
2684
  var submissionResponse_1, payload, host, endpoint, response, statusMessage, submissionResponse_2, e_1, err;
@@ -2923,6 +2956,7 @@
2923
2956
  idFrontUvImage: idFrontUvImage,
2924
2957
  idBackUvImage: idBackUvImage,
2925
2958
  passportImage: passportImage,
2959
+ idBarcodeImage: idBarcodeImage,
2926
2960
  selfieImage: selfieImage,
2927
2961
  signatureData: signatureData,
2928
2962
  signatureVideoUrl: signatureVideoUrl,
@@ -2939,9 +2973,12 @@
2939
2973
  setIdBackIrImage: setIdBackIrImage,
2940
2974
  setIdFrontUvImage: setIdFrontUvImage,
2941
2975
  setIdBackUvImage: setIdBackUvImage,
2976
+ setIdBarcodeImage: setIdBarcodeImage,
2942
2977
  setSelfieImage: setSelfieImage,
2943
2978
  setSignatureData: setSignatureData,
2944
2979
  setSignatureVideoUrl: setSignatureVideoUrl,
2980
+ setSignatureStartTimestamp: setSignatureStartTimestamp,
2981
+ setSignatureEndTimestamp: setSignatureEndTimestamp,
2945
2982
  setIdCaptureVideoUrl: setIdCaptureVideoUrl,
2946
2983
  setIdCaptureVideoIdFrontImage: setIdCaptureVideoIdFrontImage,
2947
2984
  setIdCaptureVideoIdBackImage: setIdCaptureVideoIdBackImage,
@@ -2957,7 +2994,7 @@
2957
2994
  checkLiveness: checkLiveness,
2958
2995
  retryLocationAccess: retryLocationAccess
2959
2996
  };
2960
- }, [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]);
2997
+ }, [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]);
2961
2998
  return /*#__PURE__*/React.createElement(SubmissionContext.Provider, {
2962
2999
  value: value
2963
3000
  }, geolocationRequired && geolocationBlocked ? ( /*#__PURE__*/React.createElement(GeolocationAccessDeniedOverlay, null)) : children, submissionError && ( /*#__PURE__*/React.createElement(SubmissionErrorOverlay, {
@@ -8075,97 +8112,6 @@
8075
8112
  });
8076
8113
  }
8077
8114
 
8078
- function getFrameDimensions(frame) {
8079
- var frameWidth = frame.width,
8080
- frameHeight = frame.height;
8081
- if (frame instanceof HTMLImageElement) {
8082
- frameWidth = frame.naturalWidth;
8083
- frameHeight = frame.naturalHeight;
8084
- }
8085
- if (frame instanceof HTMLVideoElement) {
8086
- frameWidth = frame.videoWidth;
8087
- frameHeight = frame.videoHeight;
8088
- }
8089
- return [frameWidth, frameHeight];
8090
- }
8091
-
8092
- var InvisibleCanvas = styled.canvas(templateObject_1$M || (templateObject_1$M = __makeTemplateObject(["\n display: none;\n"], ["\n display: none;\n"])));
8093
- function drawToCanvas(canvas, frame, width, height) {
8094
- if (!canvas) return;
8095
- var ctx = canvas.getContext('2d');
8096
- if (!ctx) return;
8097
- if (!width || !height) {
8098
- var _a = getFrameDimensions(frame),
8099
- frameWidth = _a[0],
8100
- frameHeight = _a[1];
8101
- width || (width = frameWidth);
8102
- height || (height = frameHeight);
8103
- }
8104
- canvas.width = width;
8105
- canvas.height = height;
8106
- ctx.drawImage(frame, 0, 0, width, height);
8107
- }
8108
- function clearCanvas(canvas) {
8109
- var _a;
8110
- (_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);
8111
- }
8112
- var templateObject_1$M;
8113
-
8114
- function cropToShoulders(rawCanvas, cropCanvas, resizeCanvas, frame, face, quality, maxHeight) {
8115
- var _a;
8116
- if (quality === void 0) {
8117
- quality = 0.92;
8118
- }
8119
- if (!rawCanvas || !cropCanvas || !resizeCanvas) return '';
8120
- var rawCtx = rawCanvas.getContext('2d');
8121
- var cropCtx = cropCanvas.getContext('2d');
8122
- var resizeCtx = resizeCanvas.getContext('2d');
8123
- if (!rawCtx || !cropCtx || !resizeCtx) throw new Error('could not get 2d context');
8124
- rawCanvas.width = frame.width;
8125
- rawCanvas.height = frame.height;
8126
- rawCtx.putImageData(frame, 0, 0);
8127
- if (frame.height > frame.width) {
8128
- cropCanvas.width = frame.width;
8129
- cropCanvas.height = frame.height;
8130
- cropCtx.drawImage(rawCanvas, 0, 0, cropCanvas.width, cropCanvas.height);
8131
- } else {
8132
- var _b = (_a = face === null || face === void 0 ? void 0 : face.box) !== null && _a !== void 0 ? _a : {
8133
- xMin: 0,
8134
- width: frame.width
8135
- },
8136
- xMin = _b.xMin,
8137
- width = _b.width;
8138
- var desiredWidth = frame.height * 0.6;
8139
- var faceCenterX = xMin + width / 2;
8140
- var xPos = Math.max(0, faceCenterX - desiredWidth / 2);
8141
- cropCanvas.width = desiredWidth;
8142
- cropCanvas.height = frame.height;
8143
- cropCtx.drawImage(rawCanvas, xPos, 0, cropCanvas.width, cropCanvas.height, 0, 0, cropCanvas.width, cropCanvas.height);
8144
- }
8145
- resizeCanvas.height = maxHeight !== null && maxHeight !== void 0 ? maxHeight : cropCanvas.height;
8146
- resizeCanvas.width = cropCanvas.width * (resizeCanvas.height / cropCanvas.height);
8147
- resizeCtx === null || resizeCtx === void 0 ? void 0 : resizeCtx.drawImage(cropCanvas, 0, 0, resizeCanvas.width, resizeCanvas.height);
8148
- var dataURL = resizeCanvas.toDataURL('image/jpeg', quality);
8149
- log('cropToShoulders size', new TextEncoder().encode(dataURL).length);
8150
- clearCanvas(rawCanvas);
8151
- clearCanvas(cropCanvas);
8152
- clearCanvas(resizeCanvas);
8153
- return dataURL;
8154
- }
8155
- function cropToDetectedObjectBox(frame, box, canvas) {
8156
- canvas || (canvas = document.createElement('canvas'));
8157
- var ctx = canvas.getContext('2d');
8158
- if (!ctx) throw new Error('could not get 2d context');
8159
- var xMin = box.xMin,
8160
- yMin = box.yMin,
8161
- width = box.width,
8162
- height = box.height;
8163
- canvas.width = width;
8164
- canvas.height = height;
8165
- ctx.drawImage(frame, xMin, yMin, width, height, 0, 0, width, height);
8166
- return canvas;
8167
- }
8168
-
8169
8115
  var defaultImageSegmenterModelPath = 'https://websdk-cdn-dev.idmission.com/assets/models/selfiesegmenter20240524/selfie_segmenter.tflite';
8170
8116
  var imageSegmenterModelSizeInBytes = 256440.32;
8171
8117
  // 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
@@ -8295,6 +8241,192 @@
8295
8241
  });
8296
8242
  }
8297
8243
 
8244
+ var DEFAULT_CDN_URL = 'https://websdk-cdn-dev.idmission.com/assets';
8245
+
8246
+ var defaultDocumentDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/DocumentDetector/DocumentDetector-20250815_115859.tflite");
8247
+
8248
+ var defaultFocusModelPath = "".concat(DEFAULT_CDN_URL, "/models/Focus/Focus-20241008_102708.tflite");
8249
+
8250
+ var defaultFaceDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/FaceDetector/FaceDetector-20250820_154546.tflite");
8251
+
8252
+ var defaultBarcodeReadabilityModelPath = "".concat(DEFAULT_CDN_URL, "/models/BarcodeReadability/BarcodeReadability-20250815_120417.tflite");
8253
+
8254
+ var defaultModelPaths = {
8255
+ documentDetector: defaultDocumentDetectorModelPath,
8256
+ focus: defaultFocusModelPath,
8257
+ faceDetection: defaultFaceDetectorModelPath,
8258
+ barcodeReadability: defaultBarcodeReadabilityModelPath
8259
+ };
8260
+
8261
+ var preloadModels = function preloadModels(_a) {
8262
+ return __awaiter(void 0, [_a], void 0, function (_b) {
8263
+ var preloadTasks;
8264
+ var _c = _b.documentDetectionModel,
8265
+ documentDetectionModel = _c === void 0 ? true : _c,
8266
+ _d = _b.focusModel,
8267
+ focusModel = _d === void 0 ? true : _d,
8268
+ _e = _b.faceDetectionModel,
8269
+ faceDetectionModel = _e === void 0 ? true : _e,
8270
+ _f = _b.barcodeReadabilityModel,
8271
+ barcodeReadabilityModel = _f === void 0 ? true : _f;
8272
+ return __generator(this, function (_g) {
8273
+ switch (_g.label) {
8274
+ case 0:
8275
+ return [4 /*yield*/, probeModelCapabilities()];
8276
+ case 1:
8277
+ _g.sent();
8278
+ preloadTasks = [];
8279
+ if (documentDetectionModel) {
8280
+ preloadTasks.push(preloadDocumentDetectorDependencies);
8281
+ }
8282
+ if (focusModel) {
8283
+ preloadTasks.push(preloadFocusModelDependencies);
8284
+ }
8285
+ if (faceDetectionModel) {
8286
+ preloadTasks.push(preloadFaceDetectorDependencies);
8287
+ }
8288
+ if (barcodeReadabilityModel) {
8289
+ preloadTasks.push(preloadBarcodeReadabilityModelDependencies);
8290
+ }
8291
+ return [4 /*yield*/, Promise.all(preloadTasks)];
8292
+ case 2:
8293
+ _g.sent();
8294
+ return [2 /*return*/];
8295
+ }
8296
+ });
8297
+ });
8298
+ };
8299
+ var progressByUrl = {};
8300
+ var progressByUseCase = {
8301
+ visionRuntime: {
8302
+ loaded: 0,
8303
+ total: 0
8304
+ },
8305
+ documentDetector: {
8306
+ loaded: 0,
8307
+ total: 0
8308
+ },
8309
+ focus: {
8310
+ loaded: 0,
8311
+ total: 0
8312
+ },
8313
+ faceDetection: {
8314
+ loaded: 0,
8315
+ total: 0
8316
+ },
8317
+ barcodeReadability: {
8318
+ loaded: 0,
8319
+ total: 0
8320
+ }
8321
+ };
8322
+ function preloadDependency(url) {
8323
+ return __awaiter(this, void 0, void 0, function () {
8324
+ return __generator(this, function (_a) {
8325
+ return [2 /*return*/, new Promise(function (resolve, reject) {
8326
+ var req = new XMLHttpRequest();
8327
+ req.addEventListener('progress', function (event) {
8328
+ if (!event.lengthComputable) return;
8329
+ progressByUrl[url] = event;
8330
+ document.dispatchEvent(new CustomEvent('idmission.preloadProgress', {
8331
+ detail: {
8332
+ url: url,
8333
+ loaded: event.loaded,
8334
+ total: event.total
8335
+ }
8336
+ }));
8337
+ });
8338
+ req.addEventListener('loadend', function () {
8339
+ resolve(req.readyState === 4 && req.status === 200);
8340
+ });
8341
+ req.addEventListener('error', reject);
8342
+ req.open('GET', url, true);
8343
+ req.send();
8344
+ })];
8345
+ });
8346
+ });
8347
+ }
8348
+ var modelsPreloading = {
8349
+ documentDetector: false,
8350
+ focus: false,
8351
+ faceDetection: false,
8352
+ barcodeReadability: false
8353
+ };
8354
+ var preloadDocumentDetectorDependencies = function preloadDocumentDetectorDependencies() {
8355
+ return preloadModelDependencies('documentDetector');
8356
+ };
8357
+ var preloadFocusModelDependencies = function preloadFocusModelDependencies() {
8358
+ return preloadModelDependencies('focus');
8359
+ };
8360
+ var preloadFaceDetectorDependencies = function preloadFaceDetectorDependencies() {
8361
+ return preloadModelDependencies('faceDetection');
8362
+ };
8363
+ var preloadBarcodeReadabilityModelDependencies = function preloadBarcodeReadabilityModelDependencies() {
8364
+ return preloadModelDependencies('barcodeReadability');
8365
+ };
8366
+ function preloadModelDependencies(model) {
8367
+ return __awaiter(this, void 0, void 0, function () {
8368
+ function handleModelDownloadProgress(event) {
8369
+ var detail = event.detail;
8370
+ if (!dependencies.includes(detail.url)) return;
8371
+ progressByUseCase[model] = sumUpProgressForDependencies(dependencies);
8372
+ document.dispatchEvent(new CustomEvent("idmission.preloadProgress.".concat(model), {
8373
+ detail: progressByUseCase[model]
8374
+ }));
8375
+ }
8376
+ var dependencies;
8377
+ return __generator(this, function (_a) {
8378
+ switch (_a.label) {
8379
+ case 0:
8380
+ if (modelsPreloading[model]) return [2 /*return*/, new Promise(function (resolve) {
8381
+ var i = setInterval(function () {
8382
+ if (!modelsPreloading[model]) {
8383
+ clearInterval(i);
8384
+ resolve();
8385
+ }
8386
+ }, 100);
8387
+ })];
8388
+ modelsPreloading[model] = true;
8389
+ return [4 /*yield*/, probeModelCapabilities()];
8390
+ case 1:
8391
+ _a.sent();
8392
+ if (modelCapabilities.delegate === 'NONE') {
8393
+ throw new Error("No available delegate for ".concat(model, " model."));
8394
+ }
8395
+ dependencies = [defaultModelPaths[model]];
8396
+ document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
8397
+ _a.label = 2;
8398
+ case 2:
8399
+ _a.trys.push([2,, 4, 5]);
8400
+ return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
8401
+ case 3:
8402
+ _a.sent();
8403
+ return [3 /*break*/, 5];
8404
+ case 4:
8405
+ document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
8406
+ modelsPreloading[model] = false;
8407
+ return [7 /*endfinally*/];
8408
+ case 5:
8409
+ return [2 /*return*/];
8410
+ }
8411
+ });
8412
+ });
8413
+ }
8414
+ function progressToPercentage(progress) {
8415
+ return progress.total > 0 ? Math.round(100.0 * progress.loaded / progress.total) : 0;
8416
+ }
8417
+ function sumUpProgressForDependencies(dependencies) {
8418
+ return dependencies.reduce(function (result, dependency) {
8419
+ var dependencyProgress = progressByUrl[dependency];
8420
+ if (!dependencyProgress) return result;
8421
+ result.loaded += dependencyProgress.loaded;
8422
+ result.total += dependencyProgress.total;
8423
+ return result;
8424
+ }, {
8425
+ loaded: 0,
8426
+ total: 0
8427
+ });
8428
+ }
8429
+
8298
8430
  function convertBoundingBox(box) {
8299
8431
  var _a, _b, _c, _d, _e, _f, _g, _h;
8300
8432
  return {
@@ -8349,785 +8481,6 @@
8349
8481
  return sum / len;
8350
8482
  }
8351
8483
 
8352
- var DEFAULT_CDN_URL = 'https://websdk-cdn-dev.idmission.com/assets';
8353
-
8354
- var defaultDocumentDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/DocumentDetector/DocumentDetector-20250815_115859.tflite");
8355
-
8356
- var defaultFocusModelPath = "".concat(DEFAULT_CDN_URL, "/models/Focus/Focus-20241008_102708.tflite");
8357
-
8358
- var defaultFaceDetectorModelPath = "".concat(DEFAULT_CDN_URL, "/models/FaceDetector/FaceDetector-20250820_154546.tflite");
8359
-
8360
- var defaultFocusModelLoadTimeoutMs = 45000;
8361
- var defaultFocusThresholds = {
8362
- idCardFront: {
8363
- desktop: 0,
8364
- mobile: 0.3
8365
- },
8366
- idCardBack: {
8367
- desktop: 0,
8368
- mobile: 0.3
8369
- },
8370
- passport: {
8371
- desktop: 0,
8372
- mobile: 0.3
8373
- },
8374
- singlePage: {
8375
- desktop: 0,
8376
- mobile: 0.3
8377
- }
8378
- };
8379
- var classifier = null;
8380
- var classifierSettings = null;
8381
- function loadFocusModel() {
8382
- return __awaiter(this, arguments, void 0, function (modelAssetPath) {
8383
- var _a, _b;
8384
- if (modelAssetPath === void 0) {
8385
- modelAssetPath = defaultFocusModelPath;
8386
- }
8387
- return __generator(this, function (_c) {
8388
- switch (_c.label) {
8389
- case 0:
8390
- if (classifier && (classifierSettings === null || classifierSettings === void 0 ? void 0 : classifierSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier];
8391
- closeFocusModel();
8392
- return [4 /*yield*/, preloadFocusModelDependencies()];
8393
- case 1:
8394
- _c.sent();
8395
- if (modelCapabilities.delegate === 'NONE') {
8396
- throw new Error('No available delegate for focus detector.');
8397
- }
8398
- _b = (_a = Ua).createFromOptions;
8399
- return [4 /*yield*/, ao.forVisionTasks(visionTasksBasePath)];
8400
- case 2:
8401
- return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
8402
- baseOptions: {
8403
- modelAssetPath: modelAssetPath,
8404
- delegate: modelCapabilities.delegate
8405
- },
8406
- // canvas: document.createElement('canvas'),
8407
- runningMode: 'VIDEO'
8408
- }])];
8409
- case 3:
8410
- classifier = _c.sent();
8411
- classifierSettings = {
8412
- modelAssetPath: modelAssetPath
8413
- };
8414
- return [2 /*return*/, classifier];
8415
- }
8416
- });
8417
- });
8418
- }
8419
- function closeFocusModel() {
8420
- classifier === null || classifier === void 0 ? void 0 : classifier.close();
8421
- classifier = null;
8422
- classifierSettings = null;
8423
- }
8424
- function useLoadFocusModel(_a) {
8425
- var _b = _a.modelPath,
8426
- modelPath = _b === void 0 ? defaultFocusModelPath : _b,
8427
- _c = _a.modelLoadTimeoutMs,
8428
- modelLoadTimeoutMs = _c === void 0 ? defaultFocusModelLoadTimeoutMs : _c,
8429
- onModelError = _a.onModelError,
8430
- videoRef = _a.videoRef,
8431
- _d = _a.shouldLoadModels,
8432
- shouldLoadModels = _d === void 0 ? true : _d;
8433
- var _e = React.useState('not-started'),
8434
- modelLoadState = _e[0],
8435
- setModelLoadState = _e[1];
8436
- var _f = React.useState(0),
8437
- modelDownloadProgress = _f[0],
8438
- setModelDownloadProgress = _f[1];
8439
- var _g = React.useState(null),
8440
- modelWarmingStartedAt = _g[0],
8441
- setModelWarmingStartedAt = _g[1];
8442
- var _h = React.useState(null),
8443
- modelError = _h[0],
8444
- setModelError = _h[1];
8445
- React.useEffect(function loadModel() {
8446
- var _this = this;
8447
- if (!shouldLoadModels) return;
8448
- setModelLoadState('downloading');
8449
- setModelWarmingStartedAt(null);
8450
- function handleDownloadProgress(event) {
8451
- setModelDownloadProgress(progressToPercentage(event.detail));
8452
- }
8453
- document.addEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
8454
- var modelLoadTimeout = setTimeout(function () {
8455
- setModelError(new Error('Model loading time limit exceeded.'));
8456
- }, modelLoadTimeoutMs);
8457
- var cancelVideoReady = function cancelVideoReady() {};
8458
- loadFocusModel(modelPath).then(function (loadedModel) {
8459
- return __awaiter(_this, void 0, void 0, function () {
8460
- var _a, videoReady, cancel, cancelled;
8461
- return __generator(this, function (_b) {
8462
- switch (_b.label) {
8463
- case 0:
8464
- setModelDownloadProgress(100);
8465
- clearTimeout(modelLoadTimeout);
8466
- setModelLoadState('warming');
8467
- setModelWarmingStartedAt(new Date().getTime());
8468
- _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
8469
- cancelled = false;
8470
- cancelVideoReady = function cancelVideoReady() {
8471
- cancelled = true;
8472
- cancel();
8473
- };
8474
- return [4 /*yield*/, videoReady];
8475
- case 1:
8476
- _b.sent();
8477
- setTimeout(function () {
8478
- if (cancelled) return;
8479
- loadedModel.classifyForVideo(videoRef.current, performance.now());
8480
- setModelLoadState('ready');
8481
- }, 500);
8482
- return [2 /*return*/];
8483
- }
8484
- });
8485
- });
8486
- })["catch"](function (e) {
8487
- setModelError(e);
8488
- setModelLoadState('error');
8489
- })["finally"](function () {
8490
- clearTimeout(modelLoadTimeout);
8491
- });
8492
- return function () {
8493
- log('unloading focus model');
8494
- cancelVideoReady();
8495
- closeFocusModel();
8496
- clearTimeout(modelLoadTimeout);
8497
- document.removeEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
8498
- };
8499
- }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
8500
- React.useEffect(function handleModelError() {
8501
- if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
8502
- }, [modelError, onModelError]);
8503
- return React.useMemo(function () {
8504
- return {
8505
- ready: modelLoadState === 'ready',
8506
- modelLoadState: modelLoadState,
8507
- modelDownloadProgress: modelDownloadProgress,
8508
- modelWarmingStartedAt: modelWarmingStartedAt,
8509
- modelError: modelError
8510
- };
8511
- }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
8512
- }
8513
- var lastFocusPredictionAt = 0;
8514
- var lastFocusPredictionTime = 0;
8515
- function setLastFocusPredictionAt(time) {
8516
- lastFocusPredictionTime = time - lastFocusPredictionAt;
8517
- lastFocusPredictionAt = time;
8518
- }
8519
- function makeFocusModelPrediction(imageData, cropCanvas, rotateCanvas, box) {
8520
- var _a, _b, _c, _d, _e;
8521
- if (!classifier) return null;
8522
- var startedAt = new Date();
8523
- var image = cropIfNecessary(imageData, cropCanvas, rotateCanvas, box);
8524
- var result = classifier.classifyForVideo(image, performance.now());
8525
- 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) {
8526
- return c.categoryName === 'focused';
8527
- })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
8528
- var predictionTime = new Date().getTime() - startedAt.getTime();
8529
- return {
8530
- score: score,
8531
- predictionTime: predictionTime
8532
- };
8533
- }
8534
- function cropIfNecessary(imageData, cropCanvas, rotateCanvas, box) {
8535
- if (!box) return imageData;
8536
- var cropped = cropToDetectedObjectBox(imageData, box, cropCanvas);
8537
- var _a = [box.width, box.height],
8538
- bw = _a[0],
8539
- bh = _a[1];
8540
- if (bh <= bw) return cropped;
8541
- var ctx = rotateCanvas.getContext('2d');
8542
- if (!ctx) return cropped;
8543
- rotateCanvas.width = bh;
8544
- rotateCanvas.height = bw;
8545
- ctx.clearRect(0, 0, rotateCanvas.width, rotateCanvas.height);
8546
- ctx.translate(rotateCanvas.width / 2, rotateCanvas.height / 2);
8547
- ctx.rotate(1.5708); // 90 deg in radians
8548
- ctx.drawImage(cropped, -bw / 2, -bh / 2);
8549
- return rotateCanvas;
8550
- }
8551
-
8552
- var defaultSelfieCaptureModelLoadTimeoutMs = 45000;
8553
- var detector$1 = null;
8554
- var detectorSettings$1 = null;
8555
- function loadFaceDetector() {
8556
- return __awaiter(this, arguments, void 0, function (modelAssetPath) {
8557
- var _a, _b;
8558
- if (modelAssetPath === void 0) {
8559
- modelAssetPath = defaultFaceDetectorModelPath;
8560
- }
8561
- return __generator(this, function (_c) {
8562
- switch (_c.label) {
8563
- case 0:
8564
- if (detector$1 && (detectorSettings$1 === null || detectorSettings$1 === void 0 ? void 0 : detectorSettings$1.modelAssetPath) === modelAssetPath) return [2 /*return*/, detector$1];
8565
- closeFaceDetector();
8566
- return [4 /*yield*/, preloadFaceDetectorDependencies()];
8567
- case 1:
8568
- _c.sent();
8569
- if (modelCapabilities.delegate === 'NONE') {
8570
- throw new Error('No available delegate for face detector.');
8571
- }
8572
- _b = (_a = ya).createFromOptions;
8573
- return [4 /*yield*/, ao.forVisionTasks(visionTasksBasePath)];
8574
- case 2:
8575
- return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
8576
- // canvas: document.createElement('canvas'),
8577
- baseOptions: {
8578
- modelAssetPath: modelAssetPath,
8579
- delegate: modelCapabilities.delegate
8580
- },
8581
- runningMode: 'VIDEO'
8582
- }])];
8583
- case 3:
8584
- detector$1 = _c.sent();
8585
- detectorSettings$1 = {
8586
- modelAssetPath: modelAssetPath
8587
- };
8588
- return [2 /*return*/, detector$1];
8589
- }
8590
- });
8591
- });
8592
- }
8593
- function closeFaceDetector() {
8594
- detector$1 === null || detector$1 === void 0 ? void 0 : detector$1.close();
8595
- detector$1 = null;
8596
- detectorSettings$1 = null;
8597
- }
8598
- function useLoadFaceDetector(_a) {
8599
- var onModelError = _a.onModelError,
8600
- _b = _a.modelLoadTimeoutMs,
8601
- modelLoadTimeoutMs = _b === void 0 ? defaultSelfieCaptureModelLoadTimeoutMs : _b,
8602
- videoRef = _a.videoRef;
8603
- var _c = React.useState('not-started'),
8604
- modelLoadState = _c[0],
8605
- setModelLoadState = _c[1];
8606
- var _d = React.useState(0),
8607
- modelDownloadProgress = _d[0],
8608
- setModelDownloadProgress = _d[1];
8609
- var _e = React.useState(null),
8610
- modelWarmingStartedAt = _e[0],
8611
- setModelWarmingStartedAt = _e[1];
8612
- var _f = React.useState(null),
8613
- modelError = _f[0],
8614
- setModelError = _f[1];
8615
- React.useEffect(function loadModel() {
8616
- var _this = this;
8617
- setModelLoadState('downloading');
8618
- setModelWarmingStartedAt(null);
8619
- var modelLoadTimeout = setTimeout(function () {
8620
- setModelError(new Error('Model loading time limit exceeded.'));
8621
- }, modelLoadTimeoutMs);
8622
- function handleDownloadProgress(event) {
8623
- setModelDownloadProgress(progressToPercentage(event.detail));
8624
- }
8625
- document.addEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
8626
- var cancelVideoReady = function cancelVideoReady() {};
8627
- loadFaceDetector().then(function (model) {
8628
- return __awaiter(_this, void 0, void 0, function () {
8629
- var _a, videoReady, cancel, cancelled;
8630
- return __generator(this, function (_b) {
8631
- switch (_b.label) {
8632
- case 0:
8633
- setModelDownloadProgress(100);
8634
- clearTimeout(modelLoadTimeout);
8635
- setModelLoadState('warming');
8636
- setModelWarmingStartedAt(new Date().getTime());
8637
- return [4 /*yield*/, testFaceDetectionAgainstKnownImage(model)];
8638
- case 1:
8639
- _b.sent();
8640
- _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
8641
- cancelled = false;
8642
- cancelVideoReady = function cancelVideoReady() {
8643
- cancelled = true;
8644
- cancel();
8645
- };
8646
- return [4 /*yield*/, videoReady];
8647
- case 2:
8648
- _b.sent();
8649
- if (cancelled) return [2 /*return*/];
8650
- model.detectForVideo(videoRef.current, performance.now());
8651
- setModelLoadState('ready');
8652
- return [2 /*return*/];
8653
- }
8654
- });
8655
- });
8656
- })["catch"](function (e) {
8657
- setModelError(e);
8658
- setModelLoadState('error');
8659
- })["finally"](function () {
8660
- clearTimeout(modelLoadTimeout);
8661
- });
8662
- return function () {
8663
- log('unloading face detection model');
8664
- cancelVideoReady();
8665
- closeFaceDetector();
8666
- clearTimeout(modelLoadTimeout);
8667
- document.removeEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
8668
- };
8669
- }, [modelLoadTimeoutMs, videoRef]);
8670
- React.useEffect(function handleModelError() {
8671
- if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
8672
- }, [modelError, onModelError]);
8673
- return React.useMemo(function () {
8674
- return {
8675
- ready: modelLoadState === 'ready',
8676
- modelLoadState: modelLoadState,
8677
- modelDownloadProgress: modelDownloadProgress,
8678
- modelWarmingStartedAt: modelWarmingStartedAt,
8679
- modelError: modelError
8680
- };
8681
- }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
8682
- }
8683
- var lastFaceDetectionAt = 0;
8684
- var lastFaceDetectionTime = 0;
8685
- function setLastFaceDetectionAt(time) {
8686
- lastFaceDetectionTime = time - lastFaceDetectionAt;
8687
- lastFaceDetectionAt = time;
8688
- }
8689
- var framesNeededSamples$1 = [];
8690
- function trackFramesNeeded$1(value, bufferLength) {
8691
- if (bufferLength === void 0) {
8692
- bufferLength = 25;
8693
- }
8694
- framesNeededSamples$1.unshift(value);
8695
- if (framesNeededSamples$1.length > bufferLength) framesNeededSamples$1.length = bufferLength;
8696
- }
8697
- var lastNFaces = [];
8698
- var lastNFacePairs = [];
8699
- var lastNNoses = [];
8700
- var lastNNosePairs = [];
8701
- function trackFace(face, framesNeeded, frameWidth, frameHeight) {
8702
- if (framesNeeded === void 0) {
8703
- framesNeeded = 12;
8704
- }
8705
- var nose = face.keypoints[2];
8706
- if (!nose) return;
8707
- lastNFaces.unshift(face);
8708
- lastNNoses.unshift(nose);
8709
- if (lastNFaces.length > framesNeeded) lastNFaces.length = framesNeeded;
8710
- if (lastNNoses.length > framesNeeded) lastNNoses.length = framesNeeded;
8711
- if (lastNFaces.length > 1) {
8712
- var lastFace = lastNFaces[1];
8713
- var iou = calculateIoU(face.box, lastFace.box);
8714
- lastNFacePairs.unshift({
8715
- a: face,
8716
- b: lastFace,
8717
- iou: iou
8718
- });
8719
- if (lastNFacePairs.length > framesNeeded - 1) lastNFacePairs.length = framesNeeded - 1;
8720
- }
8721
- if (lastNNoses.length > 1) {
8722
- var lastNose = lastNNoses[1];
8723
- var noseDistance = Math.sqrt(Math.pow((nose.x - lastNose.x) / frameWidth, 2) + Math.pow((nose.y - lastNose.y) / frameHeight, 2));
8724
- lastNNosePairs.unshift({
8725
- a: nose,
8726
- b: lastNose,
8727
- distance: noseDistance
8728
- });
8729
- if (lastNNosePairs.length > framesNeeded - 1) lastNNosePairs.length = framesNeeded - 1;
8730
- }
8731
- }
8732
- function makeFaceDetectorPrediction(imageData) {
8733
- if (!detector$1) return null;
8734
- var prediction = detector$1.detectForVideo(imageData, performance.now());
8735
- var faces = prediction.detections.map(function (d) {
8736
- return {
8737
- box: convertBoundingBox(d.boundingBox),
8738
- keypoints: d.keypoints.map(function (k) {
8739
- var _a;
8740
- return _assign(_assign({}, k), {
8741
- x: k.x * imageData.width,
8742
- y: k.y * imageData.height,
8743
- name: (_a = k.label) !== null && _a !== void 0 ? _a : ''
8744
- });
8745
- })
8746
- };
8747
- });
8748
- return _assign(_assign({}, prediction), {
8749
- faces: faces
8750
- });
8751
- }
8752
- function processFaceDetectorPrediction(_a) {
8753
- var faces = _a.faces,
8754
- videoWidth = _a.videoWidth,
8755
- videoHeight = _a.videoHeight,
8756
- _b = _a.requireVerticalFaceCentering,
8757
- requireVerticalFaceCentering = _b === void 0 ? true : _b,
8758
- _c = _a.stabilityThreshold,
8759
- stabilityThreshold = _c === void 0 ? 0.7 : _c,
8760
- _d = _a.noseDistanceThreshold,
8761
- noseDistanceThreshold = _d === void 0 ? 0.025 : _d,
8762
- _e = _a.xBoundary,
8763
- xBoundary = _e === void 0 ? 0.01 : _e,
8764
- // this represents the edge that the sides of the face box should not cross -- 1% of video width
8765
- _f = _a.yBoundary,
8766
- // this represents the edge that the sides of the face box should not cross -- 1% of video width
8767
- yBoundary = _f === void 0 ? 0.01 : _f,
8768
- // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
8769
- _g = _a.xCentroidBoundary,
8770
- // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
8771
- xCentroidBoundary = _g === void 0 ? 0.125 : _g,
8772
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
8773
- _h = _a.yCentroidBoundary,
8774
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
8775
- yCentroidBoundary = _h === void 0 ? 0.125 : _h,
8776
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
8777
- _j = _a.foreheadRatio,
8778
- // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
8779
- foreheadRatio = _j === void 0 ? 0.275 : _j,
8780
- // 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.
8781
- _k = _a.noseTrackingThreshold,
8782
- // 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.
8783
- noseTrackingThreshold = _k === void 0 ? 0.2 : _k,
8784
- // 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
8785
- minCaptureBrightnessThreshold = _a.minCaptureBrightnessThreshold,
8786
- minCaptureRangeThreshold = _a.minCaptureRangeThreshold,
8787
- minCaptureVarianceThreshold = _a.minCaptureVarianceThreshold,
8788
- brightness = _a.brightness,
8789
- range = _a.range,
8790
- variance = _a.variance;
8791
- var face = faces[0];
8792
- var faceNotDetected = faces.length === 0;
8793
- var faceNotCentered = false,
8794
- faceLookingAway = false,
8795
- faceTooClose = false,
8796
- faceTooFar = false,
8797
- faceVisibilityTooLow = false;
8798
- var hasAnyThreshold = minCaptureBrightnessThreshold !== undefined || minCaptureRangeThreshold !== undefined || minCaptureVarianceThreshold !== undefined;
8799
- if (hasAnyThreshold) {
8800
- var tooDark = minCaptureBrightnessThreshold !== undefined && brightness !== undefined && brightness < minCaptureBrightnessThreshold;
8801
- var tooLowRange = minCaptureRangeThreshold !== undefined && range !== undefined && range < minCaptureRangeThreshold;
8802
- var tooLowVariance = minCaptureVarianceThreshold !== undefined && variance !== undefined && variance < minCaptureVarianceThreshold;
8803
- faceVisibilityTooLow = !!(tooDark || tooLowRange || tooLowVariance);
8804
- }
8805
- if (face && !faceVisibilityTooLow) {
8806
- // calculate frame centroids
8807
- var frameCX = videoWidth / 2;
8808
- var frameCY = videoHeight / 2;
8809
- // calculate head bounding box, with forehead extension
8810
- var foreheadSize = face.box.height * foreheadRatio;
8811
- var headXMin = face.box.xMin;
8812
- var headXMax = face.box.xMax;
8813
- var headYMin = face.box.yMin - foreheadSize;
8814
- var headYMax = face.box.yMax;
8815
- // calculate head centroids
8816
- var headCX = (headXMin + headXMax) / 2;
8817
- var headCY = (headYMin + headYMax) / 2;
8818
- // calculate thresholds
8819
- var vTX = videoWidth * xBoundary;
8820
- var vTY = videoHeight * yBoundary;
8821
- var vCTX = videoWidth * xCentroidBoundary;
8822
- var vCTY = videoHeight * yCentroidBoundary;
8823
- var faceNotCenteredHorizontally = Math.abs(frameCX - headCX) > vCTX;
8824
- var faceNotCenteredVertically = Math.abs(frameCY - headCY) > vCTY;
8825
- var faceViolatesHorizontalBoundary = headXMin < vTX || headXMax > videoWidth - vTX;
8826
- var faceViolatesVerticalBoundary = headYMin < vTY || headYMax > videoHeight - vTY;
8827
- faceNotCentered = faceViolatesHorizontalBoundary || faceViolatesVerticalBoundary || faceNotCenteredHorizontally || requireVerticalFaceCentering && faceNotCenteredVertically;
8828
- var isMobile = videoWidth < videoHeight;
8829
- var tooCloseMultiple = 1.5;
8830
- var tooFarMultiple = isMobile ? 6 : 7;
8831
- faceTooClose = face.box.width > videoWidth / tooCloseMultiple;
8832
- faceTooFar = face.box.width < videoWidth / tooFarMultiple;
8833
- var nose = face.keypoints[2];
8834
- var fTW = face.box.width * noseTrackingThreshold;
8835
- var fTH = face.box.height * noseTrackingThreshold;
8836
- faceLookingAway = !nose || Math.abs(headCX - nose.x) > fTW || Math.abs(headCY - nose.y) > fTH;
8837
- }
8838
- var faceInGuides = !faceNotDetected && !faceNotCentered && !faceLookingAway && !faceTooClose && !faceTooFar;
8839
- if (lastFaceDetectionTime > 0) {
8840
- trackFramesNeeded$1(500 / lastFaceDetectionTime);
8841
- }
8842
- var faceIsStable = false,
8843
- noseIsStable = false;
8844
- if (faceInGuides && !faceVisibilityTooLow) {
8845
- var framesNeeded = Math.max(Math.ceil(average(framesNeededSamples$1)), 5);
8846
- trackFace(face, framesNeeded, videoWidth, videoHeight);
8847
- faceIsStable = lastNFaces.length >= framesNeeded && !lastNFacePairs.some(function (pair) {
8848
- return pair.iou < stabilityThreshold;
8849
- });
8850
- noseIsStable = lastNNoses.length >= framesNeeded && !lastNNosePairs.some(function (pair) {
8851
- return pair.distance > noseDistanceThreshold;
8852
- });
8853
- }
8854
- var faceReady = faceInGuides && faceIsStable && noseIsStable && !faceVisibilityTooLow;
8855
- return {
8856
- face: face,
8857
- faceNotDetected: faceNotDetected,
8858
- faceNotCentered: faceNotCentered,
8859
- faceLookingAway: faceLookingAway,
8860
- faceTooClose: faceTooClose,
8861
- faceTooFar: faceTooFar,
8862
- faceReady: faceReady,
8863
- faceReadyAt: faceReady ? new Date() : null,
8864
- faceIsStable: faceIsStable,
8865
- noseIsStable: noseIsStable,
8866
- faceVisibilityTooLow: faceVisibilityTooLow
8867
- };
8868
- }
8869
- function testFaceDetectionAgainstKnownImage(detector) {
8870
- return new Promise(function (resolve, reject) {
8871
- var img = new Image();
8872
- img.crossOrigin = 'anonymous';
8873
- img.onload = function () {
8874
- var prediction = detector.detectForVideo(img, performance.now());
8875
- if (prediction.detections.length > 0) {
8876
- debug('face detection test result', prediction.detections);
8877
- resolve(void 0);
8878
- } else {
8879
- warn('face detection test failed');
8880
- reject(new Error('testFaceDetectionAgainstKnownImage failed to predict'));
8881
- }
8882
- };
8883
- img.onerror = function () {
8884
- return reject(new Error('testFaceDetectionAgainstKnownImage failed to load image'));
8885
- };
8886
- img.src = "".concat(DEFAULT_CDN_URL, "/head-test.jpg");
8887
- });
8888
- }
8889
-
8890
- var preloadModels = function preloadModels(_a) {
8891
- return __awaiter(void 0, [_a], void 0, function (_b) {
8892
- var preloadTasks;
8893
- var _c = _b.documentDetectionModel,
8894
- documentDetectionModel = _c === void 0 ? true : _c,
8895
- _d = _b.focusModel,
8896
- focusModel = _d === void 0 ? true : _d,
8897
- _e = _b.faceDetectionModel,
8898
- faceDetectionModel = _e === void 0 ? true : _e;
8899
- return __generator(this, function (_f) {
8900
- switch (_f.label) {
8901
- case 0:
8902
- return [4 /*yield*/, probeModelCapabilities()];
8903
- case 1:
8904
- _f.sent();
8905
- preloadTasks = [];
8906
- if (documentDetectionModel) {
8907
- preloadTasks.push(preloadDocumentDetectorDependencies);
8908
- }
8909
- if (focusModel) {
8910
- preloadTasks.push(preloadFocusModelDependencies);
8911
- }
8912
- if (faceDetectionModel) {
8913
- preloadTasks.push(preloadFaceDetectorDependencies);
8914
- }
8915
- return [4 /*yield*/, Promise.all(preloadTasks)];
8916
- case 2:
8917
- _f.sent();
8918
- return [2 /*return*/];
8919
- }
8920
- });
8921
- });
8922
- };
8923
- var progressByUrl = {};
8924
- var progressByUseCase = {
8925
- visionRuntime: {
8926
- loaded: 0,
8927
- total: 0
8928
- },
8929
- documentDetection: {
8930
- loaded: 0,
8931
- total: 0
8932
- },
8933
- focus: {
8934
- loaded: 0,
8935
- total: 0
8936
- },
8937
- faceDetection: {
8938
- loaded: 0,
8939
- total: 0
8940
- }
8941
- };
8942
- function preloadDependency(url) {
8943
- return __awaiter(this, void 0, void 0, function () {
8944
- return __generator(this, function (_a) {
8945
- return [2 /*return*/, new Promise(function (resolve, reject) {
8946
- var req = new XMLHttpRequest();
8947
- req.addEventListener('progress', function (event) {
8948
- if (!event.lengthComputable) return;
8949
- progressByUrl[url] = event;
8950
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress', {
8951
- detail: {
8952
- url: url,
8953
- loaded: event.loaded,
8954
- total: event.total
8955
- }
8956
- }));
8957
- });
8958
- req.addEventListener('loadend', function () {
8959
- resolve(req.readyState === 4 && req.status === 200);
8960
- });
8961
- req.addEventListener('error', reject);
8962
- req.open('GET', url, true);
8963
- req.send();
8964
- })];
8965
- });
8966
- });
8967
- }
8968
- var documentDetectorPreloading = false,
8969
- focusModelPreloading = false,
8970
- faceDetectorPreloading = false;
8971
- function preloadDocumentDetectorDependencies() {
8972
- return __awaiter(this, void 0, void 0, function () {
8973
- function handleDownloadProgress(event) {
8974
- var detail = event.detail;
8975
- if (!dependencies.includes(detail.url)) return;
8976
- progressByUseCase.documentDetection = sumUpProgressForDependencies(dependencies);
8977
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.documentDetection', {
8978
- detail: progressByUseCase.documentDetection
8979
- }));
8980
- }
8981
- var dependencies;
8982
- return __generator(this, function (_a) {
8983
- switch (_a.label) {
8984
- case 0:
8985
- if (documentDetectorPreloading) return [2 /*return*/, new Promise(function (resolve) {
8986
- var i = setInterval(function () {
8987
- if (!documentDetectorPreloading) {
8988
- clearInterval(i);
8989
- resolve();
8990
- }
8991
- }, 100);
8992
- })];
8993
- documentDetectorPreloading = true;
8994
- return [4 /*yield*/, probeModelCapabilities()];
8995
- case 1:
8996
- _a.sent();
8997
- if (modelCapabilities.delegate === 'NONE') {
8998
- throw new Error('No available delegate for document detector.');
8999
- }
9000
- dependencies = [defaultDocumentDetectorModelPath];
9001
- document.addEventListener('idmission.preloadProgress', handleDownloadProgress);
9002
- _a.label = 2;
9003
- case 2:
9004
- _a.trys.push([2,, 4, 5]);
9005
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
9006
- case 3:
9007
- _a.sent();
9008
- return [3 /*break*/, 5];
9009
- case 4:
9010
- document.removeEventListener('idmission.preloadProgress', handleDownloadProgress);
9011
- documentDetectorPreloading = false;
9012
- return [7 /*endfinally*/];
9013
- case 5:
9014
- return [2 /*return*/];
9015
- }
9016
- });
9017
- });
9018
- }
9019
- function preloadFocusModelDependencies() {
9020
- return __awaiter(this, void 0, void 0, function () {
9021
- function handleModelDownloadProgress(event) {
9022
- var detail = event.detail;
9023
- if (!dependencies.includes(detail.url)) return;
9024
- progressByUseCase.focus = sumUpProgressForDependencies(dependencies);
9025
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.focus', {
9026
- detail: progressByUseCase.focus
9027
- }));
9028
- }
9029
- var dependencies;
9030
- return __generator(this, function (_a) {
9031
- switch (_a.label) {
9032
- case 0:
9033
- if (focusModelPreloading) return [2 /*return*/, new Promise(function (resolve) {
9034
- var i = setInterval(function () {
9035
- if (!focusModelPreloading) {
9036
- clearInterval(i);
9037
- resolve();
9038
- }
9039
- }, 100);
9040
- })];
9041
- focusModelPreloading = true;
9042
- return [4 /*yield*/, probeModelCapabilities()];
9043
- case 1:
9044
- _a.sent();
9045
- if (modelCapabilities.delegate === 'NONE') {
9046
- throw new Error('No available delegate for document detector.');
9047
- }
9048
- dependencies = [defaultFocusModelPath];
9049
- document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
9050
- _a.label = 2;
9051
- case 2:
9052
- _a.trys.push([2,, 4, 5]);
9053
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
9054
- case 3:
9055
- _a.sent();
9056
- return [3 /*break*/, 5];
9057
- case 4:
9058
- document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
9059
- focusModelPreloading = false;
9060
- return [7 /*endfinally*/];
9061
- case 5:
9062
- return [2 /*return*/];
9063
- }
9064
- });
9065
- });
9066
- }
9067
- function preloadFaceDetectorDependencies() {
9068
- return __awaiter(this, void 0, void 0, function () {
9069
- function handleModelDownloadProgress(event) {
9070
- var detail = event.detail;
9071
- if (!dependencies.includes(detail.url)) return;
9072
- progressByUseCase.faceDetection = sumUpProgressForDependencies(dependencies);
9073
- document.dispatchEvent(new CustomEvent('idmission.preloadProgress.faceDetection', {
9074
- detail: progressByUseCase.faceDetection
9075
- }));
9076
- }
9077
- var dependencies;
9078
- return __generator(this, function (_a) {
9079
- switch (_a.label) {
9080
- case 0:
9081
- if (faceDetectorPreloading) return [2 /*return*/, new Promise(function (resolve) {
9082
- var i = setInterval(function () {
9083
- if (!faceDetectorPreloading) {
9084
- clearInterval(i);
9085
- resolve();
9086
- }
9087
- }, 100);
9088
- })];
9089
- faceDetectorPreloading = true;
9090
- return [4 /*yield*/, probeModelCapabilities()];
9091
- case 1:
9092
- _a.sent();
9093
- if (modelCapabilities.delegate === 'NONE') {
9094
- throw new Error('No available delegate for document detector.');
9095
- }
9096
- dependencies = [defaultFaceDetectorModelPath];
9097
- document.addEventListener('idmission.preloadProgress', handleModelDownloadProgress);
9098
- _a.label = 2;
9099
- case 2:
9100
- _a.trys.push([2,, 4, 5]);
9101
- return [4 /*yield*/, Promise.all(dependencies.map(preloadDependency))];
9102
- case 3:
9103
- _a.sent();
9104
- return [3 /*break*/, 5];
9105
- case 4:
9106
- document.removeEventListener('idmission.preloadProgress', handleModelDownloadProgress);
9107
- faceDetectorPreloading = false;
9108
- return [7 /*endfinally*/];
9109
- case 5:
9110
- return [2 /*return*/];
9111
- }
9112
- });
9113
- });
9114
- }
9115
- function progressToPercentage(progress) {
9116
- return progress.total > 0 ? Math.round(100.0 * progress.loaded / progress.total) : 0;
9117
- }
9118
- function sumUpProgressForDependencies(dependencies) {
9119
- return dependencies.reduce(function (result, dependency) {
9120
- var dependencyProgress = progressByUrl[dependency];
9121
- if (!dependencyProgress) return result;
9122
- result.loaded += dependencyProgress.loaded;
9123
- result.total += dependencyProgress.total;
9124
- return result;
9125
- }, {
9126
- loaded: 0,
9127
- total: 0
9128
- });
9129
- }
9130
-
9131
8484
  var defaultDocumentDetectionScoreThreshold = 0.1;
9132
8485
  var defaultDocumentDetectionModelLoadTimeoutMs = 45000;
9133
8486
  var defaultDocumentDetectionThresholds = {
@@ -9149,8 +8502,8 @@
9149
8502
  singlePage: 'Single page',
9150
8503
  none: 'None'
9151
8504
  };
9152
- var detector = null;
9153
- var detectorSettings = null;
8505
+ var detector$1 = null;
8506
+ var detectorSettings$1 = null;
9154
8507
  function loadDocumentDetector() {
9155
8508
  return __awaiter(this, arguments, void 0, function (modelAssetPath, scoreThreshold) {
9156
8509
  var _a, _b;
@@ -9163,7 +8516,7 @@
9163
8516
  return __generator(this, function (_c) {
9164
8517
  switch (_c.label) {
9165
8518
  case 0:
9166
- 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];
8519
+ 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];
9167
8520
  closeDocumentDetector();
9168
8521
  return [4 /*yield*/, preloadDocumentDetectorDependencies()];
9169
8522
  case 1:
@@ -9184,20 +8537,20 @@
9184
8537
  runningMode: 'VIDEO'
9185
8538
  }])];
9186
8539
  case 3:
9187
- detector = _c.sent();
9188
- detectorSettings = {
8540
+ detector$1 = _c.sent();
8541
+ detectorSettings$1 = {
9189
8542
  modelAssetPath: modelAssetPath,
9190
8543
  scoreThreshold: scoreThreshold
9191
8544
  };
9192
- return [2 /*return*/, detector];
8545
+ return [2 /*return*/, detector$1];
9193
8546
  }
9194
8547
  });
9195
8548
  });
9196
8549
  }
9197
8550
  function closeDocumentDetector() {
9198
- detector === null || detector === void 0 ? void 0 : detector.close();
9199
- detector = null;
9200
- detectorSettings = null;
8551
+ detector$1 === null || detector$1 === void 0 ? void 0 : detector$1.close();
8552
+ detector$1 = null;
8553
+ detectorSettings$1 = null;
9201
8554
  }
9202
8555
  function useLoadDocumentDetector(_a) {
9203
8556
  var _b = _a.shouldLoadModels,
@@ -9230,7 +8583,7 @@
9230
8583
  function handleDownloadProgress(event) {
9231
8584
  setModelDownloadProgress(progressToPercentage(event.detail));
9232
8585
  }
9233
- document.addEventListener('idmission.preloadProgress.documentDetection', handleDownloadProgress);
8586
+ document.addEventListener('idmission.preloadProgress.documentDetector', handleDownloadProgress);
9234
8587
  var modelLoadTimeout = setTimeout(function () {
9235
8588
  setModelError(new Error('Model loading time limit exceeded.'));
9236
8589
  }, modelLoadTimeoutMs);
@@ -9243,7 +8596,7 @@
9243
8596
  case 0:
9244
8597
  setModelDownloadProgress(100);
9245
8598
  setModelLoadState('warming');
9246
- setModelWarmingStartedAt(new Date().getTime());
8599
+ setModelWarmingStartedAt(performance.now());
9247
8600
  clearTimeout(modelLoadTimeout);
9248
8601
  return [4 /*yield*/, testDocumentDetectionAgainstKnownImage(model)];
9249
8602
  case 1:
@@ -9277,7 +8630,7 @@
9277
8630
  cancelVideoReady();
9278
8631
  closeDocumentDetector();
9279
8632
  clearTimeout(modelLoadTimeout);
9280
- document.removeEventListener('idmission.preloadProgress.documentDetection', handleDownloadProgress);
8633
+ document.removeEventListener('idmission.preloadProgress.documentDetector', handleDownloadProgress);
9281
8634
  };
9282
8635
  }, [shouldLoadModels, modelLoadTimeoutMs, modelPath, scoreThreshold, videoRef]);
9283
8636
  React.useEffect(function handleModelError() {
@@ -9298,13 +8651,13 @@
9298
8651
  return __awaiter(this, void 0, void 0, function () {
9299
8652
  var startedAt, prediction, time, frameWidth, frameHeight;
9300
8653
  return __generator(this, function (_a) {
9301
- if (!detector) return [2 /*return*/, null];
9302
- startedAt = new Date();
8654
+ if (!detector$1) return [2 /*return*/, null];
8655
+ startedAt = performance.now();
9303
8656
  // Detectors can throw errors, for example when using custom URLs that
9304
8657
  // contain a model that doesn't provide the expected output.
9305
8658
  try {
9306
- prediction = detector.detectForVideo(frame, performance.now());
9307
- time = new Date().getTime() - startedAt.getTime();
8659
+ prediction = detector$1.detectForVideo(frame, performance.now());
8660
+ time = performance.now() - startedAt;
9308
8661
  frameWidth = frame.width;
9309
8662
  frameHeight = frame.height;
9310
8663
  return [2 /*return*/, _assign(_assign({}, prediction), {
@@ -9325,13 +8678,13 @@
9325
8678
  lastDetectionTime = time - lastDetectionAt;
9326
8679
  lastDetectionAt = time;
9327
8680
  }
9328
- var framesNeededSamples = [];
9329
- function trackFramesNeeded(value, bufferLength) {
8681
+ var framesNeededSamples$1 = [];
8682
+ function trackFramesNeeded$1(value, bufferLength) {
9330
8683
  if (bufferLength === void 0) {
9331
8684
  bufferLength = 25;
9332
8685
  }
9333
- framesNeededSamples.unshift(value);
9334
- if (framesNeededSamples.length > bufferLength) framesNeededSamples.length = bufferLength;
8686
+ framesNeededSamples$1.unshift(value);
8687
+ if (framesNeededSamples$1.length > bufferLength) framesNeededSamples$1.length = bufferLength;
9335
8688
  }
9336
8689
  var lastNBoxes = [];
9337
8690
  var lastNPairs = [];
@@ -9437,7 +8790,7 @@
9437
8790
  }
9438
8791
  var documentInBounds = !!bestDocument;
9439
8792
  if (lastDetectionTime > 0) {
9440
- trackFramesNeeded(1000 / lastDetectionTime);
8793
+ trackFramesNeeded$1(1000 / lastDetectionTime);
9441
8794
  }
9442
8795
  var documentIsStable = false;
9443
8796
  var documentTooClose = false;
@@ -9449,13 +8802,19 @@
9449
8802
  if (detectionThresholdMet && documentInBounds && !documentTooClose) {
9450
8803
  var thresholdSet = (_p = thresholds.stability) !== null && _p !== void 0 ? _p : defaultDocumentDetectionThresholds.stability;
9451
8804
  var threshold_1 = thresholdSet[detectedDocumentType];
9452
- var framesNeeded = Math.ceil(average(framesNeededSamples));
8805
+ var framesNeeded = Math.ceil(average(framesNeededSamples$1));
9453
8806
  trackBox(bestDocument.box, framesNeeded);
9454
8807
  documentIsStable = lastNBoxes.length >= framesNeeded && !lastNPairs.some(function (pair) {
9455
8808
  return pair.iou < threshold_1;
9456
8809
  });
9457
8810
  }
9458
8811
  }
8812
+ var bestPDF417;
8813
+ if (detectedObjects.length > 0) {
8814
+ bestPDF417 = detectedObjects.find(function (obj) {
8815
+ return obj.label === 'PDF417';
8816
+ });
8817
+ }
9459
8818
  return {
9460
8819
  prediction: prediction,
9461
8820
  detectedObjects: detectedObjects,
@@ -9472,6 +8831,7 @@
9472
8831
  singlePageDetectionScore: singlePageDetectionScore,
9473
8832
  singlePageDetectionThresholdMet: singlePageDetectionThresholdMet,
9474
8833
  bestDocument: bestDocument,
8834
+ bestPDF417: bestPDF417,
9475
8835
  documentInBounds: documentInBounds,
9476
8836
  documentTooClose: documentTooClose,
9477
8837
  documentIsStable: documentIsStable,
@@ -9515,6 +8875,43 @@
9515
8875
  });
9516
8876
  }
9517
8877
 
8878
+ function getFrameDimensions(frame) {
8879
+ var frameWidth = frame.width,
8880
+ frameHeight = frame.height;
8881
+ if (frame instanceof HTMLImageElement) {
8882
+ frameWidth = frame.naturalWidth;
8883
+ frameHeight = frame.naturalHeight;
8884
+ }
8885
+ if (frame instanceof HTMLVideoElement) {
8886
+ frameWidth = frame.videoWidth;
8887
+ frameHeight = frame.videoHeight;
8888
+ }
8889
+ return [frameWidth, frameHeight];
8890
+ }
8891
+
8892
+ 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"])));
8893
+ var InvisibleCanvas = styled.canvas(templateObject_2$G || (templateObject_2$G = __makeTemplateObject(["\n display: none;\n"], ["\n display: none;\n"])));
8894
+ function drawToCanvas(canvas, frame, width, height) {
8895
+ if (!canvas) return;
8896
+ var ctx = canvas.getContext('2d');
8897
+ if (!ctx) return;
8898
+ if (!width || !height) {
8899
+ var _a = getFrameDimensions(frame),
8900
+ frameWidth = _a[0],
8901
+ frameHeight = _a[1];
8902
+ width || (width = frameWidth);
8903
+ height || (height = frameHeight);
8904
+ }
8905
+ canvas.width = width;
8906
+ canvas.height = height;
8907
+ ctx.drawImage(frame, 0, 0, width, height);
8908
+ }
8909
+ function clearCanvas(canvas) {
8910
+ var _a;
8911
+ (_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);
8912
+ }
8913
+ var templateObject_1$M, templateObject_2$G;
8914
+
9518
8915
  function useFrameLoop(fn, options) {
9519
8916
  if (options === void 0) {
9520
8917
  options = {};
@@ -14333,13 +13730,278 @@
14333
13730
  documentDetectionLastPredictionCanvas: lastPredictionCanvas,
14334
13731
  clearDocumentDetectionLastPredictionCanvas: clearDocumentDetectionLastPredictionCanvas
14335
13732
  };
14336
- }, [start, stop, load, modelLoadState, modelWarmingStartedAt, modelError, modelDownloadProgress, onDocumentDetected, documentDetectionThresholds, documentDetectionBoundaries, clearDocumentDetectionLastPredictionCanvas]);
14337
- return /*#__PURE__*/React__namespace.createElement(DocumentDetectionModelContext.Provider, {
14338
- value: value
14339
- }, /*#__PURE__*/React__namespace.createElement(InvisibleCanvas, {
14340
- key: canvasKey,
14341
- ref: lastPredictionCanvas
14342
- }), children);
13733
+ }, [start, stop, load, modelLoadState, modelWarmingStartedAt, modelError, modelDownloadProgress, onDocumentDetected, documentDetectionThresholds, documentDetectionBoundaries, clearDocumentDetectionLastPredictionCanvas]);
13734
+ return /*#__PURE__*/React__namespace.createElement(DocumentDetectionModelContext.Provider, {
13735
+ value: value
13736
+ }, /*#__PURE__*/React__namespace.createElement(InvisibleCanvas, {
13737
+ key: canvasKey,
13738
+ ref: lastPredictionCanvas
13739
+ }), children);
13740
+ }
13741
+
13742
+ function cropToShoulders(rawCanvas, cropCanvas, resizeCanvas, frame, face, quality, maxHeight) {
13743
+ var _a;
13744
+ if (quality === void 0) {
13745
+ quality = 0.92;
13746
+ }
13747
+ if (!rawCanvas || !cropCanvas || !resizeCanvas) return '';
13748
+ var rawCtx = rawCanvas.getContext('2d');
13749
+ var cropCtx = cropCanvas.getContext('2d');
13750
+ var resizeCtx = resizeCanvas.getContext('2d');
13751
+ if (!rawCtx || !cropCtx || !resizeCtx) throw new Error('could not get 2d context');
13752
+ rawCanvas.width = frame.width;
13753
+ rawCanvas.height = frame.height;
13754
+ rawCtx.putImageData(frame, 0, 0);
13755
+ if (frame.height > frame.width) {
13756
+ cropCanvas.width = frame.width;
13757
+ cropCanvas.height = frame.height;
13758
+ cropCtx.drawImage(rawCanvas, 0, 0, cropCanvas.width, cropCanvas.height);
13759
+ } else {
13760
+ var _b = (_a = face === null || face === void 0 ? void 0 : face.box) !== null && _a !== void 0 ? _a : {
13761
+ xMin: 0,
13762
+ width: frame.width
13763
+ },
13764
+ xMin = _b.xMin,
13765
+ width = _b.width;
13766
+ var desiredWidth = frame.height * 0.6;
13767
+ var faceCenterX = xMin + width / 2;
13768
+ var xPos = Math.max(0, faceCenterX - desiredWidth / 2);
13769
+ cropCanvas.width = desiredWidth;
13770
+ cropCanvas.height = frame.height;
13771
+ cropCtx.drawImage(rawCanvas, xPos, 0, cropCanvas.width, cropCanvas.height, 0, 0, cropCanvas.width, cropCanvas.height);
13772
+ }
13773
+ resizeCanvas.height = maxHeight !== null && maxHeight !== void 0 ? maxHeight : cropCanvas.height;
13774
+ resizeCanvas.width = cropCanvas.width * (resizeCanvas.height / cropCanvas.height);
13775
+ resizeCtx === null || resizeCtx === void 0 ? void 0 : resizeCtx.drawImage(cropCanvas, 0, 0, resizeCanvas.width, resizeCanvas.height);
13776
+ var dataURL = resizeCanvas.toDataURL('image/jpeg', quality);
13777
+ log('cropToShoulders size', new TextEncoder().encode(dataURL).length);
13778
+ clearCanvas(rawCanvas);
13779
+ clearCanvas(cropCanvas);
13780
+ clearCanvas(resizeCanvas);
13781
+ return dataURL;
13782
+ }
13783
+ function cropToDetectedObjectBox(frame, box, canvas, padding) {
13784
+ if (padding === void 0) {
13785
+ padding = 0;
13786
+ }
13787
+ canvas || (canvas = document.createElement('canvas'));
13788
+ var ctx = canvas.getContext('2d');
13789
+ if (!ctx) throw new Error('could not get 2d context');
13790
+ var xMin = box.xMin,
13791
+ yMin = box.yMin,
13792
+ width = box.width,
13793
+ height = box.height;
13794
+ canvas.width = width + padding * 2;
13795
+ canvas.height = height + padding * 2;
13796
+ ctx.drawImage(frame, xMin - padding, yMin - padding, width + padding * 2, height + padding * 2, 0, 0, canvas.width, canvas.height);
13797
+ return canvas;
13798
+ }
13799
+ function cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box, padding) {
13800
+ if (padding === void 0) {
13801
+ padding = 0;
13802
+ }
13803
+ if (!box) return imageData;
13804
+ var cropped = cropToDetectedObjectBox(imageData, box, cropCanvas, padding);
13805
+ var _a = [box.width, box.height],
13806
+ bw = _a[0],
13807
+ bh = _a[1];
13808
+ if (bh <= bw) return cropped;
13809
+ var ctx = rotateCanvas.getContext('2d');
13810
+ if (!ctx) return cropped;
13811
+ rotateCanvas.width = bh;
13812
+ rotateCanvas.height = bw;
13813
+ ctx.clearRect(0, 0, rotateCanvas.width, rotateCanvas.height);
13814
+ ctx.translate(rotateCanvas.width / 2, rotateCanvas.height / 2);
13815
+ ctx.rotate(1.5708); // 90 deg in radians
13816
+ ctx.drawImage(cropped, -bw / 2, -bh / 2);
13817
+ return rotateCanvas;
13818
+ }
13819
+ function resizeIfNecessary(imageData, resizeCanvas, maxWidth) {
13820
+ var width = imageData.width,
13821
+ height = imageData.height;
13822
+ if (width <= maxWidth) return imageData;
13823
+ var resizeCtx = resizeCanvas.getContext('2d');
13824
+ if (!resizeCtx) return imageData;
13825
+ var scale = maxWidth / width;
13826
+ resizeCanvas.width = maxWidth;
13827
+ resizeCanvas.height = height * scale;
13828
+ resizeCtx.drawImage(imageData, 0, 0, resizeCanvas.width, resizeCanvas.height);
13829
+ return resizeCanvas;
13830
+ }
13831
+
13832
+ var defaultFocusModelLoadTimeoutMs = 45000;
13833
+ var defaultFocusThresholds = {
13834
+ idCardFront: {
13835
+ desktop: 0,
13836
+ mobile: 0.3
13837
+ },
13838
+ idCardBack: {
13839
+ desktop: 0,
13840
+ mobile: 0.3
13841
+ },
13842
+ passport: {
13843
+ desktop: 0,
13844
+ mobile: 0.3
13845
+ },
13846
+ singlePage: {
13847
+ desktop: 0,
13848
+ mobile: 0.3
13849
+ }
13850
+ };
13851
+ var classifier$1 = null;
13852
+ var classifierSettings$1 = null;
13853
+ function loadFocusModel() {
13854
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
13855
+ var _a, _b;
13856
+ if (modelAssetPath === void 0) {
13857
+ modelAssetPath = defaultFocusModelPath;
13858
+ }
13859
+ return __generator(this, function (_c) {
13860
+ switch (_c.label) {
13861
+ case 0:
13862
+ if (classifier$1 && (classifierSettings$1 === null || classifierSettings$1 === void 0 ? void 0 : classifierSettings$1.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier$1];
13863
+ closeFocusModel();
13864
+ return [4 /*yield*/, preloadFocusModelDependencies()];
13865
+ case 1:
13866
+ _c.sent();
13867
+ if (modelCapabilities.delegate === 'NONE') {
13868
+ throw new Error('No available delegate for focus detector.');
13869
+ }
13870
+ _b = (_a = Ua).createFromOptions;
13871
+ return [4 /*yield*/, ao.forVisionTasks(visionTasksBasePath)];
13872
+ case 2:
13873
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
13874
+ baseOptions: {
13875
+ modelAssetPath: modelAssetPath,
13876
+ delegate: modelCapabilities.delegate
13877
+ },
13878
+ // canvas: document.createElement('canvas'),
13879
+ runningMode: 'VIDEO'
13880
+ }])];
13881
+ case 3:
13882
+ classifier$1 = _c.sent();
13883
+ classifierSettings$1 = {
13884
+ modelAssetPath: modelAssetPath
13885
+ };
13886
+ return [2 /*return*/, classifier$1];
13887
+ }
13888
+ });
13889
+ });
13890
+ }
13891
+ function closeFocusModel() {
13892
+ classifier$1 === null || classifier$1 === void 0 ? void 0 : classifier$1.close();
13893
+ classifier$1 = null;
13894
+ classifierSettings$1 = null;
13895
+ }
13896
+ function useLoadFocusModel(_a) {
13897
+ var _b = _a.modelPath,
13898
+ modelPath = _b === void 0 ? defaultFocusModelPath : _b,
13899
+ _c = _a.modelLoadTimeoutMs,
13900
+ modelLoadTimeoutMs = _c === void 0 ? defaultFocusModelLoadTimeoutMs : _c,
13901
+ onModelError = _a.onModelError,
13902
+ videoRef = _a.videoRef,
13903
+ _d = _a.shouldLoadModels,
13904
+ shouldLoadModels = _d === void 0 ? true : _d;
13905
+ var _e = React.useState('not-started'),
13906
+ modelLoadState = _e[0],
13907
+ setModelLoadState = _e[1];
13908
+ var _f = React.useState(0),
13909
+ modelDownloadProgress = _f[0],
13910
+ setModelDownloadProgress = _f[1];
13911
+ var _g = React.useState(null),
13912
+ modelWarmingStartedAt = _g[0],
13913
+ setModelWarmingStartedAt = _g[1];
13914
+ var _h = React.useState(null),
13915
+ modelError = _h[0],
13916
+ setModelError = _h[1];
13917
+ React.useEffect(function loadModel() {
13918
+ var _this = this;
13919
+ if (!shouldLoadModels) return;
13920
+ setModelLoadState('downloading');
13921
+ setModelWarmingStartedAt(null);
13922
+ function handleDownloadProgress(event) {
13923
+ setModelDownloadProgress(progressToPercentage(event.detail));
13924
+ }
13925
+ document.addEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
13926
+ var modelLoadTimeout = setTimeout(function () {
13927
+ setModelError(new Error('Model loading time limit exceeded.'));
13928
+ }, modelLoadTimeoutMs);
13929
+ var cancelVideoReady = function cancelVideoReady() {};
13930
+ loadFocusModel(modelPath).then(function (loadedModel) {
13931
+ return __awaiter(_this, void 0, void 0, function () {
13932
+ var _a, videoReady, cancel, cancelled;
13933
+ return __generator(this, function (_b) {
13934
+ switch (_b.label) {
13935
+ case 0:
13936
+ setModelDownloadProgress(100);
13937
+ clearTimeout(modelLoadTimeout);
13938
+ setModelLoadState('warming');
13939
+ setModelWarmingStartedAt(performance.now());
13940
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
13941
+ cancelled = false;
13942
+ cancelVideoReady = function cancelVideoReady() {
13943
+ cancelled = true;
13944
+ cancel();
13945
+ };
13946
+ return [4 /*yield*/, videoReady];
13947
+ case 1:
13948
+ _b.sent();
13949
+ setTimeout(function () {
13950
+ if (cancelled) return;
13951
+ loadedModel.classifyForVideo(videoRef.current, performance.now());
13952
+ setModelLoadState('ready');
13953
+ }, 500);
13954
+ return [2 /*return*/];
13955
+ }
13956
+ });
13957
+ });
13958
+ })["catch"](function (e) {
13959
+ setModelError(e);
13960
+ setModelLoadState('error');
13961
+ })["finally"](function () {
13962
+ clearTimeout(modelLoadTimeout);
13963
+ });
13964
+ return function () {
13965
+ log('unloading focus model');
13966
+ cancelVideoReady();
13967
+ closeFocusModel();
13968
+ clearTimeout(modelLoadTimeout);
13969
+ document.removeEventListener('idmission.preloadProgress.focus', handleDownloadProgress);
13970
+ };
13971
+ }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
13972
+ React.useEffect(function handleModelError() {
13973
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
13974
+ }, [modelError, onModelError]);
13975
+ return React.useMemo(function () {
13976
+ return {
13977
+ ready: modelLoadState === 'ready',
13978
+ modelLoadState: modelLoadState,
13979
+ modelDownloadProgress: modelDownloadProgress,
13980
+ modelWarmingStartedAt: modelWarmingStartedAt,
13981
+ modelError: modelError
13982
+ };
13983
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
13984
+ }
13985
+ var lastFocusPredictionAt = 0;
13986
+ var lastFocusPredictionTime = 0;
13987
+ function setLastFocusPredictionAt(time) {
13988
+ lastFocusPredictionTime = time - lastFocusPredictionAt;
13989
+ lastFocusPredictionAt = time;
13990
+ }
13991
+ function makeFocusModelPrediction(imageData, cropCanvas, rotateCanvas, box) {
13992
+ var _a, _b, _c, _d, _e;
13993
+ if (!classifier$1) return null;
13994
+ var startedAt = performance.now();
13995
+ var image = cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box);
13996
+ var result = classifier$1.classifyForVideo(image, performance.now());
13997
+ 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) {
13998
+ return c.categoryName === 'focused';
13999
+ })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
14000
+ var predictionTime = performance.now() - startedAt;
14001
+ return {
14002
+ score: score,
14003
+ predictionTime: predictionTime
14004
+ };
14343
14005
  }
14344
14006
 
14345
14007
  var FocusModelContext = /*#__PURE__*/React.createContext({
@@ -14416,7 +14078,7 @@
14416
14078
  }, [focusThresholds, load, makeFocusPrediction, modelDownloadProgress, modelError, modelLoadState, modelWarmingStartedAt]);
14417
14079
  return /*#__PURE__*/React.createElement(FocusModelContext.Provider, {
14418
14080
  value: value
14419
- }, /*#__PURE__*/React.createElement(InvisibleCanvas, {
14081
+ }, /*#__PURE__*/React.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React.createElement(InvisibleCanvas, {
14420
14082
  ref: rotateCanvas,
14421
14083
  style: showCanvases ? {
14422
14084
  display: 'block'
@@ -14426,7 +14088,7 @@
14426
14088
  style: showCanvases ? {
14427
14089
  display: 'block'
14428
14090
  } : undefined
14429
- }), children);
14091
+ })), children);
14430
14092
  }
14431
14093
 
14432
14094
  function _isNavigatorDefined() {
@@ -14461,7 +14123,379 @@
14461
14123
  return false;
14462
14124
  }
14463
14125
 
14126
+ var defaultBarcodeReadabilityModelLoadTimeoutMs = 45000;
14127
+ var classifier = null;
14128
+ var classifierSettings = null;
14129
+ function loadBarcodeReadabilityModel() {
14130
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
14131
+ var _a, _b;
14132
+ if (modelAssetPath === void 0) {
14133
+ modelAssetPath = defaultBarcodeReadabilityModelPath;
14134
+ }
14135
+ return __generator(this, function (_c) {
14136
+ switch (_c.label) {
14137
+ case 0:
14138
+ if (classifier && (classifierSettings === null || classifierSettings === void 0 ? void 0 : classifierSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, classifier];
14139
+ closeBarcodeReadabilityModel();
14140
+ return [4 /*yield*/, preloadBarcodeReadabilityModelDependencies()];
14141
+ case 1:
14142
+ _c.sent();
14143
+ if (modelCapabilities.delegate === 'NONE') {
14144
+ throw new Error('No available delegate for barcode readability model.');
14145
+ }
14146
+ _b = (_a = Ua).createFromOptions;
14147
+ return [4 /*yield*/, ao.forVisionTasks(visionTasksBasePath)];
14148
+ case 2:
14149
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
14150
+ baseOptions: {
14151
+ modelAssetPath: modelAssetPath,
14152
+ delegate: 'CPU'
14153
+ },
14154
+ runningMode: 'VIDEO',
14155
+ maxResults: 1
14156
+ }])];
14157
+ case 3:
14158
+ classifier = _c.sent();
14159
+ classifierSettings = {
14160
+ modelAssetPath: modelAssetPath
14161
+ };
14162
+ return [2 /*return*/, classifier];
14163
+ }
14164
+ });
14165
+ });
14166
+ }
14167
+ function closeBarcodeReadabilityModel() {
14168
+ classifier === null || classifier === void 0 ? void 0 : classifier.close();
14169
+ classifier = null;
14170
+ classifierSettings = null;
14171
+ }
14172
+ function useLoadBarcodeReadabilityModel(_a) {
14173
+ var _b = _a.modelPath,
14174
+ modelPath = _b === void 0 ? defaultBarcodeReadabilityModelPath : _b,
14175
+ _c = _a.modelLoadTimeoutMs,
14176
+ modelLoadTimeoutMs = _c === void 0 ? defaultBarcodeReadabilityModelLoadTimeoutMs : _c,
14177
+ onModelError = _a.onModelError,
14178
+ videoRef = _a.videoRef,
14179
+ _d = _a.shouldLoadModels,
14180
+ shouldLoadModels = _d === void 0 ? true : _d;
14181
+ var _e = React.useState('not-started'),
14182
+ modelLoadState = _e[0],
14183
+ setModelLoadState = _e[1];
14184
+ var _f = React.useState(0),
14185
+ modelDownloadProgress = _f[0],
14186
+ setModelDownloadProgress = _f[1];
14187
+ var _g = React.useState(null),
14188
+ modelWarmingStartedAt = _g[0],
14189
+ setModelWarmingStartedAt = _g[1];
14190
+ var _h = React.useState(null),
14191
+ modelError = _h[0],
14192
+ setModelError = _h[1];
14193
+ React.useEffect(function loadModel() {
14194
+ var _this = this;
14195
+ if (!shouldLoadModels) return;
14196
+ setModelLoadState('downloading');
14197
+ setModelWarmingStartedAt(null);
14198
+ function handleDownloadProgress(event) {
14199
+ setModelDownloadProgress(progressToPercentage(event.detail));
14200
+ }
14201
+ document.addEventListener('idmission.preloadProgress.barcodeReadability', handleDownloadProgress);
14202
+ var modelLoadTimeout = setTimeout(function () {
14203
+ setModelError(new Error('Model loading time limit exceeded.'));
14204
+ }, modelLoadTimeoutMs);
14205
+ var cancelVideoReady = function cancelVideoReady() {};
14206
+ loadBarcodeReadabilityModel(modelPath).then(function (loadedModel) {
14207
+ return __awaiter(_this, void 0, void 0, function () {
14208
+ var _a, videoReady, cancel, cancelled;
14209
+ return __generator(this, function (_b) {
14210
+ switch (_b.label) {
14211
+ case 0:
14212
+ setModelDownloadProgress(100);
14213
+ clearTimeout(modelLoadTimeout);
14214
+ setModelLoadState('warming');
14215
+ setModelWarmingStartedAt(new Date().getTime());
14216
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
14217
+ cancelled = false;
14218
+ cancelVideoReady = function cancelVideoReady() {
14219
+ cancelled = true;
14220
+ cancel();
14221
+ };
14222
+ return [4 /*yield*/, videoReady];
14223
+ case 1:
14224
+ _b.sent();
14225
+ setTimeout(function () {
14226
+ if (cancelled) return;
14227
+ loadedModel.classifyForVideo(videoRef.current, performance.now());
14228
+ setModelLoadState('ready');
14229
+ }, 500);
14230
+ return [2 /*return*/];
14231
+ }
14232
+ });
14233
+ });
14234
+ })["catch"](function (e) {
14235
+ setModelError(e);
14236
+ setModelLoadState('error');
14237
+ })["finally"](function () {
14238
+ clearTimeout(modelLoadTimeout);
14239
+ });
14240
+ return function () {
14241
+ log('unloading barcode readability model');
14242
+ cancelVideoReady();
14243
+ closeBarcodeReadabilityModel();
14244
+ clearTimeout(modelLoadTimeout);
14245
+ document.removeEventListener('idmission.preloadProgress.barcodeReadability', handleDownloadProgress);
14246
+ };
14247
+ }, [modelPath, modelLoadTimeoutMs, videoRef, shouldLoadModels]);
14248
+ React.useEffect(function handleModelError() {
14249
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
14250
+ }, [modelError, onModelError]);
14251
+ return React.useMemo(function () {
14252
+ return {
14253
+ ready: modelLoadState === 'ready',
14254
+ modelLoadState: modelLoadState,
14255
+ modelDownloadProgress: modelDownloadProgress,
14256
+ modelWarmingStartedAt: modelWarmingStartedAt,
14257
+ modelError: modelError
14258
+ };
14259
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
14260
+ }
14261
+ var lastBarcodeReadabilityPredictionAt = 0;
14262
+ var lastBarcodeReadabilityPredictionTime = 0;
14263
+ function setLastBarcodeReadabilityPredictionAt(time) {
14264
+ lastBarcodeReadabilityPredictionTime = time - lastBarcodeReadabilityPredictionAt;
14265
+ lastBarcodeReadabilityPredictionAt = time;
14266
+ }
14267
+ function makeBarcodeReadabilityModelPrediction(imageData, cropCanvas, rotateCanvas, resizeCanvas, box) {
14268
+ var _a, _b, _c, _d, _e;
14269
+ if (!classifier) return null;
14270
+ var startedAt = performance.now();
14271
+ var image = cropAndRotateIfNecessary(imageData, cropCanvas, rotateCanvas, box);
14272
+ var resized = resizeIfNecessary(image, resizeCanvas, 500);
14273
+ var result = classifier.classifyForVideo(resized, performance.now());
14274
+ 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) {
14275
+ return c.categoryName === 'blurry';
14276
+ })) === null || _d === void 0 ? void 0 : _d.score) !== null && _e !== void 0 ? _e : 0;
14277
+ debug('barcode prediction', "".concat(performance.now() - startedAt, "ms"), score);
14278
+ var predictionTime = performance.now() - startedAt;
14279
+ return {
14280
+ score: score,
14281
+ predictionTime: predictionTime
14282
+ };
14283
+ }
14284
+
14285
+ var BarcodeReadabilityModelContext = /*#__PURE__*/React.createContext({
14286
+ loadBarcodeReadabilityModel: function loadBarcodeReadabilityModel() {
14287
+ return null;
14288
+ },
14289
+ barcodeReadabilityModelState: 'not-started',
14290
+ barcodeReadabilityModelDownloadProgress: 0,
14291
+ barcodeReadabilityModelWarmingStartedAt: null,
14292
+ barcodeReadabilityModelError: null,
14293
+ barcodeReadabilityThresholds: {},
14294
+ setBarcodeReadabilityThresholds: function setBarcodeReadabilityThresholds() {
14295
+ return null;
14296
+ },
14297
+ makeBarcodeReadabilityPrediction: function makeBarcodeReadabilityPrediction() {
14298
+ return null;
14299
+ },
14300
+ barcodeReadabilityPredictionTime: 0
14301
+ });
14302
+ function BarcodeReadabilityModelProvider(_a) {
14303
+ var children = _a.children,
14304
+ _b = _a.barcodeReadabilityModelPath,
14305
+ barcodeReadabilityModelPath = _b === void 0 ? defaultBarcodeReadabilityModelPath : _b,
14306
+ _c = _a.barcodeReadabilityModelLoadTimeoutMs,
14307
+ barcodeReadabilityModelLoadTimeoutMs = _c === void 0 ? defaultBarcodeReadabilityModelLoadTimeoutMs : _c,
14308
+ onBarcodeReadabilityModelError = _a.onBarcodeReadabilityModelError,
14309
+ _d = _a.showCanvases,
14310
+ showCanvases = _d === void 0 ? false : _d,
14311
+ _e = _a.shouldLoadModels,
14312
+ shouldLoadModelsProp = _e === void 0 ? true : _e;
14313
+ var cropCanvas = React.useRef(null);
14314
+ var rotateCanvas = React.useRef(null);
14315
+ var resizeCanvas = React.useRef(null);
14316
+ var _f = React.useState({}),
14317
+ barcodeReadabilityThresholds = _f[0],
14318
+ setBarcodeReadabilityThresholds = _f[1];
14319
+ var videoRef = useCameraStore().videoRef;
14320
+ var _g = React.useState(shouldLoadModelsProp),
14321
+ shouldLoadModels = _g[0],
14322
+ setShouldLoadModels = _g[1];
14323
+ var load = React.useCallback(function () {
14324
+ return setShouldLoadModels(true);
14325
+ }, []);
14326
+ var _h = useLoadBarcodeReadabilityModel({
14327
+ modelPath: barcodeReadabilityModelPath,
14328
+ modelLoadTimeoutMs: barcodeReadabilityModelLoadTimeoutMs,
14329
+ onModelError: onBarcodeReadabilityModelError,
14330
+ videoRef: videoRef,
14331
+ shouldLoadModels: shouldLoadModels
14332
+ }),
14333
+ ready = _h.ready,
14334
+ modelLoadState = _h.modelLoadState,
14335
+ modelDownloadProgress = _h.modelDownloadProgress,
14336
+ modelWarmingStartedAt = _h.modelWarmingStartedAt,
14337
+ modelError = _h.modelError;
14338
+ var makeBarcodeReadabilityPrediction = React.useCallback(function (imageData, box) {
14339
+ if (!ready) return null;
14340
+ var prediction = makeBarcodeReadabilityModelPrediction(imageData, cropCanvas.current, rotateCanvas.current, resizeCanvas.current, box);
14341
+ if (!prediction) return null;
14342
+ setLastBarcodeReadabilityPredictionAt(prediction.predictionTime);
14343
+ return prediction;
14344
+ }, [ready]);
14345
+ var value = React.useMemo(function () {
14346
+ return {
14347
+ loadBarcodeReadabilityModel: load,
14348
+ barcodeReadabilityModelState: modelLoadState,
14349
+ barcodeReadabilityModelDownloadProgress: modelDownloadProgress,
14350
+ barcodeReadabilityModelWarmingStartedAt: modelWarmingStartedAt,
14351
+ barcodeReadabilityModelError: modelError,
14352
+ makeBarcodeReadabilityPrediction: makeBarcodeReadabilityPrediction,
14353
+ barcodeReadabilityPredictionTime: lastBarcodeReadabilityPredictionTime,
14354
+ barcodeReadabilityThresholds: barcodeReadabilityThresholds,
14355
+ setBarcodeReadabilityThresholds: setBarcodeReadabilityThresholds
14356
+ };
14357
+ }, [barcodeReadabilityThresholds, load, makeBarcodeReadabilityPrediction, modelDownloadProgress, modelError, modelLoadState, modelWarmingStartedAt]);
14358
+ return /*#__PURE__*/React.createElement(BarcodeReadabilityModelContext.Provider, {
14359
+ value: value
14360
+ }, /*#__PURE__*/React.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React.createElement(InvisibleCanvas, {
14361
+ ref: rotateCanvas
14362
+ }), /*#__PURE__*/React.createElement(InvisibleCanvas, {
14363
+ ref: cropCanvas
14364
+ }), /*#__PURE__*/React.createElement(InvisibleCanvas, {
14365
+ ref: resizeCanvas,
14366
+ style: showCanvases ? {
14367
+ display: 'block'
14368
+ } : undefined
14369
+ })), children);
14370
+ }
14371
+ function useBarcodeReadabilityModelContext() {
14372
+ var context = React.useContext(BarcodeReadabilityModelContext);
14373
+ if (!context) {
14374
+ throw new Error('useBarcodeReadabilityModelContext must be used within a BarcodeReadabilityModelProvider');
14375
+ }
14376
+ return context;
14377
+ }
14378
+
14464
14379
  var onMobile = isMobile();
14380
+ /**
14381
+ * Analyzes barcode readability for a detected document
14382
+ * @param prediction The document detection prediction
14383
+ * @param lastPredictionCanvas The canvas containing the original frame
14384
+ * @param croppedDocumentCanvas Canvas for storing cropped document
14385
+ * @param bestBarcodeCanvas Canvas for storing best barcode crop
14386
+ * @param currentBestBarcodeScore Current best barcode score
14387
+ * @param documentDetectionThresholds Thresholds for document detection
14388
+ * @param makeBarcodeReadabilityPrediction Function to make barcode readability predictions
14389
+ * @param barcodeReadabilityThresholds Thresholds for barcode readability
14390
+ * @returns Object containing barcode analysis results
14391
+ */
14392
+ function analyzeBarcodeReadability(prediction, lastPredictionCanvas, croppedDocumentCanvas, bestBarcodeCanvas, currentBestBarcodeScore, documentDetectionThresholds, makeBarcodeReadabilityPrediction, barcodeReadabilityThreshold) {
14393
+ return __awaiter(this, void 0, void 0, function () {
14394
+ var pdf417PredictionTime, pdf417PredictionScore, pdf417PredictionThresholdMet, newBestBarcodeScore, newBestBarcodeDetails, documentCroppedPrediction, processedCroppedPrediction, pdf417Prediction;
14395
+ var _a;
14396
+ return __generator(this, function (_b) {
14397
+ switch (_b.label) {
14398
+ case 0:
14399
+ pdf417PredictionTime = 0;
14400
+ pdf417PredictionScore = 0;
14401
+ pdf417PredictionThresholdMet = false;
14402
+ if (!prediction.bestDocument || !((_a = prediction.bestPDF417) === null || _a === void 0 ? void 0 : _a.box) || !bestBarcodeCanvas) {
14403
+ return [2 /*return*/, {
14404
+ pdf417PredictionTime: pdf417PredictionTime,
14405
+ pdf417PredictionScore: pdf417PredictionScore,
14406
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet,
14407
+ newBestBarcodeScore: newBestBarcodeScore,
14408
+ newBestBarcodeDetails: newBestBarcodeDetails
14409
+ }];
14410
+ }
14411
+ /**
14412
+ * Step 1: Crop the full frame to just the document area
14413
+ * This removes background noise and focuses analysis on the document
14414
+ */
14415
+ cropToDetectedObjectBox(lastPredictionCanvas, prediction.bestDocument.box, croppedDocumentCanvas);
14416
+ return [4 /*yield*/, makeDocumentDetectorPrediction(croppedDocumentCanvas)];
14417
+ case 1:
14418
+ documentCroppedPrediction = _b.sent();
14419
+ if (!documentCroppedPrediction) {
14420
+ // error occurred during prediction (error logged by callee)
14421
+ return [2 /*return*/, {
14422
+ pdf417PredictionTime: pdf417PredictionTime,
14423
+ pdf417PredictionScore: pdf417PredictionScore,
14424
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet,
14425
+ newBestBarcodeScore: newBestBarcodeScore,
14426
+ newBestBarcodeDetails: newBestBarcodeDetails
14427
+ }];
14428
+ }
14429
+ processedCroppedPrediction = processDocumentDetectorPrediction(documentCroppedPrediction, documentDetectionThresholds);
14430
+ if (processedCroppedPrediction.bestPDF417) {
14431
+ pdf417Prediction = makeBarcodeReadabilityPrediction(croppedDocumentCanvas, processedCroppedPrediction.bestPDF417.box);
14432
+ if (pdf417Prediction) {
14433
+ pdf417PredictionTime = pdf417Prediction.predictionTime;
14434
+ pdf417PredictionScore = pdf417Prediction.score;
14435
+ if (pdf417Prediction.score > currentBestBarcodeScore) {
14436
+ /**
14437
+ * Step 5: Update best barcode
14438
+ */
14439
+ newBestBarcodeScore = pdf417Prediction.score;
14440
+ newBestBarcodeDetails = {
14441
+ boundingBox: prediction.bestPDF417.box,
14442
+ score: pdf417Prediction.score
14443
+ };
14444
+ if (pdf417PredictionScore >= barcodeReadabilityThreshold) {
14445
+ pdf417PredictionThresholdMet = true;
14446
+ }
14447
+ cropToDetectedObjectBox(croppedDocumentCanvas, processedCroppedPrediction.bestPDF417.box, bestBarcodeCanvas, 16);
14448
+ }
14449
+ }
14450
+ }
14451
+ return [2 /*return*/, {
14452
+ pdf417PredictionTime: pdf417PredictionTime,
14453
+ pdf417PredictionScore: pdf417PredictionScore,
14454
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet,
14455
+ newBestBarcodeScore: newBestBarcodeScore,
14456
+ newBestBarcodeDetails: newBestBarcodeDetails
14457
+ }];
14458
+ }
14459
+ });
14460
+ });
14461
+ }
14462
+ /**
14463
+ * Calculates the barcode readability threshold for a given document type
14464
+ * @param detectedDocumentType The type of document detected
14465
+ * @param barcodeReadabilityThresholds The threshold configuration object
14466
+ * @returns The appropriate threshold value for the current platform (mobile/desktop)
14467
+ */
14468
+ function calculateBarcodeReadabilityThreshold(detectedDocumentType, barcodeReadabilityThresholds) {
14469
+ var barcodeReadabilityThresholdSet = detectedDocumentType in barcodeReadabilityThresholds ? barcodeReadabilityThresholds[detectedDocumentType] : undefined;
14470
+ if (barcodeReadabilityThresholdSet) {
14471
+ return onMobile ? barcodeReadabilityThresholdSet.mobile || 0 : barcodeReadabilityThresholdSet.desktop || 0;
14472
+ }
14473
+ return 0;
14474
+ }
14475
+ /**
14476
+ * Hook that calculates the barcode readability threshold for a given document type
14477
+ */
14478
+ function useBarcodeReadabilityThreshold() {
14479
+ var barcodeReadabilityThresholds = useBarcodeReadabilityModelContext().barcodeReadabilityThresholds;
14480
+ return React.useCallback(function (detectedDocumentType) {
14481
+ return calculateBarcodeReadabilityThreshold(detectedDocumentType, barcodeReadabilityThresholds);
14482
+ }, [barcodeReadabilityThresholds]);
14483
+ }
14484
+ function useBarcodeReadabilityAnalysis() {
14485
+ var _this = this;
14486
+ var documentDetectionThresholds = React.useContext(DocumentDetectionModelContext).documentDetectionThresholds;
14487
+ var makeBarcodeReadabilityPrediction = useBarcodeReadabilityModelContext().makeBarcodeReadabilityPrediction;
14488
+ var getBarcodeReadabilityThreshold = useBarcodeReadabilityThreshold();
14489
+ return React.useCallback(function (prediction, lastPredictionCanvas, croppedDocumentCanvas, bestBarcodeCanvas, currentBestBarcodeScore) {
14490
+ return __awaiter(_this, void 0, void 0, function () {
14491
+ var barcodeReadabilityThreshold;
14492
+ return __generator(this, function (_a) {
14493
+ barcodeReadabilityThreshold = getBarcodeReadabilityThreshold(prediction.detectedDocumentType);
14494
+ return [2 /*return*/, analyzeBarcodeReadability(prediction, lastPredictionCanvas, croppedDocumentCanvas, bestBarcodeCanvas, currentBestBarcodeScore, documentDetectionThresholds, makeBarcodeReadabilityPrediction, barcodeReadabilityThreshold)];
14495
+ });
14496
+ });
14497
+ }, [documentDetectionThresholds, makeBarcodeReadabilityPrediction, getBarcodeReadabilityThreshold]);
14498
+ }
14465
14499
  var defaultIdCaptureThresholds = {
14466
14500
  detection: defaultDocumentDetectionThresholds,
14467
14501
  focus: defaultFocusThresholds
@@ -14494,6 +14528,7 @@
14494
14528
  },
14495
14529
  detectionTime: 0,
14496
14530
  focusPredictionTime: 0,
14531
+ barcodeReadabilityPredictionTime: 0,
14497
14532
  bestFrameDetails: {
14498
14533
  current: null
14499
14534
  },
@@ -14503,55 +14538,80 @@
14503
14538
  resetBestFrame: function resetBestFrame() {
14504
14539
  return null;
14505
14540
  },
14541
+ bestBarcodeDetails: {
14542
+ current: null
14543
+ },
14544
+ getBestBarcode: function getBestBarcode() {
14545
+ return null;
14546
+ },
14506
14547
  requiredDocumentType: 'none',
14507
14548
  setRequiredDocumentType: function setRequiredDocumentType() {
14508
14549
  return null;
14509
14550
  }
14510
14551
  });
14511
14552
  function IdCaptureModelsProviderInner(_a) {
14553
+ var _b;
14512
14554
  var children = _a.children,
14513
14555
  onModelError = _a.onModelError,
14514
- _b = _a.allowSinglePageIdCapture,
14515
- allowSinglePageIdCapture = _b === void 0 ? false : _b;
14516
- var _c = React.useContext(DocumentDetectionModelContext),
14517
- documentDetectionModelState = _c.documentDetectionModelState,
14518
- documentDetectionModelDownloadProgress = _c.documentDetectionModelDownloadProgress,
14519
- documentDetectionModelWarmingStartedAt = _c.documentDetectionModelWarmingStartedAt,
14520
- startDocumentDetection = _c.startDocumentDetection,
14521
- stopDocumentDetection = _c.stopDocumentDetection,
14522
- loadDocumentDetectionModel = _c.loadDocumentDetectionModel,
14523
- lastPredictionCanvas = _c.documentDetectionLastPredictionCanvas,
14524
- clearDocumentDetectionLastPredictionCanvas = _c.clearDocumentDetectionLastPredictionCanvas,
14525
- onDocumentDetected = _c.onDocumentDetected,
14526
- detectionTime = _c.detectionTime,
14527
- documentDetectionThresholds = _c.documentDetectionThresholds,
14528
- setDocumentDetectionThresholds = _c.setDocumentDetectionThresholds,
14529
- documentDetectionBoundaries = _c.documentDetectionBoundaries,
14530
- setDocumentDetectionBoundaries = _c.setDocumentDetectionBoundaries,
14531
- documentDetectionModelError = _c.documentDetectionModelError;
14532
- var _d = React.useContext(FocusModelContext),
14533
- loadFocusModel = _d.loadFocusModel,
14534
- focusModelState = _d.focusModelState,
14535
- focusModelDownloadProgress = _d.focusModelDownloadProgress,
14536
- focusModelWarmingStartedAt = _d.focusModelWarmingStartedAt,
14537
- makeFocusPrediction = _d.makeFocusPrediction,
14538
- focusThresholds = _d.focusThresholds,
14539
- setFocusThresholds = _d.setFocusThresholds,
14540
- focusPredictionTime = _d.focusPredictionTime,
14541
- focusModelError = _d.focusModelError;
14556
+ _c = _a.allowSinglePageIdCapture,
14557
+ allowSinglePageIdCapture = _c === void 0 ? false : _c,
14558
+ _d = _a.enableBarcodeReadabilityModel,
14559
+ enableBarcodeReadabilityModel = _d === void 0 ? true : _d;
14560
+ var _e = React.useContext(DocumentDetectionModelContext),
14561
+ documentDetectionModelState = _e.documentDetectionModelState,
14562
+ documentDetectionModelDownloadProgress = _e.documentDetectionModelDownloadProgress,
14563
+ documentDetectionModelWarmingStartedAt = _e.documentDetectionModelWarmingStartedAt,
14564
+ startDocumentDetection = _e.startDocumentDetection,
14565
+ stopDocumentDetection = _e.stopDocumentDetection,
14566
+ loadDocumentDetectionModel = _e.loadDocumentDetectionModel,
14567
+ lastPredictionCanvas = _e.documentDetectionLastPredictionCanvas,
14568
+ clearDocumentDetectionLastPredictionCanvas = _e.clearDocumentDetectionLastPredictionCanvas,
14569
+ onDocumentDetected = _e.onDocumentDetected,
14570
+ detectionTime = _e.detectionTime,
14571
+ documentDetectionThresholds = _e.documentDetectionThresholds,
14572
+ setDocumentDetectionThresholds = _e.setDocumentDetectionThresholds,
14573
+ documentDetectionBoundaries = _e.documentDetectionBoundaries,
14574
+ setDocumentDetectionBoundaries = _e.setDocumentDetectionBoundaries,
14575
+ documentDetectionModelError = _e.documentDetectionModelError;
14576
+ var _f = React.useContext(FocusModelContext),
14577
+ loadFocusModel = _f.loadFocusModel,
14578
+ focusModelState = _f.focusModelState,
14579
+ focusModelDownloadProgress = _f.focusModelDownloadProgress,
14580
+ focusModelWarmingStartedAt = _f.focusModelWarmingStartedAt,
14581
+ makeFocusPrediction = _f.makeFocusPrediction,
14582
+ focusThresholds = _f.focusThresholds,
14583
+ setFocusThresholds = _f.setFocusThresholds,
14584
+ focusPredictionTime = _f.focusPredictionTime,
14585
+ focusModelError = _f.focusModelError;
14586
+ var _g = useBarcodeReadabilityModelContext(),
14587
+ loadBarcodeReadabilityModel = _g.loadBarcodeReadabilityModel,
14588
+ barcodeReadabilityModelState = _g.barcodeReadabilityModelState,
14589
+ barcodeReadabilityModelDownloadProgress = _g.barcodeReadabilityModelDownloadProgress,
14590
+ barcodeReadabilityModelWarmingStartedAt = _g.barcodeReadabilityModelWarmingStartedAt,
14591
+ makeBarcodeReadabilityPrediction = _g.makeBarcodeReadabilityPrediction,
14592
+ barcodeReadabilityThresholds = _g.barcodeReadabilityThresholds,
14593
+ setBarcodeReadabilityThresholds = _g.setBarcodeReadabilityThresholds,
14594
+ barcodeReadabilityPredictionTime = _g.barcodeReadabilityPredictionTime,
14595
+ barcodeReadabilityModelError = _g.barcodeReadabilityModelError;
14542
14596
  var onPredictionHandler = React.useRef();
14543
14597
  var bestFrameDetails = React.useRef(null);
14598
+ var bestBarcodeDetails = React.useRef(null);
14544
14599
  var bestPredictionCanvas = React.useRef(null);
14600
+ var bestBarcodeCanvas = React.useRef(null);
14601
+ var croppedDocumentCanvas = React.useRef(null);
14545
14602
  var bestFocusScore = React.useRef(0);
14603
+ var bestBarcodeScore = React.useRef(0);
14546
14604
  var stopDetection = React.useRef(0);
14547
- var _e = React.useState('none'),
14548
- requiredDocumentType = _e[0],
14549
- setRequiredDocumentType = _e[1];
14605
+ var analyzeBarcodeReadability = useBarcodeReadabilityAnalysis();
14606
+ var _h = React.useState('none'),
14607
+ requiredDocumentType = _h[0],
14608
+ setRequiredDocumentType = _h[1];
14550
14609
  var thresholds = React.useMemo(function () {
14551
14610
  return _assign(_assign({}, documentDetectionThresholds), {
14552
- focus: focusThresholds
14611
+ focus: focusThresholds,
14612
+ barcodeReadability: barcodeReadabilityThresholds
14553
14613
  });
14554
- }, [documentDetectionThresholds, focusThresholds]);
14614
+ }, [documentDetectionThresholds, focusThresholds, barcodeReadabilityThresholds]);
14555
14615
  var setThresholds = React.useCallback(function (thresholds) {
14556
14616
  if (thresholds.detection) {
14557
14617
  setDocumentDetectionThresholds(thresholds.detection);
@@ -14559,57 +14619,87 @@
14559
14619
  if (thresholds.focus) {
14560
14620
  setFocusThresholds(thresholds.focus);
14561
14621
  }
14562
- }, [setDocumentDetectionThresholds, setFocusThresholds]);
14622
+ if (thresholds.barcodeReadability) {
14623
+ setBarcodeReadabilityThresholds(thresholds.barcodeReadability);
14624
+ }
14625
+ }, [setBarcodeReadabilityThresholds, setDocumentDetectionThresholds, setFocusThresholds]);
14563
14626
  React.useEffect(function handleDetections() {
14564
14627
  var _this = this;
14565
14628
  onDocumentDetected(function (prediction) {
14566
14629
  return __awaiter(_this, void 0, void 0, function () {
14567
- var stopDetectionAtStart, focusPredictionTime, focusScore, focusThresholdMet, isSinglePage, isRequiredDocumentType, focusPrediction, focusThresholdSet, focusThreshold;
14630
+ var stopDetectionAtStart, focusPredictionTime, focusScore, focusThresholdMet, pdf417PredictionTime, pdf417PredictionScore, pdf417PredictionThresholdMet, isSinglePage, isRequiredDocumentType, focusPrediction, focusThresholdSet, focusThreshold, barcodeAnalysisResult;
14568
14631
  var _a, _b, _c, _d, _e, _f, _g;
14569
14632
  return __generator(this, function (_h) {
14570
- if (!lastPredictionCanvas.current) return [2 /*return*/];
14571
- stopDetectionAtStart = stopDetection.current;
14572
- focusPredictionTime = 0, focusScore = 0, focusThresholdMet = false;
14573
- isSinglePage = prediction.detectedDocumentType === 'singlePage';
14574
- if (!allowSinglePageIdCapture && isSinglePage) {
14575
- prediction.detectedDocumentType = 'passport';
14576
- prediction.passportDetectionScore = prediction.singlePageDetectionScore;
14577
- prediction.passportDetectionThresholdMet = prediction.singlePageDetectionThresholdMet;
14578
- prediction.singlePageDetectionScore = 0;
14579
- prediction.singlePageDetectionThresholdMet = false;
14580
- }
14581
- 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'));
14582
- if (isRequiredDocumentType && prediction.detectedDocumentType !== 'none' && prediction.detectionThresholdMet && prediction.documentInBounds && !prediction.documentTooClose && prediction.documentIsStable) {
14583
- focusPrediction = makeFocusPrediction(lastPredictionCanvas.current, (_c = prediction.bestDocument) === null || _c === void 0 ? void 0 : _c.box);
14584
- if (focusPrediction) {
14585
- focusScore = focusPrediction.score;
14586
- focusPredictionTime = focusPrediction.predictionTime;
14587
- }
14588
- focusThresholdSet = (_d = thresholds.focus) === null || _d === void 0 ? void 0 : _d[prediction.detectedDocumentType];
14589
- 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;
14590
- focusThresholdMet = focusScore >= focusThreshold;
14591
- if (bestFocusScore.current <= focusScore && stopDetectionAtStart === stopDetection.current) {
14592
- bestFocusScore.current = focusScore;
14593
- drawToCanvas(bestPredictionCanvas.current, lastPredictionCanvas.current);
14594
- bestFrameDetails.current = {
14595
- boundingBox: (_f = prediction.bestDocument) === null || _f === void 0 ? void 0 : _f.box,
14596
- documentType: prediction.detectedDocumentType,
14597
- detectionScore: prediction.detectionScore,
14598
- focusScore: focusScore
14599
- };
14600
- }
14633
+ switch (_h.label) {
14634
+ case 0:
14635
+ if (!lastPredictionCanvas.current) return [2 /*return*/];
14636
+ stopDetectionAtStart = stopDetection.current;
14637
+ focusPredictionTime = 0, focusScore = 0, focusThresholdMet = false, pdf417PredictionTime = 0, pdf417PredictionScore = 0, pdf417PredictionThresholdMet = false;
14638
+ isSinglePage = prediction.detectedDocumentType === 'singlePage';
14639
+ if (!allowSinglePageIdCapture && isSinglePage) {
14640
+ prediction.detectedDocumentType = 'passport';
14641
+ prediction.passportDetectionScore = prediction.singlePageDetectionScore;
14642
+ prediction.passportDetectionThresholdMet = prediction.singlePageDetectionThresholdMet;
14643
+ prediction.singlePageDetectionScore = 0;
14644
+ prediction.singlePageDetectionThresholdMet = false;
14645
+ }
14646
+ 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'));
14647
+ if (!(isRequiredDocumentType && prediction.detectedDocumentType !== 'none' && prediction.detectionThresholdMet && prediction.documentInBounds && !prediction.documentTooClose && prediction.documentIsStable)) return [3 /*break*/, 2];
14648
+ focusPrediction = makeFocusPrediction(lastPredictionCanvas.current, (_c = prediction.bestDocument) === null || _c === void 0 ? void 0 : _c.box);
14649
+ if (focusPrediction) {
14650
+ focusScore = focusPrediction.score;
14651
+ focusPredictionTime = focusPrediction.predictionTime;
14652
+ }
14653
+ focusThresholdSet = (_d = thresholds.focus) === null || _d === void 0 ? void 0 : _d[prediction.detectedDocumentType];
14654
+ 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;
14655
+ focusThresholdMet = focusScore >= focusThreshold;
14656
+ if (!(stopDetectionAtStart === stopDetection.current)) return [3 /*break*/, 2];
14657
+ if (bestFocusScore.current <= focusScore) {
14658
+ bestFocusScore.current = focusScore;
14659
+ drawToCanvas(bestPredictionCanvas.current, lastPredictionCanvas.current);
14660
+ bestFrameDetails.current = {
14661
+ boundingBox: (_f = prediction.bestDocument) === null || _f === void 0 ? void 0 : _f.box,
14662
+ documentType: prediction.detectedDocumentType,
14663
+ detectionScore: prediction.detectionScore,
14664
+ focusScore: focusScore
14665
+ };
14666
+ }
14667
+ if (!(enableBarcodeReadabilityModel && prediction.bestDocument && prediction.bestPDF417 && croppedDocumentCanvas.current)) return [3 /*break*/, 2];
14668
+ return [4 /*yield*/, analyzeBarcodeReadability(prediction, lastPredictionCanvas.current, croppedDocumentCanvas.current, bestBarcodeCanvas.current, bestBarcodeScore.current)];
14669
+ case 1:
14670
+ barcodeAnalysisResult = _h.sent();
14671
+ pdf417PredictionTime = barcodeAnalysisResult.pdf417PredictionTime;
14672
+ pdf417PredictionScore = barcodeAnalysisResult.pdf417PredictionScore;
14673
+ pdf417PredictionThresholdMet = barcodeAnalysisResult.pdf417PredictionThresholdMet;
14674
+ if (barcodeAnalysisResult.newBestBarcodeScore) {
14675
+ bestBarcodeScore.current = barcodeAnalysisResult.newBestBarcodeScore;
14676
+ }
14677
+ if (barcodeAnalysisResult.newBestBarcodeDetails) {
14678
+ bestBarcodeDetails.current = barcodeAnalysisResult.newBestBarcodeDetails;
14679
+ }
14680
+ _h.label = 2;
14681
+ case 2:
14682
+ /**
14683
+ * @note
14684
+ * This should ALWAYS be called.
14685
+ * Do not return early from this function unless
14686
+ * lastPredictionCanvas.current is not set
14687
+ */
14688
+ (_g = onPredictionHandler.current) === null || _g === void 0 ? void 0 : _g.call(onPredictionHandler, _assign(_assign({}, prediction), {
14689
+ focusScore: focusScore,
14690
+ focusPredictionTime: focusPredictionTime,
14691
+ focusThresholdMet: focusThresholdMet,
14692
+ pdf417PredictionTime: pdf417PredictionTime,
14693
+ pdf417PredictionScore: pdf417PredictionScore,
14694
+ pdf417PredictionThresholdMet: pdf417PredictionThresholdMet
14695
+ }));
14696
+ return [2 /*return*/];
14601
14697
  }
14602
- (_g = onPredictionHandler.current) === null || _g === void 0 ? void 0 : _g.call(onPredictionHandler, _assign(_assign({}, prediction), {
14603
- focusScore: focusScore,
14604
- focusPredictionTime: focusPredictionTime,
14605
- focusThresholdMet: focusThresholdMet
14606
- }));
14607
- return [2 /*return*/];
14608
14698
  });
14609
14699
  });
14610
14700
  });
14611
- }, [allowSinglePageIdCapture, lastPredictionCanvas, makeFocusPrediction, onDocumentDetected, requiredDocumentType, thresholds.focus]);
14612
- var modelError = documentDetectionModelError !== null && documentDetectionModelError !== void 0 ? documentDetectionModelError : focusModelError;
14701
+ }, [allowSinglePageIdCapture, analyzeBarcodeReadability, barcodeReadabilityThresholds, enableBarcodeReadabilityModel, lastPredictionCanvas, makeBarcodeReadabilityPrediction, makeFocusPrediction, onDocumentDetected, requiredDocumentType, thresholds.focus]);
14702
+ var modelError = (_b = documentDetectionModelError !== null && documentDetectionModelError !== void 0 ? documentDetectionModelError : focusModelError) !== null && _b !== void 0 ? _b : barcodeReadabilityModelError;
14613
14703
  React.useEffect(function handleModelErrors() {
14614
14704
  if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
14615
14705
  }, [modelError, onModelError]);
@@ -14622,9 +14712,15 @@
14622
14712
  canvas: bestPredictionCanvas.current
14623
14713
  });
14624
14714
  }, []);
14625
- var _f = React.useState(0),
14626
- canvasKey = _f[0],
14627
- setCanvasKey = _f[1];
14715
+ var getBestBarcode = React.useCallback(function () {
14716
+ if (!bestBarcodeDetails.current || !bestBarcodeCanvas.current) return null;
14717
+ return _assign(_assign({}, bestBarcodeDetails.current), {
14718
+ canvas: bestBarcodeCanvas.current
14719
+ });
14720
+ }, []);
14721
+ var _j = React.useState(0),
14722
+ canvasKey = _j[0],
14723
+ setCanvasKey = _j[1];
14628
14724
  var resetBestFrame = React.useCallback(function () {
14629
14725
  stopDetection.current += 1;
14630
14726
  setCanvasKey(function (n) {
@@ -14640,16 +14736,45 @@
14640
14736
  var load = React.useCallback(function () {
14641
14737
  loadDocumentDetectionModel();
14642
14738
  loadFocusModel();
14643
- }, [loadDocumentDetectionModel, loadFocusModel]);
14644
- var ready = documentDetectionModelState === 'ready' && focusModelState === 'ready';
14645
- var modelLoadState = ready ? 'ready' : documentDetectionModelState === 'warming' || focusModelState === 'warming' ? 'warming' : focusModelState === 'downloading' || documentDetectionModelState === 'downloading' ? 'downloading' : 'not-started';
14646
- var modelWarmingStartedAt = !documentDetectionModelWarmingStartedAt && !focusModelWarmingStartedAt ? null : Math.min.apply(Math, [documentDetectionModelWarmingStartedAt, focusModelWarmingStartedAt].filter(function (v) {
14647
- return v !== null;
14648
- }));
14739
+ if (enableBarcodeReadabilityModel) loadBarcodeReadabilityModel();
14740
+ }, [enableBarcodeReadabilityModel, loadBarcodeReadabilityModel, loadDocumentDetectionModel, loadFocusModel]);
14741
+ var _k = React.useMemo(function () {
14742
+ var modelStates = [documentDetectionModelState, focusModelState];
14743
+ var modelWarmingStartedAts = [documentDetectionModelWarmingStartedAt, focusModelWarmingStartedAt];
14744
+ var modelDownloadProgresses = [documentDetectionModelDownloadProgress, focusModelDownloadProgress];
14745
+ if (enableBarcodeReadabilityModel) {
14746
+ modelStates.push(barcodeReadabilityModelState);
14747
+ modelWarmingStartedAts.push(barcodeReadabilityModelWarmingStartedAt);
14748
+ modelDownloadProgresses.push(barcodeReadabilityModelDownloadProgress);
14749
+ }
14750
+ var ready = modelStates.every(function (state) {
14751
+ return state === 'ready';
14752
+ });
14753
+ return {
14754
+ ready: ready,
14755
+ modelLoadState: ready ? 'ready' : modelStates.some(function (state) {
14756
+ return state === 'warming';
14757
+ }) ? 'warming' : modelStates.some(function (state) {
14758
+ return state === 'downloading';
14759
+ }) ? 'downloading' : 'not-started',
14760
+ modelWarmingStartedAt: modelWarmingStartedAts.every(function (v) {
14761
+ return v === null;
14762
+ }) ? null : Math.min.apply(Math, modelWarmingStartedAts.filter(function (v) {
14763
+ return v !== null;
14764
+ })),
14765
+ modelDownloadProgress: modelDownloadProgresses.reduce(function (a, b) {
14766
+ return a + b;
14767
+ }, 0) / modelDownloadProgresses.length
14768
+ };
14769
+ }, [barcodeReadabilityModelDownloadProgress, barcodeReadabilityModelState, barcodeReadabilityModelWarmingStartedAt, documentDetectionModelDownloadProgress, documentDetectionModelState, documentDetectionModelWarmingStartedAt, enableBarcodeReadabilityModel, focusModelDownloadProgress, focusModelState, focusModelWarmingStartedAt]),
14770
+ ready = _k.ready,
14771
+ modelLoadState = _k.modelLoadState,
14772
+ modelWarmingStartedAt = _k.modelWarmingStartedAt,
14773
+ modelDownloadProgress = _k.modelDownloadProgress;
14649
14774
  var value = React.useMemo(function () {
14650
14775
  return {
14651
14776
  ready: ready,
14652
- modelDownloadProgress: (documentDetectionModelDownloadProgress + focusModelDownloadProgress) / 2,
14777
+ modelDownloadProgress: modelDownloadProgress,
14653
14778
  modelLoadState: modelLoadState,
14654
14779
  modelWarmingStartedAt: modelWarmingStartedAt,
14655
14780
  modelError: modelError,
@@ -14663,24 +14788,35 @@
14663
14788
  onPredictionMade: onPredictionMade,
14664
14789
  detectionTime: detectionTime,
14665
14790
  focusPredictionTime: focusPredictionTime,
14791
+ barcodeReadabilityPredictionTime: barcodeReadabilityPredictionTime,
14666
14792
  getBestFrame: getBestFrame,
14667
14793
  resetBestFrame: resetBestFrame,
14668
14794
  bestFrameDetails: bestFrameDetails,
14795
+ bestBarcodeDetails: bestBarcodeDetails,
14796
+ getBestBarcode: getBestBarcode,
14669
14797
  requiredDocumentType: requiredDocumentType,
14670
14798
  setRequiredDocumentType: setRequiredDocumentType
14671
14799
  };
14672
- }, [detectionTime, documentDetectionBoundaries, documentDetectionModelDownloadProgress, focusModelDownloadProgress, focusPredictionTime, getBestFrame, load, modelLoadState, modelError, modelWarmingStartedAt, onPredictionMade, ready, requiredDocumentType, resetBestFrame, setDocumentDetectionBoundaries, setThresholds, startDocumentDetection, stopDocumentDetection, thresholds]);
14800
+ }, [ready, modelDownloadProgress, modelLoadState, modelWarmingStartedAt, modelError, startDocumentDetection, stopDocumentDetection, load, thresholds, setThresholds, documentDetectionBoundaries, setDocumentDetectionBoundaries, onPredictionMade, detectionTime, focusPredictionTime, barcodeReadabilityPredictionTime, getBestFrame, resetBestFrame, getBestBarcode, requiredDocumentType]);
14673
14801
  return /*#__PURE__*/React.createElement(IdCaptureModelsContext.Provider, {
14674
14802
  value: value
14675
- }, /*#__PURE__*/React.createElement(InvisibleCanvas, {
14676
- key: canvasKey,
14803
+ }, /*#__PURE__*/React.createElement(InvisibleCanvasContainer, null, /*#__PURE__*/React.createElement(InvisibleCanvas, {
14804
+ key: "bf-".concat(canvasKey),
14677
14805
  ref: bestPredictionCanvas
14678
- }), children);
14806
+ }), /*#__PURE__*/React.createElement(InvisibleCanvas, {
14807
+ key: "bb-".concat(canvasKey),
14808
+ ref: bestBarcodeCanvas
14809
+ }), /*#__PURE__*/React.createElement(InvisibleCanvas, {
14810
+ key: "cd-".concat(canvasKey),
14811
+ ref: croppedDocumentCanvas
14812
+ })), children);
14679
14813
  }
14680
14814
  function IdCaptureModelsProvider(_a) {
14681
14815
  var children = _a.children,
14682
14816
  props = __rest(_a, ["children"]);
14683
- return /*#__PURE__*/React.createElement(DocumentDetectionModelProvider, _assign({}, props), /*#__PURE__*/React.createElement(FocusModelProvider, _assign({}, props), /*#__PURE__*/React.createElement(IdCaptureModelsProviderInner, _assign({}, props), children)));
14817
+ return /*#__PURE__*/React.createElement(DocumentDetectionModelProvider, _assign({}, props), /*#__PURE__*/React.createElement(FocusModelProvider, _assign({}, props), /*#__PURE__*/React.createElement(BarcodeReadabilityModelProvider, _assign({}, props, {
14818
+ shouldLoadModels: props.enableBarcodeReadabilityModel
14819
+ }), /*#__PURE__*/React.createElement(IdCaptureModelsProviderInner, _assign({}, props), children))));
14684
14820
  }
14685
14821
  function useIdCaptureModelsContext() {
14686
14822
  var context = React.useContext(IdCaptureModelsContext);
@@ -14773,7 +14909,7 @@
14773
14909
  });
14774
14910
  }
14775
14911
 
14776
- var CapturedDocumentTypeValues = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'selfie', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
14912
+ var CapturedDocumentTypeValues = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'selfie', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage', 'idBarcodeImage'];
14777
14913
 
14778
14914
  var acceptedDocumentTypesForIdCaptureRequirementOption = {
14779
14915
  idCardFront: ['idCardFront'],
@@ -15139,6 +15275,7 @@
15139
15275
  capturing: false,
15140
15276
  captureFailed: false,
15141
15277
  imageUrl: null,
15278
+ idBarcodeImage: null,
15142
15279
  captureState: 'initializing',
15143
15280
  capturedDocuments: {},
15144
15281
  captureRequirement: 'idCardOrPassport',
@@ -15418,6 +15555,17 @@
15418
15555
  }
15419
15556
  return newState;
15420
15557
  }
15558
+ case 'barcodeCaptured':
15559
+ return _reducer(state, {
15560
+ type: 'documentCaptured',
15561
+ payload: {
15562
+ imageData: action.payload.imageUrl,
15563
+ documentType: 'idBarcodeImage',
15564
+ width: 0,
15565
+ height: 0,
15566
+ barcodeReadabilityScore: action.payload.barcodeReadabilityScore
15567
+ }
15568
+ });
15421
15569
  case 'flipRequestCompleted':
15422
15570
  return _assign(_assign({}, state), {
15423
15571
  captureState: 'capturing',
@@ -15909,12 +16057,13 @@
15909
16057
  height = _q === void 0 ? 1 : _q;
15910
16058
  var state = useIdCaptureStore();
15911
16059
  var isRearFacing = useCameraStore().isRearFacing;
15912
- var _r = React.useContext(IdCaptureModelsContext),
16060
+ var _r = useIdCaptureModelsContext(),
15913
16061
  modelsReady = _r.ready,
15914
16062
  setThresholds = _r.setThresholds,
15915
16063
  detectionTime = _r.detectionTime,
15916
16064
  focusPredictionTime = _r.focusPredictionTime,
15917
- getBestFrame = _r.getBestFrame;
16065
+ getBestFrame = _r.getBestFrame,
16066
+ getBestBarcode = _r.getBestBarcode;
15918
16067
  React.useEffect(function () {
15919
16068
  return dispatchIdCaptureAction({
15920
16069
  type: 'captureInitialized'
@@ -15953,6 +16102,16 @@
15953
16102
  });
15954
16103
  return;
15955
16104
  }
16105
+ var bestBarcode = getBestBarcode();
16106
+ if (bestBarcode) {
16107
+ dispatchIdCaptureAction({
16108
+ type: 'barcodeCaptured',
16109
+ payload: {
16110
+ imageUrl: bestBarcode.canvas.toDataURL('image/jpeg', 0.95),
16111
+ barcodeReadabilityScore: bestBarcode.score
16112
+ }
16113
+ });
16114
+ }
15956
16115
  var canvas = bestFrame.canvas,
15957
16116
  documentType = bestFrame.documentType,
15958
16117
  boundingBox = bestFrame.boundingBox,
@@ -15969,21 +16128,22 @@
15969
16128
  });
15970
16129
  var capturedDocumentType = documentType;
15971
16130
  setTimeout(function () {
15972
- var _a;
15973
- var captureTime = new Date().getTime() - ((_a = state.captureStartedAt) !== null && _a !== void 0 ? _a : new Date()).getTime();
16131
+ var _a, _b;
16132
+ var captureTime = performance.now() - ((_a = state.captureStartedAt) !== null && _a !== void 0 ? _a : new Date()).getTime();
15974
16133
  var metadata = {
15975
16134
  autoCapture: 'Y',
15976
16135
  captureTime: captureTime,
15977
16136
  boundingBox: boundingBox,
15978
16137
  bestDetectionScore: detectionScore,
15979
- bestFocusScore: focusScore
16138
+ bestFocusScore: focusScore,
16139
+ bestBarcodeScore: (_b = bestBarcode === null || bestBarcode === void 0 ? void 0 : bestBarcode.score) !== null && _b !== void 0 ? _b : 0
15980
16140
  };
15981
16141
  onCapture === null || onCapture === void 0 ? void 0 : onCapture(imageUrl, width, height, capturedDocumentType, metadata);
15982
16142
  dispatchIdCaptureAction({
15983
16143
  type: 'captured'
15984
16144
  });
15985
16145
  }, 0);
15986
- }, [getBestFrame, onCapture, shouldCapture, state.captureStartedAt, state.requestedDocumentType]);
16146
+ }, [getBestBarcode, getBestFrame, onCapture, shouldCapture, state.captureStartedAt, state.requestedDocumentType]);
15987
16147
  var theme = styled.useTheme();
15988
16148
  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');
15989
16149
  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');
@@ -16798,7 +16958,7 @@
16798
16958
  };
16799
16959
  }, [ready]);
16800
16960
  var imageRef = React.useRef(null);
16801
- var timeSinceWarmingStarted = modelWarmingStartedAt ? new Date().getTime() - modelWarmingStartedAt : 0;
16961
+ var timeSinceWarmingStarted = modelWarmingStartedAt ? performance.now() - modelWarmingStartedAt : 0;
16802
16962
  var warmingProgress = timeSinceWarmingStarted / 5000.0;
16803
16963
  var modelLoadProgress = modelsReady ? 100 : modelDownloadProgress * 0.5 + warmingProgress * 49.0;
16804
16964
  useLoadProgressHooks({
@@ -17136,7 +17296,7 @@
17136
17296
  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"])));
17137
17297
  var templateObject_1$D, templateObject_2$y;
17138
17298
 
17139
- var imageDisplayOrder = ['idCardFront', 'idCardBack', 'passport', 'singlePage', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
17299
+ var imageDisplayOrder = ['idCardFront', 'idCardBack', 'idBarcodeImage', 'passport', 'singlePage', 'idFrontIrImage', 'idBackIrImage', 'idFrontUvImage', 'idBackUvImage'];
17140
17300
  var IdCaptureSuccess = function IdCaptureSuccess(_a) {
17141
17301
  var capturedDocuments = _a.capturedDocuments,
17142
17302
  onSubmitClick = _a.onSubmitClick,
@@ -17178,7 +17338,7 @@
17178
17338
  image: doc,
17179
17339
  className: classNames.image,
17180
17340
  alt: doc.documentType
17181
- }), debugMode && ( /*#__PURE__*/React.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)))));
17341
+ }), debugMode && ( /*#__PURE__*/React.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)))));
17182
17342
  }))), /*#__PURE__*/React.createElement(ButtonsColumn, {
17183
17343
  className: classNames.buttonsRow
17184
17344
  }, /*#__PURE__*/React.createElement(WideButton, {
@@ -19800,7 +19960,7 @@
19800
19960
  var _6 = React.useState(false),
19801
19961
  overlayDismissed = _6[0],
19802
19962
  setOverlayDismissed = _6[1];
19803
- var _7 = React.useContext(SubmissionContext),
19963
+ var _7 = useSubmissionContext(),
19804
19964
  submissionStatus = _7.submissionStatus,
19805
19965
  setIdFrontImage = _7.setIdFrontImage,
19806
19966
  setIdBackImage = _7.setIdBackImage,
@@ -19809,6 +19969,7 @@
19809
19969
  setIdBackIrImage = _7.setIdBackIrImage,
19810
19970
  setIdFrontUvImage = _7.setIdFrontUvImage,
19811
19971
  setIdBackUvImage = _7.setIdBackUvImage,
19972
+ setIdBarcodeImage = _7.setIdBarcodeImage,
19812
19973
  logIdFrontCaptureAttempt = _7.logIdFrontCaptureAttempt,
19813
19974
  logIdBackCaptureAttempt = _7.logIdBackCaptureAttempt;
19814
19975
  var _8 = useIdCaptureModelsContext(),
@@ -19909,7 +20070,7 @@
19909
20070
  });
19910
20071
  }, [logCaptureMetadata, onDocumentCaptured]);
19911
20072
  var onSubmitClick = React.useCallback(function () {
19912
- var _a, _b, _c, _d, _e, _f, _g, _h;
20073
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
19913
20074
  var docs = state.capturedDocuments;
19914
20075
  var submission = {
19915
20076
  idFrontImage: maybeDataUrlToBase64Sync((_a = docs.idCardFront) === null || _a === void 0 ? void 0 : _a.imageData),
@@ -19919,7 +20080,8 @@
19919
20080
  idFrontIrImage: maybeDataUrlToBase64Sync((_e = docs.idFrontIrImage) === null || _e === void 0 ? void 0 : _e.imageData),
19920
20081
  idBackIrImage: maybeDataUrlToBase64Sync((_f = docs.idBackIrImage) === null || _f === void 0 ? void 0 : _f.imageData),
19921
20082
  idFrontUvImage: maybeDataUrlToBase64Sync((_g = docs.idFrontUvImage) === null || _g === void 0 ? void 0 : _g.imageData),
19922
- idBackUvImage: maybeDataUrlToBase64Sync((_h = docs.idBackUvImage) === null || _h === void 0 ? void 0 : _h.imageData)
20083
+ idBackUvImage: maybeDataUrlToBase64Sync((_h = docs.idBackUvImage) === null || _h === void 0 ? void 0 : _h.imageData),
20084
+ idBarcodeImage: maybeDataUrlToBase64Sync((_j = docs.idBarcodeImage) === null || _j === void 0 ? void 0 : _j.imageData)
19923
20085
  };
19924
20086
  if (submission.idFrontImage) setIdFrontImage(submission.idFrontImage);
19925
20087
  if (submission.idBackImage) setIdBackImage(submission.idBackImage);
@@ -19929,11 +20091,12 @@
19929
20091
  if (submission.idBackIrImage) setIdBackIrImage(submission.idBackIrImage);
19930
20092
  if (submission.idFrontUvImage) setIdFrontUvImage(submission.idFrontUvImage);
19931
20093
  if (submission.idBackUvImage) setIdBackUvImage(submission.idBackUvImage);
20094
+ if (submission.idBarcodeImage) setIdBarcodeImage(submission.idBarcodeImage);
19932
20095
  if (releaseCameraAccessOnExit) releaseCameraAccess();
19933
20096
  setTimeout(function () {
19934
20097
  return onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess(submission);
19935
20098
  }, 0);
19936
- }, [onSuccess, releaseCameraAccess, releaseCameraAccessOnExit, setIdBackImage, setIdBackIrImage, setIdBackUvImage, setIdFrontImage, setIdFrontIrImage, setIdFrontUvImage, setPassportImage, state.capturedDocuments]);
20099
+ }, [onSuccess, releaseCameraAccess, releaseCameraAccessOnExit, setIdBarcodeImage, setIdBackImage, setIdBackIrImage, setIdBackUvImage, setIdFrontImage, setIdFrontIrImage, setIdFrontUvImage, setPassportImage, state.capturedDocuments]);
19937
20100
  var showSuccessScreen = useShowSuccessScreen(skipSuccessScreen, state.captureState === 'complete', onSubmitClick);
19938
20101
  var onRetryClick = React.useCallback(function () {
19939
20102
  return dispatchIdCaptureAction({
@@ -20723,59 +20886,397 @@
20723
20886
  fill: "white"
20724
20887
  }))))));
20725
20888
  }
20726
- function SelfieCaptureAnimatedMaskWithStatus(_a) {
20727
- var _b = _a.status,
20728
- status = _b === void 0 ? 'ready' : _b,
20729
- props = __rest(_a, ["status"]);
20730
- var _c = React.useState(1),
20731
- frame = _c[0],
20732
- setFrame = _c[1];
20733
- React.useEffect(function () {
20734
- if (status !== 'processing') {
20735
- setFrame(0);
20736
- return;
20737
- }
20738
- setFrame(1);
20739
- var interval = setInterval(function () {
20740
- setFrame(function (n) {
20741
- return (n + 1) % 6;
20742
- });
20743
- }, 250);
20744
- return function () {
20745
- clearInterval(interval);
20889
+ function SelfieCaptureAnimatedMaskWithStatus(_a) {
20890
+ var _b = _a.status,
20891
+ status = _b === void 0 ? 'ready' : _b,
20892
+ props = __rest(_a, ["status"]);
20893
+ var _c = React.useState(1),
20894
+ frame = _c[0],
20895
+ setFrame = _c[1];
20896
+ React.useEffect(function () {
20897
+ if (status !== 'processing') {
20898
+ setFrame(0);
20899
+ return;
20900
+ }
20901
+ setFrame(1);
20902
+ var interval = setInterval(function () {
20903
+ setFrame(function (n) {
20904
+ return (n + 1) % 6;
20905
+ });
20906
+ }, 250);
20907
+ return function () {
20908
+ clearInterval(interval);
20909
+ };
20910
+ }, [status]);
20911
+ return /*#__PURE__*/React.createElement(SelfieCaptureAnimatedMask, _assign({}, props, {
20912
+ frame: frame,
20913
+ status: status
20914
+ }));
20915
+ }
20916
+ var templateObject_1$o, templateObject_2$m, templateObject_3$g;
20917
+
20918
+ 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"])));
20919
+ 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"])));
20920
+ var FaceCaptureGuideOverlay = function FaceCaptureGuideOverlay(_a) {
20921
+ var _b = _a.classNames,
20922
+ classNames = _b === void 0 ? {} : _b,
20923
+ _c = _a.status,
20924
+ status = _c === void 0 ? 'ready' : _c,
20925
+ _d = _a.borderWidth,
20926
+ borderWidth = _d === void 0 ? 5 : _d,
20927
+ _e = _a.borderColor,
20928
+ borderColor = _e === void 0 ? 'white' : _e,
20929
+ _f = _a.borderOpacity,
20930
+ borderOpacity = _f === void 0 ? 0.8 : _f;
20931
+ return /*#__PURE__*/React.createElement(FaceCaptureGuideContainer, {
20932
+ className: classNames.container
20933
+ }, /*#__PURE__*/React.createElement(FaceCaptureGuideInner, null, /*#__PURE__*/React.createElement(SelfieCaptureAnimatedMaskWithStatus, {
20934
+ status: status,
20935
+ borderColor: borderColor,
20936
+ borderWidth: borderWidth,
20937
+ borderOpacity: borderOpacity,
20938
+ verticalAlign: "center"
20939
+ })));
20940
+ };
20941
+ var templateObject_1$n, templateObject_2$l;
20942
+
20943
+ var defaultSelfieCaptureModelLoadTimeoutMs = 45000;
20944
+ var detector = null;
20945
+ var detectorSettings = null;
20946
+ function loadFaceDetector() {
20947
+ return __awaiter(this, arguments, void 0, function (modelAssetPath) {
20948
+ var _a, _b;
20949
+ if (modelAssetPath === void 0) {
20950
+ modelAssetPath = defaultFaceDetectorModelPath;
20951
+ }
20952
+ return __generator(this, function (_c) {
20953
+ switch (_c.label) {
20954
+ case 0:
20955
+ if (detector && (detectorSettings === null || detectorSettings === void 0 ? void 0 : detectorSettings.modelAssetPath) === modelAssetPath) return [2 /*return*/, detector];
20956
+ closeFaceDetector();
20957
+ return [4 /*yield*/, preloadFaceDetectorDependencies()];
20958
+ case 1:
20959
+ _c.sent();
20960
+ if (modelCapabilities.delegate === 'NONE') {
20961
+ throw new Error('No available delegate for face detector.');
20962
+ }
20963
+ _b = (_a = ya).createFromOptions;
20964
+ return [4 /*yield*/, ao.forVisionTasks(visionTasksBasePath)];
20965
+ case 2:
20966
+ return [4 /*yield*/, _b.apply(_a, [_c.sent(), {
20967
+ // canvas: document.createElement('canvas'),
20968
+ baseOptions: {
20969
+ modelAssetPath: modelAssetPath,
20970
+ delegate: modelCapabilities.delegate
20971
+ },
20972
+ runningMode: 'VIDEO'
20973
+ }])];
20974
+ case 3:
20975
+ detector = _c.sent();
20976
+ detectorSettings = {
20977
+ modelAssetPath: modelAssetPath
20978
+ };
20979
+ return [2 /*return*/, detector];
20980
+ }
20981
+ });
20982
+ });
20983
+ }
20984
+ function closeFaceDetector() {
20985
+ detector === null || detector === void 0 ? void 0 : detector.close();
20986
+ detector = null;
20987
+ detectorSettings = null;
20988
+ }
20989
+ function useLoadFaceDetector(_a) {
20990
+ var onModelError = _a.onModelError,
20991
+ _b = _a.modelLoadTimeoutMs,
20992
+ modelLoadTimeoutMs = _b === void 0 ? defaultSelfieCaptureModelLoadTimeoutMs : _b,
20993
+ videoRef = _a.videoRef;
20994
+ var _c = React.useState('not-started'),
20995
+ modelLoadState = _c[0],
20996
+ setModelLoadState = _c[1];
20997
+ var _d = React.useState(0),
20998
+ modelDownloadProgress = _d[0],
20999
+ setModelDownloadProgress = _d[1];
21000
+ var _e = React.useState(null),
21001
+ modelWarmingStartedAt = _e[0],
21002
+ setModelWarmingStartedAt = _e[1];
21003
+ var _f = React.useState(null),
21004
+ modelError = _f[0],
21005
+ setModelError = _f[1];
21006
+ React.useEffect(function loadModel() {
21007
+ var _this = this;
21008
+ setModelLoadState('downloading');
21009
+ setModelWarmingStartedAt(null);
21010
+ var modelLoadTimeout = setTimeout(function () {
21011
+ setModelError(new Error('Model loading time limit exceeded.'));
21012
+ }, modelLoadTimeoutMs);
21013
+ function handleDownloadProgress(event) {
21014
+ setModelDownloadProgress(progressToPercentage(event.detail));
21015
+ }
21016
+ document.addEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
21017
+ var cancelVideoReady = function cancelVideoReady() {};
21018
+ loadFaceDetector().then(function (model) {
21019
+ return __awaiter(_this, void 0, void 0, function () {
21020
+ var _a, videoReady, cancel, cancelled;
21021
+ return __generator(this, function (_b) {
21022
+ switch (_b.label) {
21023
+ case 0:
21024
+ setModelDownloadProgress(100);
21025
+ clearTimeout(modelLoadTimeout);
21026
+ setModelLoadState('warming');
21027
+ setModelWarmingStartedAt(performance.now());
21028
+ return [4 /*yield*/, testFaceDetectionAgainstKnownImage(model)];
21029
+ case 1:
21030
+ _b.sent();
21031
+ _a = waitForVideoReady(videoRef), videoReady = _a[0], cancel = _a[1];
21032
+ cancelled = false;
21033
+ cancelVideoReady = function cancelVideoReady() {
21034
+ cancelled = true;
21035
+ cancel();
21036
+ };
21037
+ return [4 /*yield*/, videoReady];
21038
+ case 2:
21039
+ _b.sent();
21040
+ if (cancelled) return [2 /*return*/];
21041
+ model.detectForVideo(videoRef.current, performance.now());
21042
+ setModelLoadState('ready');
21043
+ return [2 /*return*/];
21044
+ }
21045
+ });
21046
+ });
21047
+ })["catch"](function (e) {
21048
+ setModelError(e);
21049
+ setModelLoadState('error');
21050
+ })["finally"](function () {
21051
+ clearTimeout(modelLoadTimeout);
21052
+ });
21053
+ return function () {
21054
+ log('unloading face detection model');
21055
+ cancelVideoReady();
21056
+ closeFaceDetector();
21057
+ clearTimeout(modelLoadTimeout);
21058
+ document.removeEventListener('idmission.preloadProgress.faceDetection', handleDownloadProgress);
21059
+ };
21060
+ }, [modelLoadTimeoutMs, videoRef]);
21061
+ React.useEffect(function handleModelError() {
21062
+ if (modelError) onModelError === null || onModelError === void 0 ? void 0 : onModelError(modelError);
21063
+ }, [modelError, onModelError]);
21064
+ return React.useMemo(function () {
21065
+ return {
21066
+ ready: modelLoadState === 'ready',
21067
+ modelLoadState: modelLoadState,
21068
+ modelDownloadProgress: modelDownloadProgress,
21069
+ modelWarmingStartedAt: modelWarmingStartedAt,
21070
+ modelError: modelError
21071
+ };
21072
+ }, [modelLoadState, modelDownloadProgress, modelWarmingStartedAt, modelError]);
21073
+ }
21074
+ var lastFaceDetectionAt = 0;
21075
+ var lastFaceDetectionTime = 0;
21076
+ function setLastFaceDetectionAt(time) {
21077
+ lastFaceDetectionTime = time - lastFaceDetectionAt;
21078
+ lastFaceDetectionAt = time;
21079
+ }
21080
+ var framesNeededSamples = [];
21081
+ function trackFramesNeeded(value, bufferLength) {
21082
+ if (bufferLength === void 0) {
21083
+ bufferLength = 25;
21084
+ }
21085
+ framesNeededSamples.unshift(value);
21086
+ if (framesNeededSamples.length > bufferLength) framesNeededSamples.length = bufferLength;
21087
+ }
21088
+ var lastNFaces = [];
21089
+ var lastNFacePairs = [];
21090
+ var lastNNoses = [];
21091
+ var lastNNosePairs = [];
21092
+ function trackFace(face, framesNeeded, frameWidth, frameHeight) {
21093
+ if (framesNeeded === void 0) {
21094
+ framesNeeded = 12;
21095
+ }
21096
+ var nose = face.keypoints[2];
21097
+ if (!nose) return;
21098
+ lastNFaces.unshift(face);
21099
+ lastNNoses.unshift(nose);
21100
+ if (lastNFaces.length > framesNeeded) lastNFaces.length = framesNeeded;
21101
+ if (lastNNoses.length > framesNeeded) lastNNoses.length = framesNeeded;
21102
+ if (lastNFaces.length > 1) {
21103
+ var lastFace = lastNFaces[1];
21104
+ var iou = calculateIoU(face.box, lastFace.box);
21105
+ lastNFacePairs.unshift({
21106
+ a: face,
21107
+ b: lastFace,
21108
+ iou: iou
21109
+ });
21110
+ if (lastNFacePairs.length > framesNeeded - 1) lastNFacePairs.length = framesNeeded - 1;
21111
+ }
21112
+ if (lastNNoses.length > 1) {
21113
+ var lastNose = lastNNoses[1];
21114
+ var noseDistance = Math.sqrt(Math.pow((nose.x - lastNose.x) / frameWidth, 2) + Math.pow((nose.y - lastNose.y) / frameHeight, 2));
21115
+ lastNNosePairs.unshift({
21116
+ a: nose,
21117
+ b: lastNose,
21118
+ distance: noseDistance
21119
+ });
21120
+ if (lastNNosePairs.length > framesNeeded - 1) lastNNosePairs.length = framesNeeded - 1;
21121
+ }
21122
+ }
21123
+ function makeFaceDetectorPrediction(imageData) {
21124
+ if (!detector) return null;
21125
+ var prediction = detector.detectForVideo(imageData, performance.now());
21126
+ var faces = prediction.detections.map(function (d) {
21127
+ return {
21128
+ box: convertBoundingBox(d.boundingBox),
21129
+ keypoints: d.keypoints.map(function (k) {
21130
+ var _a;
21131
+ return _assign(_assign({}, k), {
21132
+ x: k.x * imageData.width,
21133
+ y: k.y * imageData.height,
21134
+ name: (_a = k.label) !== null && _a !== void 0 ? _a : ''
21135
+ });
21136
+ })
20746
21137
  };
20747
- }, [status]);
20748
- return /*#__PURE__*/React.createElement(SelfieCaptureAnimatedMask, _assign({}, props, {
20749
- frame: frame,
20750
- status: status
20751
- }));
21138
+ });
21139
+ return _assign(_assign({}, prediction), {
21140
+ faces: faces
21141
+ });
21142
+ }
21143
+ function processFaceDetectorPrediction(_a) {
21144
+ var faces = _a.faces,
21145
+ videoWidth = _a.videoWidth,
21146
+ videoHeight = _a.videoHeight,
21147
+ _b = _a.requireVerticalFaceCentering,
21148
+ requireVerticalFaceCentering = _b === void 0 ? true : _b,
21149
+ _c = _a.stabilityThreshold,
21150
+ stabilityThreshold = _c === void 0 ? 0.7 : _c,
21151
+ _d = _a.noseDistanceThreshold,
21152
+ noseDistanceThreshold = _d === void 0 ? 0.025 : _d,
21153
+ _e = _a.xBoundary,
21154
+ xBoundary = _e === void 0 ? 0.01 : _e,
21155
+ // this represents the edge that the sides of the face box should not cross -- 1% of video width
21156
+ _f = _a.yBoundary,
21157
+ // this represents the edge that the sides of the face box should not cross -- 1% of video width
21158
+ yBoundary = _f === void 0 ? 0.01 : _f,
21159
+ // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
21160
+ _g = _a.xCentroidBoundary,
21161
+ // this represents the edge that the top or bottom of the face box should not cross -- 1% of video height
21162
+ xCentroidBoundary = _g === void 0 ? 0.125 : _g,
21163
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
21164
+ _h = _a.yCentroidBoundary,
21165
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video width
21166
+ yCentroidBoundary = _h === void 0 ? 0.125 : _h,
21167
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
21168
+ _j = _a.foreheadRatio,
21169
+ // this represents the edge that the centroid of the face should not cross -- 12.5% of video height
21170
+ foreheadRatio = _j === void 0 ? 0.275 : _j,
21171
+ // 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.
21172
+ _k = _a.noseTrackingThreshold,
21173
+ // 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.
21174
+ noseTrackingThreshold = _k === void 0 ? 0.2 : _k,
21175
+ // 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
21176
+ minCaptureBrightnessThreshold = _a.minCaptureBrightnessThreshold,
21177
+ minCaptureRangeThreshold = _a.minCaptureRangeThreshold,
21178
+ minCaptureVarianceThreshold = _a.minCaptureVarianceThreshold,
21179
+ brightness = _a.brightness,
21180
+ range = _a.range,
21181
+ variance = _a.variance;
21182
+ var face = faces[0];
21183
+ var faceNotDetected = faces.length === 0;
21184
+ var faceNotCentered = false,
21185
+ faceLookingAway = false,
21186
+ faceTooClose = false,
21187
+ faceTooFar = false,
21188
+ faceVisibilityTooLow = false;
21189
+ var hasAnyThreshold = minCaptureBrightnessThreshold !== undefined || minCaptureRangeThreshold !== undefined || minCaptureVarianceThreshold !== undefined;
21190
+ if (hasAnyThreshold) {
21191
+ var tooDark = minCaptureBrightnessThreshold !== undefined && brightness !== undefined && brightness < minCaptureBrightnessThreshold;
21192
+ var tooLowRange = minCaptureRangeThreshold !== undefined && range !== undefined && range < minCaptureRangeThreshold;
21193
+ var tooLowVariance = minCaptureVarianceThreshold !== undefined && variance !== undefined && variance < minCaptureVarianceThreshold;
21194
+ faceVisibilityTooLow = !!(tooDark || tooLowRange || tooLowVariance);
21195
+ }
21196
+ if (face && !faceVisibilityTooLow) {
21197
+ // calculate frame centroids
21198
+ var frameCX = videoWidth / 2;
21199
+ var frameCY = videoHeight / 2;
21200
+ // calculate head bounding box, with forehead extension
21201
+ var foreheadSize = face.box.height * foreheadRatio;
21202
+ var headXMin = face.box.xMin;
21203
+ var headXMax = face.box.xMax;
21204
+ var headYMin = face.box.yMin - foreheadSize;
21205
+ var headYMax = face.box.yMax;
21206
+ // calculate head centroids
21207
+ var headCX = (headXMin + headXMax) / 2;
21208
+ var headCY = (headYMin + headYMax) / 2;
21209
+ // calculate thresholds
21210
+ var vTX = videoWidth * xBoundary;
21211
+ var vTY = videoHeight * yBoundary;
21212
+ var vCTX = videoWidth * xCentroidBoundary;
21213
+ var vCTY = videoHeight * yCentroidBoundary;
21214
+ var faceNotCenteredHorizontally = Math.abs(frameCX - headCX) > vCTX;
21215
+ var faceNotCenteredVertically = Math.abs(frameCY - headCY) > vCTY;
21216
+ var faceViolatesHorizontalBoundary = headXMin < vTX || headXMax > videoWidth - vTX;
21217
+ var faceViolatesVerticalBoundary = headYMin < vTY || headYMax > videoHeight - vTY;
21218
+ faceNotCentered = faceViolatesHorizontalBoundary || faceViolatesVerticalBoundary || faceNotCenteredHorizontally || requireVerticalFaceCentering && faceNotCenteredVertically;
21219
+ var isMobile = videoWidth < videoHeight;
21220
+ var tooCloseMultiple = 1.5;
21221
+ var tooFarMultiple = isMobile ? 6 : 7;
21222
+ faceTooClose = face.box.width > videoWidth / tooCloseMultiple;
21223
+ faceTooFar = face.box.width < videoWidth / tooFarMultiple;
21224
+ var nose = face.keypoints[2];
21225
+ var fTW = face.box.width * noseTrackingThreshold;
21226
+ var fTH = face.box.height * noseTrackingThreshold;
21227
+ faceLookingAway = !nose || Math.abs(headCX - nose.x) > fTW || Math.abs(headCY - nose.y) > fTH;
21228
+ }
21229
+ var faceInGuides = !faceNotDetected && !faceNotCentered && !faceLookingAway && !faceTooClose && !faceTooFar;
21230
+ if (lastFaceDetectionTime > 0) {
21231
+ trackFramesNeeded(500 / lastFaceDetectionTime);
21232
+ }
21233
+ var faceIsStable = false,
21234
+ noseIsStable = false;
21235
+ if (faceInGuides && !faceVisibilityTooLow) {
21236
+ var framesNeeded = Math.max(Math.ceil(average(framesNeededSamples)), 5);
21237
+ trackFace(face, framesNeeded, videoWidth, videoHeight);
21238
+ faceIsStable = lastNFaces.length >= framesNeeded && !lastNFacePairs.some(function (pair) {
21239
+ return pair.iou < stabilityThreshold;
21240
+ });
21241
+ noseIsStable = lastNNoses.length >= framesNeeded && !lastNNosePairs.some(function (pair) {
21242
+ return pair.distance > noseDistanceThreshold;
21243
+ });
21244
+ }
21245
+ var faceReady = faceInGuides && faceIsStable && noseIsStable && !faceVisibilityTooLow;
21246
+ return {
21247
+ face: face,
21248
+ faceNotDetected: faceNotDetected,
21249
+ faceNotCentered: faceNotCentered,
21250
+ faceLookingAway: faceLookingAway,
21251
+ faceTooClose: faceTooClose,
21252
+ faceTooFar: faceTooFar,
21253
+ faceReady: faceReady,
21254
+ faceReadyAt: faceReady ? new Date() : null,
21255
+ faceIsStable: faceIsStable,
21256
+ noseIsStable: noseIsStable,
21257
+ faceVisibilityTooLow: faceVisibilityTooLow
21258
+ };
21259
+ }
21260
+ function testFaceDetectionAgainstKnownImage(detector) {
21261
+ return new Promise(function (resolve, reject) {
21262
+ var img = new Image();
21263
+ img.crossOrigin = 'anonymous';
21264
+ img.onload = function () {
21265
+ var prediction = detector.detectForVideo(img, performance.now());
21266
+ if (prediction.detections.length > 0) {
21267
+ debug('face detection test result', prediction.detections);
21268
+ resolve(void 0);
21269
+ } else {
21270
+ warn('face detection test failed');
21271
+ reject(new Error('testFaceDetectionAgainstKnownImage failed to predict'));
21272
+ }
21273
+ };
21274
+ img.onerror = function () {
21275
+ return reject(new Error('testFaceDetectionAgainstKnownImage failed to load image'));
21276
+ };
21277
+ img.src = "".concat(DEFAULT_CDN_URL, "/head-test.jpg");
21278
+ });
20752
21279
  }
20753
- var templateObject_1$o, templateObject_2$m, templateObject_3$g;
20754
-
20755
- 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"])));
20756
- 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"])));
20757
- var FaceCaptureGuideOverlay = function FaceCaptureGuideOverlay(_a) {
20758
- var _b = _a.classNames,
20759
- classNames = _b === void 0 ? {} : _b,
20760
- _c = _a.status,
20761
- status = _c === void 0 ? 'ready' : _c,
20762
- _d = _a.borderWidth,
20763
- borderWidth = _d === void 0 ? 5 : _d,
20764
- _e = _a.borderColor,
20765
- borderColor = _e === void 0 ? 'white' : _e,
20766
- _f = _a.borderOpacity,
20767
- borderOpacity = _f === void 0 ? 0.8 : _f;
20768
- return /*#__PURE__*/React.createElement(FaceCaptureGuideContainer, {
20769
- className: classNames.container
20770
- }, /*#__PURE__*/React.createElement(FaceCaptureGuideInner, null, /*#__PURE__*/React.createElement(SelfieCaptureAnimatedMaskWithStatus, {
20771
- status: status,
20772
- borderColor: borderColor,
20773
- borderWidth: borderWidth,
20774
- borderOpacity: borderOpacity,
20775
- verticalAlign: "center"
20776
- })));
20777
- };
20778
- var templateObject_1$n, templateObject_2$l;
20779
21280
 
20780
21281
  function detectBrightnessAndContrast(frame, brightnessAverager) {
20781
21282
  var ctx = frame.getContext('2d');
@@ -22069,7 +22570,7 @@
22069
22570
  });
22070
22571
  }, 3000);
22071
22572
  }, []);
22072
- var timeSinceWarmingStarted = modelWarmingStartedAt ? new Date().getTime() - modelWarmingStartedAt : 0;
22573
+ var timeSinceWarmingStarted = modelWarmingStartedAt ? performance.now() - modelWarmingStartedAt : 0;
22073
22574
  var warmingProgress = timeSinceWarmingStarted / 5000.0;
22074
22575
  var _o = React.useState(false),
22075
22576
  overrideModelsReady = _o[0],
@@ -23690,6 +24191,16 @@
23690
24191
  var AcceptBtn$1 = styled(LoaderButton)(templateObject_2$b || (templateObject_2$b = __makeTemplateObject(["\n margin-left: auto;\n"], ["\n margin-left: auto;\n"])));
23691
24192
  var templateObject_1$c, templateObject_2$b;
23692
24193
 
24194
+ function isBlob(blobPart) {
24195
+ return typeof Blob !== 'undefined' && blobPart instanceof Blob;
24196
+ }
24197
+ function inferBlobType(blobPart) {
24198
+ var _a;
24199
+ if (!isBlob(blobPart)) return undefined;
24200
+ var t = ((_a = blobPart.type) !== null && _a !== void 0 ? _a : '').trim();
24201
+ return t.length > 0 ? t : undefined;
24202
+ }
24203
+
23693
24204
  var videoRecorder = null;
23694
24205
  var audioRecorder = null;
23695
24206
  var videoChunks = [];
@@ -23823,8 +24334,9 @@
23823
24334
  useVideoRecorderStore.getState().clearRecordedData();
23824
24335
  }, []);
23825
24336
  var processVideo = React.useCallback(function () {
24337
+ var inferredType = inferBlobType(videoChunks[0]) || (videoRecorder === null || videoRecorder === void 0 ? void 0 : videoRecorder.mimeType) || 'video/mp4';
23826
24338
  var videoBlob = new Blob(videoChunks, {
23827
- type: 'video/mp4'
24339
+ type: inferredType
23828
24340
  });
23829
24341
  useVideoRecorderStore.setState({
23830
24342
  videoUrl: URL.createObjectURL(videoBlob),
@@ -23834,8 +24346,9 @@
23834
24346
  setVideoRecorder(null);
23835
24347
  }, []);
23836
24348
  var processAudio = React.useCallback(function () {
24349
+ var inferredType = inferBlobType(audioChunks[0]) || (audioRecorder === null || audioRecorder === void 0 ? void 0 : audioRecorder.mimeType) || 'audio/mp4';
23837
24350
  var audioBlob = new Blob(audioChunks, {
23838
- type: 'audio/mp4'
24351
+ type: inferredType
23839
24352
  });
23840
24353
  useVideoRecorderStore.setState({
23841
24354
  audioUrl: URL.createObjectURL(audioBlob),
@@ -23875,6 +24388,7 @@
23875
24388
  }, [audioRecordingIntentionallyStopped, audioRecordingStopped, audioUrl, isRecordingAudio, isRecordingVideo, videoRecordingIntentionallyStopped, videoRecordingStopped, videoUrl]);
23876
24389
  };
23877
24390
 
24391
+ var RECORDING_TIMESTAMP_PADDING_MS = 1000;
23878
24392
  var signatureRecorder = null;
23879
24393
  var signatureChunks = [];
23880
24394
  var videoSignatureInitialState = {
@@ -23887,7 +24401,6 @@
23887
24401
  clearRecordedData: function clearRecordedData() {
23888
24402
  return null;
23889
24403
  },
23890
- isRecording: false,
23891
24404
  signaturePad: {
23892
24405
  current: null
23893
24406
  },
@@ -23910,7 +24423,7 @@
23910
24423
  if (!camera) throw new Error('Camera not found');
23911
24424
  // set our flag and clear whatever we have recorded so far.
23912
24425
  set({
23913
- isRecording: true
24426
+ recordingStartedAt: performance.now()
23914
24427
  });
23915
24428
  signatureChunks = [];
23916
24429
  // start recording video and audio
@@ -23924,27 +24437,52 @@
23924
24437
  videoBitsPerSecond: 270000,
23925
24438
  audioBitsPerSecond: 32000
23926
24439
  });
24440
+ var hasFirstChunk = false;
23927
24441
  signatureRecorder.ondataavailable = function (event) {
23928
24442
  signatureChunks.push(event.data);
24443
+ if (!hasFirstChunk) {
24444
+ hasFirstChunk = true;
24445
+ set({
24446
+ firstChunkReceivedAt: performance.now(),
24447
+ lastChunkReceivedAt: performance.now()
24448
+ });
24449
+ } else {
24450
+ set({
24451
+ lastChunkReceivedAt: performance.now()
24452
+ });
24453
+ }
23929
24454
  };
23930
24455
  signatureRecorder.start(100);
23931
24456
  },
23932
24457
  stopRecording: function stopRecording(signatureData, imageUrl) {
23933
24458
  set({
23934
- isRecording: false
24459
+ firstChunkReceivedAt: undefined,
24460
+ recordingStoppedAt: performance.now()
24461
+ });
24462
+ waitForOneMoreChunk().then(function () {
24463
+ if (!signatureRecorder) return;
24464
+ signatureRecorder.stop();
24465
+ signatureRecorder.onstop = function () {
24466
+ var inferredType = inferBlobType(signatureChunks[0]) || (signatureRecorder === null || signatureRecorder === void 0 ? void 0 : signatureRecorder.mimeType) || 'video/mp4';
24467
+ var blob = new Blob(signatureChunks, {
24468
+ type: inferredType
24469
+ });
24470
+ signatureChunks = [];
24471
+ signatureRecorder = null;
24472
+ if (!signatureData) return;
24473
+ var _a = get(),
24474
+ onSignatureVideoCaptured = _a.onSignatureVideoCaptured,
24475
+ recordingStartedAt = _a.recordingStartedAt,
24476
+ signatureStartedAt = _a.signatureStartedAt,
24477
+ signatureEndedAt = _a.signatureEndedAt,
24478
+ lastChunkReceivedAt = _a.lastChunkReceivedAt;
24479
+ var endMs = Math.min(signatureEndedAt !== null && signatureEndedAt !== void 0 ? signatureEndedAt : Infinity, lastChunkReceivedAt !== null && lastChunkReceivedAt !== void 0 ? lastChunkReceivedAt : Infinity);
24480
+ var signatureStartTimestamp = signatureStartedAt && recordingStartedAt ? formatTimestamp(Math.max(0, signatureStartedAt - recordingStartedAt - RECORDING_TIMESTAMP_PADDING_MS)) : undefined;
24481
+ var signatureEndTimestamp = endMs !== Infinity && recordingStartedAt ? formatTimestamp(Math.min(endMs - recordingStartedAt + RECORDING_TIMESTAMP_PADDING_MS, lastChunkReceivedAt !== null && lastChunkReceivedAt !== void 0 ? lastChunkReceivedAt : Infinity)) : undefined;
24482
+ onSignatureVideoCaptured(blob, signatureData, imageUrl !== null && imageUrl !== void 0 ? imageUrl : null, signatureStartTimestamp, signatureEndTimestamp);
24483
+ };
24484
+ useVideoRecorderStore.getState().stopRecording();
23935
24485
  });
23936
- if (!signatureRecorder) return;
23937
- signatureRecorder.stop();
23938
- signatureRecorder.onstop = function () {
23939
- var blob = new Blob(signatureChunks, {
23940
- type: 'video/mp4'
23941
- });
23942
- signatureChunks = [];
23943
- signatureRecorder = null;
23944
- if (!signatureData) return;
23945
- get().onSignatureVideoCaptured(blob, signatureData, imageUrl !== null && imageUrl !== void 0 ? imageUrl : null);
23946
- };
23947
- useVideoRecorderStore.getState().stopRecording();
23948
24486
  },
23949
24487
  clearRecordedData: function clearRecordedData() {
23950
24488
  signatureChunks = [];
@@ -23953,13 +24491,42 @@
23953
24491
  signatureRecorder === null || signatureRecorder === void 0 ? void 0 : signatureRecorder.stop();
23954
24492
  signatureRecorder = null;
23955
24493
  set({
23956
- isRecording: false,
24494
+ recordingStartedAt: undefined,
24495
+ recordingStoppedAt: undefined,
24496
+ firstChunkReceivedAt: undefined,
24497
+ lastChunkReceivedAt: undefined,
23957
24498
  signaturePadEmpty: true,
23958
- signatureValid: false
24499
+ signatureValid: false,
24500
+ signatureStartedAt: undefined,
24501
+ signatureEndedAt: undefined
23959
24502
  });
23960
24503
  }
23961
24504
  });
23962
24505
  }));
24506
+ function waitForOneMoreChunk(timeoutMs) {
24507
+ if (timeoutMs === void 0) {
24508
+ timeoutMs = 3000;
24509
+ }
24510
+ var start = performance.now();
24511
+ return new Promise(function (resolve) {
24512
+ var initialLastChunkReceivedAt = useVideoSignatureStore.getState().lastChunkReceivedAt;
24513
+ if (!initialLastChunkReceivedAt) return resolve();
24514
+ function gotAChunk() {
24515
+ var lastChunkReceivedAt = useVideoSignatureStore.getState().lastChunkReceivedAt;
24516
+ return performance.now() - start > timeoutMs || !lastChunkReceivedAt || !initialLastChunkReceivedAt || lastChunkReceivedAt > initialLastChunkReceivedAt;
24517
+ }
24518
+ setTimeout(function () {
24519
+ if (gotAChunk()) return resolve(); // check immediately
24520
+ // otherwise, check every 100ms
24521
+ var interval = setInterval(function () {
24522
+ if (gotAChunk()) {
24523
+ clearInterval(interval);
24524
+ resolve();
24525
+ }
24526
+ }, 100);
24527
+ }, 0);
24528
+ });
24529
+ }
23963
24530
  function VideoSignatureContextProvider(_a) {
23964
24531
  var _this = this;
23965
24532
  var _b, _c;
@@ -23978,7 +24545,14 @@
23978
24545
  // clear recorded data when the component is mounted
23979
24546
  useVideoSignatureStore.getState().clearRecordedData();
23980
24547
  }, []);
23981
- var isRecording = useVideoSignatureStore().isRecording;
24548
+ var _e = useVideoSignatureStore(useShallow(function (state) {
24549
+ return {
24550
+ recordingStartedAt: state.recordingStartedAt,
24551
+ recordingStoppedAt: state.recordingStoppedAt
24552
+ };
24553
+ })),
24554
+ recordingStartedAt = _e.recordingStartedAt,
24555
+ recordingStoppedAt = _e.recordingStoppedAt;
23982
24556
  useFrameLoop(React.useCallback(function () {
23983
24557
  return __awaiter(_this, void 0, void 0, function () {
23984
24558
  var signaturePad, ctx, _a, w, h, isPortrait, rect;
@@ -24005,7 +24579,7 @@
24005
24579
  });
24006
24580
  });
24007
24581
  }, [videoRef]), {
24008
- autoStart: isRecording,
24582
+ autoStart: !!recordingStartedAt && !recordingStoppedAt,
24009
24583
  throttleMs: 1000 / 24
24010
24584
  });
24011
24585
  return /*#__PURE__*/React.createElement(React.Fragment, null, children, /*#__PURE__*/React.createElement(InvisibleCanvas, {
@@ -24014,6 +24588,17 @@
24014
24588
  height: (_c = videoRef.current) === null || _c === void 0 ? void 0 : _c.videoHeight
24015
24589
  }));
24016
24590
  }
24591
+ function formatTimestamp(durationMs) {
24592
+ // should be in the format of 00:00:00:00 (hh:mm:ss:cs)
24593
+ var hours = Math.floor(durationMs / 3600000);
24594
+ var minutes = Math.floor(durationMs % 3600000 / 60000);
24595
+ var seconds = Math.floor(durationMs % 60000 / 1000);
24596
+ var milliseconds = durationMs % 1000;
24597
+ // Convert milliseconds to centiseconds (1/100th of a second)
24598
+ var centiseconds = Math.floor(milliseconds / 10);
24599
+ var csString = centiseconds.toString().padStart(2, '0');
24600
+ return "".concat(hours.toString().padStart(2, '0'), ":") + "".concat(minutes.toString().padStart(2, '0'), ":") + "".concat(seconds.toString().padStart(2, '0'), ":") + "".concat(csString);
24601
+ }
24017
24602
 
24018
24603
  function VideoSignaturePad(_a) {
24019
24604
  var onAcceptBtnClicked = _a.onAcceptBtnClicked,
@@ -24075,8 +24660,11 @@
24075
24660
  ref: signaturePad,
24076
24661
  canvasProps: canvasProps,
24077
24662
  onBegin: function onBegin() {
24078
- return useVideoSignatureStore.setState({
24079
- signaturePadEmpty: false
24663
+ return useVideoSignatureStore.setState(function (s) {
24664
+ return {
24665
+ signaturePadEmpty: false,
24666
+ signatureStartedAt: s.signatureStartedAt || performance.now()
24667
+ };
24080
24668
  });
24081
24669
  },
24082
24670
  onEnd: function onEnd() {
@@ -24086,7 +24674,8 @@
24086
24674
  return point;
24087
24675
  });
24088
24676
  useVideoSignatureStore.setState({
24089
- signatureValid: points.length >= minSignaturePadPoints
24677
+ signatureValid: points.length >= minSignaturePadPoints,
24678
+ signatureEndedAt: performance.now()
24090
24679
  });
24091
24680
  }
24092
24681
  }), !headTrackingSatisfied && !!verbiage.headTrackingUnsatisfiedText ? ( /*#__PURE__*/React.createElement(SignaturePadContentContainer, {
@@ -24153,6 +24742,12 @@
24153
24742
  React.useEffect(function () {
24154
24743
  if (guideToDisplay) setMode(guideToDisplay);
24155
24744
  }, [guideToDisplay]);
24745
+ var firstChunkReceivedAt = useVideoSignatureStore(useShallow(function (state) {
24746
+ return {
24747
+ firstChunkReceivedAt: state.firstChunkReceivedAt
24748
+ };
24749
+ })).firstChunkReceivedAt;
24750
+ var signaturePadDisabled = requestedAction !== 'CAPTURE_SIGNATURE' || !firstChunkReceivedAt;
24156
24751
  return /*#__PURE__*/React.createElement(Container$3, {
24157
24752
  className: classNames.container
24158
24753
  }, /*#__PURE__*/React.createElement(Inner$1, {
@@ -24176,7 +24771,7 @@
24176
24771
  }, /*#__PURE__*/React.createElement(VideoSignaturePad, {
24177
24772
  onAcceptBtnClicked: onAcceptBtnClicked,
24178
24773
  onClearBtnClicked: onClearBtnClicked,
24179
- disabled: requestedAction !== 'CAPTURE_SIGNATURE',
24774
+ disabled: signaturePadDisabled,
24180
24775
  headTrackingSatisfied: headTrackingSatisfied,
24181
24776
  minSignaturePadPoints: minSignaturePadPoints,
24182
24777
  classNames: classNames,
@@ -24233,9 +24828,11 @@
24233
24828
  onHeadTrackingPredictionMade = _o.onPredictionMade,
24234
24829
  startHeadTracking = _o.start,
24235
24830
  stopHeadTracking = _o.stop;
24236
- var _p = useVideoSignatureStore(),
24237
- clearRecordedData = _p.clearRecordedData,
24238
- isRecording = _p.isRecording;
24831
+ var firstChunkReceivedAt = useVideoSignatureStore(useShallow(function (state) {
24832
+ return {
24833
+ firstChunkReceivedAt: state.firstChunkReceivedAt
24834
+ };
24835
+ })).firstChunkReceivedAt;
24239
24836
  React.useEffect(function () {
24240
24837
  useVideoSignatureStore.setState({
24241
24838
  onSignatureVideoCaptured: onSignatureVideoCaptured
@@ -24254,15 +24851,15 @@
24254
24851
  var verbiage = useTranslations(rawVerbiage, {
24255
24852
  guidanceMessageText: 'Please sign the box below'
24256
24853
  });
24257
- var _q = React.useState(true),
24258
- headTrackingSatisfied = _q[0],
24259
- setHeadTrackingSatisfied = _q[1];
24260
- var _r = React.useState(null),
24261
- lastFace = _r[0],
24262
- setLastFace = _r[1];
24263
- var _s = React.useState(0),
24264
- numFramesWithoutFaces = _s[0],
24265
- setNumFramesWithoutFaces = _s[1];
24854
+ var _p = React.useState(true),
24855
+ headTrackingSatisfied = _p[0],
24856
+ setHeadTrackingSatisfied = _p[1];
24857
+ var _q = React.useState(null),
24858
+ lastFace = _q[0],
24859
+ setLastFace = _q[1];
24860
+ var _r = React.useState(0),
24861
+ numFramesWithoutFaces = _r[0],
24862
+ setNumFramesWithoutFaces = _r[1];
24266
24863
  onHeadTrackingPredictionMade(f(React.useCallback(function (_a) {
24267
24864
  var face = _a.face;
24268
24865
  if (headTrackingDisabled) return;
@@ -24277,12 +24874,12 @@
24277
24874
  return n + 1;
24278
24875
  });
24279
24876
  }, [headTrackingBoundaryPercentage, headTrackingBoundaryType, headTrackingDisabled, videoHeight, videoWidth]), 16));
24280
- var _t = useResizeObserver(),
24281
- ref = _t.ref,
24282
- _u = _t.width,
24283
- width = _u === void 0 ? 1 : _u,
24284
- _v = _t.height,
24285
- height = _v === void 0 ? 1 : _v;
24877
+ var _s = useResizeObserver(),
24878
+ ref = _s.ref,
24879
+ _t = _s.width,
24880
+ width = _t === void 0 ? 1 : _t,
24881
+ _u = _s.height,
24882
+ height = _u === void 0 ? 1 : _u;
24286
24883
  var debugScalingDetails = useDebugScalingDetails({
24287
24884
  enabled: debugMode,
24288
24885
  pageWidth: width,
@@ -24313,13 +24910,19 @@
24313
24910
  classNames: classNames.guides,
24314
24911
  verbiage: rawVerbiage.guides,
24315
24912
  onClearBtnClicked: restartVideoOnSignaturePadCleared ? function () {
24316
- return setTimeout(clearRecordedData, 100);
24317
- } : undefined
24913
+ return setTimeout(function () {
24914
+ return useVideoSignatureStore.getState().clearRecordedData();
24915
+ }, 100);
24916
+ } : function () {
24917
+ return useVideoSignatureStore.setState({
24918
+ signatureStartedAt: undefined
24919
+ });
24920
+ }
24318
24921
  }), debugMode && ( /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ObjectDetectionDebugOverlayDiv, null, lastFace && ( /*#__PURE__*/React.createElement(SelfieCaptureFaceDebugBox, {
24319
24922
  face: lastFace,
24320
24923
  scaling: debugScalingDetails,
24321
24924
  color: headTrackingSatisfied ? 'green' : 'red'
24322
- }))), /*#__PURE__*/React.createElement(DebugStatsPane, null, "Video: ", videoWidth, "x", videoHeight, /*#__PURE__*/React.createElement("br", null), "Recording: ", isRecording ? 'true' : 'false'))), /*#__PURE__*/React.createElement(ExitCaptureButton, {
24925
+ }))), /*#__PURE__*/React.createElement(DebugStatsPane, null, "Video: ", videoWidth, "x", videoHeight, /*#__PURE__*/React.createElement("br", null), "Recording: ", firstChunkReceivedAt ? 'true' : 'false'))), /*#__PURE__*/React.createElement(ExitCaptureButton, {
24323
24926
  onClick: onExit,
24324
24927
  className: classNames.exitCaptureBtn
24325
24928
  }));
@@ -24650,6 +25253,8 @@
24650
25253
  setSelfieImage = _u.setSelfieImage,
24651
25254
  setSignatureData = _u.setSignatureData,
24652
25255
  setSignatureVideoUrl = _u.setSignatureVideoUrl,
25256
+ setSignatureStartTimestamp = _u.setSignatureStartTimestamp,
25257
+ setSignatureEndTimestamp = _u.setSignatureEndTimestamp,
24653
25258
  logSelfieCaptureAttempt = _u.logSelfieCaptureAttempt,
24654
25259
  uploadDocument = _u.uploadDocument;
24655
25260
  var cameraAccessDenied = useCameraStore(useShallow(function (state) {
@@ -24709,12 +25314,14 @@
24709
25314
  filetype: 'image/jpeg'
24710
25315
  }).then(onSelfieCaptured);
24711
25316
  }, [logCaptureMetadata, onSelfieCaptured, setSelfieImage, uploadDocument]);
24712
- var onSignatureCaptureCompleted = React.useCallback(function (videoData, signatureData, signatureImageData) {
25317
+ var onSignatureCaptureCompleted = React.useCallback(function (videoData, signatureData, signatureImageData, signatureStartTimestamp, signatureEndTimestamp) {
24713
25318
  setSignatureData(signatureData);
24714
25319
  setSignatureVideoUrl(URL.createObjectURL(videoData));
25320
+ if (signatureStartTimestamp) setSignatureStartTimestamp(signatureStartTimestamp);
25321
+ if (signatureEndTimestamp) setSignatureEndTimestamp(signatureEndTimestamp);
24715
25322
  setCaptureState('SUCCESS');
24716
- onVideoCaptured === null || onVideoCaptured === void 0 ? void 0 : onVideoCaptured(videoData, signatureData, signatureImageData);
24717
- }, [onVideoCaptured, setSignatureData, setSignatureVideoUrl]);
25323
+ onVideoCaptured === null || onVideoCaptured === void 0 ? void 0 : onVideoCaptured(videoData, signatureData, signatureImageData, signatureStartTimestamp, signatureEndTimestamp);
25324
+ }, [onVideoCaptured, setSignatureData, setSignatureEndTimestamp, setSignatureStartTimestamp, setSignatureVideoUrl]);
24718
25325
  var _x = React.useState(true),
24719
25326
  showLoadingOverlay = _x[0],
24720
25327
  setShowLoadingOverlay = _x[1];
@@ -24883,6 +25490,7 @@
24883
25490
  var onClearBtnClicked = React.useCallback(function () {
24884
25491
  var _a, _b;
24885
25492
  useVideoSignatureStore.setState({
25493
+ signatureStartedAt: undefined,
24886
25494
  signaturePadEmpty: true,
24887
25495
  signatureValid: false
24888
25496
  });