@andresxid/xid_camera_ocr_sdk_react 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/README.md +37 -9
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +45 -11
- package/dist/index.d.ts +45 -11
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -19,7 +19,7 @@ interface CornerPoint {
|
|
|
19
19
|
}
|
|
20
20
|
/** User-facing guidance for the current frame. */
|
|
21
21
|
type FrameHint = 'no_document' | 'too_small' | 'too_dark' | 'glare' | 'blurry' | 'hold_still' | 'ready'
|
|
22
|
-
/** OpenCV failed to load or the worker crashed: auto-capture is off, `captureNow()`
|
|
22
|
+
/** OpenCV failed to load or the worker crashed: auto-capture is off, `captureNow()` still crops the guide region. */
|
|
23
23
|
| 'detector_unavailable';
|
|
24
24
|
interface XidCameraOcrSessionOptions {
|
|
25
25
|
/** `<video>` element that renders the camera stream. */
|
|
@@ -27,16 +27,26 @@ interface XidCameraOcrSessionOptions {
|
|
|
27
27
|
/**
|
|
28
28
|
* Shape hints the host is interested in. Detection and capture are NOT
|
|
29
29
|
* filtered by this list (any quadrilateral in [1.25, 1.75] aspect is
|
|
30
|
-
* capturable)
|
|
30
|
+
* capturable). The first entry fixes the guide ratio (PASSPORT_MX → TD3,
|
|
31
|
+
* otherwise ID-1) for both the on-screen guide and the captured crop.
|
|
31
32
|
*/
|
|
32
33
|
documentTypes?: DocumentType[];
|
|
34
|
+
/**
|
|
35
|
+
* When `true`, the capture is cropped to the guide rectangle (cover math over the video
|
|
36
|
+
* element's client box). Only enable it when the video is `object-fit: cover` filling its
|
|
37
|
+
* box and a centered guide is drawn with `guideBox`. Default `false`: full-frame snapshot.
|
|
38
|
+
* `<XidCameraOcr />` turns it on whenever it draws the guide.
|
|
39
|
+
*/
|
|
40
|
+
cropToGuide?: boolean;
|
|
41
|
+
/** Live guide ratio (width / height) read at capture time. Default: derived from `documentTypes`. */
|
|
42
|
+
guideRatio?: () => number;
|
|
33
43
|
/** When `true`, captures automatically once a stable, good-quality quad is seen. Default `false`: the user takes the photo manually. */
|
|
34
44
|
autoCapture?: boolean;
|
|
35
45
|
/** Consecutive stable frames required before auto-capture. Default 10 (≈ 1 s at 10 fps). */
|
|
36
46
|
stableFramesRequired?: number;
|
|
37
47
|
/** JPEG quality of the captured image (0–1). Default 0.92. */
|
|
38
48
|
captureQuality?: number;
|
|
39
|
-
/**
|
|
49
|
+
/** Max long side of the captured guide crop (never upscaled): `standard` = 1024 px, `high` = 1600 px. Default `standard`. */
|
|
40
50
|
captureResolution?: 'standard' | 'high';
|
|
41
51
|
/**
|
|
42
52
|
* URL of the OpenCV.js asset the worker loads lazily. Defaults to the
|
|
@@ -204,7 +214,25 @@ declare class CVWorkerClient {
|
|
|
204
214
|
private request;
|
|
205
215
|
}
|
|
206
216
|
|
|
207
|
-
|
|
217
|
+
interface BoxSize {
|
|
218
|
+
width: number;
|
|
219
|
+
height: number;
|
|
220
|
+
}
|
|
221
|
+
interface PixelRect {
|
|
222
|
+
x: number;
|
|
223
|
+
y: number;
|
|
224
|
+
width: number;
|
|
225
|
+
height: number;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Fixed guide ratio from the configured document types: TD3 when the first accepted
|
|
229
|
+
* type is PASSPORT_MX, ID-1 otherwise. Detection never changes it.
|
|
230
|
+
*/
|
|
231
|
+
declare function guideRatioFor(documentTypes: readonly DocumentType[] | undefined): number;
|
|
232
|
+
/** Guide size in container px: at most 85% of the width and 70% of the height, keeping `ratio`. */
|
|
233
|
+
declare function guideBox(container: BoxSize, ratio: number): BoxSize;
|
|
234
|
+
|
|
235
|
+
type WorkerClient = Pick<CVWorkerClient, 'init' | 'isReady' | 'analyze' | 'terminate'>;
|
|
208
236
|
/**
|
|
209
237
|
* @internal Test seam (second constructor argument). Not part of the public,
|
|
210
238
|
* documented API and may change without notice.
|
|
@@ -216,8 +244,8 @@ interface XidCameraOcrSessionDeps {
|
|
|
216
244
|
attachCamera(video: HTMLVideoElement): Promise<MediaStream>;
|
|
217
245
|
detachCamera(video: HTMLVideoElement, stream: MediaStream | null): void;
|
|
218
246
|
sampleFrame(video: HTMLVideoElement, targetWidth: number): ImageDataLike | null;
|
|
219
|
-
|
|
220
|
-
|
|
247
|
+
/** Draws `rect` (video px) of the current frame scaled to `out` and encodes it as JPEG. */
|
|
248
|
+
cropFrame(video: HTMLVideoElement, rect: PixelRect, out: BoxSize, quality: number): Promise<Blob>;
|
|
221
249
|
snapshotToBlob(video: HTMLVideoElement, quality: number): Promise<Blob>;
|
|
222
250
|
supportsTorch(track: MediaStreamTrack): boolean;
|
|
223
251
|
setTorch(track: MediaStreamTrack, on: boolean): Promise<boolean>;
|
|
@@ -233,8 +261,6 @@ declare class XidCameraOcrSession {
|
|
|
233
261
|
private generation;
|
|
234
262
|
private timer;
|
|
235
263
|
private frameCallback;
|
|
236
|
-
/** The in-flight analyze request, so a manual capture never overlaps it. */
|
|
237
|
-
private inFlight;
|
|
238
264
|
/** 0 = not armed yet (armed on the first analysed frame and after each capture). */
|
|
239
265
|
private warmupUntil;
|
|
240
266
|
private capturing;
|
|
@@ -267,8 +293,15 @@ declare class XidCameraOcrSession {
|
|
|
267
293
|
private updateTorch;
|
|
268
294
|
/** Reprojects a sample-frame quad onto the full video frame; null when degenerate. */
|
|
269
295
|
private fullFrameQuad;
|
|
270
|
-
/** `
|
|
296
|
+
/** `typeHint` is the stable detection hint (null when nothing stable was tracked). */
|
|
271
297
|
private doCapture;
|
|
298
|
+
/**
|
|
299
|
+
* With `cropToGuide` off, takes the plain full-frame snapshot. Otherwise crops the guide region out of the current full frame. The rect is computed now, from
|
|
300
|
+
* the live element sizes, so a rotation mid-session is handled. The video element fills
|
|
301
|
+
* the root with `object-fit: cover`, so its client box is the guide's container. Without
|
|
302
|
+
* a usable rect (no layout / no frame) or when the crop fails, the full-frame snapshot
|
|
303
|
+
* is used and the type is null.
|
|
304
|
+
*/
|
|
272
305
|
private captureBlob;
|
|
273
306
|
/** Clears every timer and frame callback, turns the torch off, closes the camera and drops the worker. */
|
|
274
307
|
private release;
|
|
@@ -342,7 +375,8 @@ declare function measureQuality(gray: GrayFrame, quad: Quad): FrameQuality;
|
|
|
342
375
|
/**
|
|
343
376
|
* Camera helpers — getUserMedia + video element wiring.
|
|
344
377
|
*/
|
|
345
|
-
|
|
378
|
+
type ViewportOrientation = 'portrait' | 'landscape';
|
|
379
|
+
declare function attachCamera(videoElement: HTMLVideoElement, constraints?: MediaStreamConstraints, orientation?: ViewportOrientation): Promise<MediaStream>;
|
|
346
380
|
declare function detachCamera(videoElement: HTMLVideoElement, stream: MediaStream | null): void;
|
|
347
381
|
/** Captura un snapshot del video y devuelve un Blob JPEG. */
|
|
348
382
|
declare function snapshotToBlob(videoElement: HTMLVideoElement, quality?: number): Promise<Blob>;
|
|
@@ -469,4 +503,4 @@ interface XidCameraOcrHandle {
|
|
|
469
503
|
}
|
|
470
504
|
declare const XidCameraOcr: react.ForwardRefExoticComponent<XidCameraOcrProps & react.RefAttributes<XidCameraOcrHandle>>;
|
|
471
505
|
|
|
472
|
-
export { CVWorkerClient, type CornerPoint, type CvDetectionResult, DEFAULT_TEXTS_EN, DEFAULT_TEXTS_ES, type DocumentType, type ExtractResult, type FrameHint, type FrameQuality, type FrameState, type HintCopy, type HintCopyKey, ID1_RATIO, type Point, QUALITY_THRESHOLDS, type Quad, type SessionState, type SessionStatus, StabilityTracker, TD3_RATIO, type UseXidCameraOcrOptions, type UseXidCameraOcrReturn, XCO_VARS, type XcoThemeKey, XidCameraOcr, type XidCameraOcrHandle, type XidCameraOcrProps, XidCameraOcrSession, type XidCameraOcrSessionOptions, type XidCameraOcrTheme, attachCamera, copyFor, decideHint, defaultOpencvUrl, detachCamera, detectDocumentCV, isCapturableAspect, measureQuality, orderCorners, rectifiedAspect, resolveTexts, sampleFrame, setTorch, snapshotToBlob, supportsTorch, typeHintFromAspect, useXidCameraOcr, warpDocument, warpDocumentImageData, warpedSnapshotToBlob };
|
|
506
|
+
export { type BoxSize, CVWorkerClient, type CornerPoint, type CvDetectionResult, DEFAULT_TEXTS_EN, DEFAULT_TEXTS_ES, type DocumentType, type ExtractResult, type FrameHint, type FrameQuality, type FrameState, type HintCopy, type HintCopyKey, ID1_RATIO, type Point, QUALITY_THRESHOLDS, type Quad, type SessionState, type SessionStatus, StabilityTracker, TD3_RATIO, type UseXidCameraOcrOptions, type UseXidCameraOcrReturn, XCO_VARS, type XcoThemeKey, XidCameraOcr, type XidCameraOcrHandle, type XidCameraOcrProps, XidCameraOcrSession, type XidCameraOcrSessionOptions, type XidCameraOcrTheme, attachCamera, copyFor, decideHint, defaultOpencvUrl, detachCamera, detectDocumentCV, guideBox, guideRatioFor, isCapturableAspect, measureQuality, orderCorners, rectifiedAspect, resolveTexts, sampleFrame, setTorch, snapshotToBlob, supportsTorch, typeHintFromAspect, useXidCameraOcr, warpDocument, warpDocumentImageData, warpedSnapshotToBlob };
|
package/dist/index.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ interface CornerPoint {
|
|
|
19
19
|
}
|
|
20
20
|
/** User-facing guidance for the current frame. */
|
|
21
21
|
type FrameHint = 'no_document' | 'too_small' | 'too_dark' | 'glare' | 'blurry' | 'hold_still' | 'ready'
|
|
22
|
-
/** OpenCV failed to load or the worker crashed: auto-capture is off, `captureNow()`
|
|
22
|
+
/** OpenCV failed to load or the worker crashed: auto-capture is off, `captureNow()` still crops the guide region. */
|
|
23
23
|
| 'detector_unavailable';
|
|
24
24
|
interface XidCameraOcrSessionOptions {
|
|
25
25
|
/** `<video>` element that renders the camera stream. */
|
|
@@ -27,16 +27,26 @@ interface XidCameraOcrSessionOptions {
|
|
|
27
27
|
/**
|
|
28
28
|
* Shape hints the host is interested in. Detection and capture are NOT
|
|
29
29
|
* filtered by this list (any quadrilateral in [1.25, 1.75] aspect is
|
|
30
|
-
* capturable)
|
|
30
|
+
* capturable). The first entry fixes the guide ratio (PASSPORT_MX → TD3,
|
|
31
|
+
* otherwise ID-1) for both the on-screen guide and the captured crop.
|
|
31
32
|
*/
|
|
32
33
|
documentTypes?: DocumentType[];
|
|
34
|
+
/**
|
|
35
|
+
* When `true`, the capture is cropped to the guide rectangle (cover math over the video
|
|
36
|
+
* element's client box). Only enable it when the video is `object-fit: cover` filling its
|
|
37
|
+
* box and a centered guide is drawn with `guideBox`. Default `false`: full-frame snapshot.
|
|
38
|
+
* `<XidCameraOcr />` turns it on whenever it draws the guide.
|
|
39
|
+
*/
|
|
40
|
+
cropToGuide?: boolean;
|
|
41
|
+
/** Live guide ratio (width / height) read at capture time. Default: derived from `documentTypes`. */
|
|
42
|
+
guideRatio?: () => number;
|
|
33
43
|
/** When `true`, captures automatically once a stable, good-quality quad is seen. Default `false`: the user takes the photo manually. */
|
|
34
44
|
autoCapture?: boolean;
|
|
35
45
|
/** Consecutive stable frames required before auto-capture. Default 10 (≈ 1 s at 10 fps). */
|
|
36
46
|
stableFramesRequired?: number;
|
|
37
47
|
/** JPEG quality of the captured image (0–1). Default 0.92. */
|
|
38
48
|
captureQuality?: number;
|
|
39
|
-
/**
|
|
49
|
+
/** Max long side of the captured guide crop (never upscaled): `standard` = 1024 px, `high` = 1600 px. Default `standard`. */
|
|
40
50
|
captureResolution?: 'standard' | 'high';
|
|
41
51
|
/**
|
|
42
52
|
* URL of the OpenCV.js asset the worker loads lazily. Defaults to the
|
|
@@ -204,7 +214,25 @@ declare class CVWorkerClient {
|
|
|
204
214
|
private request;
|
|
205
215
|
}
|
|
206
216
|
|
|
207
|
-
|
|
217
|
+
interface BoxSize {
|
|
218
|
+
width: number;
|
|
219
|
+
height: number;
|
|
220
|
+
}
|
|
221
|
+
interface PixelRect {
|
|
222
|
+
x: number;
|
|
223
|
+
y: number;
|
|
224
|
+
width: number;
|
|
225
|
+
height: number;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Fixed guide ratio from the configured document types: TD3 when the first accepted
|
|
229
|
+
* type is PASSPORT_MX, ID-1 otherwise. Detection never changes it.
|
|
230
|
+
*/
|
|
231
|
+
declare function guideRatioFor(documentTypes: readonly DocumentType[] | undefined): number;
|
|
232
|
+
/** Guide size in container px: at most 85% of the width and 70% of the height, keeping `ratio`. */
|
|
233
|
+
declare function guideBox(container: BoxSize, ratio: number): BoxSize;
|
|
234
|
+
|
|
235
|
+
type WorkerClient = Pick<CVWorkerClient, 'init' | 'isReady' | 'analyze' | 'terminate'>;
|
|
208
236
|
/**
|
|
209
237
|
* @internal Test seam (second constructor argument). Not part of the public,
|
|
210
238
|
* documented API and may change without notice.
|
|
@@ -216,8 +244,8 @@ interface XidCameraOcrSessionDeps {
|
|
|
216
244
|
attachCamera(video: HTMLVideoElement): Promise<MediaStream>;
|
|
217
245
|
detachCamera(video: HTMLVideoElement, stream: MediaStream | null): void;
|
|
218
246
|
sampleFrame(video: HTMLVideoElement, targetWidth: number): ImageDataLike | null;
|
|
219
|
-
|
|
220
|
-
|
|
247
|
+
/** Draws `rect` (video px) of the current frame scaled to `out` and encodes it as JPEG. */
|
|
248
|
+
cropFrame(video: HTMLVideoElement, rect: PixelRect, out: BoxSize, quality: number): Promise<Blob>;
|
|
221
249
|
snapshotToBlob(video: HTMLVideoElement, quality: number): Promise<Blob>;
|
|
222
250
|
supportsTorch(track: MediaStreamTrack): boolean;
|
|
223
251
|
setTorch(track: MediaStreamTrack, on: boolean): Promise<boolean>;
|
|
@@ -233,8 +261,6 @@ declare class XidCameraOcrSession {
|
|
|
233
261
|
private generation;
|
|
234
262
|
private timer;
|
|
235
263
|
private frameCallback;
|
|
236
|
-
/** The in-flight analyze request, so a manual capture never overlaps it. */
|
|
237
|
-
private inFlight;
|
|
238
264
|
/** 0 = not armed yet (armed on the first analysed frame and after each capture). */
|
|
239
265
|
private warmupUntil;
|
|
240
266
|
private capturing;
|
|
@@ -267,8 +293,15 @@ declare class XidCameraOcrSession {
|
|
|
267
293
|
private updateTorch;
|
|
268
294
|
/** Reprojects a sample-frame quad onto the full video frame; null when degenerate. */
|
|
269
295
|
private fullFrameQuad;
|
|
270
|
-
/** `
|
|
296
|
+
/** `typeHint` is the stable detection hint (null when nothing stable was tracked). */
|
|
271
297
|
private doCapture;
|
|
298
|
+
/**
|
|
299
|
+
* With `cropToGuide` off, takes the plain full-frame snapshot. Otherwise crops the guide region out of the current full frame. The rect is computed now, from
|
|
300
|
+
* the live element sizes, so a rotation mid-session is handled. The video element fills
|
|
301
|
+
* the root with `object-fit: cover`, so its client box is the guide's container. Without
|
|
302
|
+
* a usable rect (no layout / no frame) or when the crop fails, the full-frame snapshot
|
|
303
|
+
* is used and the type is null.
|
|
304
|
+
*/
|
|
272
305
|
private captureBlob;
|
|
273
306
|
/** Clears every timer and frame callback, turns the torch off, closes the camera and drops the worker. */
|
|
274
307
|
private release;
|
|
@@ -342,7 +375,8 @@ declare function measureQuality(gray: GrayFrame, quad: Quad): FrameQuality;
|
|
|
342
375
|
/**
|
|
343
376
|
* Camera helpers — getUserMedia + video element wiring.
|
|
344
377
|
*/
|
|
345
|
-
|
|
378
|
+
type ViewportOrientation = 'portrait' | 'landscape';
|
|
379
|
+
declare function attachCamera(videoElement: HTMLVideoElement, constraints?: MediaStreamConstraints, orientation?: ViewportOrientation): Promise<MediaStream>;
|
|
346
380
|
declare function detachCamera(videoElement: HTMLVideoElement, stream: MediaStream | null): void;
|
|
347
381
|
/** Captura un snapshot del video y devuelve un Blob JPEG. */
|
|
348
382
|
declare function snapshotToBlob(videoElement: HTMLVideoElement, quality?: number): Promise<Blob>;
|
|
@@ -469,4 +503,4 @@ interface XidCameraOcrHandle {
|
|
|
469
503
|
}
|
|
470
504
|
declare const XidCameraOcr: react.ForwardRefExoticComponent<XidCameraOcrProps & react.RefAttributes<XidCameraOcrHandle>>;
|
|
471
505
|
|
|
472
|
-
export { CVWorkerClient, type CornerPoint, type CvDetectionResult, DEFAULT_TEXTS_EN, DEFAULT_TEXTS_ES, type DocumentType, type ExtractResult, type FrameHint, type FrameQuality, type FrameState, type HintCopy, type HintCopyKey, ID1_RATIO, type Point, QUALITY_THRESHOLDS, type Quad, type SessionState, type SessionStatus, StabilityTracker, TD3_RATIO, type UseXidCameraOcrOptions, type UseXidCameraOcrReturn, XCO_VARS, type XcoThemeKey, XidCameraOcr, type XidCameraOcrHandle, type XidCameraOcrProps, XidCameraOcrSession, type XidCameraOcrSessionOptions, type XidCameraOcrTheme, attachCamera, copyFor, decideHint, defaultOpencvUrl, detachCamera, detectDocumentCV, isCapturableAspect, measureQuality, orderCorners, rectifiedAspect, resolveTexts, sampleFrame, setTorch, snapshotToBlob, supportsTorch, typeHintFromAspect, useXidCameraOcr, warpDocument, warpDocumentImageData, warpedSnapshotToBlob };
|
|
506
|
+
export { type BoxSize, CVWorkerClient, type CornerPoint, type CvDetectionResult, DEFAULT_TEXTS_EN, DEFAULT_TEXTS_ES, type DocumentType, type ExtractResult, type FrameHint, type FrameQuality, type FrameState, type HintCopy, type HintCopyKey, ID1_RATIO, type Point, QUALITY_THRESHOLDS, type Quad, type SessionState, type SessionStatus, StabilityTracker, TD3_RATIO, type UseXidCameraOcrOptions, type UseXidCameraOcrReturn, XCO_VARS, type XcoThemeKey, XidCameraOcr, type XidCameraOcrHandle, type XidCameraOcrProps, XidCameraOcrSession, type XidCameraOcrSessionOptions, type XidCameraOcrTheme, attachCamera, copyFor, decideHint, defaultOpencvUrl, detachCamera, detectDocumentCV, guideBox, guideRatioFor, isCapturableAspect, measureQuality, orderCorners, rectifiedAspect, resolveTexts, sampleFrame, setTorch, snapshotToBlob, supportsTorch, typeHintFromAspect, useXidCameraOcr, warpDocument, warpDocumentImageData, warpedSnapshotToBlob };
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {forwardRef,useMemo,useImperativeHandle,useRef,useEffect,useState,useCallback,useLayoutEffect}from'react';import {jsx,jsxs}from'react/jsx-runtime';async function le(e,t){let r={audio:false,video:{facingMode:{ideal:"environment"},width:{ideal:1920,min:640},height:{ideal:1080,min:480},aspectRatio:{ideal:1.7777777777777777}}};if(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)throw new Error("Camera unavailable: getUserMedia requires a secure context (HTTPS or localhost) and a browser with MediaDevices support.");let n;try{n=await navigator.mediaDevices.getUserMedia(t??r);}catch(s){if(!t)n=await navigator.mediaDevices.getUserMedia({audio:false,video:true});else throw s}e.srcObject=n,e.muted=true,e.playsInline=true,e.autoplay=true;let a=n.getVideoTracks()[0],i=a.getCapabilities?.();return i&&"focusMode"in i&&i.focusMode?.includes("continuous")&&a.applyConstraints({advanced:[{focusMode:"continuous"}]}).catch(()=>{}),await e.play().catch(()=>{}),n}function ce(e,t){e.srcObject===t&&(e.srcObject=null),t?.getTracks().forEach(r=>r.stop());}async function ue(e,t=.92){let r=e.videoWidth,n=e.videoHeight;if(!r||!n)throw new Error("Video stream not ready (videoWidth=0)");let a=document.createElement("canvas");a.width=r,a.height=n;let i=a.getContext("2d");if(!i)throw new Error("2D canvas context unavailable");return i.drawImage(e,0,0,r,n),new Promise((s,o)=>{a.toBlob(l=>l?s(l):o(new Error("Canvas toBlob returned null")),"image/jpeg",t);})}var U=null;function de(e,t=640){let r=e.videoWidth,n=e.videoHeight;if(!r||!n)return null;let a=Math.round(t),i=Math.round(n*t/r);U??=document.createElement("canvas"),(U.width!==a||U.height!==i)&&(U.width=a,U.height=i);let s=U.getContext("2d",{willReadFrequently:true});return s?(s.drawImage(e,0,0,a,i),s.getImageData(0,0,a,i)):null}function Ee(e){let t=e.videoWidth,r=e.videoHeight;if(!t||!r)return null;let n=document.createElement("canvas");n.width=t,n.height=r;let a=n.getContext("2d",{willReadFrequently:true});return a?(a.drawImage(e,0,0,t,r),a.getImageData(0,0,t,r)):null}function _e(e,t=.92){let r=document.createElement("canvas");r.width=e.width,r.height=e.height;let n=r.getContext("2d");return n?(n.putImageData(e,0,0),new Promise((a,i)=>r.toBlob(s=>s?a(s):i(new Error("Canvas toBlob returned null")),"image/jpeg",t))):Promise.reject(new Error("2D canvas context unavailable"))}function pe(e){let t=e.getCapabilities;return typeof t!="function"?false:t.call(e).torch===true}async function me(e,t){try{return await e.applyConstraints({advanced:[{torch:t}]}),!0}catch{return false}}var gt="@andresxid/xid_camera_ocr_sdk_react";function Ae(e,t){return e.pathname.endsWith(`/${gt}/${t}`)}function Fe(e){return new URL(e,import.meta.url)}function Pe(){return new URL("@andresxid/xid_camera_ocr_sdk_react/opencv.js",import.meta.url)}function he(){let e=Pe();return Ae(e,"opencv.js")?Fe("./opencv.js").href:e.href}function Oe(e){return e!==void 0?new Worker(e,{type:"module"}):Ae(Pe(),"opencv.js")?new Worker(Fe("./cv-worker.js"),{type:"module"}):new Worker(new URL("@andresxid/xid_camera_ocr_sdk_react/cv-worker.js",import.meta.url),{type:"module"})}function De(e){if(!e||typeof e!="object")return null;let t=e;switch(t.type){case "ready":return {type:"ready"};case "init-error":return typeof t.error=="string"?{type:"init-error",error:t.error}:null;case "error":return typeof t.id=="number"&&typeof t.error=="string"?{type:"error",id:t.id,error:t.error}:null;case "analyze-result":return typeof t.id=="number"&&t.result&&typeof t.result=="object"?{type:"analyze-result",id:t.id,result:t.result}:null;case "warp-result":return typeof t.id=="number"&&typeof t.width=="number"&&typeof t.height=="number"&&t.buffer instanceof ArrayBuffer?{type:"warp-result",id:t.id,width:t.width,height:t.height,buffer:t.buffer}:null;default:return null}}function Ie(e){let t=new Uint8ClampedArray(e.data.byteLength);return t.set(e.data),t.buffer}var St=e=>e instanceof Error?e:new Error(String(e)),W=class{initTimeoutMs;worker=null;readyPromise=null;rejectInit=null;initTimer=null;ready=false;pending=new Map;nextId=1;constructor(t={}){this.initTimeoutMs=t.initTimeoutMs??3e4;}init(t=he(),r){if(this.readyPromise)return this.readyPromise;let n;try{n=Oe(r);}catch(i){return Promise.reject(St(i))}this.worker=n;let a=new Promise((i,s)=>{this.rejectInit=s,this.initTimer=setTimeout(()=>this.fail(new Error(`OpenCV worker not ready within ${this.initTimeoutMs} ms`)),this.initTimeoutMs),n.addEventListener("message",o=>{if(this.worker!==n)return;let l=De(o.data);if(!l)return;if(l.type==="ready"){this.clearInitTimer(),this.rejectInit=null,this.ready=true,i();return}if(l.type==="init-error"){this.fail(new Error(l.error));return}let c=this.pending.get(l.id);c&&(this.pending.delete(l.id),l.type==="error"?c.reject(new Error(l.error)):c.resolve(l));}),n.addEventListener("error",o=>{this.worker===n&&this.fail(new Error(o.message||"Worker error"));}),n.addEventListener("messageerror",o=>{if(this.worker!==n)return;let l=new Error("Worker message could not be deserialized"),c=o.data?.id,d=typeof c=="number"?this.pending.get(c):void 0;if(typeof c=="number"&&d){this.pending.delete(c),d.reject(l);return}this.fail(l);});});return this.readyPromise=a,n.postMessage({type:"init",opencvUrl:t}),a}isReady(){return this.ready&&this.worker!==null}async analyze(t,r={}){let n=Ie(t),a=r.prior,i=await this.request(s=>({type:"analyze",id:s,width:t.width,height:t.height,buffer:n,...a?{prior:a}:{}}),[n]);if(i.type!=="analyze-result")throw new Error(`Unexpected worker response: ${i.type}`);return i.result}async warp(t,r,n,a=1024){let i=Ie(t),s=await this.request(o=>({type:"warp",id:o,width:t.width,height:t.height,buffer:i,corners:r,docType:n,longSide:a}),[i]);if(s.type!=="warp-result")throw new Error(`Unexpected worker response: ${s.type}`);return new ImageData(new Uint8ClampedArray(s.buffer),s.width,s.height)}terminate(){this.rejectInit=null,this.shutdown(new Error("Worker terminated"));}fail(t){let r=this.rejectInit;this.rejectInit=null,this.shutdown(t),r?.(t);}clearInitTimer(){this.initTimer!==null&&clearTimeout(this.initTimer),this.initTimer=null;}shutdown(t){this.clearInitTimer(),this.worker?.terminate(),this.worker=null,this.readyPromise=null,this.ready=false;let r=[...this.pending.values()];this.pending.clear();for(let n of r)n.reject(t);}request(t,r){let n=this.worker;if(!n||!this.ready)return Promise.reject(new Error("CVWorkerClient not ready"));let a=t(this.nextId++),i=new Promise((s,o)=>this.pending.set(a.id,{resolve:s,reject:o}));return n.postMessage(a,r),i}};var O=1.585772508336421,I=125/88,Ct=1.503,wt=.05,Z=1.25,ye=1.75,Tt=.25;function fe(e){if(e.length!==4)throw new Error(`orderCorners expects 4 points, got ${e.length}`);let t=(e[0].x+e[1].x+e[2].x+e[3].x)/4,r=(e[0].y+e[1].y+e[2].y+e[3].y)/4,n=[...e].sort((i,s)=>Math.atan2(i.y-r,i.x-t)-Math.atan2(s.y-r,s.x-t)),a=0;for(let i=1;i<4;i++){let s=n[i],o=n[a];(s.x+s.y<o.x+o.y||s.x+s.y===o.x+o.y&&s.y<o.y)&&(a=i);}return [0,1,2,3].map(i=>n[(a+i)%4])}function H(e){let t=0;for(let r=0;r<e.length;r++){let n=e[r],a=e[(r+1)%e.length];t+=n.x*a.y-a.x*n.y;}return Math.abs(t)/2}function ee(e){let[t,r,n,a]=e;return {top:Math.hypot(r.x-t.x,r.y-t.y),right:Math.hypot(n.x-r.x,n.y-r.y),bottom:Math.hypot(n.x-a.x,n.y-a.y),left:Math.hypot(a.x-t.x,a.y-t.y)}}function Rt(e){let t=[0,0,0,0];for(let r=0;r<4;r++){let n=e[(r+3)%4],a=e[r],i=e[(r+1)%4],s=n.x-a.x,o=n.y-a.y,l=i.x-a.x,c=i.y-a.y,d=Math.hypot(s,o),p=Math.hypot(l,c);if(d===0||p===0){t[r]=0;continue}let m=Math.min(1,Math.max(-1,(s*l+o*c)/(d*p)));t[r]=Math.acos(m)*180/Math.PI;}return t}function te(e,t=70,r=110){let n=ee(e);return n.top<=0||n.right<=0||n.bottom<=0||n.left<=0||!vt(e)||H(e)<=0?false:Rt(e).every(a=>a>=t&&a<=r)}function vt(e){let t=0;for(let r=0;r<4;r++){let n=e[r],a=e[(r+1)%4],i=e[(r+2)%4],s=(a.x-n.x)*(i.y-a.y)-(a.y-n.y)*(i.x-a.x);if(s===0)return false;let o=Math.sign(s);if(t===0)t=o;else if(o!==t)return false}return true}function j(e){let t=ee(e),r=(t.top+t.bottom)/2,n=(t.left+t.right)/2,a=Math.min(r,n);return a<=0?0:Math.max(r,n)/a}function kt(e){if(!Number.isFinite(e))return 0;let t=Math.min(Math.abs(e-O),Math.abs(e-I));return Math.max(0,1-t/Tt)}function He(e){return .5*e.areaRatio+.3*e.rectangularity+.2*kt(e.aspect)}function re(e){let t=e>=Ct?O:I;return Math.abs(e-t)/t<=wt?t===O?"INE":"PASSPORT_MX":"OTHER"}function be(e){return e>=Z&&e<=ye}function Le(e,t){return e==="INE"?O:e==="PASSPORT_MX"?I:t}var z=1024,Ue=1600;function Qe(e,t,r,n,a=z){let i=Et(Le(n,j(r))),s=Math.max(1,Math.round(a/i)),o=ee(r),l=o.top+o.bottom<o.left+o.right,c=n==="INE"||n==="PASSPORT_MX",d=l&&c?[r[3],r[0],r[1],r[2]]:r,p=!l||c,m=p?a:s,u=p?s:a,x=null,S=null,y=null,b=null,h=null,f=null;try{return x=e.matFromImageData(t),S=new e.Mat,y=e.matFromArray(4,1,e.CV_32FC2,[d[0].x,d[0].y,d[1].x,d[1].y,d[2].x,d[2].y,d[3].x,d[3].y]),b=e.matFromArray(4,1,e.CV_32FC2,[0,0,m,0,m,u,0,u]),h=e.getPerspectiveTransform(y,b),e.warpPerspective(x,S,h,new e.Size(m,u),e.INTER_LINEAR,e.BORDER_CONSTANT,new e.Scalar(0,0,0,255)),S.channels()!==4&&(f=new e.Mat,e.cvtColor(S,f,e.COLOR_BGR2RGBA)),_t(new Uint8ClampedArray((f??S).data),m,u)}finally{for(let T of [f,h,b,y,S,x])T?.delete();}}function qe(e,t,r,n,a=z){let i=t.getContext("2d",{willReadFrequently:true});if(!i)throw new Error("2D canvas context unavailable");let s=i.getImageData(0,0,t.width,t.height),o=Qe(e,s,r,n,a),l=document.createElement("canvas");l.width=o.width,l.height=o.height;let c=l.getContext("2d");if(!c)throw new Error("2D canvas context unavailable (output)");return c.putImageData(o,0,0),l}async function Mt(e,t,r,n,a=.92,i=z){let s=r?qe(e,t,r,n,i):t;return new Promise((o,l)=>{s.toBlob(c=>c?o(c):l(new Error("Canvas toBlob returned null")),"image/jpeg",a);})}function Et(e){return Number.isFinite(e)?Math.min(ye,Math.max(Z,e)):Z}function _t(e,t,r){return typeof globalThis.ImageData=="function"?new ImageData(e,t,r):{data:e,width:t,height:r,colorSpace:"srgb"}}var M={brightnessMin:.18,brightnessMax:.9,blurMin:60,glareMax:.04,fillMin:.25,glarePixel:248};function V(e,t,r){let n=new Int32Array(r*2);for(let a=0;a<r;a++){let i=a+.5,s=1/0,o=-1/0;for(let l=0;l<4;l++){let c=e[l],d=e[(l+1)%4],p=Math.min(c.y,d.y),m=Math.max(c.y,d.y);if(i<p||i>m||m===p)continue;let u=c.x+(i-c.y)*(d.x-c.x)/(d.y-c.y);u<s&&(s=u),u>o&&(o=u);}if(s===1/0){n[a*2]=0,n[a*2+1]=0;continue}n[a*2]=Math.max(0,Math.ceil(s-.5)),n[a*2+1]=Math.min(t,Math.floor(o+.5));}return n}function ge(e,t){let{data:r,width:n,height:a}=e,i=V(t,n,a),s=M.glarePixel,o=0,l=0,c=0,d=0,p=0,m=0;for(let f=0;f<a;f++){let T=i[f*2],w=i[f*2+1];if(T>=w)continue;let v=0,R=0;f>0&&f<a-1&&(v=Math.max(T,i[(f-1)*2],i[(f+1)*2])+1,R=Math.min(w,i[(f-1)*2+1],i[(f+1)*2+1])-1);let C=f*n;for(let k=T;k<w;k++){let A=C+k,E=r[A];if(o+=E,E>=s&&l++,c++,k>=v&&k<R){let P=4*E-r[A-n]-r[A+n]-r[A-1]-r[A+1];d+=P,p+=P*P,m++;}}}let u=c>0?o/c/255:0,x=c>0?l/c:0,S=m>0?Math.max(0,p/m-(d/m)**2):0,y=n*a,b=y>0?H(t)/y:0,h=u>=M.brightnessMin&&u<=M.brightnessMax&&S>=M.blurMin&&x<=M.glareMax&&b>=M.fillMin;return {brightness:u,blurScore:S,glareRatio:x,docFillRatio:b,ok:h}}function Ne(e){let{data:t}=e;if(t.length===0)return 0;let r=0;for(let n=0;n<t.length;n++)r+=t[n];return r/t.length/255}function xe(e){if(!e.detected||!e.quality)return "no_document";let t=e.quality;return !Number.isFinite(t.docFillRatio)||t.docFillRatio<M.fillMin?"too_small":!Number.isFinite(t.brightness)||t.brightness<M.brightnessMin?"too_dark":!Number.isFinite(t.glareRatio)||t.glareRatio>M.glareMax||t.brightness>M.brightnessMax?"glare":!Number.isFinite(t.blurScore)||t.blurScore<M.blurMin?"blurry":e.stableFrames<e.stableFramesRequired?"hold_still":"ready"}var At=M.brightnessMin;function Xe(e){return !e.torchSupported||e.torchOn?false:(e.quality?e.quality.brightness:e.frameBrightness)<At}var Se=Object.freeze({idle:"Toca para activar la c\xE1mara",starting:"Abriendo la c\xE1mara\u2026",loading_detector:"Preparando la c\xE1mara\u2026",no_document:"Coloca tu identificaci\xF3n dentro del recuadro",too_small:"Acerca m\xE1s tu identificaci\xF3n",too_dark:"Hay poca luz, busca un lugar m\xE1s iluminado",glare:"Hay un reflejo, inclina un poco tu identificaci\xF3n",blurry:"Espera a que la c\xE1mara enfoque",hold_still:"Mant\xE9n la c\xE1mara quieta",ready:"\xA1Perfecto! Toma la foto",capturing:"Tomando la foto\u2026",uploading:"Revisando tu identificaci\xF3n\u2026",done:"\xA1Listo!",error:"Algo sali\xF3 mal, int\xE9ntalo de nuevo",detector_unavailable:"Toma la foto con el bot\xF3n",retake:"Tomar otra vez",capture:"Tomar foto",tip_light:"Busca un lugar con buena luz",tip_glare:"Evita reflejos: no apuntes una l\xE1mpara directo a tu identificaci\xF3n",tip_focus:"Espera a que la c\xE1mara enfoque y luego toca el bot\xF3n",tips_dismiss:"Entendido"}),Ft=Object.freeze({idle:"Ready to start",starting:"Starting camera\u2026",loading_detector:"Loading detector\u2026",no_document:"Place the document inside the frame",too_small:"Move closer to the document",too_dark:"Find more light",glare:"Tilt the document to avoid glare",blurry:"Hold still to focus",hold_still:"Hold the camera steady",ready:"Perfect! Take the photo",capturing:"Capturing\u2026",uploading:"Processing document\u2026",done:"Done",error:"Something went wrong \u2014 try again",detector_unavailable:"Detector unavailable \u2014 capture manually",retake:"Capture again",capture:"Capture now",tip_light:"Find a well-lit place",tip_glare:"Avoid glare: don't point a lamp straight at your ID",tip_focus:"Wait for the camera to focus, then tap the button",tips_dismiss:"Got it"}),Pt=["loading_detector","capturing","uploading","done","error"];function Ot(e){return Pt.includes(e)}function G(e,t){return t?.[e]??Se[e]}function Ce(e){let t={...Se};for(let r of Object.keys(t))t[r]=G(r,e);return t}function ne(e,t,r){return e==="idle"||e==="stopped"?G("idle",r):e==="starting"?G("starting",r):Ot(e)?G(e,r):G(t??"no_document",r)}var Dt=.05;function It(e,t,r){let n=r.width/t.width,a=r.height/t.height;return e.map(i=>({x:i.x*n,y:i.y*a}))}function Ht(e,t){return e.map(r=>({x:Math.min(t.width,Math.max(0,r.x)),y:Math.min(t.height,Math.max(0,r.y))}))}function Be(e,t,r){let n=Ht(It(e,t,r),r);return !te(n)||H(n)<Dt*r.width*r.height?null:n}var We={stableFrames:0,isStable:false,quad:null,typeHint:null},Y=class{required;maxRatio;switchFrames;current=We;candidate=null;constructor(t={}){this.required=t.stableFramesRequired??10,this.maxRatio=t.maxDisplacementRatio??.015,this.switchFrames=Math.max(1,t.hintSwitchFrames??3);}get snapshot(){return this.current}reset(){this.current=We,this.candidate=null;}update(t,r){if(!t)return this.reset(),this.current;let n=Math.hypot(r.width,r.height)*this.maxRatio,a=this.current,i=a.quad!==null&&a.quad.every((l,c)=>Math.hypot(t.quad[c].x-l.x,t.quad[c].y-l.y)<=n),s=a.typeHint??t.typeHint,o=i?a.stableFrames+1:1;if(t.typeHint===s)this.candidate=null;else {let l=this.candidate?.typeHint===t.typeHint?this.candidate.frames+1:1;this.candidate={typeHint:t.typeHint,frames:l},l>=this.switchFrames&&(s=t.typeHint,o=1,this.candidate=null);}return this.current={stableFrames:o,isStable:o>=this.required,quad:t.quad,typeHint:s},this.current}};var Ut=640,Qt=10,je=1500,qt=35e3,Nt=5,Xt={createWorkerClient:e=>new W(e),attachCamera:e=>le(e),detachCamera:ce,sampleFrame:de,grabFrame:Ee,encodeJpeg:_e,snapshotToBlob:ue,supportsTorch:pe,setTorch:me,now:()=>performance.now()},ze=e=>e.provenance==="reduced"||e.provenance==="lowres",Ve=e=>e instanceof Error?e:new Error(String(e)),Ge=e=>e.map(t=>({x:t.x,y:t.y})),K=class{opts;deps;stream=null;track=null;cv=null;generation=0;timer=null;frameCallback=null;inFlight=null;warmupUntil=0;capturing=false;autoShutterSpent=false;torchSupported=false;torchOn=false;torchRejected=false;weakRun=false;prior=null;stability;state={status:"idle",lastFrame:null,lastResult:null,lastError:null};constructor(t,r={}){this.opts={videoElement:t.videoElement,documentTypes:t.documentTypes??["INE","PASSPORT_MX"],autoCapture:t.autoCapture??false,stableFramesRequired:t.stableFramesRequired??10,captureQuality:t.captureQuality??.92,captureResolution:t.captureResolution??"standard",opencvUrl:t.opencvUrl,workerUrl:t.workerUrl,onUpload:t.onUpload,onFrameAnalyzed:t.onFrameAnalyzed,onCaptured:t.onCaptured,onResult:t.onResult,onError:t.onError},this.deps={...Xt,...r},this.stability=new Y({stableFramesRequired:this.opts.stableFramesRequired});}async start(){if(!["idle","stopped","error"].includes(this.state.status))throw new Error(`Cannot start session from status=${this.state.status}`);this.release();let t=++this.generation;this.setStatus("starting"),this.state.lastError=null;try{let r=await this.deps.attachCamera(this.opts.videoElement);if(t!==this.generation){this.deps.detachCamera(this.opts.videoElement,r);return}this.stream=r,this.track=r.getVideoTracks()[0]??null,this.torchSupported=this.track?this.deps.supportsTorch(this.track):!1,this.warmupUntil=0,this.setStatus("loading_detector");let n=this.deps.createWorkerClient({initTimeoutMs:qt});this.cv=n,n.init(this.opts.opencvUrl,this.opts.workerUrl).then(()=>{t!==this.generation||this.cv!==n||(this.state.status==="loading_detector"&&this.setStatus("streaming"),this.scheduleNext(t,0));},a=>this.detectorUnavailable(t,n,a));}catch(r){throw t===this.generation&&this.emitError(r),r}}stop(){this.generation++,this.release(),this.setStatus("stopped");}async captureNow(){if(this.capturing)return;let t=this.state.status;if(t!=="streaming"&&t!=="loading_detector"&&!(t==="done"&&this.stream))throw new Error(`Cannot capture from status=${this.state.status}`);let r=this.stability.snapshot,n=this.state.lastFrame?.frameSize??null,a=r.quad&&n?this.fullFrameQuad(r.quad,n):null;await this.doCapture(this.generation,a?r.typeHint:null,a);}getState(){return {...this.state}}scheduleNext(t,r){this.timer=setTimeout(()=>{if(this.timer=null,t!==this.generation)return;let n=this.opts.videoElement;typeof n.requestVideoFrameCallback=="function"?this.frameCallback=n.requestVideoFrameCallback(()=>{this.frameCallback=null,this.tick(t);}):this.tick(t);},r);}async tick(t){if(t!==this.generation)return;let r=this.deps.now();try{await this.analyzeFrame(t);}catch(n){t===this.generation&&console.warn("[xid-camera-ocr] analyzeFrame error:",n);}t!==this.generation||!this.cv||this.scheduleNext(t,Math.max(0,1e3/Qt-(this.deps.now()-r)));}async analyzeFrame(t){let r=this.cv;if(this.capturing||!r?.isReady())return;let n=this.deps.sampleFrame(this.opts.videoElement,Ut);if(!n)return;let a={width:n.width,height:n.height};this.warmupUntil===0&&(this.warmupUntil=this.deps.now()+je);let i=this.prior&&this.prior.width===n.width&&this.prior.height===n.height?this.prior.quad:null,s=r.analyze(n,i?{prior:i}:{});this.inFlight=s;let o;try{o=await s;}catch(u){if(t===this.generation&&this.cv===r&&!r.isReady()){this.detectorUnavailable(t,r,u);return}throw u}finally{this.inFlight===s&&(this.inFlight=null);}if(t!==this.generation||this.capturing)return;this.prior=o.detected&&o.corners?{quad:Ge(o.corners),...a}:null;let c=!(this.deps.now()<this.warmupUntil)&&o.detected&&o.corners&&o.documentType?{quad:o.corners,typeHint:o.documentType}:null,d=this.stability.update(c,a);this.weakRun=d.stableFrames<=1?c!==null&&ze(o):this.weakRun||ze(o);let p=this.opts.stableFramesRequired+(this.weakRun?Nt:0);if(await this.updateTorch(t,o),t!==this.generation)return;let m={detected:o.detected,documentType:o.documentType,confidence:Math.min(d.stableFrames/p,1),aspectRatio:o.aspectRatio,quality:o.quality,corners:o.corners?Ge(o.corners):null,frameSize:a,hint:xe({detected:o.detected,quality:o.quality,stableFrames:d.stableFrames,stableFramesRequired:p}),...this.torchSupported?{torch:this.torchOn}:{}};if(this.state.lastFrame=m,this.opts.onFrameAnalyzed?.(m),t===this.generation&&this.opts.autoCapture&&!this.autoShutterSpent&&d.quad&&d.stableFrames>=p&&o.quality?.ok){let u=this.fullFrameQuad(d.quad,a);if(!u){this.stability.reset(),this.weakRun=false;return}await this.doCapture(t,d.typeHint,u);}}detectorUnavailable(t,r,n){if(t!==this.generation||this.cv!==r)return;r.terminate(),this.cv=null,this.inFlight=null,this.prior=null,this.stability.reset(),this.weakRun=false,this.autoShutterSpent=true,this.state.status==="loading_detector"&&this.setStatus("streaming");let a=Ve(n);this.state.lastError=a;let i={detected:false,documentType:null,confidence:0,aspectRatio:null,quality:null,corners:null,frameSize:null,hint:"detector_unavailable",...this.torchSupported?{torch:this.torchOn}:{}};this.state.lastFrame=i,this.opts.onFrameAnalyzed?.(i),t===this.generation&&this.opts.onError?.(a);}async updateTorch(t,r){if(!this.track||this.torchRejected||!Xe({torchSupported:this.torchSupported,torchOn:this.torchOn,quality:r.quality,frameBrightness:r.frameBrightness}))return;let n=await this.deps.setTorch(this.track,true);t===this.generation&&(this.torchOn=n,n||(this.torchRejected=true));}fullFrameQuad(t,r){let n=this.opts.videoElement;return !n.videoWidth||!n.videoHeight?null:Be(t,r,{width:n.videoWidth,height:n.videoHeight})}async doCapture(t,r,n){if(!this.capturing){this.capturing=true,this.autoShutterSpent=true,this.prior=null,this.stability.reset(),this.weakRun=false,this.setStatus("capturing");try{let{blob:a,type:i}=await this.captureBlob(t,r,n);if(t!==this.generation)return;this.opts.onCaptured?.(a,i),this.setStatus("uploading");let s=await this.opts.onUpload(a,i);if(t!==this.generation)return;this.state.lastResult=s,this.setStatus("done"),this.opts.onResult?.(s);}catch(a){t===this.generation&&this.emitError(a);}finally{t===this.generation&&(this.stability.reset(),this.weakRun=false,this.warmupUntil=this.deps.now()+je,this.capturing=false);}}}async captureBlob(t,r,n){let a=this.opts.videoElement,i=async()=>({blob:await this.deps.snapshotToBlob(a,this.opts.captureQuality),type:null}),s=this.cv;if(!s?.isReady()||!n)return i();try{await this.inFlight?.catch(()=>{});let o=this.deps.grabFrame(a);if(!o||!s.isReady())return i();let l=this.opts.captureResolution==="high"?Ue:z,c=await s.warp(o,n,r,l);return {blob:await this.deps.encodeJpeg(c,this.opts.captureQuality),type:r}}catch(o){if(t!==this.generation)throw o;return console.warn("[xid-camera-ocr] warp failed, using plain snapshot:",o),i()}}release(){this.prior=null,this.timer!==null&&clearTimeout(this.timer),this.timer=null,this.frameCallback!==null&&(this.opts.videoElement.cancelVideoFrameCallback?.(this.frameCallback),this.frameCallback=null),this.track&&this.torchOn&&this.deps.setTorch(this.track,false),this.torchOn=false,this.torchRejected=false,this.stream&&this.deps.detachCamera(this.opts.videoElement,this.stream),this.stream=null,this.track=null,this.cv?.terminate(),this.cv=null,this.inFlight=null,this.stability.reset(),this.weakRun=false,this.capturing=false,this.autoShutterSpent=false;}setStatus(t){this.state.status=t;}emitError(t){let r=Ve(t);this.state.lastError=r,this.setStatus("error"),this.opts.onError?.(r);}};var Ye=.08,Bt=.95,Wt=.02,Q=8,jt=2,Ke=8,$e=.33,ae=2,zt=2,Vt=1,Gt=zt+ae,Yt=2,Kt=2*(ae+1),$t=10,Je=1.1,rt=ae+1,Jt=6,nt=.92,Zt=1/nt,er=.85,tr=2,rr=.05,Ze=2,et=64;function at(e){return {detected:false,documentType:null,aspectRatio:null,corners:null,boundingBox:null,quality:null,frameBrightness:e,score:null}}function nr(e,t,r,n={}){let a={brightness:0};try{return ar(e,t,a,n.prior??null)}catch(i){return console.warn("[xid-camera-ocr] detectDocumentCV failed:",i),at(a.brightness)}}function ar(e,t,r,n){let{width:a,height:i}=t,s=[],o=l=>(s.push(l),l);try{let l=o(e.matFromImageData(t)),c=o(new e.Mat),d=o(new e.Mat),p={equalized:o(new e.Mat),filtered:o(new e.Mat),padded:o(new e.Mat),edges:o(new e.Mat),dilated:o(new e.Mat),kernel:o(e.Mat.ones(3,3,e.CV_8U)),contours:o(new e.MatVector),hierarchy:o(new e.Mat),hull:o(new e.Mat),approx:o(new e.Mat),clahe:o(new e.CLAHE(jt,new e.Size(Ke,Ke)))};e.cvtColor(l,c,e.COLOR_RGBA2GRAY),r.brightness=Ne(we(c,a,i));let m=[],u=tt(e,c,p,a,i,m,n),x=!1,S=Math.round(a/Ze),y=Math.round(i/Ze);if(!u&&S>=et&&y>=et&&(e.resize(c,d,new e.Size(S,y),0,0,e.INTER_AREA),u=tt(e,d,p,a,i,m,n),x=u!==null),u&&ur(u,m,we(c,a,i))&&(u=null),!u)return at(r.brightness);let b=x?"lowres":u.reduced?"reduced":"direct",h=u.quad.map(C=>C.x),f=u.quad.map(C=>C.y),T=Math.min(...h),w=Math.max(...h),v=Math.min(...f),R=Math.max(...f);return {detected:!0,documentType:re(u.aspect),aspectRatio:u.aspect,corners:u.quad,boundingBox:{x:T/a,y:v/i,width:(w-T)/a,height:(R-v)/i},quality:ge(we(c,a,i),st(u.quad,rt*u.scale)),frameBrightness:r.brightness,score:b==="direct"?u.score:u.score*er,provenance:b}}finally{for(let l of s)l.delete();}}function tt(e,t,r,n,a,i,s){let o=t.cols,l=t.rows,c=n/o,d=a/l,p=o*l,m=h=>({x:h.x*c,y:h.y*d}),{hull:u,approx:x,contours:S}=r;r.clahe.apply(t,r.equalized),e.bilateralFilter(r.equalized,r.filtered,9,75,75,e.BORDER_DEFAULT),e.copyMakeBorder(r.filtered,r.padded,Q,Q,Q,Q,e.BORDER_CONSTANT,new e.Scalar(0));let y=hr(r.padded.data);e.Canny(r.padded,r.edges,Math.max(10,(1-$e)*y),Math.min(255,(1+$e)*y)),e.dilate(r.edges,r.dilated,r.kernel,new e.Point(-1,-1),ae),e.findContours(r.dilated,S,r.hierarchy,e.RETR_LIST,e.CHAIN_APPROX_SIMPLE);let b=null;for(let h=0;h<S.size();h++){let f=S.get(h);try{let T=e.boundingRect(f);if(T.width*T.height<p*Ye)continue;e.convexHull(f,u,!1,!0);let w=e.contourArea(u);if(w<p*Ye||w>p*Bt||(e.approxPolyDP(u,x,Wt*e.arcLength(u,!0),!0),x.rows<4||x.rows>Jt||!e.isContourConvex(x)))continue;let v=x.rows!==4,R;if(!v)R=ir(x,o,l);else {let L=sr(ot(x));if(!L)continue;R=L.map(bt=>it(bt,o,l));let D=w/H(R);if(!(D>=nt&&D<=Zt))continue}let C=w*c*d,k=R.map(m),A=Gt*c;if(mr(k,n,a,A)>Vt){cr(k,n,a,A)||i.push({pts:k,area:C});continue}let E=fe(k);if(!te(E))continue;let P=e.minAreaRect(v?u:x),q=P.size.width*P.size.height,se=q>0?Math.min(1,w/q):0,N=j(E);if(!be(N))continue;let X=He({areaRatio:w/p,rectangularity:se,aspect:N}),B=s?X-or(E,s,n,a):X;(!b||B>b.rank)&&(b={quad:E,score:X,rank:B,aspect:N,area:C,scale:c,reduced:v});}finally{f.delete();}}return b}function or(e,t,r,n){let a=1/0;for(let i=0;i<4;i++){let s=0;for(let o=0;o<4;o++){let l=e[(o+i)%4];s=Math.max(s,Math.hypot(l.x-t[o].x,l.y-t[o].y));}a=Math.min(a,s);}return tr*Math.min(a/Math.hypot(r,n),rr)}function we(e,t,r){return {data:e.data,width:t,height:r}}function ot(e){let t=e.data32S,r=[];for(let n=0;n<e.rows;n++)r.push({x:t[n*2]-Q,y:t[n*2+1]-Q});return r}function it(e,t,r){return {x:Math.min(t,Math.max(0,e.x)),y:Math.min(r,Math.max(0,e.y))}}function ir(e,t,r){return ot(e).map(n=>it(n,t,r))}function sr(e){let t=e;for(;t.length>4;){let r=t.length,n=-1,a=1/0,i=null;for(let o=0;o<r;o++){let l=t[(o+r-1)%r],c=t[o],d=t[(o+1)%r],p=t[(o+2)%r],m=lr(l,c,p,d);if(!m)continue;let u=Math.abs((m.x-c.x)*(d.y-c.y)-(m.y-c.y)*(d.x-c.x))/2;u<a&&(a=u,n=o,i=m);}if(n<0||!i)return null;let s=[];for(let o=0;o<r;o++)o===n?s.push(i):o!==(n+1)%r&&s.push(t[o]);t=s;}return t}function lr(e,t,r,n){let a=t.x-e.x,i=t.y-e.y,s=n.x-r.x,o=n.y-r.y,l=a*o-i*s;if(Math.abs(l)<1e-9)return null;let c=((r.x-e.x)*o-(r.y-e.y)*s)/l,d=((r.x-e.x)*i-(r.y-e.y)*a)/l;return c<1||d<1?null:{x:e.x+c*a,y:e.y+c*i}}function cr(e,t,r,n){let a=e.map(s=>s.x),i=e.map(s=>s.y);return Math.min(...a)<=n&&Math.max(...a)>=t-n||Math.min(...i)<=n&&Math.max(...i)>=r-n}function ur(e,t,r){let n=Kt*e.scale;if(!t.some(o=>o.area>=Yt*e.area&&e.quad.every(l=>pr(o.pts,l,n))))return false;if(re(e.aspect)==="OTHER")return true;let{inner:i,ring:s}=dr(r,st(e.quad,rt*e.scale),e.quad);return i<s-$t}function dr(e,t,r){let{data:n,width:a,height:i}=e,s=(r[0].x+r[1].x+r[2].x+r[3].x)/4,o=(r[0].y+r[1].y+r[2].y+r[3].y)/4,l=r.map(y=>({x:s+(y.x-s)*Je,y:o+(y.y-o)*Je})),c=V(l,a,i),d=V(r,a,i),p=V(t,a,i),m=0,u=0,x=0,S=0;for(let y=0;y<i;y++){let b=c[y*2],h=c[y*2+1];if(b>=h)continue;let f=d[y*2],T=d[y*2+1],w=p[y*2],v=p[y*2+1],R=y*a;for(let C=b;C<h;C++){let k=n[R+C];C>=w&&C<v?(m+=k,u++):(C<f||C>=T)&&(x+=k,S++);}}return {inner:u>0?m/u:0,ring:S>0?x/S:0}}function pr(e,t,r){let n=0;for(let i=0;i<e.length;i++){let s=e[i],o=e[(i+1)%e.length];n+=s.x*o.y-o.x*s.y;}let a=Math.sign(n);if(a===0)return false;for(let i=0;i<e.length;i++){let s=e[i],o=e[(i+1)%e.length],l=Math.hypot(o.x-s.x,o.y-s.y);if(l===0)continue;if(a*((o.x-s.x)*(t.y-s.y)-(o.y-s.y)*(t.x-s.x))/l<r)return false}return true}function st(e,t){return e.map((r,n)=>{let a=e[(n+3)%4],i=e[(n+1)%4],s=a.x-r.x,o=a.y-r.y,l=i.x-r.x,c=i.y-r.y,d=Math.hypot(s,o),p=Math.hypot(l,c),m=s/d+l/p,u=o/d+c/p,x=Math.hypot(m,u),S=Math.sin(Math.acos(Math.min(1,Math.max(-1,(s*l+o*c)/(d*p))))/2),y=t/S/x;return {x:r.x+m*y,y:r.y+u*y}})}function mr(e,t,r,n){let a=0;for(let i of e)(i.x<=n||i.x>=t-n||i.y<=n||i.y>=r-n)&&a++;return a}function hr(e){let t=new Uint32Array(256);for(let n=0;n<e.length;n++)t[e[n]]++;let r=0;for(let n=0;n<256;n++)if(r+=t[n],r>=e.length/2)return n;return 128}function Re(e){let t=useRef(null),r=useRef(null),[n,a]=useState("idle"),[i,s]=useState(null),[o,l]=useState(null),[c,d]=useState(null),p=useRef(e);p.current=e;let m=useCallback(()=>{if(r.current)return r.current;if(!t.current)throw new Error("videoRef not attached yet");let b=new K({videoElement:t.current,documentTypes:p.current.documentTypes,autoCapture:p.current.autoCapture,stableFramesRequired:p.current.stableFramesRequired,captureQuality:p.current.captureQuality,captureResolution:p.current.captureResolution,opencvUrl:p.current.opencvUrl,workerUrl:p.current.workerUrl,onUpload:(h,f)=>p.current.onUpload(h,f),onFrameAnalyzed:h=>{s(h),r.current===b&&a(b.getState().status),p.current.onFrameAnalyzed?.(h);},onCaptured:(h,f)=>{a("capturing"),p.current.onCaptured?.(h,f);},onResult:h=>{l(h),a("done"),p.current.onResult?.(h);},onError:h=>{d(h),r.current===b&&a(b.getState().status),p.current.onError?.(h);}});return r.current=b,b},[]),u=useCallback(async()=>{let b=m();await b.start(),r.current===b&&a(b.getState().status);},[m]),x=useCallback(()=>{r.current?.stop(),a("stopped");},[]),S=useCallback(async()=>{await r.current?.captureNow();},[]),y=useCallback(async()=>{x(),l(null),d(null),s(null),await u();},[x,u]);return useEffect(()=>(e.autoStart!==false&&t.current&&u().catch(()=>{}),()=>{r.current?.stop(),r.current=null;}),[]),{videoRef:t,status:n,frame:i,result:o,error:c,start:u,stop:x,captureNow:S,retake:y}}function br({status:e,showTips:t,dismissed:r,completedOnce:n}){return t&&!r&&(e==="error"||!n&&(e==="starting"||e==="loading_detector"))}function lt(e,t){let[r,n]=useState(false),[a,i]=useState(e==="done"),[s,o]=useState(e),l=r,c=a;s!==e&&(o(e),e==="error"&&(l=false,n(false)),e==="done"&&(c=true,i(true)));let d=useCallback(()=>n(true),[]);return {visible:br({status:e,showTips:t,dismissed:l,completedOnce:c}),dismiss:d}}var ie={accent:{name:"--xco-accent",fallback:"#22c55e"},warning:{name:"--xco-warning",fallback:"#eab308"},danger:{name:"--xco-danger",fallback:"#ef4444"},background:{name:"--xco-background",fallback:"#000"},mask:{name:"--xco-mask",fallback:"rgba(0,0,0,0.4)"},hintBg:{name:"--xco-hint-bg",fallback:"rgba(0,0,0,0.7)"},hintFg:{name:"--xco-hint-fg",fallback:"white"},buttonBg:{name:"--xco-button-bg",fallback:"rgba(255,255,255,0.92)"},buttonFg:{name:"--xco-button-fg",fallback:"#111"},shutter:{name:"--xco-shutter",fallback:"rgba(255,255,255,0.9)"},overlayBg:{name:"--xco-overlay-bg",fallback:"rgba(0,0,0,0.78)"},overlayFg:{name:"--xco-overlay-fg",fallback:"white"},fontFamily:{name:"--xco-font-family",fallback:"system-ui, -apple-system, sans-serif"},radius:{name:"--xco-radius",fallback:"12px"}};function g(e){let{name:t,fallback:r}=ie[e];return `var(${t}, ${r})`}function ct(e){let t={};if(!e)return t;for(let r of Object.keys(e)){if(!Object.prototype.hasOwnProperty.call(ie,r))continue;let n=e[r];typeof n!="string"||n===""||(t[ie[r].name]=n);}return t}function ut(e,t){return e==="done"?g("accent"):e==="error"?g("danger"):e==="uploading"||e==="capturing"?g("accent"):t?.detected?t.confidence>=1?g("accent"):g("warning"):g("danger")}var ke={width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",focusable:"false",style:{flex:"0 0 auto"}},gr=()=>jsxs("svg",{...ke,children:[jsx("circle",{cx:"12",cy:"12",r:"4"}),jsx("path",{d:"M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"})]}),xr=()=>jsxs("svg",{...ke,children:[jsx("rect",{x:"3",y:"5",width:"18",height:"14",rx:"2"}),jsx("path",{d:"M14 5l-6 14M18 5l-6 14"})]}),Sr=()=>jsxs("svg",{...ke,children:[jsx("path",{d:"M4 8V5a1 1 0 0 1 1-1h3M16 4h3a1 1 0 0 1 1 1v3M20 16v3a1 1 0 0 1-1 1h-3M8 20H5a1 1 0 0 1-1-1v-3"}),jsx("circle",{cx:"12",cy:"12",r:"2"})]});function dt({texts:e,onDismiss:t}){let r=[{Icon:gr,text:e.tip_light},{Icon:xr,text:e.tip_glare},{Icon:Sr,text:e.tip_focus}];return jsxs("div",{className:"xco-tips",style:Cr,children:[jsx("ul",{style:wr,children:r.map(({Icon:n,text:a})=>jsxs("li",{style:Tr,children:[jsx(n,{}),jsx("span",{children:a})]},a))}),jsx("button",{type:"button",className:"xco-tips-dismiss",onClick:t,style:Rr,children:e.tips_dismiss})]})}var Cr={position:"absolute",top:"calc(16px + env(safe-area-inset-top, 0px))",left:"50%",transform:"translateX(-50%)",boxSizing:"border-box",width:"calc(100% - 32px)",maxWidth:360,padding:16,background:g("overlayBg"),color:g("overlayFg"),borderRadius:g("radius"),fontFamily:g("fontFamily"),fontSize:15,lineHeight:1.35,display:"flex",flexDirection:"column",gap:12,pointerEvents:"auto",zIndex:5},wr={listStyle:"none",margin:0,padding:0,display:"flex",flexDirection:"column",gap:10},Tr={display:"flex",alignItems:"center",gap:12},Rr={alignSelf:"flex-end",minHeight:44,padding:"10px 20px",borderRadius:g("radius"),background:g("buttonBg"),color:g("buttonFg"),border:"none",fontFamily:g("fontFamily"),fontSize:15,fontWeight:600,cursor:"pointer",WebkitTapHighlightColor:"transparent"};var _r=typeof window>"u"?useEffect:useLayoutEffect;function mt({videoRef:e,status:t,frame:r,texts:n,documentTypes:a,theme:i,className:s,style:o,hideStatusOverlay:l,hideShutter:c,tipsVisible:d,onCapture:p,onRetake:m,onStart:u,onDismissTips:x}){let S=t==="streaming"||t==="loading_detector",y=t==="done"||t==="error",b=t==="idle"||t==="stopped",h=t==="capturing"||t==="uploading",f=useRef(null),[T,w]=useState({width:0,height:0}),v=r?.documentType,R=v==="PASSPORT_MX"?I:v==="INE"?O:a[0]==="PASSPORT_MX"?I:O;_r(()=>{let E=f.current;if(!E)return;let P=()=>{let se=E.clientWidth,N=E.clientHeight,X=se*.85,B=N*.7,L=X,D=L/R;D>B&&(D=B,L=D*R),w({width:L,height:D});};P();let q=new ResizeObserver(P);return q.observe(E),()=>q.disconnect()},[R]);let C=ut(t,r),k=ne(t,r?.hint,n),A=s?`xid-camera-ocr ${s}`:"xid-camera-ocr";return jsxs("div",{ref:f,className:A,"data-status":t,"data-hint":r?.hint??"",style:{...Ar,...ct(i),...o},children:[jsx("style",{children:"@keyframes xco-spin { to { transform: rotate(360deg); } }"}),jsx("video",{ref:e,playsInline:true,muted:true,autoPlay:true,style:Fr}),!l&&jsx("div",{style:Pr,children:jsx("div",{className:"xco-guide",style:{...Or,width:T.width,height:T.height,borderColor:C}})}),!l&&(b?jsx("button",{type:"button",className:"xco-hint",onClick:u,style:qr,children:k}):jsx("p",{className:"xco-hint",style:yt,role:"status","aria-live":"polite",children:k})),!l&&!c&&S&&jsx("button",{type:"button",className:"xco-shutter",onClick:p,"aria-label":n.capture,style:Lr,children:jsx("span",{style:Ur})}),!l&&y&&jsx("button",{type:"button",className:"xco-retake",onClick:m,"aria-label":n.retake,style:Qr,children:n.retake}),!l&&h&&jsxs("div",{className:"xco-loader",style:Dr,"aria-busy":"true","aria-live":"polite",children:[jsx("div",{style:Ir}),jsx("p",{style:Hr,children:ne(t,void 0,n)})]}),d&&!l&&jsx(dt,{texts:n,onDismiss:x})]})}var ht="calc(104px + env(safe-area-inset-bottom, 0px))",Ar={position:"relative",width:"100%",height:"100%",overflow:"hidden",background:g("background"),fontFamily:g("fontFamily"),touchAction:"none"},Fr={position:"absolute",inset:0,width:"100%",height:"100%",objectFit:"cover",display:"block"},Pr={position:"absolute",inset:0,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",pointerEvents:"none"},Or={borderRadius:g("radius"),borderWidth:4,borderStyle:"solid",boxShadow:`0 0 0 9999px ${g("mask")}`,transition:"border-color 200ms ease-in-out, width 200ms ease-in-out, height 200ms ease-in-out"},Dr={position:"absolute",inset:0,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:20,background:g("overlayBg"),backdropFilter:"blur(6px)",WebkitBackdropFilter:"blur(6px)",pointerEvents:"auto",zIndex:10},Ir={width:56,height:56,borderRadius:"50%",border:"5px solid rgba(255, 255, 255, 0.18)",borderTopColor:g("accent"),animation:"xco-spin 0.85s linear infinite"},Hr={color:g("overlayFg"),fontFamily:g("fontFamily"),fontSize:15,fontWeight:500,margin:0,textAlign:"center",padding:"0 24px"},Lr={position:"absolute",bottom:ht,left:"50%",transform:"translateX(-50%)",width:68,height:68,borderRadius:"50%",background:"rgba(255,255,255,0.18)",border:`4px solid ${g("shutter")}`,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",pointerEvents:"auto",WebkitTapHighlightColor:"transparent",padding:0},Ur={width:52,height:52,borderRadius:"50%",background:"white",display:"block"},Qr={position:"absolute",bottom:ht,left:"50%",transform:"translateX(-50%)",minHeight:44,padding:"10px 20px",borderRadius:22,background:g("buttonBg"),color:g("buttonFg"),border:"none",fontFamily:g("fontFamily"),fontSize:15,fontWeight:600,cursor:"pointer",pointerEvents:"auto",WebkitTapHighlightColor:"transparent"},yt={position:"absolute",bottom:"calc(16px + env(safe-area-inset-bottom, 0px))",left:"50%",transform:"translateX(-50%)",boxSizing:"border-box",width:"max-content",maxWidth:"calc(100% - 32px)",background:g("hintBg"),color:g("hintFg"),padding:"10px 16px",borderRadius:g("radius"),fontFamily:g("fontFamily"),fontSize:16,lineHeight:1.35,margin:0,whiteSpace:"normal",textAlign:"center"},qr={...yt,border:"none",minHeight:44,cursor:"pointer",pointerEvents:"auto",WebkitTapHighlightColor:"transparent"};var zr=["INE","PASSPORT_MX"],Me=()=>{},ft=forwardRef(function({className:t,style:r,hideStatusOverlay:n,texts:a,theme:i,showTips:s,hideShutter:o,onStatusChange:l,...c},d){let{videoRef:p,status:m,frame:u,start:x,captureNow:S,retake:y}=Re(c),b=lt(m,s??true),h=useMemo(()=>Ce(a),[a]),f=m==="streaming"||m==="loading_detector",T=m==="done"||m==="error",w=async()=>{f&&await S().catch(Me);},v=()=>{T&&y().catch(Me);},R=async()=>{await x().catch(Me);};useImperativeHandle(d,()=>({capture:w,retake:v,start:R}));let C=useRef(l);return C.current=l,useEffect(()=>{C.current?.(m);},[m]),jsx(mt,{videoRef:p,status:m,frame:u,texts:h,documentTypes:c.documentTypes??zr,theme:i,className:t,style:r,hideStatusOverlay:n,hideShutter:o,tipsVisible:b.visible,onCapture:()=>{w();},onRetake:v,onStart:()=>{R();},onDismissTips:b.dismiss})});ft.displayName="XidCameraOcr";export{W as CVWorkerClient,Ft as DEFAULT_TEXTS_EN,Se as DEFAULT_TEXTS_ES,O as ID1_RATIO,M as QUALITY_THRESHOLDS,Y as StabilityTracker,I as TD3_RATIO,ie as XCO_VARS,ft as XidCameraOcr,K as XidCameraOcrSession,le as attachCamera,ne as copyFor,xe as decideHint,he as defaultOpencvUrl,ce as detachCamera,nr as detectDocumentCV,be as isCapturableAspect,ge as measureQuality,fe as orderCorners,j as rectifiedAspect,Ce as resolveTexts,de as sampleFrame,me as setTorch,ue as snapshotToBlob,pe as supportsTorch,re as typeHintFromAspect,Re as useXidCameraOcr,qe as warpDocument,Qe as warpDocumentImageData,Mt as warpedSnapshotToBlob};//# sourceMappingURL=index.js.map
|
|
1
|
+
import {forwardRef,useMemo,useImperativeHandle,useRef,useEffect,useState,useCallback,useLayoutEffect}from'react';import {jsx,jsxs}from'react/jsx-runtime';function Rt(e=typeof window>"u"?void 0:window){return e?typeof e.matchMedia=="function"?e.matchMedia("(orientation: portrait)").matches?"portrait":"landscape":e.innerHeight>e.innerWidth?"portrait":"landscape":"landscape"}function Tt(e){return {audio:false,video:{facingMode:{ideal:"environment"},...e==="portrait"?{width:{ideal:1080},height:{ideal:1920},aspectRatio:{ideal:9/16}}:{width:{ideal:1920,min:640},height:{ideal:1080,min:480},aspectRatio:{ideal:16/9}}}}}async function ae(e,t,r=Rt()){let n=Tt(r);if(typeof navigator>"u"||!navigator.mediaDevices?.getUserMedia)throw new Error("Camera unavailable: getUserMedia requires a secure context (HTTPS or localhost) and a browser with MediaDevices support.");let o;try{o=await navigator.mediaDevices.getUserMedia(t??n);}catch(s){if(!t)o=await navigator.mediaDevices.getUserMedia({audio:false,video:true});else throw s}e.srcObject=o,e.muted=true,e.playsInline=true,e.autoplay=true;let a=o.getVideoTracks()[0],i=a.getCapabilities?.();return i&&"focusMode"in i&&i.focusMode?.includes("continuous")&&a.applyConstraints({advanced:[{focusMode:"continuous"}]}).catch(()=>{}),await e.play().catch(()=>{}),o}function ie(e,t){e.srcObject===t&&(e.srcObject=null),t?.getTracks().forEach(r=>r.stop());}async function se(e,t=.92){let r=e.videoWidth,n=e.videoHeight;if(!r||!n)throw new Error("Video stream not ready (videoWidth=0)");let o=document.createElement("canvas");o.width=r,o.height=n;let a=o.getContext("2d");if(!a)throw new Error("2D canvas context unavailable");return a.drawImage(e,0,0,r,n),new Promise((i,s)=>{o.toBlob(u=>u?i(u):s(new Error("Canvas toBlob returned null")),"image/jpeg",t);})}function Ae(e,t,r,n=.92){let o=document.createElement("canvas");o.width=r.width,o.height=r.height;let a=o.getContext("2d");return a?(a.imageSmoothingEnabled=true,a.imageSmoothingQuality="high",a.drawImage(e,t.x,t.y,t.width,t.height,0,0,r.width,r.height),new Promise((i,s)=>o.toBlob(u=>u?i(u):s(new Error("Canvas toBlob returned null")),"image/jpeg",n))):Promise.reject(new Error("2D canvas context unavailable"))}var H=null;function ue(e,t=640){let r=e.videoWidth,n=e.videoHeight;if(!r||!n)return null;let o=Math.round(t),a=Math.round(n*t/r);H??=document.createElement("canvas"),(H.width!==o||H.height!==a)&&(H.width=o,H.height=a);let i=H.getContext("2d",{willReadFrequently:true});return i?(i.drawImage(e,0,0,o,a),i.getImageData(0,0,o,a)):null}function ce(e){let t=e.getCapabilities;return typeof t!="function"?false:t.call(e).torch===true}async function le(e,t){try{return await e.applyConstraints({advanced:[{torch:t}]}),!0}catch{return false}}var Mt="@andresxid/xid_camera_ocr_sdk_react";function Pe(e,t){return e.pathname.endsWith(`/${Mt}/${t}`)}function Fe(e){return new URL(e,import.meta.url)}function Oe(){return new URL("@andresxid/xid_camera_ocr_sdk_react/opencv.js",import.meta.url)}function de(){let e=Oe();return Pe(e,"opencv.js")?Fe("./opencv.js").href:e.href}function De(e){return e!==void 0?new Worker(e,{type:"module"}):Pe(Oe(),"opencv.js")?new Worker(Fe("./cv-worker.js"),{type:"module"}):new Worker(new URL("@andresxid/xid_camera_ocr_sdk_react/cv-worker.js",import.meta.url),{type:"module"})}function Ie(e){if(!e||typeof e!="object")return null;let t=e;switch(t.type){case "ready":return {type:"ready"};case "init-error":return typeof t.error=="string"?{type:"init-error",error:t.error}:null;case "error":return typeof t.id=="number"&&typeof t.error=="string"?{type:"error",id:t.id,error:t.error}:null;case "analyze-result":return typeof t.id=="number"&&t.result&&typeof t.result=="object"?{type:"analyze-result",id:t.id,result:t.result}:null;case "warp-result":return typeof t.id=="number"&&typeof t.width=="number"&&typeof t.height=="number"&&t.buffer instanceof ArrayBuffer?{type:"warp-result",id:t.id,width:t.width,height:t.height,buffer:t.buffer}:null;default:return null}}function He(e){let t=new Uint8ClampedArray(e.data.byteLength);return t.set(e.data),t.buffer}var Et=e=>e instanceof Error?e:new Error(String(e)),B=class{initTimeoutMs;worker=null;readyPromise=null;rejectInit=null;initTimer=null;ready=false;pending=new Map;nextId=1;constructor(t={}){this.initTimeoutMs=t.initTimeoutMs??3e4;}init(t=de(),r){if(this.readyPromise)return this.readyPromise;let n;try{n=De(r);}catch(a){return Promise.reject(Et(a))}this.worker=n;let o=new Promise((a,i)=>{this.rejectInit=i,this.initTimer=setTimeout(()=>this.fail(new Error(`OpenCV worker not ready within ${this.initTimeoutMs} ms`)),this.initTimeoutMs),n.addEventListener("message",s=>{if(this.worker!==n)return;let u=Ie(s.data);if(!u)return;if(u.type==="ready"){this.clearInitTimer(),this.rejectInit=null,this.ready=true,a();return}if(u.type==="init-error"){this.fail(new Error(u.error));return}let c=this.pending.get(u.id);c&&(this.pending.delete(u.id),u.type==="error"?c.reject(new Error(u.error)):c.resolve(u));}),n.addEventListener("error",s=>{this.worker===n&&this.fail(new Error(s.message||"Worker error"));}),n.addEventListener("messageerror",s=>{if(this.worker!==n)return;let u=new Error("Worker message could not be deserialized"),c=s.data?.id,d=typeof c=="number"?this.pending.get(c):void 0;if(typeof c=="number"&&d){this.pending.delete(c),d.reject(u);return}this.fail(u);});});return this.readyPromise=o,n.postMessage({type:"init",opencvUrl:t}),o}isReady(){return this.ready&&this.worker!==null}async analyze(t,r={}){let n=He(t),o=r.prior,a=await this.request(i=>({type:"analyze",id:i,width:t.width,height:t.height,buffer:n,...o?{prior:o}:{}}),[n]);if(a.type!=="analyze-result")throw new Error(`Unexpected worker response: ${a.type}`);return a.result}async warp(t,r,n,o=1024){let a=He(t),i=await this.request(s=>({type:"warp",id:s,width:t.width,height:t.height,buffer:a,corners:r,docType:n,longSide:o}),[a]);if(i.type!=="warp-result")throw new Error(`Unexpected worker response: ${i.type}`);return new ImageData(new Uint8ClampedArray(i.buffer),i.width,i.height)}terminate(){this.rejectInit=null,this.shutdown(new Error("Worker terminated"));}fail(t){let r=this.rejectInit;this.rejectInit=null,this.shutdown(t),r?.(t);}clearInitTimer(){this.initTimer!==null&&clearTimeout(this.initTimer),this.initTimer=null;}shutdown(t){this.clearInitTimer(),this.worker?.terminate(),this.worker=null,this.readyPromise=null,this.ready=false;let r=[...this.pending.values()];this.pending.clear();for(let n of r)n.reject(t);}request(t,r){let n=this.worker;if(!n||!this.ready)return Promise.reject(new Error("CVWorkerClient not ready"));let o=t(this.nextId++),a=new Promise((i,s)=>this.pending.set(o.id,{resolve:i,reject:s}));return n.postMessage(o,r),a}};var O=1.585772508336421,L=125/88,kt=1.503,_t=.05,Y=1.25,pe=1.75,At=.25;function me(e){if(e.length!==4)throw new Error(`orderCorners expects 4 points, got ${e.length}`);let t=(e[0].x+e[1].x+e[2].x+e[3].x)/4,r=(e[0].y+e[1].y+e[2].y+e[3].y)/4,n=[...e].sort((a,i)=>Math.atan2(a.y-r,a.x-t)-Math.atan2(i.y-r,i.x-t)),o=0;for(let a=1;a<4;a++){let i=n[a],s=n[o];(i.x+i.y<s.x+s.y||i.x+i.y===s.x+s.y&&i.y<s.y)&&(o=a);}return [0,1,2,3].map(a=>n[(o+a)%4])}function D(e){let t=0;for(let r=0;r<e.length;r++){let n=e[r],o=e[(r+1)%e.length];t+=n.x*o.y-o.x*n.y;}return Math.abs(t)/2}function K(e){let[t,r,n,o]=e;return {top:Math.hypot(r.x-t.x,r.y-t.y),right:Math.hypot(n.x-r.x,n.y-r.y),bottom:Math.hypot(n.x-o.x,n.y-o.y),left:Math.hypot(o.x-t.x,o.y-t.y)}}function Pt(e){let t=[0,0,0,0];for(let r=0;r<4;r++){let n=e[(r+3)%4],o=e[r],a=e[(r+1)%4],i=n.x-o.x,s=n.y-o.y,u=a.x-o.x,c=a.y-o.y,d=Math.hypot(i,s),p=Math.hypot(u,c);if(d===0||p===0){t[r]=0;continue}let m=Math.min(1,Math.max(-1,(i*u+s*c)/(d*p)));t[r]=Math.acos(m)*180/Math.PI;}return t}function $(e,t=70,r=110){let n=K(e);return n.top<=0||n.right<=0||n.bottom<=0||n.left<=0||!Ft(e)||D(e)<=0?false:Pt(e).every(o=>o>=t&&o<=r)}function Ft(e){let t=0;for(let r=0;r<4;r++){let n=e[r],o=e[(r+1)%4],a=e[(r+2)%4],i=(o.x-n.x)*(a.y-o.y)-(o.y-n.y)*(a.x-o.x);if(i===0)return false;let s=Math.sign(i);if(t===0)t=s;else if(s!==t)return false}return true}function Q(e){let t=K(e),r=(t.top+t.bottom)/2,n=(t.left+t.right)/2,o=Math.min(r,n);return o<=0?0:Math.max(r,n)/o}function Ot(e){if(!Number.isFinite(e))return 0;let t=Math.min(Math.abs(e-O),Math.abs(e-L));return Math.max(0,1-t/At)}function Le(e){return .5*e.areaRatio+.3*e.rectangularity+.2*Ot(e.aspect)}function Z(e){let t=e>=kt?O:L;return Math.abs(e-t)/t<=_t?t===O?"INE":"PASSPORT_MX":"OTHER"}function he(e){return e>=Y&&e<=pe}function Ue(e,t){return e==="INE"?O:e==="PASSPORT_MX"?L:t}var X=1024,Be=1600;function Qe(e,t,r,n,o=X){let a=It(Ue(n,Q(r))),i=Math.max(1,Math.round(o/a)),s=K(r),u=s.top+s.bottom<s.left+s.right,c=n==="INE"||n==="PASSPORT_MX",d=u&&c?[r[3],r[0],r[1],r[2]]:r,p=!u||c,m=p?o:i,l=p?i:o,x=null,S=null,y=null,b=null,h=null,f=null;try{return x=e.matFromImageData(t),S=new e.Mat,y=e.matFromArray(4,1,e.CV_32FC2,[d[0].x,d[0].y,d[1].x,d[1].y,d[2].x,d[2].y,d[3].x,d[3].y]),b=e.matFromArray(4,1,e.CV_32FC2,[0,0,m,0,m,l,0,l]),h=e.getPerspectiveTransform(y,b),e.warpPerspective(x,S,h,new e.Size(m,l),e.INTER_LINEAR,e.BORDER_CONSTANT,new e.Scalar(0,0,0,255)),S.channels()!==4&&(f=new e.Mat,e.cvtColor(S,f,e.COLOR_BGR2RGBA)),Ht(new Uint8ClampedArray((f??S).data),m,l)}finally{for(let R of [f,h,b,y,S,x])R?.delete();}}function Xe(e,t,r,n,o=X){let a=t.getContext("2d",{willReadFrequently:true});if(!a)throw new Error("2D canvas context unavailable");let i=a.getImageData(0,0,t.width,t.height),s=Qe(e,i,r,n,o),u=document.createElement("canvas");u.width=s.width,u.height=s.height;let c=u.getContext("2d");if(!c)throw new Error("2D canvas context unavailable (output)");return c.putImageData(s,0,0),u}async function Dt(e,t,r,n,o=.92,a=X){let i=r?Xe(e,t,r,n,a):t;return new Promise((s,u)=>{i.toBlob(c=>c?s(c):u(new Error("Canvas toBlob returned null")),"image/jpeg",o);})}function It(e){return Number.isFinite(e)?Math.min(pe,Math.max(Y,e)):Y}function Ht(e,t,r){return typeof globalThis.ImageData=="function"?new ImageData(e,t,r):{data:e,width:t,height:r,colorSpace:"srgb"}}var Lt=.85,Ut=.7;function I(e){return e?.[0]==="PASSPORT_MX"?L:O}function q(e,t){let r=e.width*Lt,n=e.height*Ut,o=r,a=o/t;return a>n&&(a=n,o=a*t),{width:o,height:a}}var qe=e=>Number.isFinite(e)&&e>0,ye=e=>qe(e.width)&&qe(e.height);function Ne(e,t,r){if(!ye(e)||!ye(t)||!ye(r))return null;let n=Math.max(t.width/e.width,t.height/e.height),o=(t.width-e.width*n)/2,a=(t.height-e.height*n)/2,i=Math.round(((t.width-r.width)/2-o)/n),s=Math.round(((t.height-r.height)/2-a)/n),u=i+Math.round(r.width/n),c=s+Math.round(r.height/n),d=Math.max(0,i),p=Math.max(0,s),m=Math.min(e.width,u),l=Math.min(e.height,c);return m<=d||l<=p?null:{x:d,y:p,width:m-d,height:l-p}}function We(e,t){let r=Math.max(e.width,e.height);if(r<=t)return {width:e.width,height:e.height};let n=t/r;return {width:Math.max(1,Math.round(e.width*n)),height:Math.max(1,Math.round(e.height*n))}}var E={brightnessMin:.18,brightnessMax:.9,blurMin:60,glareMax:.04,fillMin:.25,glarePixel:248};function N(e,t,r){let n=new Int32Array(r*2);for(let o=0;o<r;o++){let a=o+.5,i=1/0,s=-1/0;for(let u=0;u<4;u++){let c=e[u],d=e[(u+1)%4],p=Math.min(c.y,d.y),m=Math.max(c.y,d.y);if(a<p||a>m||m===p)continue;let l=c.x+(a-c.y)*(d.x-c.x)/(d.y-c.y);l<i&&(i=l),l>s&&(s=l);}if(i===1/0){n[o*2]=0,n[o*2+1]=0;continue}n[o*2]=Math.max(0,Math.ceil(i-.5)),n[o*2+1]=Math.min(t,Math.floor(s+.5));}return n}function fe(e,t){let{data:r,width:n,height:o}=e,a=N(t,n,o),i=E.glarePixel,s=0,u=0,c=0,d=0,p=0,m=0;for(let f=0;f<o;f++){let R=a[f*2],C=a[f*2+1];if(R>=C)continue;let T=0,M=0;f>0&&f<o-1&&(T=Math.max(R,a[(f-1)*2],a[(f+1)*2])+1,M=Math.min(C,a[(f-1)*2+1],a[(f+1)*2+1])-1);let w=f*n;for(let v=R;v<C;v++){let k=w+v,A=r[k];if(s+=A,A>=i&&u++,c++,v>=T&&v<M){let F=4*A-r[k-n]-r[k+n]-r[k-1]-r[k+1];d+=F,p+=F*F,m++;}}}let l=c>0?s/c/255:0,x=c>0?u/c:0,S=m>0?Math.max(0,p/m-(d/m)**2):0,y=n*o,b=y>0?D(t)/y:0,h=l>=E.brightnessMin&&l<=E.brightnessMax&&S>=E.blurMin&&x<=E.glareMax&&b>=E.fillMin;return {brightness:l,blurScore:S,glareRatio:x,docFillRatio:b,ok:h}}function je(e){let{data:t}=e;if(t.length===0)return 0;let r=0;for(let n=0;n<t.length;n++)r+=t[n];return r/t.length/255}function be(e){if(!e.detected||!e.quality)return "no_document";let t=e.quality;return !Number.isFinite(t.docFillRatio)||t.docFillRatio<E.fillMin?"too_small":!Number.isFinite(t.brightness)||t.brightness<E.brightnessMin?"too_dark":!Number.isFinite(t.glareRatio)||t.glareRatio>E.glareMax||t.brightness>E.brightnessMax?"glare":!Number.isFinite(t.blurScore)||t.blurScore<E.blurMin?"blurry":e.stableFrames<e.stableFramesRequired?"hold_still":"ready"}var Bt=E.brightnessMin;function ze(e){return !e.torchSupported||e.torchOn?false:(e.quality?e.quality.brightness:e.frameBrightness)<Bt}var ge=Object.freeze({idle:"Toca para activar la c\xE1mara",starting:"Abriendo la c\xE1mara\u2026",loading_detector:"Preparando la c\xE1mara\u2026",no_document:"Coloca tu identificaci\xF3n dentro del recuadro",too_small:"Acerca m\xE1s tu identificaci\xF3n",too_dark:"Hay poca luz, busca un lugar m\xE1s iluminado",glare:"Hay un reflejo, inclina un poco tu identificaci\xF3n",blurry:"Espera a que la c\xE1mara enfoque",hold_still:"Mant\xE9n la c\xE1mara quieta",ready:"\xA1Perfecto! Toma la foto",capturing:"Tomando la foto\u2026",uploading:"Revisando tu identificaci\xF3n\u2026",done:"\xA1Listo!",error:"Algo sali\xF3 mal, int\xE9ntalo de nuevo",detector_unavailable:"Toma la foto con el bot\xF3n",retake:"Tomar otra vez",capture:"Tomar foto",tip_light:"Busca un lugar con buena luz",tip_glare:"Evita reflejos: no apuntes una l\xE1mpara directo a tu identificaci\xF3n",tip_focus:"Espera a que la c\xE1mara enfoque y luego toca el bot\xF3n",tips_dismiss:"Entendido"}),Qt=Object.freeze({idle:"Ready to start",starting:"Starting camera\u2026",loading_detector:"Loading detector\u2026",no_document:"Place the document inside the frame",too_small:"Move closer to the document",too_dark:"Find more light",glare:"Tilt the document to avoid glare",blurry:"Hold still to focus",hold_still:"Hold the camera steady",ready:"Perfect! Take the photo",capturing:"Capturing\u2026",uploading:"Processing document\u2026",done:"Done",error:"Something went wrong \u2014 try again",detector_unavailable:"Detector unavailable \u2014 capture manually",retake:"Capture again",capture:"Capture now",tip_light:"Find a well-lit place",tip_glare:"Avoid glare: don't point a lamp straight at your ID",tip_focus:"Wait for the camera to focus, then tap the button",tips_dismiss:"Got it"}),Xt=["loading_detector","capturing","uploading","done","error"];function qt(e){return Xt.includes(e)}function W(e,t){return t?.[e]??ge[e]}function xe(e){let t={...ge};for(let r of Object.keys(t))t[r]=W(r,e);return t}function J(e,t,r){return e==="idle"||e==="stopped"?W("idle",r):e==="starting"?W("starting",r):qt(e)?W(e,r):W(t??"no_document",r)}var Nt=.05;function Wt(e,t,r){let n=r.width/t.width,o=r.height/t.height;return e.map(a=>({x:a.x*n,y:a.y*o}))}function jt(e,t){return e.map(r=>({x:Math.min(t.width,Math.max(0,r.x)),y:Math.min(t.height,Math.max(0,r.y))}))}function Ve(e,t,r){let n=jt(Wt(e,t,r),r);return !$(n)||D(n)<Nt*r.width*r.height?null:n}var Ge={stableFrames:0,isStable:false,quad:null,typeHint:null},j=class{required;maxRatio;switchFrames;current=Ge;candidate=null;constructor(t={}){this.required=t.stableFramesRequired??10,this.maxRatio=t.maxDisplacementRatio??.015,this.switchFrames=Math.max(1,t.hintSwitchFrames??3);}get snapshot(){return this.current}reset(){this.current=Ge,this.candidate=null;}update(t,r){if(!t)return this.reset(),this.current;let n=Math.hypot(r.width,r.height)*this.maxRatio,o=this.current,a=o.quad!==null&&o.quad.every((u,c)=>Math.hypot(t.quad[c].x-u.x,t.quad[c].y-u.y)<=n),i=o.typeHint??t.typeHint,s=a?o.stableFrames+1:1;if(t.typeHint===i)this.candidate=null;else {let u=this.candidate?.typeHint===t.typeHint?this.candidate.frames+1:1;this.candidate={typeHint:t.typeHint,frames:u},u>=this.switchFrames&&(i=t.typeHint,s=1,this.candidate=null);}return this.current={stableFrames:s,isStable:s>=this.required,quad:t.quad,typeHint:i},this.current}};var Vt=640,Gt=10,Ye=1500,Yt=35e3,Kt=5,$t={createWorkerClient:e=>new B(e),attachCamera:e=>ae(e),detachCamera:ie,sampleFrame:ue,cropFrame:Ae,snapshotToBlob:se,supportsTorch:ce,setTorch:le,now:()=>performance.now()},Ke=e=>e.provenance==="reduced"||e.provenance==="lowres",$e=e=>e instanceof Error?e:new Error(String(e)),Ze=e=>e.map(t=>({x:t.x,y:t.y})),z=class{opts;deps;stream=null;track=null;cv=null;generation=0;timer=null;frameCallback=null;warmupUntil=0;capturing=false;autoShutterSpent=false;torchSupported=false;torchOn=false;torchRejected=false;weakRun=false;prior=null;stability;state={status:"idle",lastFrame:null,lastResult:null,lastError:null};constructor(t,r={}){this.opts={videoElement:t.videoElement,documentTypes:t.documentTypes??["INE","PASSPORT_MX"],cropToGuide:t.cropToGuide??false,guideRatio:t.guideRatio,autoCapture:t.autoCapture??false,stableFramesRequired:t.stableFramesRequired??10,captureQuality:t.captureQuality??.92,captureResolution:t.captureResolution??"standard",opencvUrl:t.opencvUrl,workerUrl:t.workerUrl,onUpload:t.onUpload,onFrameAnalyzed:t.onFrameAnalyzed,onCaptured:t.onCaptured,onResult:t.onResult,onError:t.onError},this.deps={...$t,...r},this.stability=new j({stableFramesRequired:this.opts.stableFramesRequired});}async start(){if(!["idle","stopped","error"].includes(this.state.status))throw new Error(`Cannot start session from status=${this.state.status}`);this.release();let t=++this.generation;this.setStatus("starting"),this.state.lastError=null;try{let r=await this.deps.attachCamera(this.opts.videoElement);if(t!==this.generation){this.deps.detachCamera(this.opts.videoElement,r);return}this.stream=r,this.track=r.getVideoTracks()[0]??null,this.torchSupported=this.track?this.deps.supportsTorch(this.track):!1,this.warmupUntil=0,this.setStatus("loading_detector");let n=this.deps.createWorkerClient({initTimeoutMs:Yt});this.cv=n,n.init(this.opts.opencvUrl,this.opts.workerUrl).then(()=>{t!==this.generation||this.cv!==n||(this.state.status==="loading_detector"&&this.setStatus("streaming"),this.scheduleNext(t,0));},o=>this.detectorUnavailable(t,n,o));}catch(r){throw t===this.generation&&this.emitError(r),r}}stop(){this.generation++,this.release(),this.setStatus("stopped");}async captureNow(){if(this.capturing)return;let t=this.state.status;if(t!=="streaming"&&t!=="loading_detector"&&!(t==="done"&&this.stream))throw new Error(`Cannot capture from status=${this.state.status}`);let r=this.stability.snapshot,n=this.state.lastFrame?.frameSize??null,o=r.quad&&n?this.fullFrameQuad(r.quad,n):null;await this.doCapture(this.generation,o?r.typeHint:null);}getState(){return {...this.state}}scheduleNext(t,r){this.timer=setTimeout(()=>{if(this.timer=null,t!==this.generation)return;let n=this.opts.videoElement;typeof n.requestVideoFrameCallback=="function"?this.frameCallback=n.requestVideoFrameCallback(()=>{this.frameCallback=null,this.tick(t);}):this.tick(t);},r);}async tick(t){if(t!==this.generation)return;let r=this.deps.now();try{await this.analyzeFrame(t);}catch(n){t===this.generation&&console.warn("[xid-camera-ocr] analyzeFrame error:",n);}t!==this.generation||!this.cv||this.scheduleNext(t,Math.max(0,1e3/Gt-(this.deps.now()-r)));}async analyzeFrame(t){let r=this.cv;if(this.capturing||!r?.isReady())return;let n=this.deps.sampleFrame(this.opts.videoElement,Vt);if(!n)return;let o={width:n.width,height:n.height};this.warmupUntil===0&&(this.warmupUntil=this.deps.now()+Ye);let a=this.prior&&this.prior.width===n.width&&this.prior.height===n.height?this.prior.quad:null,i;try{i=await r.analyze(n,a?{prior:a}:{});}catch(m){if(t===this.generation&&this.cv===r&&!r.isReady()){this.detectorUnavailable(t,r,m);return}throw m}if(t!==this.generation||this.capturing)return;this.prior=i.detected&&i.corners?{quad:Ze(i.corners),...o}:null;let u=!(this.deps.now()<this.warmupUntil)&&i.detected&&i.corners&&i.documentType?{quad:i.corners,typeHint:i.documentType}:null,c=this.stability.update(u,o);this.weakRun=c.stableFrames<=1?u!==null&&Ke(i):this.weakRun||Ke(i);let d=this.opts.stableFramesRequired+(this.weakRun?Kt:0);if(await this.updateTorch(t,i),t!==this.generation)return;let p={detected:i.detected,documentType:i.documentType,confidence:Math.min(c.stableFrames/d,1),aspectRatio:i.aspectRatio,quality:i.quality,corners:i.corners?Ze(i.corners):null,frameSize:o,hint:be({detected:i.detected,quality:i.quality,stableFrames:c.stableFrames,stableFramesRequired:d}),...this.torchSupported?{torch:this.torchOn}:{}};if(this.state.lastFrame=p,this.opts.onFrameAnalyzed?.(p),t===this.generation&&this.opts.autoCapture&&!this.autoShutterSpent&&c.quad&&c.stableFrames>=d&&i.quality?.ok){if(!this.fullFrameQuad(c.quad,o)){this.stability.reset(),this.weakRun=false;return}await this.doCapture(t,c.typeHint);}}detectorUnavailable(t,r,n){if(t!==this.generation||this.cv!==r)return;r.terminate(),this.cv=null,this.prior=null,this.stability.reset(),this.weakRun=false,this.autoShutterSpent=true,this.state.status==="loading_detector"&&this.setStatus("streaming");let o=$e(n);this.state.lastError=o;let a={detected:false,documentType:null,confidence:0,aspectRatio:null,quality:null,corners:null,frameSize:null,hint:"detector_unavailable",...this.torchSupported?{torch:this.torchOn}:{}};this.state.lastFrame=a,this.opts.onFrameAnalyzed?.(a),t===this.generation&&this.opts.onError?.(o);}async updateTorch(t,r){if(!this.track||this.torchRejected||!ze({torchSupported:this.torchSupported,torchOn:this.torchOn,quality:r.quality,frameBrightness:r.frameBrightness}))return;let n=await this.deps.setTorch(this.track,true);t===this.generation&&(this.torchOn=n,n||(this.torchRejected=true));}fullFrameQuad(t,r){let n=this.opts.videoElement;return !n.videoWidth||!n.videoHeight?null:Ve(t,r,{width:n.videoWidth,height:n.videoHeight})}async doCapture(t,r){if(!this.capturing){this.capturing=true,this.autoShutterSpent=true,this.prior=null,this.stability.reset(),this.weakRun=false,this.setStatus("capturing");try{let{blob:n,type:o}=await this.captureBlob(t,r);if(t!==this.generation)return;this.opts.onCaptured?.(n,o),this.setStatus("uploading");let a=await this.opts.onUpload(n,o);if(t!==this.generation)return;this.state.lastResult=a,this.setStatus("done"),this.opts.onResult?.(a);}catch(n){t===this.generation&&this.emitError(n);}finally{t===this.generation&&(this.stability.reset(),this.weakRun=false,this.warmupUntil=this.deps.now()+Ye,this.capturing=false);}}}async captureBlob(t,r){let n=this.opts.videoElement,o=async()=>({blob:await this.deps.snapshotToBlob(n,this.opts.captureQuality),type:null});if(!this.opts.cropToGuide)return {blob:await this.deps.snapshotToBlob(n,this.opts.captureQuality),type:r};let a={width:n.clientWidth,height:n.clientHeight},i=this.opts.guideRatio?.()??I(this.opts.documentTypes),s=Ne({width:n.videoWidth,height:n.videoHeight},a,q(a,i));if(!s)return o();try{let u=this.opts.captureResolution==="high"?Be:X;return {blob:await this.deps.cropFrame(n,s,We(s,u),this.opts.captureQuality),type:r}}catch(u){if(t!==this.generation)throw u;return console.warn("[xid-camera-ocr] guide crop failed, using plain snapshot:",u),o()}}release(){this.prior=null,this.timer!==null&&clearTimeout(this.timer),this.timer=null,this.frameCallback!==null&&(this.opts.videoElement.cancelVideoFrameCallback?.(this.frameCallback),this.frameCallback=null),this.track&&this.torchOn&&this.deps.setTorch(this.track,false),this.torchOn=false,this.torchRejected=false,this.stream&&this.deps.detachCamera(this.opts.videoElement,this.stream),this.stream=null,this.track=null,this.cv?.terminate(),this.cv=null,this.stability.reset(),this.weakRun=false,this.capturing=false,this.autoShutterSpent=false;}setStatus(t){this.state.status=t;}emitError(t){let r=$e(t);this.state.lastError=r,this.setStatus("error"),this.opts.onError?.(r);}};var Je=.08,Zt=.95,Jt=.02,U=8,er=2,et=8,tt=.33,ee=2,tr=2,rr=1,nr=tr+ee,or=2,ar=2*(ee+1),ir=10,rt=1.1,it=ee+1,sr=6,st=.92,ur=1/st,cr=.85,lr=2,dr=.05,nt=2,ot=64;function ut(e){return {detected:false,documentType:null,aspectRatio:null,corners:null,boundingBox:null,quality:null,frameBrightness:e,score:null}}function pr(e,t,r,n={}){let o={brightness:0};try{return mr(e,t,o,n.prior??null)}catch(a){return console.warn("[xid-camera-ocr] detectDocumentCV failed:",a),ut(o.brightness)}}function mr(e,t,r,n){let{width:o,height:a}=t,i=[],s=u=>(i.push(u),u);try{let u=s(e.matFromImageData(t)),c=s(new e.Mat),d=s(new e.Mat),p={equalized:s(new e.Mat),filtered:s(new e.Mat),padded:s(new e.Mat),edges:s(new e.Mat),dilated:s(new e.Mat),kernel:s(e.Mat.ones(3,3,e.CV_8U)),contours:s(new e.MatVector),hierarchy:s(new e.Mat),hull:s(new e.Mat),approx:s(new e.Mat),clahe:s(new e.CLAHE(er,new e.Size(et,et)))};e.cvtColor(u,c,e.COLOR_RGBA2GRAY),r.brightness=je(Se(c,o,a));let m=[],l=at(e,c,p,o,a,m,n),x=!1,S=Math.round(o/nt),y=Math.round(a/nt);if(!l&&S>=ot&&y>=ot&&(e.resize(c,d,new e.Size(S,y),0,0,e.INTER_AREA),l=at(e,d,p,o,a,m,n),x=l!==null),l&&xr(l,m,Se(c,o,a))&&(l=null),!l)return ut(r.brightness);let b=x?"lowres":l.reduced?"reduced":"direct",h=l.quad.map(w=>w.x),f=l.quad.map(w=>w.y),R=Math.min(...h),C=Math.max(...h),T=Math.min(...f),M=Math.max(...f);return {detected:!0,documentType:Z(l.aspect),aspectRatio:l.aspect,corners:l.quad,boundingBox:{x:R/o,y:T/a,width:(C-R)/o,height:(M-T)/a},quality:fe(Se(c,o,a),dt(l.quad,it*l.scale)),frameBrightness:r.brightness,score:b==="direct"?l.score:l.score*cr,provenance:b}}finally{for(let u of i)u.delete();}}function at(e,t,r,n,o,a,i){let s=t.cols,u=t.rows,c=n/s,d=o/u,p=s*u,m=h=>({x:h.x*c,y:h.y*d}),{hull:l,approx:x,contours:S}=r;r.clahe.apply(t,r.equalized),e.bilateralFilter(r.equalized,r.filtered,9,75,75,e.BORDER_DEFAULT),e.copyMakeBorder(r.filtered,r.padded,U,U,U,U,e.BORDER_CONSTANT,new e.Scalar(0));let y=Rr(r.padded.data);e.Canny(r.padded,r.edges,Math.max(10,(1-tt)*y),Math.min(255,(1+tt)*y)),e.dilate(r.edges,r.dilated,r.kernel,new e.Point(-1,-1),ee),e.findContours(r.dilated,S,r.hierarchy,e.RETR_LIST,e.CHAIN_APPROX_SIMPLE);let b=null;for(let h=0;h<S.size();h++){let f=S.get(h);try{let R=e.boundingRect(f);if(R.width*R.height<p*Je)continue;e.convexHull(f,l,!1,!0);let C=e.contourArea(l);if(C<p*Je||C>p*Zt||(e.approxPolyDP(l,x,Jt*e.arcLength(l,!0),!0),x.rows<4||x.rows>sr||!e.isContourConvex(x)))continue;let T=x.rows!==4,M;if(!T)M=yr(x,s,u);else {let ke=fr(ct(x));if(!ke)continue;M=ke.map(Ct=>lt(Ct,s,u));let _e=C/D(M);if(!(_e>=st&&_e<=ur))continue}let w=C*c*d,v=M.map(m),k=nr*c;if(Cr(v,n,o,k)>rr){gr(v,n,o,k)||a.push({pts:v,area:w});continue}let A=me(v);if(!$(A))continue;let F=e.minAreaRect(T?l:x),ve=F.size.width*F.size.height,wt=ve>0?Math.min(1,C/ve):0,ne=Q(A);if(!he(ne))continue;let oe=Le({areaRatio:C/p,rectangularity:wt,aspect:ne}),Ee=i?oe-hr(A,i,n,o):oe;(!b||Ee>b.rank)&&(b={quad:A,score:oe,rank:Ee,aspect:ne,area:w,scale:c,reduced:T});}finally{f.delete();}}return b}function hr(e,t,r,n){let o=1/0;for(let a=0;a<4;a++){let i=0;for(let s=0;s<4;s++){let u=e[(s+a)%4];i=Math.max(i,Math.hypot(u.x-t[s].x,u.y-t[s].y));}o=Math.min(o,i);}return lr*Math.min(o/Math.hypot(r,n),dr)}function Se(e,t,r){return {data:e.data,width:t,height:r}}function ct(e){let t=e.data32S,r=[];for(let n=0;n<e.rows;n++)r.push({x:t[n*2]-U,y:t[n*2+1]-U});return r}function lt(e,t,r){return {x:Math.min(t,Math.max(0,e.x)),y:Math.min(r,Math.max(0,e.y))}}function yr(e,t,r){return ct(e).map(n=>lt(n,t,r))}function fr(e){let t=e;for(;t.length>4;){let r=t.length,n=-1,o=1/0,a=null;for(let s=0;s<r;s++){let u=t[(s+r-1)%r],c=t[s],d=t[(s+1)%r],p=t[(s+2)%r],m=br(u,c,p,d);if(!m)continue;let l=Math.abs((m.x-c.x)*(d.y-c.y)-(m.y-c.y)*(d.x-c.x))/2;l<o&&(o=l,n=s,a=m);}if(n<0||!a)return null;let i=[];for(let s=0;s<r;s++)s===n?i.push(a):s!==(n+1)%r&&i.push(t[s]);t=i;}return t}function br(e,t,r,n){let o=t.x-e.x,a=t.y-e.y,i=n.x-r.x,s=n.y-r.y,u=o*s-a*i;if(Math.abs(u)<1e-9)return null;let c=((r.x-e.x)*s-(r.y-e.y)*i)/u,d=((r.x-e.x)*a-(r.y-e.y)*o)/u;return c<1||d<1?null:{x:e.x+c*o,y:e.y+c*a}}function gr(e,t,r,n){let o=e.map(i=>i.x),a=e.map(i=>i.y);return Math.min(...o)<=n&&Math.max(...o)>=t-n||Math.min(...a)<=n&&Math.max(...a)>=r-n}function xr(e,t,r){let n=ar*e.scale;if(!t.some(s=>s.area>=or*e.area&&e.quad.every(u=>wr(s.pts,u,n))))return false;if(Z(e.aspect)==="OTHER")return true;let{inner:a,ring:i}=Sr(r,dt(e.quad,it*e.scale),e.quad);return a<i-ir}function Sr(e,t,r){let{data:n,width:o,height:a}=e,i=(r[0].x+r[1].x+r[2].x+r[3].x)/4,s=(r[0].y+r[1].y+r[2].y+r[3].y)/4,u=r.map(y=>({x:i+(y.x-i)*rt,y:s+(y.y-s)*rt})),c=N(u,o,a),d=N(r,o,a),p=N(t,o,a),m=0,l=0,x=0,S=0;for(let y=0;y<a;y++){let b=c[y*2],h=c[y*2+1];if(b>=h)continue;let f=d[y*2],R=d[y*2+1],C=p[y*2],T=p[y*2+1],M=y*o;for(let w=b;w<h;w++){let v=n[M+w];w>=C&&w<T?(m+=v,l++):(w<f||w>=R)&&(x+=v,S++);}}return {inner:l>0?m/l:0,ring:S>0?x/S:0}}function wr(e,t,r){let n=0;for(let a=0;a<e.length;a++){let i=e[a],s=e[(a+1)%e.length];n+=i.x*s.y-s.x*i.y;}let o=Math.sign(n);if(o===0)return false;for(let a=0;a<e.length;a++){let i=e[a],s=e[(a+1)%e.length],u=Math.hypot(s.x-i.x,s.y-i.y);if(u===0)continue;if(o*((s.x-i.x)*(t.y-i.y)-(s.y-i.y)*(t.x-i.x))/u<r)return false}return true}function dt(e,t){return e.map((r,n)=>{let o=e[(n+3)%4],a=e[(n+1)%4],i=o.x-r.x,s=o.y-r.y,u=a.x-r.x,c=a.y-r.y,d=Math.hypot(i,s),p=Math.hypot(u,c),m=i/d+u/p,l=s/d+c/p,x=Math.hypot(m,l),S=Math.sin(Math.acos(Math.min(1,Math.max(-1,(i*u+s*c)/(d*p))))/2),y=t/S/x;return {x:r.x+m*y,y:r.y+l*y}})}function Cr(e,t,r,n){let o=0;for(let a of e)(a.x<=n||a.x>=t-n||a.y<=n||a.y>=r-n)&&o++;return o}function Rr(e){let t=new Uint32Array(256);for(let n=0;n<e.length;n++)t[e[n]]++;let r=0;for(let n=0;n<256;n++)if(r+=t[n],r>=e.length/2)return n;return 128}function Ce(e){let t=useRef(null),r=useRef(null),[n,o]=useState("idle"),[a,i]=useState(null),[s,u]=useState(null),[c,d]=useState(null),p=useRef(e);p.current=e;let m=useCallback(()=>{if(r.current)return r.current;if(!t.current)throw new Error("videoRef not attached yet");let b=new z({videoElement:t.current,documentTypes:p.current.documentTypes,cropToGuide:p.current.cropToGuide,guideRatio:()=>I(p.current.documentTypes),autoCapture:p.current.autoCapture,stableFramesRequired:p.current.stableFramesRequired,captureQuality:p.current.captureQuality,captureResolution:p.current.captureResolution,opencvUrl:p.current.opencvUrl,workerUrl:p.current.workerUrl,onUpload:(h,f)=>p.current.onUpload(h,f),onFrameAnalyzed:h=>{i(h),r.current===b&&o(b.getState().status),p.current.onFrameAnalyzed?.(h);},onCaptured:(h,f)=>{o("capturing"),p.current.onCaptured?.(h,f);},onResult:h=>{u(h),o("done"),p.current.onResult?.(h);},onError:h=>{d(h),r.current===b&&o(b.getState().status),p.current.onError?.(h);}});return r.current=b,b},[]),l=useCallback(async()=>{let b=m();await b.start(),r.current===b&&o(b.getState().status);},[m]),x=useCallback(()=>{r.current?.stop(),o("stopped");},[]),S=useCallback(async()=>{await r.current?.captureNow();},[]),y=useCallback(async()=>{x(),u(null),d(null),i(null),await l();},[x,l]);return useEffect(()=>(e.autoStart!==false&&t.current&&l().catch(()=>{}),()=>{r.current?.stop(),r.current=null;}),[]),{videoRef:t,status:n,frame:a,result:s,error:c,start:l,stop:x,captureNow:S,retake:y}}function vr({status:e,showTips:t,dismissed:r,completedOnce:n}){return t&&!r&&(e==="error"||!n&&(e==="starting"||e==="loading_detector"))}function pt(e,t){let[r,n]=useState(false),[o,a]=useState(e==="done"),[i,s]=useState(e),u=r,c=o;i!==e&&(s(e),e==="error"&&(u=false,n(false)),e==="done"&&(c=true,a(true)));let d=useCallback(()=>n(true),[]);return {visible:vr({status:e,showTips:t,dismissed:u,completedOnce:c}),dismiss:d}}var re={accent:{name:"--xco-accent",fallback:"#22c55e"},warning:{name:"--xco-warning",fallback:"#eab308"},danger:{name:"--xco-danger",fallback:"#ef4444"},background:{name:"--xco-background",fallback:"#000"},mask:{name:"--xco-mask",fallback:"rgba(0,0,0,0.4)"},hintBg:{name:"--xco-hint-bg",fallback:"rgba(0,0,0,0.7)"},hintFg:{name:"--xco-hint-fg",fallback:"white"},buttonBg:{name:"--xco-button-bg",fallback:"rgba(255,255,255,0.92)"},buttonFg:{name:"--xco-button-fg",fallback:"#111"},shutter:{name:"--xco-shutter",fallback:"rgba(255,255,255,0.9)"},overlayBg:{name:"--xco-overlay-bg",fallback:"rgba(0,0,0,0.78)"},overlayFg:{name:"--xco-overlay-fg",fallback:"white"},fontFamily:{name:"--xco-font-family",fallback:"system-ui, -apple-system, sans-serif"},radius:{name:"--xco-radius",fallback:"12px"}};function g(e){let{name:t,fallback:r}=re[e];return `var(${t}, ${r})`}function mt(e){let t={};if(!e)return t;for(let r of Object.keys(e)){if(!Object.prototype.hasOwnProperty.call(re,r))continue;let n=e[r];typeof n!="string"||n===""||(t[re[r].name]=n);}return t}function ht(e,t){return e==="done"?g("accent"):e==="error"?g("danger"):e==="uploading"||e==="capturing"?g("accent"):t?.detected?t.confidence>=1?g("accent"):g("warning"):g("danger")}var Te={width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",focusable:"false",style:{flex:"0 0 auto"}},Er=()=>jsxs("svg",{...Te,children:[jsx("circle",{cx:"12",cy:"12",r:"4"}),jsx("path",{d:"M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4"})]}),kr=()=>jsxs("svg",{...Te,children:[jsx("rect",{x:"3",y:"5",width:"18",height:"14",rx:"2"}),jsx("path",{d:"M14 5l-6 14M18 5l-6 14"})]}),_r=()=>jsxs("svg",{...Te,children:[jsx("path",{d:"M4 8V5a1 1 0 0 1 1-1h3M16 4h3a1 1 0 0 1 1 1v3M20 16v3a1 1 0 0 1-1 1h-3M8 20H5a1 1 0 0 1-1-1v-3"}),jsx("circle",{cx:"12",cy:"12",r:"2"})]});function yt({texts:e,onDismiss:t}){let r=[{Icon:Er,text:e.tip_light},{Icon:kr,text:e.tip_glare},{Icon:_r,text:e.tip_focus}];return jsxs("div",{className:"xco-tips",style:Ar,children:[jsx("ul",{style:Pr,children:r.map(({Icon:n,text:o})=>jsxs("li",{style:Fr,children:[jsx(n,{}),jsx("span",{children:o})]},o))}),jsx("button",{type:"button",className:"xco-tips-dismiss",onClick:t,style:Or,children:e.tips_dismiss})]})}var Ar={position:"absolute",top:"calc(16px + env(safe-area-inset-top, 0px))",left:"50%",transform:"translateX(-50%)",boxSizing:"border-box",width:"calc(100% - 32px)",maxWidth:360,padding:16,background:g("overlayBg"),color:g("overlayFg"),borderRadius:g("radius"),fontFamily:g("fontFamily"),fontSize:15,lineHeight:1.35,display:"flex",flexDirection:"column",gap:12,pointerEvents:"auto",zIndex:5},Pr={listStyle:"none",margin:0,padding:0,display:"flex",flexDirection:"column",gap:10},Fr={display:"flex",alignItems:"center",gap:12},Or={alignSelf:"flex-end",minHeight:44,padding:"10px 20px",borderRadius:g("radius"),background:g("buttonBg"),color:g("buttonFg"),border:"none",fontFamily:g("fontFamily"),fontSize:15,fontWeight:600,cursor:"pointer",WebkitTapHighlightColor:"transparent"};var Ur=typeof window>"u"?useEffect:useLayoutEffect;function bt({videoRef:e,status:t,frame:r,texts:n,documentTypes:o,theme:a,className:i,style:s,hideStatusOverlay:u,hideShutter:c,tipsVisible:d,onCapture:p,onRetake:m,onStart:l,onDismissTips:x}){let S=t==="streaming"||t==="loading_detector",y=t==="done"||t==="error",b=t==="idle"||t==="stopped",h=t==="capturing"||t==="uploading",f=useRef(null),[R,C]=useState({width:0,height:0}),T=I(o);Ur(()=>{let k=f.current;if(!k)return;let A=()=>C(q({width:k.clientWidth,height:k.clientHeight},T));A();let F=new ResizeObserver(A);return F.observe(k),()=>F.disconnect()},[T]);let M=ht(t,r),w=J(t,r?.hint,n),v=i?`xid-camera-ocr ${i}`:"xid-camera-ocr";return jsxs("div",{ref:f,className:v,"data-status":t,"data-hint":r?.hint??"",style:{...Br,...mt(a),...s},children:[jsx("style",{children:"@keyframes xco-spin { to { transform: rotate(360deg); } }"}),jsx("video",{ref:e,playsInline:true,muted:true,autoPlay:true,style:Qr}),!u&&jsx("div",{style:Xr,children:jsx("div",{className:"xco-guide",style:{...qr,width:R.width,height:R.height,borderColor:M}})}),!u&&(b?jsx("button",{type:"button",className:"xco-hint",onClick:l,style:Yr,children:w}):jsx("p",{className:"xco-hint",style:xt,role:"status","aria-live":"polite",children:w})),!u&&!c&&S&&jsx("button",{type:"button",className:"xco-shutter",onClick:p,"aria-label":n.capture,style:zr,children:jsx("span",{style:Vr})}),!u&&y&&jsx("button",{type:"button",className:"xco-retake",onClick:m,"aria-label":n.retake,style:Gr,children:n.retake}),!u&&h&&jsxs("div",{className:"xco-loader",style:Nr,"aria-busy":"true","aria-live":"polite",children:[jsx("div",{style:Wr}),jsx("p",{style:jr,children:J(t,void 0,n)})]}),d&&!u&&jsx(yt,{texts:n,onDismiss:x})]})}var gt="calc(104px + env(safe-area-inset-bottom, 0px))",Br={position:"relative",width:"100%",height:"100%",overflow:"hidden",background:g("background"),fontFamily:g("fontFamily"),touchAction:"none"},Qr={position:"absolute",inset:0,width:"100%",height:"100%",objectFit:"cover",display:"block"},Xr={position:"absolute",inset:0,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",pointerEvents:"none"},qr={borderRadius:g("radius"),boxSizing:"content-box",borderWidth:4,borderStyle:"solid",boxShadow:`0 0 0 9999px ${g("mask")}`,transition:"border-color 200ms ease-in-out"},Nr={position:"absolute",inset:0,display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center",gap:20,background:g("overlayBg"),backdropFilter:"blur(6px)",WebkitBackdropFilter:"blur(6px)",pointerEvents:"auto",zIndex:10},Wr={width:56,height:56,borderRadius:"50%",border:"5px solid rgba(255, 255, 255, 0.18)",borderTopColor:g("accent"),animation:"xco-spin 0.85s linear infinite"},jr={color:g("overlayFg"),fontFamily:g("fontFamily"),fontSize:15,fontWeight:500,margin:0,textAlign:"center",padding:"0 24px"},zr={position:"absolute",bottom:gt,left:"50%",transform:"translateX(-50%)",width:68,height:68,borderRadius:"50%",background:"rgba(255,255,255,0.18)",border:`4px solid ${g("shutter")}`,cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",pointerEvents:"auto",WebkitTapHighlightColor:"transparent",padding:0},Vr={width:52,height:52,borderRadius:"50%",background:"white",display:"block"},Gr={position:"absolute",bottom:gt,left:"50%",transform:"translateX(-50%)",minHeight:44,padding:"10px 20px",borderRadius:22,background:g("buttonBg"),color:g("buttonFg"),border:"none",fontFamily:g("fontFamily"),fontSize:15,fontWeight:600,cursor:"pointer",pointerEvents:"auto",WebkitTapHighlightColor:"transparent"},xt={position:"absolute",bottom:"calc(16px + env(safe-area-inset-bottom, 0px))",left:"50%",transform:"translateX(-50%)",boxSizing:"border-box",width:"max-content",maxWidth:"calc(100% - 32px)",background:g("hintBg"),color:g("hintFg"),padding:"10px 16px",borderRadius:g("radius"),fontFamily:g("fontFamily"),fontSize:16,lineHeight:1.35,margin:0,whiteSpace:"normal",textAlign:"center"},Yr={...xt,border:"none",minHeight:44,cursor:"pointer",pointerEvents:"auto",WebkitTapHighlightColor:"transparent"};var tn=["INE","PASSPORT_MX"],Me=()=>{},St=forwardRef(function({className:t,style:r,hideStatusOverlay:n,texts:o,theme:a,showTips:i,hideShutter:s,onStatusChange:u,...c},d){let{videoRef:p,status:m,frame:l,start:x,captureNow:S,retake:y}=Ce({...c,cropToGuide:!n}),b=pt(m,i??true),h=useMemo(()=>xe(o),[o]),f=m==="streaming"||m==="loading_detector",R=m==="done"||m==="error",C=async()=>{f&&await S().catch(Me);},T=()=>{R&&y().catch(Me);},M=async()=>{await x().catch(Me);};useImperativeHandle(d,()=>({capture:C,retake:T,start:M}));let w=useRef(u);return w.current=u,useEffect(()=>{w.current?.(m);},[m]),jsx(bt,{videoRef:p,status:m,frame:l,texts:h,documentTypes:c.documentTypes??tn,theme:a,className:t,style:r,hideStatusOverlay:n,hideShutter:s,tipsVisible:b.visible,onCapture:()=>{C();},onRetake:T,onStart:()=>{M();},onDismissTips:b.dismiss})});St.displayName="XidCameraOcr";export{B as CVWorkerClient,Qt as DEFAULT_TEXTS_EN,ge as DEFAULT_TEXTS_ES,O as ID1_RATIO,E as QUALITY_THRESHOLDS,j as StabilityTracker,L as TD3_RATIO,re as XCO_VARS,St as XidCameraOcr,z as XidCameraOcrSession,ae as attachCamera,J as copyFor,be as decideHint,de as defaultOpencvUrl,ie as detachCamera,pr as detectDocumentCV,q as guideBox,I as guideRatioFor,he as isCapturableAspect,fe as measureQuality,me as orderCorners,Q as rectifiedAspect,xe as resolveTexts,ue as sampleFrame,le as setTorch,se as snapshotToBlob,ce as supportsTorch,Z as typeHintFromAspect,Ce as useXidCameraOcr,Xe as warpDocument,Qe as warpDocumentImageData,Dt as warpedSnapshotToBlob};//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|