@neofaceid/web-sdk 1.39.1 → 1.40.1

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.
@@ -162,6 +162,7 @@ var ErrorType = /* @__PURE__ */ ((ErrorType2) => {
162
162
  ErrorType2["NOT_FOUND"] = "NotFoundError";
163
163
  ErrorType2["UNKNOWN"] = "UnknownError";
164
164
  ErrorType2["CONSENT_DENIED"] = "ConsentDeniedError";
165
+ ErrorType2["LIVENESS_BLINK_MISSING"] = "LivenessBlinkMissingError";
165
166
  return ErrorType2;
166
167
  })(ErrorType || {});
167
168
  class NeoFaceError extends Error {
@@ -199,6 +200,8 @@ class NeoFaceError extends Error {
199
200
  return "Dados inválidos ou rosto não detectado corretamente.";
200
201
  case "ConsentDeniedError":
201
202
  return "É necessário aceitar o uso do seu rosto para continuar.";
203
+ case "LivenessBlinkMissingError":
204
+ return "Não detectamos uma piscada. Pisque os olhos naturalmente e tente novamente.";
202
205
  case "ApiError":
203
206
  if (this.message.includes("400")) return "Requisição inválida. Tente novamente.";
204
207
  if (this.message.includes("500"))
@@ -4681,6 +4684,14 @@ function getLocale() {
4681
4684
  function getConsent() {
4682
4685
  return { ...globalConfig.consent };
4683
4686
  }
4687
+ async function withObjectURL(blob, fn) {
4688
+ const url = URL.createObjectURL(blob);
4689
+ try {
4690
+ return await fn(url);
4691
+ } finally {
4692
+ URL.revokeObjectURL(url);
4693
+ }
4694
+ }
4684
4695
  const getApiBaseUrl = () => getBaseUrl();
4685
4696
  const REQUEST_TIMEOUT = 1e4;
4686
4697
  const ensureSecureContext = () => {
@@ -4698,75 +4709,81 @@ const createTimeoutController = () => {
4698
4709
  controller.signal.addEventListener("abort", () => clearTimeout(timeoutId));
4699
4710
  return controller;
4700
4711
  };
4701
- const compressImage = async (imageBlob) => new Promise((resolve, reject) => {
4702
- const img = new Image();
4703
- img.onload = () => {
4704
- const canvas = document.createElement("canvas");
4705
- canvas.width = img.width;
4706
- canvas.height = img.height;
4707
- const ctx = canvas.getContext("2d");
4708
- if (!ctx) {
4709
- reject(new Error("Failed to get canvas context"));
4710
- return;
4711
- }
4712
- ctx.drawImage(img, 0, 0);
4713
- canvas.toBlob(
4714
- (blob) => {
4715
- if (blob) {
4716
- resolve(blob);
4717
- } else {
4718
- reject(new Error("Failed to compress image"));
4719
- }
4720
- },
4721
- "image/jpeg",
4722
- 0.7
4723
- );
4724
- };
4725
- img.onerror = () => {
4726
- reject(new Error("Failed to load image"));
4727
- };
4728
- img.src = URL.createObjectURL(imageBlob);
4729
- });
4730
- const compressDocumentImage = async (imageBlob) => new Promise((resolve, reject) => {
4731
- const img = new Image();
4732
- img.onload = () => {
4733
- const MAX_SIZE = 1280;
4734
- let { width } = img;
4735
- let { height } = img;
4736
- if (width > height && width > MAX_SIZE) {
4737
- height = height * MAX_SIZE / width;
4738
- width = MAX_SIZE;
4739
- } else if (height > MAX_SIZE) {
4740
- width = width * MAX_SIZE / height;
4741
- height = MAX_SIZE;
4742
- }
4743
- const canvas = document.createElement("canvas");
4744
- canvas.width = width;
4745
- canvas.height = height;
4746
- const ctx = canvas.getContext("2d");
4747
- if (!ctx) {
4748
- reject(new Error("Failed to get canvas context"));
4749
- return;
4750
- }
4751
- ctx.drawImage(img, 0, 0, width, height);
4752
- canvas.toBlob(
4753
- (blob) => {
4754
- if (blob) {
4755
- resolve(blob);
4756
- } else {
4757
- reject(new Error("Failed to compress document image"));
4758
- }
4759
- },
4760
- "image/jpeg",
4761
- 0.75
4762
- // 75% quality to keep file size manageable
4763
- );
4764
- };
4765
- img.onerror = () => {
4766
- reject(new Error("Failed to load document image"));
4767
- };
4768
- img.src = URL.createObjectURL(imageBlob);
4769
- });
4712
+ const compressImage = async (imageBlob) => withObjectURL(
4713
+ imageBlob,
4714
+ (url) => new Promise((resolve, reject) => {
4715
+ const img = new Image();
4716
+ img.onload = () => {
4717
+ const canvas = document.createElement("canvas");
4718
+ canvas.width = img.width;
4719
+ canvas.height = img.height;
4720
+ const ctx = canvas.getContext("2d");
4721
+ if (!ctx) {
4722
+ reject(new Error("Failed to get canvas context"));
4723
+ return;
4724
+ }
4725
+ ctx.drawImage(img, 0, 0);
4726
+ canvas.toBlob(
4727
+ (blob) => {
4728
+ if (blob) {
4729
+ resolve(blob);
4730
+ } else {
4731
+ reject(new Error("Failed to compress image"));
4732
+ }
4733
+ },
4734
+ "image/jpeg",
4735
+ 0.7
4736
+ );
4737
+ };
4738
+ img.onerror = () => {
4739
+ reject(new Error("Failed to load image"));
4740
+ };
4741
+ img.src = url;
4742
+ })
4743
+ );
4744
+ const compressDocumentImage = async (imageBlob) => withObjectURL(
4745
+ imageBlob,
4746
+ (url) => new Promise((resolve, reject) => {
4747
+ const img = new Image();
4748
+ img.onload = () => {
4749
+ const MAX_SIZE = 1280;
4750
+ let { width } = img;
4751
+ let { height } = img;
4752
+ if (width > height && width > MAX_SIZE) {
4753
+ height = height * MAX_SIZE / width;
4754
+ width = MAX_SIZE;
4755
+ } else if (height > MAX_SIZE) {
4756
+ width = width * MAX_SIZE / height;
4757
+ height = MAX_SIZE;
4758
+ }
4759
+ const canvas = document.createElement("canvas");
4760
+ canvas.width = width;
4761
+ canvas.height = height;
4762
+ const ctx = canvas.getContext("2d");
4763
+ if (!ctx) {
4764
+ reject(new Error("Failed to get canvas context"));
4765
+ return;
4766
+ }
4767
+ ctx.drawImage(img, 0, 0, width, height);
4768
+ canvas.toBlob(
4769
+ (blob) => {
4770
+ if (blob) {
4771
+ resolve(blob);
4772
+ } else {
4773
+ reject(new Error("Failed to compress document image"));
4774
+ }
4775
+ },
4776
+ "image/jpeg",
4777
+ 0.75
4778
+ // 75% quality to keep file size manageable
4779
+ );
4780
+ };
4781
+ img.onerror = () => {
4782
+ reject(new Error("Failed to load document image"));
4783
+ };
4784
+ img.src = url;
4785
+ })
4786
+ );
4770
4787
  const validateToken = async (applicationToken) => {
4771
4788
  ensureSecureContext();
4772
4789
  const controller = createTimeoutController();
@@ -6436,6 +6453,63 @@ function ScreenFlashOverlay({
6436
6453
  ] })
6437
6454
  ] });
6438
6455
  }
