or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

barcode-scanning.mdcamera-component.mdindex.mdmedia-capture.mdpermissions.md
tile.json

camera-component.mddocs/

Camera Component

The CameraView component is the core camera interface that renders a live camera preview and provides comprehensive camera control functionality across iOS, Android, and Web platforms.

Capabilities

CameraView Component

The main React component for camera functionality.

/**
 * React component that renders a camera preview with full camera controls
 */
declare const CameraView: React.ForwardRefExoticComponent<
  CameraViewProps & React.RefAttributes<CameraViewRef>
>;

CameraView Props

Complete configuration interface for the camera component.

interface CameraViewProps extends ViewProps {
  /**
   * Camera facing direction
   * @default 'back'
   */
  facing?: CameraType;
  
  /**
   * Flash mode setting
   * @default 'off'
   */
  flash?: FlashMode;
  
  /**
   * Zoom level (0 to 1, where 1 is maximum zoom)
   * @default 0
   */
  zoom?: number;
  
  /**
   * Camera mode for capture
   * @default 'picture'
   */
  mode?: CameraMode;
  
  /**
   * Whether to mute video recording
   * @default false
   */
  mute?: boolean;
  
  /**
   * Whether to mirror the image (front camera)
   * @default false
   */
  mirror?: boolean;
  
  /**
   * Auto focus mode (iOS only)
   * @default 'off'
   */
  autofocus?: FocusMode;
  
  /**
   * Whether camera should be active (iOS only)
   * @default true
   */
  active?: boolean;
  
  /**
   * Video quality setting
   */
  videoQuality?: VideoQuality;
  
  /**
   * Video bitrate in bits per second
   */
  videoBitrate?: number;
  
  /**
   * Whether to animate shutter
   * @default true
   */
  animateShutter?: boolean;
  
  /**
   * Picture size string (use getAvailablePictureSizes to get options)
   */
  pictureSize?: string;
  
  /**
   * Selected lens identifier (iOS only)
   * @default 'builtInWideAngleCamera'
   */
  selectedLens?: string;
  
  /**
   * Whether to enable torch
   * @default false
   */
  enableTorch?: boolean;
  
  /**
   * Video stabilization mode (iOS only)
   */
  videoStabilizationMode?: VideoStabilization;
  
  /**
   * Barcode scanner configuration
   */
  barcodeScannerSettings?: BarcodeSettings;
  
  /**
   * Loading poster image URL (Web only)
   */
  poster?: string;
  
  /**
   * Allow responsive orientation when locked (iOS only)
   */
  responsiveOrientationWhenOrientationLocked?: boolean;
  
  /**
   * Camera preview aspect ratio (Android only)
   */
  ratio?: CameraRatio;
  
  /**
   * Callback when camera is ready
   */
  onCameraReady?: () => void;
  
  /**
   * Callback when camera mount fails
   */
  onMountError?: (event: CameraMountError) => void;
  
  /**
   * Callback when barcode is scanned
   */
  onBarcodeScanned?: (result: BarcodeScanningResult) => void;
  
  /**
   * Callback when orientation changes (iOS only)
   */
  onResponsiveOrientationChanged?: (event: ResponsiveOrientationChanged) => void;
  
  /**
   * Callback when available lenses change (iOS only)
   */
  onAvailableLensesChanged?: (event: AvailableLenses) => void;
}

Static Methods and Properties

Static methods and properties available on the CameraView class.

/**
 * Check whether the current device has a camera
 * This is useful for web and simulators cases
 * @platform web
 * @returns Promise resolving to boolean indicating camera availability
 */
static isAvailableAsync(): Promise<boolean>;

/**
 * Get available video codecs for the current device
 * @platform ios  
 * @returns Promise resolving to array of supported video codecs
 */
static getAvailableVideoCodecsAsync(): Promise<VideoCodec[]>;

/**
 * Property indicating if modern barcode scanner is available
 * @platform ios
 */
static readonly isModernBarcodeScannerAvailable: boolean;

/**
 * Launch the modern barcode scanner with options
 * @platform ios
 * @param options Scanner configuration options
 * @returns Promise resolving when scanner launches
 */
static launchScanner(options?: ScanningOptions): Promise<void>;

/**
 * Dismiss the modern barcode scanner
 * @platform ios  
 * @returns Promise resolving when scanner dismisses
 */
static dismissScanner(): Promise<void>;

/**
 * Listen for modern barcode scanner events
 * @platform ios
 * @param listener Event listener function
 * @returns Event subscription object
 */
static onModernBarcodeScanned(listener: (event: ScanningResult) => void): EventSubscription;

Component Ref Methods

Methods available through the component ref for programmatic camera control.

interface CameraViewRef {
  /**
   * Take a picture with the specified options
   * @param options Picture capture configuration
   * @returns Promise resolving to captured picture data
   */
  readonly takePicture: (options?: CameraPictureOptions) => Promise<CameraCapturedPicture>;
  
  /**
   * Take a picture and return a PictureRef for native image handling
   * @param options Picture capture configuration
   * @returns Promise resolving to picture reference
   */
  readonly takePictureRef?: (options?: CameraPictureOptions) => Promise<PictureRef>;
  
