@jaak.ai/stamps 2.0.0-dev.24 → 2.0.0-dev.26
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.
- package/README.md +50 -12
- package/dist/cjs/{index-DGM9-FNg.js → index-BfhtOB0D.js} +5 -2
- package/dist/cjs/index-BfhtOB0D.js.map +1 -0
- package/dist/cjs/jaak-stamps-webcomponent.cjs.js +2 -2
- package/dist/cjs/jaak-stamps.cjs.entry.js +385 -25
- package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
- package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
- package/dist/cjs/loader.cjs.js +2 -2
- package/dist/collection/components/my-component/my-component.css +227 -0
- package/dist/collection/components/my-component/my-component.js +467 -24
- package/dist/collection/components/my-component/my-component.js.map +1 -1
- package/dist/components/index.js +3 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/jaak-stamps.js +393 -25
- package/dist/components/jaak-stamps.js.map +1 -1
- package/dist/esm/{index-DqoVMnc7.js → index-BP1Q4KOg.js} +5 -2
- package/dist/esm/index-BP1Q4KOg.js.map +1 -0
- package/dist/esm/jaak-stamps-webcomponent.js +3 -3
- package/dist/esm/jaak-stamps.entry.js +385 -25
- package/dist/esm/jaak-stamps.entry.js.map +1 -1
- package/dist/esm/loader.js +3 -3
- package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/p-14eb13d8.entry.js +2 -0
- package/dist/jaak-stamps-webcomponent/p-14eb13d8.entry.js.map +1 -0
- package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js +3 -0
- package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js.map +1 -0
- package/dist/types/components/my-component/my-component.d.ts +37 -0
- package/dist/types/components.d.ts +18 -0
- package/package.json +1 -1
- package/dist/cjs/index-DGM9-FNg.js.map +0 -1
- package/dist/esm/index-DqoVMnc7.js.map +0 -1
- package/dist/jaak-stamps-webcomponent/p-0521d8f5.entry.js +0 -2
- package/dist/jaak-stamps-webcomponent/p-0521d8f5.entry.js.map +0 -1
- package/dist/jaak-stamps-webcomponent/p-DqoVMnc7.js +0 -3
- package/dist/jaak-stamps-webcomponent/p-DqoVMnc7.js.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { p as proxyCustomElement, H, c as createEvent, h } from './index.js';
|
|
2
2
|
|
|
3
|
-
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,canvas{position:absolute;width:100%;height:100%;border-radius:8px}video.mirror,canvas.mirror{transform:rotateY(180deg)}canvas{z-index:1}video{z-index:0}.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;box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.7);opacity:0.8}.card-outline.perfect-match{box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.7)}.side{position:absolute;background:#999;transition:background-color 0.3s ease}.side.aligned{background:#28a745}.side-top{top:0;left:0;width:100%;height:3px}.side-right{top:0;right:0;width:3px;height:100%}.side-bottom{bottom:0;left:0;width:100%;height:3px}.side-left{top:0;left:0;width:3px;height:100%}.corner{position:absolute;width:20px;height:20px;border:2px solid #999;z-index:12}.corner-tl{top:-10px;left:-10px;border-right:none;border-bottom:none}.corner-tr{top:-10px;right:-10px;border-left:none;border-bottom:none}.corner-bl{bottom:-10px;left:-10px;border-right:none;border-top:none}.corner-br{bottom:-10px;right:-10px;border-left:none;border-top:none}.corner.perfect-match{border-color:#28a745}.guide-text{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);color:#fff;font-size:14px;font-weight:600;text-align:center;white-space:normal;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px;z-index:20}.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 9999px rgba(0, 0, 0, 0.7), 0 0 0 4px rgba(40, 167, 69, 0)}50%{border-color:#28a745;box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.7), 0 0 0 8px rgba(40, 167, 69, 0.6)}100%{border-color:#28a745;box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.7), 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-button{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;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:translateX(-50%) translateY(0)}.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))}.loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0, 0, 0, 0.8);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:30;border-radius:20px}.loading-spinner{width:60px;height:60px;border:4px solid rgba(255, 255, 255, 0.2);border-top:4px solid #007bff;border-radius:50%;animation:spin 1s linear infinite;margin-bottom:20px}.loading-text{color:white;font-size:16px;font-weight:500;text-align:center;opacity:0.9}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}";
|
|
3
|
+
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,canvas{position:absolute;width:100%;height:100%;border-radius:8px}video.mirror,canvas.mirror{transform:rotateY(180deg)}canvas{z-index:1}video{z-index:0}.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;box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.7);opacity:0.8}.card-outline.perfect-match{box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.7)}.side{position:absolute;background:#999;transition:background-color 0.3s ease}.side.aligned{background:#28a745}.side-top{top:0;left:0;width:100%;height:3px}.side-right{top:0;right:0;width:3px;height:100%}.side-bottom{bottom:0;left:0;width:100%;height:3px}.side-left{top:0;left:0;width:3px;height:100%}.corner{position:absolute;width:20px;height:20px;border:2px solid #999;z-index:12}.corner-tl{top:-10px;left:-10px;border-right:none;border-bottom:none}.corner-tr{top:-10px;right:-10px;border-left:none;border-bottom:none}.corner-bl{bottom:-10px;left:-10px;border-right:none;border-top:none}.corner-br{bottom:-10px;right:-10px;border-left:none;border-top:none}.corner.perfect-match{border-color:#28a745}.guide-text{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);color:#fff;font-size:14px;font-weight:600;text-align:center;white-space:normal;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px;z-index:20}.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 9999px rgba(0, 0, 0, 0.7), 0 0 0 4px rgba(40, 167, 69, 0)}50%{border-color:#28a745;box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.7), 0 0 0 8px rgba(40, 167, 69, 0.6)}100%{border-color:#28a745;box-shadow:0 0 0 9999px rgba(0, 0, 0, 0.7), 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-button{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;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:translateX(-50%) translateY(0)}.camera-controls{position:absolute;top:16px;right:16px;z-index:25;display:flex;gap:8px;pointer-events:auto}.flip-camera-button{height:40px;padding:0 16px;border:none;border-radius:8px;background:rgba(0, 0, 0, 0.6);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{height:40px;padding:0 16px;border:none;border-radius:8px;background:rgba(0, 0, 0, 0.6);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}.flip-camera-button:hover,.camera-selector-button:hover{background:rgba(0, 0, 0, 0.8);border-color:rgba(255, 255, 255, 0.2);transform:translateY(-1px)}.flip-camera-button:active,.camera-selector-button:active{transform:translateY(0);background:rgba(0, 0, 0, 0.9)}.camera-selector-dropdown{position:absolute;top:56px;right:16px;z-index:30;background:rgba(0, 0, 0, 0.85);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)}}.camera-selector-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;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:10px 16px;border:none;background:none;text-align:left;cursor:pointer;transition:all 0.2s ease;display:flex;justify-content:space-between;align-items:center;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:8px;font-weight:400}.selected-indicator{font-size:14px;color:#ffffff;opacity:0.9}.device-info{padding:8px 16px;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}.flip-camera-button{height:36px;padding:0 12px;font-size:11px;border-radius: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:10px 14px}.camera-option{padding:8px 14px}.device-info{padding:6px 14px}}.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))}.loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0, 0, 0, 0.8);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:30;border-radius:20px}.loading-spinner{width:60px;height:60px;border:4px solid rgba(255, 255, 255, 0.2);border-top:4px solid #007bff;border-radius:50%;animation:spin 1s linear infinite;margin-bottom:20px}.loading-text{color:white;font-size:16px;font-weight:500;text-align:center;opacity:0.9}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}";
|
|
4
4
|
|
|
5
5
|
const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H {
|
|
6
6
|
constructor() {
|
|
@@ -15,6 +15,8 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
15
15
|
alignmentTolerance = 10; // Tolerancia en píxeles para considerar un lado alineado (escalado para 320x320)
|
|
16
16
|
maskSize = 90; // Porcentaje del video que ocupará la máscara (default 90%)
|
|
17
17
|
cropMargin = 0; // Margen en píxeles para el recorte del documento (default 0)
|
|
18
|
+
useDocumentClassification = false; // Habilita la clasificación automática de documentos para determinar si solicitar reverso
|
|
19
|
+
preferredCamera = 'auto'; // Define qué cámara usar: 'auto' (automático según dispositivo), 'front' (frontal), 'back' (trasera)
|
|
18
20
|
captureCompleted;
|
|
19
21
|
isReady;
|
|
20
22
|
isVideoActive = false;
|
|
@@ -40,6 +42,10 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
40
42
|
isLoading = false;
|
|
41
43
|
isModelPreloaded = false;
|
|
42
44
|
isMaskReady = false;
|
|
45
|
+
availableCameras = [];
|
|
46
|
+
selectedCameraId = null;
|
|
47
|
+
showCameraSelector = false;
|
|
48
|
+
isMultipleCamerasAvailable = false;
|
|
43
49
|
videoRef;
|
|
44
50
|
canvasRef;
|
|
45
51
|
session;
|
|
@@ -50,6 +56,9 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
50
56
|
lastDetectedBox;
|
|
51
57
|
mobileNetSession;
|
|
52
58
|
mobileNetClassMap;
|
|
59
|
+
// Camera management properties
|
|
60
|
+
deviceType = 'desktop';
|
|
61
|
+
preferredCameraFacing = null;
|
|
53
62
|
// Performance optimization properties
|
|
54
63
|
frameSkipCounter = 0;
|
|
55
64
|
FRAME_SKIP = 2; // Process every 3rd frame (reduces CPU by ~66%)
|
|
@@ -86,6 +95,13 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
86
95
|
this.cropMargin = 0;
|
|
87
96
|
}
|
|
88
97
|
}
|
|
98
|
+
validatePreferredCamera() {
|
|
99
|
+
const validOptions = ['auto', 'front', 'back'];
|
|
100
|
+
if (!validOptions.includes(this.preferredCamera)) {
|
|
101
|
+
console.warn(`preferredCamera debe ser uno de: ${validOptions.join(', ')}. Valor actual: ${this.preferredCamera}. Usando valor por defecto: 'auto'`);
|
|
102
|
+
this.preferredCamera = 'auto';
|
|
103
|
+
}
|
|
104
|
+
}
|
|
89
105
|
emitReadyEvent() {
|
|
90
106
|
const isDocumentReady = !!window.ort && this.isModelPreloaded;
|
|
91
107
|
this.isReady.emit(isDocumentReady);
|
|
@@ -98,9 +114,267 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
98
114
|
const settings = videoTrack.getSettings();
|
|
99
115
|
return settings.facingMode === 'environment';
|
|
100
116
|
}
|
|
117
|
+
async detectDeviceTypeAndCameras() {
|
|
118
|
+
// Detect device type
|
|
119
|
+
const userAgent = navigator.userAgent;
|
|
120
|
+
const isMobile = /Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(userAgent);
|
|
121
|
+
const isTablet = /iPad|Android/i.test(userAgent) && window.innerWidth >= 768;
|
|
122
|
+
if (isTablet) {
|
|
123
|
+
this.deviceType = 'tablet';
|
|
124
|
+
}
|
|
125
|
+
else if (isMobile) {
|
|
126
|
+
this.deviceType = 'mobile';
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
this.deviceType = 'desktop';
|
|
130
|
+
}
|
|
131
|
+
this.debugLog('📱 Device type detected:', this.deviceType);
|
|
132
|
+
// Enumerate available cameras
|
|
133
|
+
await this.enumerateAndDetectCameras();
|
|
134
|
+
// Load user preference
|
|
135
|
+
this.loadCameraPreference();
|
|
136
|
+
}
|
|
137
|
+
async enumerateAndDetectCameras() {
|
|
138
|
+
try {
|
|
139
|
+
// First, check if we have permission to enumerate devices
|
|
140
|
+
const permissionStatus = await this.checkCameraPermission();
|
|
141
|
+
if (permissionStatus === 'denied') {
|
|
142
|
+
this.debugLog('❌ Camera permission denied');
|
|
143
|
+
this.statusMessage = "Permiso de cámara denegado";
|
|
144
|
+
this.statusColor = "#ff6b6b";
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
// Request minimal permission to get device labels
|
|
148
|
+
if (permissionStatus === 'prompt') {
|
|
149
|
+
const tempStream = await navigator.mediaDevices.getUserMedia({ video: true });
|
|
150
|
+
tempStream.getTracks().forEach(track => track.stop());
|
|
151
|
+
}
|
|
152
|
+
// Now enumerate devices with labels
|
|
153
|
+
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
154
|
+
this.availableCameras = devices.filter(device => device.kind === 'videoinput');
|
|
155
|
+
this.isMultipleCamerasAvailable = this.availableCameras.length > 1;
|
|
156
|
+
this.debugLog('📹 Available cameras:', {
|
|
157
|
+
count: this.availableCameras.length,
|
|
158
|
+
isMultipleCamerasAvailable: this.isMultipleCamerasAvailable,
|
|
159
|
+
cameras: this.availableCameras.map(cam => ({
|
|
160
|
+
id: cam.deviceId,
|
|
161
|
+
label: cam.label || 'Unknown Camera'
|
|
162
|
+
}))
|
|
163
|
+
});
|
|
164
|
+
// Set initial camera preference based on device type
|
|
165
|
+
this.setInitialCameraPreference();
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
this.debugLog('❌ Error enumerating cameras:', error);
|
|
169
|
+
this.handleCameraPermissionError(error);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
async checkCameraPermission() {
|
|
173
|
+
try {
|
|
174
|
+
if (!navigator.permissions) {
|
|
175
|
+
return 'prompt'; // Assume we need to prompt on older browsers
|
|
176
|
+
}
|
|
177
|
+
const permission = await navigator.permissions.query({ name: 'camera' });
|
|
178
|
+
return permission.state;
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
this.debugLog('⚠️ Could not check camera permission:', error);
|
|
182
|
+
return 'prompt';
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
handleCameraPermissionError(error) {
|
|
186
|
+
if (error.name === 'NotAllowedError') {
|
|
187
|
+
this.statusMessage = "Permiso de cámara denegado. Active el permiso en configuración.";
|
|
188
|
+
this.statusColor = "#ff6b6b";
|
|
189
|
+
this.availableCameras = [];
|
|
190
|
+
this.isMultipleCamerasAvailable = false;
|
|
191
|
+
}
|
|
192
|
+
else if (error.name === 'NotFoundError') {
|
|
193
|
+
this.statusMessage = "No se encontraron cámaras disponibles.";
|
|
194
|
+
this.statusColor = "#ff6b6b";
|
|
195
|
+
this.availableCameras = [];
|
|
196
|
+
this.isMultipleCamerasAvailable = false;
|
|
197
|
+
}
|
|
198
|
+
else if (error.name === 'NotReadableError') {
|
|
199
|
+
this.statusMessage = "Cámara en uso por otra aplicación.";
|
|
200
|
+
this.statusColor = "#ff6b6b";
|
|
201
|
+
this.availableCameras = [];
|
|
202
|
+
this.isMultipleCamerasAvailable = false;
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
this.statusMessage = "Error al acceder a las cámaras.";
|
|
206
|
+
this.statusColor = "#ff6b6b";
|
|
207
|
+
this.availableCameras = [];
|
|
208
|
+
this.isMultipleCamerasAvailable = false;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
setInitialCameraPreference() {
|
|
212
|
+
if (this.availableCameras.length === 0)
|
|
213
|
+
return;
|
|
214
|
+
// Apply user preference for camera selection
|
|
215
|
+
if (this.preferredCamera === 'front') {
|
|
216
|
+
// User explicitly wants front camera
|
|
217
|
+
this.preferredCameraFacing = 'user';
|
|
218
|
+
const frontCamera = this.availableCameras.find(camera => camera.label.toLowerCase().includes('front') ||
|
|
219
|
+
camera.label.toLowerCase().includes('user') ||
|
|
220
|
+
camera.label.toLowerCase().includes('selfie') ||
|
|
221
|
+
!camera.label.toLowerCase().includes('back') && !camera.label.toLowerCase().includes('rear'));
|
|
222
|
+
if (frontCamera) {
|
|
223
|
+
this.selectedCameraId = frontCamera.deviceId;
|
|
224
|
+
this.debugLog('👤 User selected front camera:', frontCamera.label);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
228
|
+
this.debugLog('⚠️ Front camera not found, using first available:', this.availableCameras[0].label);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
else if (this.preferredCamera === 'back') {
|
|
232
|
+
// User explicitly wants back camera
|
|
233
|
+
this.preferredCameraFacing = 'environment';
|
|
234
|
+
const backCamera = this.availableCameras.find(camera => camera.label.toLowerCase().includes('back') ||
|
|
235
|
+
camera.label.toLowerCase().includes('rear') ||
|
|
236
|
+
camera.label.toLowerCase().includes('environment'));
|
|
237
|
+
if (backCamera) {
|
|
238
|
+
this.selectedCameraId = backCamera.deviceId;
|
|
239
|
+
this.debugLog('📷 User selected back camera:', backCamera.label);
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
243
|
+
this.debugLog('⚠️ Back camera not found, using first available:', this.availableCameras[0].label);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
// Auto mode - use device type to determine best camera
|
|
248
|
+
if (this.deviceType === 'mobile' || this.deviceType === 'tablet') {
|
|
249
|
+
// For mobile/tablet, prefer rear camera for document scanning
|
|
250
|
+
this.preferredCameraFacing = 'environment';
|
|
251
|
+
const rearCamera = this.availableCameras.find(camera => camera.label.toLowerCase().includes('back') ||
|
|
252
|
+
camera.label.toLowerCase().includes('rear') ||
|
|
253
|
+
camera.label.toLowerCase().includes('environment'));
|
|
254
|
+
if (rearCamera) {
|
|
255
|
+
this.selectedCameraId = rearCamera.deviceId;
|
|
256
|
+
this.debugLog('📱 Auto-selected rear camera for mobile:', rearCamera.label);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
260
|
+
this.debugLog('📱 Rear camera not found, using first available:', this.availableCameras[0].label);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
// For desktop, use first available camera (usually the only one)
|
|
265
|
+
this.selectedCameraId = this.availableCameras[0].deviceId;
|
|
266
|
+
this.debugLog('💻 Auto-selected desktop camera:', this.availableCameras[0].label);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
loadCameraPreference() {
|
|
271
|
+
try {
|
|
272
|
+
const saved = localStorage.getItem('jaak-stamps-camera-preference');
|
|
273
|
+
if (saved) {
|
|
274
|
+
const preference = JSON.parse(saved);
|
|
275
|
+
// Validate that the saved camera is still available
|
|
276
|
+
const isStillAvailable = this.availableCameras.some(camera => camera.deviceId === preference.cameraId);
|
|
277
|
+
if (isStillAvailable) {
|
|
278
|
+
this.selectedCameraId = preference.cameraId;
|
|
279
|
+
this.preferredCameraFacing = preference.facing;
|
|
280
|
+
this.debugLog('💾 Loaded camera preference:', preference);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
catch (error) {
|
|
285
|
+
this.debugLog('⚠️ Error loading camera preference:', error);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
saveCameraPreference() {
|
|
289
|
+
try {
|
|
290
|
+
const preference = {
|
|
291
|
+
cameraId: this.selectedCameraId,
|
|
292
|
+
facing: this.preferredCameraFacing,
|
|
293
|
+
timestamp: Date.now()
|
|
294
|
+
};
|
|
295
|
+
localStorage.setItem('jaak-stamps-camera-preference', JSON.stringify(preference));
|
|
296
|
+
this.debugLog('💾 Saved camera preference:', preference);
|
|
297
|
+
}
|
|
298
|
+
catch (error) {
|
|
299
|
+
this.debugLog('⚠️ Error saving camera preference:', error);
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
async switchCamera(cameraId) {
|
|
303
|
+
if (!this.isVideoActive || this.selectedCameraId === cameraId)
|
|
304
|
+
return;
|
|
305
|
+
try {
|
|
306
|
+
// Check if the selected camera is still available
|
|
307
|
+
const selectedCamera = this.availableCameras.find(cam => cam.deviceId === cameraId);
|
|
308
|
+
if (!selectedCamera) {
|
|
309
|
+
this.debugLog('❌ Selected camera not found, re-enumerating...');
|
|
310
|
+
await this.enumerateAndDetectCameras();
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
// Show loading state
|
|
314
|
+
this.statusMessage = "Cambiando cámara...";
|
|
315
|
+
this.statusColor = "#007bff";
|
|
316
|
+
// Stop current stream
|
|
317
|
+
if (this.videoStream) {
|
|
318
|
+
this.videoStream.getTracks().forEach(track => track.stop());
|
|
319
|
+
}
|
|
320
|
+
// Update selected camera
|
|
321
|
+
this.selectedCameraId = cameraId;
|
|
322
|
+
// Update facing mode preference
|
|
323
|
+
const isRearCamera = selectedCamera.label.toLowerCase().includes('back') ||
|
|
324
|
+
selectedCamera.label.toLowerCase().includes('rear') ||
|
|
325
|
+
selectedCamera.label.toLowerCase().includes('environment');
|
|
326
|
+
this.preferredCameraFacing = isRearCamera ? 'environment' : 'user';
|
|
327
|
+
// Save preference
|
|
328
|
+
this.saveCameraPreference();
|
|
329
|
+
// Setup new camera with error handling
|
|
330
|
+
await this.setupCameraWithRetry();
|
|
331
|
+
this.debugLog('🔄 Switched to camera:', selectedCamera.label);
|
|
332
|
+
}
|
|
333
|
+
catch (error) {
|
|
334
|
+
this.debugLog('❌ Error switching camera:', error);
|
|
335
|
+
this.handleCameraPermissionError(error);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
async setupCameraWithRetry(maxRetries = 3) {
|
|
339
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
340
|
+
try {
|
|
341
|
+
await this.setupCamera();
|
|
342
|
+
return; // Success
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
this.debugLog(`❌ Camera setup attempt ${attempt} failed:`, error);
|
|
346
|
+
if (attempt === maxRetries) {
|
|
347
|
+
// Last attempt failed, handle the error
|
|
348
|
+
this.handleCameraPermissionError(error);
|
|
349
|
+
throw error;
|
|
350
|
+
}
|
|
351
|
+
// Wait before retrying
|
|
352
|
+
await new Promise(resolve => setTimeout(resolve, 500 * attempt));
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
toggleCameraSelector() {
|
|
357
|
+
this.showCameraSelector = !this.showCameraSelector;
|
|
358
|
+
this.debugLog('📹 Camera selector toggled:', {
|
|
359
|
+
showCameraSelector: this.showCameraSelector,
|
|
360
|
+
isMultipleCamerasAvailable: this.isMultipleCamerasAvailable,
|
|
361
|
+
availableCameras: this.availableCameras.length,
|
|
362
|
+
isVideoActive: this.isVideoActive
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
async flipCamera() {
|
|
366
|
+
if (!this.isMultipleCamerasAvailable)
|
|
367
|
+
return;
|
|
368
|
+
const currentIndex = this.availableCameras.findIndex(camera => camera.deviceId === this.selectedCameraId);
|
|
369
|
+
const nextIndex = (currentIndex + 1) % this.availableCameras.length;
|
|
370
|
+
const nextCamera = this.availableCameras[nextIndex];
|
|
371
|
+
await this.switchCamera(nextCamera.deviceId);
|
|
372
|
+
}
|
|
101
373
|
async componentDidLoad() {
|
|
102
374
|
this.validateMaskSize();
|
|
103
375
|
this.validateCropMargin();
|
|
376
|
+
this.validatePreferredCamera();
|
|
377
|
+
await this.detectDeviceTypeAndCameras();
|
|
104
378
|
if (!window.ort) {
|
|
105
379
|
const script = document.createElement('script');
|
|
106
380
|
script.src = 'https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js';
|
|
@@ -277,8 +551,10 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
277
551
|
// Configure ONNX Runtime with device-specific optimizations
|
|
278
552
|
const sessionOptions = this.getSessionOptions();
|
|
279
553
|
this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
|
|
280
|
-
// Preload MobileNet model and classes
|
|
281
|
-
|
|
554
|
+
// Preload MobileNet model and classes only if classification is enabled
|
|
555
|
+
if (this.useDocumentClassification) {
|
|
556
|
+
await this.loadMobileNetModel();
|
|
557
|
+
}
|
|
282
558
|
this.isModelPreloaded = true;
|
|
283
559
|
this.isLoading = false;
|
|
284
560
|
this.statusMessage = "Modelos precargados. Listo para comenzar detección";
|
|
@@ -300,6 +576,35 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
300
576
|
this.completeProcess(true);
|
|
301
577
|
}
|
|
302
578
|
}
|
|
579
|
+
async getCameraInfo() {
|
|
580
|
+
return {
|
|
581
|
+
availableCameras: this.availableCameras.map(camera => ({
|
|
582
|
+
id: camera.deviceId,
|
|
583
|
+
label: camera.label || 'Unknown Camera',
|
|
584
|
+
selected: camera.deviceId === this.selectedCameraId
|
|
585
|
+
})),
|
|
586
|
+
selectedCameraId: this.selectedCameraId,
|
|
587
|
+
deviceType: this.deviceType,
|
|
588
|
+
isMultipleCamerasAvailable: this.isMultipleCamerasAvailable,
|
|
589
|
+
preferredFacing: this.preferredCameraFacing,
|
|
590
|
+
userPreferredCamera: this.preferredCamera
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
async setPreferredCamera(camera) {
|
|
594
|
+
this.preferredCamera = camera;
|
|
595
|
+
this.debugLog('🎯 Camera preference changed to:', camera);
|
|
596
|
+
// Re-detect and apply new camera preference
|
|
597
|
+
await this.enumerateAndDetectCameras();
|
|
598
|
+
// If video is active, switch to the new preferred camera
|
|
599
|
+
if (this.isVideoActive && this.selectedCameraId) {
|
|
600
|
+
await this.switchCamera(this.selectedCameraId);
|
|
601
|
+
}
|
|
602
|
+
return {
|
|
603
|
+
success: true,
|
|
604
|
+
selectedCamera: this.selectedCameraId,
|
|
605
|
+
availableCameras: this.availableCameras.length
|
|
606
|
+
};
|
|
607
|
+
}
|
|
303
608
|
async loadMobileNetModel() {
|
|
304
609
|
try {
|
|
305
610
|
this.debugLog('🤖 Loading MobileNet model...');
|
|
@@ -416,18 +721,37 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
416
721
|
}
|
|
417
722
|
async getMaxResolution() {
|
|
418
723
|
try {
|
|
419
|
-
//
|
|
724
|
+
// Build constraints with selected camera if available
|
|
725
|
+
const videoConstraints = {};
|
|
726
|
+
if (this.selectedCameraId) {
|
|
727
|
+
videoConstraints.deviceId = { exact: this.selectedCameraId };
|
|
728
|
+
}
|
|
729
|
+
else if (this.preferredCameraFacing) {
|
|
730
|
+
videoConstraints.facingMode = this.preferredCameraFacing;
|
|
731
|
+
}
|
|
732
|
+
else {
|
|
733
|
+
videoConstraints.facingMode = "environment";
|
|
734
|
+
}
|
|
735
|
+
// Get temporary stream to access capabilities
|
|
420
736
|
const tempStream = await navigator.mediaDevices.getUserMedia({
|
|
421
|
-
video:
|
|
737
|
+
video: videoConstraints
|
|
422
738
|
});
|
|
423
739
|
const videoTrack = tempStream.getVideoTracks()[0];
|
|
424
740
|
const capabilities = videoTrack.getCapabilities();
|
|
425
741
|
// Detener el stream temporal
|
|
426
742
|
tempStream.getTracks().forEach(track => track.stop());
|
|
427
|
-
//
|
|
428
|
-
const constraints = {
|
|
429
|
-
|
|
430
|
-
|
|
743
|
+
// Build constraints with resolution optimized for tablets
|
|
744
|
+
const constraints = {};
|
|
745
|
+
// Set camera selection constraints
|
|
746
|
+
if (this.selectedCameraId) {
|
|
747
|
+
constraints.deviceId = { exact: this.selectedCameraId };
|
|
748
|
+
}
|
|
749
|
+
else if (this.preferredCameraFacing) {
|
|
750
|
+
constraints.facingMode = this.preferredCameraFacing;
|
|
751
|
+
}
|
|
752
|
+
else {
|
|
753
|
+
constraints.facingMode = "environment";
|
|
754
|
+
}
|
|
431
755
|
if (capabilities.width && capabilities.height) {
|
|
432
756
|
// Limitar resolución máxima para tablets para evitar problemas de rendimiento
|
|
433
757
|
const maxWidth = Math.min(capabilities.width.max, 1920);
|
|
@@ -454,13 +778,23 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
454
778
|
}
|
|
455
779
|
catch (err) {
|
|
456
780
|
this.debugLog('⚠️ Could not get capabilities, using fallback');
|
|
457
|
-
//
|
|
781
|
+
// Optimized fallback for tablets
|
|
458
782
|
const isTablet = /iPad|Android/i.test(navigator.userAgent) && window.innerWidth >= 768;
|
|
459
|
-
|
|
460
|
-
facingMode: "environment",
|
|
783
|
+
const fallbackConstraints = {
|
|
461
784
|
width: { ideal: isTablet ? 1280 : 1920 },
|
|
462
785
|
height: { ideal: isTablet ? 720 : 1080 }
|
|
463
786
|
};
|
|
787
|
+
// Add camera selection to fallback
|
|
788
|
+
if (this.selectedCameraId) {
|
|
789
|
+
fallbackConstraints.deviceId = { exact: this.selectedCameraId };
|
|
790
|
+
}
|
|
791
|
+
else if (this.preferredCameraFacing) {
|
|
792
|
+
fallbackConstraints.facingMode = this.preferredCameraFacing;
|
|
793
|
+
}
|
|
794
|
+
else {
|
|
795
|
+
fallbackConstraints.facingMode = "environment";
|
|
796
|
+
}
|
|
797
|
+
return fallbackConstraints;
|
|
464
798
|
}
|
|
465
799
|
}
|
|
466
800
|
async setupCamera() {
|
|
@@ -495,8 +829,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
495
829
|
}
|
|
496
830
|
catch (err) {
|
|
497
831
|
this.debugLog("❌ No se pudo acceder a la cámara:", err);
|
|
498
|
-
this.
|
|
499
|
-
this.statusColor = "#ff6b6b";
|
|
832
|
+
this.handleCameraPermissionError(err);
|
|
500
833
|
}
|
|
501
834
|
}
|
|
502
835
|
preprocess(video) {
|
|
@@ -547,8 +880,8 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
547
880
|
this.debugLog('🤖 Loading detection model:', modelPath);
|
|
548
881
|
const sessionOptions = this.getSessionOptions();
|
|
549
882
|
this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
|
|
550
|
-
// Load MobileNet model if not already loaded
|
|
551
|
-
if (!this.mobileNetSession) {
|
|
883
|
+
// Load MobileNet model if classification is enabled and not already loaded
|
|
884
|
+
if (this.useDocumentClassification && !this.mobileNetSession) {
|
|
552
885
|
await this.loadMobileNetModel();
|
|
553
886
|
}
|
|
554
887
|
this.isModelPreloaded = true;
|
|
@@ -894,13 +1227,27 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
894
1227
|
// Captura del frente usando canvas reutilizado
|
|
895
1228
|
this.capturedFullFrame = this.captureCanvas.toDataURL('image/png');
|
|
896
1229
|
this.capturedCroppedId = croppedCanvas.toDataURL('image/png');
|
|
897
|
-
//
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
1230
|
+
// Check if document classification is enabled
|
|
1231
|
+
if (this.useDocumentClassification) {
|
|
1232
|
+
// Load MobileNet model if not loaded yet (lazy loading)
|
|
1233
|
+
if (!this.mobileNetSession) {
|
|
1234
|
+
try {
|
|
1235
|
+
await this.loadMobileNetModel();
|
|
1236
|
+
}
|
|
1237
|
+
catch (error) {
|
|
1238
|
+
this.debugLog('⚠️ Failed to load classification model, continuing without classification:', error);
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
// Classify the cropped document if model is available
|
|
1242
|
+
if (this.mobileNetSession) {
|
|
1243
|
+
const classification = await this.classifyDocument(croppedCanvas);
|
|
1244
|
+
if (classification && classification.class === 'passport') {
|
|
1245
|
+
// If it's a passport, skip back capture since passports don't have a back side
|
|
1246
|
+
this.debugLog('📄 Passport detected - skipping back capture');
|
|
1247
|
+
this.completeProcess(true);
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
}
|
|
904
1251
|
}
|
|
905
1252
|
// For other IDs, continue with normal flow (back capture)
|
|
906
1253
|
this.captureStep = 'back';
|
|
@@ -1032,7 +1379,20 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
1032
1379
|
this.cleanup();
|
|
1033
1380
|
}
|
|
1034
1381
|
render() {
|
|
1035
|
-
return (h("div", { key: '
|
|
1382
|
+
return (h("div", { key: 'b90673f523dbf112786eb7184f56415055765c0c', class: "detector-container" }, h("div", { key: '925c5c886e9af53b460281244958e722de670a70', class: "video-container" }, h("video", { key: '4a0074e33a81b4694c6c99e3ece256c1ac8fe1d5', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: this.isVideoActive ? 'block' : 'none' } }), h("canvas", { key: 'a7b7f3b35c0535c11f6a4a155502dbe016f590b7', ref: el => this.canvasRef = el, class: this.shouldMirrorVideo ? 'mirror' : '' }), this.isMaskReady && (h("div", { key: '695b6a2f97e29b0b9c5b9d43682a951caff376a1', class: "overlay-mask" }, h("div", { key: '768875c39d5917c6a04306037d03d9e1aed114bd', class: "card-outline" }, h("div", { key: 'a56536deb7b8c99145d1bef6fee84e5801798644', class: "side side-top" }), h("div", { key: 'df413058c7e787f9c8a95a429a4f7186de07f5f6', class: "side side-right" }), h("div", { key: '37e074e3d4c914457f97720f9ab1f1ac2c70c4f1', class: "side side-bottom" }), h("div", { key: '772d3d40925c75ba5d39e2e7dd6405f7cc88d292', class: "side side-left" }), h("div", { key: 'd4e624782b3f4b4b8dbb8286b3acf003e433928c', class: "corner corner-tl" }), h("div", { key: '63f0ccfbbe3c1d413ca6912f36cab4afa6334bb2', class: "corner corner-tr" }), h("div", { key: '20012a50fe3d98ddfa669f5283a871c757522797', class: "corner corner-bl" }), h("div", { key: '9d82646bd08a6ca2b8c5782629fc68fd93cf1287', class: "corner corner-br" }), !this.showFlipAnimation && !this.showSuccessAnimation && (h("div", { key: '79fcbdb52e434a45aa6f2748d6d84500beb2e844', class: "guide-text" }, this.statusMessage))), this.captureStep === 'back' && !this.showFlipAnimation && !this.showSuccessAnimation && (h("button", { key: '16e587d645e2489a3410fe80bfc014738f08f02f', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, "Saltar reverso")), this.isVideoActive && (h("div", { key: 'd46d6881a9e1b63bdd849f5a8c6e96a2caefdefb', class: "camera-controls" }, this.isMultipleCamerasAvailable && (h("button", { key: 'afb4b44d691471f8af6e894e061aecb6c82259da', class: "flip-camera-button", onClick: () => this.flipCamera(), type: "button", title: "Cambiar c\u00E1mara" }, "Girar c\u00E1mara")), h("button", { key: '4e0680c2da9e6cc70b5880e8f5db9830c080acf9', class: "camera-selector-button", onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara" }, "C\u00E1maras"), this.debug && (h("div", { key: 'fc59922452a216273f742d3158559f6b2a1da43e', style: {
|
|
1383
|
+
position: 'absolute',
|
|
1384
|
+
top: '50px',
|
|
1385
|
+
right: '0',
|
|
1386
|
+
background: 'rgba(0,0,0,0.8)',
|
|
1387
|
+
color: 'white',
|
|
1388
|
+
padding: '8px',
|
|
1389
|
+
fontSize: '10px',
|
|
1390
|
+
borderRadius: '4px',
|
|
1391
|
+
whiteSpace: 'nowrap'
|
|
1392
|
+
} }, "C\u00E1maras: ", this.availableCameras.length, h("br", { key: '8f112283d1e0518a395dc6d94e1caa46fee0a86b' }), "M\u00FAltiples: ", this.isMultipleCamerasAvailable ? 'Sí' : 'No', h("br", { key: 'aacfd3ee868ee5d0819ce5ef693e3ef384867332' }), "Selector: ", this.showCameraSelector ? 'Visible' : 'Oculto', h("br", { key: '9927df7f56583c7388cee25e13526efc7e032eb1' }), "Video: ", this.isVideoActive ? 'Activo' : 'Inactivo')))), this.showCameraSelector && this.availableCameras.length > 0 && (h("div", { key: 'c2914bf7f3175b8f0ddab977abbdefe3022d7d29', class: "camera-selector-dropdown" }, h("div", { key: '0b5397e77ff33944f3620d78b1ab41275dffd7ac', class: "camera-selector-header" }, h("span", { key: '78f0fb8e34a0cf2d16138522a98cbdb9eefd671f' }, "Seleccionar C\u00E1mara"), h("button", { key: '0d4ea7b191d61d1d9b9c35462ce336148be73fcb', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: 'c16c7a106493ef7633a4cd35b06a4f45327a2e23', class: "camera-list" }, this.availableCameras.map((camera) => (h("button", { key: camera.deviceId, class: `camera-option ${this.selectedCameraId === camera.deviceId ? 'selected' : ''}`, onClick: () => {
|
|
1393
|
+
this.switchCamera(camera.deviceId);
|
|
1394
|
+
this.toggleCameraSelector();
|
|
1395
|
+
}, type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${this.availableCameras.indexOf(camera) + 1}`), this.selectedCameraId === camera.deviceId && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '11d6f980c3995a8414da5f7e6921f963ca72aed4', class: "device-info" }, h("small", { key: '78f5ff030f9e6e5021234a246599eb459b05d9f7' }, "Dispositivo: ", this.deviceType)))))), this.isCapturing && (h("div", { key: 'ef7d32491d8bdb94b2d6456420c2ddbc80f03d81', class: "capture-animation" })), this.showFlipAnimation && (h("div", { key: 'cfb5868ee75a9d1d1604c52f6fce1241090e4ac2', class: "flip-animation" }, h("div", { key: '1b41035e63f88434aba6699d4e68e06bea2c1529', class: "id-card-icon" }), h("div", { key: '4e83af9d0d39ce37b7448c4a0783b60b42b858e2', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), this.showSuccessAnimation && (h("div", { key: 'c7911e8be74b0fc7d7d18d7dcb52374645ca5f12', class: "success-animation" }, h("div", { key: '18e5ea5cfa3eb35fe3b99c12e6fab8e27e09e85e', class: "check-icon" }), h("div", { key: '490d8fcd6540c3b4fdc95f7fb5e6f6697722c9ac', class: "success-text" }, "\u00A1Proceso completado!"))), this.isLoading && (h("div", { key: 'f7fbfec6be2d8e0dc4e522b85b7d67897575cf0e', class: "loading-overlay" }, h("div", { key: '8282b92f19da6a9c7d22a64a0929b2b4d67c46be', class: "loading-spinner" }), h("div", { key: '7880b689297eb9d80a9b0023ba7933148fd8710a', class: "loading-text" }, this.statusMessage))), h("div", { key: '887c951fb03097171d9bd466fe24e36d11a49954', class: "watermark" }, h("img", { key: '314c9c172a4c6795c825741ea6f02b0e1186e93d', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
|
|
1036
1396
|
}
|
|
1037
1397
|
static get style() { return myComponentCss; }
|
|
1038
1398
|
}, [1, "jaak-stamps", {
|
|
@@ -1040,6 +1400,8 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
1040
1400
|
"alignmentTolerance": [2, "alignment-tolerance"],
|
|
1041
1401
|
"maskSize": [2, "mask-size"],
|
|
1042
1402
|
"cropMargin": [2, "crop-margin"],
|
|
1403
|
+
"useDocumentClassification": [4, "use-document-classification"],
|
|
1404
|
+
"preferredCamera": [1, "preferred-camera"],
|
|
1043
1405
|
"isVideoActive": [32],
|
|
1044
1406
|
"statusMessage": [32],
|
|
1045
1407
|
"statusColor": [32],
|
|
@@ -1058,6 +1420,10 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
1058
1420
|
"isLoading": [32],
|
|
1059
1421
|
"isModelPreloaded": [32],
|
|
1060
1422
|
"isMaskReady": [32],
|
|
1423
|
+
"availableCameras": [32],
|
|
1424
|
+
"selectedCameraId": [32],
|
|
1425
|
+
"showCameraSelector": [32],
|
|
1426
|
+
"isMultipleCamerasAvailable": [32],
|
|
1061
1427
|
"getCapturedImages": [64],
|
|
1062
1428
|
"isProcessCompleted": [64],
|
|
1063
1429
|
"startCapture": [64],
|
|
@@ -1065,7 +1431,9 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
|
|
|
1065
1431
|
"resetCapture": [64],
|
|
1066
1432
|
"getStatus": [64],
|
|
1067
1433
|
"preloadModel": [64],
|
|
1068
|
-
"skipBackCapture": [64]
|
|
1434
|
+
"skipBackCapture": [64],
|
|
1435
|
+
"getCameraInfo": [64],
|
|
1436
|
+
"setPreferredCamera": [64]
|
|
1069
1437
|
}]);
|
|
1070
1438
|
function defineCustomElement$1() {
|
|
1071
1439
|
if (typeof customElements === "undefined") {
|