@exige/web-scanner-sdk 0.2.37 → 0.2.39

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/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","names":[],"sources":["../src/sdk/display-quad.ts","../src/react/scanner-context.ts","../src/react/context.tsx","../src/react/hooks.ts","../src/live-overlay-geometry.ts","../src/components/ModelDownloadRing.tsx","../src/react/guidance.ts","../src/react/parts.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 { createContext } from 'react'\nimport type { ScannerApi, ScannerState } from './types'\n\nexport interface ScannerContextValue extends ScannerState, ScannerApi {\n bindPreview: (node: HTMLVideoElement | null) => void\n}\n\nexport const ScannerContext = createContext<ScannerContextValue | null>(null)\n","import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport {\n detectBrowserEngine,\n formatCaptureDiagnosticsReport,\n hasTransientUserActivation,\n meanFrameLuminance,\n NEAR_BLACK_LUMINANCE,\n pickNativeCameraStill,\n shouldUseImageCapture,\n shouldUseSystemCameraCapture,\n startCamera,\n type CameraDiagnostics,\n type CameraPhoto,\n type CameraSession,\n} from '../sdk/camera'\nimport {\n selectFinderHint,\n startFinder,\n type FinderSession,\n type FinderStatus,\n} from '../sdk/finder'\nimport { decodePdf417, PDF417_LIVE_MAX_EDGE } from '../sdk/barcode'\nimport { scanSystemCameraStill } from '../sdk/scan'\nimport {\n LICENSE_BACK_POLL_MS,\n startDriverLicenseSession,\n waitForPdf417Frame,\n type DriverLicenseSession,\n} from '../sdk/driver-license'\nimport { QuadDisplaySmoother } from '../sdk/display-quad'\nimport {\n subscribeModelDownloads,\n type ModelDownloadSnapshot,\n} from '../sdk/model-download'\nimport type { DocumentQuad } from '../sdk/types'\nimport type { ScannerApi, ScannerCapture, ScannerProviderProps, ScannerState } from './types'\nimport { ScannerContext, type ScannerContextValue } from './scanner-context'\n\nfunction revokePreviewUrl(url: string | undefined) {\n if (url?.startsWith('blob:')) URL.revokeObjectURL(url)\n}\n\nfunction stillUrlFromCanvas(canvas: HTMLCanvasElement): string | undefined {\n try {\n const url = canvas.toDataURL('image/jpeg', 0.92)\n return url.startsWith('data:image/') ? url : undefined\n } catch {\n return undefined\n }\n}\n\nfunction invokeIfFunction<T>(\n fn: ((value: T) => void | Promise<void>) | undefined,\n value: T,\n) {\n if (typeof fn === 'function') return fn(value)\n}\n\nexport function ScannerProvider({\n open,\n useCase = 'document',\n autoCapture = 'defaultOn',\n captureMode = 'auto',\n torch = 'defaultOff',\n onCapture,\n onDriverLicense,\n onCancel,\n onError,\n onSettings,\n onFinderStatus,\n modelUrl,\n ortWasmPaths,\n detectionIntervalMs,\n apiRef,\n children,\n}: ScannerProviderProps) {\n const usingSystemCamera = shouldUseSystemCameraCapture(captureMode)\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 const captureErrorRef = useRef(false)\n const systemCaptureInFlightRef = useRef(false)\n const callbacksRef = useRef({\n onCapture,\n onDriverLicense,\n onCancel,\n onError,\n onSettings,\n onFinderStatus,\n useCase,\n })\n const licenseSessionRef = useRef<DriverLicenseSession | undefined>(undefined)\n const licenseReadyRef = useRef<Promise<DriverLicenseSession> | undefined>(undefined)\n const handleLicenseStillRef = useRef<(capture: ScannerCapture) => Promise<void>>(async () => undefined)\n const licenseBackLockRef = useRef(false)\n const barcodeAbortRef = useRef<AbortController | undefined>(undefined)\n const stateRef = useRef<ScannerState>(null!)\n const [preview, setPreview] = useState<HTMLVideoElement | null>(null)\n const [phase, setPhase] = useState<ScannerState['phase']>(\n usingSystemCamera && open ? 'capturing' : usingSystemCamera ? 'ready' : 'starting',\n )\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<ScannerState['copyState']>('idle')\n const [frozenPreviewUrl, setFrozenPreviewUrl] = useState<string>()\n const frozenPreviewUrlRef = useRef<string | undefined>(undefined)\n const [licenseSide, setLicenseSide] = useState<'front' | 'back'>('front')\n const licenseSideRef = useRef<'front' | 'back'>('front')\n const [licenseBusy, setLicenseBusy] = useState(false)\n const [modelDownload, setModelDownload] = useState<ModelDownloadSnapshot>({\n downloading: false,\n loaded: 0,\n total: null,\n })\n\n const clearFrozenPreview = useCallback(() => {\n revokePreviewUrl(frozenPreviewUrlRef.current)\n frozenPreviewUrlRef.current = undefined\n setFrozenPreviewUrl(undefined)\n }, [])\n\n const freezePreview = useCallback((frame: HTMLCanvasElement, video?: HTMLVideoElement | null) => {\n const still = stillUrlFromCanvas(frame)\n revokePreviewUrl(frozenPreviewUrlRef.current)\n frozenPreviewUrlRef.current = still\n setFrozenPreviewUrl(still)\n video?.pause()\n }, [])\n\n useLayoutEffect(() => {\n callbacksRef.current = {\n onCapture,\n onDriverLicense,\n onCancel,\n onError,\n onSettings,\n onFinderStatus,\n useCase,\n }\n }, [onCapture, onDriverLicense, onCancel, onError, onSettings, onFinderStatus, useCase])\n\n useEffect(() => subscribeModelDownloads(setModelDownload), [])\n\n useEffect(() => {\n if (!open || useCase !== 'drivers-license') {\n licenseReadyRef.current = undefined\n licenseSessionRef.current = undefined\n licenseBackLockRef.current = false\n setLicenseSide('front')\n setLicenseBusy(false)\n return\n }\n const sessionPromise = startDriverLicenseSession({\n scan: { modelUrl, ortWasmPaths },\n })\n licenseReadyRef.current = sessionPromise\n void sessionPromise.then((session) => {\n licenseSessionRef.current = session\n })\n return () => {\n void sessionPromise.then((session) => session.cancel())\n if (licenseSessionRef.current) licenseSessionRef.current = undefined\n licenseReadyRef.current = undefined\n }\n }, [open, useCase, modelUrl, ortWasmPaths])\n\n const bindPreview = useCallback((node: HTMLVideoElement | null) => {\n setPreview(node)\n }, [])\n\n useEffect(() => {\n if (!open || !preview) return\n const updateSize = () => {\n const bounds = preview.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(preview)\n return () => observer.disconnect()\n }, [open, preview])\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 || usingSystemCamera) return\n if (!preview) return\n let cancelled = false\n let barcodeAbort = new AbortController()\n barcodeAbortRef.current = barcodeAbort\n\n const stop = () => {\n barcodeAbort.abort()\n if (barcodeAbortRef.current === barcodeAbort) barcodeAbortRef.current = undefined\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 clearFrozenPreview()\n }\n\n const start = async () => {\n stop()\n barcodeAbort = new AbortController()\n barcodeAbortRef.current = barcodeAbort\n captureErrorRef.current = false\n setPhase('starting')\n setError('')\n setFinderStatus(undefined)\n setCaptureMethod(undefined)\n setShutterDiagnostics(undefined)\n setCopyState('idle')\n clearFrozenPreview()\n try {\n const camera = await startCamera(preview, { 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('[ScannerProvider] camera settings', actualSettings)\n const licenseBack = callbacksRef.current.useCase === 'drivers-license'\n && licenseSideRef.current === 'back'\n if (licenseBack) {\n setFinderStatus(undefined)\n setDisplayQuad(undefined)\n displaySmootherRef.current.clear()\n setPhase('ready')\n void (async () => {\n try {\n let photoTick = 0\n const frame = await waitForPdf417Frame(\n async () => {\n photoTick += 1\n const engine = detectBrowserEngine()\n if (\n photoTick % 4 === 0\n && shouldUseImageCapture(engine, 'ImageCapture' in globalThis)\n ) {\n try {\n const photo = await camera.capturePhoto()\n if (photo.frame && photo.luminance > NEAR_BLACK_LUMINANCE) return photo.frame\n } catch {\n // Live frame / mirror next.\n }\n }\n try {\n return await camera.captureLiveFrame(PDF417_LIVE_MAX_EDGE)\n } catch {\n // Video not ready; poll again.\n return undefined\n }\n },\n { intervalMs: detectionIntervalMs ?? LICENSE_BACK_POLL_MS, signal: barcodeAbort.signal },\n )\n if (cancelled || barcodeAbort.signal.aborted || licenseBackLockRef.current) return\n licenseBackLockRef.current = true\n freezePreview(frame, preview)\n setCaptureMethod('live-mirror')\n setPhase('captured')\n await handleLicenseStillRef.current({\n frame,\n reason: 'auto',\n method: 'live-mirror',\n settings: camera.getSettings(),\n })\n } catch (cause) {\n if (cancelled || barcodeAbort.signal.aborted) return\n if (cause instanceof DOMException && cause.name === 'AbortError') return\n const nextError = cause instanceof Error ? cause : new Error('Could not read the barcode.')\n captureErrorRef.current = true\n setError(nextError.message)\n setPhase('error')\n callbacksRef.current.onError?.(nextError)\n }\n })()\n return\n }\n finderRef.current = await startFinder({\n source: preview,\n autoCapture,\n intervalMs: detectionIntervalMs,\n detection: {\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 freezePreview(photo.frame, preview)\n setPhase('captured')\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 await new Promise((resolve) => window.setTimeout(resolve, 140))\n const nextCapture = {\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 if (callbacksRef.current.useCase === 'drivers-license') {\n await handleLicenseStillRef.current(nextCapture)\n return\n }\n await invokeIfFunction(callbacksRef.current.onCapture, nextCapture)\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 preview,\n usingSystemCamera,\n autoCapture,\n torch,\n modelUrl,\n ortWasmPaths,\n detectionIntervalMs,\n attempt,\n clearFrozenPreview,\n freezePreview,\n ])\n\n const guidanceHint = finderStatus\n ? selectFinderHint(finderStatus.guidance, finderStatus.lighting)\n : undefined\n const licenseBackLive = useCase === 'drivers-license'\n && licenseSide === 'back'\n && !usingSystemCamera\n const detectorStatus = licenseBackLive\n ? 'zxing'\n : finderStatus?.modelStatus === 'failed'\n ? `ML failed${finderStatus.modelError ? `: ${finderStatus.modelError}` : ''}`\n : finderStatus?.detector === 'ml'\n ? `ML ${finderStatus.modelProvider ?? ''}`.trim()\n : 'ML loading'\n const state: ScannerState = {\n open,\n phase,\n autoCapture,\n captureMode,\n usingSystemCamera,\n finderStatus,\n displayQuad,\n previewSize,\n settings,\n captureMethod,\n error,\n diagnostics,\n shutterDiagnostics,\n copyState,\n guidanceHint,\n detectorStatus,\n modelDownload,\n frozenPreviewUrl,\n useCase,\n licenseSide: useCase === 'drivers-license' ? licenseSide : undefined,\n licenseBusy: useCase === 'drivers-license' ? licenseBusy : undefined,\n }\n useEffect(() => {\n stateRef.current = state\n })\n\n const cancel = useCallback(() => {\n callbacksRef.current.onCancel()\n }, [])\n\n const captureSystemStill = useCallback(async () => {\n if (systemCaptureInFlightRef.current) return\n systemCaptureInFlightRef.current = true\n captureErrorRef.current = false\n setError('')\n setDisplayQuad(undefined)\n displaySmootherRef.current.clear()\n setPhase('capturing')\n try {\n const frame = await pickNativeCameraStill()\n freezePreview(frame)\n const settings = {\n width: frame.width,\n height: frame.height,\n } satisfies MediaTrackSettings\n setSettings(settings)\n callbacksRef.current.onSettings?.(settings)\n setCaptureMethod('system-camera')\n let luminance: number | undefined\n try {\n const pixels = frame.getContext('2d', { willReadFrequently: true })\n ?.getImageData(0, 0, frame.width, frame.height).data\n if (pixels) luminance = meanFrameLuminance(pixels)\n } catch {\n luminance = undefined\n }\n const licenseBack = callbacksRef.current.useCase === 'drivers-license'\n && licenseSideRef.current === 'back'\n if (licenseBack) {\n setDisplayQuad(undefined)\n displaySmootherRef.current.clear()\n capturedDisplayRef.current = {}\n setPhase('captured')\n await handleLicenseStillRef.current({\n frame,\n reason: 'manual',\n method: 'system-camera',\n settings,\n luminance,\n })\n return\n }\n const detection = await scanSystemCameraStill(frame, {\n modelUrl,\n ortWasmPaths,\n })\n if (detection.status !== 'success' || !detection.corners || !detection.quad) {\n captureErrorRef.current = true\n setPhase('error')\n setError(detection.message)\n callbacksRef.current.onError?.(new Error(detection.message))\n return\n }\n capturedDisplayRef.current = {\n quad: detection.quad,\n sourceWidth: detection.sourceWidth,\n sourceHeight: detection.sourceHeight,\n }\n if (detection.quad) setDisplayQuad(detection.quad)\n setPhase('captured')\n const nextCapture = {\n frame,\n detection,\n reason: 'manual' as const,\n method: 'system-camera' as const,\n settings,\n luminance,\n displayedQuad: detection.quad,\n displaySourceWidth: detection.sourceWidth,\n displaySourceHeight: detection.sourceHeight,\n }\n if (callbacksRef.current.useCase === 'drivers-license') {\n await handleLicenseStillRef.current(nextCapture)\n return\n }\n await invokeIfFunction(callbacksRef.current.onCapture, nextCapture)\n } catch (cause) {\n const nextError = cause instanceof Error ? cause : new Error('Could not take a photo.')\n if (nextError.message === 'No photo was selected.') {\n if (frozenPreviewUrlRef.current) {\n setPhase('error')\n return\n }\n callbacksRef.current.onCancel()\n return\n }\n captureErrorRef.current = true\n setError(nextError.message)\n setPhase('error')\n callbacksRef.current.onError?.(nextError)\n } finally {\n systemCaptureInFlightRef.current = false\n }\n }, [freezePreview, modelUrl, ortWasmPaths])\n\n const handleLicenseStill = useCallback(async (capture: ScannerCapture) => {\n const session = await licenseReadyRef.current\n if (!session) return\n setLicenseBusy(true)\n try {\n const step = await session.submitStill(capture.frame, capture.detection)\n if (step.kind === 'need-back') {\n licenseSideRef.current = 'back'\n licenseBackLockRef.current = false\n setLicenseSide('back')\n captureErrorRef.current = false\n setError('')\n setFinderStatus(undefined)\n setDisplayQuad(undefined)\n displaySmootherRef.current.clear()\n clearFrozenPreview()\n if (usingSystemCamera) {\n setPhase('ready')\n return\n }\n if (preview?.paused) void preview.play()\n setPhase('starting')\n setAttempt((value) => value + 1)\n return\n }\n if (step.kind === 'retry') {\n captureErrorRef.current = true\n setError(step.message)\n setPhase('error')\n return\n }\n await invokeIfFunction(callbacksRef.current.onDriverLicense, step.result)\n } catch (cause) {\n const nextError = cause instanceof Error ? cause : new Error('Driver’s license scan failed.')\n captureErrorRef.current = true\n setError(nextError.message)\n setPhase('error')\n callbacksRef.current.onError?.(nextError)\n } finally {\n setLicenseBusy(false)\n }\n }, [clearFrozenPreview, preview, usingSystemCamera])\n\n useLayoutEffect(() => {\n handleLicenseStillRef.current = handleLicenseStill\n }, [handleLicenseStill])\n\n const capture = useCallback(async () => {\n if (usingSystemCamera) {\n await captureSystemStill()\n return\n }\n const liveCamera = cameraRef.current\n if (\n liveCamera\n && callbacksRef.current.useCase === 'drivers-license'\n && licenseSideRef.current === 'back'\n ) {\n try {\n const photo = await liveCamera.capturePhoto()\n const decoded = await decodePdf417(photo.frame)\n if (!decoded?.text) return\n if (licenseBackLockRef.current) return\n licenseBackLockRef.current = true\n barcodeAbortRef.current?.abort()\n latestPhotoRef.current = photo\n setCaptureMethod(photo.method)\n setShutterDiagnostics(photo.diagnostics)\n setDiagnostics(photo.diagnostics)\n freezePreview(photo.frame, preview)\n setPhase('captured')\n await handleLicenseStillRef.current({\n frame: photo.frame,\n reason: 'manual',\n method: photo.method,\n settings: photo.settings,\n fallbackReason: photo.fallbackReason,\n luminance: photo.luminance,\n diagnostics: photo.diagnostics,\n })\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 callbacksRef.current.onError?.(nextError)\n }\n return\n }\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 callbacksRef.current.onError?.(nextError)\n }\n }, [captureSystemStill, freezePreview, preview, usingSystemCamera])\n\n const captureSystemStillRef = useRef(captureSystemStill)\n captureSystemStillRef.current = captureSystemStill\n const openedSystemSessionRef = useRef(false)\n\n useLayoutEffect(() => {\n if (!open || !usingSystemCamera) {\n openedSystemSessionRef.current = false\n return\n }\n if (openedSystemSessionRef.current) return\n openedSystemSessionRef.current = true\n captureErrorRef.current = false\n setError('')\n setFinderStatus(undefined)\n setCaptureMethod(undefined)\n setShutterDiagnostics(undefined)\n setCopyState('idle')\n setDisplayQuad(undefined)\n displaySmootherRef.current.clear()\n clearFrozenPreview()\n if (!hasTransientUserActivation()) {\n setPhase('ready')\n return\n }\n void captureSystemStillRef.current()\n }, [open, usingSystemCamera, clearFrozenPreview])\n\n const retry = useCallback(() => {\n captureErrorRef.current = false\n licenseBackLockRef.current = false\n setError('')\n setShutterDiagnostics(undefined)\n setCopyState('idle')\n setFinderStatus(undefined)\n setDisplayQuad(undefined)\n displaySmootherRef.current.clear()\n if (usingSystemCamera) {\n void captureSystemStill()\n return\n }\n clearFrozenPreview()\n if (useCase === 'drivers-license') {\n setPhase('starting')\n setAttempt((value) => value + 1)\n return\n }\n const liveCamera = cameraRef.current\n if (preview?.paused) void preview.play()\n setPhase(liveCamera ? 'ready' : 'starting')\n if (!liveCamera) setAttempt((value) => value + 1)\n }, [captureSystemStill, clearFrozenPreview, preview, useCase, usingSystemCamera])\n\n const setTorch = useCallback(async (enabled: boolean) => {\n const camera = cameraRef.current\n if (!camera) return\n await camera.setTorch(enabled)\n setDiagnostics(camera.getDiagnostics())\n }, [])\n\n const setAutoCapture = useCallback((enabled: boolean) => {\n finderRef.current?.setAutoCapture(enabled)\n }, [])\n\n const copyReport = useCallback(async () => {\n const current = stateRef.current\n const live = cameraRef.current?.getDiagnostics() ?? current.diagnostics\n const finder = current.finderStatus\n const report = formatCaptureDiagnosticsReport({\n error: current.error || undefined,\n captureMethod: current.captureMethod,\n luminance: latestPhotoRef.current?.luminance,\n fallbackReason: latestPhotoRef.current?.fallbackReason,\n shutter: current.shutterDiagnostics ?? latestPhotoRef.current?.diagnostics,\n live,\n finder: finder\n ? {\n state: finder.state,\n confidence: finder.confidence,\n stableFrames: finder.stableFrames,\n requiredStableFrames: finder.requiredStableFrames,\n detector: finder.detector,\n modelStatus: finder.modelStatus,\n modelError: finder.modelError,\n modelProvider: finder.modelProvider,\n modelNote: finder.modelNote,\n inferenceMs: finder.inferenceMs,\n sourceWidth: finder.sourceWidth,\n sourceHeight: finder.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\n const getState = useCallback(() => stateRef.current, [])\n\n const api = useMemo<ScannerApi>(() => ({\n capture,\n cancel,\n retry,\n setTorch,\n setAutoCapture,\n copyReport,\n getState,\n }), [capture, cancel, retry, setTorch, setAutoCapture, copyReport, getState])\n\n useEffect(() => {\n if (!apiRef) return\n apiRef.current = api\n return () => {\n apiRef.current = null\n }\n }, [api, apiRef])\n\n const value: ScannerContextValue = {\n ...state,\n ...api,\n bindPreview,\n }\n\n return (\n <ScannerContext.Provider value={value}>\n {children}\n </ScannerContext.Provider>\n )\n}\n","import { useContext, useRef } from 'react'\nimport type { ScannerApi } from './types'\nimport { ScannerContext } from './scanner-context'\n\nexport function useScannerRef() {\n return useRef<ScannerApi | null>(null)\n}\n\nexport function useScanner() {\n const value = useContext(ScannerContext)\n if (!value) throw new Error('useScanner must be used within ScannerProvider.')\n return value\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 type { ModelDownloadSnapshot } from '../sdk/model-download'\n\nexport function ModelDownloadRing({ snapshot }: { snapshot: ModelDownloadSnapshot }) {\n if (!snapshot.downloading) return null\n const ratio = snapshot.total && snapshot.total > 0\n ? Math.min(1, snapshot.loaded / snapshot.total)\n : null\n const percent = ratio === null ? null : Math.round(ratio * 100)\n const radius = 28\n const circumference = 2 * Math.PI * radius\n return (\n <div\n className={`model-download-ring${ratio === null ? ' is-indeterminate' : ''}`}\n role=\"progressbar\"\n aria-label=\"Model download\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={percent ?? undefined}\n data-loaded={snapshot.loaded}\n data-total={snapshot.total ?? ''}\n >\n <svg viewBox=\"0 0 72 72\" aria-hidden=\"true\">\n <circle className=\"track\" cx=\"36\" cy=\"36\" r={radius} />\n <circle\n className=\"value\"\n cx=\"36\"\n cy=\"36\"\n r={radius}\n strokeDasharray={ratio === null ? undefined : `${circumference} ${circumference}`}\n strokeDashoffset={ratio === null ? undefined : circumference * (1 - ratio)}\n />\n </svg>\n {percent !== null ? <strong>{percent}%</strong> : <strong className=\"model-download-ring__pending\">…</strong>}\n </div>\n )\n}\n","import { holdStillCountdownLabel, type FinderGuidanceReason } from '../sdk/finder'\nimport type { ScannerPhase } from './types'\n\nexport function overlayGuidanceText(input: {\n usingSystemCamera: boolean\n phase: ScannerPhase\n licenseBusy?: boolean\n holdStillSeconds?: number\n guidanceHint?: string\n guidanceReason?: FinderGuidanceReason\n licenseHeadline?: string\n}) {\n if (input.usingSystemCamera || input.licenseBusy) return undefined\n if (input.phase === 'error') return undefined\n if (input.phase === 'starting') return input.licenseHeadline\n if (input.phase === 'capturing') return 'Capturing full resolution…'\n if (input.phase === 'captured') return 'Document captured'\n if (input.holdStillSeconds && input.holdStillSeconds > 0) {\n return holdStillCountdownLabel(input.holdStillSeconds)\n }\n if (input.guidanceHint && input.guidanceReason && input.guidanceReason !== 'place-document') {\n return input.guidanceHint\n }\n return input.licenseHeadline ?? input.guidanceHint ?? 'Place the document in the frame'\n}\n","import { useCallback, useEffect, useRef, type CSSProperties } from 'react'\nimport { detectBrowserEngine } from '../sdk/camera'\nimport { liveOverlayTransform } from '../live-overlay-geometry'\nimport type { ModelDownloadSnapshot } from '../sdk/model-download'\nimport { ModelDownloadRing } from '../components/ModelDownloadRing'\nimport '../components/scanner-camera-overlay.css'\nimport { driverLicensePrompt } from '../sdk/driver-license'\nimport { overlayGuidanceText } from './guidance'\nimport { useScanner } from './hooks'\nimport type { ScannerFrameProps, ScannerTheme } from './types'\n\nconst themeProperties = {\n primaryColorHex: '--scanner-overlay-primary',\n seekingColorHex: '--scanner-overlay-seeking',\n detectingColorHex: '--scanner-overlay-detecting',\n unstableColorHex: '--scanner-overlay-unstable',\n readyColorHex: '--scanner-overlay-ready',\n capturedColorHex: '--scanner-overlay-captured',\n} as const\n\nfunction themeVars(theme: ScannerTheme | undefined) {\n if (!theme) return undefined\n const vars: Record<string, string> = {}\n for (const [field, property] of Object.entries(themeProperties)) {\n const color = theme[field as keyof ScannerTheme]?.trim()\n if (color) vars[property] = color\n }\n return Object.keys(vars).length > 0 ? vars : undefined\n}\n\nexport function ScannerFrame({ theme, style, title, children }: ScannerFrameProps) {\n const scanner = useScanner()\n if (!scanner.open) return null\n const frameTitle = title\n ?? (scanner.useCase === 'drivers-license' ? 'Scan a driver’s license' : 'Scan a document')\n const vars = themeVars(theme)\n const frameStyle: CSSProperties | undefined = vars ? { ...style, ...vars } : style\n return (\n <div\n className={`scanner-camera-overlay ${scanner.phase === 'captured' || scanner.finderStatus?.state === 'captured' ? 'is-captured' : ''} ${scanner.usingSystemCamera ? 'is-system-camera' : ''}`.trim()}\n style={frameStyle}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={frameTitle}\n >\n {children}\n <ScannerModelDownload />\n </div>\n )\n}\n\nexport function ScannerPreview() {\n const { bindPreview, frozenPreviewUrl, usingSystemCamera } = useScanner()\n const videoRef = useRef<HTMLVideoElement | null>(null)\n const setPreviewNode = useCallback((node: HTMLVideoElement | null) => {\n videoRef.current = node\n bindPreview(node)\n }, [bindPreview])\n\n useEffect(() => {\n if (frozenPreviewUrl) videoRef.current?.pause()\n }, [frozenPreviewUrl])\n\n if (usingSystemCamera) {\n return frozenPreviewUrl ? (\n <img\n src={frozenPreviewUrl}\n className=\"scanner-camera-overlay__video scanner-camera-overlay__still\"\n alt=\"\"\n aria-label=\"Captured document\"\n />\n ) : (\n <div className=\"scanner-camera-overlay__video\" aria-hidden=\"true\" />\n )\n }\n\n return (\n <>\n <video\n ref={setPreviewNode}\n className=\"scanner-camera-overlay__video\"\n muted\n autoPlay\n playsInline\n style={{ objectFit: 'cover' }}\n aria-hidden={Boolean(frozenPreviewUrl)}\n aria-label=\"Rear camera preview\"\n />\n {frozenPreviewUrl ? (\n <img\n src={frozenPreviewUrl}\n className=\"scanner-camera-overlay__video scanner-camera-overlay__still\"\n alt=\"\"\n aria-label=\"Captured document\"\n />\n ) : null}\n </>\n )\n}\n\nexport function ScannerQuad() {\n const { finderStatus, displayQuad, previewSize } = useScanner()\n if (!displayQuad || !finderStatus?.sourceWidth || !finderStatus.sourceHeight) {\n return null\n }\n const overlayTransform = liveOverlayTransform(\n finderStatus.sourceWidth,\n finderStatus.sourceHeight,\n previewSize.width,\n previewSize.height,\n 'cover',\n )\n return (\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\nexport function ScannerTopBar({ title }: { title?: string }) {\n const {\n phase,\n cancel,\n usingSystemCamera,\n useCase,\n licenseSide,\n licenseBusy,\n } = useScanner()\n const license = useCase === 'drivers-license'\n ? driverLicensePrompt(licenseSide ?? 'front', usingSystemCamera)\n : undefined\n const heading = title ?? license?.title ?? 'Scan a document'\n return (\n <div className=\"scanner-camera-overlay__topbar\">\n <div>\n <strong>{heading}</strong>\n <span aria-live=\"polite\">\n {licenseBusy && (licenseSide === 'back' ? 'Reading the barcode…' : 'Reading the front…')}\n {!licenseBusy && license && phase === 'error' && (\n licenseSide === 'back' ? 'Could not read the back' : 'Could not read the front'\n )}\n {!licenseBusy && !license && usingSystemCamera && (\n <>\n {phase === 'starting' && 'Preparing the system camera…'}\n {phase === 'ready' && 'Take a photo. There is no live document guide.'}\n {phase === 'capturing' && 'Looking for a document…'}\n {phase === 'captured' && 'Document captured'}\n {phase === 'error' && 'No document found'}\n </>\n )}\n {!licenseBusy && !license && !usingSystemCamera && phase === 'error' && 'Camera unavailable'}\n </span>\n </div>\n <button type=\"button\" onClick={cancel} aria-label=\"Close camera\">×</button>\n </div>\n )\n}\n\nexport function ScannerNotice() {\n const {\n phase,\n error,\n diagnostics,\n copyState,\n retry,\n copyReport,\n cancel,\n usingSystemCamera,\n frozenPreviewUrl,\n useCase,\n licenseSide,\n licenseBusy,\n } = useScanner()\n const license = useCase === 'drivers-license'\n ? driverLicensePrompt(licenseSide ?? 'front', usingSystemCamera)\n : undefined\n if (phase === 'error') {\n const title = license\n ? (licenseSide === 'back' ? 'Could not read the back' : 'Could not read the front')\n : usingSystemCamera\n ? frozenPreviewUrl ? 'No document found' : 'Could not take a photo'\n : diagnostics ? 'Capture failed' : 'Could not open the camera'\n return (\n <div className=\"scanner-camera-overlay__message\" role=\"alert\">\n <strong>{title}</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={cancel}>Cancel</button>\n </div>\n </div>\n )\n }\n if (licenseBusy) {\n return (\n <div className=\"scanner-camera-overlay__message\" aria-live=\"polite\">\n <span className=\"scanner-camera-overlay__spinner\" />\n <strong>{licenseSide === 'back' ? 'Reading the barcode' : 'Reading the front'}</strong>\n <p>{licenseSide === 'back' ? 'Decoding the AAMVA PDF417 on the back.' : 'Finding the card and reading the front with OCR.'}</p>\n </div>\n )\n }\n if (usingSystemCamera && phase === 'capturing' && !frozenPreviewUrl) {\n return (\n <div className=\"scanner-camera-overlay__message\" aria-live=\"polite\">\n <span className=\"scanner-camera-overlay__spinner\" />\n <strong>{license ? license.headline : 'Opening the system camera'}</strong>\n <p>{license ? license.detail : 'There is no live document guide. We find the page after you take the photo.'}</p>\n </div>\n )\n }\n if (usingSystemCamera && phase === 'ready' && !frozenPreviewUrl) {\n return (\n <div className=\"scanner-camera-overlay__message\" aria-live=\"polite\">\n <strong>{license ? license.headline : 'System camera'}</strong>\n <p>{license ? license.detail : 'Tap the shutter to open the Camera app. There is no live document guide.'}</p>\n </div>\n )\n }\n if (phase === 'starting' && !usingSystemCamera) {\n return (\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 )\n }\n return null\n}\n\nexport function ScannerStatus() {\n const {\n finderStatus,\n detectorStatus,\n settings,\n usingSystemCamera,\n captureMethod,\n phase,\n useCase,\n licenseSide,\n } = useScanner()\n const width = settings?.width\n const height = settings?.height\n const licenseLabel = useCase === 'drivers-license'\n ? ` · ${licenseSide === 'back' ? 'back' : 'front'}`\n : ''\n if (usingSystemCamera) {\n return (\n <div className=\"scanner-camera-overlay__status\" aria-live=\"polite\">\n <div className=\"scanner-camera-overlay__status-line\">\n <span className={phase === 'captured' ? 'ready' : phase === 'error' ? 'seeking' : 'detecting'} />\n {captureMethod === 'system-camera' ? 'system camera' : 'system camera · waiting'}\n {licenseLabel}\n {width && height ? ` · ${width}×${height}` : ''}\n </div>\n </div>\n )\n }\n const liveBarcode = useCase === 'drivers-license' && licenseSide === 'back'\n const stateLabel = liveBarcode && !finderStatus\n ? 'reading'\n : (finderStatus?.state ?? 'detecting')\n return (\n <div className=\"scanner-camera-overlay__status\" aria-live=\"polite\">\n <div className=\"scanner-camera-overlay__status-line\">\n <span className={liveBarcode && !finderStatus ? 'detecting' : (finderStatus?.state ?? 'detecting')} />\n {stateLabel}\n {licenseLabel}\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 </div>\n )\n}\n\nexport function ScannerDiagnostics() {\n const {\n diagnostics,\n shutterDiagnostics,\n captureMethod,\n copyState,\n copyReport,\n } = useScanner()\n const engine = diagnostics?.engine ?? detectBrowserEngine()\n return (\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 {diagnostics\n ? `${diagnostics.videoWidth}×${diagnostics.videoHeight} rs${diagnostics.readyState}${diagnostics.paused ? ' paused' : ''}${diagnostics.rendered ? '' : ' hidden'}`\n : 'starting'}\n </dd>\n </div>\n <div>\n <dt>track</dt>\n <dd>\n {diagnostics\n ? `${diagnostics.trackReadyState}${diagnostics.trackMuted ? ' muted' : ''}${diagnostics.trackEnabled ? '' : ' disabled'}`\n : '—'}\n </dd>\n </div>\n <div>\n <dt>torch</dt>\n <dd>\n {diagnostics\n ? `${diagnostics.torch.mode} · ${diagnostics.torch.supported ? (diagnostics.torch.on ? 'on' : 'off') : 'unsupported'}`\n : 'starting'}\n </dd>\n </div>\n <div>\n <dt>luma</dt>\n <dd>\n {diagnostics\n ? `live ${diagnostics.liveLuminance.toFixed(1)} · mirror ${diagnostics.mirrorLuminance.toFixed(1)}${Number.isFinite(diagnostics.mirrorAgeMs) ? ` (${Math.round(diagnostics.mirrorAgeMs)}ms)` : ' (none)'}`\n : '—'}\n </dd>\n </div>\n <div>\n <dt>path</dt>\n <dd>{captureMethod ?? 'video-frame / live-mirror'}</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}\n\nexport function ScannerControls() {\n const {\n autoCapture,\n phase,\n finderStatus,\n diagnostics,\n captureMethod,\n settings,\n cancel,\n capture,\n setAutoCapture,\n setTorch,\n usingSystemCamera,\n licenseBusy,\n useCase,\n licenseSide,\n guidanceHint,\n } = useScanner()\n const width = settings?.width\n const height = settings?.height\n const showShutter = usingSystemCamera\n ? phase === 'ready'\n : autoCapture !== 'only'\n const license = useCase === 'drivers-license'\n ? driverLicensePrompt(licenseSide ?? 'front', usingSystemCamera)\n : undefined\n const guidance = overlayGuidanceText({\n usingSystemCamera,\n phase,\n licenseBusy,\n holdStillSeconds: finderStatus?.holdStillSeconds,\n guidanceHint,\n guidanceReason: finderStatus?.guidance.reason,\n licenseHeadline: license?.headline,\n })\n const holdStill = Boolean(finderStatus?.holdStillSeconds)\n return (\n <div className=\"scanner-camera-overlay__controls\">\n <button type=\"button\" className=\"scanner-camera-overlay__cancel\" onClick={cancel}>Cancel</button>\n <div className=\"scanner-camera-overlay__capture\">\n {guidance && (\n <p\n className={`scanner-camera-overlay__guidance${holdStill ? ' is-ready' : ''}`}\n aria-live=\"polite\"\n >\n {guidance}\n </p>\n )}\n {showShutter && (\n <button\n type=\"button\"\n className=\"scanner-camera-overlay__shutter\"\n onClick={() => void capture()}\n disabled={phase !== 'ready' || Boolean(licenseBusy)}\n aria-label={usingSystemCamera ? 'Take a photo with the system camera' : 'Capture full-resolution photo'}\n >\n <span />\n </button>\n )}\n {!usingSystemCamera && (\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) => 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 )}\n </div>\n <div className=\"scanner-camera-overlay__quality\">\n <span>{usingSystemCamera ? 'System camera' : captureMethod === 'live-mirror' ? 'Mirror' : 'Camera'}</span>\n <strong>{width && height ? `${width} × ${height}` : usingSystemCamera ? 'Tap to photograph' : 'Measuring…'}</strong>\n </div>\n </div>\n )\n}\n\nexport function ScannerModelDownload({ snapshot }: { snapshot?: ModelDownloadSnapshot }) {\n const { modelDownload } = useScanner()\n return <ModelDownloadRing snapshot={snapshot ?? modelDownload} />\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"react.js","names":[],"sources":["../src/sdk/display-quad.ts","../src/react/scanner-context.ts","../src/react/context.tsx","../src/react/hooks.ts","../src/live-overlay-geometry.ts","../src/components/ModelDownloadRing.tsx","../src/react/guidance.ts","../src/react/parts.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 { createContext } from 'react'\nimport type { ScannerApi, ScannerState } from './types'\n\nexport interface ScannerContextValue extends ScannerState, ScannerApi {\n bindPreview: (node: HTMLVideoElement | null) => void\n}\n\nexport const ScannerContext = createContext<ScannerContextValue | null>(null)\n","import {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport {\n detectBrowserEngine,\n formatCaptureDiagnosticsReport,\n hasTransientUserActivation,\n meanFrameLuminance,\n NEAR_BLACK_LUMINANCE,\n pickNativeCameraStill,\n shouldUseImageCapture,\n shouldUseSystemCameraCapture,\n startCamera,\n type CameraDiagnostics,\n type CameraPhoto,\n type CameraSession,\n} from '../sdk/camera'\nimport {\n selectFinderHint,\n startFinder,\n type FinderSession,\n type FinderStatus,\n} from '../sdk/finder'\nimport { decodePdf417, PDF417_LIVE_MAX_EDGE } from '../sdk/barcode'\nimport { scanSystemCameraStill } from '../sdk/scan'\nimport {\n LICENSE_BACK_HIT_MS,\n LICENSE_BACK_POLL_MS,\n startDriverLicenseSession,\n waitForPdf417Frame,\n waitLicenseFlipCue,\n type DriverLicenseSession,\n} from '../sdk/driver-license'\nimport { QuadDisplaySmoother } from '../sdk/display-quad'\nimport {\n subscribeModelDownloads,\n type ModelDownloadSnapshot,\n} from '../sdk/model-download'\nimport type { DocumentQuad } from '../sdk/types'\nimport type { ScannerApi, ScannerCapture, ScannerProviderProps, ScannerState } from './types'\nimport { ScannerContext, type ScannerContextValue } from './scanner-context'\n\nfunction revokePreviewUrl(url: string | undefined) {\n if (url?.startsWith('blob:')) URL.revokeObjectURL(url)\n}\n\nfunction yieldPaint() {\n return new Promise<void>((resolve) => {\n if (typeof requestAnimationFrame === 'function') {\n requestAnimationFrame(() => requestAnimationFrame(() => resolve()))\n return\n }\n setTimeout(resolve, 0)\n })\n}\n\nfunction stillUrlFromCanvas(canvas: HTMLCanvasElement): string | undefined {\n try {\n const url = canvas.toDataURL('image/jpeg', 0.92)\n return url.startsWith('data:image/') ? url : undefined\n } catch {\n return undefined\n }\n}\n\nfunction invokeIfFunction<T>(\n fn: ((value: T) => void | Promise<void>) | undefined,\n value: T,\n) {\n if (typeof fn === 'function') return fn(value)\n}\n\nexport function ScannerProvider({\n open,\n useCase = 'document',\n autoCapture = 'defaultOn',\n captureMode = 'auto',\n torch = 'defaultOff',\n onCapture,\n onDriverLicense,\n onCancel,\n onError,\n onSettings,\n onFinderStatus,\n modelUrl,\n ortWasmPaths,\n detectionIntervalMs,\n apiRef,\n children,\n}: ScannerProviderProps) {\n const usingSystemCamera = shouldUseSystemCameraCapture(captureMode)\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 const captureErrorRef = useRef(false)\n const systemCaptureInFlightRef = useRef(false)\n const callbacksRef = useRef({\n onCapture,\n onDriverLicense,\n onCancel,\n onError,\n onSettings,\n onFinderStatus,\n useCase,\n })\n const licenseSessionRef = useRef<DriverLicenseSession | undefined>(undefined)\n const licenseReadyRef = useRef<Promise<DriverLicenseSession> | undefined>(undefined)\n const handleLicenseStillRef = useRef<(capture: ScannerCapture) => Promise<void>>(async () => undefined)\n const licenseBackLockRef = useRef(false)\n const barcodeAbortRef = useRef<AbortController | undefined>(undefined)\n const licenseFlipAbortRef = useRef<AbortController | undefined>(undefined)\n const stateRef = useRef<ScannerState>(null!)\n const [preview, setPreview] = useState<HTMLVideoElement | null>(null)\n const [phase, setPhase] = useState<ScannerState['phase']>(\n usingSystemCamera && open ? 'capturing' : usingSystemCamera ? 'ready' : 'starting',\n )\n const [finderStatus, setFinderStatus] = useState<FinderStatus>()\n const [displayQuad, setDisplayQuad] = useState<DocumentQuad>()\n const [barcodeOverlay, setBarcodeOverlay] = useState<{ width: number, height: number }>()\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<ScannerState['copyState']>('idle')\n const [frozenPreviewUrl, setFrozenPreviewUrl] = useState<string>()\n const frozenPreviewUrlRef = useRef<string | undefined>(undefined)\n const [licenseSide, setLicenseSide] = useState<'front' | 'back' | 'flip'>('front')\n const licenseSideRef = useRef<'front' | 'back'>('front')\n const [licenseBusy, setLicenseBusy] = useState(false)\n const [modelDownload, setModelDownload] = useState<ModelDownloadSnapshot>({\n downloading: false,\n loaded: 0,\n total: null,\n })\n\n const clearFrozenPreview = useCallback(() => {\n revokePreviewUrl(frozenPreviewUrlRef.current)\n frozenPreviewUrlRef.current = undefined\n setFrozenPreviewUrl(undefined)\n }, [])\n\n const freezePreview = useCallback((frame: HTMLCanvasElement, video?: HTMLVideoElement | null) => {\n const still = stillUrlFromCanvas(frame)\n revokePreviewUrl(frozenPreviewUrlRef.current)\n frozenPreviewUrlRef.current = still\n setFrozenPreviewUrl(still)\n video?.pause()\n }, [])\n\n const revealBarcodeHit = useCallback(async (\n frame: HTMLCanvasElement,\n quad: DocumentQuad | undefined,\n ) => {\n if (!quad) return\n setBarcodeOverlay({ width: frame.width, height: frame.height })\n setDisplayQuad(quad)\n await yieldPaint()\n await new Promise<void>((resolve) => {\n window.setTimeout(resolve, LICENSE_BACK_HIT_MS)\n })\n }, [])\n\n useLayoutEffect(() => {\n callbacksRef.current = {\n onCapture,\n onDriverLicense,\n onCancel,\n onError,\n onSettings,\n onFinderStatus,\n useCase,\n }\n }, [onCapture, onDriverLicense, onCancel, onError, onSettings, onFinderStatus, useCase])\n\n useEffect(() => subscribeModelDownloads(setModelDownload), [])\n\n useEffect(() => {\n if (!open || useCase !== 'drivers-license') {\n licenseFlipAbortRef.current?.abort()\n licenseFlipAbortRef.current = undefined\n licenseReadyRef.current = undefined\n licenseSessionRef.current = undefined\n licenseBackLockRef.current = false\n licenseSideRef.current = 'front'\n setLicenseSide('front')\n setLicenseBusy(false)\n return\n }\n const sessionPromise = startDriverLicenseSession({\n scan: { modelUrl, ortWasmPaths },\n })\n licenseReadyRef.current = sessionPromise\n void sessionPromise.then((session) => {\n licenseSessionRef.current = session\n })\n return () => {\n licenseFlipAbortRef.current?.abort()\n licenseFlipAbortRef.current = undefined\n void sessionPromise.then((session) => session.cancel())\n if (licenseSessionRef.current) licenseSessionRef.current = undefined\n licenseReadyRef.current = undefined\n }\n }, [open, useCase, modelUrl, ortWasmPaths])\n\n const bindPreview = useCallback((node: HTMLVideoElement | null) => {\n setPreview(node)\n }, [])\n\n useEffect(() => {\n if (!open || !preview) return\n const updateSize = () => {\n const bounds = preview.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(preview)\n return () => observer.disconnect()\n }, [open, preview])\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 || usingSystemCamera) return\n if (!preview) return\n let cancelled = false\n let barcodeAbort = new AbortController()\n barcodeAbortRef.current = barcodeAbort\n\n const stop = () => {\n barcodeAbort.abort()\n if (barcodeAbortRef.current === barcodeAbort) barcodeAbortRef.current = undefined\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 clearFrozenPreview()\n }\n\n const start = async () => {\n stop()\n barcodeAbort = new AbortController()\n barcodeAbortRef.current = barcodeAbort\n captureErrorRef.current = false\n setPhase('starting')\n setError('')\n setFinderStatus(undefined)\n setCaptureMethod(undefined)\n setShutterDiagnostics(undefined)\n setCopyState('idle')\n clearFrozenPreview()\n try {\n const camera = await startCamera(preview, { 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('[ScannerProvider] camera settings', actualSettings)\n const licenseBack = callbacksRef.current.useCase === 'drivers-license'\n && licenseSideRef.current === 'back'\n if (licenseBack) {\n setFinderStatus(undefined)\n setDisplayQuad(undefined)\n setBarcodeOverlay(undefined)\n displaySmootherRef.current.clear()\n setPhase('ready')\n void (async () => {\n try {\n let photoTick = 0\n const hit = await waitForPdf417Frame(\n async () => {\n photoTick += 1\n const engine = detectBrowserEngine()\n if (\n photoTick % 4 === 0\n && shouldUseImageCapture(engine, 'ImageCapture' in globalThis)\n ) {\n try {\n const photo = await camera.capturePhoto()\n if (photo.frame && photo.luminance > NEAR_BLACK_LUMINANCE) return photo.frame\n } catch {\n // Live frame / mirror next.\n }\n }\n try {\n return await camera.captureLiveFrame(PDF417_LIVE_MAX_EDGE)\n } catch {\n // Video not ready; poll again.\n return undefined\n }\n },\n { intervalMs: detectionIntervalMs ?? LICENSE_BACK_POLL_MS, signal: barcodeAbort.signal },\n )\n if (cancelled || barcodeAbort.signal.aborted || licenseBackLockRef.current) return\n licenseBackLockRef.current = true\n freezePreview(hit.frame, preview)\n setCaptureMethod('live-mirror')\n setPhase('captured')\n await revealBarcodeHit(hit.frame, hit.quad)\n if (cancelled || barcodeAbort.signal.aborted) return\n await handleLicenseStillRef.current({\n frame: hit.frame,\n reason: 'auto',\n method: 'live-mirror',\n settings: camera.getSettings(),\n })\n } catch (cause) {\n if (cancelled || barcodeAbort.signal.aborted) return\n if (cause instanceof DOMException && cause.name === 'AbortError') return\n const nextError = cause instanceof Error ? cause : new Error('Could not read the barcode.')\n captureErrorRef.current = true\n setError(nextError.message)\n setPhase('error')\n callbacksRef.current.onError?.(nextError)\n }\n })()\n return\n }\n finderRef.current = await startFinder({\n source: preview,\n autoCapture,\n intervalMs: detectionIntervalMs,\n detection: {\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 freezePreview(photo.frame, preview)\n setPhase('captured')\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 await new Promise((resolve) => window.setTimeout(resolve, 140))\n const nextCapture = {\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 if (callbacksRef.current.useCase === 'drivers-license') {\n await handleLicenseStillRef.current(nextCapture)\n return\n }\n await invokeIfFunction(callbacksRef.current.onCapture, nextCapture)\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 preview,\n usingSystemCamera,\n autoCapture,\n torch,\n modelUrl,\n ortWasmPaths,\n detectionIntervalMs,\n attempt,\n clearFrozenPreview,\n freezePreview,\n revealBarcodeHit,\n ])\n\n const guidanceHint = finderStatus\n ? selectFinderHint(finderStatus.guidance, finderStatus.lighting)\n : undefined\n const licenseBackLive = useCase === 'drivers-license'\n && licenseSide === 'back'\n && !usingSystemCamera\n const detectorStatus = licenseBackLive\n ? 'zxing'\n : finderStatus?.modelStatus === 'failed'\n ? `ML failed${finderStatus.modelError ? `: ${finderStatus.modelError}` : ''}`\n : finderStatus?.detector === 'ml'\n ? `ML ${finderStatus.modelProvider ?? ''}`.trim()\n : 'ML loading'\n const state: ScannerState = {\n open,\n phase,\n autoCapture,\n captureMode,\n usingSystemCamera,\n finderStatus,\n displayQuad,\n barcodeOverlay,\n previewSize,\n settings,\n captureMethod,\n error,\n diagnostics,\n shutterDiagnostics,\n copyState,\n guidanceHint,\n detectorStatus,\n modelDownload,\n frozenPreviewUrl,\n useCase,\n licenseSide: useCase === 'drivers-license' ? licenseSide : undefined,\n licenseBusy: useCase === 'drivers-license' ? licenseBusy : undefined,\n }\n useEffect(() => {\n stateRef.current = state\n })\n\n const cancel = useCallback(() => {\n callbacksRef.current.onCancel()\n }, [])\n\n const captureSystemStill = useCallback(async () => {\n if (systemCaptureInFlightRef.current) return\n systemCaptureInFlightRef.current = true\n captureErrorRef.current = false\n setError('')\n setDisplayQuad(undefined)\n setBarcodeOverlay(undefined)\n displaySmootherRef.current.clear()\n setPhase('capturing')\n try {\n const frame = await pickNativeCameraStill()\n freezePreview(frame)\n const settings = {\n width: frame.width,\n height: frame.height,\n } satisfies MediaTrackSettings\n setSettings(settings)\n callbacksRef.current.onSettings?.(settings)\n setCaptureMethod('system-camera')\n let luminance: number | undefined\n try {\n const pixels = frame.getContext('2d', { willReadFrequently: true })\n ?.getImageData(0, 0, frame.width, frame.height).data\n if (pixels) luminance = meanFrameLuminance(pixels)\n } catch {\n luminance = undefined\n }\n const licenseBack = callbacksRef.current.useCase === 'drivers-license'\n && licenseSideRef.current === 'back'\n if (licenseBack) {\n setDisplayQuad(undefined)\n setBarcodeOverlay(undefined)\n displaySmootherRef.current.clear()\n capturedDisplayRef.current = {}\n setPhase('captured')\n const decoded = await decodePdf417(frame)\n await revealBarcodeHit(frame, decoded?.quad)\n await handleLicenseStillRef.current({\n frame,\n reason: 'manual',\n method: 'system-camera',\n settings,\n luminance,\n })\n return\n }\n const detection = await scanSystemCameraStill(frame, {\n modelUrl,\n ortWasmPaths,\n })\n if (detection.status !== 'success' || !detection.corners || !detection.quad) {\n captureErrorRef.current = true\n setPhase('error')\n setError(detection.message)\n callbacksRef.current.onError?.(new Error(detection.message))\n return\n }\n capturedDisplayRef.current = {\n quad: detection.quad,\n sourceWidth: detection.sourceWidth,\n sourceHeight: detection.sourceHeight,\n }\n if (detection.quad) setDisplayQuad(detection.quad)\n setPhase('captured')\n const nextCapture = {\n frame,\n detection,\n reason: 'manual' as const,\n method: 'system-camera' as const,\n settings,\n luminance,\n displayedQuad: detection.quad,\n displaySourceWidth: detection.sourceWidth,\n displaySourceHeight: detection.sourceHeight,\n }\n if (callbacksRef.current.useCase === 'drivers-license') {\n await handleLicenseStillRef.current(nextCapture)\n return\n }\n await invokeIfFunction(callbacksRef.current.onCapture, nextCapture)\n } catch (cause) {\n const nextError = cause instanceof Error ? cause : new Error('Could not take a photo.')\n if (nextError.message === 'No photo was selected.') {\n if (frozenPreviewUrlRef.current) {\n setPhase('error')\n return\n }\n callbacksRef.current.onCancel()\n return\n }\n captureErrorRef.current = true\n setError(nextError.message)\n setPhase('error')\n callbacksRef.current.onError?.(nextError)\n } finally {\n systemCaptureInFlightRef.current = false\n }\n }, [freezePreview, modelUrl, ortWasmPaths, revealBarcodeHit])\n\n const handleLicenseStill = useCallback(async (capture: ScannerCapture) => {\n const session = await licenseReadyRef.current\n if (!session) return\n setLicenseBusy(true)\n try {\n const step = await session.submitStill(capture.frame, capture.detection)\n if (step.kind === 'need-back') {\n licenseFlipAbortRef.current?.abort()\n const flipAbort = new AbortController()\n licenseFlipAbortRef.current = flipAbort\n finderRef.current?.stop()\n finderRef.current = undefined\n licenseSideRef.current = 'front'\n licenseBackLockRef.current = false\n setLicenseSide('flip')\n captureErrorRef.current = false\n setError('')\n setFinderStatus(undefined)\n setDisplayQuad(undefined)\n setBarcodeOverlay(undefined)\n displaySmootherRef.current.clear()\n setPhase('ready')\n setLicenseBusy(false)\n try {\n await waitLicenseFlipCue(flipAbort.signal)\n } catch {\n return\n }\n if (licenseFlipAbortRef.current !== flipAbort || flipAbort.signal.aborted) return\n licenseFlipAbortRef.current = undefined\n licenseSideRef.current = 'back'\n setLicenseSide('back')\n clearFrozenPreview()\n if (usingSystemCamera) {\n setPhase('ready')\n return\n }\n if (preview?.paused) void preview.play()\n setPhase('starting')\n setAttempt((value) => value + 1)\n return\n }\n if (step.kind === 'retry') {\n captureErrorRef.current = true\n setError(step.message)\n setPhase('error')\n return\n }\n await invokeIfFunction(callbacksRef.current.onDriverLicense, step.result)\n } catch (cause) {\n const nextError = cause instanceof Error ? cause : new Error('Driver’s license scan failed.')\n captureErrorRef.current = true\n setError(nextError.message)\n setPhase('error')\n callbacksRef.current.onError?.(nextError)\n } finally {\n setLicenseBusy(false)\n }\n }, [clearFrozenPreview, preview, usingSystemCamera])\n\n useLayoutEffect(() => {\n handleLicenseStillRef.current = handleLicenseStill\n }, [handleLicenseStill])\n\n const capture = useCallback(async () => {\n if (usingSystemCamera) {\n await captureSystemStill()\n return\n }\n const liveCamera = cameraRef.current\n if (\n liveCamera\n && callbacksRef.current.useCase === 'drivers-license'\n && licenseSideRef.current === 'back'\n ) {\n try {\n const photo = await liveCamera.capturePhoto()\n const decoded = await decodePdf417(photo.frame)\n if (!decoded?.text) return\n if (licenseBackLockRef.current) return\n licenseBackLockRef.current = true\n barcodeAbortRef.current?.abort()\n latestPhotoRef.current = photo\n setCaptureMethod(photo.method)\n setShutterDiagnostics(photo.diagnostics)\n setDiagnostics(photo.diagnostics)\n freezePreview(photo.frame, preview)\n setPhase('captured')\n await revealBarcodeHit(photo.frame, decoded.quad)\n await handleLicenseStillRef.current({\n frame: photo.frame,\n reason: 'manual',\n method: photo.method,\n settings: photo.settings,\n fallbackReason: photo.fallbackReason,\n luminance: photo.luminance,\n diagnostics: photo.diagnostics,\n })\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 callbacksRef.current.onError?.(nextError)\n }\n return\n }\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 callbacksRef.current.onError?.(nextError)\n }\n }, [captureSystemStill, freezePreview, preview, revealBarcodeHit, usingSystemCamera])\n\n const captureSystemStillRef = useRef(captureSystemStill)\n captureSystemStillRef.current = captureSystemStill\n const openedSystemSessionRef = useRef(false)\n\n useLayoutEffect(() => {\n if (!open || !usingSystemCamera) {\n openedSystemSessionRef.current = false\n return\n }\n if (openedSystemSessionRef.current) return\n openedSystemSessionRef.current = true\n captureErrorRef.current = false\n setError('')\n setFinderStatus(undefined)\n setCaptureMethod(undefined)\n setShutterDiagnostics(undefined)\n setCopyState('idle')\n setDisplayQuad(undefined)\n setBarcodeOverlay(undefined)\n displaySmootherRef.current.clear()\n clearFrozenPreview()\n if (!hasTransientUserActivation()) {\n setPhase('ready')\n return\n }\n void captureSystemStillRef.current()\n }, [open, usingSystemCamera, clearFrozenPreview])\n\n const retry = useCallback(() => {\n captureErrorRef.current = false\n licenseBackLockRef.current = false\n setError('')\n setShutterDiagnostics(undefined)\n setCopyState('idle')\n setFinderStatus(undefined)\n setDisplayQuad(undefined)\n setBarcodeOverlay(undefined)\n displaySmootherRef.current.clear()\n if (usingSystemCamera) {\n void captureSystemStill()\n return\n }\n clearFrozenPreview()\n if (useCase === 'drivers-license') {\n setPhase('starting')\n setAttempt((value) => value + 1)\n return\n }\n const liveCamera = cameraRef.current\n if (preview?.paused) void preview.play()\n setPhase(liveCamera ? 'ready' : 'starting')\n if (!liveCamera) setAttempt((value) => value + 1)\n }, [captureSystemStill, clearFrozenPreview, preview, useCase, usingSystemCamera])\n\n const setTorch = useCallback(async (enabled: boolean) => {\n const camera = cameraRef.current\n if (!camera) return\n await camera.setTorch(enabled)\n setDiagnostics(camera.getDiagnostics())\n }, [])\n\n const setAutoCapture = useCallback((enabled: boolean) => {\n finderRef.current?.setAutoCapture(enabled)\n }, [])\n\n const copyReport = useCallback(async () => {\n const current = stateRef.current\n const live = cameraRef.current?.getDiagnostics() ?? current.diagnostics\n const finder = current.finderStatus\n const report = formatCaptureDiagnosticsReport({\n error: current.error || undefined,\n captureMethod: current.captureMethod,\n luminance: latestPhotoRef.current?.luminance,\n fallbackReason: latestPhotoRef.current?.fallbackReason,\n shutter: current.shutterDiagnostics ?? latestPhotoRef.current?.diagnostics,\n live,\n finder: finder\n ? {\n state: finder.state,\n confidence: finder.confidence,\n stableFrames: finder.stableFrames,\n requiredStableFrames: finder.requiredStableFrames,\n detector: finder.detector,\n modelStatus: finder.modelStatus,\n modelError: finder.modelError,\n modelProvider: finder.modelProvider,\n modelNote: finder.modelNote,\n inferenceMs: finder.inferenceMs,\n sourceWidth: finder.sourceWidth,\n sourceHeight: finder.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\n const getState = useCallback(() => stateRef.current, [])\n\n const api = useMemo<ScannerApi>(() => ({\n capture,\n cancel,\n retry,\n setTorch,\n setAutoCapture,\n copyReport,\n getState,\n }), [capture, cancel, retry, setTorch, setAutoCapture, copyReport, getState])\n\n useEffect(() => {\n if (!apiRef) return\n apiRef.current = api\n return () => {\n apiRef.current = null\n }\n }, [api, apiRef])\n\n const value: ScannerContextValue = {\n ...state,\n ...api,\n bindPreview,\n }\n\n return (\n <ScannerContext.Provider value={value}>\n {children}\n </ScannerContext.Provider>\n )\n}\n","import { useContext, useRef } from 'react'\nimport type { ScannerApi } from './types'\nimport { ScannerContext } from './scanner-context'\n\nexport function useScannerRef() {\n return useRef<ScannerApi | null>(null)\n}\n\nexport function useScanner() {\n const value = useContext(ScannerContext)\n if (!value) throw new Error('useScanner must be used within ScannerProvider.')\n return value\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 type { ModelDownloadSnapshot } from '../sdk/model-download'\n\nexport function ModelDownloadRing({ snapshot }: { snapshot: ModelDownloadSnapshot }) {\n if (!snapshot.downloading) return null\n const ratio = snapshot.total && snapshot.total > 0\n ? Math.min(1, snapshot.loaded / snapshot.total)\n : null\n const percent = ratio === null ? null : Math.round(ratio * 100)\n const radius = 28\n const circumference = 2 * Math.PI * radius\n return (\n <div\n className={`model-download-ring${ratio === null ? ' is-indeterminate' : ''}`}\n role=\"progressbar\"\n aria-label=\"Model download\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={percent ?? undefined}\n data-loaded={snapshot.loaded}\n data-total={snapshot.total ?? ''}\n >\n <svg viewBox=\"0 0 72 72\" aria-hidden=\"true\">\n <circle className=\"track\" cx=\"36\" cy=\"36\" r={radius} />\n <circle\n className=\"value\"\n cx=\"36\"\n cy=\"36\"\n r={radius}\n strokeDasharray={ratio === null ? undefined : `${circumference} ${circumference}`}\n strokeDashoffset={ratio === null ? undefined : circumference * (1 - ratio)}\n />\n </svg>\n {percent !== null ? <strong>{percent}%</strong> : <strong className=\"model-download-ring__pending\">…</strong>}\n </div>\n )\n}\n","import { holdStillCountdownLabel, type FinderGuidanceReason } from '../sdk/finder'\nimport type { ScannerPhase } from './types'\n\nexport function overlayGuidanceText(input: {\n usingSystemCamera: boolean\n phase: ScannerPhase\n licenseBusy?: boolean\n holdStillSeconds?: number\n guidanceHint?: string\n guidanceReason?: FinderGuidanceReason\n licenseHeadline?: string\n licenseFlipCue?: boolean\n}) {\n if (input.usingSystemCamera || input.licenseBusy) return undefined\n if (input.phase === 'error') return undefined\n if (input.licenseFlipCue) return input.licenseHeadline\n if (input.phase === 'starting') return input.licenseHeadline\n if (input.phase === 'capturing') return 'Capturing full resolution…'\n if (input.phase === 'captured') return 'Document captured'\n if (input.holdStillSeconds && input.holdStillSeconds > 0) {\n return holdStillCountdownLabel(input.holdStillSeconds)\n }\n if (input.guidanceHint && input.guidanceReason && input.guidanceReason !== 'place-document') {\n return input.guidanceHint\n }\n return input.licenseHeadline ?? input.guidanceHint ?? 'Place the document in the frame'\n}\n","import { useCallback, useEffect, useRef, type CSSProperties } from 'react'\nimport { detectBrowserEngine } from '../sdk/camera'\nimport { liveOverlayTransform } from '../live-overlay-geometry'\nimport type { ModelDownloadSnapshot } from '../sdk/model-download'\nimport { ModelDownloadRing } from '../components/ModelDownloadRing'\nimport '../components/scanner-camera-overlay.css'\nimport { driverLicensePrompt } from '../sdk/driver-license'\nimport { overlayGuidanceText } from './guidance'\nimport { useScanner } from './hooks'\nimport type { ScannerFrameProps, ScannerTheme } from './types'\n\nconst themeProperties = {\n primaryColorHex: '--scanner-overlay-primary',\n seekingColorHex: '--scanner-overlay-seeking',\n detectingColorHex: '--scanner-overlay-detecting',\n unstableColorHex: '--scanner-overlay-unstable',\n readyColorHex: '--scanner-overlay-ready',\n capturedColorHex: '--scanner-overlay-captured',\n} as const\n\nfunction themeVars(theme: ScannerTheme | undefined) {\n if (!theme) return undefined\n const vars: Record<string, string> = {}\n for (const [field, property] of Object.entries(themeProperties)) {\n const color = theme[field as keyof ScannerTheme]?.trim()\n if (color) vars[property] = color\n }\n return Object.keys(vars).length > 0 ? vars : undefined\n}\n\nexport function ScannerFrame({ theme, style, title, children }: ScannerFrameProps) {\n const scanner = useScanner()\n if (!scanner.open) return null\n const frameTitle = title\n ?? (scanner.useCase === 'drivers-license' ? 'Scan a driver’s license' : 'Scan a document')\n const vars = themeVars(theme)\n const frameStyle: CSSProperties | undefined = vars ? { ...style, ...vars } : style\n return (\n <div\n className={`scanner-camera-overlay ${scanner.phase === 'captured' || scanner.finderStatus?.state === 'captured' ? 'is-captured' : ''} ${scanner.usingSystemCamera ? 'is-system-camera' : ''}`.trim()}\n style={frameStyle}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={frameTitle}\n >\n {children}\n <ScannerModelDownload />\n </div>\n )\n}\n\nexport function ScannerPreview() {\n const { bindPreview, frozenPreviewUrl, usingSystemCamera } = useScanner()\n const videoRef = useRef<HTMLVideoElement | null>(null)\n const setPreviewNode = useCallback((node: HTMLVideoElement | null) => {\n videoRef.current = node\n bindPreview(node)\n }, [bindPreview])\n\n useEffect(() => {\n if (frozenPreviewUrl) videoRef.current?.pause()\n }, [frozenPreviewUrl])\n\n if (usingSystemCamera) {\n return frozenPreviewUrl ? (\n <img\n src={frozenPreviewUrl}\n className=\"scanner-camera-overlay__video scanner-camera-overlay__still\"\n alt=\"\"\n aria-label=\"Captured document\"\n />\n ) : (\n <div className=\"scanner-camera-overlay__video\" aria-hidden=\"true\" />\n )\n }\n\n return (\n <>\n <video\n ref={setPreviewNode}\n className=\"scanner-camera-overlay__video\"\n muted\n autoPlay\n playsInline\n style={{ objectFit: 'cover' }}\n aria-hidden={Boolean(frozenPreviewUrl)}\n aria-label=\"Rear camera preview\"\n />\n {frozenPreviewUrl ? (\n <img\n src={frozenPreviewUrl}\n className=\"scanner-camera-overlay__video scanner-camera-overlay__still\"\n alt=\"\"\n aria-label=\"Captured document\"\n />\n ) : null}\n </>\n )\n}\n\nexport function ScannerQuad() {\n const { finderStatus, displayQuad, previewSize, barcodeOverlay } = useScanner()\n const sourceWidth = finderStatus?.sourceWidth ?? barcodeOverlay?.width\n const sourceHeight = finderStatus?.sourceHeight ?? barcodeOverlay?.height\n if (!displayQuad || !sourceWidth || !sourceHeight) {\n return null\n }\n const overlayTransform = liveOverlayTransform(\n sourceWidth,\n sourceHeight,\n previewSize.width,\n previewSize.height,\n 'cover',\n )\n const state = barcodeOverlay ? 'ready' : finderStatus?.state\n return (\n <svg\n className={`scanner-camera-overlay__quad ${state ?? ''}`.trim()}\n viewBox={overlayTransform.viewBox}\n preserveAspectRatio={overlayTransform.preserveAspectRatio}\n aria-label={barcodeOverlay ? 'PDF417 barcode boundary' : `${finderStatus?.state ?? 'document'} 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\nexport function ScannerTopBar({ title }: { title?: string }) {\n const {\n phase,\n cancel,\n usingSystemCamera,\n useCase,\n licenseSide,\n licenseBusy,\n } = useScanner()\n const license = useCase === 'drivers-license'\n ? driverLicensePrompt(licenseSide ?? 'front', usingSystemCamera)\n : undefined\n const heading = title ?? license?.title ?? 'Scan a document'\n return (\n <div className=\"scanner-camera-overlay__topbar\">\n <div>\n <strong>{heading}</strong>\n <span aria-live=\"polite\">\n {licenseBusy && (licenseSide === 'back' ? 'Reading the barcode…' : 'Reading the front…')}\n {!licenseBusy && license && licenseSide === 'flip' && 'Turn the license over'}\n {!licenseBusy && license && phase === 'error' && (\n licenseSide === 'back' ? 'Could not read the back' : 'Could not read the front'\n )}\n {!licenseBusy && !license && usingSystemCamera && (\n <>\n {phase === 'starting' && 'Preparing the system camera…'}\n {phase === 'ready' && 'Take a photo. There is no live document guide.'}\n {phase === 'capturing' && 'Looking for a document…'}\n {phase === 'captured' && 'Document captured'}\n {phase === 'error' && 'No document found'}\n </>\n )}\n {!licenseBusy && !license && !usingSystemCamera && phase === 'error' && 'Camera unavailable'}\n </span>\n </div>\n <button type=\"button\" onClick={cancel} aria-label=\"Close camera\">×</button>\n </div>\n )\n}\n\nexport function ScannerNotice() {\n const {\n phase,\n error,\n diagnostics,\n copyState,\n retry,\n copyReport,\n cancel,\n usingSystemCamera,\n frozenPreviewUrl,\n useCase,\n licenseSide,\n licenseBusy,\n } = useScanner()\n const license = useCase === 'drivers-license'\n ? driverLicensePrompt(licenseSide ?? 'front', usingSystemCamera)\n : undefined\n if (licenseSide === 'flip' && license) {\n if (!usingSystemCamera) return null\n return (\n <div className=\"scanner-camera-overlay__message\" aria-live=\"polite\">\n <strong>{license.headline}</strong>\n <p>{license.detail}</p>\n </div>\n )\n }\n if (phase === 'error') {\n const title = license\n ? (licenseSide === 'back' ? 'Could not read the back' : 'Could not read the front')\n : usingSystemCamera\n ? frozenPreviewUrl ? 'No document found' : 'Could not take a photo'\n : diagnostics ? 'Capture failed' : 'Could not open the camera'\n return (\n <div className=\"scanner-camera-overlay__message\" role=\"alert\">\n <strong>{title}</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={cancel}>Cancel</button>\n </div>\n </div>\n )\n }\n if (licenseBusy) {\n return (\n <div className=\"scanner-camera-overlay__message\" aria-live=\"polite\">\n <span className=\"scanner-camera-overlay__spinner\" />\n <strong>{licenseSide === 'back' ? 'Reading the barcode' : 'Reading the front'}</strong>\n <p>{licenseSide === 'back' ? 'Decoding the AAMVA PDF417 on the back.' : 'Finding the card and reading the front with OCR.'}</p>\n </div>\n )\n }\n if (usingSystemCamera && phase === 'capturing' && !frozenPreviewUrl) {\n return (\n <div className=\"scanner-camera-overlay__message\" aria-live=\"polite\">\n <span className=\"scanner-camera-overlay__spinner\" />\n <strong>{license ? license.headline : 'Opening the system camera'}</strong>\n <p>{license ? license.detail : 'There is no live document guide. We find the page after you take the photo.'}</p>\n </div>\n )\n }\n if (usingSystemCamera && phase === 'ready' && !frozenPreviewUrl) {\n return (\n <div className=\"scanner-camera-overlay__message\" aria-live=\"polite\">\n <strong>{license ? license.headline : 'System camera'}</strong>\n <p>{license ? license.detail : 'Tap the shutter to open the Camera app. There is no live document guide.'}</p>\n </div>\n )\n }\n if (phase === 'starting' && !usingSystemCamera) {\n return (\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 )\n }\n return null\n}\n\nexport function ScannerStatus() {\n const {\n finderStatus,\n detectorStatus,\n settings,\n usingSystemCamera,\n captureMethod,\n phase,\n useCase,\n licenseSide,\n } = useScanner()\n const width = settings?.width\n const height = settings?.height\n const licenseLabel = useCase === 'drivers-license'\n ? ` · ${licenseSide === 'back' ? 'back' : licenseSide === 'flip' ? 'flip' : 'front'}`\n : ''\n if (usingSystemCamera) {\n return (\n <div className=\"scanner-camera-overlay__status\" aria-live=\"polite\">\n <div className=\"scanner-camera-overlay__status-line\">\n <span className={phase === 'captured' ? 'ready' : phase === 'error' ? 'seeking' : 'detecting'} />\n {captureMethod === 'system-camera' ? 'system camera' : 'system camera · waiting'}\n {licenseLabel}\n {width && height ? ` · ${width}×${height}` : ''}\n </div>\n </div>\n )\n }\n const liveBarcode = useCase === 'drivers-license' && licenseSide === 'back'\n const stateLabel = liveBarcode && !finderStatus\n ? 'reading'\n : (finderStatus?.state ?? 'detecting')\n return (\n <div className=\"scanner-camera-overlay__status\" aria-live=\"polite\">\n <div className=\"scanner-camera-overlay__status-line\">\n <span className={liveBarcode && !finderStatus ? 'detecting' : (finderStatus?.state ?? 'detecting')} />\n {stateLabel}\n {licenseLabel}\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 </div>\n )\n}\n\nexport function ScannerDiagnostics() {\n const {\n diagnostics,\n shutterDiagnostics,\n captureMethod,\n copyState,\n copyReport,\n } = useScanner()\n const engine = diagnostics?.engine ?? detectBrowserEngine()\n return (\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 {diagnostics\n ? `${diagnostics.videoWidth}×${diagnostics.videoHeight} rs${diagnostics.readyState}${diagnostics.paused ? ' paused' : ''}${diagnostics.rendered ? '' : ' hidden'}`\n : 'starting'}\n </dd>\n </div>\n <div>\n <dt>track</dt>\n <dd>\n {diagnostics\n ? `${diagnostics.trackReadyState}${diagnostics.trackMuted ? ' muted' : ''}${diagnostics.trackEnabled ? '' : ' disabled'}`\n : '—'}\n </dd>\n </div>\n <div>\n <dt>torch</dt>\n <dd>\n {diagnostics\n ? `${diagnostics.torch.mode} · ${diagnostics.torch.supported ? (diagnostics.torch.on ? 'on' : 'off') : 'unsupported'}`\n : 'starting'}\n </dd>\n </div>\n <div>\n <dt>luma</dt>\n <dd>\n {diagnostics\n ? `live ${diagnostics.liveLuminance.toFixed(1)} · mirror ${diagnostics.mirrorLuminance.toFixed(1)}${Number.isFinite(diagnostics.mirrorAgeMs) ? ` (${Math.round(diagnostics.mirrorAgeMs)}ms)` : ' (none)'}`\n : '—'}\n </dd>\n </div>\n <div>\n <dt>path</dt>\n <dd>{captureMethod ?? 'video-frame / live-mirror'}</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}\n\nexport function ScannerControls() {\n const {\n autoCapture,\n phase,\n finderStatus,\n diagnostics,\n captureMethod,\n settings,\n cancel,\n capture,\n setAutoCapture,\n setTorch,\n usingSystemCamera,\n licenseBusy,\n useCase,\n licenseSide,\n guidanceHint,\n } = useScanner()\n const width = settings?.width\n const height = settings?.height\n const showShutter = licenseSide !== 'flip' && (usingSystemCamera\n ? phase === 'ready'\n : autoCapture !== 'only')\n const license = useCase === 'drivers-license'\n ? driverLicensePrompt(licenseSide ?? 'front', usingSystemCamera)\n : undefined\n const guidance = overlayGuidanceText({\n usingSystemCamera,\n phase,\n licenseBusy,\n holdStillSeconds: finderStatus?.holdStillSeconds,\n guidanceHint,\n guidanceReason: finderStatus?.guidance.reason,\n licenseHeadline: license?.headline,\n licenseFlipCue: licenseSide === 'flip',\n })\n const holdStill = Boolean(finderStatus?.holdStillSeconds)\n return (\n <div className=\"scanner-camera-overlay__controls\">\n <button type=\"button\" className=\"scanner-camera-overlay__cancel\" onClick={cancel}>Cancel</button>\n <div className=\"scanner-camera-overlay__capture\">\n {guidance && (\n <p\n className={`scanner-camera-overlay__guidance${holdStill ? ' is-ready' : ''}`}\n aria-live=\"polite\"\n >\n {guidance}\n </p>\n )}\n {showShutter && (\n <button\n type=\"button\"\n className=\"scanner-camera-overlay__shutter\"\n onClick={() => void capture()}\n disabled={phase !== 'ready' || Boolean(licenseBusy)}\n aria-label={usingSystemCamera ? 'Take a photo with the system camera' : 'Capture full-resolution photo'}\n >\n <span />\n </button>\n )}\n {!usingSystemCamera && (\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) => 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 )}\n </div>\n <div className=\"scanner-camera-overlay__quality\">\n <span>{usingSystemCamera ? 'System camera' : captureMethod === 'live-mirror' ? 'Mirror' : 'Camera'}</span>\n <strong>{width && height ? `${width} × ${height}` : usingSystemCamera ? 'Tap to photograph' : 'Measuring…'}</strong>\n </div>\n </div>\n )\n}\n\nexport function ScannerModelDownload({ snapshot }: { snapshot?: ModelDownloadSnapshot }) {\n const { modelDownload } = useScanner()\n return <ModelDownloadRing snapshot={snapshot ?? modelDownload} />\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { $ as e, A as t, B as n, C as r, D as i, E as a, F as o, G as s, H as c, I as l, J as u, L as d, M as ee, N as te, O as ne, P as f, Q as p, R as m, S as h, T as g, U as _, V as v, W as y, X as b, Y as x, Z as S, _ as C, a as w, b as T, c as E, d as D, et as O, g as k, h as A, i as j, j as re, k as M, l as N, m as P, n as F, nt as I, p as L, q as R, r as z, rt as B, s as V, t as H, tt as U, u as W, v as G, w as K, x as q, y as J, z as Y } from "./driver-license-DWQiITx8.js";
1
+ import { $ as e, A as t, B as n, C as r, D as i, E as a, F as o, G as s, H as c, I as l, J as u, K as d, L as ee, M as te, N as ne, O as f, P as p, Q as m, R as h, S as g, T as _, U as v, V as y, W as b, X as x, Y as S, Z as C, _ as w, a as T, b as E, c as D, d as O, et as k, f as A, g as j, h as re, i as M, it as N, j as P, k as F, l as I, m as L, n as R, nt as z, r as B, rt as V, t as H, tt as U, u as W, v as G, w as K, x as q, y as J, z as Y } from "./driver-license-BmeEh0a_.js";
2
2
  //#region src/sdk/frame-geometry.ts
3
3
  function X(e, t, n) {
4
4
  let r = Math.max(1, t.width), i = Math.max(1, t.height), a = Math.max(1, n.width), o = Math.max(1, n.height), s = Math.max(r / a, i / o), c = (r - a * s) / 2, l = (i - o * s) / 2;
@@ -86,7 +86,7 @@ function ae(e) {
86
86
  }
87
87
  function $(e, t) {
88
88
  let n = e.getContext("2d");
89
- if (!n) throw B();
89
+ if (!n) throw N();
90
90
  let r = n.createLinearGradient(0, 0, e.width, e.height);
91
91
  r.addColorStop(0, "#16231c"), r.addColorStop(1, "#32443a"), n.fillStyle = r, n.fillRect(0, 0, e.width, e.height), n.save(), n.translate(t.centerX, t.centerY), n.rotate(t.rotation), n.shadowColor = "rgba(0,0,0,.45)", n.shadowBlur = 24, n.fillStyle = "#fffdf4", n.strokeStyle = "#111914", n.lineWidth = 7, n.fillRect(-t.width / 2, -t.height / 2, t.width, t.height), n.strokeRect(-t.width / 2, -t.height / 2, t.width, t.height), n.shadowColor = "transparent";
92
92
  let i = -t.width / 2, a = -t.height / 2;
@@ -110,6 +110,6 @@ function oe(e) {
110
110
  };
111
111
  }
112
112
  //#endregion
113
- export { te as AutoTorchController, a as DEFAULT_DOCUMENT_MODEL_URL, k as DEFAULT_HOLD_STILL_MS, S as DEV_LICENSE_HOSTS, p as LicenseError, f as NEAR_BLACK_LUMINANCE, C as QuadStabilityTracker, o as STILL_MAX_EDGE, I as ScannerError, N as applyRedactions, e as assertLicense, G as autoCaptureControl, l as captureVideoFrame, oe as createFinderSimulator, i as cropDocument, L as decodePdf417, d as detectBrowserEngine, ne as detectDocument, H as driverLicenseFieldsFromOcr, F as driverLicenseHoldStillMs, z as driverLicensePrompt, m as formatCaptureDiagnosticsReport, O as getLicense, Y as hasTransientUserActivation, J as holdStillCountdownLabel, T as holdStillSecondsRemaining, n as isAndroidBrowser, v as isNearBlackFrame, q as limitingFillTarget, ie as mapDocumentCornersToFrame, V as matchRedactionRules, c as meanFrameLuminance, h as measureQuadFill, j as mergeDriverLicenseFields, _ as mobileCameraConstraints, W as parseAamvaDate, D as parseAamvaPayload, P as pdf417BarcodeDetectorSupported, y as pickNativeCameraStill, A as recognizeText, E as redactProgrammatically, M as resolveDocumentModelUrl, t as scanDocument, re as scanSystemCameraStill, r as selectFinderGuidance, K as selectFinderHint, U as setLicenseKey, s as shouldPreferWebGpuForDocumentModel, R as shouldUseSystemCameraCapture, ae as simulatorQuad, u as startCamera, w as startDriverLicenseSession, g as startFinder, b as subscribeModelDownloads, ee as systemCameraFindMessage, x as torchControl };
113
+ export { p as AutoTorchController, i as DEFAULT_DOCUMENT_MODEL_URL, w as DEFAULT_HOLD_STILL_MS, m as DEV_LICENSE_HOSTS, e as LicenseError, o as NEAR_BLACK_LUMINANCE, G as QuadStabilityTracker, l as STILL_MAX_EDGE, V as ScannerError, W as applyRedactions, k as assertLicense, J as autoCaptureControl, ee as captureVideoFrame, oe as createFinderSimulator, f as cropDocument, L as decodePdf417, h as detectBrowserEngine, F as detectDocument, H as driverLicenseFieldsFromOcr, R as driverLicenseHoldStillMs, B as driverLicensePrompt, Y as formatCaptureDiagnosticsReport, U as getLicense, n as hasTransientUserActivation, E as holdStillCountdownLabel, q as holdStillSecondsRemaining, y as isAndroidBrowser, c as isNearBlackFrame, g as limitingFillTarget, ie as mapDocumentCornersToFrame, D as matchRedactionRules, v as meanFrameLuminance, r as measureQuadFill, M as mergeDriverLicenseFields, b as mobileCameraConstraints, O as parseAamvaDate, A as parseAamvaPayload, re as pdf417BarcodeDetectorSupported, s as pickNativeCameraStill, j as recognizeText, I as redactProgrammatically, t as resolveDocumentModelUrl, P as scanDocument, te as scanSystemCameraStill, K as selectFinderGuidance, _ as selectFinderHint, z as setLicenseKey, d as shouldPreferWebGpuForDocumentModel, u as shouldUseSystemCameraCapture, ae as simulatorQuad, S as startCamera, T as startDriverLicenseSession, a as startFinder, C as subscribeModelDownloads, ne as systemCameraFindMessage, x as torchControl };
114
114
 
115
115
  //# sourceMappingURL=scanner-sdk.js.map
@@ -1,4 +1,4 @@
1
- import type { ImageSource } from './types';
1
+ import type { DocumentCorners, DocumentQuad, ImageSource, Point } from './types';
2
2
  /**
3
3
  * Never feed zxing a 4K original. A 2160×3840 portrait still is ~8MP;
4
4
  * the PDF417 is a wide center band and reads at ~1600 long-edge (the
@@ -16,6 +16,15 @@ export type Pdf417DecoderState = 'idle' | 'loading' | 'ready' | 'failed';
16
16
  export interface Pdf417DecodeResult {
17
17
  text: string;
18
18
  source: Pdf417DecodeSource;
19
+ /** ZXing barcode corners in the source image’s pixel space. */
20
+ quad?: DocumentQuad;
21
+ }
22
+ export interface Pdf417Variant {
23
+ canvas: HTMLCanvasElement;
24
+ originX: number;
25
+ originY: number;
26
+ /** Variant pixels / source (or crop) pixels. */
27
+ scale: number;
19
28
  }
20
29
  export declare class Pdf417DecoderError extends Error {
21
30
  readonly code: "zxing-wasm-load";
@@ -28,6 +37,9 @@ export declare function getPdf417DecoderStatus(): {
28
37
  export declare function pdf417BarcodeDetectorSupported(): Promise<boolean>;
29
38
  /** Load packaged zxing-wasm now so a later live poll does not fail silently. */
30
39
  export declare function preparePdf417Decoder(): Promise<void>;
40
+ export declare function cornersToQuad(corners: DocumentCorners): DocumentQuad;
41
+ export declare function mapPdf417VariantPoint(point: Point, variant: Pick<Pdf417Variant, 'originX' | 'originY' | 'scale'>): Point;
42
+ export declare function mapPdf417VariantCorners(corners: DocumentCorners, variant: Pick<Pdf417Variant, 'originX' | 'originY' | 'scale'>): DocumentCorners;
31
43
  /** Full-frame copies capped at `PDF417_LIVE_MAX_EDGE`. */
32
44
  export declare function pdf417ScaleCanvases(canvas: HTMLCanvasElement): HTMLCanvasElement[];
33
45
  /**
@@ -37,6 +49,8 @@ export declare function pdf417ScaleCanvases(canvas: HTMLCanvasElement): HTMLCanv
37
49
  export declare function pdf417BandCanvases(canvas: HTMLCanvasElement): HTMLCanvasElement[];
38
50
  /** Band crops first (portrait), then capped full-frame scales. */
39
51
  export declare function pdf417DecodeCanvases(canvas: HTMLCanvasElement): HTMLCanvasElement[];
52
+ /** Same copies as `pdf417DecodeCanvases`, with crop/scale so a zxing quad maps back. */
53
+ export declare function pdf417DecodeVariants(canvas: HTMLCanvasElement): Pdf417Variant[];
40
54
  /**
41
55
  * PDF417 from a live frame or still via packaged `zxing-wasm` only.
42
56
  * Does not use `BarcodeDetector` (Chrome’s detector often misses a
@@ -50,6 +50,17 @@ export declare function processDriverLicenseFront(frame: HTMLCanvasElement, dete
50
50
  }>>;
51
51
  /** Live back polls this often when the host does not pass `detectionIntervalMs`. */
52
52
  export declare const LICENSE_BACK_POLL_MS = 140;
53
+ /** Green barcode box stays up this long before `onDriverLicense`. */
54
+ export declare const LICENSE_BACK_HIT_MS = 280;
55
+ /** Flip-to-back chip / notice stays up this long before the barcode session starts. */
56
+ export declare const LICENSE_FLIP_CUE_MS = 1600;
57
+ export type DriverLicensePromptSide = 'front' | 'back' | 'flip';
58
+ /** Hold the between-sides “turn it over” cue. Aborts if the session ends. */
59
+ export declare function waitLicenseFlipCue(signal?: AbortSignal): Promise<void>;
60
+ export interface Pdf417FrameHit {
61
+ frame: HTMLCanvasElement;
62
+ quad?: DocumentQuad;
63
+ }
53
64
  /**
54
65
  * Decode PDF417 from successive live frames until one succeeds.
55
66
  * Does not wait for a document quad.
@@ -57,11 +68,11 @@ export declare const LICENSE_BACK_POLL_MS = 140;
57
68
  export declare function waitForPdf417Frame(grabFrame: () => HTMLCanvasElement | undefined | Promise<HTMLCanvasElement | undefined>, options?: {
58
69
  intervalMs?: number;
59
70
  signal?: AbortSignal;
60
- }): Promise<HTMLCanvasElement>;
71
+ }): Promise<Pdf417FrameHit>;
61
72
  export declare function processDriverLicenseBack(frame: HTMLCanvasElement, front: DriverLicenseResult['front']): Promise<DriverLicenseResult>;
62
73
  /** Live back no longer starts the finder. Kept so hosts can skip hold-still if they still mount one. */
63
74
  export declare function driverLicenseHoldStillMs(side: 'front' | 'back'): 0 | undefined;
64
- export declare function driverLicensePrompt(side: 'front' | 'back', usingSystemCamera: boolean): {
75
+ export declare function driverLicensePrompt(side: DriverLicensePromptSide, usingSystemCamera: boolean): {
65
76
  title: string;
66
77
  headline: string;
67
78
  detail: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exige/web-scanner-sdk",
3
- "version": "0.2.37",
3
+ "version": "0.2.39",
4
4
  "description": "@exige/web-scanner-sdk is a client-side web document scanner SDK. ML document finding, OCR, and redaction run in the browser. The public demo is the only path that does not need an account. A hostname you control needs a signed license key.",
5
5
  "type": "module",
6
6
  "license": "MIT",