@jaak.ai/stamps 2.1.0-dev.3 → 2.1.0-dev.5

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.
@@ -16,7 +16,7 @@ var patchBrowser = () => {
16
16
 
17
17
  patchBrowser().then(async (options) => {
18
18
  await globalScripts();
19
- return bootstrapLazy([["jaak-stamps",[[1,"jaak-stamps",{"debug":[4],"alignmentTolerance":[2,"alignment-tolerance"],"maskSize":[2,"mask-size"],"cropMargin":[2,"crop-margin"],"useDocumentClassification":[4,"use-document-classification"],"useDocumentDetector":[4,"use-document-detector"],"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],"cameraInfoWithAutofocus":[32],"currentStatus":[32],"performanceData":[32],"backDocumentTimerRemaining":[32],"showManualCaptureButton":[32],"captureStateVersion":[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]}]]]], options);
19
+ return bootstrapLazy([["jaak-stamps",[[1,"jaak-stamps",{"debug":[4],"alignmentTolerance":[2,"alignment-tolerance"],"maskSize":[2,"mask-size"],"cropMargin":[2,"crop-margin"],"useDocumentClassification":[4,"use-document-classification"],"useDocumentDetector":[4,"use-document-detector"],"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],"cameraInfoWithAutofocus":[32],"currentStatus":[32],"performanceData":[32],"backDocumentTimerRemaining":[32],"showManualCaptureButton":[32],"performanceDegradedMode":[32],"showPerformanceMessage":[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]}]]]], options);
20
20
  });
21
21
  //# sourceMappingURL=jaak-stamps-webcomponent.js.map
22
22
 
@@ -1089,7 +1089,7 @@ class ServiceContainer {
1089
1089
  }
1090
1090
  }
1091
1091
 
1092
- const myComponentCss = ":host{display:block;width:100%;height:100%;font-family:system-ui, -apple-system, sans-serif;color:#1a1a1a}.detector-container{display:flex;flex-direction:column;align-items:center;width:100%;height:100%}h1{font-size:24px;font-weight:500;color:#333;margin:0 0 24px 0}.video-container{position:relative;width:100%;height:100%;background:#333;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden}video,.detection-overlay{position:absolute;width:100%;height:100%;border-radius:8px}video.mirror,.detection-overlay.mirror{transform:rotateY(180deg)}.detection-overlay{z-index:1;pointer-events:none}video{z-index:0}.detection-box{transition:opacity 0.2s ease}.status{margin-top:16px;font-size:12px;color:#666}.overlay-mask{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10;display:block;pointer-events:none}.card-outline{position:absolute;top:var(--mask-center-y, 50%);left:var(--mask-center-x, 50%);transform:translate(-50%, -50%);width:var(--mask-width, 88%);height:var(--mask-height, 55%);border:none;border-radius:4px;background:transparent;opacity:0.8}.side{position:absolute;background:#999;transition:background-color 0.3s ease;border-radius:1px}.side-top.aligned{border-left-color:#28a745;border-top-color:#28a745}.side-right.aligned{border-right-color:#28a745;border-top-color:#28a745}.side-bottom.aligned{border-left-color:#28a745;border-bottom-color:#28a745}.side-left.aligned{border-right-color:#28a745;border-bottom-color:#28a745}.side-top{top:-3px;left:-3px;width:30px;height:30px;border-left:6px solid #ffffff;border-top:6px solid #ffffff;background:transparent}.side-right{top:-3px;right:-3px;width:30px;height:30px;border-right:6px solid #ffffff;border-top:6px solid #ffffff;background:transparent}.side-bottom{bottom:-3px;left:-3px;width:30px;height:30px;border-left:6px solid #ffffff;border-bottom:6px solid #ffffff;background:transparent}.side-left{bottom:-3px;right:-3px;width:30px;height:30px;border-right:6px solid #ffffff;border-bottom:6px solid #ffffff;background:transparent}.guide-text{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);color:#ffffff;font-size:12px;font-weight:500;text-align:center;white-space:normal;padding:13px;max-width:300px;z-index:20;height:fit-content;width:fit-content;animation:slideInFromTopCentered 0.3s ease-out}.quality-indicator{position:absolute;top:20px;right:20px;display:flex;align-items:center;gap:8px;background:rgba(0, 0, 0, 0.8);padding:8px 12px;border-radius:20px;z-index:25;transition:all 0.3s ease}.quality-indicator.warning{background:rgba(255, 152, 0, 0.9)}.quality-indicator.good{background:rgba(76, 175, 80, 0.9)}.quality-score{color:#fff;font-size:12px;font-weight:600;min-width:30px;text-align:center}.quality-status{width:20px;height:20px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:bold;color:#fff;transition:all 0.3s ease}.quality-status.ready{background:#4CAF50}.quality-status.not-ready{background:#f44336}.card-outline.quality-warning{animation:qualityWarning 1s ease-in-out infinite alternate}@keyframes qualityWarning{0%{box-shadow:0 0 0 3px rgba(255, 152, 0, 0.6)}100%{box-shadow:0 0 0 6px rgba(255, 152, 0, 0.3)}}.capture-animation{position:absolute;top:0;left:0;width:100%;height:100%;background:#fff;opacity:0;z-index:30;pointer-events:none;animation:captureFlash 0.6s ease-out}@keyframes captureFlash{0%{opacity:0}15%{opacity:0.8}30%{opacity:0}45%{opacity:0.4}60%{opacity:0}100%{opacity:0}}.card-outline.capturing{animation:pulseGreen 0.6s ease-out}@keyframes pulseGreen{0%{border-color:#28a745;box-shadow:0 0 0 4px rgba(40, 167, 69, 0)}50%{border-color:#28a745;box-shadow:0 0 0 8px rgba(40, 167, 69, 0.6)}100%{border-color:#28a745;box-shadow:0 0 0 4px rgba(40, 167, 69, 0)}}.flip-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showFlipInstruction 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.id-card-icon{width:80px;height:50px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:8px;position:relative;animation:flipCard 2s ease-in-out infinite;box-shadow:0 4px 12px rgba(0, 0, 0, 0.3)}.id-card-icon::before{content:'';position:absolute;top:8px;left:8px;width:16px;height:12px;background:rgba(255, 255, 255, 0.9);border-radius:2px}.id-card-icon::after{content:'';position:absolute;top:25px;left:8px;width:64px;height:3px;background:rgba(255, 255, 255, 0.7);border-radius:1px;box-shadow:0 6px 0 rgba(255, 255, 255, 0.7), 0 12px 0 rgba(255, 255, 255, 0.7)}.flip-text{margin-top:12px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px}@keyframes showFlipInstruction{0%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}}@keyframes flipCard{0%{transform:rotateY(0deg)}50%{transform:rotateY(180deg)}100%{transform:rotateY(360deg)}}.success-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showSuccessMessage 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.check-icon{width:80px;height:80px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:50%;position:relative;animation:bounceSuccess 0.6s ease-out;box-shadow:0 4px 16px rgba(108, 117, 125, 0.4);display:flex;align-items:center;justify-content:center}.check-icon::before{content:'';position:absolute;width:20px;height:35px;border:4px solid #fff;border-top:none;border-left:none;transform:rotate(45deg);animation:drawCheck 0.4s ease-out 0.2s both}.success-text{margin-top:16px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px;animation:fadeInUp 0.5s ease-out 0.4s both}@keyframes showSuccessMessage{0%{opacity:0;transform:translate(-50%, -50%) scale(0.5)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.9)}}@keyframes bounceSuccess{0%{transform:scale(0)}50%{transform:scale(1.1)}100%{transform:scale(1)}}@keyframes drawCheck{0%{width:0;height:0}50%{width:20px;height:0}100%{width:20px;height:35px}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}100%{opacity:1;transform:translateY(0)}}.skip-section{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;display:flex;flex-direction:column;align-items:center;width:100%;max-width:300px}.back-capture-section{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;display:flex;flex-direction:column;align-items:center;width:100%;max-width:320px}.back-capture-buttons{display:flex;gap:12px;align-items:center;justify-content:center;flex-wrap:wrap}.capture-button{pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.capture-button:hover{background:#f8f9fa}.capture-button:active{background:#e9ecef;transform:translateY(1px)}.capture-button:disabled{background:#e9ecef;color:#6c757d;cursor:not-allowed;transform:none}@media (max-width: 480px){.back-capture-section{bottom:16px;max-width:300px}.back-capture-buttons{flex-direction:column;gap:8px;width:100%}.capture-button,.back-capture-buttons .skip-button{width:100%;max-width:200px;padding:10px 20px;font-size:13px}}.skip-explanation{background:rgba(0, 0, 0, 0.5);color:#ffffff;padding:10px 16px;border-radius:8px;font-size:14px;font-weight:500;text-align:center;margin-bottom:12px;box-shadow:0 2px 8px rgba(0, 0, 0, 0.2);backdrop-filter:blur(12px);border:1px solid rgba(255, 255, 255, 0.1);animation:fadeIn 0.3s ease-in-out}@keyframes fadeIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.skip-button{pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.skip-button:hover{background:#f8f9fa}.skip-button:active{background:#e9ecef;transform:translateY(1px)}.camera-controls{position:absolute;top:16px;right:16px;z-index:25;display:flex;gap:8px;pointer-events:auto;animation:slideInFromTop 0.3s ease-out}.camera-selector-button{height:32px;padding:0 10px;border:none;border-radius:8px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(12px);color:#ffffff;font-size:12px;font-weight:500;cursor:pointer;transition:all 0.2s ease;display:flex;align-items:center;justify-content:center;border:1px solid rgba(255, 255, 255, 0.1);white-space:nowrap;min-width:fit-content}.camera-selector-button:hover{background:rgba(0, 0, 0, 0.8);border-color:rgba(255, 255, 255, 0.2);transform:translateY(-1px)}.camera-selector-button:active{transform:translateY(0);background:rgba(0, 0, 0, 0.9)}.camera-selector-button:disabled,.camera-selector-button.loading{opacity:0.7;cursor:not-allowed;pointer-events:none}.camera-selector-button:disabled:hover,.camera-selector-button.loading:hover{transform:none;background:rgba(0, 0, 0, 0.6);border-color:rgba(255, 255, 255, 0.1)}.button-spinner{width:16px;height:16px;border:2px solid rgba(255, 255, 255, 0.3);border-top:2px solid #ffffff;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.camera-selector-dropdown{position:absolute;top:56px;right:16px;z-index:30;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;min-width:260px;max-width:300px;border:1px solid rgba(255, 255, 255, 0.1);overflow:hidden;pointer-events:auto;animation:slideInFromTop 0.3s ease-out}@keyframes slideInFromTop{0%{opacity:0;transform:translateY(-8px) scale(0.95)}100%{opacity:1;transform:translateY(0) scale(1)}}@keyframes slideInFromTopCentered{0%{opacity:0;transform:translate(-50%, -50%) translateY(-8px) scale(0.95)}100%{opacity:1;transform:translate(-50%, -50%) translateY(0) scale(1)}}.camera-selector-header{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-bottom:1px solid rgba(255, 255, 255, 0.1)}.camera-selector-header span{font-weight:500;color:#ffffff;font-size:13px;opacity:0.9}.close-selector{width:20px;height:20px;border:none;background:none;color:rgba(255, 255, 255, 0.7);font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all 0.2s ease}.close-selector:hover{background:rgba(255, 255, 255, 0.1);color:#ffffff}.camera-list{padding:4px 0;max-height:240px;overflow-y:auto}.camera-option{width:100%;padding:8px 12px;border:none;background:none;text-align:left;cursor:pointer;transition:all 0.2s ease;display:flex;justify-content:flex-start;align-items:center;gap:8px;color:rgba(255, 255, 255, 0.9)}.camera-option:hover{background:rgba(255, 255, 255, 0.08)}.camera-option.selected{background:rgba(255, 255, 255, 0.12);color:#ffffff}.camera-label{font-size:13px;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:0;font-weight:400;display:flex;align-items:center;gap:6px}.camera-label .autofocus-icon{font-size:12px;color:#ffffff !important;opacity:0.8;flex-shrink:0}.selected-indicator{font-size:14px;color:#ffffff;opacity:0.9;flex-shrink:0}.device-info{padding:6px 12px;border-top:1px solid rgba(255, 255, 255, 0.1);background:rgba(255, 255, 255, 0.05)}.device-info small{color:rgba(255, 255, 255, 0.6);font-size:11px;text-transform:capitalize;font-weight:400}@media (max-width: 480px){.camera-controls{top:12px;right:12px;gap:6px}.camera-selector-button{height:36px;padding:0 12px;font-size:11px;border-radius:6px}.camera-selector-dropdown{right:12px;top:48px;min-width:240px;max-width:calc(100vw - 24px)}.camera-selector-header{padding:6px 10px}.camera-option{padding:6px 10px}.device-info{padding:4px 10px}}.watermark{position:absolute;bottom:12px;right:12px;z-index:15;pointer-events:none;opacity:0.7}.watermark img{height:24px;width:auto;filter:drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3))}.component-status{position:absolute;top:16px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);display:flex;align-items:center;gap:6px;padding:6px 10px;z-index:40;height:32px;width:fit-content;animation:slideInFromTop 0.3s ease-out}.status-spinner{width:16px;height:16px;border:1px solid rgba(255, 255, 255, 0.3);border-top:1px solid #ffffff;border-radius:50%;animation:statusSpin 1s linear infinite;flex-shrink:0}.status-content{display:flex;flex-direction:column;gap:1px}.status-message{color:#ffffff;font-size:12px;font-weight:500;margin:0}.status-description{color:rgba(255, 255, 255, 0.7);font-size:10px;line-height:1.2;margin:0}@keyframes statusSpin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@media (max-width: 480px){.component-status{top:12px;left:12px;padding:4px 8px;gap:4px;height:28px;border-radius:8px}.status-spinner{width:14px;height:14px}.status-message{font-size:11px}.status-description{font-size:9px}.guide-text{font-size:11px;padding:4px 8px;border-radius:8px}}.loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0, 0, 0, 0.85);backdrop-filter:blur(4px);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:30;border-radius:8px}.loading-spinner{width:50px;height:50px;border:3px solid rgba(255, 255, 255, 0.15);border-top:3px solid #28a745;border-radius:50%;animation:spin 1s ease-in-out infinite;margin-bottom:16px}.loading-text{color:#ffffff;font-size:14px;font-weight:500;text-align:center;opacity:0.9;margin-bottom:4px}.loading-description{color:rgba(255, 255, 255, 0.7);font-size:12px;text-align:center;opacity:0.8}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.performance-monitor{position:absolute;top:70px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);z-index:35;width:fit-content;animation:slideInFromTop 0.3s ease-out;transition:all 0.3s ease}@keyframes slideInFromLeft{0%{opacity:0;transform:translateX(-20px) scale(0.95)}100%{opacity:1;transform:translateX(0) scale(1)}}.performance-expanded{padding:6px 10px}.metrics-row{display:flex;gap:8px;margin-bottom:4px}.metrics-row:last-child{margin-bottom:0}.metric-compact{display:flex;flex-direction:column;align-items:center;gap:2px;min-width:50px}.metric-label{font-size:9px;color:rgba(255, 255, 255, 0.6);font-weight:500;text-transform:uppercase;letter-spacing:0.3px}.metric-value{font-size:10px;font-weight:600;font-family:'Monaco', 'Menlo', 'Consolas', monospace;padding:2px 4px;border-radius:3px;text-align:center;white-space:nowrap}.metric-value.good{color:#4ade80;background:rgba(74, 222, 128, 0.1);border:1px solid rgba(74, 222, 128, 0.2)}.metric-value.warning{color:#fbbf24;background:rgba(251, 191, 36, 0.1);border:1px solid rgba(251, 191, 36, 0.2)}.metric-value.danger{color:#f87171;background:rgba(248, 113, 113, 0.1);border:1px solid rgba(248, 113, 113, 0.2)}@media (max-width: 480px){.performance-monitor{top:60px;left:12px;width:fit-content}.performance-expanded{padding:4px 8px}.metrics-row{gap:6px;margin-bottom:3px}.metric-compact{min-width:45px;gap:1px}.metric-label{font-size:8px}.metric-value{font-size:9px;padding:1px 3px}}.quality-monitor{position:absolute;top:200px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);z-index:35;width:fit-content;animation:slideInFromLeft 0.3s ease-out;transition:all 0.3s ease}.quality-text{padding:6px 10px;font-size:11px;color:white;font-family:'Monaco', 'Menlo', 'Consolas', monospace;line-height:1.4}.quality-fail{color:#ff9999}@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.7}}.metric-value.danger{animation:pulse 2s infinite}@media (max-width: 480px){.quality-monitor{top:160px;left:12px}.quality-text{padding:4px 8px;font-size:10px}}.manual-capture-section{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;display:flex;flex-direction:column;align-items:center;width:100%;max-width:300px}.manual-capture-button{pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.manual-capture-button:hover{background:#f8f9fa}.manual-capture-button:active{background:#e9ecef;transform:translateY(1px)}.manual-capture-button:disabled{background:#e9ecef;color:#6c757d;cursor:not-allowed;transform:none}@media (max-width: 480px){.manual-capture-section{bottom:16px;max-width:280px}.manual-capture-button{padding:10px 20px;font-size:13px}}";
1092
+ const myComponentCss = ":host{display:block;width:100%;height:100%;font-family:system-ui, -apple-system, sans-serif;color:#1a1a1a}.detector-container{display:flex;flex-direction:column;align-items:center;width:100%;height:100%}h1{font-size:24px;font-weight:500;color:#333;margin:0 0 24px 0}.video-container{position:relative;width:100%;height:100%;background:#333;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden}video,.detection-overlay{position:absolute;width:100%;height:100%;border-radius:8px}video.mirror,.detection-overlay.mirror{transform:rotateY(180deg)}.detection-overlay{z-index:1;pointer-events:none}video{z-index:0}.detection-box{transition:opacity 0.2s ease}.status{margin-top:16px;font-size:12px;color:#666}.overlay-mask{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10;display:block;pointer-events:none}.card-outline{position:absolute;top:var(--mask-center-y, 50%);left:var(--mask-center-x, 50%);transform:translate(-50%, -50%);width:var(--mask-width, 88%);height:var(--mask-height, 55%);border:none;border-radius:4px;background:transparent;opacity:0.8}.side{position:absolute;background:#999;transition:background-color 0.3s ease;border-radius:1px}.side-top.aligned{border-left-color:#28a745;border-top-color:#28a745}.side-right.aligned{border-right-color:#28a745;border-top-color:#28a745}.side-bottom.aligned{border-left-color:#28a745;border-bottom-color:#28a745}.side-left.aligned{border-right-color:#28a745;border-bottom-color:#28a745}.side-top{top:-3px;left:-3px;width:30px;height:30px;border-left:6px solid #ffffff;border-top:6px solid #ffffff;background:transparent}.side-right{top:-3px;right:-3px;width:30px;height:30px;border-right:6px solid #ffffff;border-top:6px solid #ffffff;background:transparent}.side-bottom{bottom:-3px;left:-3px;width:30px;height:30px;border-left:6px solid #ffffff;border-bottom:6px solid #ffffff;background:transparent}.side-left{bottom:-3px;right:-3px;width:30px;height:30px;border-right:6px solid #ffffff;border-bottom:6px solid #ffffff;background:transparent}.guide-text{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);color:#ffffff;font-size:12px;font-weight:500;text-align:center;white-space:normal;padding:13px;max-width:300px;z-index:20;height:fit-content;width:fit-content;animation:slideInFromTopCentered 0.3s ease-out}.quality-indicator{position:absolute;top:20px;right:20px;display:flex;align-items:center;gap:8px;background:rgba(0, 0, 0, 0.8);padding:8px 12px;border-radius:20px;z-index:25;transition:all 0.3s ease}.quality-indicator.warning{background:rgba(255, 152, 0, 0.9)}.quality-indicator.good{background:rgba(76, 175, 80, 0.9)}.quality-score{color:#fff;font-size:12px;font-weight:600;min-width:30px;text-align:center}.quality-status{width:20px;height:20px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:bold;color:#fff;transition:all 0.3s ease}.quality-status.ready{background:#4CAF50}.quality-status.not-ready{background:#f44336}.card-outline.quality-warning{animation:qualityWarning 1s ease-in-out infinite alternate}@keyframes qualityWarning{0%{box-shadow:0 0 0 3px rgba(255, 152, 0, 0.6)}100%{box-shadow:0 0 0 6px rgba(255, 152, 0, 0.3)}}.capture-animation{position:absolute;top:0;left:0;width:100%;height:100%;background:#fff;opacity:0;z-index:30;pointer-events:none;animation:captureFlash 0.6s ease-out}@keyframes captureFlash{0%{opacity:0}15%{opacity:0.8}30%{opacity:0}45%{opacity:0.4}60%{opacity:0}100%{opacity:0}}.card-outline.capturing{animation:pulseGreen 0.6s ease-out}@keyframes pulseGreen{0%{border-color:#28a745;box-shadow:0 0 0 4px rgba(40, 167, 69, 0)}50%{border-color:#28a745;box-shadow:0 0 0 8px rgba(40, 167, 69, 0.6)}100%{border-color:#28a745;box-shadow:0 0 0 4px rgba(40, 167, 69, 0)}}.flip-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showFlipInstruction 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.id-card-icon{width:80px;height:50px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:8px;position:relative;animation:flipCard 2s ease-in-out infinite;box-shadow:0 4px 12px rgba(0, 0, 0, 0.3)}.id-card-icon::before{content:'';position:absolute;top:8px;left:8px;width:16px;height:12px;background:rgba(255, 255, 255, 0.9);border-radius:2px}.id-card-icon::after{content:'';position:absolute;top:25px;left:8px;width:64px;height:3px;background:rgba(255, 255, 255, 0.7);border-radius:1px;box-shadow:0 6px 0 rgba(255, 255, 255, 0.7), 0 12px 0 rgba(255, 255, 255, 0.7)}.flip-text{margin-top:12px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px}@keyframes showFlipInstruction{0%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}}@keyframes flipCard{0%{transform:rotateY(0deg)}50%{transform:rotateY(180deg)}100%{transform:rotateY(360deg)}}.success-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showSuccessMessage 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.check-icon{width:80px;height:80px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:50%;position:relative;animation:bounceSuccess 0.6s ease-out;box-shadow:0 4px 16px rgba(108, 117, 125, 0.4);display:flex;align-items:center;justify-content:center}.check-icon::before{content:'';position:absolute;width:20px;height:35px;border:4px solid #fff;border-top:none;border-left:none;transform:rotate(45deg);animation:drawCheck 0.4s ease-out 0.2s both}.success-text{margin-top:16px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px;animation:fadeInUp 0.5s ease-out 0.4s both}@keyframes showSuccessMessage{0%{opacity:0;transform:translate(-50%, -50%) scale(0.5)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.9)}}@keyframes bounceSuccess{0%{transform:scale(0)}50%{transform:scale(1.1)}100%{transform:scale(1)}}@keyframes drawCheck{0%{width:0;height:0}50%{width:20px;height:0}100%{width:20px;height:35px}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}100%{opacity:1;transform:translateY(0)}}.skip-section{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;display:flex;flex-direction:column;align-items:center;width:100%;max-width:300px}.back-capture-section{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;display:flex;flex-direction:column;align-items:center;width:100%;max-width:320px}.back-capture-buttons{display:flex;gap:12px;align-items:center;justify-content:center;flex-wrap:wrap}.capture-button{pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.capture-button:hover{background:#f8f9fa}.capture-button:active{background:#e9ecef;transform:translateY(1px)}.capture-button:disabled{background:#e9ecef;color:#6c757d;cursor:not-allowed;transform:none}@media (max-width: 480px){.back-capture-section{bottom:16px;max-width:300px}.back-capture-buttons{flex-direction:column;gap:8px;width:100%}.capture-button,.back-capture-buttons .skip-button{width:100%;max-width:200px;padding:10px 20px;font-size:13px}}.skip-explanation{background:rgba(0, 0, 0, 0.5);color:#ffffff;padding:10px 16px;border-radius:8px;font-size:14px;font-weight:500;text-align:center;margin-bottom:12px;box-shadow:0 2px 8px rgba(0, 0, 0, 0.2);backdrop-filter:blur(12px);border:1px solid rgba(255, 255, 255, 0.1);animation:fadeIn 0.3s ease-in-out}@keyframes fadeIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.guide-text.performance-warning-text{animation:gentlePulse 2s ease-in-out infinite;background:rgba(255, 107, 107, 0.3);border:1px solid rgba(255, 107, 107, 0.5)}@keyframes gentlePulse{0%,100%{transform:translate(-50%, -50%) scale(1);background:rgba(255, 107, 107, 0.3)}50%{transform:translate(-50%, -50%) scale(1.02);background:rgba(255, 107, 107, 0.4)}}.skip-button{pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.skip-button:hover{background:#f8f9fa}.skip-button:active{background:#e9ecef;transform:translateY(1px)}.camera-controls{position:absolute;top:16px;right:16px;z-index:25;display:flex;gap:8px;pointer-events:auto;animation:slideInFromTop 0.3s ease-out}.camera-selector-button{height:32px;padding:0 10px;border:none;border-radius:8px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(12px);color:#ffffff;font-size:12px;font-weight:500;cursor:pointer;transition:all 0.2s ease;display:flex;align-items:center;justify-content:center;border:1px solid rgba(255, 255, 255, 0.1);white-space:nowrap;min-width:fit-content}.camera-selector-button:hover{background:rgba(0, 0, 0, 0.8);border-color:rgba(255, 255, 255, 0.2);transform:translateY(-1px)}.camera-selector-button:active{transform:translateY(0);background:rgba(0, 0, 0, 0.9)}.camera-selector-button:disabled,.camera-selector-button.loading{opacity:0.7;cursor:not-allowed;pointer-events:none}.camera-selector-button:disabled:hover,.camera-selector-button.loading:hover{transform:none;background:rgba(0, 0, 0, 0.6);border-color:rgba(255, 255, 255, 0.1)}.button-spinner{width:16px;height:16px;border:2px solid rgba(255, 255, 255, 0.3);border-top:2px solid #ffffff;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.camera-selector-dropdown{position:absolute;top:56px;right:16px;z-index:30;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;min-width:260px;max-width:300px;border:1px solid rgba(255, 255, 255, 0.1);overflow:hidden;pointer-events:auto;animation:slideInFromTop 0.3s ease-out}@keyframes slideInFromTop{0%{opacity:0;transform:translateY(-8px) scale(0.95)}100%{opacity:1;transform:translateY(0) scale(1)}}@keyframes slideInFromTopCentered{0%{opacity:0;transform:translate(-50%, -50%) translateY(-8px) scale(0.95)}100%{opacity:1;transform:translate(-50%, -50%) translateY(0) scale(1)}}.camera-selector-header{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-bottom:1px solid rgba(255, 255, 255, 0.1)}.camera-selector-header span{font-weight:500;color:#ffffff;font-size:13px;opacity:0.9}.close-selector{width:20px;height:20px;border:none;background:none;color:rgba(255, 255, 255, 0.7);font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all 0.2s ease}.close-selector:hover{background:rgba(255, 255, 255, 0.1);color:#ffffff}.camera-list{padding:4px 0;max-height:240px;overflow-y:auto}.camera-option{width:100%;padding:8px 12px;border:none;background:none;text-align:left;cursor:pointer;transition:all 0.2s ease;display:flex;justify-content:flex-start;align-items:center;gap:8px;color:rgba(255, 255, 255, 0.9)}.camera-option:hover{background:rgba(255, 255, 255, 0.08)}.camera-option.selected{background:rgba(255, 255, 255, 0.12);color:#ffffff}.camera-label{font-size:13px;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:0;font-weight:400;display:flex;align-items:center;gap:6px}.camera-label .autofocus-icon{font-size:12px;color:#ffffff !important;opacity:0.8;flex-shrink:0}.selected-indicator{font-size:14px;color:#ffffff;opacity:0.9;flex-shrink:0}.device-info{padding:6px 12px;border-top:1px solid rgba(255, 255, 255, 0.1);background:rgba(255, 255, 255, 0.05)}.device-info small{color:rgba(255, 255, 255, 0.6);font-size:11px;text-transform:capitalize;font-weight:400}@media (max-width: 480px){.camera-controls{top:12px;right:12px;gap:6px}.camera-selector-button{height:36px;padding:0 12px;font-size:11px;border-radius:6px}.camera-selector-dropdown{right:12px;top:48px;min-width:240px;max-width:calc(100vw - 24px)}.camera-selector-header{padding:6px 10px}.camera-option{padding:6px 10px}.device-info{padding:4px 10px}}.watermark{position:absolute;bottom:12px;right:12px;z-index:15;pointer-events:none;opacity:0.7}.watermark img{height:24px;width:auto;filter:drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3))}.component-status{position:absolute;top:16px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);display:flex;align-items:center;gap:6px;padding:6px 10px;z-index:40;height:32px;width:fit-content;animation:slideInFromTop 0.3s ease-out}.status-spinner{width:16px;height:16px;border:1px solid rgba(255, 255, 255, 0.3);border-top:1px solid #ffffff;border-radius:50%;animation:statusSpin 1s linear infinite;flex-shrink:0}.status-content{display:flex;flex-direction:column;gap:1px}.status-message{color:#ffffff;font-size:12px;font-weight:500;margin:0}.status-description{color:rgba(255, 255, 255, 0.7);font-size:10px;line-height:1.2;margin:0}@keyframes statusSpin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@media (max-width: 480px){.component-status{top:12px;left:12px;padding:4px 8px;gap:4px;height:28px;border-radius:8px}.status-spinner{width:14px;height:14px}.status-message{font-size:11px}.status-description{font-size:9px}.guide-text{font-size:11px;padding:4px 8px;border-radius:8px}}.loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0, 0, 0, 0.85);backdrop-filter:blur(4px);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:30;border-radius:8px}.loading-spinner{width:50px;height:50px;border:3px solid rgba(255, 255, 255, 0.15);border-top:3px solid #28a745;border-radius:50%;animation:spin 1s ease-in-out infinite;margin-bottom:16px}.loading-text{color:#ffffff;font-size:14px;font-weight:500;text-align:center;opacity:0.9;margin-bottom:4px}.loading-description{color:rgba(255, 255, 255, 0.7);font-size:12px;text-align:center;opacity:0.8}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.performance-monitor{position:absolute;top:70px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);z-index:35;width:fit-content;animation:slideInFromTop 0.3s ease-out;transition:all 0.3s ease}@keyframes slideInFromLeft{0%{opacity:0;transform:translateX(-20px) scale(0.95)}100%{opacity:1;transform:translateX(0) scale(1)}}.performance-expanded{padding:6px 10px}.metrics-row{display:flex;gap:8px;margin-bottom:4px}.metrics-row:last-child{margin-bottom:0}.metric-compact{display:flex;flex-direction:column;align-items:center;gap:2px;min-width:50px}.metric-label{font-size:9px;color:rgba(255, 255, 255, 0.6);font-weight:500;text-transform:uppercase;letter-spacing:0.3px}.metric-value{font-size:10px;font-weight:600;font-family:'Monaco', 'Menlo', 'Consolas', monospace;padding:2px 4px;border-radius:3px;text-align:center;white-space:nowrap}.metric-value.good{color:#4ade80;background:rgba(74, 222, 128, 0.1);border:1px solid rgba(74, 222, 128, 0.2)}.metric-value.warning{color:#fbbf24;background:rgba(251, 191, 36, 0.1);border:1px solid rgba(251, 191, 36, 0.2)}.metric-value.danger{color:#f87171;background:rgba(248, 113, 113, 0.1);border:1px solid rgba(248, 113, 113, 0.2)}@media (max-width: 480px){.performance-monitor{top:60px;left:12px;width:fit-content}.performance-expanded{padding:4px 8px}.metrics-row{gap:6px;margin-bottom:3px}.metric-compact{min-width:45px;gap:1px}.metric-label{font-size:8px}.metric-value{font-size:9px;padding:1px 3px}}.quality-monitor{position:absolute;top:200px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);z-index:35;width:fit-content;animation:slideInFromLeft 0.3s ease-out;transition:all 0.3s ease}.quality-text{padding:6px 10px;font-size:11px;color:white;font-family:'Monaco', 'Menlo', 'Consolas', monospace;line-height:1.4}.quality-fail{color:#ff9999}@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.7}}.metric-value.danger{animation:pulse 2s infinite}@media (max-width: 480px){.quality-monitor{top:160px;left:12px}.quality-text{padding:4px 8px;font-size:10px}}.manual-capture-section{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;display:flex;flex-direction:column;align-items:center;width:100%;max-width:300px}.manual-capture-button{pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.manual-capture-button:hover{background:#f8f9fa}.manual-capture-button:active{background:#e9ecef;transform:translateY(1px)}.manual-capture-button:disabled{background:#e9ecef;color:#6c757d;cursor:not-allowed;transform:none}@media (max-width: 480px){.manual-capture-section{bottom:16px;max-width:280px}.manual-capture-button{padding:10px 20px;font-size:13px}}";
1093
1093
 
1094
1094
  const JaakStamps = class {
1095
1095
  constructor(hostRef) {
@@ -1145,7 +1145,8 @@ const JaakStamps = class {
1145
1145
  };
1146
1146
  backDocumentTimerRemaining = 0;
1147
1147
  showManualCaptureButton = false;
1148
- captureStateVersion = 0; // Triggers re-render when StateManager changes
1148
+ performanceDegradedMode = false; // Auto-switched to manual mode due to performance
1149
+ showPerformanceMessage = false; // Show performance message temporarily
1149
1150
  // Services
1150
1151
  serviceContainer;
1151
1152
  eventBus;
@@ -1169,7 +1170,6 @@ const JaakStamps = class {
1169
1170
  fps: 0,
1170
1171
  inferenceTime: 0,
1171
1172
  memoryUsage: 0,
1172
- cpuUsage: 0,
1173
1173
  onnxLoadTime: 0,
1174
1174
  frameProcessingTime: 0,
1175
1175
  totalDetections: 0,
@@ -1188,6 +1188,12 @@ const JaakStamps = class {
1188
1188
  MIN_INFERENCE_INTERVAL = 50;
1189
1189
  performanceHistory = [];
1190
1190
  PERFORMANCE_HISTORY_SIZE = 10;
1191
+ // Sistema simplificado de monitoreo de rendimiento
1192
+ PERFORMANCE_THRESHOLD_MS = 2000; // Umbral único para todos los frames
1193
+ SLOW_FRAMES_TO_TRIGGER = 2; // Cuántos frames lentos consecutivos antes de cambiar
1194
+ slowFrameCount = 0; // Contador de frames consecutivos lentos
1195
+ processedFramesCount = 0; // Contador total de frames procesados
1196
+ hasAutoSwitchedToManual = false;
1191
1197
  // Canvas pool for optimized screenshot capture
1192
1198
  canvasPool = [];
1193
1199
  MAX_CANVAS_POOL_SIZE = 3;
@@ -1220,14 +1226,8 @@ const JaakStamps = class {
1220
1226
  this.detectionService = this.serviceContainer.getDetectionService();
1221
1227
  }
1222
1228
  async setupEventListeners() {
1223
- this.eventBus.on('state-changed', (data) => {
1224
- this.handleStateChange(data);
1225
- });
1226
- this.eventBus.on('camera-changed', () => {
1227
- // Camera changed event
1228
- });
1229
- this.eventBus.on('error', () => {
1230
- // Handle service errors
1229
+ this.eventBus.on('state-changed', () => {
1230
+ this.handleStateChange();
1231
1231
  });
1232
1232
  }
1233
1233
  async initializeComponent() {
@@ -1334,7 +1334,8 @@ const JaakStamps = class {
1334
1334
  return false;
1335
1335
  }
1336
1336
  }
1337
- handleStateChange(data) {
1337
+ handleStateChange() {
1338
+ // Handle state changes from StateManager if needed
1338
1339
  }
1339
1340
  initializeResizeObserver() {
1340
1341
  if ('ResizeObserver' in window && this.detectionContainer) {
@@ -1351,13 +1352,14 @@ const JaakStamps = class {
1351
1352
  this.updateMaskDimensions(rect);
1352
1353
  }
1353
1354
  }
1354
- triggerRerender() {
1355
- this.captureStateVersion = this.captureStateVersion + 1;
1356
- }
1357
1355
  getGuideText(step) {
1358
1356
  if (step === 'completed') {
1359
1357
  return 'Proceso completado';
1360
1358
  }
1359
+ // Check if we should show performance message
1360
+ if (this.showPerformanceMessage && step === 'front') {
1361
+ return 'Modo manual activado por rendimiento. Use el botón para capturar.';
1362
+ }
1361
1363
  if (step === 'front') {
1362
1364
  // Para el frente, si el detector manual está activo, mostrar instrucciones de captura manual
1363
1365
  if (this.showManualCaptureButton) {
@@ -1587,9 +1589,21 @@ const JaakStamps = class {
1587
1589
  if (this.stateManager) {
1588
1590
  this.stateManager.updateCaptureState({ isLoading: true });
1589
1591
  }
1590
- await this.detectionService.loadModel();
1592
+ try {
1593
+ await this.detectionService.loadModel();
1594
+ }
1595
+ catch (modelError) {
1596
+ this.switchToManualModeWithError('Error al cargar modelo de detección');
1597
+ throw modelError;
1598
+ }
1591
1599
  this.updateStatus('Optimizando detección...', 'Configurando reconocimiento de documentos', 'loading');
1592
- await this.detectionService.loadClassificationModel();
1600
+ try {
1601
+ await this.detectionService.loadClassificationModel();
1602
+ }
1603
+ catch (classificationError) {
1604
+ this.switchToManualModeWithError('Error al cargar modelo de clasificación');
1605
+ throw classificationError;
1606
+ }
1593
1607
  const loadEndTime = performance.now();
1594
1608
  const loadTime = loadEndTime - loadStartTime;
1595
1609
  // Record ONNX load time
@@ -1706,9 +1720,21 @@ const JaakStamps = class {
1706
1720
  const loadStartTime = performance.now();
1707
1721
  this.updateStatus('Preparando reconocimiento...', 'Configurando detección de documentos', 'loading');
1708
1722
  this.stateManager.updateCaptureState({ isLoading: true });
1709
- await this.detectionService.loadModel();
1723
+ try {
1724
+ await this.detectionService.loadModel();
1725
+ }
1726
+ catch (modelError) {
1727
+ this.switchToManualModeWithError('Error al cargar modelo de detección');
1728
+ throw modelError;
1729
+ }
1710
1730
  this.updateStatus('Optimizando detección...', 'Configurando reconocimiento de documentos', 'loading');
1711
- await this.detectionService.loadClassificationModel();
1731
+ try {
1732
+ await this.detectionService.loadClassificationModel();
1733
+ }
1734
+ catch (classificationError) {
1735
+ this.switchToManualModeWithError('Error al cargar modelo de clasificación');
1736
+ throw classificationError;
1737
+ }
1712
1738
  const loadEndTime = performance.now();
1713
1739
  const loadTime = loadEndTime - loadStartTime;
1714
1740
  // Record ONNX load time
@@ -1723,9 +1749,9 @@ const JaakStamps = class {
1723
1749
  // Paso 3: Configurar cámara seleccionada
1724
1750
  this.updateStatus('Ajustando cámara...', 'Configurando calidad de imagen', 'loading');
1725
1751
  const stream = await this.cameraService.setupCamera();
1726
- // Paso 4: Inicializar video y ocultar estado inmediatamente
1752
+ // Paso 4: Inicializar video y mostrar estado de análisis inicial
1727
1753
  if (this.useDocumentDetector) {
1728
- this.updateStatus('Captura activa', 'Buscando documento en el marco de captura', 'active');
1754
+ this.updateStatus('Analizando estabilidad...', 'Evaluando rendimiento del sistema', 'loading');
1729
1755
  }
1730
1756
  else {
1731
1757
  this.updateStatus('Captura activa', 'Posicione su documento y use el botón para capturar', 'active');
@@ -1775,8 +1801,8 @@ const JaakStamps = class {
1775
1801
  const captureState = this.stateManager.getCaptureState();
1776
1802
  if (!this.videoRef || !this.detectionContainer || !this.detectionService.isModelLoaded())
1777
1803
  return;
1778
- // Show manual capture button when document detector is disabled
1779
- if (!this.useDocumentDetector) {
1804
+ // Show manual capture button when document detector is disabled or performance is degraded
1805
+ if (!this.useDocumentDetector || this.performanceDegradedMode) {
1780
1806
  this.showManualCaptureButton = true;
1781
1807
  // Continue the loop for UI updates but skip detection logic
1782
1808
  if (captureState.step !== 'completed') {
@@ -1784,7 +1810,7 @@ const JaakStamps = class {
1784
1810
  }
1785
1811
  return;
1786
1812
  }
1787
- else {
1813
+ else if (!this.performanceDegradedMode) {
1788
1814
  this.showManualCaptureButton = false;
1789
1815
  }
1790
1816
  if (captureState.isDetectionPaused) {
@@ -1814,10 +1840,27 @@ const JaakStamps = class {
1814
1840
  this.lastInferenceTime = currentTime;
1815
1841
  // Measure preprocessing and inference time
1816
1842
  const inferenceStartTime = performance.now();
1817
- const inputTensor = this.detectionService.preprocess(this.videoRef);
1818
- // Standard detection without quality validation
1819
- const detections = await this.detectionService.runInference(inputTensor);
1820
- const inferenceTime = performance.now() - inferenceStartTime;
1843
+ let inputTensor;
1844
+ let detections;
1845
+ let inferenceTime;
1846
+ try {
1847
+ inputTensor = this.detectionService.preprocess(this.videoRef);
1848
+ }
1849
+ catch (preprocessError) {
1850
+ this.switchToManualModeWithError('Error al procesar imagen');
1851
+ return;
1852
+ }
1853
+ try {
1854
+ // Standard detection without timeout (timeout is handled by frame counting)
1855
+ detections = await this.detectionService.runInference(inputTensor);
1856
+ inferenceTime = performance.now() - inferenceStartTime;
1857
+ }
1858
+ catch (inferenceError) {
1859
+ this.switchToManualModeWithError('Error en detección automática');
1860
+ return;
1861
+ }
1862
+ // Increment frame count
1863
+ this.processedFramesCount++;
1821
1864
  // Record ONNX performance metrics
1822
1865
  if (this.debug) {
1823
1866
  this.recordOnnxPerformance(0, inferenceTime);
@@ -1856,9 +1899,30 @@ const JaakStamps = class {
1856
1899
  }
1857
1900
  this.updateMaskColor(detections);
1858
1901
  // Record frame processing metrics
1902
+ const frameEndTime = performance.now();
1903
+ const totalFrameTime = frameEndTime - frameStartTime;
1904
+ // Sistema simplificado: Verificar rendimiento de cada frame (solo si no se ha cambiado a manual)
1905
+ if (this.useDocumentDetector && !this.hasAutoSwitchedToManual) {
1906
+ // Verificar si el frame es lento
1907
+ if (totalFrameTime >= this.PERFORMANCE_THRESHOLD_MS) {
1908
+ this.slowFrameCount++;
1909
+ // Si tenemos suficientes frames lentos consecutivos, cambiar a manual
1910
+ if (this.slowFrameCount >= this.SLOW_FRAMES_TO_TRIGGER) {
1911
+ this.switchToManualMode();
1912
+ }
1913
+ }
1914
+ else {
1915
+ // Frame rápido, reiniciar contador
1916
+ if (this.slowFrameCount > 0) {
1917
+ this.slowFrameCount = 0;
1918
+ }
1919
+ }
1920
+ // Cambiar mensaje de estado después de analizar los primeros 2 frames
1921
+ if (this.processedFramesCount === 2) {
1922
+ this.updateStatus('Captura activa', 'Buscando documento en el marco de captura', 'active');
1923
+ }
1924
+ }
1859
1925
  if (this.debug) {
1860
- const frameEndTime = performance.now();
1861
- const totalFrameTime = frameEndTime - frameStartTime;
1862
1926
  this.recordFrameProcessing(totalFrameTime, detections.length);
1863
1927
  }
1864
1928
  // Continue detection loop
@@ -1894,6 +1958,8 @@ const JaakStamps = class {
1894
1958
  clearTimeout(this.alignmentTimer);
1895
1959
  this.alignmentTimer = undefined;
1896
1960
  }
1961
+ // Liberar recursos de ONNX al limpiar el componente
1962
+ this.releaseOnnxResources();
1897
1963
  if (this.performanceUpdateInterval) {
1898
1964
  clearInterval(this.performanceUpdateInterval);
1899
1965
  this.performanceUpdateInterval = undefined;
@@ -1914,7 +1980,7 @@ const JaakStamps = class {
1914
1980
  isCapturing: false
1915
1981
  };
1916
1982
  const cameraInfo = this.cameraInfoWithAutofocus;
1917
- return (h("div", { key: '3026fb421368ee82a1d2cefd8f9355ebf3194146', class: "detector-container" }, h("div", { key: '62b1230c3268412f4ff301d480d666065037d9b3', class: "video-container" }, h("video", { key: '170a0e7235522dec33b914b6d2841b36503c781f', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: '915af3649a7a551a46f1cb97af0a45916666cc12', 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: {
1983
+ return (h("div", { key: '687a01ebb87f3c9e4424f4bcd355cd68c21366f0', class: "detector-container" }, h("div", { key: 'd4c9f1fbf653ea7764dcc7265f5f7180c99fe5e7', class: "video-container" }, h("video", { key: '37a159daaaa4682d8e14a1dcdef32225706e1f20', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: '74fe5c8612be7a8d904510c226d68a6860a0f67d', 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: {
1918
1984
  position: 'absolute',
1919
1985
  left: `${box.x}px`,
1920
1986
  top: `${box.y}px`,
@@ -1923,9 +1989,9 @@ const JaakStamps = class {
1923
1989
  border: '2px solid #32406C',
1924
1990
  pointerEvents: 'none',
1925
1991
  boxSizing: 'border-box'
1926
- } })))), this.isMaskReady && (h("div", { key: 'b40cf136e5b9a120aa7243c12005383196428b34', class: "overlay-mask" }, h("div", { key: 'e82324a37682c94f03576e89d880c3b17520b5e5', class: "card-outline" }, h("div", { key: 'b1fd7df2a36300f2e6eb96474b449be74abd1ed4', class: "side side-top" }), h("div", { key: 'a6b3eb63fb35b22d0d53c8fd5aa88b2e299ae8c4', class: "side side-right" }), h("div", { key: '2d43e9281ad4fe05e314627aa249f56a7b0de9f1', class: "side side-bottom" }), h("div", { key: '231440a2dccc0f8ede35971ef092523d7be444b9', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'a923e81e11ead323b9bcf76bd6b0fea421bc1517', class: "guide-text" }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '4b68212634cbc4916cd16c4e00ca4e91b924de6e', class: "back-capture-section" }, h("div", { key: 'f2ec22b132defe1e4026ad38977c52974c5cdb21', class: "back-capture-buttons" }, !this.useDocumentDetector && (h("button", { key: 'ae8c0e452fbf1bb69b6683ae775f1c1a4b7d22d9', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: captureState.isCapturing }, captureState.isCapturing ? 'Capturando...' : 'Capturar Reverso')), h("button", { key: 'f1ec52715a584da161885bcbae0db7a38632905c', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
1992
+ } })))), this.isMaskReady && (h("div", { key: '4f2e282a8eb99947b1e67690ef236019e87ad87e', class: "overlay-mask" }, h("div", { key: '1d102684d59e5f7f5d6243f95e39ee0e1812032e', class: "card-outline" }, h("div", { key: '4ba0df1528de02cc037022948e425ffb13c49822', class: "side side-top" }), h("div", { key: '36bc3f2d39f61d39af2522ffe13b6df16c8bf00b', class: "side side-right" }), h("div", { key: '88d2402044de0309055c31fd98e596b88b1d51ce', class: "side side-bottom" }), h("div", { key: '72262621ee2c2b4824f3b313f27a5793fa4c123f', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'df9320c0f5518c04b1504d355223730e6d686779', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'e86f6eec1ea7712fb8c94d1455dd9c0c7c01db21', class: "back-capture-section" }, h("div", { key: 'ad965847b25eeae92eb22c3d89b09e953fabb2d2', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode) && (h("button", { key: '3e57f0bf7600bc650e44f40e3c1fd13747885781', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: captureState.isCapturing }, captureState.isCapturing ? 'Capturando...' : 'Capturar Reverso')), h("button", { key: 'd598cd7778869b46b5c7ceafcb43c469b4b5c7e7', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
1927
1993
  ? `Saltar reverso (${this.backDocumentTimerRemaining}s)`
1928
- : 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: 'a831afce8ac493fe9716fc5608c1be5373cac9f4', class: "camera-controls" }, h("button", { key: '9a56a494d6357eac86211af857b74db4509aad64', 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: 'b08699bf97018b3318771aa9c19a5848fae6e09f', class: "camera-selector-dropdown" }, h("div", { key: '24d010fde00991a80f92803511ae31ab23d2d4ee', class: "camera-selector-header" }, h("span", { key: 'ea0a21c5989cc28dff59bab870cfbb39b401b466' }, "Seleccionar C\u00E1mara"), h("button", { key: '2cbd997565bfaeceb799a95fcb8e26681bab22ef', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: 'c00abb13cb7299ff325b85d3fcd44dcad7839e53', 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}`, camera.hasAutofocus && (h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: 'e369c9ae07f0638b490d67bb01ad2a3a7f9b56a1', class: "device-info" }, h("small", { key: '04d4a8c24a1a4487939f87e8af240962705fd685' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'f955e8e5b6917d01477fd171e3c16a44a3d0a916', class: "manual-capture-section" }, h("button", { key: 'cb122ec84fec7afae8185e561f4da197a210b0dd', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: captureState.isCapturing }, captureState.isCapturing ? 'Capturando...' : 'Capturar Frente'))))), captureState.isCapturing && (h("div", { key: '98d15bcd0afab9daa3bc64096535db74f795723b', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: '86132c96fc3ff3296c04c32c03ef624511d175fd', class: "flip-animation" }, h("div", { key: '05efba20dc5a4890a6de5650e67b5144853fa9d6', class: "id-card-icon" }), h("div", { key: 'a2e307b126a1c65681733e68bb737ed21e9cb119', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: '38e1e4f5c3c8a5002fc45c8490e3134e31b4652a', class: "success-animation" }, h("div", { key: '2f6faebde51e90059106e64ef50af51d9395c0cf', class: "check-icon" }), h("div", { key: '63385f75ab3933966f58bb954c13f4cacb4d5c21', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: '0853a33e794b26c727336fb13c9430d99b992d7f', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: 'e0d258b6897ebaa281473ee6633244a89d9b3cc2', class: "status-spinner" })), h("div", { key: 'e54b82a5a895734bdaeb95fc9bfb631fd4680c87', class: "status-content" }, h("div", { key: '57e712d858574138a9ffdefa298adc99765788f3', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: 'b2e1240eb71ed506157353fe5e24d62c3a0da8ab', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: '3f3acb1ffc8e2c1d64cc8dd0e76bf64772a92def', class: "performance-monitor" }, h("div", { key: '83c1640404aad9552ad082a78327acf9facd79ad', class: "performance-expanded" }, h("div", { key: '18ee837b0fa64bae25285183cbf79733f7654153', class: "metrics-row" }, h("div", { key: 'b7d6b1c15b7e57e67d886c1bbc279573e795a3a3', class: "metric-compact" }, h("span", { key: '2b02e2323aadc064231ab8735a5810acc7bdd871', class: "metric-label" }, "FPS"), h("span", { key: 'd0cbe3e212f216834127456574eef6e61b4f3d6c', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: '974538f93bbe0abb25eadba4a73d9a28f9c9ae0a', class: "metric-compact" }, h("span", { key: 'e04bc2180ede406b787f63f92eb6086d4e372c77', class: "metric-label" }, "MEM"), h("span", { key: 'c7911542d7a39a334b0a2f0f258256d11b297fa4', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: '92bbce4d85240a84d53afce554792ae51597e16f', class: "metrics-row" }, h("div", { key: '7b78afc87a85a229b582d870e85d3015ca54b941', class: "metric-compact" }, h("span", { key: '7579b2b804c8a869894c0ed5a89c71f19d493c69', class: "metric-label" }, "INF"), h("span", { key: '029733bca2504d1d3c1fef77519e0df90b28d5d1', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: 'f7fe505877d8e9214c2c819e714e3039c95c0ec7', class: "metric-compact" }, h("span", { key: 'ecef2280e78aecb7b811f9fa14c7fdbda8c4d065', class: "metric-label" }, "FRAME"), h("span", { key: 'c6cadf43725c125f371d3d849e8b09953a3747fc', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: '832e8ee75377791a17279a3c7eee12fc45f21820', class: "metrics-row" }, h("div", { key: 'abb2dc9ce8a52374bc04e4b36560885427303fb6', class: "metric-compact" }, h("span", { key: '8f8c9cfab162a01807d07f44278f4f5889a1b206', class: "metric-label" }, "DET"), h("span", { key: '7359af4c236091e99b1f653ba20d8e3bd3acaf1b', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: '7dd17d6d47289a11087a33c6104269899b72e46e', class: "metric-compact" }, h("span", { key: '0b1317becd3af6804e1fb1965593882886c51b15', class: "metric-label" }, "RATE"), h("span", { key: '9e94ba4257aa707e6c751852db48a17fb7ec8bae', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: '77beb6f47153c43fddbc643fe00d1777ecfab295', class: "watermark" }, h("img", { key: 'e6aec0055f8ffb058dc2249fa1182dae06638a31', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
1994
+ : 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: 'b1508382d2b75584a19dade3f8e685a34ff2c3a3', class: "camera-controls" }, h("button", { key: '9c1f945b051f8e000f87fb3674ecfd386bdc2208', 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: '4adab3b896be86322be168db377cbacbcb3a7422', class: "camera-selector-dropdown" }, h("div", { key: 'a60e3f46cfe5997cf9b82d685a1574b7002c0071', class: "camera-selector-header" }, h("span", { key: '71e012a8a4953f584aeffc985040e434fadfb00b' }, "Seleccionar C\u00E1mara"), h("button", { key: '046ee4f6d81b34349ecad4e9de98f4d8653dad6b', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: '539ad135914d9ceb3a6b9a2de2d9ae4ea7a996b3', 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}`, camera.hasAutofocus && (h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '082d1cc259af3c1fc95b53da1e754382e874b837', class: "device-info" }, h("small", { key: 'dad398582ac7bfd31ee43704d47fd3036fc59d06' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '231ff3eb4672b4ac310419cccc8cd6d1caab9e14', class: "manual-capture-section" }, h("button", { key: 'fa2fcc4bfe63bf2ccdba2c2ad3c8c4b4a5aabbb5', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: captureState.isCapturing }, captureState.isCapturing ? 'Capturando...' : 'Capturar Frente'))))), captureState.isCapturing && (h("div", { key: '39426754973f1a9e07b56399f344add21bf9b848', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: '307a7eb06b41a8baebe37ad26b1f5e4cf0a43ec1', class: "flip-animation" }, h("div", { key: '7070ad263e3894dc1488bb8a17f5bf23b7b757f0', class: "id-card-icon" }), h("div", { key: '81a0d8b6377b397bbeebe2e31800fe88f88593a0', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: '741e5043bd57a3e13e39fd897a64cd20a75dad2e', class: "success-animation" }, h("div", { key: '6269a51c0651e5f76490906e50eb111f6a88f267', class: "check-icon" }), h("div", { key: '1c90a9cf6c90bb10af90660c714b7ff1ed6acfa0', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: 'f6746c1fb15cc238846f047743a9d45b1d4a41f8', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: '00d198abdc90683e5f05a9fd9b54d44e55c16630', class: "status-spinner" })), h("div", { key: 'b0254dea36bae65692bfbd200dfb75eb5a3a50dc', class: "status-content" }, h("div", { key: 'e3e48ea04f40ddd7c66aa8eda3d341f24a9c3dc4', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: 'd3f40ca5b72a661f9631145880fc6d1bba878961', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: 'eabe40809e744eb62b2ac76733952060988b675c', class: "performance-monitor" }, h("div", { key: '44e51257d4ba2c2153749cf14f3aebbf22ca02ec', class: "performance-expanded" }, h("div", { key: '493fc680db2d1e82068eadda3786fad57e8594cc', class: "metrics-row" }, h("div", { key: 'aaa734d066246c9364d51c04d41a0a84d0b7e216', class: "metric-compact" }, h("span", { key: 'f0b59f76e8aa1723a429289b7898d35f22ff86d4', class: "metric-label" }, "FPS"), h("span", { key: 'a562359df92cabe40f54b355ffa264f246e7ec8e', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: '9adca77e934ee3cd07fb54a056132e305637848c', class: "metric-compact" }, h("span", { key: '65ec83dca0e74b42065962d2a2e4bae7515b9fc1', class: "metric-label" }, "MEM"), h("span", { key: '427fc6b5b538742d0987b0240f526616b910ae69', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: 'fc551d8ef39308980437b72b3fb4c0bdb2bfbf67', class: "metrics-row" }, h("div", { key: 'b88785c108e5586fecc8702f3e4da883ace00f15', class: "metric-compact" }, h("span", { key: '31db440861e6fd9c2ee36ccd242f1b7bb3d47f45', class: "metric-label" }, "INF"), h("span", { key: 'af45bbb41110a04ed3d22a9e112b8644dd7ec355', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: 'deabe5ce0661557fabe4ccdde1af48beed564ad9', class: "metric-compact" }, h("span", { key: '072f9159e95b3f3226f07b879b377a3d34940825', class: "metric-label" }, "FRAME"), h("span", { key: '841de1ae8df76919c2b644c6ff813dd927b52013', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: '68c6c777db1430987f20536849a3ed9169ec794a', class: "metrics-row" }, h("div", { key: '736e361beaa88d268041ec55fd73db0ee405e1ae', class: "metric-compact" }, h("span", { key: 'bfa6c3aa54a96e5eab32dc4fa0227ca836142561', class: "metric-label" }, "DET"), h("span", { key: 'f9a2479c470779403bf1cbfd4f433f80e5fa34d8', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: 'bfc1d7f8cbc7449a96e751b005a02bb112e63a86', class: "metric-compact" }, h("span", { key: '45a7171a72ac6ae9c29a4de3c7a260ae78681dc1', class: "metric-label" }, "RATE"), h("span", { key: '7419ace73d0302d662b3a6308f313be271049b5a', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: '786544dff913bb4b1003e62d9ab35b3f29f4b497', class: "watermark" }, h("img", { key: 'e08c893afa8bad94d04b01ea4732044b1c9a2d6c', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
1929
1995
  }
1930
1996
  // Utility methods
1931
1997
  updateDetectionBoxes(boxes) {
@@ -2113,12 +2179,17 @@ const JaakStamps = class {
2113
2179
  });
2114
2180
  // Check if document classification is enabled (independent of detector)
2115
2181
  if (this.useDocumentClassification) {
2116
- const classification = await this.detectionService.classifyDocument(croppedCanvas);
2117
- if (classification && classification.class === 'passport') {
2118
- this.completeProcess(true);
2119
- this.returnCanvasToPool(captureCanvas);
2120
- this.returnCanvasToPool(croppedCanvas);
2121
- return;
2182
+ try {
2183
+ const classification = await this.detectionService.classifyDocument(croppedCanvas);
2184
+ if (classification && classification.class === 'passport') {
2185
+ this.completeProcess(true);
2186
+ this.returnCanvasToPool(captureCanvas);
2187
+ this.returnCanvasToPool(croppedCanvas);
2188
+ return;
2189
+ }
2190
+ }
2191
+ catch (classifyError) {
2192
+ // No cambiar a manual aquí, solo registrar el error y continuar
2122
2193
  }
2123
2194
  }
2124
2195
  this.stateManager.updateCaptureState({
@@ -2126,13 +2197,11 @@ const JaakStamps = class {
2126
2197
  isDetectionPaused: true,
2127
2198
  showFlipAnimation: true
2128
2199
  });
2129
- this.triggerRerender();
2130
2200
  setTimeout(() => {
2131
2201
  this.stateManager.updateCaptureState({
2132
2202
  showFlipAnimation: false,
2133
2203
  isDetectionPaused: false
2134
2204
  });
2135
- this.triggerRerender();
2136
2205
  this.startBackDocumentTimer();
2137
2206
  }, 3000);
2138
2207
  }
@@ -2182,10 +2251,15 @@ const JaakStamps = class {
2182
2251
  });
2183
2252
  // Check if document classification is enabled
2184
2253
  if (this.useDocumentClassification) {
2185
- const classification = await this.detectionService.classifyDocument(croppedCanvas);
2186
- if (classification && classification.class === 'passport') {
2187
- this.completeProcess(true);
2188
- return;
2254
+ try {
2255
+ const classification = await this.detectionService.classifyDocument(croppedCanvas);
2256
+ if (classification && classification.class === 'passport') {
2257
+ this.completeProcess(true);
2258
+ return;
2259
+ }
2260
+ }
2261
+ catch (classifyError) {
2262
+ // No cambiar a manual aquí, solo registrar el error y continuar
2189
2263
  }
2190
2264
  }
2191
2265
  this.stateManager.updateCaptureState({
@@ -2222,6 +2296,60 @@ const JaakStamps = class {
2222
2296
  cardOutline?.classList.remove('capturing');
2223
2297
  }, 600);
2224
2298
  }
2299
+ // Método simplificado para cambio a modo manual
2300
+ switchToManualMode() {
2301
+ // Only switch if detector is enabled and not already switched
2302
+ if (!this.useDocumentDetector || this.hasAutoSwitchedToManual) {
2303
+ return;
2304
+ }
2305
+ // Detener todo el monitoreo de performance
2306
+ this.stopPerformanceMonitoring();
2307
+ // Liberar recursos de ONNX
2308
+ this.releaseOnnxResources();
2309
+ this.hasAutoSwitchedToManual = true;
2310
+ this.performanceDegradedMode = true;
2311
+ this.showManualCaptureButton = true;
2312
+ this.showPerformanceMessage = true;
2313
+ // Hide performance message after 5 seconds
2314
+ setTimeout(() => {
2315
+ this.showPerformanceMessage = false;
2316
+ }, 5000);
2317
+ }
2318
+ // Método para cambiar a modo manual por errores de ONNX
2319
+ switchToManualModeWithError(errorMessage) {
2320
+ // Solo cambiar si el detector está habilitado y no se ha cambiado ya
2321
+ if (!this.useDocumentDetector || this.hasAutoSwitchedToManual) {
2322
+ return;
2323
+ }
2324
+ // Liberar recursos de ONNX inmediatamente
2325
+ this.releaseOnnxResources();
2326
+ // Cambiar a modo manual
2327
+ this.hasAutoSwitchedToManual = true;
2328
+ this.performanceDegradedMode = true;
2329
+ this.showManualCaptureButton = true;
2330
+ this.useDocumentDetector = false; // Desactivar detector automático
2331
+ // Actualizar el estado con mensaje de error
2332
+ this.updateStatus('Modo manual activado', errorMessage, 'error');
2333
+ // Ocultar mensaje después de 5 segundos
2334
+ setTimeout(() => {
2335
+ this.updateStatus('Captura manual', 'Use el botón para capturar', 'ready');
2336
+ }, 5000);
2337
+ }
2338
+ stopPerformanceMonitoring() {
2339
+ // Nota: No necesitamos limpiar más variables porque ya no se usarán
2340
+ // El sistema automáticamente saltará la lógica de performance una vez que hasAutoSwitchedToManual = true
2341
+ }
2342
+ // Método para liberar recursos de ONNX cuando se cambia a modo manual
2343
+ releaseOnnxResources() {
2344
+ try {
2345
+ // Liberar recursos del servicio de detección
2346
+ if (this.detectionService) {
2347
+ this.detectionService.cleanup();
2348
+ }
2349
+ }
2350
+ catch (error) {
2351
+ }
2352
+ }
2225
2353
  completeProcess(skippedBack = false) {
2226
2354
  this.stateManager.updateCaptureState({
2227
2355
  step: 'completed',
@@ -2335,6 +2463,13 @@ const JaakStamps = class {
2335
2463
  this.detectionBoxes = [];
2336
2464
  this.alignmentStartTime = undefined;
2337
2465
  this.hasDocumentDetected = false;
2466
+ // Reset sistema simplificado
2467
+ this.processedFramesCount = 0;
2468
+ this.slowFrameCount = 0;
2469
+ // Reset performance degradation state
2470
+ this.hasAutoSwitchedToManual = false;
2471
+ this.performanceDegradedMode = false;
2472
+ this.showPerformanceMessage = false;
2338
2473
  if (this.alignmentTimer) {
2339
2474
  clearTimeout(this.alignmentTimer);
2340
2475
  this.alignmentTimer = undefined;