@jaak.ai/stamps 2.1.0-dev.8 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/cjs/app-globals-V2Kpy_OQ.js +8 -0
  2. package/dist/cjs/app-globals-V2Kpy_OQ.js.map +1 -0
  3. package/dist/cjs/{index-BfhtOB0D.js → index-Ga0t6BMe.js} +176 -119
  4. package/dist/cjs/index-Ga0t6BMe.js.map +1 -0
  5. package/dist/cjs/jaak-stamps-webcomponent.cjs.js +5 -4
  6. package/dist/cjs/jaak-stamps-webcomponent.cjs.js.map +1 -1
  7. package/dist/cjs/jaak-stamps.cjs.entry.js +144 -409
  8. package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
  9. package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
  10. package/dist/cjs/loader.cjs.js +4 -3
  11. package/dist/cjs/loader.cjs.js.map +1 -1
  12. package/dist/collection/collection-manifest.json +1 -1
  13. package/dist/collection/components/my-component/my-component.css +1 -1
  14. package/dist/collection/components/my-component/my-component.js +53 -295
  15. package/dist/collection/components/my-component/my-component.js.map +1 -1
  16. package/dist/collection/services/CameraService.js +84 -2
  17. package/dist/collection/services/CameraService.js.map +1 -1
  18. package/dist/collection/services/DetectionService.js +7 -146
  19. package/dist/collection/services/DetectionService.js.map +1 -1
  20. package/dist/collection/services/interfaces/IDetectionService.js.map +1 -1
  21. package/dist/components/index.js +165 -113
  22. package/dist/components/index.js.map +1 -1
  23. package/dist/components/jaak-stamps.js +145 -412
  24. package/dist/components/jaak-stamps.js.map +1 -1
  25. package/dist/esm/app-globals-DQuL1Twl.js +6 -0
  26. package/dist/esm/app-globals-DQuL1Twl.js.map +1 -0
  27. package/dist/esm/{index-BP1Q4KOg.js → index-Drbzcuq-.js} +177 -119
  28. package/dist/esm/index-Drbzcuq-.js.map +1 -0
  29. package/dist/esm/jaak-stamps-webcomponent.js +5 -4
  30. package/dist/esm/jaak-stamps-webcomponent.js.map +1 -1
  31. package/dist/esm/jaak-stamps.entry.js +144 -409
  32. package/dist/esm/jaak-stamps.entry.js.map +1 -1
  33. package/dist/esm/loader.js +4 -3
  34. package/dist/esm/loader.js.map +1 -1
  35. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
  36. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js.map +1 -1
  37. package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
  38. package/dist/jaak-stamps-webcomponent/loader.esm.js.map +1 -1
  39. package/dist/jaak-stamps-webcomponent/p-DQuL1Twl.js +2 -0
  40. package/dist/jaak-stamps-webcomponent/p-DQuL1Twl.js.map +1 -0
  41. package/dist/jaak-stamps-webcomponent/p-Drbzcuq-.js +3 -0
  42. package/dist/jaak-stamps-webcomponent/p-Drbzcuq-.js.map +1 -0
  43. package/dist/jaak-stamps-webcomponent/p-c06e5d7b.entry.js +2 -0
  44. package/dist/jaak-stamps-webcomponent/p-c06e5d7b.entry.js.map +1 -0
  45. package/dist/types/components/my-component/my-component.d.ts +1 -27
  46. package/dist/types/components.d.ts +1 -3
  47. package/dist/types/services/CameraService.d.ts +1 -0
  48. package/dist/types/services/DetectionService.d.ts +1 -9
  49. package/dist/types/services/interfaces/IDetectionService.d.ts +0 -6
  50. package/dist/types/stencil-public-runtime.d.ts +12 -5
  51. package/package.json +3 -1
  52. package/dist/cjs/index-BfhtOB0D.js.map +0 -1
  53. package/dist/esm/index-BP1Q4KOg.js.map +0 -1
  54. package/dist/jaak-stamps-webcomponent/p-8e25497e.entry.js +0 -2
  55. package/dist/jaak-stamps-webcomponent/p-8e25497e.entry.js.map +0 -1
  56. package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js +0 -3
  57. package/dist/jaak-stamps-webcomponent/p-BP1Q4KOg.js.map +0 -1
