@jaak.ai/stamps 2.0.0-beta.4 → 2.0.0-beta.6

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 (29) hide show
  1. package/README.md +660 -510
  2. package/dist/cjs/jaak-stamps-webcomponent.cjs.js +1 -1
  3. package/dist/cjs/jaak-stamps.cjs.entry.js +241 -41
  4. package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
  5. package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
  6. package/dist/cjs/loader.cjs.js +1 -1
  7. package/dist/collection/components/my-component/my-component.css +54 -24
  8. package/dist/collection/components/my-component/my-component.js +91 -5
  9. package/dist/collection/components/my-component/my-component.js.map +1 -1
  10. package/dist/collection/services/CameraService.js +158 -21
  11. package/dist/collection/services/CameraService.js.map +1 -1
  12. package/dist/collection/services/DetectionService.js +34 -16
  13. package/dist/collection/services/DetectionService.js.map +1 -1
  14. package/dist/components/jaak-stamps.js +244 -41
  15. package/dist/components/jaak-stamps.js.map +1 -1
  16. package/dist/esm/jaak-stamps-webcomponent.js +1 -1
  17. package/dist/esm/jaak-stamps.entry.js +241 -41
  18. package/dist/esm/jaak-stamps.entry.js.map +1 -1
  19. package/dist/esm/loader.js +1 -1
  20. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
  21. package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
  22. package/dist/jaak-stamps-webcomponent/p-65990bdd.entry.js +2 -0
  23. package/dist/jaak-stamps-webcomponent/p-65990bdd.entry.js.map +1 -0
  24. package/dist/types/components/my-component/my-component.d.ts +6 -0
  25. package/dist/types/components.d.ts +18 -2
  26. package/dist/types/services/CameraService.d.ts +1 -0
  27. package/package.json +2 -2
  28. package/dist/jaak-stamps-webcomponent/p-10ee2dab.entry.js +0 -2
  29. package/dist/jaak-stamps-webcomponent/p-10ee2dab.entry.js.map +0 -1
@@ -5,7 +5,7 @@ var index = require('./index-BfhtOB0D.js');
5
5
  const defineCustomElements = async (win, options) => {
6
6
  if (typeof window === 'undefined') return undefined;
7
7
  await index.globalScripts();
8
- return index.bootstrapLazy([["jaak-stamps.cjs",[[1,"jaak-stamps",{"debug":[4],"alignmentTolerance":[2,"alignment-tolerance"],"maskSize":[2,"mask-size"],"cropMargin":[2,"crop-margin"],"useDocumentClassification":[4,"use-document-classification"],"preferredCamera":[1,"preferred-camera"],"captureDelay":[2,"capture-delay"],"detectionBoxes":[32],"sideAlignment":[32],"isMaskReady":[32],"shouldMirrorVideo":[32],"showCameraSelector":[32],"isSwitchingCamera":[32],"hasDocumentDetected":[32],"currentStatus":[32],"performanceData":[32],"getCapturedImages":[64],"isProcessCompleted":[64],"startCapture":[64],"stopCapture":[64],"resetCapture":[64],"skipBackCapture":[64],"getStatus":[64],"preloadModel":[64],"getCameraInfo":[64],"setPreferredCamera":[64],"setCaptureDelay":[64],"getCaptureDelay":[64],"setTorchEnabled":[64],"focusAtPoint":[64]}]]]], options);
8
+ return index.bootstrapLazy([["jaak-stamps.cjs",[[1,"jaak-stamps",{"debug":[4],"alignmentTolerance":[2,"alignment-tolerance"],"maskSize":[2,"mask-size"],"cropMargin":[2,"crop-margin"],"useDocumentClassification":[4,"use-document-classification"],"preferredCamera":[1,"preferred-camera"],"captureDelay":[2,"capture-delay"],"enableBackDocumentTimer":[4,"enable-back-document-timer"],"backDocumentTimerDuration":[2,"back-document-timer-duration"],"detectionBoxes":[32],"sideAlignment":[32],"isMaskReady":[32],"shouldMirrorVideo":[32],"showCameraSelector":[32],"isSwitchingCamera":[32],"hasDocumentDetected":[32],"currentStatus":[32],"performanceData":[32],"backDocumentTimerRemaining":[32],"getCapturedImages":[64],"isProcessCompleted":[64],"startCapture":[64],"stopCapture":[64],"resetCapture":[64],"skipBackCapture":[64],"getStatus":[64],"preloadModel":[64],"getCameraInfo":[64],"setPreferredCamera":[64],"setCaptureDelay":[64],"getCaptureDelay":[64],"setTorchEnabled":[64],"focusAtPoint":[64]}]]]], options);
9
9
  };
