import './camera.css';
/**
* Camera lifecycle state.
* - `'open'` — Camera is active and streaming.
* - `'loading'` — Camera is being initialized.
* - `'close'` — Camera is inactive.
*/
type CameraState = 'open' | 'loading' | 'close';
/**
* Camera facing direction.
* - `'front'` — Front-facing (selfie) camera.
* - `'back'` — Rear-facing camera.
*/
type FacingMode = 'front' | 'back';
/**
* Options for opening a camera.
*/
export interface CameraOpenOptions {
/**
* Camera facing direction.
* @default 'front'
*/
facingMode?: FacingMode;
/**
* Desired camera resolution width in pixels.
*/
width?: number;
/**
* Desired camera resolution height in pixels.
*/
height?: number;
/**
* Specific camera device ID. When specified, `facingMode` is ignored.
*/
deviceId?: string;
}
/**
* Options for configuring image capture behavior.
*
* @example
* // Capture with resize
* const dataUrl = camera.capture({ width: 640, height: 480, fit: 'cover' });
*
* @example
* // Capture and crop a specific region
* const dataUrl = camera.capture({
* extract: { x: 100, y: 50, width: 200, height: 200 },
* format: 'image/jpeg',
* });
*/
export interface CaptureOptions {
/**
* Target width in pixels for resizing the captured image.
* If omitted, the original width is preserved.
* When only `width` is specified, `height` is calculated to maintain the aspect ratio.
*/
width?: number;
/**
* Target height in pixels for resizing the captured image.
* If omitted, the original height is preserved.
* When only `height` is specified, `width` is calculated to maintain the aspect ratio.
*/
height?: number;
/**
* Region to crop from the captured frame.
* Coordinates are relative to the camera viewport (CSS pixels).
*/
extract?: {
/** Horizontal offset from the left edge (px). */
x: number;
/** Vertical offset from the top edge (px). */
y: number;
/** Width of the crop region (px). */
width: number;
/** Height of the crop region (px). */
height: number;
};
/**
* Resize fitting strategy, analogous to CSS `object-fit`.
* - `'cover'` — Scale to fill the target dimensions, cropping if necessary.
* - `'contain'` — Scale to fit within the target dimensions, letter-boxing if necessary.
* - `'fill'` — Stretch to exactly match the target dimensions.
* @default 'fill'
*/
fit?: 'cover' | 'contain' | 'fill';
/**
* Output MIME type for the captured image.
* @default 'image/png'
*/
format?: string;
}
/**
* A custom element that provides camera access, live preview, image capture,
* and optional built-in controls using the Web Components V1 API.
*
* @example
* // Register and create programmatically
* Camera.define();
* const camera = document.querySelector('js-camera') as Camera;
* await camera.open({ facingMode: 'back', width: 1920, height: 1080 });
* const dataUrl = camera.capture({ format: 'image/jpeg' });
*
* @example
* // Declarative usage with auto-play
* //
*
* @fires opened - Camera stream has been opened and is ready.
* @fires played - Camera playback has resumed from a paused state.
* @fires paused - Camera playback has been paused.
* @fires captured - A frame has been captured. Event `detail.capture` contains the data URL.
*/
declare class Camera extends HTMLElement {
#private;
/**
* Current camera lifecycle state.
*
* @example
* if (camera.state === 'open') {
* camera.capture();
* }
*/
get state(): CameraState;
/**
* Active camera facing direction, or `undefined` if the camera has not been opened.
*
* @example
* console.log(camera.facingMode); // 'front' or 'back'
*/
get facingMode(): FacingMode | undefined;
/**
* Device ID of the currently active camera, or `undefined` if not opened.
*/
get deviceId(): string | undefined;
/**
* The active `MediaStreamTrack` for the video feed,
* or `undefined` if no stream is active.
*
* @example
* if (camera.track) {
* console.log(camera.track.getSettings());
* }
*/
get track(): MediaStreamTrack | undefined;
/**
* Whether the camera stream is currently active.
*
* @example
* if (camera.opened) {
* const dataUrl = camera.capture();
* }
*/
get opened(): boolean;
/**
* Whether the camera playback is currently paused.
*/
get paused(): boolean;
/**
* The actual video resolution reported by the camera hardware.
*
* @example
* const { width, height } = camera.resolution;
* console.log(`Camera resolution: ${width}x${height}`);
*/
get resolution(): {
width: number;
height: number;
};
/**
* Current zoom level. `1` means no zoom.
*
* @example
* console.log(camera.zoom); // 1
*/
get zoom(): number;
constructor();
/**
* Called when the element is inserted into the DOM.
* Initializes the camera UI and optional controls.
*/
protected connectedCallback(): void;
/**
* Registers the `` custom element.
* Safe to call multiple times; subsequent calls are no-ops.
*
* @returns The Camera class for chaining.
*
* @example
* Camera.define();
* // is now available in HTML
*/
static define(): typeof Camera;
/**
* Creates a new `` element instance.
* Automatically calls {@link define} if not already registered.
*
* @returns A new Camera element ready to be appended to the DOM.
*
* @example
* const camera = Camera.createElement();
* document.body.appendChild(camera);
* await camera.open({ facingMode: 'back' });
*/
static createElement(): Camera;
/**
* Opens the camera with the specified options.
* If a camera is already open, it is closed and re-opened with the new options.
*
* @param options - Camera configuration including facing mode and resolution.
* @returns The actual track settings reported by the camera device.
* @throws {DOMException} If camera access is denied or the device is unavailable.
*
* @example
* // Open the rear camera at Full HD resolution
* const settings = await camera.open({
* facingMode: 'back',
* width: 1920,
* height: 1080,
* });
* console.log(settings.deviceId);
*
* @example
* // Open a specific camera by device ID
* const settings = await camera.open({
* deviceId: 'abc123',
* });
*/
open(options?: CameraOpenOptions): Promise;
/**
* Returns a promise that resolves when the camera finishes opening.
* If the camera is not currently loading, resolves immediately.
*
* @example
* await camera.waitOpen();
* const dataUrl = camera.capture();
*/
waitOpen(): Promise;
/**
* Closes the camera and releases all associated resources.
*
* @example
* camera.close();
* console.log(camera.state); // 'close'
*/
close(): void;
/**
* Resumes camera playback from a paused state.
*
* @example
* camera.play();
*/
play(): Promise;
/**
* Pauses camera playback.
* The current frame remains visible but the stream stops updating.
*
* @example
* camera.pause();
* console.log(camera.paused); // true
*/
pause(): void;
/**
* Resets the zoom level to 1 (no zoom).
*
* @example
* camera.resetZoom();
* console.log(camera.zoom); // 1
*/
resetZoom(): void;
/**
* Captures the current video frame as a data URL.
* Applies optional cropping, resizing, and format conversion.
*
* @param options - Capture configuration for cropping, resizing, and output format.
* @returns A data URL string of the captured image.
*
* @example
* // Simple capture as PNG
* const dataUrl = camera.capture();
*
* @example
* // Capture as JPEG, resized to 320x240 with cover fit
* const dataUrl = camera.capture({
* width: 320,
* height: 240,
* fit: 'cover',
* format: 'image/jpeg',
* });
*
* @example
* // Crop a 200x200 region from position (100, 50)
* const dataUrl = camera.capture({
* extract: { x: 100, y: 50, width: 200, height: 200 },
* });
*/
capture(options?: CaptureOptions): string;
/**
* Queries the current camera permission state.
*
* @returns The permission state, or `undefined` if the Permissions API is unavailable.
*
* @example
* const permission = await camera.queryPermission();
* if (permission === 'granted') {
* await camera.open({ facingMode: 'back' });
* }
*/
queryPermission(): Promise;
/**
* Revokes camera permissions using the Permissions API.
* Not all browsers support this; a warning is logged if unsupported.
*/
revokePermission(): Promise;
/**
* Enumerates available camera devices on the system.
* Requests temporary camera access if permission has not been granted.
*
* @returns An array of objects containing `deviceId` and `label` for each camera.
*
* @example
* const devices = await camera.getDevices();
* devices.forEach(d => console.log(`${d.label} (${d.deviceId})`));
*/
getDevices(): Promise[]>;
/**
* Adds an event listener to this camera element.
*
* @param type - Event type (e.g., `'opened'`, `'captured'`).
* @param listener - Callback function.
* @param options - Listener options.
* @returns This camera element for chaining.
*
* @example
* camera
* .on('opened', () => console.log('Camera ready'))
* .on('captured', (e) => console.log('Captured:', e.detail.capture));
*/
on(type: string, listener: (event?: Event) => void, options?: {
once?: boolean;
}): Camera;
/**
* Removes an event listener from this camera element.
*
* @param type - Event type.
* @param listener - The listener to remove.
* @returns This camera element for chaining.
*/
off(type: string, listener: (event?: Event) => void): Camera;
}
export default Camera;