@jaak.ai/stamps 2.2.0-dev.9 → 2.3.0-dev.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 (30) hide show
  1. package/README.md +188 -8
  2. package/dist/cjs/jaak-stamps.cjs.entry.js +124 -25
  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/collection/components/my-component/my-component.css +23 -2
  6. package/dist/collection/components/my-component/my-component.js +44 -16
  7. package/dist/collection/components/my-component/my-component.js.map +1 -1
  8. package/dist/collection/services/CameraService.js +41 -9
  9. package/dist/collection/services/CameraService.js.map +1 -1
  10. package/dist/collection/services/LicenseValidationService.js +1 -1
  11. package/dist/collection/services/LicenseValidationService.js.map +1 -1
  12. package/dist/collection/services/factories/DeviceStrategyFactory.js +7 -0
  13. package/dist/collection/services/factories/DeviceStrategyFactory.js.map +1 -1
  14. package/dist/collection/services/strategies/IOSSafariStrategy.js +33 -0
  15. package/dist/collection/services/strategies/IOSSafariStrategy.js.map +1 -0
  16. package/dist/components/jaak-stamps.js +124 -25
  17. package/dist/components/jaak-stamps.js.map +1 -1
  18. package/dist/esm/jaak-stamps.entry.js +124 -25
  19. package/dist/esm/jaak-stamps.entry.js.map +1 -1
  20. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
  21. package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
  22. package/dist/jaak-stamps-webcomponent/p-04f57d50.entry.js +7 -0
  23. package/dist/jaak-stamps-webcomponent/p-04f57d50.entry.js.map +1 -0
  24. package/dist/types/components/my-component/my-component.d.ts +2 -1
  25. package/dist/types/components.d.ts +2 -2
  26. package/dist/types/services/LicenseValidationService.d.ts +1 -1
  27. package/dist/types/services/strategies/IOSSafariStrategy.d.ts +12 -0
  28. package/package.json +1 -1
  29. package/dist/jaak-stamps-webcomponent/p-dfecb452.entry.js +0 -7
  30. package/dist/jaak-stamps-webcomponent/p-dfecb452.entry.js.map +0 -1
@@ -25,8 +25,8 @@ h1 {
25
25
  position: relative;
26
26
  width: 100%;
27
27
  height: 100%;
28
- background: #333;
29
- border: 1px solid #e0e0e0;
28
+ background-color: #000;
29
+ border: none;
30
30
  border-radius: 8px;
31
31
  overflow: hidden;
32
32
  }
@@ -51,6 +51,27 @@ video {
51
51
  z-index: 0;
52
52
  }
53
53
 
54
+ /* Hide native video controls on Safari/WebKit */
55
+ video::-webkit-media-controls {
56
+ display: none !important;
57
+ }
58
+
59
+ video::-webkit-media-controls-panel {
60
+ display: none !important;
61
+ }
62
+
63
+ video::-webkit-media-controls-play-button {
64
+ display: none !important;
65
+ }
66
+
67
+ video::-webkit-media-controls-start-playback-button {
68
+ display: none !important;
69
+ }
70
+
71
+ video::-webkit-media-controls-enclosure {
72
+ display: none !important;
73
+ }
74
+
54
75
  /* Detection boxes for debug mode */