6456
+ const POLL_INTERVAL_MS = 50;
6457
+ const MIN_HORIZONTAL_DISTANCE = 1e-6;
6458
+ function distance(a, b) {
6459
+ return Math.hypot(a.x - b.x, a.y - b.y);
6460
+ }
6461
+ function calculateEAR(eyePoints) {
6462
+ if (eyePoints.length !== 6) {
6463
+ throw new Error(`calculateEAR espera exatamente 6 pontos do olho, recebeu ${eyePoints.length}`);
6464
+ }
6465
+ const [p1, p2, p3, p4, p5, p6] = eyePoints;
6466
+ const verticalA = distance(p2, p6);
6467
+ const verticalB = distance(p3, p5);
6468
+ const horizontal = distance(p1, p4);
6469
+ if (horizontal < MIN_HORIZONTAL_DISTANCE) return 0;
6470
+ return (verticalA + verticalB) / (2 * horizontal);
6471
+ }
6472
+ function detectBlinkInWindow(faceapi2, videoEl, windowMs = 3e3, threshold = 0.2, signal) {
6473
+ return new Promise((resolve) => {
6474
+ const deadline = Date.now() + windowMs;
6475
+ let eyesWereClosed = false;
6476
+ let isResolved = false;
6477
+ const finish = (result) => {
6478
+ if (isResolved) return;
6479
+ isResolved = true;
6480
+ resolve(result);
6481
+ };
6482
+ const checkFrame = () => {
6483
+ if (isResolved) return;
6484
+ if (signal == null ? void 0 : signal.aborted) {
6485
+ finish(false);
6486
+ return;
6487
+ }
6488
+ if (Date.now() >= deadline) {
6489
+ finish(false);
6490
+ return;
6491
+ }
6492
+ const detectionTask = faceapi2.detectSingleFace(videoEl, new faceapi2.TinyFaceDetectorOptions()).withFaceLandmarks();
6493
+ detectionTask.then((detection) => {
6494
+ if (detection) {
6495
+ const leftEAR = calculateEAR(detection.landmarks.getLeftEye());
6496
+ const rightEAR = calculateEAR(detection.landmarks.getRightEye());
6497
+ const ear = (leftEAR + rightEAR) / 2;
6498
+ if (ear < threshold) {
6499
+ eyesWereClosed = true;
6500
+ } else if (eyesWereClosed) {
6501
+ finish(true);
6502
+ return;
6503
+ }
6504
+ }
6505
+ setTimeout(checkFrame, POLL_INTERVAL_MS);
6506
+ }).catch(() => {
6507
+ setTimeout(checkFrame, POLL_INTERVAL_MS);
6508
+ });
6509
+ };
6510
+ checkFrame();
6511
+ });
6512
+ }
6439
6513
  const modalReducer$1 = (state, action) => {
6440
6514
  switch (action.type) {
6441
6515
  case "PERMISSION_GRANTED":
@@ -6582,6 +6656,8 @@ function FaceCaptureModal({
6582
6656
  const canvasRef = useRef(null);
6583
6657
  const streamRef = useRef(null);
6584
6658
  const faceDetectionTimeoutRef = useRef(null);
6659
+ const isCapturingRef = useRef(false);
6660
+ const blinkAbortControllerRef = useRef(null);
6585
6661
  const [state, dispatch] = useReducer(modalReducer$1, { status: "requestingPermission" });
6586
6662
  const [faceDetected, setFaceDetected] = useState(false);
6587
6663
  const { startCamera, stopCamera } = useCamera();
@@ -6617,6 +6693,13 @@ function FaceCaptureModal({
6617
6693
  useEffect(() => {
6618
6694
  injectThemeStyles();
6619
6695
  }, []);
6696
+ useEffect(
6697
+ () => () => {
6698
+ var _a2;
6699
+ (_a2 = blinkAbortControllerRef.current) == null ? void 0 : _a2.abort();
6700
+ },
6701
+ []
6702
+ );
6620
6703
  const flashEnabled = autoLighting && (state.status === "ready" || state.status === "capturing");
6621
6704
  const { flashOn } = useScreenFlash(videoRef, { enabled: flashEnabled });
6622
6705
  useEffect(() => {
@@ -6660,19 +6743,40 @@ function FaceCaptureModal({
6660
6743
  }, [startCamera, stopCamera]);
6661
6744
  const handleCapture = async () => {
6662
6745
  if (!canvasRef.current || !videoRef.current) return;
6746
+ if (isCapturingRef.current) return;
6747
+ isCapturingRef.current = true;
6748
+ const videoEl = videoRef.current;
6749
+ const canvasEl = canvasRef.current;
6750
+ const abortController = new AbortController();
6751
+ blinkAbortControllerRef.current = abortController;
6663
6752
  try {
6664
6753
  dispatch({ type: "START_CAPTURE" });
6665
- const context = canvasRef.current.getContext("2d");
6754
+ const blinkDetected = await detectBlinkInWindow(
6755
+ faceapi,
6756
+ videoEl,
6757
+ void 0,
6758
+ void 0,
6759
+ abortController.signal
6760
+ );
6761
+ if (abortController.signal.aborted) return;
6762
+ if (!blinkDetected) {
6763
+ const blinkError = new NeoFaceError(
6764
+ "Blink not detected within window",
6765
+ ErrorType.LIVENESS_BLINK_MISSING
6766
+ );
6767
+ dispatch({ type: "SET_ERROR", message: blinkError.getFriendlyMessage() });
6768
+ return;
6769
+ }
6770
+ const context = canvasEl.getContext("2d");
6666
6771
  if (!context) {
6667
6772
  dispatch({ type: "SET_ERROR", message: "Failed to get canvas context" });
6668
6773
  return;
6669
6774
  }
6670
- canvasRef.current.width = videoRef.current.videoWidth;
6671
- canvasRef.current.height = videoRef.current.videoHeight;
6672
- context.drawImage(videoRef.current, 0, 0, canvasRef.current.width, canvasRef.current.height);
6775
+ canvasEl.width = videoEl.videoWidth;
6776
+ canvasEl.height = videoEl.videoHeight;
6777
+ context.drawImage(videoEl, 0, 0, canvasEl.width, canvasEl.height);
6673
6778
  const blob = await new Promise((resolve, reject) => {
6674
- var _a2;
6675
- (_a2 = canvasRef.current) == null ? void 0 : _a2.toBlob(
6779
+ canvasEl.toBlob(
6676
6780
  (b) => {
6677
6781
  if (b) resolve(b);
6678
6782
  else reject(new Error("Failed to convert canvas to blob"));
@@ -6697,6 +6801,8 @@ function FaceCaptureModal({
6697
6801
  }
6698
6802
  } catch (error) {
6699
6803
  dispatch({ type: "SET_ERROR", message: "Failed to capture image" });
6804
+ } finally {
6805
+ isCapturingRef.current = false;
6700
6806
  }
6701
6807
  };
6702
6808
  const handleRetry = () => {
@@ -7735,6 +7841,7 @@ function BiometricRegistrationModal({
7735
7841
  if (onPhotosCaptured) {
7736
7842
  dispatch({ type: "SUCCESS" });
7737
7843
  onPhotosCaptured(photos);
7844
+ photos.length = 0;
7738
7845
  return;
7739
7846
  }
7740
7847
  if (!personData || !applicationToken) {
@@ -7754,6 +7861,7 @@ function BiometricRegistrationModal({
7754
7861
  dispatch({ type: "SUCCESS" });
7755
7862
  if (onSuccess) {
7756
7863
  onSuccess(adaptedResult);
7864
+ photos.length = 0;
7757
7865
  }
7758
7866
  } catch (error) {
7759
7867
  const errorMessage = error instanceof Error ? error.message : "Erro desconhecido";
@@ -8628,6 +8736,74 @@ function BiometricRegistrationModal({
8628
8736
  /* @__PURE__ */ jsx("canvas", { ref: canvasRef })
8629
8737
  ] });
8630
8738
  }
8739
+ const VERSION = "1.40.1";
8740
+ const RELEASE_DATE = "2026-09-09";
8741
+ const CONSENT_TRAIL_STORAGE_KEY = "neoface_consent_trail_v1";
8742
+ const CONSENT_TRAIL_MAX_LIMIT = 100;
8743
+ async function hashString(inputStr) {
8744
+ try {
8745
+ if (typeof crypto !== "undefined" && crypto.subtle && typeof crypto.subtle.digest === "function") {
8746
+ const encoder = new TextEncoder();
8747
+ const buffer = await crypto.subtle.digest("SHA-256", encoder.encode(inputStr));
8748
+ return Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
8749
+ }
8750
+ } catch {
8751
+ }
8752
+ return "sha256-unavailable";
8753
+ }
8754
+ function getConsentTrail() {
8755
+ try {
8756
+ if (typeof window === "undefined" || !window.localStorage) {
8757
+ return [];
8758
+ }
8759
+ const rawData = window.localStorage.getItem(CONSENT_TRAIL_STORAGE_KEY);
8760
+ if (!rawData) {
8761
+ return [];
8762
+ }
8763
+ const parsed = JSON.parse(rawData);
8764
+ if (Array.isArray(parsed)) {
8765
+ return parsed;
8766
+ }
8767
+ return [];
8768
+ } catch {
8769
+ return [];
8770
+ }
8771
+ }
8772
+ function clearConsentTrail() {
8773
+ try {
8774
+ if (typeof window !== "undefined" && window.localStorage) {
8775
+ window.localStorage.removeItem(CONSENT_TRAIL_STORAGE_KEY);
8776
+ }
8777
+ } catch {
8778
+ }
8779
+ }
8780
+ async function recordConsent(customConsent) {
8781
+ try {
8782
+ const configConsent = getConsent();
8783
+ const purpose = (customConsent == null ? void 0 : customConsent.purpose) ?? configConsent.purpose ?? "authentication";
8784
+ const legalBasis = (customConsent == null ? void 0 : customConsent.legalBasis) ?? configConsent.legalBasis ?? "fraud_prevention";
8785
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
8786
+ const userAgent = typeof navigator !== "undefined" ? navigator.userAgent : "";
8787
+ const sdkVersion = VERSION;
8788
+ const hash = await hashString(`${userAgent}${purpose}${timestamp}`);
8789
+ const record = {
8790
+ hash,
8791
+ timestamp,
8792
+ purpose,
8793
+ legalBasis,
8794
+ sdkVersion
8795
+ };
8796
+ const currentTrail = getConsentTrail();
8797
+ currentTrail.push(record);
8798
+ const updatedTrail = currentTrail.slice(-CONSENT_TRAIL_MAX_LIMIT);
8799
+ if (typeof window !== "undefined" && window.localStorage) {
8800
+ window.localStorage.setItem(CONSENT_TRAIL_STORAGE_KEY, JSON.stringify(updatedTrail));
8801
+ }
8802
+ return record;
8803
+ } catch {
8804
+ return null;
8805
+ }
8806
+ }
8631
8807
  const DEFAULT_PRIVACY_URL = "https://neofaceid.com/privacidade";
8632
8808
  const DEFAULT_RETENTION_DAYS = 90;
8633
8809
  const COPY = {
@@ -8919,7 +9095,11 @@ function ConsentModalComponent({
8919
9095
  {
8920
9096
  type: "button",
8921
9097
  className: "neofaceid-consent-button neofaceid-consent-button-primary",
8922
- onClick: onAccept,
9098
+ onClick: () => {
9099
+ recordConsent().catch(() => {
9100
+ });
9101
+ onAccept();
9102
+ },
8923
9103
  children: copy.primary
8924
9104
  }
8925
9105
  ),
@@ -11163,8 +11343,6 @@ const biometricDetection = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.
11163
11343
  initializeBiometricDetection,
11164
11344
  isAdvancedDetectionAvailable
11165
11345
  }, Symbol.toStringTag, { value: "Module" }));
11166
- const VERSION = "1.39.1";
11167
- const RELEASE_DATE = "2026-09-08";
11168
11346
  let cachedSession = null;
11169
11347
  function getCachedCaptureSession() {
11170
11348
  return cachedSession;
@@ -12130,11 +12308,13 @@ const authorizeOperation = async (applicationToken, cpf, options) => {
12130
12308
  sessionData
12131
12309
  );
12132
12310
  if (!recognitionResult.success) {
12311
+ capturedPhotos.length = 0;
12133
12312
  throw new NeoFaceError(
12134
12313
  "Authorization failed: Person not recognized",
12135
12314
  ErrorType.RECOGNITION_FAILED
12136
12315
  );
12137
12316
  }
12317
+ capturedPhotos.length = 0;
12138
12318
  return {
12139
12319
  success: true,
12140
12320
  authorizationHash: sessionData.sessionId,
@@ -13117,6 +13297,7 @@ class DocumentCaptureModal {
13117
13297
  __publicField(this, "flashController", null);
13118
13298
  __publicField(this, "frontBlob", null);
13119
13299
  __publicField(this, "backBlob", null);
13300
+ __publicField(this, "_previewObjectUrl", null);
13120
13301
  this.options = {
13121
13302
  title: (options == null ? void 0 : options.title) ?? "Validação de Identidade",
13122
13303
  subtitle: (options == null ? void 0 : options.subtitle) ?? "Selecione o tipo de documento",
@@ -13422,47 +13603,50 @@ class DocumentCaptureModal {
13422
13603
  }
13423
13604
  }
13424
13605
  compressUploadedImage(file) {
13425
- return new Promise((resolve, reject) => {
13426
- const img = new Image();
13427
- img.onload = () => {
13428
- const MAX_SIZE = 1280;
13429
- let { width } = img;
13430
- let { height } = img;
13431
- if (width > height && width > MAX_SIZE) {
13432
- height = height * MAX_SIZE / width;
13433
- width = MAX_SIZE;
13434
- } else if (height > MAX_SIZE) {
13435
- width = width * MAX_SIZE / height;
13436
- height = MAX_SIZE;
13437
- }
13438
- const canvas = document.createElement("canvas");
13439
- canvas.width = width;
13440
- canvas.height = height;
13441
- const ctx = canvas.getContext("2d");
13442
- if (!ctx) {
13443
- reject(new Error("Failed to get canvas context"));
13444
- return;
13445
- }
13446
- ctx.drawImage(img, 0, 0, width, height);
13447
- canvas.toBlob(
13448
- (blob) => {
13449
- if (blob) {
13450
- console.log(
13451
- `[DocumentCapture] Compressed image from ${(file.size / 1024).toFixed(0)}KB to ${(blob.size / 1024).toFixed(0)}KB`
13452
- );
13453
- resolve(blob);
13454
- } else {
13455
- reject(new Error("Failed to compress image"));
13456
- }
13457
- },
13458
- "image/jpeg",
13459
- 0.75
13460
- // 75% quality - keeps file size manageable for server limits
13461
- );
13462
- };
13463
- img.onerror = () => reject(new Error("Failed to load image"));
13464
- img.src = URL.createObjectURL(file);
13465
- });
13606
+ return withObjectURL(
13607
+ file,
13608
+ (url) => new Promise((resolve, reject) => {
13609
+ const img = new Image();
13610
+ img.onload = () => {
13611
+ const MAX_SIZE = 1280;
13612
+ let { width } = img;
13613
+ let { height } = img;
13614
+ if (width > height && width > MAX_SIZE) {
13615
+ height = height * MAX_SIZE / width;
13616
+ width = MAX_SIZE;
13617
+ } else if (height > MAX_SIZE) {
13618
+ width = width * MAX_SIZE / height;
13619
+ height = MAX_SIZE;
13620
+ }
13621
+ const canvas = document.createElement("canvas");
13622
+ canvas.width = width;
13623
+ canvas.height = height;
13624
+ const ctx = canvas.getContext("2d");
13625
+ if (!ctx) {
13626
+ reject(new Error("Failed to get canvas context"));
13627
+ return;
13628
+ }
13629
+ ctx.drawImage(img, 0, 0, width, height);
13630
+ canvas.toBlob(
13631
+ (blob) => {
13632
+ if (blob) {
13633
+ console.log(
13634
+ `[DocumentCapture] Compressed image from ${(file.size / 1024).toFixed(0)}KB to ${(blob.size / 1024).toFixed(0)}KB`
13635
+ );
13636
+ resolve(blob);
13637
+ } else {
13638
+ reject(new Error("Failed to compress image"));
13639
+ }
13640
+ },
13641
+ "image/jpeg",
13642
+ 0.75
13643
+ // 75% quality - keeps file size manageable for server limits
13644
+ );
13645
+ };
13646
+ img.onerror = () => reject(new Error("Failed to load image"));
13647
+ img.src = url;
13648
+ })
13649
+ );
13466
13650
  }
13467
13651
  bindPreviewEvents() {
13468
13652
  var _a2, _b, _c;
@@ -13475,7 +13659,14 @@ class DocumentCaptureModal {
13475
13659
  );
13476
13660
  if (previewImg) {
13477
13661
  const blob = this.currentStep === "preview-front" ? this.frontBlob : this.backBlob;
13478
- if (blob) previewImg.src = URL.createObjectURL(blob);
13662
+ if (blob) {
13663
+ if (this._previewObjectUrl) {
13664
+ URL.revokeObjectURL(this._previewObjectUrl);
13665
+ this._previewObjectUrl = null;
13666
+ }
13667
+ this._previewObjectUrl = URL.createObjectURL(blob);
13668
+ previewImg.src = this._previewObjectUrl;
13669
+ }
13479
13670
  }
13480
13671
  this.bindCloseEvent();
13481
13672
  }
@@ -13662,6 +13853,10 @@ class DocumentCaptureModal {
13662
13853
  }
13663
13854
  close() {
13664
13855
  this.stopCamera();
13856
+ if (this._previewObjectUrl) {
13857
+ URL.revokeObjectURL(this._previewObjectUrl);
13858
+ this._previewObjectUrl = null;
13859
+ }
13665
13860
  if (this.overlay) {
13666
13861
  this.overlay.remove();
13667
13862
  this.overlay = null;
@@ -14262,6 +14457,7 @@ export {
14262
14457
  authorize,
14263
14458
  authorizeOperation,
14264
14459
  checkUserExistence,
14460
+ clearConsentTrail,
14265
14461
  completeOnboarding,
14266
14462
  completeOnboardingWithData,
14267
14463
  confirmPasswordReset,
@@ -14273,6 +14469,7 @@ export {
14273
14469
  getCachedCaptureSession,
14274
14470
  getConfig,
14275
14471
  getConsent,
14472
+ getConsentTrail,
14276
14473
  getEnvironment,
14277
14474
  getLocale,
14278
14475
  getRadius,
@@ -14291,6 +14488,7 @@ export {
14291
14488
  recognize,
14292
14489
  recognizeBiometric,
14293
14490
  recognizeByPurpose,
14491
+ recordConsent,
14294
14492
  registerBiometric,
14295
14493
  registerPersonWithBiometric,
14296
14494
  registerPersonWithoutFace,