@jaak.ai/stamps 2.5.8-dev.1 → 2.5.8-dev.2

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.
@@ -18819,6 +18819,18 @@ const JaakStamps = class {
18819
18819
  // Canvas pool for optimized screenshot capture
18820
18820
  canvasPool = [];
18821
18821
  MAX_CANVAS_POOL_SIZE = 3;
18822
+ // Readiness gate for startCapture(). The host may call startCapture() before the
18823
+ // component finishes loading its resources (ONNX Runtime + WASM/models from the CDN).
18824
+ // On slow devices/networks this race made startCapture() abort with "El componente
18825
+ // está cargando recursos", leaving the screen black (TO-807). Instead of aborting we
18826
+ // wait for initialization to settle and retry. `initializationSettled` flips once
18827
+ // finalizeInitialization() has run; pending waiters are released via these callbacks.
18828
+ initializationSettled = false;
18829
+ initializationWaiters = [];
18830
+ // Max time startCapture() waits for a still-initializing component before giving up.
18831
+ // Sized for slow Android/network asset downloads; if resources never load (CDN down,
18832
+ // 404, CORS) the timeout fires and startCapture() returns the original error.
18833
+ START_CAPTURE_READY_TIMEOUT_MS = 15000;
18822
18834
  async componentWillLoad() {
18823
18835
  // @Watch handlers fire synchronously when Angular sets properties, which happens
18824
18836
  // BEFORE componentWillLoad (Stencil schedules componentWillLoad as a microtask after
@@ -18958,6 +18970,13 @@ const JaakStamps = class {
18958
18970
  else {
18959
18971
  this._pendingEnvironmentRetry = false;
18960
18972
  }
18973
+ // Release any startCapture() calls waiting on readiness. On success this is a
18974
+ // no-op (finalizeInitialization already settled); on a terminal failure (invalid
18975
+ // license / init error) it lets startCapture() return its error without waiting
18976
+ // out the full timeout. Idempotent, so a completed retry above stays settled.
18977
+ if (!this._initializing) {
18978
+ this.settleInitialization();
18979
+ }
18961
18980
  }
18962
18981
  }
18963
18982
  async initializeServices() {
@@ -19148,6 +19167,42 @@ const JaakStamps = class {
19148
19167
  };
19149
19168
  }
19150
19169
  this.emitReadyEvent();
19170
+ this.settleInitialization();
19171
+ }
19172
+ // Releases any startCapture() calls that arrived while the component was still
19173
+ // initializing. Idempotent: safe to call more than once.
19174
+ settleInitialization() {
19175
+ if (this.initializationSettled) {
19176
+ return;
19177
+ }
19178
+ this.initializationSettled = true;
19179
+ const waiters = this.initializationWaiters;
19180
+ this.initializationWaiters = [];
19181
+ waiters.forEach(resolve => resolve());
19182
+ }
19183
+ // Waits until initialization settles (finalizeInitialization ran) or the timeout
19184
+ // elapses, whichever comes first. Resolves regardless of outcome; the caller
19185
+ // re-checks isComponentReady() afterwards to decide success/failure.
19186
+ waitForInitialization(timeoutMs) {
19187
+ if (this.initializationSettled) {
19188
+ return Promise.resolve();
19189
+ }
19190
+ return new Promise(resolve => {
19191
+ let settled = false;
19192
+ const done = () => {
19193
+ if (settled) {
19194
+ return;
19195
+ }
19196
+ settled = true;
19197
+ clearTimeout(timer);
19198
+ resolve();
19199
+ };
19200
+ const timer = setTimeout(() => {
19201
+ this.initializationWaiters = this.initializationWaiters.filter(w => w !== done);
19202
+ done();
19203
+ }, timeoutMs);
19204
+ this.initializationWaiters.push(done);
19205
+ });
19151
19206
  }