  /**
   * Get available picture sizes for the current camera
   * @returns Promise resolving to array of size strings
   */
  readonly getAvailablePictureSizes: () => Promise<string[]>;
  
  /**
   * Get available camera lenses (iOS only)
   * @returns Promise resolving to array of lens identifiers
   */
  readonly getAvailableLenses: () => Promise<string[]>;
  
  /**
   * Start video recording
   * @param options Recording configuration options
   * @returns Promise resolving to video file info
   */
  readonly record: (options?: CameraRecordingOptions) => Promise<{ uri: string }>;
  
  /**
   * Toggle video recording state (iOS 18+ only)
   * @platform ios
   * @returns Promise resolving when toggle completes
   */
  readonly toggleRecording: () => Promise<void>;
  
  /**
   * Stop video recording
   * @returns Promise resolving when recording stops
   */
  readonly stopRecording: () => Promise<void>;
  
  /**
   * Launch modern barcode scanner (iOS only)
   * @returns Promise resolving when scanner launches
   */
  readonly launchModernScanner: () => Promise<void>;
  
  /**
   * Resume camera preview
   * @returns Promise resolving when preview resumes
   */
  readonly resumePreview: () => Promise<void>;
  
  /**
   * Pause camera preview
   * @returns Promise resolving when preview pauses
   */
  readonly pausePreview: () => Promise<void>;
}

Type Definitions

Core types used by the camera component.

type CameraType = 'front' | 'back';

type FlashMode = 'off' | 'on' | 'auto';

type CameraMode = 'picture' | 'video';

type CameraRatio = '4:3' | '16:9' | '1:1';

type FocusMode = 'on' | 'off';

type VideoQuality = '2160p' | '1080p' | '720p' | '480p' | '4:3';

type VideoCodec = 'avc1' | 'hvc1' | 'jpeg' | 'apcn' | 'ap4h';

type VideoStabilization = 'off' | 'standard' | 'cinematic' | 'auto';

type CameraOrientation = 'portrait' | 'portraitUpsideDown' | 'landscapeLeft' | 'landscapeRight';

interface CameraMountError {
  message: string;
}

interface ResponsiveOrientationChanged {
  orientation: CameraOrientation;
}

interface AvailableLenses {
  lenses: string[];
}

interface BarcodeSettings {
  barcodeTypes: BarcodeType[];
}

interface ScanningOptions {
  /**
   * Array of barcode types to scan for
   */
  barcodeTypes: BarcodeType[];
  
  /**
   * Whether pinch-to-zoom gesture is enabled (iOS only)
   * @default true
   */
  isPinchToZoomEnabled?: boolean;
  
  /**
   * Whether guidance text appears over video (iOS only)  
   * @default true
   */
  isGuidanceEnabled?: boolean;
  
  /**
   * Whether highlights appear around recognized items (iOS only)
   * @default false
   */
  isHighlightingEnabled?: boolean;
}

interface ScanningResult {
  /**
   * The barcode type
   */
  type: string;
  
  /**
   * The parsed information encoded in the barcode
   */
  data: string;
  
  /**
   * The raw information encoded in the barcode (Android only)
   */
  raw?: string;
}

Usage Examples

Basic Camera Setup

import React, { useRef } from 'react';
import { View, StyleSheet } from 'react-native';
import { CameraView, CameraType } from 'expo-camera';

export function BasicCamera() {
  const cameraRef = useRef<CameraView>(null);

  return (
    <View style={styles.container}>
      <CameraView
        ref={cameraRef}
        style={styles.camera}
        facing="back"
        flash="off"
        mode="picture"
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  camera: { flex: 1 },
});

Advanced Camera Configuration

import React, { useState, useRef } from 'react';
import { View, StyleSheet } from 'react-native';
import { CameraView, CameraType, FlashMode, VideoQuality } from 'expo-camera';

export function AdvancedCamera() {
  const [facing, setFacing] = useState<CameraType>('back');
  const [flash, setFlash] = useState<FlashMode>('off');
  const [zoom, setZoom] = useState(0);
  const cameraRef = useRef<CameraView>(null);

  const handleCameraReady = () => {
    console.log('Camera is ready');
  };

  const handleMountError = (error: { message: string }) => {
    console.error('Camera mount error:', error.message);
  };

  return (
    <View style={styles.container}>
      <CameraView
        ref={cameraRef}
        style={styles.camera}
        facing={facing}
        flash={flash}
        zoom={zoom}
        mode="picture"
        animateShutter={true}
        enableTorch={false}
        mirror={facing === 'front'}
        videoQuality="1080p"
        videoBitrate={10000000}
        onCameraReady={handleCameraReady}
        onMountError={handleMountError}
        barcodeScannerSettings={{
          barcodeTypes: ['qr', 'ean13', 'code128']
        }}
      />
    </View>
  );
}

const styles = StyleSheet.create({
  container: { flex: 1 },
  camera: { flex: 1 },
});

Using Component Ref Methods

import React, { useRef } from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
import { CameraView } from 'expo-camera';

