Camera Component
Introduction
The Camera Component in CXTMS captures still images using the device camera in picture mode. It is designed for workflows requiring visual documentation — proof of delivery, shipment verification, damage inspection, etc. The component streams the camera feed to a <video> element, captures frames to a hidden <canvas>, and fires onCapture with the result (base64 or Blob) for upload or storage.
YAML Structure
component: camera
name: cameraPrimary
props:
width: <number>
height: <number>
facing: <"front" | "back">
mode: <string> # currently only "picture" is supported
enableTorch: <boolean>
zoom: <number>
autofocus: <"on" | "off" | undefined>
mirror: <boolean>
picture:
quality: <number> # 0–1, default varies
format: <"jpeg" | "png" | "webp">
base64: <boolean> # if true, result is base64 string; else Blob
onCapture:
- <action_sequence>
onScan:
- <action_sequence>
onError:
- <action_sequence>
onPermissionDenied:
- <action_sequence>
onClose:
- <action_sequence>
onReady:
- <action_sequence>
onPermissionDenied:
- <action_sequence>
onError:
- <action_sequence>
Structure Breakdown
| Element | Type | Description |
|---|---|---|
component | string | Always camera |
props | object | Camera options and event handlers |
width / height | number | Viewport dimensions in pixels |
facing | string | Camera to use: front or back (default: back) |
picture | object | Capture format and quality settings |
enableTorch | boolean | Enable flashlight/torch while streaming |
zoom | number | Initial zoom level |
autofocus | string | on / off; defaults to browser auto |
mirror | boolean | Mirror the preview (default: true for front camera) |
onCapture | array | Actions fired after a successful capture |
scanner.recognize | array | Mobile recognition modes: barcode, vin, and container |
scanner.autoCapture | boolean | Mobile: capture a proof photo when a scan is accepted |
onClose | array | Actions fired when the camera stream stops |
onReady | array | Actions fired when the camera is initialized |
onPermissionDenied | array | Actions fired when camera permission is denied |
onError | array | Actions fired on camera initialization or runtime errors |
Attribute Description
Root level
- Type:
string - Description: Always set to
camera.
props.facing
- Type:
string - Values:
front,back - Default:
back - Description: Selects which physical camera to use.
props.mode
- Type:
string - Default:
picture - Description: Currently only
picturemode is supported. Other values fall back to picture mode with a console warning.
props.picture
| Sub-prop | Type | Default | Description |
|---|---|---|---|
quality | number | provider default | JPEG quality from 0 to 1 |
format | string | jpeg | Output format: jpeg, png, or webp |
base64 | boolean | — | If true, onCapture receives a base64 string; otherwise a Blob |
props.enableTorch
- Type:
boolean - Description: Activates the device flash / torch during streaming.
props.zoom
- Type:
number - Description: Initial zoom factor (device capabilities determine actual range).
props.autofocus
- Type:
string - Values:
on,off - Description: Controls the autofocus feature. Omit to let the browser decide.
props.mirror
- Type:
boolean - Default:
truefor front camera,falsefor back - Description: Horizontally flips the video preview (does not affect the captured image).
Event Handlers
onCapture
Fired after a frame is captured from the canvas. Receives { data: string|Blob, width: number, height: number }.
onClose
Fired when the camera stream is stopped (component unmounts or parent closes it).
onReady
Fired once the camera is initialized and streaming. Receives { facing, mode: 'picture' }.
onPermissionDenied
Fired when the browser denies camera permission. Receives { permission: 'camera' }.
onError
Fired on camera initialization failure or runtime errors. Receives { message: string, code: string }.
Mobile scanning and OCR
The native renderer supports scanner.recognize with barcode, vin, and container. VIN recognition validates ISO 3779 values; container recognition validates ISO 6346 numbers. OCR candidates must repeat across frames before acceptance, and a confirmed value is cooled down to prevent duplicate events. Barcode decoding remains enabled only when barcode is included, but valid VIN or container barcodes are classified as their specific type when those modes are also enabled.
onScan receives { data, format, type }, where type identifies the accepted recognition mode. Set scanner.autoCapture: true to take a proof photo immediately after an accepted scan; the result additionally contains photoUri, photoWidth, and photoHeight, or captureError when the value was accepted but the photo failed. OCR runs in native builds; Expo Go uses its available scanner implementation and does not provide the native OCR pipeline.
component: camera
name: vehicleScanner
props:
mode: scanner
scanner:
recognize: [barcode, vin, container]
autoCapture: true
onScan:
- setStore:
scannedValue: "{{ result.data }}"
recognizedAs: "{{ result.type }}"
proofPhoto: "{{ result.photoUri }}"
Examples
1. Picture mode — proof-of-delivery photo
A driver captures a single photo, uploads it, and stores the resulting URL on the delivery record.
component: camera
name: podCamera
props:
width: 1024
height: 768
facing: back
onCapture:
- fileUpload:
file: "{{ result.data }}"
name: "capture"
onSuccess:
- setStore:
imageUrl: "{{ result.url }}"
onClose:
- navigateBackOrClose:
result: "cancelled"
Front Camera with Mirror and Torch
component: camera
props:
facing: front
mirror: true
enableTorch: false
picture:
format: jpeg
quality: 0.85
base64: true
onCapture:
- setStore:
selfieData: "{{ result.data }}"
onPermissionDenied:
- notification:
message: "Camera access is required to take photos."
variant: warning
onError:
- notification:
message: "Camera error: {{ error.message }}"
variant: error
With Autofocus Disabled and Zoom
component: camera
name: receivingScanner
props:
width: 1280
height: 720
facing: back
zoom: 1.5
autofocus: off
picture:
format: png
base64: true
onCapture:
- setStore:
scannedImage: "{{ result.data }}"
Best Practices
- Pick the tightest
barcodeTypeswhitelist that fits your workflow. Decoding every symbology is slower and admits more false reads. Retail flows usually needean13,ean8,upc_a,upc_e. Logistics flows usually needcode128,itf14,qr,datamatrix. - Set a realistic
minBarcodeLength. Too low admits noise from wedge scanners and partial reads; too high rejects legitimate short codes (e.g.ean8is only 8 characters). - Use
enableTorchfor dim environments. Warehouses, trailer interiors, and night deliveries decode dramatically faster with the torch on. Consider exposing it as a user-toggleable UI control rather than hard-codingtrue. - Leave
deduplicate: truefor multi-scan workflows. Operators routinely sweep the same carton twice; deduplication prevents double-counting without forcing the operator to be careful. - Always handle
onPermissionDeniedon mobile devices. A camera component that silently shows nothing when permission is denied is the most common in-field complaint. Show a dialog explaining how to re-enable the permission. - In
hybridmode, give visual confirmation of scans. Because scans and captures are independent in hybrid mode, operators benefit from an on-screen confirmation (notification or store-bound badge) before they tap the shutter — otherwise they don't know whether the scan landed. - Prefer
result.urloverresult.datafor uploads. The Base64 payload doubles memory pressure; only setpicture.base64: trueif a downstream consumer specifically needs it. - Avoid logging sensitive barcode contents. Shipping labels often encode customer addresses, PII, and order values. Restrict any action that persists raw barcode data to authorized roles.
When to use Camera vs Barcode Scanner Component vs openBarcodeScanner action
CXTMS exposes three different barcode-capable surfaces. Use this table to pick the right one:
| Use case | Best surface |
|---|---|
| Inline live camera viewport that only scans (no photo) | Barcode Scanner Component |
| One-off "Scan something" triggered from a button or workflow | openBarcodeScanner action |
| Camera viewport that captures still photos | camera with mode: picture |
| Camera viewport that captures still photos and scans codes | camera with mode: hybrid |
| Full-screen continuous scanning workflow with live preview | camera with mode: scanner |
Rule of thumb: choose camera when the operator needs to see the preview as part of the task. Choose the standalone scanner component or action when the camera is purely an input device and a live viewport is incidental.
Related Topics
On mobile, camera event handlers receive the enclosing form context and component name. This allows scan or capture handlers to use form actions such as setFields; camera permission handling and the existing native-device limitations still apply.
The mobile camera viewport now honors supported sx/options.sx sizing and presentation properties on its outer container, including explicit height, minimum height, border radius, and overflow. The same container style is retained while permission is loading or denied, preventing the screen from jumping between camera states. Selector-based web CSS remains unsupported on native.