@exige/web-scanner-sdk 0.2.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/README.md +288 -0
- package/dist/assets/document-worker-QjcJjl9-.js +2 -0
- package/dist/assets/document-worker-QjcJjl9-.js.map +1 -0
- package/dist/assets/ort.min-CA5AZ7mL.js +2937 -0
- package/dist/assets/ort.min-CA5AZ7mL.js.map +1 -0
- package/dist/components/ScannerCameraOverlay.d.ts +36 -0
- package/dist/components/scanner-camera-overlay.css +2 -0
- package/dist/finder-Clo7f2gN.js +1447 -0
- package/dist/finder-Clo7f2gN.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/live-overlay-geometry.d.ts +11 -0
- package/dist/react.d.ts +2 -0
- package/dist/react.js +448 -0
- package/dist/react.js.map +1 -0
- package/dist/scanner-sdk.js +921 -0
- package/dist/scanner-sdk.js.map +1 -0
- package/dist/sdk/camera.d.ts +142 -0
- package/dist/sdk/detect.d.ts +3 -0
- package/dist/sdk/display-quad.d.ts +23 -0
- package/dist/sdk/document-analysis.d.ts +14 -0
- package/dist/sdk/document-geometry.d.ts +21 -0
- package/dist/sdk/field-model.d.ts +4 -0
- package/dist/sdk/finder-simulator.d.ts +17 -0
- package/dist/sdk/finder.d.ts +166 -0
- package/dist/sdk/frame-geometry.d.ts +6 -0
- package/dist/sdk/image.d.ts +18 -0
- package/dist/sdk/license-codec.d.ts +2 -0
- package/dist/sdk/license-public-key.d.ts +9 -0
- package/dist/sdk/license-runtime.d.ts +2 -0
- package/dist/sdk/license.d.ts +76 -0
- package/dist/sdk/lighting.d.ts +22 -0
- package/dist/sdk/ocr.d.ts +75 -0
- package/dist/sdk/programmatic-redaction.d.ts +102 -0
- package/dist/sdk/redact.d.ts +12 -0
- package/dist/sdk/scan.d.ts +32 -0
- package/dist/sdk/types.d.ts +92 -0
- package/package.json +74 -0
package/dist/react.js
ADDED
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
import { A as e, E as t, T as n, v as r, y as i } from "./finder-Clo7f2gN.js";
|
|
2
|
+
import { useEffect as a, useRef as o, useState as s } from "react";
|
|
3
|
+
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
4
|
+
//#region src/sdk/display-quad.ts
|
|
5
|
+
function u(e) {
|
|
6
|
+
return [
|
|
7
|
+
e.topLeft,
|
|
8
|
+
e.topRight,
|
|
9
|
+
e.bottomRight,
|
|
10
|
+
e.bottomLeft
|
|
11
|
+
];
|
|
12
|
+
}
|
|
13
|
+
function d(e) {
|
|
14
|
+
let [t, n, r, i] = e;
|
|
15
|
+
return {
|
|
16
|
+
topLeft: t,
|
|
17
|
+
topRight: n,
|
|
18
|
+
bottomRight: r,
|
|
19
|
+
bottomLeft: i,
|
|
20
|
+
edges: {
|
|
21
|
+
top: {
|
|
22
|
+
start: t,
|
|
23
|
+
end: n
|
|
24
|
+
},
|
|
25
|
+
right: {
|
|
26
|
+
start: n,
|
|
27
|
+
end: r
|
|
28
|
+
},
|
|
29
|
+
bottom: {
|
|
30
|
+
start: r,
|
|
31
|
+
end: i
|
|
32
|
+
},
|
|
33
|
+
left: {
|
|
34
|
+
start: i,
|
|
35
|
+
end: t
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function f(e) {
|
|
41
|
+
return d(u(e).map((e) => ({ ...e })));
|
|
42
|
+
}
|
|
43
|
+
var p = class {
|
|
44
|
+
current;
|
|
45
|
+
target;
|
|
46
|
+
response;
|
|
47
|
+
snapDistance;
|
|
48
|
+
constructor(e = {}) {
|
|
49
|
+
this.response = e.response ?? 14, this.snapDistance = e.snapDistance ?? .1;
|
|
50
|
+
}
|
|
51
|
+
setTarget(e, t, n) {
|
|
52
|
+
let r = Math.max(1, Math.hypot(t, n)), i = !this.current || u(e).some((e, t) => {
|
|
53
|
+
let n = u(this.current)[t];
|
|
54
|
+
return Math.hypot(e.x - n.x, e.y - n.y) / r > this.snapDistance;
|
|
55
|
+
});
|
|
56
|
+
return this.target = f(e), i && (this.current = f(e)), {
|
|
57
|
+
quad: this.current,
|
|
58
|
+
snapped: i
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
step(e) {
|
|
62
|
+
if (!this.current || !this.target) return this.current;
|
|
63
|
+
let t = 1 - Math.exp(-this.response * Math.max(0, e) / 1e3);
|
|
64
|
+
return this.current = d(u(this.current).map((e, n) => {
|
|
65
|
+
let r = u(this.target)[n];
|
|
66
|
+
return {
|
|
67
|
+
x: e.x + (r.x - e.x) * t,
|
|
68
|
+
y: e.y + (r.y - e.y) * t
|
|
69
|
+
};
|
|
70
|
+
})), this.current;
|
|
71
|
+
}
|
|
72
|
+
clear() {
|
|
73
|
+
this.current = void 0, this.target = void 0;
|
|
74
|
+
}
|
|
75
|
+
getCurrent() {
|
|
76
|
+
return this.current;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
//#endregion
|
|
80
|
+
//#region src/live-overlay-geometry.ts
|
|
81
|
+
function ee(e, t, n, r, i) {
|
|
82
|
+
let a = Math.max(1, e), o = Math.max(1, t), s = Math.max(1, n), c = Math.max(1, r), l = s / a, u = c / o, d = i === "cover" ? Math.max(l, u) : Math.min(l, u), f = (s - a * d) / 2, p = (c - o * d) / 2;
|
|
83
|
+
if (i === "contain") return {
|
|
84
|
+
viewBox: `0 0 ${a} ${o}`,
|
|
85
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
86
|
+
scale: d,
|
|
87
|
+
offsetX: f,
|
|
88
|
+
offsetY: p
|
|
89
|
+
};
|
|
90
|
+
let ee = s / d, m = c / d;
|
|
91
|
+
return {
|
|
92
|
+
viewBox: `${-f / d} ${-p / d} ${ee} ${m}`,
|
|
93
|
+
preserveAspectRatio: "none",
|
|
94
|
+
scale: d,
|
|
95
|
+
offsetX: f,
|
|
96
|
+
offsetY: p
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/components/ScannerCameraOverlay.tsx
|
|
101
|
+
function m({ open: u, autoCapture: d = "defaultOn", torch: f = "defaultOff", cameraOptions: m, onCapture: h, onClose: te, onError: g, onSettings: _, onFinderStatus: v, className: ne = "", title: re = "Scan a document", previewFit: y = "cover", detector: b = "classical", modelUrl: x, ortWasmPaths: ie, detectionIntervalMs: ae }) {
|
|
102
|
+
let S = o(null), C = o(void 0), w = o(void 0), T = o(void 0), E = o(void 0), D = o({}), O = o(new p()), k = o(!1), A = o({
|
|
103
|
+
onCapture: h,
|
|
104
|
+
onError: g,
|
|
105
|
+
onSettings: _,
|
|
106
|
+
onFinderStatus: v
|
|
107
|
+
}), [j, M] = s("starting"), [N, oe] = s(), [P, F] = s(), [I, se] = s({
|
|
108
|
+
width: 1,
|
|
109
|
+
height: 1
|
|
110
|
+
}), [L, ce] = s(), [R, z] = s(), [B, V] = s(""), [H, le] = s(0), [U, W] = s(), [G, K] = s(), [q, J] = s("idle");
|
|
111
|
+
if (a(() => {
|
|
112
|
+
A.current = {
|
|
113
|
+
onCapture: h,
|
|
114
|
+
onError: g,
|
|
115
|
+
onSettings: _,
|
|
116
|
+
onFinderStatus: v
|
|
117
|
+
};
|
|
118
|
+
}, [
|
|
119
|
+
h,
|
|
120
|
+
g,
|
|
121
|
+
_,
|
|
122
|
+
v
|
|
123
|
+
]), a(() => {
|
|
124
|
+
if (!u) return;
|
|
125
|
+
let e = document.body.style.overflow;
|
|
126
|
+
return document.body.style.overflow = "hidden", () => {
|
|
127
|
+
document.body.style.overflow = e;
|
|
128
|
+
};
|
|
129
|
+
}, [u]), a(() => {
|
|
130
|
+
if (!u) return;
|
|
131
|
+
let e = S.current;
|
|
132
|
+
if (!e) return;
|
|
133
|
+
let t = () => {
|
|
134
|
+
let t = e.getBoundingClientRect();
|
|
135
|
+
se({
|
|
136
|
+
width: t.width,
|
|
137
|
+
height: t.height
|
|
138
|
+
});
|
|
139
|
+
};
|
|
140
|
+
if (t(), typeof ResizeObserver > "u") return window.addEventListener("resize", t), () => window.removeEventListener("resize", t);
|
|
141
|
+
let n = new ResizeObserver(t);
|
|
142
|
+
return n.observe(e), () => n.disconnect();
|
|
143
|
+
}, [u]), a(() => {
|
|
144
|
+
if (!u) return;
|
|
145
|
+
let e = window.setInterval(() => {
|
|
146
|
+
let e = C.current?.getDiagnostics();
|
|
147
|
+
e && W(e);
|
|
148
|
+
}, 500);
|
|
149
|
+
return () => window.clearInterval(e);
|
|
150
|
+
}, [u, H]), a(() => {
|
|
151
|
+
if (!u) return;
|
|
152
|
+
let e = 0, t = performance.now(), n = (r) => {
|
|
153
|
+
let i = O.current.step(r - t);
|
|
154
|
+
t = r, i && F(i), e = requestAnimationFrame(n);
|
|
155
|
+
};
|
|
156
|
+
return e = requestAnimationFrame(n), () => cancelAnimationFrame(e);
|
|
157
|
+
}, [u]), a(() => {
|
|
158
|
+
if (!u) return;
|
|
159
|
+
let t = S.current;
|
|
160
|
+
if (!t) return;
|
|
161
|
+
let n = !1, r = () => {
|
|
162
|
+
w.current?.stop(), w.current = void 0, C.current?.stop(), C.current = void 0, E.current = void 0, T.current = void 0, D.current = {};
|
|
163
|
+
};
|
|
164
|
+
return (async () => {
|
|
165
|
+
r(), k.current = !1, M("starting"), V(""), oe(void 0), z(void 0), K(void 0), J("idle");
|
|
166
|
+
try {
|
|
167
|
+
let r = await e(t, {
|
|
168
|
+
...m,
|
|
169
|
+
torch: f
|
|
170
|
+
});
|
|
171
|
+
if (n) {
|
|
172
|
+
r.stop();
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
C.current = r;
|
|
176
|
+
let a = r.getSettings();
|
|
177
|
+
ce(a), A.current.onSettings?.(a), console.info("[ScannerCameraOverlay] camera settings", a), w.current = await i({
|
|
178
|
+
source: t,
|
|
179
|
+
autoCapture: d,
|
|
180
|
+
intervalMs: ae,
|
|
181
|
+
detection: {
|
|
182
|
+
detector: b,
|
|
183
|
+
modelUrl: x,
|
|
184
|
+
ortWasmPaths: ie
|
|
185
|
+
},
|
|
186
|
+
onStatus: (e) => {
|
|
187
|
+
if (T.current = e, oe(e), A.current.onFinderStatus?.(e), e.quad && e.sourceWidth && e.sourceHeight) {
|
|
188
|
+
let t = O.current.setTarget(e.quad, e.sourceWidth, e.sourceHeight);
|
|
189
|
+
F(t.quad);
|
|
190
|
+
} else O.current.clear(), F(void 0);
|
|
191
|
+
e.state !== "captured" && !k.current && M("ready");
|
|
192
|
+
},
|
|
193
|
+
captureFrame: async () => {
|
|
194
|
+
M("capturing"), D.current = {
|
|
195
|
+
quad: O.current.getCurrent(),
|
|
196
|
+
sourceWidth: T.current?.sourceWidth,
|
|
197
|
+
sourceHeight: T.current?.sourceHeight
|
|
198
|
+
};
|
|
199
|
+
let e = await r.capturePhoto();
|
|
200
|
+
if (E.current = e, z(e.method), K(e.diagnostics), W(e.diagnostics), e.luminance <= 10) throw Error(`The captured frame was blank (luminance ${e.luminance.toFixed(1)} via ${e.method}). Keep the scanner visible while capturing and retake.`);
|
|
201
|
+
return e.frame;
|
|
202
|
+
},
|
|
203
|
+
onCaptureError: (e) => {
|
|
204
|
+
k.current = !0, M("error"), V(e.message);
|
|
205
|
+
let t = C.current?.getDiagnostics();
|
|
206
|
+
t && W(t), A.current.onError?.(e);
|
|
207
|
+
},
|
|
208
|
+
onCapture: async (e) => {
|
|
209
|
+
let t = E.current;
|
|
210
|
+
await new Promise((e) => window.setTimeout(e, 140)), await A.current.onCapture({
|
|
211
|
+
...e,
|
|
212
|
+
method: t?.method ?? "video-frame",
|
|
213
|
+
settings: t?.settings ?? r.getSettings(),
|
|
214
|
+
fallbackReason: t?.fallbackReason,
|
|
215
|
+
luminance: t?.luminance,
|
|
216
|
+
diagnostics: t?.diagnostics,
|
|
217
|
+
displayedQuad: D.current.quad,
|
|
218
|
+
displaySourceWidth: D.current.sourceWidth,
|
|
219
|
+
displaySourceHeight: D.current.sourceHeight
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
});
|
|
223
|
+
} catch (e) {
|
|
224
|
+
if (n) return;
|
|
225
|
+
r();
|
|
226
|
+
let t = e instanceof Error ? e : /* @__PURE__ */ Error("Camera access failed.");
|
|
227
|
+
V(t.message), M("error"), A.current.onError?.(t);
|
|
228
|
+
}
|
|
229
|
+
})(), () => {
|
|
230
|
+
n = !0, r();
|
|
231
|
+
};
|
|
232
|
+
}, [
|
|
233
|
+
u,
|
|
234
|
+
d,
|
|
235
|
+
f,
|
|
236
|
+
m,
|
|
237
|
+
b,
|
|
238
|
+
x,
|
|
239
|
+
ie,
|
|
240
|
+
ae,
|
|
241
|
+
H
|
|
242
|
+
]), !u) return null;
|
|
243
|
+
let Y = () => {
|
|
244
|
+
w.current?.stop(), C.current?.stop(), te();
|
|
245
|
+
}, ue = async () => {
|
|
246
|
+
try {
|
|
247
|
+
await w.current?.capture();
|
|
248
|
+
} catch (e) {
|
|
249
|
+
let t = e instanceof Error ? e : /* @__PURE__ */ Error("Could not capture the camera frame.");
|
|
250
|
+
k.current = !0, V(t.message);
|
|
251
|
+
let n = C.current?.getDiagnostics();
|
|
252
|
+
n && W(n), E.current?.diagnostics && K(E.current.diagnostics), M("error"), g?.(t);
|
|
253
|
+
}
|
|
254
|
+
}, de = () => {
|
|
255
|
+
k.current = !1, V(""), K(void 0), J("idle");
|
|
256
|
+
let e = C.current;
|
|
257
|
+
M(e ? "ready" : "starting"), e || le((e) => e + 1);
|
|
258
|
+
}, fe = async (e) => {
|
|
259
|
+
let t = C.current;
|
|
260
|
+
t && (await t.setTorch(e), W(t.getDiagnostics()));
|
|
261
|
+
}, pe = async () => {
|
|
262
|
+
let e = C.current?.getDiagnostics() ?? U, n = t({
|
|
263
|
+
error: B || void 0,
|
|
264
|
+
captureMethod: R,
|
|
265
|
+
luminance: E.current?.luminance,
|
|
266
|
+
fallbackReason: E.current?.fallbackReason,
|
|
267
|
+
shutter: G ?? E.current?.diagnostics,
|
|
268
|
+
live: e,
|
|
269
|
+
finder: N ? {
|
|
270
|
+
state: N.state,
|
|
271
|
+
confidence: N.confidence,
|
|
272
|
+
stableFrames: N.stableFrames,
|
|
273
|
+
requiredStableFrames: N.requiredStableFrames,
|
|
274
|
+
detector: N.detector,
|
|
275
|
+
modelStatus: N.modelStatus,
|
|
276
|
+
sourceWidth: N.sourceWidth,
|
|
277
|
+
sourceHeight: N.sourceHeight
|
|
278
|
+
} : void 0
|
|
279
|
+
});
|
|
280
|
+
try {
|
|
281
|
+
if (navigator.clipboard?.writeText) await navigator.clipboard.writeText(n);
|
|
282
|
+
else {
|
|
283
|
+
let e = document.createElement("textarea");
|
|
284
|
+
e.value = n, e.setAttribute("readonly", ""), e.style.position = "fixed", e.style.left = "-9999px", document.body.append(e), e.select();
|
|
285
|
+
let t = document.execCommand("copy");
|
|
286
|
+
if (e.remove(), !t) throw Error("Clipboard copy is unavailable.");
|
|
287
|
+
}
|
|
288
|
+
J("copied");
|
|
289
|
+
} catch {
|
|
290
|
+
J("failed");
|
|
291
|
+
}
|
|
292
|
+
}, X = L?.width, Z = L?.height, Q = U?.engine ?? n(), $ = U, me = N?.sourceWidth && N.sourceHeight ? ee(N.sourceWidth, N.sourceHeight, I.width, I.height, y) : void 0, he = N?.modelStatus === "fallback" ? "classical fallback" : N?.modelStatus === "failed" ? "ML failed" : N?.detector === "ml" ? `ML ${N.modelProvider ?? ""}`.trim() : b === "ml" || b === "auto" ? "ML loading" : "classical", ge = N ? r(N.guidance, N.lighting) : void 0;
|
|
293
|
+
return /* @__PURE__ */ l("div", {
|
|
294
|
+
className: `scanner-camera-overlay ${N?.state === "captured" ? "is-captured" : ""} ${ne}`.trim(),
|
|
295
|
+
role: "dialog",
|
|
296
|
+
"aria-modal": "true",
|
|
297
|
+
"aria-label": re,
|
|
298
|
+
children: [
|
|
299
|
+
/* @__PURE__ */ c("video", {
|
|
300
|
+
ref: S,
|
|
301
|
+
className: "scanner-camera-overlay__video",
|
|
302
|
+
muted: !0,
|
|
303
|
+
autoPlay: !0,
|
|
304
|
+
playsInline: !0,
|
|
305
|
+
style: { objectFit: y },
|
|
306
|
+
"aria-label": "Rear camera preview"
|
|
307
|
+
}),
|
|
308
|
+
P && N?.sourceWidth && N.sourceHeight && /* @__PURE__ */ c("svg", {
|
|
309
|
+
className: `scanner-camera-overlay__quad ${N.state}`,
|
|
310
|
+
viewBox: me?.viewBox,
|
|
311
|
+
preserveAspectRatio: me?.preserveAspectRatio,
|
|
312
|
+
"aria-label": `${N.state} document boundary`,
|
|
313
|
+
children: /* @__PURE__ */ c("polygon", { points: `${P.topLeft.x},${P.topLeft.y} ${P.topRight.x},${P.topRight.y} ${P.bottomRight.x},${P.bottomRight.y} ${P.bottomLeft.x},${P.bottomLeft.y}` })
|
|
314
|
+
}),
|
|
315
|
+
/* @__PURE__ */ l("div", {
|
|
316
|
+
className: "scanner-camera-overlay__topbar",
|
|
317
|
+
children: [/* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("strong", { children: re }), /* @__PURE__ */ l("span", {
|
|
318
|
+
"aria-live": "polite",
|
|
319
|
+
children: [
|
|
320
|
+
j === "starting" && "Starting rear camera…",
|
|
321
|
+
j === "ready" && (ge ?? "Place the document in the frame"),
|
|
322
|
+
j === "capturing" && "Capturing full resolution…",
|
|
323
|
+
j === "error" && "Camera unavailable"
|
|
324
|
+
]
|
|
325
|
+
})] }), /* @__PURE__ */ c("button", {
|
|
326
|
+
type: "button",
|
|
327
|
+
onClick: Y,
|
|
328
|
+
"aria-label": "Close camera",
|
|
329
|
+
children: "×"
|
|
330
|
+
})]
|
|
331
|
+
}),
|
|
332
|
+
j === "error" ? /* @__PURE__ */ l("div", {
|
|
333
|
+
className: "scanner-camera-overlay__message",
|
|
334
|
+
role: "alert",
|
|
335
|
+
children: [
|
|
336
|
+
/* @__PURE__ */ c("strong", { children: U ? "Capture failed" : "Could not open the camera" }),
|
|
337
|
+
/* @__PURE__ */ c("p", { children: B }),
|
|
338
|
+
/* @__PURE__ */ l("div", { children: [
|
|
339
|
+
/* @__PURE__ */ c("button", {
|
|
340
|
+
type: "button",
|
|
341
|
+
onClick: de,
|
|
342
|
+
children: "Try again"
|
|
343
|
+
}),
|
|
344
|
+
/* @__PURE__ */ c("button", {
|
|
345
|
+
type: "button",
|
|
346
|
+
onClick: () => void pe(),
|
|
347
|
+
children: q === "copied" ? "Copied" : q === "failed" ? "Copy failed" : "Copy report"
|
|
348
|
+
}),
|
|
349
|
+
/* @__PURE__ */ c("button", {
|
|
350
|
+
type: "button",
|
|
351
|
+
onClick: Y,
|
|
352
|
+
children: "Cancel"
|
|
353
|
+
})
|
|
354
|
+
] })
|
|
355
|
+
]
|
|
356
|
+
}) : j === "starting" ? /* @__PURE__ */ l("div", {
|
|
357
|
+
className: "scanner-camera-overlay__message",
|
|
358
|
+
"aria-live": "polite",
|
|
359
|
+
children: [
|
|
360
|
+
/* @__PURE__ */ c("span", { className: "scanner-camera-overlay__spinner" }),
|
|
361
|
+
/* @__PURE__ */ c("strong", { children: "Requesting the highest practical resolution" }),
|
|
362
|
+
/* @__PURE__ */ c("p", { children: "Allow camera access to continue." })
|
|
363
|
+
]
|
|
364
|
+
}) : null,
|
|
365
|
+
/* @__PURE__ */ l("div", {
|
|
366
|
+
className: "scanner-camera-overlay__status",
|
|
367
|
+
"aria-live": "polite",
|
|
368
|
+
children: [
|
|
369
|
+
/* @__PURE__ */ c("span", { className: N?.state ?? "detecting" }),
|
|
370
|
+
N?.state ?? "detecting",
|
|
371
|
+
N ? ` · ${Math.round(N.confidence * 100)}% · ${N.stableFrames}/${N.requiredStableFrames}` : "",
|
|
372
|
+
` · ${he}`,
|
|
373
|
+
N?.inferenceMs === void 0 ? "" : ` · ${Math.round(N.inferenceMs)}ms`,
|
|
374
|
+
X && Z ? ` · ${X}×${Z}` : ""
|
|
375
|
+
]
|
|
376
|
+
}),
|
|
377
|
+
/* @__PURE__ */ l("dl", {
|
|
378
|
+
className: "scanner-camera-overlay__diagnostics",
|
|
379
|
+
"aria-label": "Camera diagnostics",
|
|
380
|
+
children: [
|
|
381
|
+
/* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("dt", { children: "engine" }), /* @__PURE__ */ l("dd", { children: [
|
|
382
|
+
Q.engine,
|
|
383
|
+
"/",
|
|
384
|
+
Q.browser,
|
|
385
|
+
Q.iosWebKit ? " ios" : ""
|
|
386
|
+
] })] }),
|
|
387
|
+
/* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("dt", { children: "video" }), /* @__PURE__ */ c("dd", { children: $ ? `${$.videoWidth}×${$.videoHeight} rs${$.readyState}${$.paused ? " paused" : ""}${$.rendered ? "" : " hidden"}` : "starting" })] }),
|
|
388
|
+
/* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("dt", { children: "track" }), /* @__PURE__ */ c("dd", { children: $ ? `${$.trackReadyState}${$.trackMuted ? " muted" : ""}${$.trackEnabled ? "" : " disabled"}` : "—" })] }),
|
|
389
|
+
/* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("dt", { children: "torch" }), /* @__PURE__ */ c("dd", { children: $ ? `${$.torch.mode} · ${$.torch.supported ? $.torch.on ? "on" : "off" : "unsupported"}` : "starting" })] }),
|
|
390
|
+
/* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("dt", { children: "luma" }), /* @__PURE__ */ c("dd", { children: $ ? `live ${$.liveLuminance.toFixed(1)} · mirror ${$.mirrorLuminance.toFixed(1)}${Number.isFinite($.mirrorAgeMs) ? ` (${Math.round($.mirrorAgeMs)}ms)` : " (none)"}` : "—" })] }),
|
|
391
|
+
/* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("dt", { children: "path" }), /* @__PURE__ */ c("dd", { children: R ?? "video-frame / live-mirror" })] }),
|
|
392
|
+
G ? /* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("dt", { children: "shutter" }), /* @__PURE__ */ c("dd", { children: `live ${G.liveLuminance.toFixed(1)} · mirror ${G.mirrorLuminance.toFixed(1)}${Number.isFinite(G.mirrorAgeMs) ? ` (${Math.round(G.mirrorAgeMs)}ms)` : " (none)"}` })] }) : null,
|
|
393
|
+
/* @__PURE__ */ l("div", { children: [/* @__PURE__ */ c("dt", { children: "share" }), /* @__PURE__ */ c("dd", { children: /* @__PURE__ */ c("button", {
|
|
394
|
+
type: "button",
|
|
395
|
+
className: "scanner-camera-overlay__copy",
|
|
396
|
+
onClick: () => void pe(),
|
|
397
|
+
children: q === "copied" ? "Copied report" : q === "failed" ? "Copy failed" : "Copy report"
|
|
398
|
+
}) })] })
|
|
399
|
+
]
|
|
400
|
+
}),
|
|
401
|
+
/* @__PURE__ */ l("div", {
|
|
402
|
+
className: "scanner-camera-overlay__controls",
|
|
403
|
+
children: [
|
|
404
|
+
/* @__PURE__ */ c("button", {
|
|
405
|
+
type: "button",
|
|
406
|
+
className: "scanner-camera-overlay__cancel",
|
|
407
|
+
onClick: Y,
|
|
408
|
+
children: "Cancel"
|
|
409
|
+
}),
|
|
410
|
+
/* @__PURE__ */ l("div", {
|
|
411
|
+
className: "scanner-camera-overlay__capture",
|
|
412
|
+
children: [/* @__PURE__ */ c("button", {
|
|
413
|
+
type: "button",
|
|
414
|
+
className: "scanner-camera-overlay__shutter",
|
|
415
|
+
onClick: () => void ue(),
|
|
416
|
+
disabled: j !== "ready",
|
|
417
|
+
"aria-label": "Capture full-resolution photo",
|
|
418
|
+
children: /* @__PURE__ */ c("span", {})
|
|
419
|
+
}), /* @__PURE__ */ l("div", {
|
|
420
|
+
className: "scanner-camera-overlay__toggles",
|
|
421
|
+
children: [N?.autoCapture.visible && /* @__PURE__ */ l("label", { children: [/* @__PURE__ */ c("input", {
|
|
422
|
+
type: "checkbox",
|
|
423
|
+
checked: N.autoCapture.checked,
|
|
424
|
+
onChange: (e) => w.current?.setAutoCapture(e.target.checked)
|
|
425
|
+
}), "Auto-capture"] }), U?.torch.visible && /* @__PURE__ */ l("label", {
|
|
426
|
+
title: U.torch.automatic ? "Torch is controlled automatically from scene brightness" : void 0,
|
|
427
|
+
children: [/* @__PURE__ */ c("input", {
|
|
428
|
+
type: "checkbox",
|
|
429
|
+
checked: U.torch.on,
|
|
430
|
+
disabled: !U.torch.mutable,
|
|
431
|
+
onChange: (e) => void fe(e.target.checked)
|
|
432
|
+
}), U.torch.automatic ? "Auto torch" : "Torch"]
|
|
433
|
+
})]
|
|
434
|
+
})]
|
|
435
|
+
}),
|
|
436
|
+
/* @__PURE__ */ l("div", {
|
|
437
|
+
className: "scanner-camera-overlay__quality",
|
|
438
|
+
children: [/* @__PURE__ */ c("span", { children: R === "live-mirror" ? "Mirror" : "Camera" }), /* @__PURE__ */ c("strong", { children: X && Z ? `${X} × ${Z}` : "Measuring…" })]
|
|
439
|
+
})
|
|
440
|
+
]
|
|
441
|
+
})
|
|
442
|
+
]
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
//#endregion
|
|
446
|
+
export { m as ScannerCameraOverlay };
|
|
447
|
+
|
|
448
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","names":[],"sources":["../src/sdk/display-quad.ts","../src/live-overlay-geometry.ts","../src/components/ScannerCameraOverlay.tsx"],"sourcesContent":["import type { DocumentQuad, Point } from './types'\n\nfunction points(quad: DocumentQuad) {\n return [quad.topLeft, quad.topRight, quad.bottomRight, quad.bottomLeft]\n}\n\nfunction withPoints(next: Point[]): DocumentQuad {\n const [topLeft, topRight, bottomRight, bottomLeft] = next\n return {\n topLeft,\n topRight,\n bottomRight,\n bottomLeft,\n edges: {\n top: { start: topLeft, end: topRight },\n right: { start: topRight, end: bottomRight },\n bottom: { start: bottomRight, end: bottomLeft },\n left: { start: bottomLeft, end: topLeft },\n },\n }\n}\n\nfunction cloneQuad(quad: DocumentQuad) {\n return withPoints(points(quad).map((point) => ({ ...point })))\n}\n\nexport interface QuadDisplaySmootherOptions {\n response?: number\n snapDistance?: number\n}\n\n/**\n * Smooths only the displayed quad. Detector stability must continue to use raw\n * detections and must never consume this animated output.\n */\nexport class QuadDisplaySmoother {\n private current?: DocumentQuad\n private target?: DocumentQuad\n private readonly response: number\n private readonly snapDistance: number\n\n constructor(options: QuadDisplaySmootherOptions = {}) {\n this.response = options.response ?? 14\n this.snapDistance = options.snapDistance ?? 0.1\n }\n\n setTarget(quad: DocumentQuad, frameWidth: number, frameHeight: number) {\n const diagonal = Math.max(1, Math.hypot(frameWidth, frameHeight))\n const shouldSnap = !this.current || points(quad).some((point, index) => {\n const previous = points(this.current!)[index]\n return Math.hypot(point.x - previous.x, point.y - previous.y) / diagonal > this.snapDistance\n })\n this.target = cloneQuad(quad)\n if (shouldSnap) this.current = cloneQuad(quad)\n return { quad: this.current, snapped: shouldSnap }\n }\n\n step(deltaMs: number) {\n if (!this.current || !this.target) return this.current\n const alpha = 1 - Math.exp(-this.response * Math.max(0, deltaMs) / 1000)\n this.current = withPoints(points(this.current).map((point, index) => {\n const target = points(this.target!)[index]\n return {\n x: point.x + (target.x - point.x) * alpha,\n y: point.y + (target.y - point.y) * alpha,\n }\n }))\n return this.current\n }\n\n clear() {\n this.current = undefined\n this.target = undefined\n }\n\n getCurrent() {\n return this.current\n }\n}\n","import type { Point } from './sdk/types'\n\nexport type LivePreviewFit = 'contain' | 'cover'\n\nexport interface LiveOverlayTransform {\n viewBox: string\n preserveAspectRatio: 'none' | 'xMidYMid meet'\n scale: number\n offsetX: number\n offsetY: number\n}\n\nexport function liveOverlayTransform(\n sourceWidth: number,\n sourceHeight: number,\n renderedWidth: number,\n renderedHeight: number,\n fit: LivePreviewFit,\n): LiveOverlayTransform {\n const safeSourceWidth = Math.max(1, sourceWidth)\n const safeSourceHeight = Math.max(1, sourceHeight)\n const safeRenderedWidth = Math.max(1, renderedWidth)\n const safeRenderedHeight = Math.max(1, renderedHeight)\n const widthScale = safeRenderedWidth / safeSourceWidth\n const heightScale = safeRenderedHeight / safeSourceHeight\n const scale = fit === 'cover'\n ? Math.max(widthScale, heightScale)\n : Math.min(widthScale, heightScale)\n const offsetX = (safeRenderedWidth - safeSourceWidth * scale) / 2\n const offsetY = (safeRenderedHeight - safeSourceHeight * scale) / 2\n if (fit === 'contain') {\n return {\n viewBox: `0 0 ${safeSourceWidth} ${safeSourceHeight}`,\n preserveAspectRatio: 'xMidYMid meet',\n scale,\n offsetX,\n offsetY,\n }\n }\n const visibleWidth = safeRenderedWidth / scale\n const visibleHeight = safeRenderedHeight / scale\n return {\n viewBox: `${-offsetX / scale} ${-offsetY / scale} ${visibleWidth} ${visibleHeight}`,\n preserveAspectRatio: 'none',\n scale,\n offsetX,\n offsetY,\n }\n}\n\nexport function mapLiveSourcePoint(point: Point, transform: LiveOverlayTransform): Point {\n return {\n x: transform.offsetX + point.x * transform.scale,\n y: transform.offsetY + point.y * transform.scale,\n }\n}\n","import { useEffect, useRef, useState } from 'react'\nimport {\n detectBrowserEngine,\n formatCaptureDiagnosticsReport,\n NEAR_BLACK_LUMINANCE,\n startCamera,\n type CameraDiagnostics,\n type CameraOptions,\n type CameraPhoto,\n type CameraSession,\n type TorchMode,\n} from '../sdk/camera'\nimport {\n selectFinderHint,\n startFinder,\n type AutoCaptureMode,\n type FinderCapture,\n type FinderSession,\n type FinderStatus,\n} from '../sdk/finder'\nimport { QuadDisplaySmoother } from '../sdk/display-quad'\nimport type { DocumentQuad } from '../sdk/types'\nimport type { DocumentDetectorMode } from '../sdk/types'\nimport {\n liveOverlayTransform,\n type LivePreviewFit,\n} from '../live-overlay-geometry'\nimport './scanner-camera-overlay.css'\n\nexport interface ScannerCameraOverlayCapture extends FinderCapture {\n method: CameraPhoto['method']\n settings: MediaTrackSettings\n fallbackReason?: CameraPhoto['fallbackReason']\n luminance?: number\n diagnostics?: CameraDiagnostics\n displayedQuad?: DocumentQuad\n displaySourceWidth?: number\n displaySourceHeight?: number\n}\n\nexport interface ScannerCameraOverlayProps {\n open: boolean\n autoCapture?: AutoCaptureMode\n /** Camera torch policy. Defaults to `defaultOff`. */\n torch?: TorchMode\n cameraOptions?: CameraOptions\n onCapture: (capture: ScannerCameraOverlayCapture) => void | Promise<void>\n onClose: () => void\n onError?: (error: Error) => void\n onSettings?: (settings: MediaTrackSettings) => void\n onFinderStatus?: (status: FinderStatus) => void\n className?: string\n title?: string\n previewFit?: LivePreviewFit\n detector?: DocumentDetectorMode\n modelUrl?: string\n ortWasmPaths?: string\n detectionIntervalMs?: number\n}\n\ntype OverlayPhase = 'starting' | 'ready' | 'capturing' | 'error'\n\nexport function ScannerCameraOverlay({\n open,\n autoCapture = 'defaultOn',\n torch = 'defaultOff',\n cameraOptions,\n onCapture,\n onClose,\n onError,\n onSettings,\n onFinderStatus,\n className = '',\n title = 'Scan a document',\n previewFit = 'cover',\n detector = 'classical',\n modelUrl,\n ortWasmPaths,\n detectionIntervalMs,\n}: ScannerCameraOverlayProps) {\n const videoRef = useRef<HTMLVideoElement>(null)\n const cameraRef = useRef<CameraSession | undefined>(undefined)\n const finderRef = useRef<FinderSession | undefined>(undefined)\n const finderStatusRef = useRef<FinderStatus | undefined>(undefined)\n const latestPhotoRef = useRef<CameraPhoto | undefined>(undefined)\n const capturedDisplayRef = useRef<{\n quad?: DocumentQuad\n sourceWidth?: number\n sourceHeight?: number\n }>({})\n const displaySmootherRef = useRef(new QuadDisplaySmoother())\n // Finder ticks continue after a failed capture, so the error must survive\n // the status updates that would otherwise restore the \"ready\" phase.\n const captureErrorRef = useRef(false)\n const callbacksRef = useRef({ onCapture, onError, onSettings, onFinderStatus })\n const [phase, setPhase] = useState<OverlayPhase>('starting')\n const [finderStatus, setFinderStatus] = useState<FinderStatus>()\n const [displayQuad, setDisplayQuad] = useState<DocumentQuad>()\n const [previewSize, setPreviewSize] = useState({ width: 1, height: 1 })\n const [settings, setSettings] = useState<MediaTrackSettings>()\n const [captureMethod, setCaptureMethod] = useState<CameraPhoto['method']>()\n const [error, setError] = useState('')\n const [attempt, setAttempt] = useState(0)\n const [diagnostics, setDiagnostics] = useState<CameraDiagnostics>()\n const [shutterDiagnostics, setShutterDiagnostics] = useState<CameraDiagnostics>()\n const [copyState, setCopyState] = useState<'idle' | 'copied' | 'failed'>('idle')\n\n useEffect(() => {\n callbacksRef.current = { onCapture, onError, onSettings, onFinderStatus }\n }, [onCapture, onError, onSettings, onFinderStatus])\n\n useEffect(() => {\n if (!open) return\n const previousOverflow = document.body.style.overflow\n document.body.style.overflow = 'hidden'\n return () => {\n document.body.style.overflow = previousOverflow\n }\n }, [open])\n\n useEffect(() => {\n if (!open) return\n const video = videoRef.current\n if (!video) return\n const updateSize = () => {\n const bounds = video.getBoundingClientRect()\n setPreviewSize({ width: bounds.width, height: bounds.height })\n }\n updateSize()\n if (typeof ResizeObserver === 'undefined') {\n window.addEventListener('resize', updateSize)\n return () => window.removeEventListener('resize', updateSize)\n }\n const observer = new ResizeObserver(updateSize)\n observer.observe(video)\n return () => observer.disconnect()\n }, [open])\n\n useEffect(() => {\n if (!open) return\n const poll = window.setInterval(() => {\n const current = cameraRef.current?.getDiagnostics()\n if (current) setDiagnostics(current)\n }, 500)\n return () => window.clearInterval(poll)\n }, [open, attempt])\n\n useEffect(() => {\n if (!open) return\n let animationFrame = 0\n let previousTime = performance.now()\n const animate = (time: number) => {\n const next = displaySmootherRef.current.step(time - previousTime)\n previousTime = time\n if (next) setDisplayQuad(next)\n animationFrame = requestAnimationFrame(animate)\n }\n animationFrame = requestAnimationFrame(animate)\n return () => cancelAnimationFrame(animationFrame)\n }, [open])\n\n useEffect(() => {\n if (!open) return\n const video = videoRef.current\n if (!video) return\n let cancelled = false\n\n const stop = () => {\n finderRef.current?.stop()\n finderRef.current = undefined\n cameraRef.current?.stop()\n cameraRef.current = undefined\n latestPhotoRef.current = undefined\n finderStatusRef.current = undefined\n capturedDisplayRef.current = {}\n }\n\n const start = async () => {\n stop()\n captureErrorRef.current = false\n setPhase('starting')\n setError('')\n setFinderStatus(undefined)\n setCaptureMethod(undefined)\n setShutterDiagnostics(undefined)\n setCopyState('idle')\n try {\n const camera = await startCamera(video, { ...cameraOptions, torch })\n if (cancelled) {\n camera.stop()\n return\n }\n cameraRef.current = camera\n const actualSettings = camera.getSettings()\n setSettings(actualSettings)\n callbacksRef.current.onSettings?.(actualSettings)\n console.info('[ScannerCameraOverlay] camera settings', actualSettings)\n finderRef.current = await startFinder({\n source: video,\n autoCapture,\n intervalMs: detectionIntervalMs,\n detection: {\n detector,\n modelUrl,\n ortWasmPaths,\n },\n onStatus: (status) => {\n finderStatusRef.current = status\n setFinderStatus(status)\n callbacksRef.current.onFinderStatus?.(status)\n if (status.quad && status.sourceWidth && status.sourceHeight) {\n const update = displaySmootherRef.current.setTarget(\n status.quad,\n status.sourceWidth,\n status.sourceHeight,\n )\n setDisplayQuad(update.quad)\n } else {\n displaySmootherRef.current.clear()\n setDisplayQuad(undefined)\n }\n if (status.state !== 'captured' && !captureErrorRef.current) setPhase('ready')\n },\n captureFrame: async () => {\n setPhase('capturing')\n capturedDisplayRef.current = {\n quad: displaySmootherRef.current.getCurrent(),\n sourceWidth: finderStatusRef.current?.sourceWidth,\n sourceHeight: finderStatusRef.current?.sourceHeight,\n }\n const photo = await camera.capturePhoto()\n latestPhotoRef.current = photo\n setCaptureMethod(photo.method)\n setShutterDiagnostics(photo.diagnostics)\n setDiagnostics(photo.diagnostics)\n if (photo.luminance <= NEAR_BLACK_LUMINANCE) {\n throw new Error(\n `The captured frame was blank (luminance ${photo.luminance.toFixed(1)} via ${photo.method}). Keep the scanner visible while capturing and retake.`,\n )\n }\n return photo.frame\n },\n onCaptureError: (captureError) => {\n captureErrorRef.current = true\n setPhase('error')\n setError(captureError.message)\n const live = cameraRef.current?.getDiagnostics()\n if (live) setDiagnostics(live)\n callbacksRef.current.onError?.(captureError)\n },\n onCapture: async (capture) => {\n const photo = latestPhotoRef.current\n // Finder has already copied the final frame and emitted its\n // captured state. Let shutter/flash feedback paint before the host\n // dismisses this overlay and starts crop/OCR work.\n await new Promise((resolve) => window.setTimeout(resolve, 140))\n await callbacksRef.current.onCapture({\n ...capture,\n method: photo?.method ?? 'video-frame',\n settings: photo?.settings ?? camera.getSettings(),\n fallbackReason: photo?.fallbackReason,\n luminance: photo?.luminance,\n diagnostics: photo?.diagnostics,\n displayedQuad: capturedDisplayRef.current.quad,\n displaySourceWidth: capturedDisplayRef.current.sourceWidth,\n displaySourceHeight: capturedDisplayRef.current.sourceHeight,\n })\n },\n })\n } catch (cause) {\n if (cancelled) return\n stop()\n const nextError = cause instanceof Error ? cause : new Error('Camera access failed.')\n setError(nextError.message)\n setPhase('error')\n callbacksRef.current.onError?.(nextError)\n }\n }\n\n void start()\n return () => {\n cancelled = true\n stop()\n }\n }, [\n open,\n autoCapture,\n torch,\n cameraOptions,\n detector,\n modelUrl,\n ortWasmPaths,\n detectionIntervalMs,\n attempt,\n ])\n\n if (!open) return null\n\n const close = () => {\n finderRef.current?.stop()\n cameraRef.current?.stop()\n onClose()\n }\n const capture = async () => {\n try {\n await finderRef.current?.capture()\n } catch (cause) {\n const nextError = cause instanceof Error ? cause : new Error('Could not capture the camera frame.')\n captureErrorRef.current = true\n setError(nextError.message)\n const live = cameraRef.current?.getDiagnostics()\n if (live) setDiagnostics(live)\n if (latestPhotoRef.current?.diagnostics) setShutterDiagnostics(latestPhotoRef.current.diagnostics)\n setPhase('error')\n onError?.(nextError)\n }\n }\n const retry = () => {\n captureErrorRef.current = false\n setError('')\n setShutterDiagnostics(undefined)\n setCopyState('idle')\n const liveCamera = cameraRef.current\n setPhase(liveCamera ? 'ready' : 'starting')\n if (!liveCamera) setAttempt((value) => value + 1)\n }\n const setTorch = async (enabled: boolean) => {\n const camera = cameraRef.current\n if (!camera) return\n await camera.setTorch(enabled)\n setDiagnostics(camera.getDiagnostics())\n }\n const copyReport = async () => {\n const live = cameraRef.current?.getDiagnostics() ?? diagnostics\n const report = formatCaptureDiagnosticsReport({\n error: error || undefined,\n captureMethod,\n luminance: latestPhotoRef.current?.luminance,\n fallbackReason: latestPhotoRef.current?.fallbackReason,\n shutter: shutterDiagnostics ?? latestPhotoRef.current?.diagnostics,\n live,\n finder: finderStatus\n ? {\n state: finderStatus.state,\n confidence: finderStatus.confidence,\n stableFrames: finderStatus.stableFrames,\n requiredStableFrames: finderStatus.requiredStableFrames,\n detector: finderStatus.detector,\n modelStatus: finderStatus.modelStatus,\n sourceWidth: finderStatus.sourceWidth,\n sourceHeight: finderStatus.sourceHeight,\n }\n : undefined,\n })\n try {\n if (navigator.clipboard?.writeText) {\n await navigator.clipboard.writeText(report)\n } else {\n const field = document.createElement('textarea')\n field.value = report\n field.setAttribute('readonly', '')\n field.style.position = 'fixed'\n field.style.left = '-9999px'\n document.body.append(field)\n field.select()\n const copied = document.execCommand('copy')\n field.remove()\n if (!copied) throw new Error('Clipboard copy is unavailable.')\n }\n setCopyState('copied')\n } catch {\n setCopyState('failed')\n }\n }\n const width = settings?.width\n const height = settings?.height\n const engine = diagnostics?.engine ?? detectBrowserEngine()\n const liveDiagnostics = diagnostics\n const overlayTransform = finderStatus?.sourceWidth && finderStatus.sourceHeight\n ? liveOverlayTransform(\n finderStatus.sourceWidth,\n finderStatus.sourceHeight,\n previewSize.width,\n previewSize.height,\n previewFit,\n )\n : undefined\n const detectorStatus = finderStatus?.modelStatus === 'fallback'\n ? 'classical fallback'\n : finderStatus?.modelStatus === 'failed'\n ? 'ML failed'\n : finderStatus?.detector === 'ml'\n ? `ML ${finderStatus.modelProvider ?? ''}`.trim()\n : detector === 'ml' || detector === 'auto'\n ? 'ML loading'\n : 'classical'\n const guidanceHint = finderStatus\n ? selectFinderHint(finderStatus.guidance, finderStatus.lighting)\n : undefined\n\n return (\n <div\n className={`scanner-camera-overlay ${finderStatus?.state === 'captured' ? 'is-captured' : ''} ${className}`.trim()}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n >\n <video\n ref={videoRef}\n className=\"scanner-camera-overlay__video\"\n muted\n autoPlay\n playsInline\n style={{ objectFit: previewFit }}\n aria-label=\"Rear camera preview\"\n />\n\n {displayQuad && finderStatus?.sourceWidth && finderStatus.sourceHeight && (\n <svg\n className={`scanner-camera-overlay__quad ${finderStatus.state}`}\n viewBox={overlayTransform?.viewBox}\n preserveAspectRatio={overlayTransform?.preserveAspectRatio}\n aria-label={`${finderStatus.state} document boundary`}\n >\n <polygon points={`${displayQuad.topLeft.x},${displayQuad.topLeft.y} ${displayQuad.topRight.x},${displayQuad.topRight.y} ${displayQuad.bottomRight.x},${displayQuad.bottomRight.y} ${displayQuad.bottomLeft.x},${displayQuad.bottomLeft.y}`} />\n </svg>\n )}\n\n <div className=\"scanner-camera-overlay__topbar\">\n <div>\n <strong>{title}</strong>\n <span aria-live=\"polite\">\n {phase === 'starting' && 'Starting rear camera…'}\n {phase === 'ready' && (guidanceHint ?? 'Place the document in the frame')}\n {phase === 'capturing' && 'Capturing full resolution…'}\n {phase === 'error' && 'Camera unavailable'}\n </span>\n </div>\n <button type=\"button\" onClick={close} aria-label=\"Close camera\">×</button>\n </div>\n\n {phase === 'error' ? (\n <div className=\"scanner-camera-overlay__message\" role=\"alert\">\n <strong>{diagnostics ? 'Capture failed' : 'Could not open the camera'}</strong>\n <p>{error}</p>\n <div>\n <button type=\"button\" onClick={retry}>Try again</button>\n <button type=\"button\" onClick={() => void copyReport()}>\n {copyState === 'copied' ? 'Copied' : copyState === 'failed' ? 'Copy failed' : 'Copy report'}\n </button>\n <button type=\"button\" onClick={close}>Cancel</button>\n </div>\n </div>\n ) : phase === 'starting' ? (\n <div className=\"scanner-camera-overlay__message\" aria-live=\"polite\">\n <span className=\"scanner-camera-overlay__spinner\" />\n <strong>Requesting the highest practical resolution</strong>\n <p>Allow camera access to continue.</p>\n </div>\n ) : null}\n\n <div className=\"scanner-camera-overlay__status\" aria-live=\"polite\">\n <span className={finderStatus?.state ?? 'detecting'} />\n {finderStatus?.state ?? 'detecting'}\n {finderStatus ? ` · ${Math.round(finderStatus.confidence * 100)}% · ${finderStatus.stableFrames}/${finderStatus.requiredStableFrames}` : ''}\n {` · ${detectorStatus}`}\n {finderStatus?.inferenceMs !== undefined ? ` · ${Math.round(finderStatus.inferenceMs)}ms` : ''}\n {width && height ? ` · ${width}×${height}` : ''}\n </div>\n\n <dl className=\"scanner-camera-overlay__diagnostics\" aria-label=\"Camera diagnostics\">\n <div>\n <dt>engine</dt>\n <dd>{engine.engine}/{engine.browser}{engine.iosWebKit ? ' ios' : ''}</dd>\n </div>\n <div>\n <dt>video</dt>\n <dd>\n {liveDiagnostics\n ? `${liveDiagnostics.videoWidth}×${liveDiagnostics.videoHeight} rs${liveDiagnostics.readyState}${liveDiagnostics.paused ? ' paused' : ''}${liveDiagnostics.rendered ? '' : ' hidden'}`\n : 'starting'}\n </dd>\n </div>\n <div>\n <dt>track</dt>\n <dd>\n {liveDiagnostics\n ? `${liveDiagnostics.trackReadyState}${liveDiagnostics.trackMuted ? ' muted' : ''}${liveDiagnostics.trackEnabled ? '' : ' disabled'}`\n : '—'}\n </dd>\n </div>\n <div>\n <dt>torch</dt>\n <dd>\n {liveDiagnostics\n ? `${liveDiagnostics.torch.mode} · ${liveDiagnostics.torch.supported ? (liveDiagnostics.torch.on ? 'on' : 'off') : 'unsupported'}`\n : 'starting'}\n </dd>\n </div>\n <div>\n <dt>luma</dt>\n <dd>\n {liveDiagnostics\n ? `live ${liveDiagnostics.liveLuminance.toFixed(1)} · mirror ${liveDiagnostics.mirrorLuminance.toFixed(1)}${Number.isFinite(liveDiagnostics.mirrorAgeMs) ? ` (${Math.round(liveDiagnostics.mirrorAgeMs)}ms)` : ' (none)'}`\n : '—'}\n </dd>\n </div>\n <div>\n <dt>path</dt>\n <dd>\n {captureMethod ?? 'video-frame / live-mirror'}\n </dd>\n </div>\n {shutterDiagnostics ? (\n <div>\n <dt>shutter</dt>\n <dd>\n {`live ${shutterDiagnostics.liveLuminance.toFixed(1)} · mirror ${shutterDiagnostics.mirrorLuminance.toFixed(1)}${Number.isFinite(shutterDiagnostics.mirrorAgeMs) ? ` (${Math.round(shutterDiagnostics.mirrorAgeMs)}ms)` : ' (none)'}`}\n </dd>\n </div>\n ) : null}\n <div>\n <dt>share</dt>\n <dd>\n <button\n type=\"button\"\n className=\"scanner-camera-overlay__copy\"\n onClick={() => void copyReport()}\n >\n {copyState === 'copied' ? 'Copied report' : copyState === 'failed' ? 'Copy failed' : 'Copy report'}\n </button>\n </dd>\n </div>\n </dl>\n\n <div className=\"scanner-camera-overlay__controls\">\n <button type=\"button\" className=\"scanner-camera-overlay__cancel\" onClick={close}>Cancel</button>\n <div className=\"scanner-camera-overlay__capture\">\n <button\n type=\"button\"\n className=\"scanner-camera-overlay__shutter\"\n onClick={() => void capture()}\n disabled={phase !== 'ready'}\n aria-label=\"Capture full-resolution photo\"\n >\n <span />\n </button>\n <div className=\"scanner-camera-overlay__toggles\">\n {finderStatus?.autoCapture.visible && (\n <label>\n <input\n type=\"checkbox\"\n checked={finderStatus.autoCapture.checked}\n onChange={(event) => finderRef.current?.setAutoCapture(event.target.checked)}\n />\n Auto-capture\n </label>\n )}\n {diagnostics?.torch.visible && (\n <label title={diagnostics.torch.automatic ? 'Torch is controlled automatically from scene brightness' : undefined}>\n <input\n type=\"checkbox\"\n checked={diagnostics.torch.on}\n disabled={!diagnostics.torch.mutable}\n onChange={(event) => void setTorch(event.target.checked)}\n />\n {diagnostics.torch.automatic ? 'Auto torch' : 'Torch'}\n </label>\n )}\n </div>\n </div>\n <div className=\"scanner-camera-overlay__quality\">\n <span>{captureMethod === 'live-mirror' ? 'Mirror' : 'Camera'}</span>\n <strong>{width && height ? `${width} × ${height}` : 'Measuring…'}</strong>\n </div>\n </div>\n </div>\n )\n}\n"],"mappings":"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"}
|