@exige/web-scanner-sdk 0.2.35 → 0.2.36

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 formatCaptureDiagnosticsReport,\n hasTransientUserActivation,\n meanFrameLuminance,\n NEAR_BLACK_LUMINANCE,\n pickNativeCameraStill,\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 } 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 const frame = await waitForPdf417Frame(\n () => {\n try {\n return camera.capture()\n } catch {\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('video-frame')\n setPhase('captured')\n await handleLicenseStillRef.current({\n frame,\n reason: 'auto',\n method: 'video-frame',\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 detectorStatus = 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 return (\n <div className=\"scanner-camera-overlay__status\" aria-live=\"polite\">\n <div className=\"scanner-camera-overlay__status-line\">\n <span className={finderStatus?.state ?? 'detecting'} />\n {finderStatus?.state ?? 'detecting'}\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 formatCaptureDiagnosticsReport,\n hasTransientUserActivation,\n meanFrameLuminance,\n NEAR_BLACK_LUMINANCE,\n pickNativeCameraStill,\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 const frame = await waitForPdf417Frame(\n () => {\n try {\n return camera.capture(PDF417_LIVE_MAX_EDGE)\n } catch {\n // Video not ready yet; 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('video-frame')\n setPhase('captured')\n await handleLicenseStillRef.current({\n frame,\n reason: 'auto',\n method: 'video-frame',\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,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, 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, j as N, k as P, l as F, m as I, n as L, p as R, q as z, r 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-CV0oawgf.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, g as A, h as j, i as re, j as M, k as N, l as P, m as F, n as I, nt as L, p as R, q as z, r 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-CBDCGp14.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 U();
89
+ if (!n) throw L();
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, _ as DEFAULT_DOCUMENT_MODEL_URL, re as DEFAULT_HOLD_STILL_MS, S as DEV_LICENSE_HOSTS, x as LicenseError, ne as NEAR_BLACK_LUMINANCE, j as QuadStabilityTracker, p as STILL_MAX_EDGE, k as ScannerError, F as applyRedactions, C as assertLicense, w as autoCaptureControl, o as captureVideoFrame, oe as createFinderSimulator, a as cropDocument, A as decodePdf417, l as detectBrowserEngine, i as detectDocument, H as driverLicenseFieldsFromOcr, L as driverLicenseHoldStillMs, B as driverLicensePrompt, ee as formatCaptureDiagnosticsReport, m as getLicense, h as hasTransientUserActivation, G as holdStillCountdownLabel, J as holdStillSecondsRemaining, Y as isAndroidBrowser, n as isNearBlackFrame, E as limitingFillTarget, ie as mapDocumentCornersToFrame, V as matchRedactionRules, y as meanFrameLuminance, q as measureQuadFill, M as mergeDriverLicenseFields, c as mobileCameraConstraints, W as parseAamvaDate, O as parseAamvaPayload, R as pdf417BarcodeDetectorSupported, v as pickNativeCameraStill, I as recognizeText, D as redactProgrammatically, f as resolveDocumentModelUrl, P as scanDocument, t as scanSystemCameraStill, g as selectFinderGuidance, r as selectFinderHint, e as setLicenseKey, b as shouldPreferWebGpuForDocumentModel, s as shouldUseSystemCameraCapture, ae as simulatorQuad, d as startCamera, T as startDriverLicenseSession, K as startFinder, u as subscribeModelDownloads, N as systemCameraFindMessage, z as torchControl };
113
+ export { ne as AutoTorchController, a as DEFAULT_DOCUMENT_MODEL_URL, A as DEFAULT_HOLD_STILL_MS, x as DEV_LICENSE_HOSTS, C as LicenseError, p as NEAR_BLACK_LUMINANCE, w as QuadStabilityTracker, o as STILL_MAX_EDGE, U as ScannerError, P as applyRedactions, m as assertLicense, G as autoCaptureControl, l as captureVideoFrame, oe as createFinderSimulator, i as cropDocument, R as decodePdf417, ee as detectBrowserEngine, f as detectDocument, H as driverLicenseFieldsFromOcr, I as driverLicenseHoldStillMs, B as driverLicensePrompt, h as formatCaptureDiagnosticsReport, e as getLicense, Y as hasTransientUserActivation, J as holdStillCountdownLabel, E as holdStillSecondsRemaining, n as isAndroidBrowser, y as isNearBlackFrame, q as limitingFillTarget, ie as mapDocumentCornersToFrame, V as matchRedactionRules, c as meanFrameLuminance, g as measureQuadFill, re as mergeDriverLicenseFields, v as mobileCameraConstraints, W as parseAamvaDate, O as parseAamvaPayload, F as pdf417BarcodeDetectorSupported, b as pickNativeCameraStill, j as recognizeText, D as redactProgrammatically, N as resolveDocumentModelUrl, t as scanDocument, M as scanSystemCameraStill, r as selectFinderGuidance, K as selectFinderHint, k as setLicenseKey, s as shouldPreferWebGpuForDocumentModel, d as shouldUseSystemCameraCapture, ae as simulatorQuad, z as startCamera, T as startDriverLicenseSession, _ as startFinder, S as subscribeModelDownloads, te as systemCameraFindMessage, u as torchControl };
114
114
 
115
115
  //# sourceMappingURL=scanner-sdk.js.map
@@ -1,9 +1,14 @@
1
1
  import type { ImageSource } from './types';
2
- /** Long-edge sizes after the original. Close-up PDF417 often fails at 4K. */
3
- export declare const PDF417_DECODE_EDGES: readonly [1280, 960, 720, 480];
4
2
  /**
5
- * Decode scales, original first, then smaller copies. Never upscales.
6
- * A US DL PDF417 that fills most of a 1080–4K frame often needs ~960–720.
3
+ * Never feed zxing a 4K original. A 2160×3840 portrait still is ~8MP;
4
+ * the PDF417 is a wide center band and reads at ~1600 long-edge (the
5
+ * distance that already worked when the code was ~1/3 of the preview).
6
+ */
7
+ export declare const PDF417_LIVE_MAX_EDGE = 1600;
8
+ export declare const PDF417_DECODE_EDGES: readonly [1600, 1280, 960, 720, 480];
9
+ /**
10
+ * Decode scales. Caps at `PDF417_LIVE_MAX_EDGE` so a 2160×3840 live
11
+ * frame is not sent to zxing at full size.
7
12
  */
8
13
  export declare function pdf417DecodeEdges(width: number, height: number): number[];
9
14
  export type Pdf417DecodeSource = 'barcode-detector' | 'zxing-wasm';
@@ -12,8 +17,15 @@ export interface Pdf417DecodeResult {
12
17
  source: Pdf417DecodeSource;
13
18
  }
14
19
  export declare function pdf417BarcodeDetectorSupported(): Promise<boolean>;
15
- /** Original plus downscaled copies. Used by live back and system-camera stills. */
20
+ /** Full-frame copies capped at `PDF417_LIVE_MAX_EDGE`. */
16
21
  export declare function pdf417ScaleCanvases(canvas: HTMLCanvasElement): HTMLCanvasElement[];
22
+ /**
23
+ * Portrait live frames (2160×3840) bury a wide PDF417 in a center band.
24
+ * Crop that band before shrinking so modules stay large enough for zxing.
25
+ */
26
+ export declare function pdf417BandCanvases(canvas: HTMLCanvasElement): HTMLCanvasElement[];
27
+ /** Band crops first (portrait), then capped full-frame scales. */
28
+ export declare function pdf417DecodeCanvases(canvas: HTMLCanvasElement): HTMLCanvasElement[];
17
29
  /**
18
30
  * PDF417 from a live frame or still via packaged `zxing-wasm` only.
19
31
  * Does not use `BarcodeDetector` (Chrome’s detector often misses a
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exige/web-scanner-sdk",
3
- "version": "0.2.35",
3
+ "version": "0.2.36",
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",