@@ -1,2 +0,0 @@
1
- import{r as t,c as e,a as i,h as a}from"./p-BP1Q4KOg.js";class s{events=new Map;on(t,e){if(!this.events.has(t)){this.events.set(t,[])}this.events.get(t).push(e)}off(t,e){const i=this.events.get(t);if(i){const t=i.indexOf(e);if(t>-1){i.splice(t,1)}}}emit(t,e){const i=this.events.get(t);if(i){i.forEach((t=>{try{t(e)}catch(t){}}))}}once(t,e){const i=a=>{e(a);this.off(t,i)};this.on(t,i)}clear(){this.events.clear()}}class o{eventBus;captureState={step:"front",isCapturing:false,isDetectionPaused:false,isVideoActive:false,isLoading:false,showFlipAnimation:false,showSuccessAnimation:false,bestScore:0,hasScreenshotTaken:false};capturedImages={front:{fullFrame:null,cropped:null},back:{fullFrame:null,cropped:null},metadata:{totalImages:0,processCompleted:false,backCaptureSkipped:false}};constructor(t){this.eventBus=t}getCaptureState(){return{...this.captureState}}updateCaptureState(t){const e={...this.captureState};this.captureState={...this.captureState,...t};this.eventBus.emit("state-changed",{previous:e,current:this.captureState,changes:t})}getCapturedImages(){return JSON.parse(JSON.stringify(this.capturedImages))}setCapturedImages(t){this.capturedImages={...this.capturedImages,...t,metadata:{...this.capturedImages.metadata,...t.metadata}};let e=0;if(this.capturedImages.front.fullFrame&&this.capturedImages.front.cropped){e+=2}if(this.capturedImages.back.fullFrame&&this.capturedImages.back.cropped){e+=2}this.capturedImages.metadata.totalImages=e}reset(){this.captureState={step:"front",isCapturing:false,isDetectionPaused:false,isVideoActive:false,isLoading:false,showFlipAnimation:false,showSuccessAnimation:false,bestScore:0,hasScreenshotTaken:false};this.capturedImages={front:{fullFrame:null,cropped:null},back:{fullFrame:null,cropped:null},metadata:{totalImages:0,processCompleted:false,backCaptureSkipped:false}};this.eventBus.emit("state-changed",{previous:null,current:this.captureState,changes:{reset:true}})}isProcessCompleted(){return this.captureState.step==="completed"}canProceedToBack(){return this.captureState.step==="front"&&this.capturedImages.front.fullFrame!==null&&this.capturedImages.front.cropped!==null}}class r{eventBus;availableCameras=[];selectedCameraId=null;deviceType="desktop";preferredCameraFacing=null;preferredCamera="auto";static cameraCapabilitiesCache=new Map;static deviceEnumerationCache=null;static CACHE_DURATION=3e4;currentStreamPromise;lastStreamConstraints;constructor(t,e="auto"){this.eventBus=t;this.preferredCamera=e}async detectDeviceType(){const t=navigator.userAgent;const e=/Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(t);const i=/iPad|Android/i.test(t)&&window.innerWidth>=768;if(i){this.deviceType="tablet"}else if(e){this.deviceType="mobile"}else{this.deviceType="desktop"}return this.deviceType}async enumerateDevices(){try{const t=Date.now();if(r.deviceEnumerationCache&&t-r.deviceEnumerationCache.timestamp<r.CACHE_DURATION){this.availableCameras=r.deviceEnumerationCache.devices;await this.setInitialCameraPreference();this.eventBus.emit("camera-changed",this.selectedCameraId);return this.availableCameras}const e=await this.checkCameraPermission();if(e==="denied"){return[]}if(e==="prompt"){const t=await navigator.mediaDevices.getUserMedia({video:true});t.getTracks().forEach((t=>t.stop()))}const i=await navigator.mediaDevices.enumerateDevices();this.availableCameras=i.filter((t=>t.kind==="videoinput"));r.deviceEnumerationCache={devices:this.availableCameras,timestamp:t};await this.setInitialCameraPreference();this.eventBus.emit("camera-changed",this.selectedCameraId);return this.availableCameras}catch(t){this.handleCameraPermissionError(t);return[]}}getAvailableCameras(){return[...this.availableCameras]}isMultipleCamerasAvailable(){return this.availableCameras.length>1}getSelectedCameraId(){return this.selectedCameraId}async setSelectedCamera(t){const e=this.availableCameras.find((e=>e.deviceId===t));if(!e){throw new Error(`Camera with ID ${t} not found`)}this.selectedCameraId=t;this.updatePreferredFacing(e);this.eventBus.emit("camera-changed",t)}getPreferredFacing(){return this.preferredCameraFacing}async setupCamera(t){try{const e=t||await this.getMaxResolution();if(this.currentStreamPromise&&this.constraintsEqual(e,this.lastStreamConstraints)){return await this.currentStreamPromise}this.currentStreamPromise=navigator.mediaDevices.getUserMedia({video:e,audio:false});this.lastStreamConstraints=e;const i=await this.currentStreamPromise;return i}catch(t){const e={width:{ideal:1280},height:{ideal:720}};if(this.deviceType!=="desktop"&&this.preferredCameraFacing){e.facingMode=this.preferredCameraFacing}this.currentStreamPromise=navigator.mediaDevices.getUserMedia({video:e,audio:false});this.lastStreamConstraints=e;return await this.currentStreamPromise}}async switchCamera(t){const e=this.availableCameras.find((e=>e.deviceId===t));if(!e){await this.enumerateDevices();return}await this.setSelectedCamera(t)}isRearCamera(t){const e=t.getVideoTracks()[0];if(!e)return false;const i=e.getSettings();return i.facingMode==="environment"}async getCameraInfo(){const t=await Promise.all(this.availableCameras.map((async t=>{const e=await this.checkCameraAutofocus(t.deviceId);return{id:t.deviceId,label:t.label||"Unknown Camera",selected:t.deviceId===this.selectedCameraId,hasAutofocus:e}})));return{availableCameras:t,selectedCameraId:this.selectedCameraId,deviceType:this.deviceType,isMultipleCamerasAvailable:this.isMultipleCamerasAvailable(),preferredFacing:this.preferredCameraFacing}}async checkCameraPermission(){try{if(!navigator.permissions){return"prompt"}const t=await navigator.permissions.query({name:"camera"});return t.state}catch(t){return"prompt"}}handleCameraPermissionError(t){this.availableCameras=[];this.eventBus.emit("error",new Error(`Camera permission error: ${t.message}`))}async setInitialCameraPreference(){if(this.availableCameras.length===0)return;if(this.preferredCamera==="front"){await this.selectFrontCamera()}else if(this.preferredCamera==="back"){await this.selectBackCamera()}else{await this.selectAutoCamera()}}async checkCameraAutofocus(t){try{if(r.cameraCapabilitiesCache.has(t)){const e=r.cameraCapabilitiesCache.get(t);return typeof e==="boolean"?e:false}const e=await navigator.mediaDevices.getUserMedia({video:{deviceId:{exact:t}}});const i=e.getVideoTracks()[0];const a=i.getCapabilities();e.getTracks().forEach((t=>t.stop()));const s=a.focusMode&&Array.isArray(a.focusMode)&&a.focusMode.length>0;const o=s&&(a.focusMode.includes("continuous")||a.focusMode.includes("auto"));r.cameraCapabilitiesCache.set(t,o);return o}catch(e){r.cameraCapabilitiesCache.set(t,false);return false}}async selectFrontCamera(){this.preferredCameraFacing="user";const t=this.availableCameras.filter((t=>{const e=t.label.toLowerCase();return e.includes("front")||e.includes("user")||e.includes("selfie")||e.includes("frontal")||!e.includes("back")&&!e.includes("rear")&&!e.includes("environment")}));let e=null;if(t.length>0){for(const i of t){const t=await this.checkCameraAutofocus(i.deviceId);if(t){e=i;break}}if(!e){e=t[0]}}this.selectedCameraId=e?e.deviceId:this.availableCameras[0].deviceId}async selectBackCamera(){this.preferredCameraFacing="environment";const t=this.availableCameras.filter((t=>{const e=t.label.toLowerCase();return e.includes("back")||e.includes("rear")||e.includes("environment")||e.includes("trasera")||e.includes("posterior")}));let e=null;if(t.length>0){for(const i of t){const t=await this.checkCameraAutofocus(i.deviceId);if(t){e=i;break}}if(!e){e=t[0]}}else if(this.availableCameras.length>1){const t=this.availableCameras[this.availableCameras.length-1];const i=await this.checkCameraAutofocus(t.deviceId);e=i?t:this.availableCameras[this.availableCameras.length-1]}this.selectedCameraId=e?e.deviceId:this.availableCameras[0].deviceId}async selectAutoCamera(){if(this.deviceType==="mobile"||this.deviceType==="tablet"){await this.selectBackCamera()}else{await this.selectFrontCamera()}}updatePreferredFacing(t){const e=t.label.toLowerCase().includes("back")||t.label.toLowerCase().includes("rear")||t.label.toLowerCase().includes("environment");this.preferredCameraFacing=e?"environment":"user"}async getMaxResolution(){try{if(!this.deviceType||this.deviceType==="desktop"){await this.detectDeviceType()}const t={};if(this.selectedCameraId){t.deviceId={exact:this.selectedCameraId}}else if(this.preferredCameraFacing){const e=this.deviceType==="desktop"?{ideal:this.preferredCameraFacing}:{exact:this.preferredCameraFacing};t.facingMode=e}else{if(this.preferredCamera==="front"){t.facingMode="user"}else if(this.preferredCamera==="back"){t.facingMode="environment"}else{t.facingMode=this.deviceType==="mobile"||this.deviceType==="tablet"?"environment":"user"}}let e;if(this.selectedCameraId&&r.cameraCapabilitiesCache.has(this.selectedCameraId+"_caps")){e=JSON.parse(r.cameraCapabilitiesCache.get(this.selectedCameraId+"_caps"))}else{const i=await navigator.mediaDevices.getUserMedia({video:t});const a=i.getVideoTracks()[0];e=a.getCapabilities();i.getTracks().forEach((t=>t.stop()));if(this.selectedCameraId){r.cameraCapabilitiesCache.set(this.selectedCameraId+"_caps",JSON.stringify(e))}}const i={...t};if(e.width&&e.height){const t=Math.min(e.width.max,1920);const a=Math.min(e.height.max,1080);const s=/iPad|Android/i.test(navigator.userAgent)&&window.innerWidth>=768;if(s){i.width={ideal:Math.min(t,1280)};i.height={ideal:Math.min(a,720)}}else{i.width={ideal:t};i.height={ideal:a}}}const a=e;if(a.focusMode&&Array.isArray(a.focusMode)){if(a.focusMode.includes("continuous")){i.focusMode="continuous"}else if(a.focusMode.includes("auto")){i.focusMode="auto"}}return i}catch(t){if(!this.deviceType||this.deviceType==="desktop"){await this.detectDeviceType()}const e=/iPad|Android/i.test(navigator.userAgent)&&window.innerWidth>=768;const i={width:{ideal:e?1280:1920},height:{ideal:e?720:1080}};if(this.selectedCameraId){i.deviceId={exact:this.selectedCameraId}}else if(this.preferredCameraFacing){const t=this.deviceType==="desktop"?{ideal:this.preferredCameraFacing}:{exact:this.preferredCameraFacing};i.facingMode=t}else{if(this.preferredCamera==="front"){i.facingMode="user"}else if(this.preferredCamera==="back"){i.facingMode="environment"}else{i.facingMode=this.deviceType==="mobile"||this.deviceType==="tablet"?"environment":"user"}}return i}}constraintsEqual(t,e){if(!t||!e)return false;return JSON.stringify(t)===JSON.stringify(e)}static clearCaches(){r.cameraCapabilitiesCache.clear();r.deviceEnumerationCache=null}invalidateDeviceCache(){r.deviceEnumerationCache=null}}class n{getDeviceInfo(){const t=navigator;const e=t.deviceMemory||t.hardwareConcurrency||4;const i=t.connection||t.mozConnection||t.webkitConnection;const a=i&&(i.effectiveType==="slow-2g"||i.effectiveType==="2g");return{estimatedRAM:e,isLowMemory:true,isSlowConnection:a}}getSessionOptions(t){return{executionProviders:["wasm"],graphOptimizationLevel:"basic",logSeverityLevel:4,logVerbosityLevel:0,enableCpuMemArena:false,enableMemPattern:false,executionMode:"sequential",interOpNumThreads:1,intraOpNumThreads:1}}shouldUseSequentialLoading(){return true}}class c{getDeviceInfo(){const t=navigator;const e=t.deviceMemory||t.hardwareConcurrency||4;const i=t.connection||t.mozConnection||t.webkitConnection;const a=i&&(i.effectiveType==="slow-2g"||i.effectiveType==="2g");return{estimatedRAM:e,isLowMemory:false,isSlowConnection:a}}getSessionOptions(t){return{executionProviders:["webgl","wasm"],graphOptimizationLevel:"all",logSeverityLevel:t?2:4,logVerbosityLevel:0,enableCpuMemArena:true,enableMemPattern:true,executionMode:"parallel",interOpNumThreads:2,intraOpNumThreads:2}}shouldUseSequentialLoading(){return false}}class l{static createStrategy(){const t=navigator;const e=t.deviceMemory||t.hardwareConcurrency||4;const i=e<=4;if(i){return new n}else{return new c}}}class d{debug;useDocumentClassification;useDocumentDetector;session;mobileNetSession;mobileNetClassMap;modelLoaded=false;deviceStrategy;MODEL_PATH="https://storage.googleapis.com/jaak-static/web/component/stamps/ddmyp-v2.onnx";MOBILENET_MODEL_PATH="https://storage.googleapis.com/jaak-static/web/component/stamps/squeezenet_new_fp32.onnx";MOBILENET_CLASSES_PATH="https://storage.googleapis.com/jaak-static/web/component/stamps/cdmmp-v1.json";INPUT_SIZE=320;CONFIDENCE_THRESHOLD=.6;preprocessCanvas;preprocessCtx;captureCanvas;static canvasPool=new Map;static MAX_POOL_SIZE=5;modelLoadController;classificationLoadController;modelBlobUrls=new Set;constructor(t=false,e=false,i=true){this.debug=t;this.useDocumentClassification=e;this.useDocumentDetector=i;this.deviceStrategy=l.createStrategy();this.initializeCanvasPool()}async loadModel(){if(this.modelLoaded||this.session){return}if(!this.useDocumentDetector){this.modelLoaded=true;return}try{this.modelLoadController=new AbortController;const t=this.deviceStrategy.getSessionOptions(this.debug);try{const e=await fetch(this.MODEL_PATH,{signal:this.modelLoadController.signal});if(!e.ok){throw new Error(`Failed to fetch model: ${e.status}`)}const i=await e.arrayBuffer();this.session=await window.ort.InferenceSession.create(i,t)}catch(t){if(t.name==="AbortError"){console.log("Model loading was cancelled");return}const e=t.message.includes("failed to allocate a buffer")||t.message.includes("Out of memory")||t.message.includes("RangeError: Out of memory")||t.message.includes("no available backend found");if(e){const t={executionProviders:["wasm"],graphOptimizationLevel:"disabled",logSeverityLevel:4,enableCpuMemArena:false,enableMemPattern:false,executionMode:"sequential",interOpNumThreads:1,intraOpNumThreads:1,enableProfiling:false,sessionLogSeverityLevel:4,sessionLogVerbosityLevel:0};try{const e=await fetch(this.MODEL_PATH,{signal:this.modelLoadController.signal});if(!e.ok){throw new Error(`Failed to fetch model with fallback: ${e.status}`)}const i=await e.arrayBuffer();this.session=await window.ort.InferenceSession.create(i,t)}catch(t){throw new Error(`no available backend found. ERR: [wasm] RangeError: Out of memory`)}}else{throw t}}this.modelLoaded=true}catch(t){throw t}}async loadClassificationModel(){if(!this.useDocumentClassification){return}try{this.classificationLoadController=new AbortController;try{const t=await fetch(this.MOBILENET_CLASSES_PATH,{signal:this.classificationLoadController.signal});if(t.ok){this.mobileNetClassMap=await t.json()}}catch(t){this.mobileNetClassMap={0:"document",1:"id_card",2:"passport",3:"license",4:"other"}}const t=this.deviceStrategy.getSessionOptions(this.debug);try{const e=await fetch(this.MOBILENET_MODEL_PATH,{signal:this.classificationLoadController.signal});if(!e.ok){throw new Error(`Failed to fetch classification model: ${e.status}`)}const i=await e.arrayBuffer();this.mobileNetSession=await window.ort.InferenceSession.create(i,t)}catch(t){if(t.name==="AbortError"){console.log("Classification model loading was cancelled");return}const e=t.message.includes("failed to allocate a buffer")||t.message.includes("Out of memory")||t.message.includes("RangeError: Out of memory")||t.message.includes("no available backend found");if(e){const t={executionProviders:["wasm"],graphOptimizationLevel:"disabled",logSeverityLevel:4,enableCpuMemArena:false,enableMemPattern:false,executionMode:"sequential",interOpNumThreads:1,intraOpNumThreads:1,enableProfiling:false,sessionLogSeverityLevel:4,sessionLogVerbosityLevel:0};try{const e=await fetch(this.MOBILENET_MODEL_PATH,{signal:this.classificationLoadController.signal});if(!e.ok){throw new Error(`Failed to fetch classification model with fallback: ${e.status}`)}const i=await e.arrayBuffer();this.mobileNetSession=await window.ort.InferenceSession.create(i,t)}catch(t){throw new Error(`no available backend found. ERR: [wasm] RangeError: Out of memory`)}}else{throw t}}}catch(t){throw t}}isModelLoaded(){if(!this.useDocumentDetector){return this.modelLoaded}return this.modelLoaded&&!!this.session}preprocess(t){if(!this.preprocessCanvas||!this.preprocessCtx){this.initializeCanvasPool()}this.preprocessCtx.clearRect(0,0,this.INPUT_SIZE,this.INPUT_SIZE);this.preprocessCtx.drawImage(t,0,0,this.INPUT_SIZE,this.INPUT_SIZE);const e=this.preprocessCtx.getImageData(0,0,this.INPUT_SIZE,this.INPUT_SIZE);const[i,a,s]=[[],[],[]];const{data:o}=e;for(let t=0;t<o.length;t+=4){i.push(o[t]/255);a.push(o[t+1]/255);s.push(o[t+2]/255)}const r=new Float32Array(i.concat(a,s));const n=new Uint16Array(r.length);for(let t=0;t<r.length;t++){n[t]=this.float32ToFloat16(r[t])}return new window.ort.Tensor("float16",n,[1,3,this.INPUT_SIZE,this.INPUT_SIZE])}async runInference(t){if(!this.useDocumentDetector){return[]}if(!this.session){throw new Error("Detection model not loaded")}const e={[this.session.inputNames[0]]:t};const i=await this.session.run(e);const a=i[this.session.outputNames[0]].data;const s=[];for(let t=0;t<a.length;t+=6){const[e,i,o,r,n,c]=a.slice(t,t+6);if(n>this.CONFIDENCE_THRESHOLD){s.push({x:e,y:i,w:o-e,h:r-i,score:n,classId:c})}}return s}async classifyDocument(t){if(!this.mobileNetSession||!this.mobileNetClassMap){return null}try{const e=this.preprocessMobileNet(t);const i={[this.mobileNetSession.inputNames[0]]:e};const a=await this.mobileNetSession.run(i);const s=a[Object.keys(a)[0]].data;const o=s.reduce(((t,e,i,a)=>e>a[t]?i:t),0);const r=s[o];const n=this.mobileNetClassMap[o.toString()]||"unknown";return{class:n,confidence:r,classIndex:o}}catch(t){return null}}checkSideAlignment(t,e){const{INPUT_SIZE:i,ID1_ASPECT_RATIO:a,shouldMirrorVideo:s,alignmentTolerance:o,maskSize:r,videoRef:n}=e;if(!n){return{top:false,right:false,bottom:false,left:false}}const c=n.videoWidth;const l=n.videoHeight;if(c===0||l===0){return{top:false,right:false,bottom:false,left:false}}const d=c/l;const h=1;let f,p;if(d>h){f=i;p=i/d}else{p=i;f=i*d}const u=p*a;let m,b;const g=r/100;if(u<=f){b=p*g;m=b*a}else{m=f*g;b=m/a}const x=m*(i/f);const w=b*(i/p);const y=i/2;const v=i/2;const k=y-x/2;const C=y+x/2;const M=v-w/2;const S=v+w/2;let z=t.x;let P=t.x+t.w;const E=t.y;const A=t.y+t.h;if(s){const t=z;const e=P;z=i-e;P=i-t}const T=o;const I=Math.abs(E-M)<=T;const D=Math.abs(P-C)<=T;const F=Math.abs(A-S)<=T;const L=Math.abs(z-k)<=T;return{top:I&&L,right:I&&D,bottom:F&&L,left:F&&D}}isCardInFrame(t){const e=t.x+t.w/2;const i=t.y+t.h/2;const a=this.INPUT_SIZE/2;const s=this.INPUT_SIZE/2;const o=40;const r=30;const n=Math.abs(e-a)<o&&Math.abs(i-s)<r;const c=t.w>150&&t.w<300&&t.h>90&&t.h<200;return n&&c}areAllSidesAligned(t){return t.top&&t.right&&t.bottom&&t.left}cleanup(){this.abortPendingRequests();this.cleanupCanvasPool();if(this.session){this.session.release?.();this.session=undefined}if(this.mobileNetSession){this.mobileNetSession.release?.();this.mobileNetSession=undefined}this.mobileNetClassMap=undefined;this.modelLoaded=false;this.revokeModelBlobUrls()}initializeCanvasPool(){this.preprocessCanvas=document.createElement("canvas");this.preprocessCanvas.width=this.INPUT_SIZE;this.preprocessCanvas.height=this.INPUT_SIZE;this.preprocessCtx=this.preprocessCanvas.getContext("2d",{alpha:false,willReadFrequently:true});this.captureCanvas=document.createElement("canvas")}cleanupCanvasPool(){if(this.preprocessCanvas){this.preprocessCtx=undefined;this.preprocessCanvas=undefined}if(this.captureCanvas){this.captureCanvas=undefined}}float32ToFloat16(t){const e=new ArrayBuffer(4);const i=new DataView(e);i.setFloat32(0,t,true);const a=i.getUint32(0,true);const s=a>>31&1;const o=a>>23&255;const r=a&8388607;let n=o-127+15;if(o===0){n=0}else if(o===255){n=31}else if(n>=31){n=31;return s<<15|n<<10}else if(n<=0){return s<<15}return s<<15|n<<10|r>>13}preprocessMobileNet(t){const e=this.getCanvas(224,224);const i=e.getContext("2d");i.clearRect(0,0,224,224);i.drawImage(t,0,0,224,224);const a=i.getImageData(0,0,224,224);const s=a.data;const o=224*224;const r=new Float32Array(3*o);for(let t=0;t<o;t++){r[t]=s[t*4+0]/255;r[o+t]=s[t*4+1]/255;r[2*o+t]=s[t*4+2]/255}this.returnCanvas(e);return new window.ort.Tensor("float32",r,[1,3,224,224])}getCanvas(t,e){const i=`${t}x${e}`;if(!d.canvasPool.has(i)){d.canvasPool.set(i,[])}const a=d.canvasPool.get(i);let s=a.pop();if(!s){s=document.createElement("canvas");s.width=t;s.height=e}else{const i=s.getContext("2d");i.clearRect(0,0,t,e)}return s}returnCanvas(t){const e=`${t.width}x${t.height}`;if(!d.canvasPool.has(e)){d.canvasPool.set(e,[])}const i=d.canvasPool.get(e);if(i.length<d.MAX_POOL_SIZE){const e=t.getContext("2d");e.clearRect(0,0,t.width,t.height);i.push(t)}}async clearModelCache(){try{const t=await caches.keys();const e=t.filter((t=>t.includes("onnx")||t.includes("jaak-static")||t.includes("squeezenet")||t.includes("ddmyp")));await Promise.all(e.map((t=>caches.delete(t))));if(this.debug){console.log(`🧹 Cleared ${e.length} model caches`)}}catch(t){console.warn("Error clearing model cache:",t)}}abortPendingRequests(){if(this.modelLoadController){this.modelLoadController.abort();this.modelLoadController=undefined}if(this.classificationLoadController){this.classificationLoadController.abort();this.classificationLoadController=undefined}}revokeModelBlobUrls(){this.modelBlobUrls.forEach((t=>URL.revokeObjectURL(t)));this.modelBlobUrls.clear()}async releaseMobileNetResources(){if(this.mobileNetSession){this.mobileNetSession.release?.();this.mobileNetSession=undefined}this.mobileNetClassMap=undefined;if(this.classificationLoadController){this.classificationLoadController.abort();this.classificationLoadController=undefined}if(this.debug){console.log("🧹 Released MobileNet classification resources")}}optimizeCanvasPool(t){d.canvasPool.forEach(((e,i)=>{while(e.length>t){const t=e.pop();if(t){const e=t.getContext("2d");if(e){e.clearRect(0,0,t.width,t.height)}}}if(e.length===0){d.canvasPool.delete(i)}}));if(this.debug){console.log(`🧹 Optimized canvas pool to max size: ${t}`)}}static clearAllCanvasPools(){d.canvasPool.forEach((t=>{t.forEach((t=>{const e=t.getContext("2d");if(e){e.clearRect(0,0,t.width,t.height)}}));t.length=0}));d.canvasPool.clear()}getPoolStats(){const t={};d.canvasPool.forEach(((e,i)=>{t[i]=e.length}));return t}}class h{services=new Map;constructor(t){this.initializeServices(t)}initializeServices(t){const e=new s;const i=new o(e);const a=new r(e,t.preferredCamera);const n=new d(t.debug,t.useDocumentClassification,t.useDocumentDetector);this.services.set("eventBus",e);this.services.set("stateManager",i);this.services.set("cameraService",a);this.services.set("detectionService",n)}get(t){const e=this.services.get(t);if(!e){throw new Error(`Service ${t} not found`)}return e}getEventBus(){return this.get("eventBus")}getStateManager(){return this.get("stateManager")}getCameraService(){return this.get("cameraService")}getDetectionService(){return this.get("detectionService")}updateConfig(t){}cleanup(){this.getDetectionService().cleanup();this.getEventBus().clear();this.services.clear()}}const f=":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,.capture-button.primary-button:disabled{cursor:not-allowed !important;transform:none !important;opacity:0.7 !important;transition:none !important}@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}.capture-button:disabled,.capture-button.primary-button:disabled,.skip-button:disabled{opacity:0.7 !important;cursor:not-allowed !important}}.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)}.skip-button:disabled{cursor:not-allowed !important;transform:none !important;opacity:0.7 !important;transition:none !important}.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(0, 0, 0, 0.2);border-top:2px solid #333333;border-radius:50%;animation:spin 1s linear infinite;display:inline-block;margin-right:8px;vertical-align:middle}@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{cursor:not-allowed !important;transform:none !important;opacity:0.7 !important;transition:none !important}@media (max-width: 480px){.manual-capture-section{bottom:16px;max-width:280px}.manual-capture-button{padding:10px 20px;font-size:13px}.manual-capture-button:disabled{opacity:0.7 !important;cursor:not-allowed !important}}";const p=class{constructor(i){t(this,i);this.captureCompleted=e(this,"captureCompleted");this.isReady=e(this,"isReady")}get el(){return i(this)}debug=false;alignmentTolerance=15;maskSize=90;cropMargin=20;useDocumentClassification=false;useDocumentDetector=true;preferredCamera="auto";captureDelay=1500;enableBackDocumentTimer=false;backDocumentTimerDuration=20;captureCompleted;isReady;detectionBoxes=[];sideAlignment={top:false,right:false,bottom:false,left:false};isMaskReady=false;shouldMirrorVideo=true;showCameraSelector=false;isSwitchingCamera=false;hasDocumentDetected=false;cameraInfoWithAutofocus={availableCameras:[],selectedCameraId:null,deviceType:"desktop",isMultipleCamerasAvailable:false,preferredFacing:null};currentStatus={message:"Preparando capturador...",description:"Configurando herramientas de captura",type:"initializing",isInitialized:false};performanceData={fps:0,inferenceTime:0,memoryUsage:0,onnxLoadTime:0,frameProcessingTime:0,totalDetections:0,successfulDetections:0,detectionRate:0};backDocumentTimerRemaining=0;showManualCaptureButton=false;performanceDegradedMode=false;showPerformanceMessage=false;captureStateVersion=0;processingButton=null;serviceContainer;eventBus;stateManager;cameraService;detectionService;videoRef;detectionContainer;videoStream;animationId;lastDetectedBox;startTime;hasScreenshotTaken=false;alignmentStartTime;alignmentTimer;backDocumentTimer;performanceMetrics={fps:0,inferenceTime:0,memoryUsage:0,onnxLoadTime:0,frameProcessingTime:0,totalDetections:0,successfulDetections:0,detectionRate:0,lastUpdateTime:0};performanceUpdateInterval;frameSkipCounter=0;BASE_FRAME_SKIP=2;MAX_FRAME_SKIP=8;consecutiveFailures=0;MAX_FAILURES=30;lastInferenceTime=0;MIN_INFERENCE_INTERVAL=50;performanceHistory=[];PERFORMANCE_HISTORY_SIZE=10;PERFORMANCE_THRESHOLD_MS=2e3;SLOW_FRAMES_TO_TRIGGER=2;slowFrameCount=0;processedFramesCount=0;hasAutoSwitchedToManual=false;canvasPool=[];MAX_CANVAS_POOL_SIZE=3;async componentDidLoad(){try{this.updateStatus("Preparando capturador...","Configurando herramientas de captura","initializing");await this.initializeServices();this.updateStatus("Preparando funciones...","Configurando herramientas de trabajo","initializing");await this.setupEventListeners();this.updateStatus("Configurando cámara...","Detectando dispositivos disponibles","initializing");await this.initializeComponent();if(this.debug){this.initializePerformanceMonitor()}}catch(t){this.updateStatus("Error de inicialización",t.message,"error")}}async initializeServices(){const t={debug:this.debug,alignmentTolerance:this.alignmentTolerance,maskSize:this.maskSize,cropMargin:this.cropMargin,useDocumentClassification:this.useDocumentClassification,useDocumentDetector:this.useDocumentDetector,preferredCamera:this.preferredCamera,captureDelay:this.captureDelay};this.serviceContainer=new h(t);this.eventBus=this.serviceContainer.getEventBus();this.stateManager=this.serviceContainer.getStateManager();this.cameraService=this.serviceContainer.getCameraService();this.detectionService=this.serviceContainer.getDetectionService()}async setupEventListeners(){this.eventBus.on("state-changed",(()=>{this.handleStateChange()}))}async initializeComponent(){this.validateProps();if(this.debug){this.stateManager.updateCaptureState({isLoading:true});await new Promise((t=>setTimeout(t,500)))}this.updateStatus("Detectando cámaras...","Buscando dispositivos de captura","initializing");await this.cameraService.detectDeviceType();await this.cameraService.enumerateDevices();await this.updateCameraInfoWithAutofocus();this.updateStatus("Preparando reconocimiento...","Configurando detección de documentos","initializing");await this.loadOnnxRuntime();this.initializeResizeObserver()}validateProps(){if(this.maskSize<50||this.maskSize>100){this.maskSize=90}if(this.cropMargin<0||this.cropMargin>100){this.cropMargin=0}const t=["auto","front","back"];if(!t.includes(this.preferredCamera)){this.preferredCamera="auto"}if(this.captureDelay<0||this.captureDelay>1e4){this.captureDelay=1500}}async loadOnnxRuntime(){if(!window.ort){this.updateStatus("Preparando herramientas...","Configurando funciones de captura","initializing");const t=document.createElement("script");t.src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js";document.head.appendChild(t);await new Promise((e=>{t.onload=()=>{setTimeout((async()=>{await this.finalizeInitialization();e(undefined)}),300)}}))}else{setTimeout((async()=>{await this.finalizeInitialization()}),300)}}async finalizeInitialization(){this.stateManager.updateCaptureState({isLoading:false});const t=await this.checkCameraPermissions();if(t){this.currentStatus={message:"Listo para capturar",description:"",type:"ready",isInitialized:true}}else{this.currentStatus={message:"Permisos de cámara requeridos",description:"Por favor, otorgue permisos de cámara para continuar",type:"error",isInitialized:true}}this.emitReadyEvent()}updateStatus(t,e,i="loading"){this.currentStatus={message:t,description:e,type:i,isInitialized:this.currentStatus.isInitialized}}emitReadyEvent(){const t=!!window.ort&&this.detectionService.isModelLoaded();this.isReady.emit(t)}async checkCameraPermissions(){try{if(!navigator.permissions){try{const t=await navigator.mediaDevices.getUserMedia({video:true});t.getTracks().forEach((t=>t.stop()));return true}catch{return false}}const t=await navigator.permissions.query({name:"camera"});return t.state==="granted"}catch(t){return false}}handleStateChange(){}initializeResizeObserver(){if("ResizeObserver"in window&&this.detectionContainer){const t=new ResizeObserver((()=>{this.handleResize()}));t.observe(this.detectionContainer.parentElement)}}handleResize(){if(this.detectionContainer){const t=this.detectionContainer.parentElement;const e=t.getBoundingClientRect();this.updateMaskDimensions(e)}}triggerRerender(){this.captureStateVersion=this.captureStateVersion+1}getGuideText(t){if(t==="completed"){return"Proceso completado"}if(this.showPerformanceMessage&&t==="front"){return"Modo manual activado por rendimiento. Use el botón para capturar."}if(t==="front"){if(this.showManualCaptureButton){return"Posicione el frente de su documento en el marco y presione el botón para capturar"}return"Alinee su identificación con el marco"}else if(t==="back"){if(this.useDocumentDetector){return"Si tu documento no tiene lado trasero, da clic en el botón para continuar con el proceso"}else{return"Posicione el reverso de su documento en el marco y capture, o salte este paso"}}return"Alinee su identificación con el marco"}updateMaskDimensions(t){if(!this.videoRef)return;const e=this.videoRef.videoWidth;const i=this.videoRef.videoHeight;if(e===0||i===0)return;const a=e/i;const s=t.width/t.height;let o,r;let n=0,c=0;if(a>s){o=t.width;r=t.width/a;c=(t.height-r)/2}else{r=t.height;o=t.height*a;n=(t.width-o)/2}const l=85.6/53.98;const d=r*l;let h,f;const p=this.maskSize/100;if(d<=o){f=r*p;h=f*l}else{h=o*p;f=h/l}const u=h/t.width*100;const m=f/t.height*100;const b=n+o/2;const g=c+r/2;const x=b/t.width*100;const w=g/t.height*100;this.el.style.setProperty("--mask-width",`${u}%`);this.el.style.setProperty("--mask-height",`${m}%`);this.el.style.setProperty("--mask-center-x",`${x}%`);this.el.style.setProperty("--mask-center-y",`${w}%`);this.isMaskReady=true}isComponentReady(){if(!this.currentStatus.isInitialized){return{ready:false,message:"El componente aún se está inicializando",status:"initializing"}}if(this.currentStatus.type==="loading"||this.currentStatus.type==="initializing"){return{ready:false,message:"El componente está cargando recursos",status:"loading"}}if(!this.serviceContainer||!this.stateManager||!this.cameraService||!this.detectionService){return{ready:false,message:"Los servicios del componente no están disponibles",status:"error"}}return{ready:true}}async getCapturedImages(){const t=this.isComponentReady();if(!t.ready){throw new Error(t.message)}const e=this.stateManager.getCaptureState();if(e.step!=="completed"){throw new Error("El proceso de captura no ha sido completado")}return this.stateManager.getCapturedImages()}async isProcessCompleted(){const t=this.isComponentReady();if(!t.ready){return false}return this.stateManager.isProcessCompleted()}async startCapture(){const t=this.isComponentReady();if(!t.ready){this.updateStatus(t.message,"Espere a que termine la inicialización",t.status);return{success:false,error:t.message}}try{await this.startDetection();return{success:true}}catch(t){this.updateStatus("Error al iniciar captura",t.message,"error");return{success:false,error:t.message}}}async stopCapture(){const t=this.isComponentReady();if(!t.ready){return{success:false,error:t.message}}try{this.exitSession();const t=await this.aggressiveResourceCleanup();return{success:true,resourcesFreed:t.freed,cleanupErrors:t.errors}}catch(t){return{success:false,error:t.message}}}async resetCapture(){const t=this.isComponentReady();if(!t.ready){return{success:false,error:t.message}}try{this.resetDetection();return{success:true}}catch(t){return{success:false,error:t.message}}}async skipBackCapture(){console.log("🟡 Botón clicked: Saltar reverso");this.processingButton="skip-back";await new Promise((t=>setTimeout(t,100)));const t=this.isComponentReady();if(!t.ready){this.processingButton=null;return{success:false,error:t.message}}try{const t=this.stateManager.getCaptureState();const e=this.stateManager.getCapturedImages();if(t.step==="back"&&e.front.fullFrame){this.completeProcess(true);return{success:true}}else{return{success:false,error:"No se puede saltar el reverso en el estado actual"}}}catch(t){return{success:false,error:t.message}}finally{this.processingButton=null}}async getStatus(){const t=this.isComponentReady();if(!t.ready){return{isVideoActive:false,captureStep:"front",hasImages:false,isProcessCompleted:false,isModelPreloaded:false,componentStatus:t.status,componentMessage:t.message}}try{const t=this.stateManager.getCaptureState();const e=this.stateManager.getCapturedImages();return{isVideoActive:t.isVideoActive,captureStep:t.step,hasImages:!!(e.front.fullFrame||e.back.fullFrame),isProcessCompleted:this.stateManager.isProcessCompleted(),isModelPreloaded:this.detectionService.isModelLoaded(),componentStatus:"ready"}}catch(t){return{isVideoActive:false,captureStep:"front",hasImages:false,isProcessCompleted:false,isModelPreloaded:false,componentStatus:"error",componentMessage:t.message}}}async preloadModel(){const t=this.isComponentReady();if(!t.ready){this.updateStatus(t.message,"Espere a que termine la inicialización",t.status);return{success:false,error:t.message}}if(this.detectionService.isModelLoaded()){this.updateStatus("Reconocimiento listo","","ready");return{success:true,message:"Model already loaded"}}try{const t=performance.now();this.updateStatus("Preparando reconocimiento...","Configurando detección de documentos","loading");if(this.stateManager){this.stateManager.updateCaptureState({isLoading:true})}try{await this.detectionService.loadModel()}catch(t){this.switchToManualModeWithError("Error al cargar modelo de detección");throw t}this.updateStatus("Optimizando detección...","Configurando reconocimiento de documentos","loading");try{await this.detectionService.loadClassificationModel()}catch(t){this.switchToManualModeWithError("Error al cargar modelo de clasificación");throw t}const e=performance.now();const i=e-t;if(this.debug){this.recordOnnxPerformance(i,0)}this.updateStatus("Finalizando configuración...","Preparando herramientas para captura","loading");await new Promise((t=>setTimeout(t,300)));this.updateStatus("Reconocimiento preparado","","ready");if(this.stateManager){this.stateManager.updateCaptureState({isLoading:false})}this.emitReadyEvent();return{success:true,message:"Models preloaded successfully"}}catch(t){this.updateStatus("Error de configuración","No se pudieron preparar las herramientas necesarias","error");if(this.stateManager){this.stateManager.updateCaptureState({isLoading:false})}return{success:false,error:t.message}}}async getCameraInfo(){const t=this.isComponentReady();if(!t.ready){return{availableCameras:[],selectedCameraId:null,deviceType:"desktop",isMultipleCamerasAvailable:false,preferredFacing:null,error:t.message}}try{return await this.cameraService.getCameraInfo()}catch(t){return{availableCameras:[],selectedCameraId:null,deviceType:"desktop",isMultipleCamerasAvailable:false,preferredFacing:null,error:t.message}}}async setPreferredCamera(t){const e=this.isComponentReady();if(!e.ready){return{success:false,error:e.message,selectedCamera:null,availableCameras:0}}try{this.preferredCamera=t;this.serviceContainer.updateConfig({preferredCamera:t});await this.cameraService.enumerateDevices();await this.updateCameraInfoWithAutofocus();const e=this.stateManager.getCaptureState();if(e.isVideoActive){const t=this.cameraService.getSelectedCameraId();if(t){await this.cameraService.switchCamera(t)}}return{success:true,selectedCamera:this.cameraService.getSelectedCameraId(),availableCameras:this.cameraService.getAvailableCameras().length}}catch(t){return{success:false,error:t.message,selectedCamera:null,availableCameras:0}}}async setCaptureDelay(t){if(t<0||t>1e4){return{success:false,error:"Capture delay must be between 0 and 10000 milliseconds",captureDelay:this.captureDelay}}this.captureDelay=t;if(this.serviceContainer){this.serviceContainer.updateConfig({captureDelay:t})}return{success:true,captureDelay:this.captureDelay}}async getCaptureDelay(){return this.captureDelay}async getResourceReport(){return this.getResourceReportInternal()}async forceResourceCleanup(){const t=this.isComponentReady();if(!t.ready){return{success:false,error:t.message}}try{const t=await this.aggressiveResourceCleanup();return{success:true,resourcesFreed:t.freed,errors:t.errors,timestamp:(new Date).toISOString()}}catch(t){return{success:false,error:t.message}}}checkDeviceCapabilities(){const t=navigator.deviceMemory;const e=navigator.hardwareConcurrency||1;const i=e<=2;const a=/Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);const s=/Safari/.test(navigator.userAgent)&&!/Chrome/.test(navigator.userAgent);if(t&&t<4){return{canUseML:false,reason:`Memoria del dispositivo (${t}GB) insuficiente para detección automática. Modo manual activado para mejor rendimiento.`,memoryMB:t*1024}}if(a&&i){return{canUseML:false,reason:"Dispositivo móvil optimizado detectado. Modo manual activado para mejor rendimiento y duración de batería.",memoryMB:null}}if(s){return{canUseML:false,reason:"Safari detectado. Modo manual activado por compatibilidad optimizada con este navegador.",memoryMB:null}}return{canUseML:true,reason:"Dispositivo compatible con detección automática.",memoryMB:t?t*1024:null}}async startDetection(){try{const t=this.checkDeviceCapabilities();if(!t.canUseML&&this.useDocumentDetector){this.switchToManualModeWithWarning(t.reason);return}if(!this.detectionService.isModelLoaded()){const t=performance.now();this.updateStatus("Preparando reconocimiento...","Configurando detección de documentos","loading");this.stateManager.updateCaptureState({isLoading:true});try{await this.detectionService.loadModel()}catch(t){if(t.message.includes("Out of memory")||t.message.includes("no available backend")){const t=navigator.deviceMemory?`(${navigator.deviceMemory}GB disponible)`:"";this.switchToManualModeWithWarning(`Memoria insuficiente para detección automática ${t}. Modo manual activado - funciona igual de bien!`);return}else{this.switchToManualModeWithError("Error al cargar modelo de detección");throw t}}this.updateStatus("Optimizando detección...","Configurando reconocimiento de documentos","loading");try{await this.detectionService.loadClassificationModel()}catch(t){if(t.message.includes("Out of memory")||t.message.includes("no available backend")){const t=navigator.deviceMemory?`(${navigator.deviceMemory}GB disponible)`:"";this.switchToManualModeWithWarning(`Memoria insuficiente para clasificación automática ${t}. Modo manual activado para optimizar rendimiento.`);return}else{this.switchToManualModeWithError("Error al cargar modelo de clasificación");throw t}}const e=performance.now();const i=e-t;if(this.debug){this.recordOnnxPerformance(i,0)}}this.updateStatus("Configurando cámara...","Buscando dispositivos disponibles","loading");try{await this.cameraService.enumerateDevices()}catch(t){throw new Error(`Error al enumerar dispositivos: ${t.message}`)}try{await this.updateCameraInfoWithAutofocus()}catch(t){throw new Error(`Error al actualizar información de cámara: ${t.message}`)}this.updateStatus("Ajustando cámara...","Configurando calidad de imagen","loading");let e;try{e=await this.cameraService.setupCamera()}catch(t){throw new Error(`Error al configurar cámara: ${t.message}`)}if(this.useDocumentDetector){this.updateStatus("Analizando estabilidad...","Evaluando rendimiento del sistema","loading")}else{this.updateStatus("Captura activa","Posicione su documento y use el botón para capturar","active")}try{await this.initializeVideoStream(e)}catch(t){throw new Error(`Error al inicializar video: ${t.message}`)}if(this.detectionContainer){const t=this.detectionContainer.parentElement;const e=t.getBoundingClientRect();this.updateMaskDimensions(e)}this.startTime=Date.now();this.stateManager.updateCaptureState({isLoading:false});if(!this.useDocumentDetector){this.showManualCaptureButton=true}this.detectFrame()}catch(t){this.updateStatus("Error al iniciar","No se pudo preparar la captura","error");this.stateManager.updateCaptureState({isLoading:false})}}async initializeVideoStream(t){if(this.videoRef){this.videoRef.srcObject=t;this.videoStream=t;const e=this.cameraService.isRearCamera(t);this.shouldMirrorVideo=!e;return new Promise((t=>{this.videoRef.onloadedmetadata=async()=>{await this.videoRef.play();this.stateManager.updateCaptureState({isVideoActive:true});t()}}))}else{throw new Error("Video element not available")}}async detectFrame(){try{const t=performance.now();const e=this.stateManager.getCaptureState();if(!this.videoRef||!this.detectionContainer||!this.detectionService.isModelLoaded())return;if(!this.useDocumentDetector||this.performanceDegradedMode){this.showManualCaptureButton=true;if(e.step!=="completed"){this.animationId=requestAnimationFrame((()=>this.detectFrame()))}return}else if(!this.performanceDegradedMode){this.showManualCaptureButton=false}if(e.isDetectionPaused){if(e.step!=="completed"){this.animationId=requestAnimationFrame((()=>this.detectFrame()))}return}this.frameSkipCounter++;const i=this.getAdaptiveFrameSkip();if(this.frameSkipCounter<=i){if(e.step!=="completed"){this.animationId=requestAnimationFrame((()=>this.detectFrame()))}return}this.frameSkipCounter=0;const a=Date.now();if(a-this.lastInferenceTime<this.MIN_INFERENCE_INTERVAL){if(e.step!=="completed"){this.animationId=requestAnimationFrame((()=>this.detectFrame()))}return}this.lastInferenceTime=a;const s=performance.now();let o;let r;let n;try{o=this.detectionService.preprocess(this.videoRef)}catch(t){this.switchToManualModeWithError("Error al procesar imagen");return}try{r=await this.detectionService.runInference(o);n=performance.now()-s}catch(t){this.switchToManualModeWithError("Error en detección automática");return}this.processedFramesCount++;if(this.debug){this.recordOnnxPerformance(0,n)}if(this.startTime&&Date.now()-this.startTime<5e3){r.forEach((t=>{const i=this.detectionService.isCardInFrame(t);const a=i?t.score*1.2:t.score;if(a>e.bestScore){this.stateManager.updateCaptureState({bestScore:a})}}))}const c=this.hasDocumentDetected;this.hasDocumentDetected=r.length>0;if(!c&&this.hasDocumentDetected&&e.step==="back"&&this.enableBackDocumentTimer){this.startBackDocumentTimer()}if(r.length===0){this.consecutiveFailures++}else{this.consecutiveFailures=0}if(this.debug){this.updateDetectionBoxes(r)}else{this.detectionBoxes=[]}this.updateMaskColor(r);const l=performance.now();const d=l-t;if(this.useDocumentDetector&&!this.hasAutoSwitchedToManual){if(d>=this.PERFORMANCE_THRESHOLD_MS){this.slowFrameCount++;if(this.slowFrameCount>=this.SLOW_FRAMES_TO_TRIGGER){this.switchToManualMode()}}else{if(this.slowFrameCount>0){this.slowFrameCount=0}}if(this.processedFramesCount===2){this.updateStatus("Captura activa","Buscando documento en el marco de captura","active")}}if(this.debug){this.recordFrameProcessing(d,r.length)}if(e.step!=="completed"){if(this.consecutiveFailures>this.MAX_FAILURES){setTimeout((()=>this.detectFrame()),200)}else{this.animationId=requestAnimationFrame((()=>this.detectFrame()))}}}catch(t){const e=this.stateManager.getCaptureState();if(e.step!=="completed"){setTimeout((()=>this.detectFrame()),100)}}}disconnectedCallback(){this.cleanup()}cleanup(){if(this.animationId){cancelAnimationFrame(this.animationId)}if(this.videoStream){this.videoStream.getTracks().forEach((t=>t.stop()))}if(this.alignmentTimer){clearTimeout(this.alignmentTimer);this.alignmentTimer=undefined}this.releaseOnnxResources();if(this.performanceUpdateInterval){clearInterval(this.performanceUpdateInterval);this.performanceUpdateInterval=undefined}this.canvasPool=[];this.cleanupDOMReferences();this.detectionBoxes=[];this.alignmentStartTime=undefined;this.hasDocumentDetected=false;this.serviceContainer?.cleanup()}cleanupDOMReferences(){if(this.videoRef){this.videoRef.srcObject=null;this.videoRef=undefined}if(this.detectionContainer){this.detectionContainer=undefined}const t=this.el.shadowRoot?.querySelectorAll("img");t?.forEach((t=>{if(t.src.startsWith("blob:")){URL.revokeObjectURL(t.src)}t.src=""}))}async clearBrowserCache(){try{if("serviceWorker"in navigator){const t=await navigator.serviceWorker.getRegistrations();await Promise.all(t.map((t=>t.unregister())))}const t=await caches.keys();const e=t.filter((t=>t.includes("jaak")||t.includes("stamps")));await Promise.all(e.map((t=>caches.delete(t))));if(this.debug&&window.gc){window.gc()}}catch(t){console.warn("Error clearing browser cache:",t)}}async clearLocalStorage(){try{const t=[];for(let e=0;e<localStorage.length;e++){const i=localStorage.key(e);if(i&&(i.includes("jaak")||i.includes("onnx")||i.includes("stamps"))){t.push(i)}}t.forEach((t=>localStorage.removeItem(t)));const e=[];for(let t=0;t<sessionStorage.length;t++){const i=sessionStorage.key(t);if(i&&(i.includes("jaak")||i.includes("onnx"))){e.push(i)}}e.forEach((t=>sessionStorage.removeItem(t)))}catch(t){console.warn("Error clearing local storage:",t)}}async aggressiveResourceCleanup(){const t=[];const e=[];try{this.releaseOnnxResources();t.push("ONNX models");if(this.detectionService){await this.detectionService.clearModelCache();t.push("Model cache")}await this.clearBrowserCache();t.push("Browser cache");await this.clearLocalStorage();t.push("Local storage");this.cleanupDOMReferences();t.push("DOM references");if(this.detectionService){this.detectionService.optimizeCanvasPool(0);t.push("Canvas pools")}this.canvasPool=[];t.push("Component canvas pool");if(this.debug&&window.gc){window.gc();t.push("Garbage collection")}}catch(t){e.push(t.message)}return{freed:t,errors:e}}async onFrontCaptureComplete(){try{if(this.detectionService&&!this.useDocumentClassification){await this.detectionService.releaseMobileNetResources()}if(this.detectionService){this.detectionService.optimizeCanvasPool(1)}while(this.canvasPool.length>1){const t=this.canvasPool.pop();if(t){const e=t.getContext("2d");if(e){e.clearRect(0,0,t.width,t.height)}}}if(this.debug){console.log("🧹 Progressive cleanup after front capture completed")}}catch(t){console.warn("Error in progressive cleanup:",t)}}getResourceReportInternal(){const t={timestamp:(new Date).toISOString(),component:{hasVideoStream:!!this.videoStream,hasAnimationFrame:!!this.animationId,canvasPoolSize:this.canvasPool.length,detectionBoxesCount:this.detectionBoxes.length,performanceMonitorActive:!!this.performanceUpdateInterval}};if(this.detectionService){t.detectionService={isModelLoaded:this.detectionService.isModelLoaded(),canvasPoolStats:this.detectionService.getPoolStats()}}if("memory"in performance){const e=performance.memory;t.memory={usedJSHeapSize:Math.round(e.usedJSHeapSize/1048576),totalJSHeapSize:Math.round(e.totalJSHeapSize/1048576),jsHeapSizeLimit:Math.round(e.jsHeapSizeLimit/1048576)}}return t}render(){const t=this.stateManager?.getCaptureState()||{isVideoActive:false,showFlipAnimation:false,showSuccessAnimation:false,step:"front",isCapturing:false};const e=this.cameraInfoWithAutofocus;return a("div",{key:"ca44b9eacbde9f688f2c41aa21ad35a2b882002b",class:"detector-container"},a("div",{key:"86c7b5d31ed69276b62fa43e01c92b0c0b9f298d",class:"video-container"},a("video",{key:"bb310544c17ae734d8b42ed2617748c2f69743ff",ref:t=>this.videoRef=t,autoplay:true,muted:true,playsinline:true,class:this.shouldMirrorVideo?"mirror":"",style:{display:t.isVideoActive?"block":"none"}}),a("div",{key:"078a79a0c6386ca6c040e629acbf4f52f12d8e29",ref:t=>this.detectionContainer=t,class:`detection-overlay ${this.shouldMirrorVideo?"mirror":""}`},this.debug&&this.detectionBoxes.map(((t,e)=>a("div",{key:e,class:"detection-box",style:{position:"absolute",left:`${t.x}px`,top:`${t.y}px`,width:`${t.w}px`,height:`${t.h}px`,border:"2px solid #32406C",pointerEvents:"none",boxSizing:"border-box"}})))),this.isMaskReady&&a("div",{key:"990015ff5b2ded89405dd2b891c027aad8788f3e",class:"overlay-mask"},a("div",{key:"dd9145140987addb1b6e4cc2119b8e9f89003726",class:"card-outline"},a("div",{key:"e8f4ec692a8b80c7a98075e4f708b79a272db67b",class:"side side-top"}),a("div",{key:"2577253b40425ecdcb3dd51b2f4a43c15c83ca79",class:"side side-right"}),a("div",{key:"30f4454020c00cf4fb92308af5ecf1843ec24005",class:"side side-bottom"}),a("div",{key:"3459f634987b8396106fff23fa1c99b295ee7d0a",class:"side side-left"})),!t.showFlipAnimation&&!t.showSuccessAnimation&&a("div",{key:"84f4d70947e211a9c6b296531d53420223d2ca34",class:`guide-text ${this.showPerformanceMessage?"performance-warning-text":""}`},this.getGuideText(t.step)),t.step==="back"&&!t.showFlipAnimation&&!t.showSuccessAnimation&&a("div",{key:"7c28e86e8de6c33bf7d7baab3083c5f6a0ab060f",class:"back-capture-section"},a("div",{key:"27bdcf9cfe9790c4bbad484423f6f4c353ccf0b3",class:"back-capture-buttons"},(!this.useDocumentDetector||this.performanceDegradedMode)&&a("button",{key:"ed0320b1df412bf53cbe4e4119f6d769926eb2c5",class:"capture-button primary-button",onClick:()=>this.takeManualScreenshot(),type:"button",disabled:this.processingButton!==null},this.processingButton==="capture-back"&&a("span",{key:"0bba706c8ebda59c33faca8e97b7536146462d21",class:"button-spinner"}),"Capturar Reverso"),a("button",{key:"b072c46b25d16a04c5e0a8f3975d8aa8d24576d5",class:"skip-button",onClick:()=>this.skipBackCapture(),type:"button",disabled:this.processingButton!==null},this.processingButton==="skip-back"&&a("span",{key:"efd0827d0f19c9072d49d1b3c0046ef6c95a842c",class:"button-spinner"}),this.enableBackDocumentTimer&&this.backDocumentTimerRemaining>0?`Saltar reverso (${this.backDocumentTimerRemaining}s)`:"Saltar reverso"))),t.isVideoActive&&a("div",{key:"bd0303e8ce85211e4c68fc3cd79545db7c74288b",class:"camera-controls"},a("button",{key:"e4327d260b988b67e0de3654c72f24455cd3bbbd",class:`camera-selector-button ${this.isSwitchingCamera?"loading":""}`,onClick:()=>this.toggleCameraSelector(),type:"button",title:"Seleccionar cámara",disabled:this.isSwitchingCamera},this.isSwitchingCamera?a("div",{class:"button-spinner"}):"Cámaras")),this.showCameraSelector&&e.availableCameras.length>0&&a("div",{key:"35da16baf4c62466c2a66650209a1daf842c0db2",class:"camera-selector-dropdown"},a("div",{key:"7035dd0e22f614cf239a015c6d59531b68fa74a9",class:"camera-selector-header"},a("span",{key:"ae026f31931f52ea0daf72391a9de4ff9e4b88f1"},"Seleccionar Cámara"),a("button",{key:"40f2ba0770bafea71fedbf849938010e743be776",class:"close-selector",onClick:()=>this.toggleCameraSelector(),type:"button"},"×")),a("div",{key:"6f26927094a724a35ebb07ef701caf14f296a837",class:"camera-list"},e.availableCameras.map((t=>a("button",{key:t.id,class:`camera-option ${e.selectedCameraId===t.id?"selected":""}`,onClick:()=>this.handleCameraSwitch(t.id),type:"button"},a("span",{class:"camera-label"},t.label||`Cámara ${e.availableCameras.indexOf(t)+1}`,t.hasAutofocus&&a("span",{class:"autofocus-icon",title:"Autofoco disponible"},"⦿")),e.selectedCameraId===t.id&&a("span",{class:"selected-indicator"},"✓"))))),a("div",{key:"082236981c369f8fd487f036439b16e6560514be",class:"device-info"},a("small",{key:"ccbbfa0bca96395f574bda71103338ae9226f709"},"Dispositivo: ",e.deviceType))),this.showManualCaptureButton&&t.step==="front"&&!t.showFlipAnimation&&!t.showSuccessAnimation&&a("div",{key:"6baa487409503777e90453b39fd30649941cbbe4",class:"manual-capture-section"},a("button",{key:"893f4715ca3315613f779603f178459955f686f0",class:"manual-capture-button",onClick:()=>this.takeManualScreenshot(),type:"button",disabled:this.processingButton!==null},this.processingButton==="capture-front"&&a("span",{key:"7c30b680fe84f4c8227beba45d8416f1edb8348f",class:"button-spinner"}),"Capturar Frente"))),t.isCapturing&&a("div",{key:"d8ef052cf67d7bda4b3534febf96efa2cdcc6bf7",class:"capture-animation"}),t.showFlipAnimation&&a("div",{key:"3dae7634e770dda2655b1042ec8fb997b3cb2220",class:"flip-animation"},a("div",{key:"a977fc5e889369121bacc06cf5213dfee39d858d",class:"id-card-icon"}),a("div",{key:"4f052cdc8c7b493cddce90e108e976325c9bab8e",class:"flip-text"},"¡Voltea tu identificación!")),t.showSuccessAnimation&&a("div",{key:"5117cd6e63e1e0763c1503f6f60f3c7ef60dd665",class:"success-animation"},a("div",{key:"d11128c45c7118915cc0dd9c25845bb55b4b3eb2",class:"check-icon"}),a("div",{key:"693e197bf8a4c91ac7ddedb457d15aa3aa46a5d5",class:"success-text"},"¡Proceso completado!")),a("div",{key:"89caaa9d78eb522e0fadfd1c0e844e05d29b8286",class:`component-status status-${this.currentStatus.type}`},(this.currentStatus.type==="loading"||this.currentStatus.type==="initializing")&&a("div",{key:"3f41d40b05b71e13e7e1d0c0e980b48308cba9d6",class:"status-spinner"}),a("div",{key:"8674480928f4f4a77099c0600ed84f0e27903379",class:"status-content"},a("div",{key:"e88f4044ab8115a6a5cbb78cc4030975eef9149a",class:"status-message"},this.currentStatus.message),this.currentStatus.description&&a("div",{key:"ad581e42c30c304b837711549148c11b801dee5e",class:"status-description"},this.currentStatus.description))),this.debug&&a("div",{key:"1b371c1b47f3ba699885db00fef52eb448f9e245",class:"performance-monitor"},a("div",{key:"8b9ac60449a15e9fb966c329b2e6c9285c0228c0",class:"performance-expanded"},a("div",{key:"760c11a3ed28e248a144d53a92fd8adee6822ff2",class:"metrics-row"},a("div",{key:"858ab8b106f1d12210e4e15c423ab3bab11bdb60",class:"metric-compact"},a("span",{key:"65fe2479c3822d99452e7e5faa93c25a80765024",class:"metric-label"},"FPS"),a("span",{key:"9faf7763d1284a6f3c1e15fb0f3c99f1d45bb4dc",class:`metric-value ${this.performanceData.fps<15?"warning":this.performanceData.fps<10?"danger":"good"}`},this.performanceData.fps)),a("div",{key:"c95ed8fa8101f42bfba5cc8ca7debbad028caf42",class:"metric-compact"},a("span",{key:"3555b3778cb71e959d132d6aa563f58f757915d8",class:"metric-label"},"MEM"),a("span",{key:"d72b0491147a6f80dcf33f5d72dd8dae5898f44a",class:`metric-value ${this.performanceData.memoryUsage>100?"warning":this.performanceData.memoryUsage>200?"danger":"good"}`},this.performanceData.memoryUsage,"MB"))),a("div",{key:"cd4dc81f28f9e59a36a0295dde7bfee89f50d3e2",class:"metrics-row"},a("div",{key:"c43d8624c5da256ce3e97f67b022bdd98fb04e07",class:"metric-compact"},a("span",{key:"adb402d83809a90580b81544f31b5331bdff59dd",class:"metric-label"},"INF"),a("span",{key:"e48c9814c08acbe321460a29e42cb49b0eab38ff",class:`metric-value ${this.performanceData.inferenceTime>100?"warning":this.performanceData.inferenceTime>200?"danger":"good"}`},this.performanceData.inferenceTime,"ms")),a("div",{key:"71517f9279e9a6aa0d5b02e2169db868ca3fb676",class:"metric-compact"},a("span",{key:"3ddbcc56b137aea702a40f900178e8e16efd146e",class:"metric-label"},"FRAME"),a("span",{key:"d3a70afb511d3f72b485b3a1cb922876faa62b11",class:`metric-value ${this.performanceData.frameProcessingTime>50?"warning":this.performanceData.frameProcessingTime>100?"danger":"good"}`},this.performanceData.frameProcessingTime,"ms"))),a("div",{key:"a3b62cdbe830b1024ab96f7fb726825df24fecdc",class:"metrics-row"},a("div",{key:"95471e5cdde748d1ce6bdee3540740dd3aa66865",class:"metric-compact"},a("span",{key:"c93e01c0bdc67621c3a666357d2477b7a5275d52",class:"metric-label"},"DET"),a("span",{key:"ef33c86a83101b0989b14c7f1ab0ce0b331b397f",class:"metric-value good"},this.performanceData.successfulDetections,"/",this.performanceData.totalDetections)),a("div",{key:"e14d56128bf96337e4c3859f8e4003e001e8e953",class:"metric-compact"},a("span",{key:"8aa828632f0a977a27ed377f103bb8d5e7e0ed1a",class:"metric-label"},"RATE"),a("span",{key:"59035c473b5a747a27f774e2554322a084b6d19f",class:`metric-value ${this.performanceData.detectionRate<30?"danger":this.performanceData.detectionRate<60?"warning":"good"}`},this.performanceData.detectionRate,"%"))))),a("div",{key:"4d0c2de00954416faac30ab622fb21f36c932aca",class:"watermark"},a("img",{key:"d8f775428ebb3ba86a943ca73b074db2180d0c29",src:"https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png",alt:"Powered by Jaak"}))))}updateDetectionBoxes(t){if(!this.videoRef||!this.detectionContainer)return;const e=this.videoRef.videoWidth;const i=this.videoRef.videoHeight;const a=this.detectionContainer.parentElement;const s=a.getBoundingClientRect();const o=s.width;const r=s.height;if(e===0||i===0)return;const n=e/i;const c=o/r;let l,d;let h=0,f=0;if(n>c){l=o;d=o/n;f=(r-d)/2}else{d=r;l=r*n;h=(o-l)/2}const p=320;const u=l/p;const m=d/p;this.detectionBoxes=t.map((t=>({x:t.x*u+h,y:t.y*m+f,w:t.w*u,h:t.h*m,score:t.score})))}updateMaskColor(t){const e=this.el.shadowRoot?.querySelector(".card-outline");const i=this.el.shadowRoot?.querySelectorAll(".corner");const a=this.el.shadowRoot?.querySelector(".side-top");const s=this.el.shadowRoot?.querySelector(".side-right");const o=this.el.shadowRoot?.querySelector(".side-bottom");const r=this.el.shadowRoot?.querySelector(".side-left");let n=null;let c={top:false,right:false,bottom:false,left:false};if(t.length>0){n=t.reduce(((t,e)=>e.score>t.score?e:t));const e={INPUT_SIZE:320,ID1_ASPECT_RATIO:85.6/53.98,shouldMirrorVideo:this.shouldMirrorVideo,alignmentTolerance:this.alignmentTolerance,maskSize:this.maskSize,videoRef:this.videoRef};c=this.detectionService.checkSideAlignment(n,e);this.sideAlignment=c}else{this.sideAlignment={top:false,right:false,bottom:false,left:false}}a?.classList.toggle("aligned",c.top);s?.classList.toggle("aligned",c.right);o?.classList.toggle("aligned",c.bottom);r?.classList.toggle("aligned",c.left);const l=this.detectionService.areAllSidesAligned(c);const d=this.stateManager.getCaptureState();if(d.step==="back"&&this.enableBackDocumentTimer&&n){const t=c.top||c.right||c.bottom||c.left;if(t){this.startBackDocumentTimer()}}if(l&&n){e?.classList.add("perfect-match");i?.forEach((t=>t.classList.add("perfect-match")));if(!this.hasScreenshotTaken){const t=Date.now();if(!this.alignmentStartTime){this.alignmentStartTime=t}const e=t-this.alignmentStartTime;if(e>=this.captureDelay){this.lastDetectedBox=n;this.takeScreenshot().catch((()=>{}));this.hasScreenshotTaken=true;this.alignmentStartTime=undefined;setTimeout((()=>{this.hasScreenshotTaken=false}),2e3)}}}else{e?.classList.remove("perfect-match");i?.forEach((t=>t.classList.remove("perfect-match")));if(this.alignmentStartTime){this.alignmentStartTime=undefined}if(this.alignmentTimer){clearTimeout(this.alignmentTimer);this.alignmentTimer=undefined}}}async takeManualScreenshot(){console.log("🔵 Botón clicked: Capturar (Frente/Reverso)");const t=this.stateManager?.getCaptureState();if(t?.step==="front"){this.processingButton="capture-front"}else if(t?.step==="back"){this.processingButton="capture-back"}console.log("🔵 processingButton set to:",this.processingButton);await new Promise((t=>setTimeout(t,100)));if(!this.videoRef){this.processingButton=null;return}await this.takeScreenshotWithMaskCoordinates()}async takeScreenshotWithMaskCoordinates(){if(!this.videoRef||!this.detectionContainer)return;this.stateManager.updateCaptureState({isCapturing:true});this.triggerCaptureAnimation();const t=this.getPooledCanvas(this.videoRef.videoWidth,this.videoRef.videoHeight);const e=t.getContext("2d",{alpha:false});e.clearRect(0,0,t.width,t.height);e.drawImage(this.videoRef,0,0,t.width,t.height);const i=this.detectionContainer.parentElement;const a=i.getBoundingClientRect();const s=parseFloat(this.el.style.getPropertyValue("--mask-width").replace("%",""))||90;const o=parseFloat(this.el.style.getPropertyValue("--mask-height").replace("%",""))||56.25;const r=parseFloat(this.el.style.getPropertyValue("--mask-center-x").replace("%",""))||50;const n=parseFloat(this.el.style.getPropertyValue("--mask-center-y").replace("%",""))||50;const c=this.videoRef.videoWidth;const l=this.videoRef.videoHeight;const d=c/l;const h=a.width/a.height;let f,p;let u=0,m=0;if(d>h){f=a.width;p=a.width/d;m=(a.height-p)/2}else{p=a.height;f=a.height*d;u=(a.width-f)/2}const b=s/100*a.width;const g=o/100*a.height;const x=r/100*a.width;const w=n/100*a.height;const y=c/f;const v=l/p;const k=(x-u)*y;const C=(w-m)*v;const M=b*y;const S=g*v;const z=Math.max(0,k-M/2-this.cropMargin);const P=Math.max(0,C-S/2-this.cropMargin);const E=Math.min(M+2*this.cropMargin,c-z);const A=Math.min(S+2*this.cropMargin,l-P);const T=this.getPooledCanvas(E,A);const I=T.getContext("2d",{alpha:false});I.clearRect(0,0,T.width,T.height);I.drawImage(this.videoRef,z,P,E,A,0,0,E,A);const D=this.stateManager.getCaptureState();if(D.step==="front"){this.stateManager.setCapturedImages({front:{fullFrame:t.toDataURL("image/png"),cropped:T.toDataURL("image/png")}});if(this.useDocumentClassification){try{const e=await this.detectionService.classifyDocument(T);if(e&&e.class==="passport"){this.completeProcess(true);this.returnCanvasToPool(t);this.returnCanvasToPool(T);this.processingButton=null;return}}catch(t){}}this.stateManager.updateCaptureState({step:"back",isDetectionPaused:true,showFlipAnimation:true});this.triggerRerender();await this.onFrontCaptureComplete();setTimeout((()=>{this.stateManager.updateCaptureState({showFlipAnimation:false,isDetectionPaused:false});this.triggerRerender();this.startBackDocumentTimer();this.processingButton=null}),3e3)}else if(D.step==="back"){this.stateManager.setCapturedImages({back:{fullFrame:t.toDataURL("image/png"),cropped:T.toDataURL("image/png")}});this.completeProcess(false);this.processingButton=null}this.returnCanvasToPool(t);this.returnCanvasToPool(T)}async takeScreenshot(){if(!this.videoRef||!this.lastDetectedBox)return;this.stateManager.updateCaptureState({isCapturing:true});this.triggerCaptureAnimation();const t=this.getPooledCanvas(this.videoRef.videoWidth,this.videoRef.videoHeight);const e=t.getContext("2d",{alpha:false});e.clearRect(0,0,t.width,t.height);e.drawImage(this.videoRef,0,0,t.width,t.height);const i=320;const a=this.videoRef.videoWidth/i;const s=this.videoRef.videoHeight/i;const o=Math.max(0,this.lastDetectedBox.x*a-this.cropMargin);const r=Math.max(0,this.lastDetectedBox.y*s-this.cropMargin);const n=Math.min(this.lastDetectedBox.w*a+2*this.cropMargin,this.videoRef.videoWidth-o);const c=Math.min(this.lastDetectedBox.h*s+2*this.cropMargin,this.videoRef.videoHeight-r);const l=this.getPooledCanvas(n,c);const d=l.getContext("2d",{alpha:false});d.clearRect(0,0,l.width,l.height);d.drawImage(this.videoRef,o,r,n,c,0,0,n,c);const h=this.stateManager.getCaptureState();if(h.step==="front"){this.stateManager.setCapturedImages({front:{fullFrame:t.toDataURL("image/png"),cropped:l.toDataURL("image/png")}});if(this.useDocumentClassification){try{const t=await this.detectionService.classifyDocument(l);if(t&&t.class==="passport"){this.completeProcess(true);return}}catch(t){}}this.stateManager.updateCaptureState({step:"back",isDetectionPaused:true,showFlipAnimation:true});await this.onFrontCaptureComplete();setTimeout((()=>{this.stateManager.updateCaptureState({showFlipAnimation:false,isDetectionPaused:false});this.startBackDocumentTimer()}),3e3)}else if(h.step==="back"){this.stateManager.setCapturedImages({back:{fullFrame:t.toDataURL("image/png"),cropped:l.toDataURL("image/png")}});this.completeProcess(false)}this.returnCanvasToPool(t);this.returnCanvasToPool(l)}triggerCaptureAnimation(){const t=this.el.shadowRoot?.querySelector(".card-outline");t?.classList.add("capturing");setTimeout((()=>{this.stateManager.updateCaptureState({isCapturing:false});t?.classList.remove("capturing")}),600)}switchToManualMode(){if(!this.useDocumentDetector||this.hasAutoSwitchedToManual){return}this.stopPerformanceMonitoring();this.releaseOnnxResources();this.resetMaskToWhite();this.detectionBoxes=[];this.hasAutoSwitchedToManual=true;this.performanceDegradedMode=true;this.showManualCaptureButton=true;this.showPerformanceMessage=true;setTimeout((()=>{this.showPerformanceMessage=false}),5e3)}switchToManualModeWithWarning(t){if(!this.useDocumentDetector||this.hasAutoSwitchedToManual){return}this.resetMaskToWhite();this.detectionBoxes=[];this.hasAutoSwitchedToManual=true;this.performanceDegradedMode=true;this.showManualCaptureButton=true;this.useDocumentDetector=false;this.updateStatus("Modo manual activado",t,"active");this.continueWithCameraSetup()}async continueWithCameraSetup(){try{this.updateStatus("Configurando cámara...","Buscando dispositivos disponibles","loading");try{await this.cameraService.enumerateDevices()}catch(t){throw new Error(`Error al enumerar dispositivos: ${t.message}`)}try{await this.updateCameraInfoWithAutofocus()}catch(t){throw new Error(`Error al actualizar información de cámara: ${t.message}`)}this.updateStatus("Ajustando cámara...","Configurando calidad de imagen","loading");let t;try{t=await this.cameraService.setupCamera()}catch(t){throw new Error(`Error al configurar cámara: ${t.message}`)}this.updateStatus("Captura manual","Posicione su documento y use el botón para capturar","active");try{await this.initializeVideoStream(t)}catch(t){throw new Error(`Error al inicializar video: ${t.message}`)}if(this.detectionContainer){const t=this.detectionContainer.parentElement;const e=t.getBoundingClientRect();this.updateMaskDimensions(e)}this.startTime=Date.now();this.stateManager.updateCaptureState({isLoading:false});this.showManualCaptureButton=true}catch(t){this.updateStatus("Error de cámara",t.message,"error");throw t}}switchToManualModeWithError(t){if(!this.useDocumentDetector||this.hasAutoSwitchedToManual){return}this.releaseOnnxResources();this.resetMaskToWhite();this.detectionBoxes=[];this.hasAutoSwitchedToManual=true;this.performanceDegradedMode=true;this.showManualCaptureButton=true;this.useDocumentDetector=false;this.updateStatus("Modo manual activado",t,"error");setTimeout((()=>{this.updateStatus("Captura manual","Use el botón para capturar","ready")}),5e3)}stopPerformanceMonitoring(){}releaseOnnxResources(){try{if(this.detectionService){this.detectionService.cleanup()}}catch(t){}}completeProcess(t=false){this.stateManager.updateCaptureState({step:"completed",showSuccessAnimation:true});const e=this.stateManager.getCapturedImages();e.metadata.processCompleted=true;e.metadata.backCaptureSkipped=t;this.stateManager.setCapturedImages(e);this.stopDetection();this.updateStatus("Proceso completado",`Imágenes capturadas exitosamente`,"ready");const i={...e,timestamp:(new Date).toISOString()};this.captureCompleted.emit(i);setTimeout((()=>{this.stateManager.updateCaptureState({showSuccessAnimation:false})}),3e3);setTimeout((async()=>{const t=await this.aggressiveResourceCleanup();if(this.debug){console.log("🧹 Post-completion cleanup:",t.freed);if(t.errors.length>0){console.warn("⚠️ Cleanup errors:",t.errors)}}}),1e3)}stopDetection(){if(this.animationId){cancelAnimationFrame(this.animationId);this.animationId=undefined}this.clearBackDocumentTimer();this.detectionBoxes=[]}startBackDocumentTimer(){if(!this.enableBackDocumentTimer)return;if(this.backDocumentTimer){clearInterval(this.backDocumentTimer)}this.backDocumentTimerRemaining=this.backDocumentTimerDuration;this.backDocumentTimer=window.setInterval((()=>{this.backDocumentTimerRemaining--;if(this.backDocumentTimerRemaining<=0){this.clearBackDocumentTimer();this.skipBackCapture()}}),1e3)}clearBackDocumentTimer(){if(this.backDocumentTimer){clearInterval(this.backDocumentTimer);this.backDocumentTimer=undefined}this.backDocumentTimerRemaining=0}toggleCameraSelector(){if(this.isSwitchingCamera)return;this.showCameraSelector=!this.showCameraSelector}async updateCameraInfoWithAutofocus(){try{const t=await this.cameraService.getCameraInfo();this.cameraInfoWithAutofocus=t}catch(t){}}async handleCameraSwitch(t){if(this.isSwitchingCamera)return;try{this.showCameraSelector=false;this.isSwitchingCamera=true;if(this.videoStream){this.videoStream.getTracks().forEach((t=>t.stop()))}await this.cameraService.switchCamera(t);const e=await this.cameraService.setupCamera();await this.initializeVideoStream(e);await this.updateCameraInfoWithAutofocus()}catch(t){try{const t=await this.cameraService.setupCamera();await this.initializeVideoStream(t)}catch(t){this.updateStatus("Error al cambiar cámara","No se pudo cambiar el dispositivo","error")}}finally{this.isSwitchingCamera=false}}resetDetection(){const t=this.stateManager.getCaptureState();const e=t.isVideoActive;this.stateManager.reset();if(e){this.stateManager.updateCaptureState({isVideoActive:true})}this.hasScreenshotTaken=false;this.startTime=Date.now();this.frameSkipCounter=0;this.consecutiveFailures=0;this.lastInferenceTime=0;this.detectionBoxes=[];this.alignmentStartTime=undefined;this.hasDocumentDetected=false;this.processedFramesCount=0;this.slowFrameCount=0;this.hasAutoSwitchedToManual=false;this.performanceDegradedMode=false;this.showPerformanceMessage=false;if(this.alignmentTimer){clearTimeout(this.alignmentTimer);this.alignmentTimer=undefined}if(e&&this.detectionService.isModelLoaded()){this.updateStatus("Captura reiniciada","Buscando documento en el marco de captura","active");this.detectFrame()}else{this.updateStatus("Listo para capturar","","ready")}}exitSession(){if(this.videoStream){this.videoStream.getTracks().forEach((t=>t.stop()));this.videoStream=undefined;this.stateManager.updateCaptureState({isVideoActive:false,isLoading:false})}this.isMaskReady=false;this.updateStatus("Captura finalizada","","ready");this.detectionBoxes=[];this.cleanup()}initializePerformanceMonitor(){this.performanceMetrics.lastUpdateTime=performance.now();this.performanceUpdateInterval=window.setInterval((()=>{this.updatePerformanceMetrics()}),500)}updatePerformanceMetrics(){const t=performance.now();const e=t-this.performanceMetrics.lastUpdateTime;if(e>0){this.performanceMetrics.fps=Math.round(1e3/(e/this.frameSkipCounter||1))}if("memory"in performance){const t=performance.memory;this.performanceMetrics.memoryUsage=Math.round(t.usedJSHeapSize/1048576)}if(this.performanceMetrics.totalDetections>0){this.performanceMetrics.successfulDetections=this.performanceMetrics.successfulDetections;const t=this.performanceMetrics.successfulDetections/this.performanceMetrics.totalDetections*100;this.performanceMetrics.detectionRate=Math.round(t)}this.performanceData={fps:this.performanceMetrics.fps,inferenceTime:this.performanceMetrics.inferenceTime,memoryUsage:this.performanceMetrics.memoryUsage,onnxLoadTime:this.performanceMetrics.onnxLoadTime,frameProcessingTime:this.performanceMetrics.frameProcessingTime,totalDetections:this.performanceMetrics.totalDetections,successfulDetections:this.performanceMetrics.successfulDetections,detectionRate:this.performanceMetrics.detectionRate};this.performanceMetrics.lastUpdateTime=t}recordOnnxPerformance(t,e){this.performanceMetrics.onnxLoadTime=Math.round(t);this.performanceMetrics.inferenceTime=Math.round(e)}recordFrameProcessing(t,e){this.performanceMetrics.frameProcessingTime=Math.round(t);this.performanceMetrics.totalDetections++;if(e>0){this.performanceMetrics.successfulDetections++}this.performanceHistory.push(t);if(this.performanceHistory.length>this.PERFORMANCE_HISTORY_SIZE){this.performanceHistory.shift()}}getAdaptiveFrameSkip(){if(this.consecutiveFailures>20)return this.MAX_FRAME_SKIP;if(this.performanceMetrics.inferenceTime>200)return 6;if(this.performanceMetrics.memoryUsage>200)return 5;if(this.performanceHistory.length>0){const t=this.performanceHistory.reduce(((t,e)=>t+e),0)/this.performanceHistory.length;if(t>100)return 4;if(t>80)return 3;if(t>60)return this.BASE_FRAME_SKIP+1}if(this.performanceMetrics.memoryUsage>150)return 4;return this.BASE_FRAME_SKIP}resetMaskToWhite(){const t=this.el.shadowRoot?.querySelector(".card-outline");const e=this.el.shadowRoot?.querySelectorAll(".corner");const i=this.el.shadowRoot?.querySelector(".side-top");const a=this.el.shadowRoot?.querySelector(".side-right");const s=this.el.shadowRoot?.querySelector(".side-bottom");const o=this.el.shadowRoot?.querySelector(".side-left");t?.classList.remove("perfect-match");e?.forEach((t=>t.classList.remove("perfect-match")));i?.classList.remove("aligned");a?.classList.remove("aligned");s?.classList.remove("aligned");o?.classList.remove("aligned");this.sideAlignment={top:false,right:false,bottom:false,left:false}}getPooledCanvas(t,e){const i=this.canvasPool.findIndex((i=>i.width===t&&i.height===e));if(i!==-1){return this.canvasPool.splice(i,1)[0]}if(this.canvasPool.length>0){const i=this.canvasPool.pop();i.width=t;i.height=e;return i}const a=document.createElement("canvas");a.width=t;a.height=e;return a}returnCanvasToPool(t){if(this.canvasPool.length<this.MAX_CANVAS_POOL_SIZE){const e=t.getContext("2d");e.clearRect(0,0,t.width,t.height);this.canvasPool.push(t)}}};p.style=f;export{p as jaak_stamps};
2
- //# sourceMappingURL=p-8e25497e.entry.js.map