@jaak.ai/stamps 2.0.0-dev.27 → 2.0.0-dev.29

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.
@@ -78,34 +78,65 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
78
78
  CONFIDENCE_THRESHOLD = 0.6;
79
79
  // ISO/IEC 7810 ID-1 standard dimensions (85.60mm x 53.98mm)
80
80
  ID1_ASPECT_RATIO = 85.60 / 53.98; // 1.5863320574...
81
- debugLog(...args) {
82
- if (this.debug) {
83
- console.log(...args);
81
+ logger = {
82
+ info: (...args) => {
83
+ if (this.debug) {
84
+ console.log(`[JAAK-STAMPS] [INFO] [${new Date().toLocaleTimeString()}]`, ...args);
85
+ }
86
+ },
87
+ warn: (...args) => {
88
+ if (this.debug) {
89
+ console.warn(`[JAAK-STAMPS] [WARN] [${new Date().toLocaleTimeString()}]`, ...args);
90
+ }
91
+ },
92
+ error: (...args) => {
93
+ if (this.debug) {
94
+ console.error(`[JAAK-STAMPS] [ERROR] [${new Date().toLocaleTimeString()}]`, ...args);
95
+ }
96
+ },
97
+ debug: (...args) => {
98
+ if (this.debug) {
99
+ console.debug(`[JAAK-STAMPS] [DEBUG] [${new Date().toLocaleTimeString()}]`, ...args);
100
+ }
101
+ },
102
+ state: (state, data) => {
103
+ if (this.debug) {
104
+ console.log(`[JAAK-STAMPS] [STATE] [${new Date().toLocaleTimeString()}] ${state}`, data || '');
105
+ }
106
+ },
107
+ performance: (operation, duration) => {
108
+ if (this.debug) {
109
+ console.log(`[JAAK-STAMPS] [PERF] [${new Date().toLocaleTimeString()}] ${operation}: ${duration}ms`);
110
+ }
84
111
  }
85
- }
112
+ };
86
113
  validateMaskSize() {
87
114
  if (this.maskSize < 50 || this.maskSize > 100) {
88
- console.warn(`maskSize debe estar entre 50 y 100. Valor actual: ${this.maskSize}. Usando valor por defecto: 90`);
115
+ this.logger.warn(`Propiedad maskSize inválida. Valor: ${this.maskSize}, esperado: 50-100. Usando valor por defecto: 90`);
89
116
  this.maskSize = 90;
90
117
  }
91
118
  }
92
119
  validateCropMargin() {
93
120
  if (this.cropMargin < 0 || this.cropMargin > 100) {
94
- console.warn(`cropMargin debe estar entre 0 y 100. Valor actual: ${this.cropMargin}. Usando valor por defecto: 0`);
121
+ this.logger.warn(`Propiedad cropMargin inválida. Valor: ${this.cropMargin}, esperado: 0-100. Usando valor por defecto: 0`);
95
122
  this.cropMargin = 0;
96
123
  }
97
124
  }
98
125
  validatePreferredCamera() {
99
126
  const validOptions = ['auto', 'front', 'back'];
100
127
  if (!validOptions.includes(this.preferredCamera)) {
101
- console.warn(`preferredCamera debe ser uno de: ${validOptions.join(', ')}. Valor actual: ${this.preferredCamera}. Usando valor por defecto: 'auto'`);
128
+ this.logger.warn(`Propiedad preferredCamera inválida. Valor: ${this.preferredCamera}, esperado: ${validOptions.join(', ')}. Usando valor por defecto: 'auto'`);
102
129
  this.preferredCamera = 'auto';
103
130
  }
104
131
  }
105
132
  emitReadyEvent() {
106
133
  const isDocumentReady = !!window.ort && this.isModelPreloaded;
107
134
  this.isReady.emit(isDocumentReady);
108
- this.debugLog('🟢 isReady event emitted:', isDocumentReady);
135
+ this.logger.state('COMPONENTE_LISTO', {
136
+ ortLibraryLoaded: !!window.ort,
137
+ modelPreloaded: this.isModelPreloaded,
138
+ isReady: isDocumentReady
139
+ });
109
140
  }
110
141
  isRearCamera(stream) {
111
142
  const videoTrack = stream.getVideoTracks()[0];
@@ -128,7 +159,11 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
128
159
  else {
129
160
  this.deviceType = 'desktop';
130
161
  }
131
- this.debugLog('📱 Device type detected:', this.deviceType);
162
+ this.logger.state('DISPOSITIVO_DETECTADO', {
163
+ deviceType: this.deviceType,
164
+ userAgent: navigator.userAgent,
165
+ screenDimensions: { width: window.innerWidth, height: window.innerHeight }
166
+ });
132
167
  // Enumerate available cameras
133
168
  await this.enumerateAndDetectCameras();
134
169
  // Load user preference
@@ -139,7 +174,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
139
174
  // First, check if we have permission to enumerate devices
140
175
  const permissionStatus = await this.checkCameraPermission();
141
176
  if (permissionStatus === 'denied') {
142
- this.debugLog(' Camera permission denied');
177
+ this.logger.error('Permiso de cámara denegado por el usuario');
143
178
  this.statusMessage = "Permiso de cámara denegado";
144
179
  this.statusColor = "#ff6b6b";
145
180
  return;
@@ -153,7 +188,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
153
188
  const devices = await navigator.mediaDevices.enumerateDevices();
154
189
  this.availableCameras = devices.filter(device => device.kind === 'videoinput');
155
190
  this.isMultipleCamerasAvailable = this.availableCameras.length > 1;
156
- this.debugLog('📹 Available cameras:', {
191
+ this.logger.state('CAMARAS_DETECTADAS', {
157
192
  count: this.availableCameras.length,
158
193
  isMultipleCamerasAvailable: this.isMultipleCamerasAvailable,
159
194
  cameras: this.availableCameras.map(cam => ({
@@ -165,7 +200,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
165
200
  this.setInitialCameraPreference();
166
201
  }
167
202
  catch (error) {
168
- this.debugLog('Error enumerating cameras:', error);
203
+ this.logger.error('Error al enumerar cámaras disponibles:', error);
169
204
  this.handleCameraPermissionError(error);
170
205
  }
171
206
  }
@@ -178,7 +213,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
178
213
  return permission.state;
179
214
  }
180
215
  catch (error) {
181
- this.debugLog('⚠️ Could not check camera permission:', error);
216
+ this.logger.warn('No se pudo verificar permisos de cámara:', error);
182
217
  return 'prompt';
183
218
  }
184
219
  }
@@ -221,11 +256,11 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
221
256
  !camera.label.toLowerCase().includes('back') && !camera.label.toLowerCase().includes('rear'));
222
257
  if (frontCamera) {
223
258
  this.selectedCameraId = frontCamera.deviceId;
224
- this.debugLog('👤 User selected front camera:', frontCamera.label);
259
+ this.logger.state('CAMARA_FRONTAL_SELECCIONADA', { label: frontCamera.label, deviceId: frontCamera.deviceId });
225
260
  }
226
261
  else {
227
262
  this.selectedCameraId = this.availableCameras[0].deviceId;
228
- this.debugLog('⚠️ Front camera not found, using first available:', this.availableCameras[0].label);
263
+ this.logger.warn('Cámara frontal no encontrada, usando primera disponible:', this.availableCameras[0].label);
229
264
  }
230
265
  }
231
266
  else if (this.preferredCamera === 'back') {
@@ -236,11 +271,11 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
236
271
  camera.label.toLowerCase().includes('environment'));
237
272
  if (backCamera) {
238
273
  this.selectedCameraId = backCamera.deviceId;
239
- this.debugLog('📷 User selected back camera:', backCamera.label);
274
+ this.logger.state('CAMARA_TRASERA_SELECCIONADA', { label: backCamera.label, deviceId: backCamera.deviceId });
240
275
  }
241
276
  else {
242
277
  this.selectedCameraId = this.availableCameras[0].deviceId;
243
- this.debugLog('⚠️ Back camera not found, using first available:', this.availableCameras[0].label);
278
+ this.logger.warn('Cámara trasera no encontrada, usando primera disponible:', this.availableCameras[0].label);
244
279
  }
245
280
  }
246
281
  else {
@@ -253,17 +288,17 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
253
288
  camera.label.toLowerCase().includes('environment'));
254
289
  if (rearCamera) {
255
290
  this.selectedCameraId = rearCamera.deviceId;
256
- this.debugLog('📱 Auto-selected rear camera for mobile:', rearCamera.label);
291
+ this.logger.state('CAMARA_AUTO_SELECCIONADA_MOBILE', { type: 'rear', label: rearCamera.label, deviceId: rearCamera.deviceId });
257
292
  }
258
293
  else {
259
294
  this.selectedCameraId = this.availableCameras[0].deviceId;
260
- this.debugLog('📱 Rear camera not found, using first available:', this.availableCameras[0].label);
295
+ this.logger.warn('Cámara trasera no encontrada en mobile, usando primera disponible:', this.availableCameras[0].label);
261
296
  }
262
297
  }
263
298
  else {
264
299
  // For desktop, use first available camera (usually the only one)
265
300
  this.selectedCameraId = this.availableCameras[0].deviceId;
266
- this.debugLog('💻 Auto-selected desktop camera:', this.availableCameras[0].label);
301
+ this.logger.state('CAMARA_AUTO_SELECCIONADA_DESKTOP', { label: this.availableCameras[0].label, deviceId: this.availableCameras[0].deviceId });
267
302
  }
268
303
  }
269
304
  }