10
10
 
11
11
  exports.setNonce = index.setNonce;
@@ -42,13 +42,13 @@ video.mirror, .detection-overlay.mirror {
42
42
  transform: rotateY(180deg);
43
43
  }
44
44
 
45
- .detection-overlay {
46
- z-index: 1;
45
+ .detection-overlay {
46
+ z-index: 1;
47
47
  pointer-events: none;
48
48
  }
49
49
 
50
- video {
51
- z-index: 0;
50
+ video {
51
+ z-index: 0;
52
52
  }
53
53
 
54
54
  /* Detection boxes for debug mode */
@@ -175,11 +175,13 @@ video {
175
175
  font-weight: 600;
176
176
  text-align: center;
177
177
  white-space: normal;
178
- background: rgba(128, 128, 128, 0.8);
178
+ background: rgba(0, 0, 0, 0.25);
179
+ backdrop-filter: blur(12px);
179
180
  padding: 12px 20px;
180
- border-radius: 20px;
181
+ border-radius: 8px;
181
182
  max-width: 300px;
182
183
  z-index: 20;
184
+ border: 1px solid rgba(255, 255, 255, 0.1);
183
185
  }
184
186
 
185
187
  /* Quality indicator */
@@ -507,13 +509,42 @@ video {
507
509
  }
508
510
  }
509
511
 
510
- /* Bot\u00f3n para saltar reverso */
511
- .skip-button {
512
+ /* Sección para saltar reverso */
513
+ .skip-section {
512
514
  position: absolute;
513
515
  bottom: 20px;
514
516
  left: 50%;
515
517
  transform: translateX(-50%);
516
518
  z-index: 25;
519
+ display: flex;
520
+ flex-direction: column;
521
+ align-items: center;
522
+ width: 100%;
523
+ max-width: 300px;
524
+ }
525
+
526
+ .skip-explanation {
527
+ background: rgba(0, 0, 0, 0.5);
528
+ color: #ffffff;
529
+ padding: 10px 16px;
530
+ border-radius: 8px;
531
+ font-size: 14px;
532
+ font-weight: 500;
533
+ text-align: center;
534
+ margin-bottom: 12px;
535
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
536
+ backdrop-filter: blur(12px);
537
+ border: 1px solid rgba(255, 255, 255, 0.1);
538
+ animation: fadeIn 0.3s ease-in-out;
539
+ }
540
+
541
+ @keyframes fadeIn {
542
+ from { opacity: 0; transform: translateY(10px); }
543
+ to { opacity: 1; transform: translateY(0); }
544
+ }
545
+
546
+ /* Botón para saltar reverso */
547
+ .skip-button {
517
548
  pointer-events: auto;
518
549
  background: #fff;
519
550
  color: #333;
@@ -532,7 +563,7 @@ video {
532
563
 
533
564
  .skip-button:active {
534
565
  background: #e9ecef;
535
- transform: translateX(-50%) translateY(0);
566
+ transform: translateY(1px);
536
567
  }
537
568
 
538
569
  /* Camera controls */
@@ -734,29 +765,29 @@ video {
734
765
  right: 12px;
735
766
  gap: 6px;
736
767
  }
737
-
768
+
738
769
  .camera-selector-button {
739
770
  height: 36px;
740
771
  padding: 0 12px;
741
772
  font-size: 11px;
742
773
  border-radius: 6px;
743
774
  }
744
-
775
+
745
776
  .camera-selector-dropdown {
746
777
  right: 12px;
747
778
  top: 48px;
748
779
  min-width: 240px;
749
780
  max-width: calc(100vw - 24px);
750
781
  }
751
-
782
+
752
783
  .camera-selector-header {
753
784
  padding: 6px 10px;
754
785
  }
755
-
786
+
756
787
  .camera-option {
757
788
  padding: 6px 10px;
758
789
  }
759
-
790
+
760
791
  .device-info {
761
792
  padding: 4px 10px;
762
793
  }
@@ -847,16 +878,16 @@ video {
847
878
  height: 28px;
848
879
  border-radius: 8px;
849
880
  }
850
-
881
+
851
882
  .status-spinner {
852
883
  width: 14px;
853
884
  height: 14px;
854
885
  }
855
-
886
+
856
887
  .status-message {
857
888
  font-size: 11px;
858
889
  }
859
-
890
+
860
891
  .status-description {
861
892
  font-size: 9px;
862
893
  }
@@ -1006,25 +1037,25 @@ video {
1006
1037
  left: 12px;
1007
1038
  width: fit-content;
1008
1039
  }
1009
-
1040
+
1010
1041
  .performance-expanded {
1011
1042
  padding: 4px 8px;
1012
1043
  }
1013
-
1044
+
1014
1045
  .metrics-row {
1015
1046
  gap: 6px;
1016
1047
  margin-bottom: 3px;
1017
1048
  }
1018
-
1049
+
1019
1050
  .metric-compact {
1020
1051
  min-width: 45px;
1021
1052
  gap: 1px;
1022
1053
  }
1023
-
1054
+
1024
1055
  .metric-label {
1025
1056
  font-size: 8px;
1026
1057
  }
1027
-
1058
+
1028
1059
  .metric-value {
1029
1060
  font-size: 9px;
1030
1061
  padding: 1px 3px;
@@ -1078,10 +1109,9 @@ video {
1078
1109
  top: 160px;
1079
1110
  left: 12px;
1080
1111
  }
1081
-
1112
+
1082
1113
  .quality-text {
1083
1114
  padding: 4px 8px;
1084
1115
  font-size: 10px;
1085
1116
  }
1086
1117
  }
1087
-
@@ -4,11 +4,13 @@ export class JaakStamps {
4
4
  el;
5
5
  debug = false;
6
6
  alignmentTolerance = 15;
7
- maskSize = 80;
7
+ maskSize = 90;
8
8
  cropMargin = 20;
9
9
  useDocumentClassification = false;
10
10
  preferredCamera = 'auto';
11
11
  captureDelay = 1500;
12
+ enableBackDocumentTimer = false;
13
+ backDocumentTimerDuration = 20;
12
14
  captureCompleted;
13
15
  isReady;
14
16
  // State derived from services
@@ -37,6 +39,7 @@ export class JaakStamps {
37
39
  successfulDetections: 0,
38
40
  detectionRate: 0
39
41
  };
42
+ backDocumentTimerRemaining = 0;
40
43
  // Services
41
44
  serviceContainer;
42
45
  logger;
@@ -55,6 +58,7 @@ export class JaakStamps {
55
58
  hasScreenshotTaken = false;
56
59
  alignmentStartTime;
57
60
  alignmentTimer;
61
+ backDocumentTimer;
58
62
  // Performance monitoring
59
63
  performanceMetrics = {
60
64
  fps: 0,
@@ -526,7 +530,13 @@ export class JaakStamps {
526
530
  });
527
531
  }
528
532
  // Update document detection state
533
+ const wasDocumentDetected = this.hasDocumentDetected;
529
534
  this.hasDocumentDetected = detections.length > 0;
535
+ // Restart timer if document detected during back capture
536
+ if (!wasDocumentDetected && this.hasDocumentDetected &&
537
+ captureState.step === 'back' && this.enableBackDocumentTimer) {
538
+ this.startBackDocumentTimer();
539
+ }
530
540
  // Adaptive frame rate
531
541
  if (detections.length === 0) {
532
542
  this.consecutiveFailures++;
@@ -607,7 +617,7 @@ export class JaakStamps {
607
617
  deviceType: 'desktop',
608
618
  preferredFacing: null
609
619
  };
610
- return (h("div", { key: '7af79a0ff25b51790a9477cd7b338a0584172fc2', class: "detector-container" }, h("div", { key: 'ebf6a3811e0e599f29e98325b975a645e3bfb5e0', class: "video-container" }, h("video", { key: '5208fc9574fa78b1149be5839bc26d04bf9bcdfc', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: 'b507c786eccbd21acdd884ef50bc6ec280b9d437', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index) => (h("div", { key: index, class: "detection-box", style: {
620
+ return (h("div", { key: '9d4d77042218ab3d0bc4fb1ce879db09dc3e78b4', class: "detector-container" }, h("div", { key: '51ac8ccb1275637282b038ad8364d19f14ef61b1', class: "video-container" }, h("video", { key: 'a34f0481da20ec5b7b62b21aa275ec5f6dfec5d1', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: '43b71dfe3eaf20ffa66a4139e24b1af6a2074631', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index) => (h("div", { key: index, class: "detection-box", style: {
611
621
  position: 'absolute',
612
622
  left: `${box.x}px`,
613
623
  top: `${box.y}px`,
@@ -616,7 +626,9 @@ export class JaakStamps {
616
626
  border: '2px solid #32406C',
617
627
  pointerEvents: 'none',
618
628
  boxSizing: 'border-box'
619
- } })))), this.isMaskReady && (h("div", { key: '53066c626b23daae351ea9a80409e8882434b0dd', class: "overlay-mask" }, h("div", { key: '77bb4048d43e328e57a5c7e1909e0a59c8957217', class: "card-outline" }, h("div", { key: 'ea0f2610d903f985286856ab69f8be24fd42148e', class: "side side-top" }), h("div", { key: 'dc671111ef4adf33aa41f4457fdf344ede23eb80', class: "side side-right" }), h("div", { key: '2475ec41577dca92b425542c8861c570ed7ecd3b', class: "side side-bottom" }), h("div", { key: 'a06171c8eb1bd6353a6464485604560d73ac04b7', class: "side side-left" }), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'ecfd98f36d457fe7282b26f6a0efef5361380c76', class: "guide-text" }, "Alinee su identificaci\u00F3n con el marco"))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("button", { key: 'f3c7b66500110437e9e4a7442cb327f2fdc6d71f', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, "Saltar reverso")), captureState.isVideoActive && (h("div", { key: 'b5b2a8dfc6dbcf381c32c4caa562c27ced2e3e56', class: "camera-controls" }, h("button", { key: '6b40d4649dfa22c5ea8ca90cacce35cd0ca53ff3', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (h("div", { key: '41feec90287510b08bd1090ad15586b323007c30', class: "camera-selector-dropdown" }, h("div", { key: '8310ebe3db842c463ad428b973f841053315a76f', class: "camera-selector-header" }, h("span", { key: '6693bdfa33643dfe73798d4f25b0c2d9de7aac7c' }, "Seleccionar C\u00E1mara"), h("button", { key: '8552d45e1482c570d7ff85588d4404eec7c369d7', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: '5333ec0e5fb2c50a07a7c0b7d4dfb1bb4ee0df1c', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '8adf70b0e632c56a4784dec44621688809a3ff56', class: "device-info" }, h("small", { key: '2ea23922386ecda4a9011b50faba5efe4b4e60bb' }, "Dispositivo: ", cameraInfo.deviceType)))))), captureState.isCapturing && (h("div", { key: '8e693db67fe1e6ae8f11082b8993682b6d19b11d', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: '474489ed7848cdc163c492a5e19f5f13231e17b3', class: "flip-animation" }, h("div", { key: 'a9bd24ca21330882f001b7811077630eb1c30f50', class: "id-card-icon" }), h("div", { key: 'ffadb660a61e0f5e3e29bdc473d987e87dc4ad8a', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: 'd2522ee33aa159d49f040a293775892fb1cb81b5', class: "success-animation" }, h("div", { key: 'e7f899fac58bc9a3d51cf2cb89ee33bb320b241f', class: "check-icon" }), h("div", { key: 'd5d0ee1f37dbc659ca625ad03cbce325be0cf0a6', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: '425d347666032c3982a660ebee13b47670b996cb', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: '4d396fa107872f9a1e526fd59dc4edf279a05792', class: "status-spinner" })), h("div", { key: '232e9ae24c8cf5ef8ac0e3442e45a920799c724d', class: "status-content" }, h("div", { key: 'fe9dc0ca6d8e8276052bac7d2d44f1c7c9730364', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '6910c7ac78fd89e6fa1165446ec6d46fb356035c', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: '7282b8afaf03da53b01a23d04babd772528c3c14', class: "performance-monitor" }, h("div", { key: 'b582b3124fed13387cd70a02a34ab2bb541f3bfc', class: "performance-expanded" }, h("div", { key: '764bac2d61224b9a5f306f50934d410e1bd27787', class: "metrics-row" }, h("div", { key: '261563f8314a9f6069b1ac6362eb9c38936a9dc7', class: "metric-compact" }, h("span", { key: '4feea98eff86620c1bc90eb65d9799102423109d', class: "metric-label" }, "FPS"), h("span", { key: 'eb15f13b27b8aa50701ad3d11c4cf87200010b67', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: '0813c35c2c33286f2276bfb5adce59b32c7bb597', class: "metric-compact" }, h("span", { key: '201e7bcb556e63b141e42a3ffc3419eb4284bfa8', class: "metric-label" }, "MEM"), h("span", { key: '4f6703cbe0128440d0f2f22f631035ab85422c64', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: '6343c361c93138b9ea66e8ae8acd361b93333f8c', class: "metrics-row" }, h("div", { key: 'd3c81fe597004bf380fae2d32f3a8314317e7769', class: "metric-compact" }, h("span", { key: 'fce572af3e200a611974dceef4da02f6aecedffc', class: "metric-label" }, "INF"), h("span", { key: '18dd78d54dcecfb70ddf59b782f87f8c6f208b0f', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: '4c31ebfd835b017fd3e41b23d6bd9b19add511aa', class: "metric-compact" }, h("span", { key: '66b1a380b9479a8fc1e8c2385cb72aa4158dc74e', class: "metric-label" }, "FRAME"), h("span", { key: '3c6e41f7f11123c524d3a9df409345929d63f352', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: '3b522e2cdfe4bd9f1dd6eb0f91ee3577dc43e490', class: "metrics-row" }, h("div", { key: 'fa1e6f687b43aa2582b8b3426feb03a16c6493fc', class: "metric-compact" }, h("span", { key: 'a9355091e71a33a6a0d7cc6c11171dcda2e51b22', class: "metric-label" }, "DET"), h("span", { key: 'beca5a7ccf4853675cf8366bcf577ebfbd46c4f0', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: '4b07fc9b3d35f99bc6e77c8726192cde0476a787', class: "metric-compact" }, h("span", { key: 'a1674b538f45328ee0afb00e582c07e0b4ccf553', class: "metric-label" }, "RATE"), h("span", { key: 'fd384a5137bc3df6c939d3d698a3ef80e9087030', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: 'ebbaf15a0ad96e4da5bbf746c32d7a4abb51b973', class: "watermark" }, h("img", { key: '8e7d274b529d1f7020ec4a7225579792763f871a', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
629
+ } })))), this.isMaskReady && (h("div", { key: 'c2596f8cabb227e3ea3b082495f52b141cb1690f', class: "overlay-mask" }, h("div", { key: 'ba1ea39b5df1cd312a9bd9410b7225a29cfb8a29', class: "card-outline" }, h("div", { key: '6ce4d4d969d5f3fbcf75a4eb285f61d434c5633b', class: "side side-top" }), h("div", { key: '36653ecc4fcda25dfc84bc4d1f4c4c5dfb71ced7', class: "side side-right" }), h("div", { key: '8b108fa8fb370b229a0d1a77cb1ff044319a8f75', class: "side side-bottom" }), h("div", { key: 'a7aa3b45c065a50445aafd5c3ccefb57b0c9c769', class: "side side-left" }), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'b94b92273e12a019238e11ae57f21e140f13c3f1', class: "guide-text" }, "Alinee su identificaci\u00F3n con el marco"))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '144c3741003ec0cc148bb6ce92012d7b3cd110c8', class: "skip-section" }, h("div", { key: 'f0a984a6b75afa374c5d47da9d53e39f98071da0', class: "skip-explanation" }, "Si tu documento no tiene lado trasero, da clic en el bot\u00F3n para continuar con el proceso"), h("button", { key: '57ac30d776e30709aab6e0a621cef889da3cc677', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
630
+ ? `Saltar reverso (${this.backDocumentTimerRemaining}s)`
631
+ : 'Saltar reverso'))), captureState.isVideoActive && (h("div", { key: 'bd45628707e0169317ed3dd4247e1056d7046104', class: "camera-controls" }, h("button", { key: 'e750fbf4d5d76d9e9596823bb2b86801ef19e485', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (h("div", { key: '40ada780a8ea13aeeaee9cb39bc6496f69f2679d', class: "camera-selector-dropdown" }, h("div", { key: '3a920bb02ba024f0359513f10544bf0528ecee6d', class: "camera-selector-header" }, h("span", { key: 'e5efd478a602b13821ba53cb9a7a59d1b4a71178' }, "Seleccionar C\u00E1mara"), h("button", { key: '2df6cc11e162be74862029e33815927e3fa8f2f8', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: '06934642dff134c9e1a6872f935a5892a9c7b835', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '8d5ede287c2efb0ebe418bee8dc7fb310443c991', class: "device-info" }, h("small", { key: 'b7dd10565113694b09f01ab28ffa29262ae1d2bc' }, "Dispositivo: ", cameraInfo.deviceType)))))), captureState.isCapturing && (h("div", { key: '2f9e549e6c0c56d4db5835e58361fb17bba6cf90', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: 'a6ef0ed127f23e9d764896ed743ca8d8454851a6', class: "flip-animation" }, h("div", { key: '0b04411f88a634bb3243b00ca2d5a45fd6962dea', class: "id-card-icon" }), h("div", { key: '9327be58879b407cea87f455989406e58302e9d1', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: 'bd268578b5003e99256e3340b4a9a6fb7656be64', class: "success-animation" }, h("div", { key: '064e0a5b9851de14bc6829f028e7ea7161fd1633', class: "check-icon" }), h("div", { key: 'bdcd94a8806399e396e218a359c10b11d05f38d6', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: '3d9af617376c16e44e065873919c3d90ff46110a', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: 'be7b56decfd6f12dcca46b2a9456480e3d5ac00e', class: "status-spinner" })), h("div", { key: '5fe9850883cb749cebaa18c3e9c13ca21325e373', class: "status-content" }, h("div", { key: '43fdb50691e4b98e56126af1a129f625061128bf', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: 'b76cbfa4a0349421fcd535d3fd8bf40c89ca3aef', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: 'eddefb464af0487ab9ab2a0f76dccbb6a2092e51', class: "performance-monitor" }, h("div", { key: '7b7d93b56cb4cd4fbb1bdde89c6150b282fa805e', class: "performance-expanded" }, h("div", { key: 'f302e8b9d985fb8cad53c4c4e0d37a3bf5a63261', class: "metrics-row" }, h("div", { key: 'e8d8f2420ee8643a7f454d38065c75b5be598f77', class: "metric-compact" }, h("span", { key: '6e52eb5bb06e0df57e61774de38c31349f45e22b', class: "metric-label" }, "FPS"), h("span", { key: '6636f9cea20c49b49c17db86188e2f6b214c45c3', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: 'afa1d9dec05b14256a1b1fcec8638b8c21a56e37', class: "metric-compact" }, h("span", { key: '9c55e30f5d01582648bacc1fb38ca1990485a591', class: "metric-label" }, "MEM"), h("span", { key: 'ca263601e8715027f95ffb2d5413a643dc570cf2', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: '03caf19961fd01b7781484d49d8121b1e78c161f', class: "metrics-row" }, h("div", { key: 'bffb08f01f703411f7c8605e4f8d95b1c37b5c0f', class: "metric-compact" }, h("span", { key: '9b92279b3253cc669412733facb3751f4344d69f', class: "metric-label" }, "INF"), h("span", { key: '3234d4150e2e1479e3b552767af8123e69911d6c', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: '77082d2669db53f19fb50b3bbfa1ebefb0b86ff4', class: "metric-compact" }, h("span", { key: 'cc6ef96c72c800ba36dab2a388f1de863b2dacd5', class: "metric-label" }, "FRAME"), h("span", { key: 'e2bb4b7351869a76e810f8bbf20d805154495e35', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: '5700d7ef839fa77686299d79445203090dc8079f', class: "metrics-row" }, h("div", { key: 'a2999a035fccb7f250c01b084075490678513c87', class: "metric-compact" }, h("span", { key: '3677d58665996fa5969507dbaff9e956b2ea54ee', class: "metric-label" }, "DET"), h("span", { key: 'c584312438b339c82a3bdc33f00fb985ff2a6f55', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: '58866219f213bf8607083f30be2d5ca5d0515cea', class: "metric-compact" }, h("span", { key: 'd90b450051331347f219b6c0f197536d0dcee9b7', class: "metric-label" }, "RATE"), h("span", { key: 'f6e6cd7948e06014e5a0416e4e81394fa36ec61d', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: 'c1d0194f181a0082cc1aa5452de382908da61b65', class: "watermark" }, h("img", { key: 'e04d35f3c79a2b4a3922ab5b0f102220171fa7c0', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
620
632
  }
621
633
  // Utility methods
622
634
  updateDetectionBoxes(boxes) {
@@ -685,6 +697,15 @@ export class JaakStamps {
685
697
  bottomSide?.classList.toggle('aligned', currentAlignment.bottom);
686
698
  leftSide?.classList.toggle('aligned', currentAlignment.left);
687
699
  const allSidesAligned = this.detectionService.areAllSidesAligned(currentAlignment);
700
+ // Restart back document timer if any border is aligned during back capture
701
+ const captureState = this.stateManager.getCaptureState();
702
+ if (captureState.step === 'back' && this.enableBackDocumentTimer && bestBox) {
703
+ const anyBorderAligned = currentAlignment.top || currentAlignment.right ||
704
+ currentAlignment.bottom || currentAlignment.left;
705
+ if (anyBorderAligned) {
706
+ this.startBackDocumentTimer();
707
+ }
708
+ }
688
709
  if (allSidesAligned && bestBox) {
689
710
  cardOutline?.classList.add('perfect-match');
690
711
  corners?.forEach(corner => corner.classList.add('perfect-match'));
@@ -799,6 +820,7 @@ export class JaakStamps {
799
820
  showFlipAnimation: false,
800
821
  isDetectionPaused: false
801
822
  });
823
+ this.startBackDocumentTimer();
802
824
  }, 3000);
803
825
  }
804
826
  else if (captureState.step === 'back') {
@@ -849,9 +871,32 @@ export class JaakStamps {
849
871
  cancelAnimationFrame(this.animationId);
850
872
  this.animationId = undefined;
851
873
  }
874
+ this.clearBackDocumentTimer();
852
875
  this.detectionBoxes = [];
853
876
  this.logger.state('DETECTOR_DETENIDO', { timestamp: Date.now() });
854
877
  }
878
+ startBackDocumentTimer() {
879
+ if (!this.enableBackDocumentTimer)
880
+ return;
881
+ if (this.backDocumentTimer) {
882
+ clearInterval(this.backDocumentTimer);
883
+ }
884
+ this.backDocumentTimerRemaining = this.backDocumentTimerDuration;
885
+ this.backDocumentTimer = window.setInterval(() => {
886
+ this.backDocumentTimerRemaining--;
887
+ if (this.backDocumentTimerRemaining <= 0) {
888
+ this.clearBackDocumentTimer();
889
+ this.skipBackCapture();
890
+ }
891
+ }, 1000);
892
+ }
893
+ clearBackDocumentTimer() {
894
+ if (this.backDocumentTimer) {
895
+ clearInterval(this.backDocumentTimer);
896
+ this.backDocumentTimer = undefined;
897
+ }
898
+ this.backDocumentTimerRemaining = 0;
899
+ }
855
900
  toggleCameraSelector() {
856
901
  if (this.isSwitchingCamera)
857
902
  return; // Don't toggle if switching camera
@@ -1060,7 +1105,7 @@ export class JaakStamps {
1060
1105
  "getter": false,
1061
1106
  "setter": false,
1062
1107
  "reflect": false,
1063
- "defaultValue": "80"
1108
+ "defaultValue": "90"
1064
1109
  },
1065
1110
  "cropMargin": {
1066
1111
  "type": "number",
@@ -1141,6 +1186,46 @@ export class JaakStamps {
1141
1186
  "setter": false,
1142
1187
  "reflect": false,
1143
1188
  "defaultValue": "1500"
1189
+ },
1190
+ "enableBackDocumentTimer": {
1191
+ "type": "boolean",
1192
+ "attribute": "enable-back-document-timer",
1193
+ "mutable": false,
1194
+ "complexType": {
1195
+ "original": "boolean",
1196
+ "resolved": "boolean",
1197
+ "references": {}
1198
+ },
1199
+ "required": false,
1200
+ "optional": false,
1201
+ "docs": {
1202
+ "tags": [],
1203
+ "text": ""
1204
+ },
1205
+ "getter": false,
1206
+ "setter": false,
1207
+ "reflect": false,
1208
+ "defaultValue": "false"
1209
+ },
1210
+ "backDocumentTimerDuration": {
1211
+ "type": "number",
1212
+ "attribute": "back-document-timer-duration",
1213
+ "mutable": false,
1214
+ "complexType": {
1215
+ "original": "number",
1216
+ "resolved": "number",
1217
+ "references": {}
1218
+ },
1219
+ "required": false,
1220
+ "optional": false,
1221
+ "docs": {
1222
+ "tags": [],
1223
+ "text": ""
1224
+ },
1225
+ "getter": false,
1226
+ "setter": false,
1227
+ "reflect": false,
1228
+ "defaultValue": "20"
1144
1229
  }
1145
1230
  };
1146
1231
  }
@@ -1154,7 +1239,8 @@ export class JaakStamps {
1154
1239
  "isSwitchingCamera": {},
1155
1240
  "hasDocumentDetected": {},
1156
1241
  "currentStatus": {},
1157
- "performanceData": {}
1242
+ "performanceData": {},
1243
+ "backDocumentTimerRemaining": {}
1158
1244
  };
1159
1245
  }
1160
1246
  static get events() {