@healthcloudai/hc-document-capture-ui
v3.2.5
Published
React Native camera capture UI for ID / insurance cards — expo-camera (native) + OpenCV.js (web). Camera-only; pair with @healthcloudai/hc-sdk for OCR.
Maintainers
Readme
@healthcloudai/hc-document-capture-ui
React Native camera capture UI for ID and insurance cards — across iOS, Android, and Web.
This package is camera-only. It captures a JPEG image of a document and hands it to the caller via onCaptured(uri). For OCR / field extraction, pair it with @healthcloudai/hc-sdk:
sdk.patient.ocrIdentityDocument({ image })— OCR an ID documentsdk.patient.ocrInsuranceDocument({ image })— OCR an insurance cardsdk.patient.scanIdentityDocument({ document_data, verify_against_demographics })— analyze + verify an identity document
No backend communication, no canned-URL uploads, no Veryfi Lens, no settings connector. Just the camera.
How it works
CardCameraCapture (native) / JScanifyWebCapture (web)
│
│ onCaptured(uri) ← JPEG: file:// URI (native) or data:image/jpeg;base64,... (web)
▼
Caller converts to data URI if needed (expo-file-system on native)
│
▼
sdk.patient.ocrIdentityDocument({ image: dataUri }) ← @healthcloudai/hc-sdk
│
▼
OCR fields → your app's pre-fill pipelineInstallation
npm install @healthcloudai/hc-document-capture-uiPeer dependencies
| Package | Required? | Used by |
|---|---|---|
| expo-camera | optional | CardCameraCapture (native) |
| expo-modules-core | required | Native module bridge (DocumentDetectModule, ImageCropModule) |
| expo-image-manipulator | optional | Fallback image crop (if native ImageCropModule not linked) |
| react-native-svg | optional | Live detected-quad overlay in CardCameraCapture |
| @expo/vector-icons | optional | Icons in capture UI |
| react-native-reanimated | optional | Animations |
| react >=18 <20 | required | — |
| react-native >=0.72.0 | required | — |
Install the peers you need:
npm install expo-camera expo-modules-core react-native-svgNative modules
This package ships two native modules (registered via expo-module.config.json autolinking — no config plugin needed):
DocumentDetectModule— iOS Vision (VNDetectRectanglesRequest) / Android pure-Kotlin (Sobel + Moore boundary trace). PowersautoDetectonCardCameraCapture.ImageCropModule— iOS CoreGraphics / AndroidBitmapRegionDecoder. Crops captured photos to the on-screen guide frame.
After installing, run npx expo prebuild to link the pods / Gradle entries.
iOS
- Requires deployment target
17.0(set viaexpo-build-propertiesor yourPodfile). - Uses
VisionandCoreGraphicsframeworks (iOS built-in — no third-party pods). - Add
NSCameraUsageDescriptiontoInfo.plist(or via theexpo-cameraconfig plugin).
Android
- Pure-Kotlin detector — no ML Kit, no Google Play Services dependency.
- Only additional dep:
androidx.core:core-ktx(already present transitively in most RN apps).
Usage
Native — CardCameraCapture
import { CardCameraCapture } from "@healthcloudai/hc-document-capture-ui";
function IdScanScreen({ onCaptured, onCancel }) {
return (
<CardCameraCapture
documentType="id"
autoDetect={true}
onCaptured={(croppedUri) => {
// croppedUri is a file:// URI to a JPEG cropped to the guide frame.
// Pass it to hc-sdk for OCR:
// const image = await uriToJpegDataUri(croppedUri);
// const result = await sdk.patient.ocrIdentityDocument({ image });
onCaptured(croppedUri);
}}
onClose={onCancel}
onError={(err) => console.error(err)}
onStatusChange={(status) => {
if (status === "ready") console.log("camera ready");
}}
/>
);
}Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| documentType | "id" \| "insurance" | — | Document kind (affects aspect ratio + stability tuning) |
| onCaptured | (croppedUri: string) => void | — | Receives a cropped JPEG file:// URI |
| onClose | () => void | — | Called when user closes the camera |
| onError | (error: unknown) => void | — | Called on capture/camera errors |
| autoDetect | boolean | true | Use native rectangle detection (iOS Vision / Android Kotlin). Falls back to legacy 2.5s timer if module not linked or 15s safety timeout. |
| autoCaptureDelayMs | number | 2500 | ms before auto-capture fires (legacy path) |
| detectionStartDelayMs | number | 1500 | ms after camera ready before detection starts |
| topInset / bottomInset | number | 0 | Safe-area insets (package does not import safe-area-context) |
| instructionText / manualHintText | string | — | Override on-screen hints |
| theme | Partial<DocumentCaptureTheme> | — | Color overrides |
| onStatusChange | (status: CaptureStatus) => void | — | Optional lifecycle hook for camera state (idle, permission_required, ready, detecting, capturing, captured, error, closed) |
| onReady | () => void | — | Convenience hook fired when the camera is usable |
Web — JScanifyWebCapture
import { JScanifyWebCapture } from "@healthcloudai/hc-document-capture-ui";
function IdScanScreenWeb({ onCaptured, onCancel }) {
return (
<JScanifyWebCapture
documentType="id"
opencvScriptUrl="https://docs.opencv.org/4.8.0/opencv.js"
onCaptured={(dataUrl) => {
// dataUrl is a data:image/jpeg;base64,... string (already a data URI).
// Pass directly to hc-sdk:
// const result = await sdk.patient.ocrIdentityDocument({ image: dataUrl });
onCaptured(dataUrl);
}}
onClose={onCancel}
onError={(err) => console.error(err)}
/>
);
}Props:
| Prop | Type | Default | Description |
|---|---|---|---|
| documentType | "id" \| "insurance" | — | Document kind |
| onCaptured | (dataUrl: string) => void | — | Receives a data:image/jpeg;base64,... string |
| onClose | () => void | — | Called when user closes |
| onError | (error: unknown) => void | — | Called on errors |
| opencvScriptUrl | string | https://docs.opencv.org/4.x/opencv.js | Override the OpenCV.js URL (e.g. to pin a version or self-host) |
| theme | Partial<DocumentCaptureTheme> | — | Color overrides |
| logger | (level, message, metadata?) => void | — | Optional logger |
| onStatusChange | (status: CaptureStatus) => void | — | Optional lifecycle hook for camera state |
| onReady | () => void | — | Convenience hook fired when the camera is usable |
opencv.js version pinning: If your app also uses
@healthcloudai/hc-cameravitals-connector(Circadify Web SDK, which loads opencv.js 4.8.0), passopencvScriptUrl="https://docs.opencv.org/4.8.0/opencv.js"to avoid loading two different opencv.js versions (which registers WASM twice).
Optional: app-wide config via DocumentCaptureProvider
Both camera components accept theme / opencvScriptUrl / logger as direct props. For app-wide defaults, wrap your navigator with a provider:
import { DocumentCaptureProvider } from "@healthcloudai/hc-document-capture-ui";
export function App() {
return (
<DocumentCaptureProvider
config={{
theme: { primary: "#36D399" },
opencvScriptUrl: "https://docs.opencv.org/4.8.0/opencv.js",
logger: (level, msg) => console[level](msg),
}}
>
<Navigator />
</DocumentCaptureProvider>
);
}Components read theme and opencvScriptUrl from context if not passed as props. Works without a provider (falls back to DEFAULT_CAPTURE_THEME and the default opencv.js URL).
Building blocks
CardScanGuide
A static card-guide frame overlay (corner brackets + scan-line animation). Useful if you build a custom camera screen and just want the guide frame.
CaptureOcrNoticeModal
A themed modal for showing OCR processing status (web-only — returns null on native).
Low-level utilities
detectDocumentQuad
import { detectDocumentQuad } from "@healthcloudai/hc-document-capture-ui";
const result = await detectDocumentQuad("data:image/jpeg;base64,...");
// → { detected: true, quad: [[x,y],...], aspect: 1.58, confidence: 0.9, width, height }
// → { detected: false } on web / module not linked / no detectionWraps the native DocumentDetectModule. Returns { detected: false } gracefully on web or when the module isn't linked.
createStabilityTracker
import { createStabilityTracker } from "@healthcloudai/hc-document-capture-ui";
const tracker = createStabilityTracker("id");
const obs = tracker.observe(detectedQuad);
if (obs.shouldCapture) {
// fire shutter
}Per-document-type stability gating (warmup frames, centroid shift threshold, area-change threshold). Used internally by CardCameraCapture.
cropToScanFrame
Crops a captured photo to the on-screen scan-guide frame. Delegates to the native ImageCropModule → expo-image-manipulator → original URI fallback chain.
Types
interface DocumentCaptureTheme {
background: string;
text: string;
primary: string;
error: string;
overlay: string;
surface: string;
border: string;
}
interface DocumentCaptureConfig {
theme?: Partial<DocumentCaptureTheme>;
opencvScriptUrl?: string;
logger?: (level, message, metadata?) => void;
}License
MIT