@@ -277,12 +312,12 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
277
312
  if (isStillAvailable) {
278
313
  this.selectedCameraId = preference.cameraId;
279
314
  this.preferredCameraFacing = preference.facing;
280
- this.debugLog('💾 Loaded camera preference:', preference);
315
+ this.logger.state('PREFERENCIA_CAMARA_CARGADA', preference);
281
316
  }
282
317
  }
283
318
  }
284
319
  catch (error) {
285
- this.debugLog('⚠️ Error loading camera preference:', error);
320
+ this.logger.warn('Error al cargar preferencia de cámara:', error);
286
321
  }
287
322
  }
288
323
  saveCameraPreference() {
@@ -293,10 +328,10 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
293
328
  timestamp: Date.now()
294
329
  };
295
330
  localStorage.setItem('jaak-stamps-camera-preference', JSON.stringify(preference));
296
- this.debugLog('💾 Saved camera preference:', preference);
331
+ this.logger.state('PREFERENCIA_CAMARA_GUARDADA', preference);
297
332
  }
298
333
  catch (error) {
299
- this.debugLog('⚠️ Error saving camera preference:', error);
334
+ this.logger.warn('Error al guardar preferencia de cámara:', error);
300
335
  }
301
336
  }
302
337
  async switchCamera(cameraId) {
@@ -306,7 +341,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
306
341
  // Check if the selected camera is still available
307
342
  const selectedCamera = this.availableCameras.find(cam => cam.deviceId === cameraId);
308
343
  if (!selectedCamera) {
309
- this.debugLog(' Selected camera not found, re-enumerating...');
344
+ this.logger.warn('Cámara seleccionada no encontrada, re-enumerando dispositivos...');
310
345
  await this.enumerateAndDetectCameras();
311
346
  return;
312
347
  }
@@ -330,10 +365,10 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
330
365
  this.saveCameraPreference();
331
366
  // Setup new camera with error handling
332
367
  await this.setupCameraWithRetry();
333
- this.debugLog('🔄 Switched to camera:', selectedCamera.label);
368
+ this.logger.state('CAMARA_CAMBIADA', { label: selectedCamera.label, deviceId: selectedCamera.deviceId });
334
369
  }
335
370
  catch (error) {
336
- this.debugLog('Error switching camera:', error);
371
+ this.logger.error('Error al cambiar de cámara:', error);
337
372
  this.handleCameraPermissionError(error);
338
373
  }
339
374
  }
@@ -348,7 +383,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
348
383
  return; // Success
349
384
  }
