@jaak.ai/stamps 2.0.0-dev.58 → 2.0.1

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 (44) hide show
  1. package/dist/cjs/jaak-stamps-webcomponent.cjs.js +1 -1
  2. package/dist/cjs/jaak-stamps.cjs.entry.js +611 -546
  3. package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
  4. package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
  5. package/dist/cjs/loader.cjs.js +1 -1
  6. package/dist/collection/components/my-component/my-component.css +2 -14
  7. package/dist/collection/components/my-component/my-component.js +237 -346
  8. package/dist/collection/components/my-component/my-component.js.map +1 -1
  9. package/dist/collection/services/CameraService.js +344 -156
  10. package/dist/collection/services/CameraService.js.map +1 -1
  11. package/dist/collection/services/DetectionService.js +38 -53
  12. package/dist/collection/services/DetectionService.js.map +1 -1
  13. package/dist/collection/services/EventBusService.js +1 -1
  14. package/dist/collection/services/EventBusService.js.map +1 -1
  15. package/dist/collection/services/LoggerService.js +40 -0
  16. package/dist/collection/services/LoggerService.js.map +1 -0
  17. package/dist/collection/services/ServiceContainer.js +12 -2
  18. package/dist/collection/services/ServiceContainer.js.map +1 -1
  19. package/dist/collection/services/interfaces/ICameraService.js.map +1 -1
  20. package/dist/collection/services/interfaces/ILogger.js +2 -0
  21. package/dist/collection/services/interfaces/ILogger.js.map +1 -0
  22. package/dist/collection/types/component-types.js.map +1 -1
  23. package/dist/components/jaak-stamps.js +614 -548
  24. package/dist/components/jaak-stamps.js.map +1 -1
  25. package/dist/esm/jaak-stamps-webcomponent.js +1 -1
  26. package/dist/esm/jaak-stamps.entry.js +611 -546
  27. package/dist/esm/jaak-stamps.entry.js.map +1 -1
  28. package/dist/esm/loader.js +1 -1
  29. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
  30. package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
  31. package/dist/jaak-stamps-webcomponent/p-2264b5b4.entry.js +2 -0
  32. package/dist/jaak-stamps-webcomponent/p-2264b5b4.entry.js.map +1 -0
  33. package/dist/types/components/my-component/my-component.d.ts +17 -62
  34. package/dist/types/components.d.ts +8 -6
  35. package/dist/types/services/CameraService.d.ts +14 -12
  36. package/dist/types/services/DetectionService.d.ts +3 -9
  37. package/dist/types/services/LoggerService.d.ts +12 -0
  38. package/dist/types/services/ServiceContainer.d.ts +2 -0
  39. package/dist/types/services/interfaces/ICameraService.d.ts +12 -3
  40. package/dist/types/services/interfaces/ILogger.d.ts +8 -0
  41. package/dist/types/types/component-types.d.ts +0 -3
  42. package/package.json +4 -4
  43. package/dist/jaak-stamps-webcomponent/p-39560f23.entry.js +0 -2
  44. package/dist/jaak-stamps-webcomponent/p-39560f23.entry.js.map +0 -1