export function CameraWithControls() {
  const cameraRef = useRef<CameraView>(null);

  const getAvailableSizes = async () => {
    if (cameraRef.current) {
      const sizes = await cameraRef.current.getAvailablePictureSizes();
      console.log('Available picture sizes:', sizes);
    }
  };

  const getAvailableLenses = async () => {
    if (cameraRef.current) {
      try {
        const lenses = await cameraRef.current.getAvailableLenses();
        console.log('Available lenses:', lenses);
      } catch (error) {
        console.log('Lenses not supported on this platform');
      }
    }
  };

  const togglePreview = async () => {
    if (cameraRef.current) {
      // Example: pause and resume preview
      await cameraRef.current.pausePreview();
      setTimeout(async () => {
        await cameraRef.current?.resumePreview();
      }, 2000);
    }
  };

  return (
    <View style={{ flex: 1 }}>
      <CameraView
        ref={cameraRef}
        style={{ flex: 1 }}
        facing="back"
      />
      <View style={{ flexDirection: 'row', justifyContent: 'space-around', padding: 20 }}>
        <TouchableOpacity onPress={getAvailableSizes}>
          <Text>Get Sizes</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={getAvailableLenses}>
          <Text>Get Lenses</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={togglePreview}>
          <Text>Toggle Preview</Text>
        </TouchableOpacity>
      </View>
    </View>
  );
}

Using Static Methods

import React, { useEffect, useState } from 'react';
import { View, Text, TouchableOpacity, Platform } from 'react-native';
import { CameraView, VideoCodec, ScanningResult } from 'expo-camera';

export function CameraCapabilities() {
  const [isCameraAvailable, setIsCameraAvailable] = useState<boolean | null>(null);
  const [videoCodecs, setVideoCodecs] = useState<VideoCodec[]>([]);
  const [isModernScannerAvailable, setIsModernScannerAvailable] = useState(false);

  useEffect(() => {
    checkCameraCapabilities();
  }, []);

  const checkCameraCapabilities = async () => {
    // Check camera availability (Web only)
    if (Platform.OS === 'web') {
      try {
        const available = await CameraView.isAvailableAsync();
        setIsCameraAvailable(available);
      } catch (error) {
        console.log('Camera availability check not supported');
      }
    }

    // Check available video codecs (iOS only)
    if (Platform.OS === 'ios') {
      try {
        const codecs = await CameraView.getAvailableVideoCodecsAsync();
        setVideoCodecs(codecs);
      } catch (error) {
        console.log('Video codecs not available');
      }
    }

    // Check modern scanner availability
    setIsModernScannerAvailable(CameraView.isModernBarcodeScannerAvailable);
  };

  const launchScanner = async () => {
    if (Platform.OS === 'ios' && CameraView.isModernBarcodeScannerAvailable) {
      try {
        // Listen for scan results
        const subscription = CameraView.onModernBarcodeScanned((result: ScanningResult) => {
          console.log('Scanned:', result.data);
          subscription.remove();
        });

        // Launch the scanner
        await CameraView.launchScanner({
          barcodeTypes: ['qr', 'ean13'],
          isPinchToZoomEnabled: true,
          isGuidanceEnabled: true,
          isHighlightingEnabled: true,
        });
      } catch (error) {
        console.error('Failed to launch scanner:', error);
      }
    }
  };

  return (
    <View style={{ flex: 1, padding: 20 }}>
      <Text>Camera Available: {isCameraAvailable?.toString() ?? 'N/A'}</Text>
      <Text>Video Codecs: {videoCodecs.join(', ') || 'N/A'}</Text>
      <Text>Modern Scanner: {isModernScannerAvailable.toString()}</Text>
      
      {isModernScannerAvailable && (
        <TouchableOpacity onPress={launchScanner} style={{ marginTop: 20, padding: 10, backgroundColor: 'blue' }}>
          <Text style={{ color: 'white' }}>Launch Scanner</Text>
        </TouchableOpacity>
      )}
      
      <CameraView style={{ flex: 1, marginTop: 20 }} facing="back" />
    </View>
  );
}

Platform-Specific Features

import React, { useRef } from 'react';
import { Platform } from 'react-native';
import { CameraView, VideoStabilization } from 'expo-camera';

export function PlatformSpecificCamera() {
  const cameraRef = useRef<CameraView>(null);

  const iosSpecificProps = Platform.OS === 'ios' ? {
    autofocus: 'on' as const,
    active: true,
    selectedLens: 'builtInWideAngleCamera',
    videoStabilizationMode: 'standard' as VideoStabilization,
    responsiveOrientationWhenOrientationLocked: true,
  } : {};

  const androidSpecificProps = Platform.OS === 'android' ? {
    ratio: '16:9' as const,
  } : {};

  const webSpecificProps = Platform.OS === 'web' ? {
    poster: 'https://example.com/camera-loading.png',
  } : {};

  return (
    <CameraView
      ref={cameraRef}
      style={{ flex: 1 }}
      facing="back"
      {...iosSpecificProps}
      {...androidSpecificProps}
      {...webSpecificProps}
    />
  );
}