API reference
Exports of @sigx/lynx-camera — one runtime object plus the capture option, result, and cancel types.
The complete public surface is a single Camera const plus the type-only exports:
import { Camera } from '@sigx/lynx-camera';
import type {
CameraOptions,
PhotoResult,
CameraVideoOptions,
VideoResult,
CameraCancelled,
PermissionResponse,
} from '@sigx/lynx-camera';
PermissionResponse is re-exported from @sigx/lynx-core. Every method below works on both iOS and Android.
Object
Camera
The single namespace object exposing all camera APIs. It is backed by the native Camera module through @sigx/lynx-core.
const Camera: {
takePicture(options?: CameraOptions): Promise<PhotoResult | CameraCancelled>;
recordVideo(options?: CameraVideoOptions): Promise<VideoResult | CameraCancelled>;
requestPermission(): Promise<PermissionResponse>;
getPermissionStatus(): Promise<PermissionResponse>;
isAvailable(): boolean;
};
See the methods below for each member.
Methods
The three-outcome contract
Both takePicture and recordVideo follow the same contract, so you narrow them the same way:
- Success — resolves with a result that always carries a
uri(PhotoResult/VideoResult). - Cancel — resolves with
CameraCancelled({ cancelled: true }, nouri) when the user dismisses the camera. The Android{ error: "cancelled" }sentinel is normalized into this shape. - Failure — throws on a real error (permission denied, no camera, native bridge missing, …).
So callers narrow on result.uri for the success path and try / catch failures:
try {
const photo = await Camera.takePicture({ quality: 0.8 });
if (photo.uri) {
// captured — load it
} else {
// user cancelled
}
} catch (err) {
// permission denied / no camera / …
}
Camera.takePicture
Opens the system camera in photo mode.
takePicture(options?: CameraOptions): Promise<PhotoResult | CameraCancelled>
options— optionalCameraOptions. Defaults to{}.- Returns — a
PhotoResult(carryinguri) on success, orCameraCancelledon user-cancel. Throws on failure (see the three-outcome contract above).
Platform notes: most option fields are iOS-only — iOS honors facing and JPEG quality; Android's ACTION_IMAGE_CAPTURE intent ignores capture options (the user can still switch cameras in its UI). The returned uri is normalized to a scheme: file:// on iOS (a temp filesystem path) and content:// on Android (a JPEG in the app cache directory, via FileProvider). On Android, takePicture now auto-requests the CAMERA runtime permission before launching the intent (see requestPermission).
Camera.recordVideo
Opens the system camera in video mode and records a clip. The returned uri is loadable directly by @sigx/lynx-video's VideoPlayer.
recordVideo(options?: CameraVideoOptions): Promise<VideoResult | CameraCancelled>
options— optionalCameraVideoOptions. Defaults to{}.- Returns — a
VideoResult(carryinguri) on success, orCameraCancelledon user-cancel. Throws on failure (see the three-outcome contract above).
Platform notes: iOS uses UIImagePickerController movie mode, honoring maxDurationMs (videoMaximumDuration) and facing (cameraDevice); Android launches an ACTION_VIDEO_CAPTURE intent, which exposes no duration cap and ignores capture options. The uri is file:// on iOS and content:// on Android. On Android, recordVideo auto-requests the CAMERA permission (and microphone too, when the app declares RECORD_AUDIO, e.g. via @sigx/lynx-audio) before launching. A single in-camera photo/video toggle is iOS-only at the system level — offer a "photo or video" choice in your own UI and call the matching method.
Camera.requestPermission
Requests camera permission, showing the OS dialog if needed.
requestPermission(): Promise<PermissionResponse>
- Returns — a
Promise<PermissionResponse>describing the resulting status.
Calling this before capture is optional: both takePicture and recordVideo auto-request the CAMERA permission on Android (iOS auto-requests at the AVCaptureDevice layer), so you only need requestPermission to gate your own UI ahead of time or to inspect canAskAgain.
Platform notes: on first denial this re-surfaces the OS dialog. Check canAskAgain on the response — when false, the user must change the permission from system Settings.
Camera.getPermissionStatus
Checks the current camera permission status without prompting.
getPermissionStatus(): Promise<PermissionResponse>
- Returns — a
Promise<PermissionResponse>for the current status.
Platform notes: never shows a dialog. Use this for a silent check before deciding whether to call requestPermission.
Camera.isAvailable
Returns whether the native Camera module is registered in the current build.
isAvailable(): boolean
- Returns —
trueif the module is present, otherwisefalse.
Platform notes: this is a JS-only check (it does not cross the native bridge and does not test for hardware). A true result means the module was linked; it does not guarantee a usable camera device.
Types
CameraOptions
Options for Camera.takePicture. All fields are optional.
interface CameraOptions {
/** 'front' or 'back' camera (iOS only). */
facing?: 'front' | 'back';
/** JPEG quality 0-1 (default 0.8, iOS only). */
quality?: number;
/** Max width in pixels (reserved — not yet applied). */
maxWidth?: number;
/** Max height in pixels (reserved — not yet applied). */
maxHeight?: number;
}
facing— which camera to use. iOS only — Android's intent ignores it (the user can switch cameras in its UI).quality— JPEG quality from0to1(default0.8). iOS only.maxWidth/maxHeight— reserved for forward compatibility; not yet applied on either platform.
PhotoResult
The result returned by Camera.takePicture.
interface PhotoResult {
/** File URI of the captured photo (`file://` iOS, `content://` Android). */
uri: string;
/** Width in pixels (iOS only). */
width?: number;
/** Height in pixels (iOS only). */
height?: number;
/** File size in bytes (iOS only). */
fileSize?: number;
/** Base64-encoded image data (if requested). */
base64?: string;
}
uri— the captured JPEG, normalized to a scheme:file://on iOS,content://on Android. Always present on success.width/height/fileSize— best-effort metadata (iOS only — Android's intent doesn't report dimensions).base64— optional base64-encoded image data; not populated by either current native implementation.
This is the success shape. On cancel the resolved value is CameraCancelled ({ cancelled: true }, no uri); on failure the call throws. Narrow on uri before reading the other fields — see the three-outcome contract.
CameraVideoOptions
Options for Camera.recordVideo. All fields are optional.
interface CameraVideoOptions {
/** 'front' or 'back' camera (iOS only). */
facing?: 'front' | 'back';
/** Max recording length in milliseconds (iOS only). */
maxDurationMs?: number;
}
facing— which camera to use. iOS only — Android'sACTION_VIDEO_CAPTUREintent ignores it.maxDurationMs— recording cap, honored on iOS (videoMaximumDuration); Android's intent exposes no duration cap.
VideoResult
The success result returned by Camera.recordVideo.
interface VideoResult {
/** File URI of the recorded clip (`file://` iOS, `content://` Android). */
uri: string;
/** Clip duration in milliseconds (if the platform reports it). */
durationMs?: number;
/** Width in pixels (if reported). */
width?: number;
/** Height in pixels (if reported). */
height?: number;
/** File size in bytes (if reported). */
fileSize?: number;
}
uri— the recorded clip, normalized to a scheme (file://iOS,content://Android). Loadable directly by@sigx/lynx-video'sVideoPlayer.durationMs/width/height/fileSize— best-effort metadata when the platform reports it.
CameraCancelled
The shape resolved (not thrown) when the user dismisses the camera without capturing — shared by both takePicture and recordVideo.
interface CameraCancelled {
cancelled: true;
uri?: undefined;
}
uri is typed as undefined so callers can narrow on result.uri to tell a successful capture from a cancel.
PermissionResponse
The response shape for Camera.requestPermission and Camera.getPermissionStatus. Re-exported type-only from @sigx/lynx-core.
interface PermissionResponse {
/** Current permission status. */
status: PermissionStatus;
/**
* Whether the app can show the OS permission dialog again.
* `false` when the user selected "Don't ask again" (Android) or
* after the first denial (iOS — user must go to Settings).
*/
canAskAgain: boolean;
}
status— the current permission status (seePermissionStatusbelow).canAskAgain— whether the OS dialog can be shown again.
PermissionStatus is defined in @sigx/lynx-core and is not re-exported from this package. If you need the literal union, import it directly:
import type { PermissionStatus } from '@sigx/lynx-core';
// type PermissionStatus = 'granted' | 'denied' | 'undetermined' | 'blocked';
Platform note: the iOS native layer can additionally emit 'restricted' and 'unknown', which fall outside the declared union — handle unexpected values defensively.
