scandoc-ai-components 0.1.9 → 0.1.12

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 (2) hide show
  1. package/dist/index.js +131 -41
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -11367,7 +11367,7 @@ class ExtractorVideo {
11367
11367
  this.turnMessageTimer = null;
11368
11368
  this.stopVideo();
11369
11369
  if (isExtractionOk) {
11370
- this.showMessage("Success - data extracted", "success");
11370
+ this.showMessage("Success - data extracted", true);
11371
11371
  const shouldStop = this.onExtractedResults({
11372
11372
  success: true,
11373
11373
  code: "001",
@@ -11399,53 +11399,40 @@ class ExtractorVideo {
11399
11399
  this.scanStartTime = Date.now();
11400
11400
  const cfgValues = (0,_config__WEBPACK_IMPORTED_MODULE_1__.getScanDocAIConfigValues)();
11401
11401
  const mode = cfgValues.VIDEO_FACING_MODE ?? "environment";
11402
- const devices = await navigator.mediaDevices.enumerateDevices();
11403
- const environmentCameras = devices.filter(device => device.kind === "videoinput" && device.label.toLowerCase().includes("back"));
11404
- let deviceId;
11405
- if (mode === "environment") {
11406
- const af = await checkAutofocusSupport(environmentCameras);
11407
- deviceId = af[0]?.deviceId || environmentCameras[0]?.deviceId;
11408
- }
11409
- const buildConstraints = () => {
11410
- const base = {
11411
- ...ExtractorVideo.VIDEO_SETTINGS
11412
- };
11413
- if (typeof mode === "string") {
11414
- base.facingMode = {
11415
- ideal: mode
11416
- }; // "environment" | "user"
11417
- } else if (mode && typeof mode === "object") {
11418
- base.facingMode = mode; // e.g. { exact: "user" }
11419
- } else {
11420
- base.facingMode = {
11421
- ideal: "environment"
11422
- };
11423
- }
11424
- if (mode === "environment" && deviceId) {
11425
- base.deviceId = {
11426
- exact: deviceId
11427
- };
11428
- }
11429
- return {
11430
- video: base
11431
- };
11432
- };
11433
11402
  let stream;
11434
11403
  try {
11435
- stream = await navigator.mediaDevices.getUserMedia(buildConstraints());
11404
+ stream = await navigator.mediaDevices.getUserMedia(buildDocumentScanConstraints(mode));
11436
11405
  } catch (e) {
11406
+ console.warn("Preferred camera constraints failed, falling back:", e);
11437
11407
  stream = await navigator.mediaDevices.getUserMedia({
11438
- video: true
11408
+ video: true,
11409
+ audio: false
11439
11410
  });
11440
11411
  }
11441
11412
  this.video.srcObject = stream;
11442
- await this.video.play().catch(e => {
11413
+ try {
11414
+ await this.video.play();
11415
+ } catch (e) {
11443
11416
  console.warn(`Error on video play: ${e}`);
11444
- });
11445
- this.video.addEventListener('loadeddata', () => {
11446
- this.adjustOverlayPosition();
11447
- });
11448
- window.addEventListener('resize', () => this.adjustOverlayPosition());
11417
+ }
11418
+
11419
+ // Try to improve document focus after stream is active
11420
+ try {
11421
+ const focusResult = await tryEnableDocumentFocus(stream);
11422
+ console.log("Focus result:", focusResult);
11423
+ } catch (focusError) {
11424
+ console.warn("Could not apply focus settings:", focusError);
11425
+ }
11426
+
11427
+ // Avoid re-binding listeners every start
11428
+ if (!this._boundLoadedDataHandler) {
11429
+ this._boundLoadedDataHandler = () => this.adjustOverlayPosition();
11430
+ this.video.addEventListener("loadeddata", this._boundLoadedDataHandler);
11431
+ }
11432
+ if (!this._boundResizeHandler) {
11433
+ this._boundResizeHandler = () => this.adjustOverlayPosition();
11434
+ window.addEventListener("resize", this._boundResizeHandler);
11435
+ }
11449
11436
  setTimeout(() => this.adjustOverlayPosition(), 500);
11450
11437
  this.scanStartTime = Date.now();
11451
11438
  setTimeout(() => this.analyzeVideoStream(), ExtractorVideo.FREQUENCY_MS);
@@ -11524,7 +11511,8 @@ class ExtractorVideo {
11524
11511
  .mobileVideo {
11525
11512
  width: 100%;
11526
11513
  height: 100%;
11527
- object-fit: cover;
11514
+ object-fit: contain;
11515
+ object-position: center;
11528
11516
  pointer-events: none;
11529
11517
  }
11530
11518
  .mobileOverlay {
@@ -11678,6 +11666,108 @@ function getExtractionVideo(tokenOrCallback, maybeCallback) {
11678
11666
  }
11679
11667
  return EXTRACTION_VIDEO;
11680
11668
  }
11669
+ function getSupportedConstraintsSafe() {
11670
+ try {
11671
+ return navigator.mediaDevices?.getSupportedConstraints?.() || {};
11672
+ } catch (_) {
11673
+ return {};
11674
+ }
11675
+ }
11676
+ function buildDocumentScanConstraints(mode = "environment") {
11677
+ const supported = getSupportedConstraintsSafe();
11678
+ const video = {};
11679
+ if (supported.facingMode) {
11680
+ video.facingMode = typeof mode === "string" ? {
11681
+ ideal: mode
11682
+ } : mode || {
11683
+ ideal: "environment"
11684
+ };
11685
+ }
11686
+ if (supported.width) {
11687
+ video.width = {
11688
+ ideal: 1920
11689
+ };
11690
+ }
11691
+ if (supported.height) {
11692
+ video.height = {
11693
+ ideal: 1080
11694
+ };
11695
+ }
11696
+ if (supported.aspectRatio) {
11697
+ video.aspectRatio = {
11698
+ ideal: 16 / 9
11699
+ };
11700
+ }
11701
+ return {
11702
+ video,
11703
+ audio: false
11704
+ };
11705
+ }
11706
+ async function tryEnableDocumentFocus(stream) {
11707
+ const track = stream?.getVideoTracks?.()[0];
11708
+ if (!track) {
11709
+ return {
11710
+ ok: false,
11711
+ reason: "No video track found"
11712
+ };
11713
+ }
11714
+ if (!track.getCapabilities || !track.applyConstraints) {
11715
+ return {
11716
+ ok: false,
11717
+ reason: "Focus APIs unavailable on this browser/device",
11718
+ settingsBefore: track.getSettings ? track.getSettings() : null
11719
+ };
11720
+ }
11721
+ const caps = track.getCapabilities();
11722
+ const result = {
11723
+ ok: true,
11724
+ capabilities: caps,
11725
+ attempts: [],
11726
+ settingsBefore: track.getSettings ? track.getSettings() : null
11727
+ };
11728
+ try {
11729
+ let applied = false;
11730
+ if (Array.isArray(caps.focusMode) && caps.focusMode.includes("continuous")) {
11731
+ await track.applyConstraints({
11732
+ advanced: [{
11733
+ focusMode: "continuous"
11734
+ }]
11735
+ });
11736
+ result.attempts.push("Applied focusMode=continuous");
11737
+ applied = true;
11738
+ }
11739
+ if (caps.focusDistance) {
11740
+ const min = caps.focusDistance.min ?? 0;
11741
+ const max = caps.focusDistance.max ?? 0;
11742
+ const docDistance = min + (max - min) * 0.3;
11743
+ const advanced = [];
11744
+ if (Array.isArray(caps.focusMode) && caps.focusMode.includes("manual")) {
11745
+ advanced.push({
11746
+ focusMode: "manual"
11747
+ });
11748
+ }
11749
+ advanced.push({
11750
+ focusDistance: docDistance
11751
+ });
11752
+ await track.applyConstraints({
11753
+ advanced
11754
+ });
11755
+ result.attempts.push(`Applied focusDistance=${docDistance}`);
11756
+ applied = true;
11757
+ }
11758
+ if (!applied) {
11759
+ result.ok = false;
11760
+ result.reason = "No supported focus controls were exposed";
11761
+ }
11762
+ result.settingsAfter = track.getSettings ? track.getSettings() : null;
11763
+ return result;
11764
+ } catch (err) {
11765
+ result.ok = false;
11766
+ result.error = err.message || String(err);
11767
+ result.settingsAfter = track.getSettings ? track.getSettings() : null;
11768
+ return result;
11769
+ }
11770
+ }
11681
11771
  async function checkAutofocusSupport(environmentCameras) {
11682
11772
  try {
11683
11773
  const camerasWithAutofocus = [];
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "scandoc-ai-components",
3
3
  "author": "ScanDoc-AI",
4
- "version": "0.1.9",
4
+ "version": "0.1.12",
5
5
  "private": false,
6
6
  "description": "Pure JavaScript package for integrating ScanDoc-AI services.",
7
7
  "keywords": [