@@ -33,6 +33,7 @@ export namespace Components {
33
33
  * @default false
34
34
  */
35
35
  "enableBackDocumentTimer": boolean;
36
+ "focusAtPoint": (x: number, y: number) => Promise<{ success: boolean; coordinates: { x: number; y: number; }; }>;
36
37
  "getCameraInfo": () => Promise<CameraInfoResponse>;
37
38
  "getCaptureDelay": () => Promise<number>;
38
39
  "getCapturedImages": () => Promise<CapturedImagesResponse>;
@@ -47,12 +48,13 @@ export namespace Components {
47
48
  */
48
49
  "preferredCamera": 'auto' | 'front' | 'back';
49
50
  "preloadModel": () => Promise<{ success: boolean; message: string; error?: undefined; } | { success: boolean; error: any; message?: undefined; }>;
50
- "resetCapture": () => Promise<{ success: boolean; error?: undefined; } | { success: boolean; error: any; }>;
51
- "setCaptureDelay": (delay: number) => Promise<{ success: boolean; error: string; captureDelay: number; } | { success: boolean; captureDelay: number; error?: undefined; }>;
52
- "setPreferredCamera": (camera: "auto" | "front" | "back") => Promise<{ success: boolean; selectedCamera: string; availableCameras: number; error?: undefined; } | { success: boolean; error: any; selectedCamera: any; availableCameras: number; }>;
53
- "skipBackCapture": () => Promise<{ success: boolean; error?: undefined; } | { success: boolean; error: any; }>;
54
- "startCapture": () => Promise<{ success: boolean; error?: undefined; } | { success: boolean; error: any; }>;
55
- "stopCapture": () => Promise<{ success: boolean; error?: undefined; } | { success: boolean; error: any; }>;
51
+ "resetCapture": () => Promise<void>;
52
+ "setCaptureDelay": (delay: number) => Promise<{ success: boolean; captureDelay: number; }>;
53
+ "setPreferredCamera": (camera: "auto" | "front" | "back") => Promise<{ success: boolean; selectedCamera: string; availableCameras: number; }>;
54
+ "setTorchEnabled": (enabled: boolean) => Promise<{ success: boolean; enabled: boolean; }>;
55
+ "skipBackCapture": () => Promise<void>;
56
+ "startCapture": () => Promise<void>;
57
+ "stopCapture": () => Promise<void>;
56
58
  /**
57
59
  * @default false
58
60
  */
@@ -1,18 +1,16 @@
1
1
  import { ICameraService, CameraInfo } from './interfaces/ICameraService';
2
+ import { ILogger } from './interfaces/ILogger';
2
3
  import { IEventBus } from './interfaces/IEventBus';
3
4
  export declare class CameraService implements ICameraService {
5
+ private logger;
4
6
  private eventBus;
5
7
  private availableCameras;
6
8
  private selectedCameraId;
7
9
  private deviceType;
8
10
  private preferredCameraFacing;
9
11
  private preferredCamera;
10
- private static cameraCapabilitiesCache;
11
- private static deviceEnumerationCache;
12
- private static readonly CACHE_DURATION;
13
- private currentStreamPromise?;
14
- private lastStreamConstraints?;
15
- constructor(eventBus: IEventBus, preferredCamera?: 'auto' | 'front' | 'back');
12
+ private isManuallySelected;
13
+ constructor(logger: ILogger, eventBus: IEventBus, preferredCamera?: 'auto' | 'front' | 'back');
16
14
  detectDeviceType(): Promise<'mobile' | 'desktop' | 'tablet'>;
17
15
  enumerateDevices(): Promise<MediaDeviceInfo[]>;
18
16
  getAvailableCameras(): MediaDeviceInfo[];
@@ -22,24 +20,28 @@ export declare class CameraService implements ICameraService {
22
20
  getPreferredFacing(): 'environment' | 'user' | null;
23
21
  setupCamera(constraints?: MediaTrackConstraints): Promise<MediaStream>;
24
22
  switchCamera(cameraId: string): Promise<void>;
23
+ flipToNextCamera(): Promise<void>;
24
+ savePreference(): void;
25
+ loadPreference(): void;
25
26
  isRearCamera(stream: MediaStream): boolean;
26
- getCameraInfo(): Promise<{
27
+ getCameraInfo(): {
27
28
  availableCameras: CameraInfo[];
28
29
  selectedCameraId: string | null;
29
30
  deviceType: string;
30
31
  isMultipleCamerasAvailable: boolean;
31
32
  preferredFacing: 'environment' | 'user' | null;
32
- }>;
33
+ };
33
34
  private checkCameraPermission;
34
35
  private handleCameraPermissionError;
35
36
  private setInitialCameraPreference;
36
- private checkCameraAutofocus;
37
37
  private selectFrontCamera;
38
38
  private selectBackCamera;
39
39
  private selectAutoCamera;
40
40
  private updatePreferredFacing;
41
41
  private getMaxResolution;
42
- private constraintsEqual;
43
- static clearCaches(): void;
44
- invalidateDeviceCache(): void;
42
+ private applyAdvancedCameraSettings;
43
+ private applyBasicFocusSettings;
44
+ private getCapabilitiesSummary;
45
+ setTorchEnabled(enabled: boolean, stream?: MediaStream): Promise<boolean>;
46
+ focusAtPoint(x: number, y: number, stream?: MediaStream): Promise<boolean>;
45
47
  }
@@ -1,5 +1,7 @@
1
1
  import { IDetectionService, DetectionBox, SideAlignment, ClassificationResult } from './interfaces/IDetectionService';
2
+ import { ILogger } from './interfaces/ILogger';
2
3
  export declare class DetectionService implements IDetectionService {
4
+ private logger;
3
5
  private debug;
4
6
  private useDocumentClassification;
5
7
  private session?;
@@ -15,9 +17,7 @@ export declare class DetectionService implements IDetectionService {
15
17
  private preprocessCanvas?;
16
18
  private preprocessCtx?;
17
19
  private captureCanvas?;
18
- private static canvasPool;
19
- private static readonly MAX_POOL_SIZE;
20
- constructor(debug?: boolean, useDocumentClassification?: boolean);
20
+ constructor(logger: ILogger, debug?: boolean, useDocumentClassification?: boolean);
21
21
  loadModel(): Promise<void>;
22
22
  loadClassificationModel(): Promise<void>;
23
23
  isModelLoaded(): boolean;
@@ -32,10 +32,4 @@ export declare class DetectionService implements IDetectionService {
32
32
  private cleanupCanvasPool;
33
33
  private float32ToFloat16;
34
34
  private preprocessMobileNet;
35
- private getCanvas;
36
- private returnCanvas;
37
- static clearCanvasPools(): void;
38
- getPoolStats(): {
39
- [key: string]: number;
40
- };
41
35
  }
@@ -0,0 +1,12 @@
1
+ import { ILogger } from './interfaces/ILogger';
2
+ export declare class LoggerService implements ILogger {
3
+ private debugMode;
4
+ constructor(debug?: boolean);
5
+ setDebugMode(debug: boolean): void;
6
+ info(...args: any[]): void;
7
+ warn(...args: any[]): void;
8
+ error(...args: any[]): void;
9
+ debug(...args: any[]): void;
10
+ state(state: string, data?: any): void;
11
+ performance(operation: string, duration: number): void;
12
+ }
@@ -1,3 +1,4 @@
1
+ import { ILogger } from './interfaces/ILogger';
1
2
  import { ICameraService } from './interfaces/ICameraService';
2
3
  import { IDetectionService } from './interfaces/IDetectionService';
3
4
  import { IStateManager } from './interfaces/IStateManager';
@@ -16,6 +17,7 @@ export declare class ServiceContainer {
16
17
  constructor(config: ComponentConfig);
17
18
  private initializeServices;
18
19
  get<T>(serviceName: string): T;
20
+ getLogger(): ILogger;
19
21
  getEventBus(): IEventBus;
20
22
  getStateManager(): IStateManager;
21
23
  getCameraService(): ICameraService;
@@ -2,7 +2,11 @@ export interface CameraInfo {
2
2
  id: string;
3
3
  label: string;
4
4
  selected: boolean;
5
- hasAutofocus: boolean;
5
+ }
6
+ export interface CameraPreference {
7
+ cameraId: string;
8
+ facing: 'environment' | 'user' | null;
9
+ timestamp: number;
6
10
  }
7
11
  export interface ICameraService {
8
12
  detectDeviceType(): Promise<'mobile' | 'desktop' | 'tablet'>;
@@ -14,12 +18,17 @@ export interface ICameraService {
14
18
  getPreferredFacing(): 'environment' | 'user' | null;
15
19
  setupCamera(constraints?: MediaTrackConstraints): Promise<MediaStream>;
16
20
  switchCamera(cameraId: string): Promise<void>;
21
+ flipToNextCamera(): Promise<void>;
22
+ savePreference(): void;
23
+ loadPreference(): void;
17
24
  isRearCamera(stream: MediaStream): boolean;
18
- getCameraInfo(): Promise<{
25
+ setTorchEnabled(enabled: boolean, stream?: MediaStream): Promise<boolean>;
26
+ focusAtPoint(x: number, y: number, stream?: MediaStream): Promise<boolean>;
27
+ getCameraInfo(): {
19
28
  availableCameras: CameraInfo[];
20
29
  selectedCameraId: string | null;
21
30
  deviceType: string;
22
31
  isMultipleCamerasAvailable: boolean;
23
32
  preferredFacing: 'environment' | 'user' | null;
24
- }>;
33
+ };
25
34
  }
@@ -0,0 +1,8 @@
1
+ export interface ILogger {
2
+ info(...args: any[]): void;
3
+ warn(...args: any[]): void;
4
+ error(...args: any[]): void;
5
+ debug(...args: any[]): void;
6
+ state(state: string, data?: any): void;
7
+ performance(operation: string, duration: number): void;
8
+ }
@@ -11,7 +11,6 @@ export interface CameraInfoResponse {
11
11
  deviceType: string;
12
12
  isMultipleCamerasAvailable: boolean;
13
13
  preferredFacing: 'environment' | 'user' | null;
14
- error?: string;
15
14
  }
16
15
  export interface CapturedImagesResponse {
17
16
  front: {
@@ -34,6 +33,4 @@ export interface StatusResponse {
34
33
  hasImages: boolean;
35
34
  isProcessCompleted: boolean;
36
35
  isModelPreloaded: boolean;
37
- componentStatus?: 'initializing' | 'loading' | 'ready' | 'error';
38
- componentMessage?: string;
39
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jaak.ai/stamps",
3
- "version": "2.0.0-dev.58",
3
+ "version": "2.0.1",
4
4
  "description": "Jaak Document Identifier",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.js",
@@ -51,9 +51,9 @@
51
51
  "@semantic-release/changelog": "^6.0.3",
52
52
  "@semantic-release/commit-analyzer": "^13.0.1",
53
53
  "@semantic-release/git": "^10.0.1",
54
- "@semantic-release/github": "^11.0.4",
54
+ "@semantic-release/github": "^11.0.6",
55
55
  "@semantic-release/npm": "^12.0.2",
56
- "@semantic-release/release-notes-generator": "^14.0.3",
57
- "semantic-release": "^24.2.7"
56
+ "@semantic-release/release-notes-generator": "^14.1.0",
57
+ "semantic-release": "^24.2.9"
58
58
  }
59
59
  }
@@ -1,2 +0,0 @@
1
- import{r as t,c as e,a as i,h as s}from"./p-BP1Q4KOg.js";class a{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=s=>{e(s);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 s=i.getCapabilities();e.getTracks().forEach((t=>t.stop()));const a=s.focusMode&&Array.isArray(s.focusMode)&&s.focusMode.length>0;const o=a&&(s.focusMode.includes("continuous")||s.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 s=i.getVideoTracks()[0];e=s.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 s=Math.min(e.height.max,1080);const a=/iPad|Android/i.test(navigator.userAgent)&&window.innerWidth>=768;if(a){i.width={ideal:Math.min(t,1280)};i.height={ideal:Math.min(s,720)}}else{i.width={ideal:t};i.height={ideal:s}}}const s=e;if(s.focusMode&&Array.isArray(s.focusMode)){if(s.focusMode.includes("continuous")){i.focusMode="continuous"}else if(s.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 s=i&&(i.effectiveType==="slow-2g"||i.effectiveType==="2g");return{estimatedRAM:e,isLowMemory:true,isSlowConnection:s}}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 s=i&&(i.effectiveType==="slow-2g"||i.effectiveType==="2g");return{estimatedRAM:e,isLowMemory:false,isSlowConnection:s}}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 d{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 l{debug;useDocumentClassification;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;constructor(t=false,e=false){this.debug=t;this.useDocumentClassification=e;this.deviceStrategy=d.createStrategy();this.initializeCanvasPool()}async loadModel(){if(this.modelLoaded||this.session){return}try{const t=this.deviceStrategy.getSessionOptions(this.debug);try{this.session=await window.ort.InferenceSession.create(this.MODEL_PATH,t)}catch(t){if(t.message.includes("failed to allocate a buffer")){const t={executionProviders:["wasm"],graphOptimizationLevel:"disabled",logSeverityLevel:4,enableCpuMemArena:false,enableMemPattern:false,executionMode:"sequential",interOpNumThreads:1,intraOpNumThreads:1};this.session=await window.ort.InferenceSession.create(this.MODEL_PATH,t)}else{throw t}}this.modelLoaded=true}catch(t){throw t}}async loadClassificationModel(){if(!this.useDocumentClassification){return}try{try{const t=await fetch(this.MOBILENET_CLASSES_PATH);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{this.mobileNetSession=await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH,t)}catch(t){if(t.message.includes("failed to allocate a buffer")){const t={executionProviders:["wasm"],graphOptimizationLevel:"disabled",logSeverityLevel:4,enableCpuMemArena:false,enableMemPattern:false,executionMode:"sequential",interOpNumThreads:1,intraOpNumThreads:1};this.mobileNetSession=await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH,t)}else{throw t}}}catch(t){throw t}}isModelLoaded(){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,s,a]=[[],[],[]];const{data:o}=e;for(let t=0;t<o.length;t+=4){i.push(o[t]/255);s.push(o[t+1]/255);a.push(o[t+2]/255)}const r=new Float32Array(i.concat(s,a));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.session){throw new Error("Detection model not loaded")}const e={[this.session.inputNames[0]]:t};const i=await this.session.run(e);const s=i[this.session.outputNames[0]].data;const a=[];for(let t=0;t<s.length;t+=6){const[e,i,o,r,n,c]=s.slice(t,t+6);if(n>this.CONFIDENCE_THRESHOLD){a.push({x:e,y:i,w:o-e,h:r-i,score:n,classId:c})}}return a}async classifyDocument(t){if(!this.mobileNetSession||!this.mobileNetClassMap){return null}try{const e=this.preprocessMobileNet(t);const i={[this.mobileNetSession.inputNames[0]]:e};const s=await this.mobileNetSession.run(i);const a=s[Object.keys(s)[0]].data;const o=a.reduce(((t,e,i,s)=>e>s[t]?i:t),0);const r=a[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:s,shouldMirrorVideo:a,alignmentTolerance:o,maskSize:r,videoRef:n}=e;if(!n){return{top:false,right:false,bottom:false,left:false}}const c=n.videoWidth;const d=n.videoHeight;if(c===0||d===0){return{top:false,right:false,bottom:false,left:false}}const l=c/d;const h=1;let f,p;if(l>h){f=i;p=i/l}else{p=i;f=i*l}const u=p*s;let m,b;const g=r/100;if(u<=f){b=p*g;m=b*s}else{m=f*g;b=m/s}const x=m*(i/f);const y=b*(i/p);const w=i/2;const v=i/2;const k=w-x/2;const C=w+x/2;const S=v-y/2;const M=v+y/2;let z=t.x;let A=t.x+t.w;const P=t.y;const T=t.y+t.h;if(a){const t=z;const e=A;z=i-e;A=i-t}const I=o;const D=Math.abs(P-S)<=I;const E=Math.abs(A-C)<=I;const F=Math.abs(T-M)<=I;const L=Math.abs(z-k)<=I;return{top:D&&L,right:D&&E,bottom:F&&L,left:F&&E}}isCardInFrame(t){const e=t.x+t.w/2;const i=t.y+t.h/2;const s=this.INPUT_SIZE/2;const a=this.INPUT_SIZE/2;const o=40;const r=30;const n=Math.abs(e-s)<o&&Math.abs(i-a)<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.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}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 s=i.getUint32(0,true);const a=s>>31&1;const o=s>>23&255;const r=s&8388607;let n=o-127+15;if(o===0){n=0}else if(o===255){n=31}else if(n>=31){n=31;return a<<15|n<<10}else if(n<=0){return a<<15}return a<<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 s=i.getImageData(0,0,224,224);const a=s.data;const o=224*224;const r=new Float32Array(3*o);for(let t=0;t<o;t++){r[t]=a[t*4+0]/255;r[o+t]=a[t*4+1]/255;r[2*o+t]=a[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(!l.canvasPool.has(i)){l.canvasPool.set(i,[])}const s=l.canvasPool.get(i);let a=s.pop();if(!a){a=document.createElement("canvas");a.width=t;a.height=e}else{const i=a.getContext("2d");i.clearRect(0,0,t,e)}return a}returnCanvas(t){const e=`${t.width}x${t.height}`;if(!l.canvasPool.has(e)){l.canvasPool.set(e,[])}const i=l.canvasPool.get(e);if(i.length<l.MAX_POOL_SIZE){i.push(t)}}static clearCanvasPools(){l.canvasPool.clear()}getPoolStats(){const t={};l.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 a;const i=new o(e);const s=new r(e,t.preferredCamera);const n=new l(t.debug,t.useDocumentClassification);this.services.set("eventBus",e);this.services.set("stateManager",i);this.services.set("cameraService",s);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%);color:#fff;font-size:14px;font-weight:600;text-align:center;white-space:normal;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(12px);padding:12px 20px;border-radius:8px;max-width:300px;z-index:20;border:1px solid rgba(255, 255, 255, 0.1)}.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}.skip-explanation{background:rgba(0, 0, 0, 0.5);color:#ffffff;padding:10px 16px;border-radius:8px;font-size:14px;font-weight:500;text-align:center;margin-bottom:12px;box-shadow:0 2px 8px rgba(0, 0, 0, 0.2);backdrop-filter:blur(12px);border:1px solid rgba(255, 255, 255, 0.1);animation:fadeIn 0.3s ease-in-out}@keyframes fadeIn{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}.skip-button{pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.skip-button:hover{background:#f8f9fa}.skip-button:active{background:#e9ecef;transform:translateY(1px)}.camera-controls{position:absolute;top:16px;right:16px;z-index:25;display:flex;gap:8px;pointer-events:auto}.camera-selector-button{height:32px;padding:0 10px;border:none;border-radius:8px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(12px);color:#ffffff;font-size:12px;font-weight:500;cursor:pointer;transition:all 0.2s ease;display:flex;align-items:center;justify-content:center;border:1px solid rgba(255, 255, 255, 0.1);white-space:nowrap;min-width:fit-content}.camera-selector-button:hover{background:rgba(0, 0, 0, 0.8);border-color:rgba(255, 255, 255, 0.2);transform:translateY(-1px)}.camera-selector-button:active{transform:translateY(0);background:rgba(0, 0, 0, 0.9)}.camera-selector-button:disabled,.camera-selector-button.loading{opacity:0.7;cursor:not-allowed;pointer-events:none}.camera-selector-button:disabled:hover,.camera-selector-button.loading:hover{transform:none;background:rgba(0, 0, 0, 0.6);border-color:rgba(255, 255, 255, 0.1)}.button-spinner{width:16px;height:16px;border:2px solid rgba(255, 255, 255, 0.3);border-top:2px solid #ffffff;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.camera-selector-dropdown{position:absolute;top:56px;right:16px;z-index:30;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;min-width:260px;max-width:300px;border:1px solid rgba(255, 255, 255, 0.1);overflow:hidden;pointer-events:auto;animation:slideInFromTop 0.3s ease-out}@keyframes slideInFromTop{0%{opacity:0;transform:translateY(-8px) scale(0.95)}100%{opacity:1;transform:translateY(0) scale(1)}}.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}}.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:slideInFromLeft 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}}";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;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;serviceContainer;eventBus;stateManager;cameraService;detectionService;videoRef;detectionContainer;videoStream;animationId;lastDetectedBox;startTime;hasScreenshotTaken=false;alignmentStartTime;alignmentTimer;backDocumentTimer;performanceMetrics={fps:0,inferenceTime:0,memoryUsage:0,cpuUsage: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;canvasPool=[];MAX_CANVAS_POOL_SIZE=3;async componentDidLoad(){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()}}async initializeServices(){const t={debug:this.debug,alignmentTolerance:this.alignmentTolerance,maskSize:this.maskSize,cropMargin:this.cropMargin,useDocumentClassification:this.useDocumentClassification,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",(t=>{this.handleStateChange(t)}));this.eventBus.on("camera-changed",(()=>{}));this.eventBus.on("error",(()=>{}))}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((()=>{this.finalizeInitialization();e(undefined)}),300)}}))}else{setTimeout((()=>{this.finalizeInitialization()}),300)}}finalizeInitialization(){this.stateManager.updateCaptureState({isLoading:false});this.currentStatus={message:"Listo para capturar",description:"",type:"ready",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)}handleStateChange(t){}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)}}updateMaskDimensions(t){if(!this.videoRef)return;const e=this.videoRef.videoWidth;const i=this.videoRef.videoHeight;if(e===0||i===0)return;const s=e/i;const a=t.width/t.height;let o,r;let n=0,c=0;if(s>a){o=t.width;r=t.width/s;c=(t.height-r)/2}else{r=t.height;o=t.height*s;n=(t.width-o)/2}const d=85.6/53.98;const l=r*d;let h,f;const p=this.maskSize/100;if(l<=o){f=r*p;h=f*d}else{h=o*p;f=h/d}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 y=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",`${y}%`);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();return{success:true}}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(){const t=this.isComponentReady();if(!t.ready){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}}}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})}await this.detectionService.loadModel();this.updateStatus("Optimizando detección...","Configurando reconocimiento de documentos","loading");await this.detectionService.loadClassificationModel();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 startDetection(){try{if(!this.detectionService.isModelLoaded()){const t=performance.now();this.updateStatus("Preparando reconocimiento...","Configurando detección de documentos","loading");this.stateManager.updateCaptureState({isLoading:true});await this.detectionService.loadModel();this.updateStatus("Optimizando detección...","Configurando reconocimiento de documentos","loading");await this.detectionService.loadClassificationModel();const e=performance.now();const i=e-t;if(this.debug){this.recordOnnxPerformance(i,0)}}this.updateStatus("Configurando cámara...","Buscando dispositivos disponibles","loading");await this.cameraService.enumerateDevices();await this.updateCameraInfoWithAutofocus();this.updateStatus("Ajustando cámara...","Configurando calidad de imagen","loading");const t=await this.cameraService.setupCamera();this.updateStatus("Captura activa","Buscando documento en el marco de captura","active");await this.initializeVideoStream(t);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.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(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 s=Date.now();if(s-this.lastInferenceTime<this.MIN_INFERENCE_INTERVAL){if(e.step!=="completed"){this.animationId=requestAnimationFrame((()=>this.detectFrame()))}return}this.lastInferenceTime=s;const a=performance.now();const o=this.detectionService.preprocess(this.videoRef);const r=await this.detectionService.runInference(o);const n=performance.now()-a;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 s=i?t.score*1.2:t.score;if(s>e.bestScore){this.stateManager.updateCaptureState({bestScore:s})}}))}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);if(this.debug){const e=performance.now();const i=e-t;this.recordFrameProcessing(i,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}if(this.performanceUpdateInterval){clearInterval(this.performanceUpdateInterval);this.performanceUpdateInterval=undefined}this.canvasPool=[];this.detectionBoxes=[];this.alignmentStartTime=undefined;this.hasDocumentDetected=false;this.serviceContainer?.cleanup()}render(){const t=this.stateManager?.getCaptureState()||{isVideoActive:false,showFlipAnimation:false,showSuccessAnimation:false,step:"front",isCapturing:false};const e=this.cameraInfoWithAutofocus;return s("div",{key:"69a8df7969288e19088e8809f1fefcc89b237cda",class:"detector-container"},s("div",{key:"79e59a315d266be9d4fb5eed5740e5ad825d5890",class:"video-container"},s("video",{key:"a3312788c739748b774a25acb30c2dcea7f01695",ref:t=>this.videoRef=t,autoplay:true,muted:true,playsinline:true,class:this.shouldMirrorVideo?"mirror":"",style:{display:t.isVideoActive?"block":"none"}}),s("div",{key:"ddab107500c2dab24c140049bef0b44aafc35dc7",ref:t=>this.detectionContainer=t,class:`detection-overlay ${this.shouldMirrorVideo?"mirror":""}`},this.debug&&this.detectionBoxes.map(((t,e)=>s("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&&s("div",{key:"370337089a3de949b8cb4ae84dc0037e6044b2d5",class:"overlay-mask"},s("div",{key:"cb35c2e42bf1729ad02a8fe7e7abaf27cf1a8d7a",class:"card-outline"},s("div",{key:"637d72ada63805e7f25051cd1ad9093030cb025a",class:"side side-top"}),s("div",{key:"c7a465aa686afa41f80433d949715b40f6f349dc",class:"side side-right"}),s("div",{key:"384aade0610b5bc7bdd7db350a70d82f9bebd8ab",class:"side side-bottom"}),s("div",{key:"5506cc346f3fd718e3fda4365f69ea780304b6d6",class:"side side-left"}),!t.showFlipAnimation&&!t.showSuccessAnimation&&s("div",{key:"f5b9b62937eabab7c096b7417a13bbf6f822ee8a",class:"guide-text"},"Alinee su identificación con el marco")),t.step==="back"&&!t.showFlipAnimation&&!t.showSuccessAnimation&&s("div",{key:"74b122125a42839d2600cf99fb855140042ab761",class:"skip-section"},s("div",{key:"0b4a39d1599854d6c445e2c35dcc89a0e4970846",class:"skip-explanation"},"Si tu documento no tiene lado trasero, da clic en el botón para continuar con el proceso"),s("button",{key:"b52b47df390cc099c8847ca8a676270bb154294d",class:"skip-button",onClick:()=>this.skipBackCapture(),type:"button"},this.enableBackDocumentTimer&&this.backDocumentTimerRemaining>0?`Saltar reverso (${this.backDocumentTimerRemaining}s)`:"Saltar reverso")),t.isVideoActive&&s("div",{key:"f04e47749a25197c434b849844c67eadca5c6af3",class:"camera-controls"},s("button",{key:"82625eef057f59b6dac11c4443ccb315231eac7f",class:`camera-selector-button ${this.isSwitchingCamera?"loading":""}`,onClick:()=>this.toggleCameraSelector(),type:"button",title:"Seleccionar cámara",disabled:this.isSwitchingCamera},this.isSwitchingCamera?s("div",{class:"button-spinner"}):"Cámaras")),this.showCameraSelector&&e.availableCameras.length>0&&s("div",{key:"61cfb89cd9bb549cfff2cb70293db06ee6cdf06b",class:"camera-selector-dropdown"},s("div",{key:"60f751d8db7b305f2bdfdc089d2110bcff940150",class:"camera-selector-header"},s("span",{key:"9dae045a34cc06f323ff4850921b495fc845be47"},"Seleccionar Cámara"),s("button",{key:"4584d7964d91ddd7f3d980c3e5e90493530d33bd",class:"close-selector",onClick:()=>this.toggleCameraSelector(),type:"button"},"×")),s("div",{key:"9881f2b4fc6ffbdc76db06a7b49d060cefbe6277",class:"camera-list"},e.availableCameras.map((t=>s("button",{key:t.id,class:`camera-option ${e.selectedCameraId===t.id?"selected":""}`,onClick:()=>this.handleCameraSwitch(t.id),type:"button"},s("span",{class:"camera-label"},t.label||`Cámara ${e.availableCameras.indexOf(t)+1}`,t.hasAutofocus&&s("span",{class:"autofocus-icon",title:"Autofoco disponible"},"⦿")),e.selectedCameraId===t.id&&s("span",{class:"selected-indicator"},"✓"))))),s("div",{key:"3dfe9ffc7b4cc9afb199a78026cef6d4b469805e",class:"device-info"},s("small",{key:"bddc865a30469bd2724624b2f7c8f641f9d97a07"},"Dispositivo: ",e.deviceType)))),t.isCapturing&&s("div",{key:"2fd963e44f69f80d17c6bbbfa3c9b5e11bc816be",class:"capture-animation"}),t.showFlipAnimation&&s("div",{key:"ba4872ea5388a0ac3134be61feff5412373465ab",class:"flip-animation"},s("div",{key:"e83a92cea79f3e85aefc6964c5d9de7b495d511e",class:"id-card-icon"}),s("div",{key:"1d06b51fd6ad14d9b37aa6bca72bd13c951a386a",class:"flip-text"},"¡Voltea tu identificación!")),t.showSuccessAnimation&&s("div",{key:"503c377896d5fdc3ae8476b09f511d571f23ae72",class:"success-animation"},s("div",{key:"e1929c245b0d1479a6fb1513b0b37c53070c4291",class:"check-icon"}),s("div",{key:"024c897c70427b205390770fc3dfb999ffcc84d3",class:"success-text"},"¡Proceso completado!")),s("div",{key:"54e350707628e5c88ae2900e412e6bda2eace943",class:`component-status status-${this.currentStatus.type}`},(this.currentStatus.type==="loading"||this.currentStatus.type==="initializing")&&s("div",{key:"82ea10569ed46285686cf3e63885ca1941bb559c",class:"status-spinner"}),s("div",{key:"1fecf179c10965cccf1be3dc0a54afd377ba38ad",class:"status-content"},s("div",{key:"1b301c1bbb02e5cac2e6babcb20c190662d45c68",class:"status-message"},this.currentStatus.message),this.currentStatus.description&&s("div",{key:"5b6c61308d17176daade02c951a436d114a74100",class:"status-description"},this.currentStatus.description))),this.debug&&s("div",{key:"b8104db64208dc87a617a072957c007f28055194",class:"performance-monitor"},s("div",{key:"e66aec071f10821be2713858dcc251c04f480e63",class:"performance-expanded"},s("div",{key:"1ae09a91d0704ab21b9eb51097cf452fd5f44359",class:"metrics-row"},s("div",{key:"340d4d16d048a5217fe13d5de63618c9ea221165",class:"metric-compact"},s("span",{key:"20cfda14969ef70d232edd68f2e9902bd44b5d9a",class:"metric-label"},"FPS"),s("span",{key:"3a089c2814a71ed6513bf05b0120a66aa159daee",class:`metric-value ${this.performanceData.fps<15?"warning":this.performanceData.fps<10?"danger":"good"}`},this.performanceData.fps)),s("div",{key:"23f700def988c3220fc5df37aeb57a0a20ff56b3",class:"metric-compact"},s("span",{key:"441e8490a871469813a6d832114e03583d375e91",class:"metric-label"},"MEM"),s("span",{key:"51f7c49164c9d5e699141c92c88375fc99b312ed",class:`metric-value ${this.performanceData.memoryUsage>100?"warning":this.performanceData.memoryUsage>200?"danger":"good"}`},this.performanceData.memoryUsage,"MB"))),s("div",{key:"6547fee80e2a1db7c9ff889a1c478fc8248159e6",class:"metrics-row"},s("div",{key:"7b2d1642fd122ee0fbed36387afb23152afe10c2",class:"metric-compact"},s("span",{key:"a9137119bf7da366f18feaf8f28807ee40ad7a25",class:"metric-label"},"INF"),s("span",{key:"5cbc0c040102688f1039cdcd4bb58020248cf700",class:`metric-value ${this.performanceData.inferenceTime>100?"warning":this.performanceData.inferenceTime>200?"danger":"good"}`},this.performanceData.inferenceTime,"ms")),s("div",{key:"cb4a86f5da46e4081d997c8b8bb6a899f06dfcd2",class:"metric-compact"},s("span",{key:"88ad5e1d842eb156cf6813ecaa9d2bec76a5999e",class:"metric-label"},"FRAME"),s("span",{key:"a9b14cd98b64dcfc058d3b68a3c168a9e092fb3c",class:`metric-value ${this.performanceData.frameProcessingTime>50?"warning":this.performanceData.frameProcessingTime>100?"danger":"good"}`},this.performanceData.frameProcessingTime,"ms"))),s("div",{key:"86e01f3596682cb8ad2ff5464748e6ecb7db374a",class:"metrics-row"},s("div",{key:"e73b9d39e9bcbc5d46fa0ba0a737700e3e5566d9",class:"metric-compact"},s("span",{key:"8ecfe969dfe77c87d9da76d7390706014b4872f3",class:"metric-label"},"DET"),s("span",{key:"bd1a6a52e0bd1fb4d377413d7515e4e0f00da10f",class:"metric-value good"},this.performanceData.successfulDetections,"/",this.performanceData.totalDetections)),s("div",{key:"36539ae98787fd60642082db1bf89031003c4bef",class:"metric-compact"},s("span",{key:"7f3a81629c09053e3beeca97f485da0f60412052",class:"metric-label"},"RATE"),s("span",{key:"72399e0ac39270c82b265ce64e402f84cda9fb2c",class:`metric-value ${this.performanceData.detectionRate<30?"danger":this.performanceData.detectionRate<60?"warning":"good"}`},this.performanceData.detectionRate,"%"))))),s("div",{key:"4e3a914ba2f5993f85de7b9dd6dc93d76b41c96d",class:"watermark"},s("img",{key:"aa634c2ba2090f64ee9b41aa1d75a9114d46fd63",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 s=this.detectionContainer.parentElement;const a=s.getBoundingClientRect();const o=a.width;const r=a.height;if(e===0||i===0)return;const n=e/i;const c=o/r;let d,l;let h=0,f=0;if(n>c){d=o;l=o/n;f=(r-l)/2}else{l=r;d=r*n;h=(o-d)/2}const p=320;const u=d/p;const m=l/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 s=this.el.shadowRoot?.querySelector(".side-top");const a=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}}s?.classList.toggle("aligned",c.top);a?.classList.toggle("aligned",c.right);o?.classList.toggle("aligned",c.bottom);r?.classList.toggle("aligned",c.left);const d=this.detectionService.areAllSidesAligned(c);const l=this.stateManager.getCaptureState();if(l.step==="back"&&this.enableBackDocumentTimer&&n){const t=c.top||c.right||c.bottom||c.left;if(t){this.startBackDocumentTimer()}}if(d&&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 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 s=this.videoRef.videoWidth/i;const a=this.videoRef.videoHeight/i;const o=Math.max(0,this.lastDetectedBox.x*s-this.cropMargin);const r=Math.max(0,this.lastDetectedBox.y*a-this.cropMargin);const n=Math.min(this.lastDetectedBox.w*s+2*this.cropMargin,this.videoRef.videoWidth-o);const c=Math.min(this.lastDetectedBox.h*a+2*this.cropMargin,this.videoRef.videoHeight-r);const d=this.getPooledCanvas(n,c);const l=d.getContext("2d",{alpha:false});l.clearRect(0,0,d.width,d.height);l.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:d.toDataURL("image/png")}});if(this.useDocumentClassification){const t=await this.detectionService.classifyDocument(d);if(t&&t.class==="passport"){this.completeProcess(true);return}}this.stateManager.updateCaptureState({step:"back",isDetectionPaused:true,showFlipAnimation:true});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:d.toDataURL("image/png")}});this.completeProcess(false)}this.returnCanvasToPool(t);this.returnCanvasToPool(d)}triggerCaptureAnimation(){const t=this.el.shadowRoot?.querySelector(".card-outline");t?.classList.add("capturing");setTimeout((()=>{this.stateManager.updateCaptureState({isCapturing:false});t?.classList.remove("capturing")}),600)}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)}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;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}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 s=document.createElement("canvas");s.width=t;s.height=e;return s}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-39560f23.entry.js.map