19152
19207
  updateStatus(message, description, type = 'loading') {
19153
19208
  this.currentStatus = {
@@ -19339,7 +19394,20 @@ const JaakStamps = class {
19339
19394
  }
19340
19395
  async startCapture() {
19341
19396
  const span = this.tracingService?.startSpan('capture.start');
19342
- const readyCheck = this.isComponentReady();
19397
+ let readyCheck = this.isComponentReady();
19398
+ // TO-807: absorb the start-before-ready race instead of aborting. When the
19399
+ // component is still loading its resources (transient initializing/loading
19400
+ // state) we wait for initialization to settle and re-check, rather than
19401
+ // returning an error immediately (which left the host with a black screen).
19402
+ // A terminal state ('error' / missing services) is not waited on.
19403
+ if (!readyCheck.ready && (readyCheck.status === 'initializing' || readyCheck.status === 'loading')) {
19404
+ this.updateStatus('El componente está cargando recursos', 'Espere a que termine la inicialización', 'loading');
19405
+ if (span) {
19406
+ this.tracingService?.setSpanAttribute(span, 'startCapture.waitedForReady', true);
19407
+ }
19408
+ await this.waitForInitialization(this.START_CAPTURE_READY_TIMEOUT_MS);
19409
+ readyCheck = this.isComponentReady();
19410
+ }
19343
19411
  if (!readyCheck.ready) {
19344
19412
  this.updateStatus(readyCheck.message, 'Espere a que termine la inicialización', readyCheck.status);
19345
19413
  if (span) {
@@ -20331,7 +20399,7 @@ const JaakStamps = class {
20331
20399
  isCapturing: false
20332
20400
  };
20333
20401
  const cameraInfo = this.cameraInfoWithAutofocus;
20334
- return (index.h("div", { key: 'c0a28d9fd8a66fc8589c0111508ea959f07c143f', class: "detector-container" }, !this.licenseValid && this.licenseError && (index.h("div", { key: '1d0162e9d56c65f646884d12a3c73f4ed7e4c1fc', class: "license-error-container" }, index.h("div", { key: 'a50de01af3d60f4dbe2d17c9d059f79ad0fc8191', class: "license-error-card" }, index.h("svg", { key: '1dd6b599a3ca9bf818aec832638bab23b4ae4074', class: "license-error-icon", width: "64", height: "64", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, index.h("path", { key: 'c7175baf6b409428d820326e24522c7dd0b28811', 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" }), index.h("path", { key: '1ff3c700981b50ed670a499054ceb7b4afc12bc2', d: "M12 8V12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), index.h("circle", { key: 'f0adaa57bc3a218eedf92478f577a381fdb29268', cx: "12", cy: "16", r: "0.5", fill: "currentColor", stroke: "currentColor", "stroke-width": "1" })), index.h("h2", { key: '076e4aaf687e47d2553ba264af3de5ff67b03c60', class: "license-error-title" }, "Licencia Requerida"), index.h("p", { key: '607d2793649698c5686ee98af1e4c48921cba094', class: "license-error-message" }, this.licenseError), index.h("p", { key: '2d5eef84366fabdfea2106e7e5a198ab085c3a01', class: "license-error-help" }, "Contacte a soporte: ", index.h("a", { key: '91d7d22d72f78ae52bc8ddc0955b3ac559474579', href: "mailto:support@jaak.ai" }, "support@jaak.ai")), index.h("div", { key: '0ccf2e04602f740b6dd8551068c044d17691ba38', class: "license-error-footer" }, "JAAK Stamps")))), this.licenseValid && (index.h("div", { key: '339a6066a03d820c74cfd77ce7d582d2282dbf05', class: "video-container" }, index.h("video", { key: '680e86ddef25468ea253febbbc2a5b895b9be955', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: {
20402
+ return (index.h("div", { key: 'ed400c7cc247fb12e5915e270207d3fa916362fd', class: "detector-container" }, !this.licenseValid && this.licenseError && (index.h("div", { key: 'd2f7507026d01d2fd381d365c9954067eb37c3f4', class: "license-error-container" }, index.h("div", { key: 'fc4ae7ae434a038a3730057a99a7d96d851dba43', class: "license-error-card" }, index.h("svg", { key: '7361da72e3fda0147044873bc770460098a4b4f1', class: "license-error-icon", width: "64", height: "64", viewBox: "0 0 24 24", fill: "none", xmlns: "http://www.w3.org/2000/svg" }, index.h("path", { key: '57a3dce14d47d4b91af6ff84ab39cde58814f573', 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" }), index.h("path", { key: '8c96a1638602eface0ae8c7377cdda04dffde5c7', d: "M12 8V12", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round" }), index.h("circle", { key: '7455af58b1827570713d778a4ef01bb0ffcfb553', cx: "12", cy: "16", r: "0.5", fill: "currentColor", stroke: "currentColor", "stroke-width": "1" })), index.h("h2", { key: '5779f8a2c4468ea185df620edecb3f79b7ae8bfb', class: "license-error-title" }, "Licencia Requerida"), index.h("p", { key: '8180147597c077798ff4ea4eb9309a3bec69c77f', class: "license-error-message" }, this.licenseError), index.h("p", { key: '2103af42045a8ee8385de273da8f98e23395469b', class: "license-error-help" }, "Contacte a soporte: ", index.h("a", { key: '8a7fe987b24600b123216c952c5b69f2c2afc0a0', href: "mailto:support@jaak.ai" }, "support@jaak.ai")), index.h("div", { key: 'fd00ef42e259669b7b7cc512478c9c925bd03415', class: "license-error-footer" }, "JAAK Stamps")))), this.licenseValid && (index.h("div", { key: '44a92ba0a4cc066bb4497f4f548fce0bd5dbc121', class: "video-container" }, index.h("video", { key: '9ef40fb28c0fea1b59657ae50134b4dc3df4cf24', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: {
20335
20403
  // Keep the element rendered (display: block) so the browser
20336
20404
  // loads stream metadata and fires 'loadedmetadata'. Hiding it
20337
20405
  // with display:none prevents metadata loading in Chrome and
@@ -20340,7 +20408,7 @@ const JaakStamps = class {
20340
20408
  // render context alive.
20341
20409
  opacity: captureState.isVideoActive ? '1' : '0',
20342
20410
  visibility: captureState.isVideoActive ? 'visible' : 'hidden',
20343
- } }), index.h("div", { key: '521004bb615866dcf160086009810a543fe26a24', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index$1) => (index.h("div", { key: index$1, class: "detection-box", style: {
20411
+ } }), index.h("div", { key: 'f3d6e544bb8b13214894f71216badf092d2516dd', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index$1) => (index.h("div", { key: index$1, class: "detection-box", style: {
20344
20412
  position: 'absolute',
20345
20413
  left: `${box.x}px`,
20346
20414
  top: `${box.y}px`,
@@ -20349,9 +20417,9 @@ const JaakStamps = class {
20349
20417
  border: '2px solid #32406C',
20350
20418
  pointerEvents: 'none',
20351
20419
  boxSizing: 'border-box'
20352
- } })))), this.isMaskReady && (index.h("div", { key: '7b4657df6b922001c726e004c326fe2bc5b20e65', class: "overlay-mask" }, index.h("div", { key: 'c5075a15c4cb994f5628df2be55c0b01077f20f3', class: "card-outline" }, index.h("div", { key: '5028c29cb564a77d7e29ea8fa5877da2d93659e3', class: "side side-top" }), index.h("div", { key: 'e8ce9c8bf2e771ad7862e5127a7d137755f85038', class: "side side-right" }), index.h("div", { key: '351b74462df5ae239fa0519a4cbd994b5e5c5bac', class: "side side-bottom" }), index.h("div", { key: 'e0e8bbe59c665db264ed6174d18cb258dfaddc30', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: '6e995dbe5753cdbb54773c519389aa0822c3913a', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: 'e1a10fcb0e57765247aea911eb24d2c079cde8ee', class: "back-capture-section" }, index.h("div", { key: '3da2aacdce5badcab9017ea5316a124690773b55', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (index.h("button", { key: 'e04c02cfa13728d7a771243167e9c94c92e3c934', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (index.h("span", { key: '47759f79990eb34c69e39b2b9f6d71e6c2d8bb33', class: "button-spinner" })), "Capturar Reverso")), index.h("button", { key: 'e41860634d1df34bfa30c2559fc85322088888ee', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (index.h("span", { key: '44358375377638cd7a7c0699fba5739f38230727', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
20420
+ } })))), this.isMaskReady && (index.h("div", { key: '312b9d7733e550a444e84d699c0e14834fc41057', class: "overlay-mask" }, index.h("div", { key: '2af1c83efb4d360ecada3301f4479bbf8845f032', class: "card-outline" }, index.h("div", { key: 'b6f57f153953e059056fae6d9f8a8220bfff4357', class: "side side-top" }), index.h("div", { key: 'e465f72b8834a04174dc88897b813517afa372fb', class: "side side-right" }), index.h("div", { key: '32e2785c7570f2002b6bc68b491007925d9fcad5', class: "side side-bottom" }), index.h("div", { key: 'bf2133811df7f516d9e3b37ae6019c90c0a68d0b', class: "side side-left" })), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: 'de00829ac42fe7f3645cb515fb46cfabe415190b', class: `guide-text ${this.showPerformanceMessage ? 'performance-warning-text' : ''}` }, this.getGuideText(captureState.step))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: 'ae09d9c23635d87d31110781dc0ab3acb8ec4667', class: "back-capture-section" }, index.h("div", { key: 'a30a50ee0272140d16e32f582dd93f8de87d2a44', class: "back-capture-buttons" }, (!this.useDocumentDetector || this.performanceDegradedMode || this.showManualCaptureButton) && (index.h("button", { key: 'fb104cf6feaeca2f9542a2d5933bbf4f15c6771f', class: "capture-button primary-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-back' && (index.h("span", { key: '7a1bff56bae244c5b8d1d4c3fd523e7a20b4b5ce', class: "button-spinner" })), "Capturar Reverso")), index.h("button", { key: '59125b29ad55122e5ee9e8c2aaf9689a1fef588e', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'skip-back' && (index.h("span", { key: '4d0b8184b4eb82824d5d864fb1b196f22302506d', class: "button-spinner" })), this.enableBackDocumentTimer && this.backDocumentTimerRemaining > 0
20353
20421
  ? `Saltar reverso (${this.backDocumentTimerRemaining}s)`
20354
- : 'Saltar reverso')))), captureState.isVideoActive && (index.h("div", { key: '2f3d35c91e490da2cb458f317fb2a7ece836ca01', class: "camera-controls" }, index.h("button", { key: '21718e9ab6932bb8bd88ca16cc820081b1ed6469', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (index.h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (index.h("div", { key: '1873af9e9d2ff2761e750713606a3b06295fb2f7', class: "camera-selector-dropdown" }, index.h("div", { key: 'df3f445f7ff51efe298f070c56dbfdd217397ea0', class: "camera-selector-header" }, index.h("span", { key: 'f9f33b0c4ed4bf62e18020f54b90f6ce09e923aa' }, "Seleccionar C\u00E1mara"), index.h("button", { key: '28c29c4c82557c80e42b3f524041ab8e160cfce1', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), index.h("div", { key: '95d06551595ca0b7d23ed16c8c4ead633f98ed2f', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (index.h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, index.h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (index.h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (index.h("span", { class: "selected-indicator" }, "\u2713")))))), index.h("div", { key: '6844114f4fa6e6a49d1194c4eaac71db4e2c2030', class: "device-info" }, index.h("small", { key: 'db82272ae5d253dd59fb42326e11ca1d50c70e3e' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: '04bc5e0a469478dab6a5e1e957fa830be15555bc', class: "manual-capture-section" }, index.h("button", { key: '4fae0d4ca89e718a69143d6167dc3f295bc2fafa', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (index.h("span", { key: '5cb26e80c3216ce4940cf24ff1c18e0664a45eb7', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (index.h("div", { key: 'c4e99932aca8940f339aa80d1c9659223d026395', class: "capture-animation" })), captureState.showFlipAnimation && (index.h("div", { key: '4102bccccbae2163e7bb520761d871e07a30e34d', class: "flip-animation" }, index.h("div", { key: '1f9cd0f6d54f643251d24553fe6022f9045a50d6', class: "id-card-icon" }), index.h("div", { key: '1fba0dd3d1b25a1b39f3bda66c8706fd43bf996d', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (index.h("div", { key: '08a0df4e7f7dbf5134cc89d2e300c04825b00495', class: "success-animation" }, index.h("div", { key: 'f94b29abea00c8293da5420981215f929fda19c3', class: "check-icon" }), index.h("div", { key: '01380c7e83e147bf841540178ba56d705c7f3258', class: "success-text" }, "\u00A1Proceso completado!"))), index.h("div", { key: '37d9824236643701b13de9d54adf83662625e6d5', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (index.h("div", { key: '37d6da93b822edf62161a1657887ae1050d16e29', class: "status-spinner" })), index.h("div", { key: '6275ed024cbbeb436b7f04e0dd3bb7cfed1a6a9d', class: "status-content" }, index.h("div", { key: '9c983c432febd71eff737e395e3104711bf8b994', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (index.h("div", { key: '721704c457c378f9563cd28e1e52fa35c68636d8', class: "status-description" }, this.currentStatus.description)))), this.debug && (index.h("div", { key: '0e0ed8e26c2ce73601a88ea74f97da447ad957a3', class: "performance-monitor" }, index.h("div", { key: 'ce46a8da032a38c4c7e6afaf706af5a7ba258f74', class: "performance-expanded" }, index.h("div", { key: '50566325fd8e54d9b5146c95a7965b262b5cbe7e', class: "metrics-row" }, index.h("div", { key: '2c255f1ab96cc0fb3e454b58a37dfe22f6df8ef2', class: "metric-compact" }, index.h("span", { key: '151e4bbf19f362bf32bb4ec838c5ff858ae5c8e6', class: "metric-label" }, "FPS"), index.h("span", { key: '4dcf58fd6d13106ca1fdb28331aebf6ff71c7886', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), index.h("div", { key: '58d0745fb27b0b216fd3865e8fac4731811536c8', class: "metric-compact" }, index.h("span", { key: '0c16975cb5f84351fbad0b6daa6a8d1214f3226e', class: "metric-label" }, "MEM"), index.h("span", { key: 'cf8edc14a7ad690c80dfaeae4f2eaa0b07f88ca3', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), index.h("div", { key: 'c50c14ac229f3a71fc37b256fd5caab77f0c43b2', class: "metrics-row" }, index.h("div", { key: 'b67d2719f42ae342c791d64a52e702af4d54bdbb', class: "metric-compact" }, index.h("span", { key: 'c2ecf87d853dc935b1dad5dd77adee52d1c56404', class: "metric-label" }, "INF"), index.h("span", { key: '86cad05a1846ed3e4e73175acd9a6acabbecb801', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), index.h("div", { key: '82268593f3edea53553b35d4a7ef4c4677ab56c6', class: "metric-compact" }, index.h("span", { key: '937ff57182396d280cb753818b62829d73f7ca4d', class: "metric-label" }, "FRAME"), index.h("span", { key: '6f605b44484ed9e916f16fd50c91e7eb55d45172', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), index.h("div", { key: '5c3c1bd6bde1d43338be02d3f711314fc7c9603c', class: "metrics-row" }, index.h("div", { key: 'bfa796075c5be71dbd8f78471ad2243392561edd', class: "metric-compact" }, index.h("span", { key: '9c2a2999f7026c96f24ef049c2779b1b63b7759a', class: "metric-label" }, "DET"), index.h("span", { key: '5ea705bcde4f534d23d23cf1bfbdbf228d394b22', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), index.h("div", { key: 'cd73965baaed7267be05bf6a8990707b94ad3761', class: "metric-compact" }, index.h("span", { key: 'f7ddd8f95353e21c776c31298c4508e0ee9fffc3', class: "metric-label" }, "RATE"), index.h("span", { key: '2388af4b2ec742889a01b922a44f0d169e747b56', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), index.h("div", { key: '822ae802489dc1621a2edebfb513c0966ea1d4b8', class: "watermark" }, index.h("img", { key: 'bc98d9afb9cb8336bfac25d3f1af3a09f49aafb3', src: "https://static.jaak.ai/commons/powered-by-jaak.png", alt: "Powered by Jaak", onError: (e) => {
20422
+ : 'Saltar reverso')))), captureState.isVideoActive && (index.h("div", { key: '1febf678f87e32916d3990677b41345ce034db4e', class: "camera-controls" }, index.h("button", { key: '79f00bac9d56347de1fc08b2e06be1c0e996a855', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (index.h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (index.h("div", { key: '4f6d101ce789b7fff227a6a2ce2479cb6255fd58', class: "camera-selector-dropdown" }, index.h("div", { key: 'f82222bb25162d2717d84c098c2a6540caa821f3', class: "camera-selector-header" }, index.h("span", { key: '0b1648857467c5749fe5d1d846d1786fa2e394c3' }, "Seleccionar C\u00E1mara"), index.h("button", { key: 'f406f08ad9dc2dcaced7e95aed013665c5fcfb4e', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), index.h("div", { key: 'a051beeab1c8447730d41e963cd3b95027922cab', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (index.h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, index.h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`, camera.hasAutofocus && (index.h("span", { class: "autofocus-icon", title: "Autofoco disponible" }, "\u29BF"))), cameraInfo.selectedCameraId === camera.id && (index.h("span", { class: "selected-indicator" }, "\u2713")))))), index.h("div", { key: 'c9c0702a57c105b02062f325cd413b531c7f802c', class: "device-info" }, index.h("small", { key: '584f4c1ce525b8ab03107329c92797737d5afad5' }, "Dispositivo: ", cameraInfo.deviceType)))), this.showManualCaptureButton && captureState.step === 'front' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (index.h("div", { key: 'e3e2a270d3c4e7accdd9bc8b37861af4fceaad5d', class: "manual-capture-section" }, index.h("button", { key: '1283629ce59fc82d7b3fc08d5573bc69238f7aab', class: "manual-capture-button", onClick: () => this.takeManualScreenshot(), type: "button", disabled: this.processingButton !== null }, this.processingButton === 'capture-front' && (index.h("span", { key: '5de009e4d2ff0de43355e95e1d69f12d7f2e65f8', class: "button-spinner" })), "Capturar Frente"))))), captureState.isCapturing && (index.h("div", { key: '975142144bb104d3ed532ac80fca19a7f237bb2b', class: "capture-animation" })), captureState.showFlipAnimation && (index.h("div", { key: '5d54b9130ed4d1e13b95cfeee8f9d694b5de68d3', class: "flip-animation" }, index.h("div", { key: 'c8b955180065d2b99f8e5f405b1ff92bc050af77', class: "id-card-icon" }), index.h("div", { key: 'f103b1871266886455d5bba094a0e119aa484595', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (index.h("div", { key: '5845c045d37099cf906f7c56d3c91568dd198bdf', class: "success-animation" }, index.h("div", { key: '430496db95f10834a43842e9ac97bdf0f025eb3b', class: "check-icon" }), index.h("div", { key: '0815cf6feffe8bd4ba84712c14d8f29c1a945577', class: "success-text" }, "\u00A1Proceso completado!"))), index.h("div", { key: 'f8a8a529850fc93e93f12810b7928e4700bac880', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (index.h("div", { key: '929ab612be046e97bb02ebe366b531864b90cc7a', class: "status-spinner" })), index.h("div", { key: 'defaf70aa54f2ccc222ddbe392cc47f7c143fc06', class: "status-content" }, index.h("div", { key: '685cca31f70e26d062f2d01b9ffd8c5a4a6b6f86', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (index.h("div", { key: '21bce9f6de9e5a50763ef83a25787225319dc5bf', class: "status-description" }, this.currentStatus.description)))), this.debug && (index.h("div", { key: '6e43560821e469e397b78ab44d1679a3ff8e330f', class: "performance-monitor" }, index.h("div", { key: 'afcde6083be4a1b4a76d5523e0a239926b76ff9a', class: "performance-expanded" }, index.h("div", { key: '0706e93c06bcaf2e573c0c2ac414c3ca7d3605ba', class: "metrics-row" }, index.h("div", { key: '32b755f0f81ae758d9ab0b2e75dd9d55ef52eef0', class: "metric-compact" }, index.h("span", { key: 'b1d8e773fdd1e333cd55bb5bbed2878a7e106474', class: "metric-label" }, "FPS"), index.h("span", { key: 'a6c53d389e7424f6696b6279bef267b28e112201', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), index.h("div", { key: 'a8c4157b696ae53e8ae5cee14f9e8b37be34a0a6', class: "metric-compact" }, index.h("span", { key: '0fa82dd84f6e0a9c16c1894021932e8ba355991a', class: "metric-label" }, "MEM"), index.h("span", { key: 'fc7f19be4e3fbbc82da538703ef9049e26571496', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), index.h("div", { key: '84bd7b6da8e91004ef6c554264b97b89fa6123e1', class: "metrics-row" }, index.h("div", { key: 'a2bc7af57fe87f5ef53ee00f76aa27675736c404', class: "metric-compact" }, index.h("span", { key: '59e9114f50cf4d69bfc447162001e8ab3214906a', class: "metric-label" }, "INF"), index.h("span", { key: 'c92e1f7e92127d85e0cdd647af44f1da4c46da57', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), index.h("div", { key: '5751e9dee9d55ddc559d1c60e68c4be7da2eb7a2', class: "metric-compact" }, index.h("span", { key: 'a34e394ab188e74a39eb77af4cf0108c8a2be1c3', class: "metric-label" }, "FRAME"), index.h("span", { key: '19165e851fc7f348e6cee93deccff0159c3bb982', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), index.h("div", { key: 'dde9e547b8c9e200624e525d15baaa4a18a27417', class: "metrics-row" }, index.h("div", { key: '770301e51025a446e29638d38e8e8a8dfb911882', class: "metric-compact" }, index.h("span", { key: '96750b7a455ef1f3353b870467afdff402fa605b', class: "metric-label" }, "DET"), index.h("span", { key: 'a7951b69998e1d13beee40b6677d55091a413a4c', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), index.h("div", { key: 'a82589fbccc749ef904a68933c6b850c3b69018c', class: "metric-compact" }, index.h("span", { key: 'ced7d42d2ebf2c4f20671c696b845263f4de4f4a', class: "metric-label" }, "RATE"), index.h("span", { key: '693c9735796ec276ca1d7e559aea250dafb0e5cf', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), index.h("div", { key: '3ff1698eae36352f9268839b86cef29144de297c', class: "watermark" }, index.h("img", { key: 'efa9735216e7caafdb67e10a5fc9363b503307b5', src: "https://static.jaak.ai/commons/powered-by-jaak.png", alt: "Powered by Jaak", onError: (e) => {
20355
20423
  const img = e.target;
20356
20424
  img.onerror = null;
20357
20425
  img.src = POWERED_BY_JAAK_FALLBACK;