350
385
  catch (error) {
351
- this.debugLog(`❌ Camera setup attempt ${attempt} failed:`, error);
386
+ this.logger.error(`Intento ${attempt} de configuración de cámara fallido:`, error);
352
387
  if (attempt === maxRetries) {
353
388
  // Last attempt failed, handle the error
354
389
  this.statusMessage = "Error al configurar la cámara";
@@ -368,7 +403,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
368
403
  }
369
404
  toggleCameraSelector() {
370
405
  this.showCameraSelector = !this.showCameraSelector;
371
- this.debugLog('📹 Camera selector toggled:', {
406
+ this.logger.state('SELECTOR_CAMARA_TOGGLE', {
372
407
  showCameraSelector: this.showCameraSelector,
373
408
  isMultipleCamerasAvailable: this.isMultipleCamerasAvailable,
374
409
  availableCameras: this.availableCameras.length,
@@ -384,6 +419,13 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
384
419
  await this.switchCamera(nextCamera.deviceId);
385
420
  }
386
421
  async componentDidLoad() {
422
+ this.logger.state('COMPONENTE_INICIALIZANDO', {
423
+ debug: this.debug,
424
+ maskSize: this.maskSize,
425
+ cropMargin: this.cropMargin,
426
+ useDocumentClassification: this.useDocumentClassification,
427
+ preferredCamera: this.preferredCamera
428
+ });
387
429
  if (this.debug) {
388
430
  // Show detailed initialization loading state only in debug mode
389
431
  this.isLoading = true;
@@ -448,7 +490,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
448
490
  this.canvasRef.height = rect.height;
449
491
  // Update mask positioning based on container and video dimensions
450
492
  this.updateMaskDimensions(rect);
451
- this.debugLog('📐 Canvas resized:', { width: rect.width, height: rect.height });
493
+ this.logger.debug('Canvas redimensionado:', { width: rect.width, height: rect.height });
452
494
  }
453
495
  }
454
496
  updateMaskDimensions(containerRect) {
@@ -508,7 +550,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
508
550
  this.el.style.setProperty('--mask-center-y', `${videoCenterYPercent}%`);
509
551
  // Mark mask as ready now that dimensions are calculated
510
552
  this.isMaskReady = true;
511
- this.debugLog('🎯 Mask dimensions updated:', {
553
+ this.logger.state('DIMENSIONES_MASCARA_ACTUALIZADAS', {
512
554
  video: { width: videoWidth, height: videoHeight },
513
555
  displayed: { width: displayedVideoWidth, height: displayedVideoHeight },
514
556
  mask: { widthPercent: maskWidthPercent, heightPercent: maskHeightPercent },
@@ -530,7 +572,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
530
572
  this.captureCtx = this.captureCanvas.getContext('2d', {
531
573
  alpha: false
532
574
  });
533
- this.debugLog('🎨 Canvas pool initialized for performance');
575
+ this.logger.state('CANVAS_POOL_INICIALIZADO', { preprocessCanvasSize: this.INPUT_SIZE });
534
576
  }
535
577
  disconnectedCallback() {
536
578
  this.cleanup();
@@ -578,7 +620,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
578
620
  }
579
621
  async preloadModel() {
580
622
  if (this.isModelPreloaded || this.session) {
581
- this.debugLog('🚀 Model already preloaded or session exists');
623
+ this.logger.state('MODELO_YA_PRECARGADO', { sessionExists: !!this.session, modelPreloaded: this.isModelPreloaded });
582
624
  return { success: true, message: 'Model already loaded' };
583
625
  }
584
626
  try {
@@ -586,12 +628,39 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
586
628
  this.statusMessage = "Precargando modelos...";
587
629
  this.statusColor = "#007bff";
588
630
  const modelPath = this.MODEL_PATH;
589
- this.debugLog('🤖 Preloading detection model:', modelPath);
631
+ this.logger.state('PRECARGANDO_MODELO_DETECCION', { modelPath });
590
632
  // Configure ONNX Runtime with device-specific optimizations
591
633
  const sessionOptions = this.getSessionOptions();
592
- this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
634
+ const deviceInfo = this.getDeviceMemoryInfo();
635
+ try {
636
+ this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
637
+ }
638
+ catch (error) {
639
+ if (error.message.includes('failed to allocate a buffer')) {
640
+ this.logger.warn('Fallo en asignación de buffer durante precarga, intentando con configuración mínima');
641
+ const fallbackOptions = {
642
+ executionProviders: ['wasm'],
643
+ graphOptimizationLevel: 'disabled',
644
+ logSeverityLevel: 4,
645
+ enableCpuMemArena: false,
646
+ enableMemPattern: false,
647
+ executionMode: 'sequential',
648
+ interOpNumThreads: 1,
649
+ intraOpNumThreads: 1,
650
+ };
651
+ this.session = await window.ort.InferenceSession.create(modelPath, fallbackOptions);
652
+ }
653
+ else {
654
+ throw error;
655
+ }
656
+ }
593
657
  // Preload MobileNet model and classes only if classification is enabled
658
+ // For low memory devices, load sequentially to avoid memory pressure
594
659
  if (this.useDocumentClassification) {
660
+ if (deviceInfo.isLowMemory) {
661
+ this.logger.state('CARGA_SECUENCIAL_MODELOS', { reason: 'low memory device' });
662
+ await new Promise(resolve => setTimeout(resolve, 1000));
663
+ }
595
664
  await this.loadMobileNetModel();
596
665
  }
597
666
  this.isModelPreloaded = true;
@@ -599,11 +668,15 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
599
668
  this.statusMessage = "Modelos precargados. Listo para comenzar detección";
600
669
  this.statusColor = "#28a745";
601
670
  this.emitReadyEvent();
602
- this.debugLog(' Models preloaded successfully');
671
+ this.logger.state('MODELOS_PRECARGADOS_EXITOSAMENTE', {
672
+ detectionModel: !!this.session,
673
+ classificationModel: !!this.mobileNetSession,
674
+ useClassification: this.useDocumentClassification
675
+ });
603
676
  return { success: true, message: 'Models preloaded successfully' };
604
677
  }
605
678
  catch (error) {
606
- this.debugLog('Error preloading models:', error);
679
+ this.logger.error('Error al precargar modelos:', error);
607
680
  this.isLoading = false;
608
681
  this.statusMessage = "Error al precargar los modelos";
609
682
  this.statusColor = "#ff6b6b";
@@ -631,7 +704,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
631
704
  }
632
705
  async setPreferredCamera(camera) {
633
706
  this.preferredCamera = camera;
634
- this.debugLog('🎯 Camera preference changed to:', camera);
707
+ this.logger.state('PREFERENCIA_CAMARA_CAMBIADA', { newPreference: camera });
635
708
  // Re-detect and apply new camera preference
636
709
  await this.enumerateAndDetectCameras();
637
710
  // If video is active, switch to the new preferred camera
@@ -646,21 +719,42 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
646
719
  }
647
720
  async loadMobileNetModel() {
648
721
  try {
649
- this.debugLog('🤖 Loading MobileNet model...');
722
+ this.logger.state('CARGANDO_MODELO_MOBILENET', { path: this.MOBILENET_MODEL_PATH });
650
723
  // Load class map
651
724
  const classResponse = await fetch(this.MOBILENET_CLASSES_PATH);
652
725
  if (!classResponse.ok) {
653
726
  throw new Error(`Failed to load class map: ${this.MOBILENET_CLASSES_PATH}`);
654
727
  }
655
728
  this.mobileNetClassMap = await classResponse.json();
656
- this.debugLog('📋 MobileNet classes loaded:', this.mobileNetClassMap);
729
+ this.logger.state('CLASES_MOBILENET_CARGADAS', { classCount: Object.keys(this.mobileNetClassMap).length });
657
730
  // Load model
658
731
  const sessionOptions = this.getSessionOptions();
659
- this.mobileNetSession = await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH, sessionOptions);
660
- this.debugLog('✅ MobileNet model loaded successfully');
732
+ try {
733
+ this.mobileNetSession = await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH, sessionOptions);
734
+ }
735
+ catch (error) {
736
+ if (error.message.includes('failed to allocate a buffer')) {
737
+ this.logger.warn('Fallo en asignación de buffer de MobileNet, intentando con configuración mínima');
738
+ const fallbackOptions = {
739
+ executionProviders: ['wasm'],
740
+ graphOptimizationLevel: 'disabled',
741
+ logSeverityLevel: 4,
742
+ enableCpuMemArena: false,
743
+ enableMemPattern: false,
744
+ executionMode: 'sequential',
745
+ interOpNumThreads: 1,
746
+ intraOpNumThreads: 1,
747
+ };
748
+ this.mobileNetSession = await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH, fallbackOptions);
749
+ }
750
+ else {
751
+ throw error;
752
+ }
753
+ }
754
+ this.logger.state('MODELO_MOBILENET_CARGADO_EXITOSAMENTE', { sessionCreated: !!this.mobileNetSession });
661
755
  }
662
756
  catch (error) {
663
- this.debugLog('Error loading MobileNet model:', error);
757
+ this.logger.error('Error al cargar modelo MobileNet:', error);
664
758
  throw error;
665
759
  }
666
760
  }
@@ -687,11 +781,11 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
687
781
  }
688
782
  async classifyDocument(canvas) {
689
783
  if (!this.mobileNetSession || !this.mobileNetClassMap) {
690
- this.debugLog('⚠️ MobileNet model not loaded');
784
+ this.logger.warn('Modelo MobileNet no está cargado, saltando clasificación');
691
785
  return null;
692
786
  }
693
787
  try {
694
- this.debugLog('🔍 Classifying document...');
788
+ this.logger.state('CLASIFICANDO_DOCUMENTO', { timestamp: Date.now() });
695
789
  // Preprocess image for MobileNet
696
790
  const inputTensor = this.preprocessMobileNet(canvas);
697
791
  // Run inference
@@ -702,10 +796,11 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
702
796
  const maxIdx = output.reduce((bestIdx, val, idx, arr) => val > arr[bestIdx] ? idx : bestIdx, 0);
703
797
  const confidence = output[maxIdx];
704
798
  const className = this.mobileNetClassMap[maxIdx.toString()] || "unknown";
705
- this.debugLog('📄 Document classification result:', {
799
+ this.logger.state('DOCUMENTO_CLASIFICADO', {
706
800
  class: className,
707
801
  confidence: confidence.toFixed(3),
708
- classIndex: maxIdx
802
+ classIndex: maxIdx,
803
+ timestamp: Date.now()
709
804
  });
710
805
  return {
711
806
  class: className,
@@ -714,7 +809,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
714
809
  };
715
810
  }
716
811
  catch (error) {
717
- this.debugLog('Error classifying document:', error);
812
+ this.logger.error('Error al clasificar documento:', error);
718
813
  return null;
719
814
  }
720
815
  }
@@ -756,7 +851,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
756
851
  }
757
852
  this.mobileNetClassMap = undefined;
758
853
  this.isModelPreloaded = false;
759
- this.debugLog('🧹 Canvas pool cleaned up');
854
+ this.logger.state('CANVAS_POOL_LIMPIADO', { timestamp: Date.now() });
760
855
  }
761
856
  async getMaxResolution() {
762
857
  try {
@@ -805,18 +900,19 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
805
900
  constraints.width = { ideal: maxWidth };
806
901
  constraints.height = { ideal: maxHeight };
807
902
  }
808
- this.debugLog('📐 Resolution capabilities:', {
903
+ this.logger.state('CAPACIDADES_RESOLUCION_DETECTADAS', {
809
904
  maxWidth: capabilities.width.max,
810
905
  maxHeight: capabilities.height.max,
811
906
  selectedWidth: constraints.width.ideal,
812
907
  selectedHeight: constraints.height.ideal,
813
- isTablet
908
+ isTablet,
909
+ deviceType: this.deviceType
814
910
  });
815
911
  }
816
912
  return constraints;
817
913
  }
818
914
  catch (err) {
819
- this.debugLog('⚠️ Could not get capabilities, using fallback');
915
+ this.logger.warn('No se pudieron obtener capacidades de cámara, usando configuración de respaldo');
820
916
  // Optimized fallback for tablets
821
917
  const isTablet = /iPad|Android/i.test(navigator.userAgent) && window.innerWidth >= 768;
822
918
  const fallbackConstraints = {
@@ -849,8 +945,11 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
849
945
  // Determine if video should be mirrored
850
946
  const isRear = this.isRearCamera(stream);
851
947
  this.shouldMirrorVideo = !isRear;
852
- this.debugLog('📹 Rear camera:', isRear);
853
- this.debugLog('🪞 Should mirror video:', this.shouldMirrorVideo);
948
+ this.logger.state('CAMARA_CONFIGURADA', {
949
+ isRearCamera: isRear,
950
+ shouldMirrorVideo: this.shouldMirrorVideo,
951
+ videoActive: this.isVideoActive
952
+ });
854
953
  return new Promise((resolve) => {
855
954
  this.videoRef.onloadedmetadata = async () => {
856
955
  await this.videoRef.play();
@@ -867,7 +966,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
867
966
  }
868
967
  }
869
968
  catch (err) {
870
- this.debugLog("❌ No se pudo acceder a la cámara:", err);
969
+ this.logger.error('No se pudo acceder a la cámara:', err);
871
970
  this.handleCameraPermissionError(err);
872
971
  }
873
972
  }
@@ -891,15 +990,39 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
891
990
  const transposedData = new Float32Array(R.concat(G, B));
892
991
  return new window.ort.Tensor("float32", transposedData, [1, 3, this.INPUT_SIZE, this.INPUT_SIZE]);
893
992
  }
993
+ getDeviceMemoryInfo() {
994
+ const nav = navigator;
995
+ const memory = nav.deviceMemory || nav.hardwareConcurrency || 4;
996
+ const connection = nav.connection || nav.mozConnection || nav.webkitConnection;
997
+ const isSlowConnection = connection && (connection.effectiveType === 'slow-2g' || connection.effectiveType === '2g');
998
+ return {
999
+ estimatedRAM: memory,
1000
+ isLowMemory: memory <= 4,
1001
+ isSlowConnection: isSlowConnection
1002
+ };
1003
+ }
894
1004
  getSessionOptions() {
1005
+ const deviceInfo = this.getDeviceMemoryInfo();
1006
+ if (deviceInfo.isLowMemory) {
1007
+ return {
1008
+ executionProviders: ['wasm'],
1009
+ graphOptimizationLevel: 'basic',
1010
+ logSeverityLevel: 4,
1011
+ logVerbosityLevel: 0,
1012
+ enableCpuMemArena: false,
1013
+ enableMemPattern: false,
1014
+ executionMode: 'sequential',
1015
+ interOpNumThreads: 1,
1016
+ intraOpNumThreads: 1,
1017
+ };
1018
+ }
895
1019
  return {
896
1020
  executionProviders: [
897
- // Try WebGL first for GPU acceleration, fallback to WASM
898
1021
  'webgl',
899
1022
  'wasm'
900
1023
  ],
901
- graphOptimizationLevel: 'all', // Maximum optimization
902
- logSeverityLevel: this.debug ? 2 : 4, // Reduce logging overhead in production
1024
+ graphOptimizationLevel: 'all',
1025
+ logSeverityLevel: this.debug ? 2 : 4,
903
1026
  logVerbosityLevel: 0,
904
1027
  enableCpuMemArena: true,
905
1028
  enableMemPattern: true,
@@ -909,6 +1032,12 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
909
1032
  };
910
1033
  }
911
1034
  async startDetection() {
1035
+ this.logger.state('INICIANDO_DETECCION', {
1036
+ sessionExists: !!this.session,
1037
+ modelPreloaded: this.isModelPreloaded,
1038
+ videoActive: this.isVideoActive,
1039
+ captureStep: this.captureStep
1040
+ });
912
1041
  try {
913
1042
  // Check if model is already preloaded
914
1043
  if (!this.session) {
@@ -922,9 +1051,30 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
922
1051
  this.statusColor = "#007bff";
923
1052
  }
924
1053
  const modelPath = this.MODEL_PATH;
925
- this.debugLog('🤖 Loading detection model:', modelPath);
1054
+ this.logger.state('CARGANDO_MODELO_DETECCION', { modelPath });
926
1055
  const sessionOptions = this.getSessionOptions();
927
- this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
1056
+ try {
1057
+ this.session = await window.ort.InferenceSession.create(modelPath, sessionOptions);
1058
+ }
1059
+ catch (error) {
1060
+ if (error.message.includes('failed to allocate a buffer')) {
1061
+ this.logger.warn('Fallo en asignación de buffer, intentando con configuración mínima');
1062
+ const fallbackOptions = {
1063
+ executionProviders: ['wasm'],
1064
+ graphOptimizationLevel: 'disabled',
1065
+ logSeverityLevel: 4,
1066
+ enableCpuMemArena: false,
1067
+ enableMemPattern: false,
1068
+ executionMode: 'sequential',
1069
+ interOpNumThreads: 1,
1070
+ intraOpNumThreads: 1,
1071
+ };
1072
+ this.session = await window.ort.InferenceSession.create(modelPath, fallbackOptions);
1073
+ }
1074
+ else {
1075
+ throw error;
1076
+ }
1077
+ }
928
1078
  // Load MobileNet model if classification is enabled and not already loaded
929
1079
  if (this.useDocumentClassification && !this.mobileNetSession) {
930
1080
  if (this.debug) {
@@ -939,7 +1089,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
939
1089
  this.emitReadyEvent();
940
1090
  }
941
1091
  else {
942
- this.debugLog('🚀 Using preloaded models');
1092
+ this.logger.state('USANDO_MODELOS_PRECARGADOS', { sessionExists: !!this.session, modelPreloaded: this.isModelPreloaded });
943
1093
  if (this.debug) {
944
1094
  this.statusMessage = "Usando modelos precargados...";
945
1095
  this.statusColor = "#007bff";
@@ -958,7 +1108,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
958
1108
  this.detectFrame();
959
1109
  }
960
1110
  catch (err) {
961
- this.debugLog("Error al inicializar:", err);
1111
+ this.logger.error('Error al inicializar detección:', err);
962
1112
  this.statusMessage = "Error al inicializar el detector";
963
1113
  this.statusColor = "#ff6b6b";
964
1114
  this.isLoading = false;
@@ -1040,7 +1190,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
1040
1190
  }
1041
1191
  }
1042
1192
  catch (e) {
1043
- this.debugLog("Error en inferencia:", e);
1193
+ this.logger.error('Error en inferencia de modelo:', e);
1044
1194
  // Solo continuar si no hemos completado el proceso
1045
1195
  if (this.captureStep !== 'completed') {
1046
1196
  // On error, wait longer before retrying
@@ -1168,7 +1318,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
1168
1318
  if (!this.hasScreenshotTaken) {
1169
1319
  this.lastDetectedBox = bestBox;
1170
1320
  this.takeScreenshot().catch(error => {
1171
- this.debugLog('Error taking screenshot:', error);
1321
+ this.logger.error('Error al tomar captura de pantalla:', error);
1172
1322
  });
1173
1323
  this.hasScreenshotTaken = true;
1174
1324
  // Reset para permitir segunda captura
@@ -1186,6 +1336,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
1186
1336
  if (boxes.length === 0) {
1187
1337
  this.statusMessage = "Posicione la identificación dentro del marco";
1188
1338
  this.statusColor = "#ff6b6b";
1339
+ this.logger.debug('Sin detección de documento en el frame');
1189
1340
  }
1190
1341
  else {
1191
1342
  const bestBox = boxes.reduce((best, current) => current.score > best.score ? current : best);
@@ -1195,6 +1346,11 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
1195
1346
  if (allSidesAligned) {
1196
1347
  this.statusMessage = "Identificación perfectamente alineada. Mantenga inmóvil";
1197
1348
  this.statusColor = "#00ff00";
1349
+ this.logger.state('DOCUMENTO_PERFECTAMENTE_ALINEADO', {
1350
+ score: bestBox.score,
1351
+ boxDimensions: { width: bestBox.w, height: bestBox.h },
1352
+ alignedSides: 4
1353
+ });
1198
1354
  }
1199
1355
  else if (alignedSides > 0) {
1200
1356
  this.statusMessage = `Alinee los lados restantes (${alignedSides}/4 lados correctos)`;
@@ -1255,6 +1411,14 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
1255
1411
  async takeScreenshot() {
1256
1412
  if (!this.videoRef || !this.lastDetectedBox)
1257
1413
  return;
1414
+ this.logger.state('INICIANDO_CAPTURA', {
1415
+ captureStep: this.captureStep,
1416
+ detectedBox: this.lastDetectedBox,
1417
+ videoResolution: {
1418
+ width: this.videoRef.videoWidth,
1419
+ height: this.videoRef.videoHeight
1420
+ }
1421
+ });
1258
1422
  // Activar animación
1259
1423
  this.triggerCaptureAnimation();
1260
1424
  // OPTIMIZATION: Reuse capture canvas for full frame
@@ -1294,7 +1458,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
1294
1458
  await this.loadMobileNetModel();
1295
1459
  }
1296
1460
  catch (error) {
1297
- this.debugLog('⚠️ Failed to load classification model, continuing without classification:', error);
1461
+ this.logger.warn('Fallo al cargar modelo de clasificación, continuando sin clasificación:', error);
1298
1462
  }
1299
1463
  }
1300
1464
  // Classify the cropped document if model is available
@@ -1302,7 +1466,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
1302
1466
  const classification = await this.classifyDocument(croppedCanvas);
1303
1467
  if (classification && classification.class === 'passport') {
1304
1468
  // If it's a passport, skip back capture since passports don't have a back side
1305
- this.debugLog('📄 Passport detected - skipping back capture');
1469
+ this.logger.state('PASAPORTE_DETECTADO_SALTANDO_REVERSO', { classification: classification?.class });
1306
1470
  this.completeProcess(true);
1307
1471
  return;
1308
1472
  }
@@ -1323,14 +1487,23 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
1323
1487
  this.isDetectionPaused = false;
1324
1488
  }, 3000);
1325
1489
  }, 800);
1326
- this.debugLog('📸 FRENTE capturado. Esperando trasera...');
1490
+ this.logger.state('CAPTURA_FRENTE_COMPLETADA', {
1491
+ captureStep: this.captureStep,
1492
+ hasFullFrame: !!this.capturedFullFrame,
1493
+ hasCroppedId: !!this.capturedCroppedId
1494
+ });
1327
1495
  }
1328
1496
  else if (this.captureStep === 'back') {
1329
1497
  // Captura de la trasera usando canvas reutilizado
1330
1498
  this.capturedBackFullFrame = this.captureCanvas.toDataURL('image/png');
1331
1499
  this.capturedBackCroppedId = croppedCanvas.toDataURL('image/png');
1332
1500
  this.completeProcess(false);
1333
- this.debugLog('📸 TRASERA capturada. Proceso completado. Detector detenido. Imágenes emitidas.');
1501
+ this.logger.state('CAPTURA_TRASERA_COMPLETADA', {
1502
+ captureStep: this.captureStep,
1503
+ hasBackFullFrame: !!this.capturedBackFullFrame,
1504
+ hasBackCroppedId: !!this.capturedBackCroppedId,
1505
+ processCompleted: true
1506
+ });
1334
1507
  }
1335
1508
  }
1336
1509
  triggerCaptureAnimation() {
@@ -1354,7 +1527,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
1354
1527
  const ctx = this.canvasRef.getContext("2d");
1355
1528
  ctx.clearRect(0, 0, this.canvasRef.width, this.canvasRef.height);
1356
1529
  }
1357
- this.debugLog('🛑 Detector de identificación detenido');
1530
+ this.logger.state('DETECTOR_DETENIDO', { timestamp: Date.now() });
1358
1531
  }
1359
1532
  resetDetection() {
1360
1533
  this.bestScore = 0;
@@ -1393,6 +1566,13 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
1393
1566
  "Proceso completado (solo frente capturado)" :
1394
1567
  "Proceso de captura completado exitosamente";
1395
1568
  this.statusColor = "#28a745";
1569
+ this.logger.state('PROCESO_COMPLETADO', {
1570
+ skippedBack,
1571
+ hasFrontImages: !!(this.capturedFullFrame && this.capturedCroppedId),
1572
+ hasBackImages: !!(this.capturedBackFullFrame && this.capturedBackCroppedId),
1573
+ totalImages: skippedBack ? 2 : 4,
1574
+ timestamp: new Date().toISOString()
1575
+ });
1396
1576
  // Detener el detector
1397
1577
  this.stopDetection();
1398
1578
  // Emitir evento con las imágenes capturadas
@@ -1444,7 +1624,7 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
1444
1624
  this.cleanup();
1445
1625
  }
1446
1626
  render() {
1447
- return (h("div", { key: '86ff6966e69804bea4faef5a9201480bd7ef5b9a', class: "detector-container" }, h("div", { key: 'aaed4a078d4eff98674f2163a56a1596782612bd', class: "video-container" }, h("video", { key: '6ae6a7c626c9b2b6e6915c826517d1365205b3a0', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: this.isVideoActive ? 'block' : 'none' } }), h("canvas", { key: 'c8666e4b4814e633155be738e23ada098fb3be93', ref: el => this.canvasRef = el, class: this.shouldMirrorVideo ? 'mirror' : '' }), this.isMaskReady && (h("div", { key: '968bcd21315afcf054f881647723299e7e57c29b', class: "overlay-mask" }, h("div", { key: '77f8a331f3d9e19b35c11b6c23b06420cbab9fd5', class: "card-outline" }, h("div", { key: '9d0164e7b2dcf6392471151c236127cd57507512', class: "side side-top" }), h("div", { key: '05a003eb49d25c72644aea2511b6519c5241ffb4', class: "side side-right" }), h("div", { key: 'a561ae9a94eb78aacfc24bac717164b3e22f41e5', class: "side side-bottom" }), h("div", { key: '81d64e5b58032c14062fc8efdee417db7f8a9f12', class: "side side-left" }), h("div", { key: '03c02e2c4c73c525965e34c7c47bb74f769d577f', class: "corner corner-tl" }), h("div", { key: '84780aec021ec4e0c7d38f6a659be765c4604ed5', class: "corner corner-tr" }), h("div", { key: '1ea67789c5a38cbc790f911f8f06b55c866d3927', class: "corner corner-bl" }), h("div", { key: 'e0e1999b0c5c37451850203eed4dbc2ff5834261', class: "corner corner-br" }), !this.showFlipAnimation && !this.showSuccessAnimation && (h("div", { key: '4909eb28d62b1674436c148ef46cd05a35ff8ec8', class: "guide-text" }, this.statusMessage))), this.captureStep === 'back' && !this.showFlipAnimation && !this.showSuccessAnimation && (h("button", { key: '5a971c2121cf9962719ad89fc45530b8acccb550', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, "Saltar reverso")), this.isVideoActive && (h("div", { key: '109e5885c49212f89d5678d9c9716ebd48614126', class: "camera-controls" }, this.isMultipleCamerasAvailable && (h("button", { key: '7c8ce2cd775c0646c80378cd0ad1f70243443ddf', class: "flip-camera-button", onClick: () => this.flipCamera(), type: "button", title: "Cambiar c\u00E1mara" }, "Girar c\u00E1mara")), h("button", { key: '5d3d066ba7e317fdc33878eeb9f2f7d28c6f65dc', class: "camera-selector-button", onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara" }, "C\u00E1maras"), this.debug && (h("div", { key: '4cbc284f2efbcb90ef91ea2e064bf0aa1e7980af', style: {
1627
+ return (h("div", { key: '87e2e2065012b5792b52b18349490492b5bdc80c', class: "detector-container" }, h("div", { key: '04b8bba38297d39c84ddc01f5a9bf72c65b9bef4', class: "video-container" }, h("video", { key: '905b99e1670fccb2ff5555818f91d0b0241fa29d', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: this.isVideoActive ? 'block' : 'none' } }), h("canvas", { key: '3f219b649b8d4f961b15256b8586451c2a737eb8', ref: el => this.canvasRef = el, class: this.shouldMirrorVideo ? 'mirror' : '' }), this.isMaskReady && (h("div", { key: 'f8d6742689d4446897ca48c2407cb3d3fab643e9', class: "overlay-mask" }, h("div", { key: '630a06c530f168cc0b71286adbf48fd922eb710d', class: "card-outline" }, h("div", { key: 'ce8c043ad41d5574cd0c4d737dec08b9f7fee927', class: "side side-top" }), h("div", { key: 'e90ead592f84e5df98143bc88714e70f32684204', class: "side side-right" }), h("div", { key: '31d6778c5036e42a3addb26c732149abc5a18ef7', class: "side side-bottom" }), h("div", { key: 'f85c31e77f024f9070c706b06b91d62a7fdbc357', class: "side side-left" }), h("div", { key: '27b362711bc53019483c0d36742d97e10ae9b9ce', class: "corner corner-tl" }), h("div", { key: '03b55893610684d690987c2eacf3c4e5d0c3bbe5', class: "corner corner-tr" }), h("div", { key: 'b6bf31327925c45a7fa8e1fd5ab2f25b824a03a2', class: "corner corner-bl" }), h("div", { key: '0737e0c82f8ad9703ce2546f3e594db6d50cafde', class: "corner corner-br" }), !this.showFlipAnimation && !this.showSuccessAnimation && (h("div", { key: '145f8383c496e151bd6ef4f5841292adeba083c4', class: "guide-text" }, this.statusMessage))), this.captureStep === 'back' && !this.showFlipAnimation && !this.showSuccessAnimation && (h("button", { key: 'fcdedebc31eddd21b978dd63e93c348d324b47da', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, "Saltar reverso")), this.isVideoActive && (h("div", { key: 'dc9157bf7bed3b6439db742055201e2c4eddec84', class: "camera-controls" }, this.isMultipleCamerasAvailable && (h("button", { key: '6b052562ccb203dbf3cc8b627f31ed2435559f80', class: "flip-camera-button", onClick: () => this.flipCamera(), type: "button", title: "Cambiar c\u00E1mara" }, "Girar c\u00E1mara")), h("button", { key: 'f9fad1757d01f0cb45f65bb2088bd1f0bc0e4e8d', class: "camera-selector-button", onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara" }, "C\u00E1maras"), this.debug && (h("div", { key: '5362fb33508c7f903b09f65fdb449b608804260d', style: {
1448
1628
  position: 'absolute',
1449
1629
  top: '50px',
1450
1630
  right: '0',
@@ -1454,10 +1634,10 @@ const JaakStamps$1 = /*@__PURE__*/ proxyCustomElement(class JaakStamps extends H
1454
1634
  fontSize: '10px',
1455
1635
  borderRadius: '4px',
1456
1636
  whiteSpace: 'nowrap'
1457
- } }, "C\u00E1maras: ", this.availableCameras.length, h("br", { key: 'df214515289add2cc73f989bfacb59069334a0e6' }), "M\u00FAltiples: ", this.isMultipleCamerasAvailable ? 'Sí' : 'No', h("br", { key: 'aa2b1784781b5b45d24139e2b6cc4865d9f3a00c' }), "Selector: ", this.showCameraSelector ? 'Visible' : 'Oculto', h("br", { key: 'fb95b2b58c9fb89f632d85a9271b7788d45a66c0' }), "Video: ", this.isVideoActive ? 'Activo' : 'Inactivo')))), this.showCameraSelector && this.availableCameras.length > 0 && (h("div", { key: 'ec1c90c5a6c84e3ef75724e7e600a60714545608', class: "camera-selector-dropdown" }, h("div", { key: 'ea118817b6563c78b7fbf5ee66af2e38a441a8b7', class: "camera-selector-header" }, h("span", { key: '52603259d50ffb7aa6ea5753762f0f0d018b39ff' }, "Seleccionar C\u00E1mara"), h("button", { key: '422ae0643f5d1451cf539b3a77becbf44904a484', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: 'd5acef7ba0b1645c52fb3ea7b3c64e70fa187a5f', class: "camera-list" }, this.availableCameras.map((camera) => (h("button", { key: camera.deviceId, class: `camera-option ${this.selectedCameraId === camera.deviceId ? 'selected' : ''}`, onClick: () => {
1637
+ } }, "C\u00E1maras: ", this.availableCameras.length, h("br", { key: '5ead451a54a59c885f62740d0a0ce43ba8b674e4' }), "M\u00FAltiples: ", this.isMultipleCamerasAvailable ? 'Sí' : 'No', h("br", { key: '9a92514d07576ed7052eaa3a418c00013ef7c479' }), "Selector: ", this.showCameraSelector ? 'Visible' : 'Oculto', h("br", { key: 'd06abebad3b2e3c19aa22e511e0c4cfd4425b8b2' }), "Video: ", this.isVideoActive ? 'Activo' : 'Inactivo')))), this.showCameraSelector && this.availableCameras.length > 0 && (h("div", { key: '93a09ce3bb108175b55944a71c21e86e58de55be', class: "camera-selector-dropdown" }, h("div", { key: '7ceb4c8826945ab2a9da106a88a44cbb5490e92a', class: "camera-selector-header" }, h("span", { key: 'fa98621700584d8021ff57eca6f804b6eb792c5b' }, "Seleccionar C\u00E1mara"), h("button", { key: 'ce6477a1494f58fb5974dd7c9e62bd7d041572c5', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: 'eff226b006c95fafce2566947155e13ee68f9a02', class: "camera-list" }, this.availableCameras.map((camera) => (h("button", { key: camera.deviceId, class: `camera-option ${this.selectedCameraId === camera.deviceId ? 'selected' : ''}`, onClick: () => {
1458
1638
  this.switchCamera(camera.deviceId);
1459
1639
  this.toggleCameraSelector();
1460
- }, type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${this.availableCameras.indexOf(camera) + 1}`), this.selectedCameraId === camera.deviceId && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: 'b670e7bf441559bf156874dbe3bbf83dbff2fa0d', class: "device-info" }, h("small", { key: '4d333925c1ff4197b6009414ed694b0a0eb06159' }, "Dispositivo: ", this.deviceType)))))), this.isCapturing && (h("div", { key: '21f7ea0e50575226daba8607ab4bccc5029aa179', class: "capture-animation" })), this.showFlipAnimation && (h("div", { key: 'c2350cc43d3a119391f62f2cf771ed5afcdb3558', class: "flip-animation" }, h("div", { key: 'a91de9e8662a4750555bce2a879b89f9216b8156', class: "id-card-icon" }), h("div", { key: 'def1c2534e1aae27e262deb6fd26a73ff0c8cb9b', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), this.showSuccessAnimation && (h("div", { key: 'acbbfb6d07e4f6bf343ff18af2d55979e76db3d4', class: "success-animation" }, h("div", { key: 'f5acd84325226e6b1ede1180335d7495a6b2d95e', class: "check-icon" }), h("div", { key: '393fd8300ce48e59bd3ef94f0e895abc3a938c1f', class: "success-text" }, "\u00A1Proceso completado!"))), this.isLoading && (h("div", { key: 'ce0d1baebab8bf0e18531a26b549f38e349a0d72', class: "loading-overlay" }, h("div", { key: '14c76fa00ddd814f37bd9c6dc57f761119886566', class: "loading-spinner" }), h("div", { key: '87ccb288f927e61ec126d83f44061699810c9e06', class: "loading-text" }, this.statusMessage))), this.debug && (h("div", { key: '943dff6e2772f2595a95116e8943866f97cada6e', class: "status-bar" }, h("div", { key: '00fe53b71ef94d51636259f106e4518df910848d', class: "status-message", style: { 'color': this.statusColor } }, this.statusMessage))), h("div", { key: '4c3bd150006473d9540fb1418f11f45fb96d1e56', class: "watermark" }, h("img", { key: 'c634701f52a4422c7be5b4007bf34ba4aeb4ebcc', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
1640
+ }, type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${this.availableCameras.indexOf(camera) + 1}`), this.selectedCameraId === camera.deviceId && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '617d33caa5d3b3e6dca56d479b27c0ac7ed19c2c', class: "device-info" }, h("small", { key: 'fba56ac1238c33864f8dba1d8bd9a5661e11d770' }, "Dispositivo: ", this.deviceType)))))), this.isCapturing && (h("div", { key: 'b46982a0b949ee9d50d0a819c59b24dceec9d7b2', class: "capture-animation" })), this.showFlipAnimation && (h("div", { key: 'c82773fffca8ec53949197a105e1e11bf0f9b294', class: "flip-animation" }, h("div", { key: 'ad52c9ec91132bf5ed94e36f621489a66b0bf680', class: "id-card-icon" }), h("div", { key: '2be407ee84beddc5ce968a9a94d9014f416cde54', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), this.showSuccessAnimation && (h("div", { key: 'f20b6be925178a123de99e535e893b7c09391dee', class: "success-animation" }, h("div", { key: 'd3ae65d40943f73bc92e9529764ded454adc5dbf', class: "check-icon" }), h("div", { key: 'f2b03082a106c69f09d384ba3b1cb4a636d3a189', class: "success-text" }, "\u00A1Proceso completado!"))), this.isLoading && (h("div", { key: '65736e303d9eb1c3f6f2dccb5cc0d27c571ac9c8', class: "loading-overlay" }, h("div", { key: '5863d855d1caea9202a9f3d0a29919985ddbb926', class: "loading-spinner" }), h("div", { key: 'aa5a16c96ac6bfa43846ba06346fad6dce39dfbb', class: "loading-text" }, this.statusMessage))), this.debug && (h("div", { key: '308c664b07d2c2427c38f766fc9eb78d27843f67', class: "status-bar" }, h("div", { key: '3884b311710d7f373a508eb492771e503e68f648', class: "status-message", style: { 'color': this.statusColor } }, this.statusMessage))), h("div", { key: '3125cfecda03d3ab9e80e0d9d5674f1cc167e2f8', class: "watermark" }, h("img", { key: '5ef43a18aea74f570db0d61f4fd86c3becf1d23e', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
1461
1641
  }
1462
1642
  static get style() { return myComponentCss; }
1463
1643
  }, [1, "jaak-stamps", {