55
76
  .detection-box {
56
77
  transition: opacity 0.2s ease;
@@ -113,6 +113,7 @@ export class JaakStamps {
113
113
  MAX_FAILURES = 30;
114
114
  lastInferenceTime = 0;
115
115
  MIN_INFERENCE_INTERVAL = 50;
116
+ MOBILE_MIN_INFERENCE_INTERVAL = 100; // Higher interval for mobile to prevent slow motion
116
117
  performanceHistory = [];
117
118
  PERFORMANCE_HISTORY_SIZE = 10;
118
119
  // Sistema simplificado de monitoreo de rendimiento
@@ -277,10 +278,25 @@ export class JaakStamps {
277
278
  if (!window.ort) {
278
279
  this.updateStatus('Preparando herramientas...', 'Configurando funciones de captura', 'initializing');
279
280
  const script = document.createElement('script');
280
- script.src = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.23.0/dist/ort.min.js';
281
+ // iOS Safari uses WASM-only build to prevent memory issues (WebKit 26+ bug)
282
+ const ua = navigator.userAgent;
283
+ const isIOSSafari = /iPad|iPhone|iPod/.test(ua) && /Safari/.test(ua) && !/CriOS|FxiOS|OPiOS|EdgiOS/.test(ua);
284
+ if (isIOSSafari) {
285
+ script.src = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.23.0/dist/ort.wasm.min.js';
286
+ }
287
+ else {
288
+ script.src = 'https://cdn.jsdelivr.net/npm/onnxruntime-web@1.23.0/dist/ort.min.js';
289
+ }
281
290
  document.head.appendChild(script);
282
291
  await new Promise((resolve) => {
283
292
  script.onload = () => {
293
+ // Configure ONNX for iOS Safari low memory mode
294
+ if (isIOSSafari && window.ort?.env) {
295
+ const ort = window.ort;
296
+ ort.env.wasm.simd = false;
297
+ ort.env.wasm.numThreads = 1;
298
+ ort.env.wasm.proxy = false;
299
+ }
284
300
  setTimeout(async () => {
285
301
  await this.finalizeInitialization();
286
302
  resolve(undefined);
@@ -977,9 +993,14 @@ export class JaakStamps {
977
993
  return;
978
994
  }
979
995
  this.frameSkipCounter = 0;
980
- // Throttle inference
996
+ // Throttle inference - use higher interval for mobile devices to prevent slow motion effect
981
997
  const currentTime = Date.now();
982
- if (currentTime - this.lastInferenceTime < this.MIN_INFERENCE_INTERVAL) {
998
+ const isMobileDevice = this.cameraInfoWithAutofocus.deviceType === 'mobile' ||
999
+ /Android|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
1000
+ const isTablet = this.cameraInfoWithAutofocus.deviceType === 'tablet' ||
1001
+ (/iPad|Android/i.test(navigator.userAgent) && window.innerWidth >= 768);
1002
+ const minInterval = (isMobileDevice && !isTablet) ? this.MOBILE_MIN_INFERENCE_INTERVAL : this.MIN_INFERENCE_INTERVAL;
1003
+ if (currentTime - this.lastInferenceTime < minInterval) {
983
1004
  if (captureState.step !== 'completed') {
984
1005
  this.animationId = requestAnimationFrame(() => this.detectFrame());
985
1006
  }
@@ -1133,7 +1154,7 @@ export class JaakStamps {
1133
1154
  isCapturing: false
1134
1155
  };
1135
1156
  const cameraInfo = this.cameraInfoWithAutofocus;
1136
- return (h("div", { key: 'a52b452a7aef6574a5e4b74a88c7bd3f9d45fd15', class: "detector-container" }, !this.licenseValid && this.licenseError && (h("div", { key: '18a99579e0b74ceb2cf1c4c3e21a864d2ec7d944', class: "license-error-container" }, h("div", { key: '3431722f4f47824c172a5b6f3a2ad9bd3bf377f2', class: "license-error-card" }, h("svg", { key: 'bf3854de3ba865a58c5c91cfd7a85d3d725be0df', class: "license-error-icon", width: "64", height: "64", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, h("path", { key: '209e3a2a22333ec90e102a7156eb644b529f47c7', d: "M12 22C12 22 20 18 20 12V5L12 2L4 5V12C4 18 12 22 12 22Z", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }), h("path", { key: '7b0dc1cd29a9055e552885b23f4537c19932556d', d: "M12 8V12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), h("circle", { key: '8ea686ebfb31a5744303f313fd104c03c02a5472', cx: "12", cy: "16", r: "0.5", fill: "currentColor", stroke: "currentColor", "stroke-width": "1" })), h("h2", { key: '7e0ec3ec23b80176cbec9c706999746d62486f3c', class: "license-error-title" }, "Licencia Requerida"), h("p", { key: '261a91e2c20feb09319dc4f319fb79611cc36a46', class: "license-error-message" }, this.licenseError), h("p", { key: '2e3cc8da0f4a8ebfd52db469b0f0900514d1d7f8', class: "license-error-help" }, "Contacte a soporte: ", h("a", { key: '283eea87e2f69dce1ea7376e3a63fed780633499', href: "mailto:support@jaak.ai" }, "support@jaak.ai")), h("div", { key: 'b4227ed25a4fb4d953c753671d27ac8c931a435f', class: "license-error-footer" }, "JAAK Stamps")))), this.licenseValid && (h("div", { key: 'cb33431cf6992f6e7466273406f729c42c1cbcdb', class: "video-container" }, h("video", { key: 'b44befd61ad616fd36fe1e98fd089a2443bc65b6', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: '8cee95ddab5f771a87d43fa434a3ba0c241d2f3e', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index) => (h("div", { key: index, class: "detection-box", style: {
1157
+ return (h("div", { key: 'dc3aed0b4d2d84039b4a123d4bdfe484ea3320ef', class: "detector-container" }, !this.licenseValid && this.licenseError && (h("div", { key: 'a9da275905e2d051252f191be944675781632d10', class: "license-error-container" }, h("div", { key: 'a36f7408f0d862edd1183ba813c64d9be91f15c6', class: "license-error-card" }, h("svg", { key: 'a8e5f3eefc224e16fb62fc0b6d152c85cee249d1', class: "license-error-icon", width: "64", height: "64", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, h("path", { key: 'f645fb46a62004309dee1ede871d980c104fedc5', d: "M12 22C12 22 20 18 20 12V5L12 2L4 5V12C4 18 12 22 12 22Z", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }), h("path", { key: 'ee472eb3d17cddf46bef7e96561296ff6fbb1aed', d: "M12 8V12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), h("circle", { key: 'c58c787c6c9e307159b3103fdd240e282823aa2f', cx: "12", cy: "16", r: "0.5", fill: "currentColor", stroke: "currentColor", "stroke-width": "1" })), h("h2", { key: 'f737ae630fb7661d12a17b7e48cb2c3a1cb6cb4e', class: "license-error-title" }, "Licencia Requerida"), h("p", { key: 'fb5cf8d815cddc79f7b5e9ff39f34852a43bc976', class: "license-error-message" }, this.licenseError), h("p", { key: 'b47831ee55110b100aa0ea9cbe21d39d2fc19306', class: "license-error-help" }, "Contacte a soporte: ", h("a", { key: '52eb8dea1dfdc989b921134f57f1f3f188429061', href: "mailto:support@jaak.ai" }, "support@jaak.ai")), h("div", { key: 'fd78565f67049165236694de5ddd415421d0063e', class: "license-error-footer" }, "JAAK Stamps")))), this.licenseValid && (h("div", { key: '19e5854e1683f57dbde2d857289095db75084496', class: "video-container" }, h("video", { key: 'e44fbc4c020317899620e8aa9e7e3c854ca5a2d9', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: '2b3af557f8ccb39fd7dbcef07fa6d41d021fd772', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index) => (h("div", { key: index, class: "detection-box", style: {
1137
1158
  position: 'absolute',
1138
1159
  left: `${box.x}px`,
1139
1160
  top: `${box.y}px`,
@@ -1142,9 +1163,9 @@ export class JaakStamps {
1142
1163
  border: '2px solid #32406C',
1143
1164
  pointerEvents: 'none',
1144
1165
  boxSizing: 'border-box'
1145
- } })))), this.isMaskReady && (h("div", { key: '00a749ad234294695d9a292911b41fdacafd219a', class: "overlay-mask" }, h("div", { key: 'e344df8a709fca5225985ccc9f8def75ddbd393c', class: "card-outline" }, h("div", { key: '2dcae9e414f2b7131397d49a3d5ecabfc7cd5eb8', class: "side side-top" }), h("div", { key: '48ac3f06fa4a2c83741df378719911f682811caa', class: "side side-right" }), h("div", { key: '238a3269b2a12d528e8a1889d3109ee319c7fd88', class: "side side-bottom" }), h("div", { key: 'b02eec6c102d7e9fb03ef24dfce7c75e081ff1c4', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '15588129ca8027a6ec1c81d70001142986966826', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'f15fd9bddc20c54afcca7be79c3cf2f9ee2b74f7', class: "back-capture-section" }, h("div", { key: 'e3284e1301840a9555857fa879de9f4ca91dc21b', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (h("button", { key: '8508d13e117deb3b223308497b1db976643b86f2', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (h("span", { key: '99bd464541d9ee8589bc11e937c5ad6bca9d95c8', class: "button-spinner" })), "Capturar Reverso")), h("button", { key: '3de5f0a142f9dfdfe4578c0fcbe004bb5fe94c56', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (h("span", { key: '268ce949bf5155b3729298f23eea0d7ec15b3590', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
1166
+ } })))), this.isMaskReady && (h("div", { key: '2cf20cef5e5dc4d5d3282413dce2af0f75b1babe', class: "overlay-mask" }, h("div", { key: '241879ebba739d63a736eca258b735c5c8fdac00', class: "card-outline" }, h("div", { key: '30d895b1a438636d9cd9a759b0fc096446e256a1', class: "side side-top" }), h("div", { key: 'dcca6a422e4c1c20bfc1bd17d7f45305422386a8', class: "side side-right" }), h("div", { key: '2cec938bd863737ae9c0906ed0bce2f16b7461fa', class: "side side-bottom" }), h("div", { key: 'c6045def438350be85f4333b9166111a9820c8fd', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '187bb5013fe6e7454bfc498b3f24844bb16881a3', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: 'a8ffba382875432493eb6564e4d8872d5d7e485a', class: "back-capture-section" }, h("div", { key: '562c149a1f81b8a73df631c81dc2119c1b9427cd', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (h("button", { key: '6dc9a222959df902caec68d72c885fba11e41a79', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (h("span", { key: 'dd3ae6cdba5f4e6085d4d31abebda12f1c1367f8', class: "button-spinner" })), "Capturar Reverso")), h("button", { key: 'cddd1951d4370da5165bf0fa450e3c176ec6cf61', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (h("span", { key: 'da8c1c0af97e164150110cce97d4f4d83e9ffb20', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
1146
1167
  ? `Saltar reverso (${this.backDocumentTimerRemaining}s)`
1147
- : 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: 'bb5c00ad882c303d8a2b6ddc79c9d5b27ff9824e', class: "camera-controls" }, h("button", { key: '7d231b550b58a8336f125a1a7fe7235c8bb3d7dd', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (h("div", { key: '95d1e0d0937f7ef821ff3ad167cd42e25fd1c87f', class: "camera-selector-dropdown" }, h("div", { key: 'e42219e5895c82f40c559c27c4f80f3145fc0a0e', class: "camera-selector-header" }, h("span", { key: '544a6fb2e08211ab6c44b0bfb281124bee318fae' }, "Seleccionar C\u00E1mara"), h("button", { key: '7c4a71243278491ee7dbcc7ab2564bc7e92f5da3', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: 'c9d24e0bd906d20370214fdfd24ae91abfda98e1', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '8c2e1d2ed02bc55c84f3f726e5be577686d0f32d', class: "device-info" }, h("small", { key: '142410a86e4f819b96ffc9573816994351588a3e' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '48c33b2d6c8c80d18fba6e5f454faaa24c28fbd9', class: "manual-capture-section" }, h("button", { key: 'e3d5bfe9ef8b8f16bf669b66bce4e7a500113798', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (h("span", { key: 'f50640fe4308c765011e6ed175528920228df5e7', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (h("div", { key: '080ab315293fa1fe5b1d97aa2511a2ffe2b013f4', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: 'b062c546af50b799bb1fb7dda07b3ffa601c4bac', class: "flip-animation" }, h("div", { key: 'f7162dc31673c7db1d8e03a658a722a3d323b28e', class: "id-card-icon" }), h("div", { key: 'd950952b480342d80d37df5c48031d72be4ac01a', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: 'bd576fd28065aa712e42636c5fd0e3566d26cc25', class: "success-animation" }, h("div", { key: '6ca5c24510df790bd1c955c5e2936909c4767560', class: "check-icon" }), h("div", { key: '3420164eacddbe1a9aa0a181528ba0be7683af56', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: '8ec2b295b233e7bb8ab0cc1c183adedd4e3c7e04', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: '97c8e7e6219984673ebc631da111c17bf72a83cb', class: "status-spinner" })), h("div", { key: '7ca06c48f295892ff77eceff6245891ef7d9dd5e', class: "status-content" }, h("div", { key: '08056c7ec8fd66d23e0b6714c08aeccc092cf46a', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '1e32ca14de53cc2f105822ed5a58e691918b307b', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: 'c25022d9aadd37ead9ae7d1cf7c7d916cdeb9cc1', class: "performance-monitor" }, h("div", { key: 'f0f99c7e820532432ba64726ef0c2aeabeb3309f', class: "performance-expanded" }, h("div", { key: 'e839e90c9cb0f33068ac3311e41914aa52610149', class: "metrics-row" }, h("div", { key: '9f74f4877a048e63f542f2df54f569f79d6f8bd0', class: "metric-compact" }, h("span", { key: '21ec7255706d6fb2cfec035c4be92295ee0216b6', class: "metric-label" }, "FPS"), h("span", { key: 'c8be17f3dc752304bf6b7fd9746f11783f7ff6ca', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: '79187257ea30ead7fb41534a94272a3a855e050b', class: "metric-compact" }, h("span", { key: 'cc53dc282c1fe4234217207c2085fa2be06a5458', class: "metric-label" }, "MEM"), h("span", { key: '032002ff63b3a2349b34833668fed8d6337e2063', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: 'e628febd5bbfb9f593e029b10827635ddd0344fb', class: "metrics-row" }, h("div", { key: 'b2fe558bab709ff6b6781648b13ebc66238f3298', class: "metric-compact" }, h("span", { key: 'd7d816aff11503657781f8ebe9cb5f0f07c7279e', class: "metric-label" }, "INF"), h("span", { key: '3d735d092b5b39d0e96f4ac59b3bf2acde739fab', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: '9a83fd4fe43e8a3760aaea1f134c3101b8757681', class: "metric-compact" }, h("span", { key: '8136ab82b50230537f19cd58ed2da0956d291287', class: "metric-label" }, "FRAME"), h("span", { key: '6221cc10edff8c4b0e4034a3734deb548416a3e6', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: 'a31bad44d5c2c5fd5417ed82589c0f103bba1d32', class: "metrics-row" }, h("div", { key: '1441d11e0d83b3b44dfa963e415c3074691eb4f2', class: "metric-compact" }, h("span", { key: '9fe5643129aa7a842f75644b6f71b1ff80993f1b', class: "metric-label" }, "DET"), h("span", { key: '0604065a3867e71a745bfb4e804c7e96048cb70e', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: 'daff0fede819f2b59a4ddb83560dc53f6151c2c9', class: "metric-compact" }, h("span", { key: '75a55c4a4e36b98af3620866ec6f7842b9ef81f7', class: "metric-label" }, "RATE"), h("span", { key: '61776c3fd4c3200d5e18cc28d917c538b282625a', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: '4092c684ee3a148ec40e266fd16a718f2c2f2f52', class: "watermark" }, h("img", { key: 'd7bae6157d22675f8b71dbf1afdf345374398c82', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" }))))));
1168
+ : 'Saltar reverso')))), captureState.isVideoActive && (h("div", { key: 'd6478c7161d61e1f9f95a9d7bd13cd0cde157061', class: "camera-controls" }, h("button", { key: 'dfede9b72f07c88fc5133d3951ddfb6e507b8e8a', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (h("div", { key: '9218f824cc57b7a8b08f87ed0728c3995fa8b57e', class: "camera-selector-dropdown" }, h("div", { key: '48828e7532f49c3e9eece8051585aa803ea3c69e', class: "camera-selector-header" }, h("span", { key: '49488cbea9f196788e4110cb9b1f132b8097a771' }, "Seleccionar C\u00E1mara"), h("button", { key: '5b762a2da1719c645a490e5234703ba07c50d294', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: '4c13d185e4166dc59621dd8a79a2e7123d810dff', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '6860e0fbc0578a74fcd59b3567dd6e4f9a5a4139', class: "device-info" }, h("small", { key: '45e6045c7fdc0f4d58bc3c4da059a6b7c2ce09f6' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '600d4932b6a7ae7529ef9dc8c22bb352e0f3ae5d', class: "manual-capture-section" }, h("button", { key: '6ad22fbe065602d9214530c374aed05d728114cc', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (h("span", { key: 'd54d5624764ef2774bac1f77551d4c657f4b3e92', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (h("div", { key: 'ab8c46dd497c3911e72d685310c4dccd0e5aca57', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: '545fc8d38085825921e5d61e9d20960b5767a50a', class: "flip-animation" }, h("div", { key: 'fd8540ca1e388070233e366aef791e00c1970de1', class: "id-card-icon" }), h("div", { key: 'f952bdf0b5eccffe5d6b36930250e699ebfb8fd8', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: 'cd9b11e3de2f799096b610582b66e044eda64c2e', class: "success-animation" }, h("div", { key: '73091c9dae5e6c0f2dbd23bf2e0b760f2495f33b', class: "check-icon" }), h("div", { key: 'ad2f9b0b90190b385740bb2fd4ed9454858f13a2', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: 'd74d66f12fab510f0aff01f0e233482ed6f63e46', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: '9060ae79961c7b1b473d5148493fda6462e50388', class: "status-spinner" })), h("div", { key: 'fd0c61e49a751afd826d30ed9f63b96b58c8e275', class: "status-content" }, h("div", { key: 'd0f0e155fba7a09658f7c21beae5f07c26c0701e', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '0694da4ec0ef14750097e69e8caf1db88cf58ed5', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: '277369112303b12a3cef89c1b7218fdc6f130723', class: "performance-monitor" }, h("div", { key: 'f6456cfd210c0d4b8b02b2b73d2405fa7c12923d', class: "performance-expanded" }, h("div", { key: '2cd33cbccf2cf3422f09bd3b914a3bc37b0a1190', class: "metrics-row" }, h("div", { key: '7871e7fe4f63249731ff33f87023351d9c5ded77', class: "metric-compact" }, h("span", { key: 'b864eb43b44838fd5c67c8e430bfa04553130473', class: "metric-label" }, "FPS"), h("span", { key: '7a0e6f4ebcf80b1483102094e0906b2b1a5aa83b', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: 'ef5e590957e12bd6e9371710654278396baa5314', class: "metric-compact" }, h("span", { key: '5cc740e4a2a1e07eb53bcb0cc8c5c3df59f27730', class: "metric-label" }, "MEM"), h("span", { key: '758018f1731d7f26aa5d84e7563b059f352be361', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: '1bedd37486ae4b8ba547507f2664ea19c67a18c7', class: "metrics-row" }, h("div", { key: '4f99be14cda01b199cae93905043a6e03a852d1b', class: "metric-compact" }, h("span", { key: 'c29a4a3461633e776cd86168c59c89c6b39af18d', class: "metric-label" }, "INF"), h("span", { key: '9401828ffd1d3e41ce473ba3d0aec592a683472f', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: '7d4fdad150bb665640add08464ea361aeaa8ef6b', class: "metric-compact" }, h("span", { key: '7c21d775970466b339fdbb392227ec7006b87e31', class: "metric-label" }, "FRAME"), h("span", { key: '255d408312a11f350ea75654fc64edf0d4bcfef2', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: '54ab129c3ffda4f1a32a2b0f437a7c38cb480aba', class: "metrics-row" }, h("div", { key: 'a246db2ef3a69d0d64827a73dd32968cb1e978e9', class: "metric-compact" }, h("span", { key: '8da1c9a5be45bcc23584234cb04f0e75fa3662c6', class: "metric-label" }, "DET"), h("span", { key: 'ad05c2b885a6b344391f70ce3acee8b41523743d', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: '7449e8f7cbd15a6b828b90c923212c3578de3d11', class: "metric-compact" }, h("span", { key: 'da37f89e9641edfdfd60de7fdbf2f6285a2a4120', class: "metric-label" }, "RATE"), h("span", { key: 'de71b2072ce451a304ceb6b158d32b0ecde6d64a', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: '6e2c10e239bca24062cd2972b5e4a3eb0951d0eb', class: "watermark" }, h("img", { key: '63fbe0ade07a191ccc9c007fc2813ac8f6e5ab2f', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" }))))));
1148
1169
  }
1149
1170
  // Utility methods
1150
1171
  updateDetectionBoxes(boxes) {
@@ -1867,28 +1888,35 @@ export class JaakStamps {
1867
1888
  }
1868
1889
  // Adaptive frame skipping based on performance
1869
1890
  getAdaptiveFrameSkip() {
1891
+ // Check if running on mobile device for more aggressive frame skipping
1892
+ const isMobileDevice = this.cameraInfoWithAutofocus.deviceType === 'mobile' ||
1893
+ /Android|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
1894
+ const isTablet = this.cameraInfoWithAutofocus.deviceType === 'tablet' ||
1895
+ (/iPad|Android/i.test(navigator.userAgent) && window.innerWidth >= 768);
1896
+ // Mobile-specific base frame skip (more aggressive to prevent slow motion effect)
1897
+ const mobileBaseSkip = isMobileDevice && !isTablet ? 4 : this.BASE_FRAME_SKIP;
1870
1898
  // Base conditions for high frame skip
1871
1899
  if (this.consecutiveFailures > 20)
1872
1900
  return this.MAX_FRAME_SKIP;
1873
1901
  if (this.performanceMetrics.inferenceTime > 200)
1874
- return 6;
1902
+ return Math.max(6, mobileBaseSkip);
1875
1903
  if (this.performanceMetrics.memoryUsage > 200)
1876
- return 5;
1904
+ return Math.max(5, mobileBaseSkip);
1877
1905
  // Calculate average processing time
1878
1906
  if (this.performanceHistory.length > 0) {
1879
1907
  const avgProcessingTime = this.performanceHistory.reduce((a, b) => a + b, 0) / this.performanceHistory.length;
1880
1908
  if (avgProcessingTime > 100)
1881
- return 4;
1909
+ return Math.max(4, mobileBaseSkip);
1882
1910
  if (avgProcessingTime > 80)
1883
- return 3;
1911
+ return Math.max(3, mobileBaseSkip);
1884
1912
  if (avgProcessingTime > 60)
1885
- return this.BASE_FRAME_SKIP + 1;
1913
+ return Math.max(this.BASE_FRAME_SKIP + 1, mobileBaseSkip);
1886
1914
  }
1887
1915
  // Low memory devices get higher frame skip
1888
1916
  if (this.performanceMetrics.memoryUsage > 150)
1889
- return 4;
1890
- // Performance is good, use base frame skip
1891
- return this.BASE_FRAME_SKIP;
1917
+ return Math.max(4, mobileBaseSkip);
1918
+ // Mobile devices use higher base frame skip for smoother video
1919
+ return mobileBaseSkip;
1892
1920
  }
1893
1921
  // Método para resetear la máscara a color blanco
1894
1922
  resetMaskToWhite() {
@@ -2353,8 +2381,8 @@ export class JaakStamps {
2353
2381
  "attribute": "license-environment",
2354
2382
  "mutable": false,
2355
2383
  "complexType": {
2356
- "original": "'dev' | 'qa' | 'staging' | 'prod'",
2357
- "resolved": "\"dev\" | \"prod\" | \"qa\" | \"staging\"",
2384
+ "original": "'dev' | 'qa' | 'sandbox' | 'prod'",
2385
+ "resolved": "\"dev\" | \"prod\" | \"qa\" | \"sandbox\"",
2358
2386
  "references": {}
2359
2387
  },
2360
2388
  "required": false,