npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@pigayazilim/react-native-camera

v1.0.5

Published

Reusable React Native camera module with photo/video capture, trimming, GIF export and image cropping

Readme

Camera Module

A reusable React Native camera module with photo/video capture, gallery access, video trimming, GIF export, and image cropping. Works on both Android and iOS with zero extra packages — all video processing is done via native platform APIs (ExoPlayer/Media3 on Android, AVFoundation on iOS).

Features

  • Photo & video capture with flash support
  • Pinch-to-zoom and double-tap to flip camera
  • Multi-select mode for batch photo/video selection
  • Gallery access (CameraRoll)
  • Video trimming and GIF export (Android: Media3, iOS: AVFoundation + ImageIO)
  • Image crop overlay
  • Fully themeable via ThemeProvider
  • Customizable UI labels (i18n friendly)

Installation

1. Install the package

npm install @pigayazilim/react-native-camera
# or
yarn add @pigayazilim/react-native-camera

2. Install peer dependencies

npm install \
  @react-native-camera-roll/camera-roll \
  react-native-gesture-handler \
  react-native-reanimated \
  react-native-worklets \
  react-native-safe-area-context \
  react-native-svg \
  react-native-svg-transformer \
  react-native-vision-camera

3. Verify autolinking

npx react-native autolinking-status

You should see camera-module listed and linked for both Android and iOS.


Native Setup

Android

android/app/src/main/AndroidManifest.xml

Add the following permissions inside <manifest>:

<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />

<!-- API 33+ -->
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />

<!-- API < 33 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
    android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="29" />

android/app/build.gradle

Ensure minSdkVersion is at least 24:

android {
    defaultConfig {
        minSdkVersion 24
    }
}

Note: If autolinking doesn't add the module automatically, add this to android/settings.gradle:

include ':camera-module'
project(':camera-module').projectDir = new File(rootProject.projectDir, '../modules/camera/android')

iOS

ios/YourApp/Info.plist

Add the following permission descriptions:

<key>NSCameraUsageDescription</key>
<string>This app needs camera access to take photos and videos.</string>

<key>NSMicrophoneUsageDescription</key>
<string>This app needs microphone access to record videos.</string>

<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs photo library access to select media.</string>

<key>NSPhotoLibraryAddUsageDescription</key>
<string>This app needs permission to save photos to your library.</string>

Install Pods

cd ios && bundle exec pod install && cd ..

Build Config Setup

babel.config.js

react-native-reanimated plugin must be the last plugin:

module.exports = {
  presets: ['module:@react-native/babel-preset'],
  plugins: [
    // ... your other plugins
    'react-native-reanimated/plugin',
  ],
};

metro.config.js

Configure react-native-svg-transformer for SVG support:

const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const { withSVGTransformer } = require('react-native-svg-transformer/react-native');

module.exports = mergeConfig(
  withSVGTransformer(getDefaultConfig(__dirname)),
  {
    // your other metro config
  }
);

declarations.d.ts (TypeScript only)

Add SVG module declaration to your project:

declare module '*.svg' {
  import React from 'react';
  import { SvgProps } from 'react-native-svg';
  const content: React.FC<SvgProps>;
  export default content;
}

Wrapping Your App

Your app's root must be wrapped with GestureHandlerRootView and SafeAreaProvider:

import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { SafeAreaProvider } from 'react-native-safe-area-context';

export default function Root() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <SafeAreaProvider>
        <App />
      </SafeAreaProvider>
    </GestureHandlerRootView>
  );
}

Usage

import { CameraModal, usePermissions } from '@pigayazilim/react-native-camera';

export default function MyScreen() {
  const [cameraVisible, setCameraVisible] = useState(false);
  const { hasAllPermissions, checkAndRequestPermissions } = usePermissions();

  const handleOpen = async () => {
    await checkAndRequestPermissions();
    setCameraVisible(true);
  };

  const handleConfirm = (media: Array<{ uri: string; type: string; name: string }>) => {
    console.log('Selected media:', media);
    setCameraVisible(false);
  };

  return (
    <>
      <Button title="Open Camera" onPress={handleOpen} />

      <CameraModal
        visible={cameraVisible}
        onClose={() => setCameraVisible(false)}
        onConfirm={handleConfirm}
        permissionGranted={hasAllPermissions}
        maxVideoDuration={60}
      />
    </>
  );
}

API

<CameraModal />

| Prop | Type | Required | Default | Description | |------|------|----------|---------|-------------| | visible | boolean | Yes | — | Controls modal visibility | | onClose | () => void | Yes | — | Called when modal is dismissed | | onConfirm | (media: MediaItem[]) => void | Yes | — | Called with selected media array | | permissionGranted | boolean | Yes | — | Whether camera/mic permissions are granted | | maxVideoDuration | number | No | 60 | Max video recording duration in seconds | | theme | Partial<ThemeColors> | No | — | Override default theme colors | | labels | Partial<CameraLabels> | No | — | Override default Turkish UI labels |

MediaItem (returned in onConfirm)

{
  uri: string;    // File URI
  type: string;   // "image/jpeg" | "image/png" | "video/mp4"
  name: string;   // e.g. "chatPhoto_1234567890.jpeg"
}

usePermissions()

const {
  hasAllPermissions,           // boolean — all required permissions granted
  isChecking,                  // boolean — permission check in progress
  hasCameraPermission,         // boolean — camera only
  hasMicPermission,            // boolean — microphone only
  checkAndRequestPermissions,  // () => Promise<boolean> — trigger request
} = usePermissions();

<ThemeProvider />

Wrap your screen (or the whole app) to apply a custom theme:

import { ThemeProvider } from '@pigayazilim/react-native-camera';

<ThemeProvider colors={{ primary: '#FF6B00', gold: '#FFC300' }}>
  <CameraModal ... />
</ThemeProvider>

ThemeColors

{
  primary: string;
  white: string;
  black: string;
  error: string;
  gold: string;
  overlay: string;
  surface: string;
  border: string;
  shadow: string;
  textSecondary: string;
  redSoft: string;
  redMedium: string;
}

CameraLabels

Override any UI text (all optional, Turkish defaults):

type CameraLabels = {
  photoMode?: string;              // default: "FOTOĞRAF"
  videoMode?: string;              // default: "VİDEO"
  permissionDenied?: string;       // default: "Kamera izni verilmedi."
  cameraNotFound?: string;         // default: "Kamera bulunamadı."
  cameraStarting?: string;         // default: "Kamera başlatılıyor..."
  errorTitle?: string;             // default: "Hata"
  micPermissionError?: string;     // default: "Video çekmek için mikrofon izni gerekli."
  recordingError?: string;         // default: "Video kaydı sırasında bir sorun oluştu"
  selectionConflictError?: string; // default: "Öncelikle seçili medyayı onaylamalı veya iptal etmelisiniz."
};

Example — English labels:

<CameraModal
  ...
  labels={{
    photoMode: 'PHOTO',
    videoMode: 'VIDEO',
    permissionDenied: 'Camera permission denied.',
    cameraNotFound: 'No camera found.',
    cameraStarting: 'Starting camera...',
    errorTitle: 'Error',
    micPermissionError: 'Microphone permission is required to record video.',
    recordingError: 'An error occurred during video recording.',
    selectionConflictError: 'Please confirm or cancel your current selection first.',
  }}
/>

Native Video Processing

| Feature | Android | iOS | |---------|---------|-----| | Video playback | ExoPlayer (Media3) | AVPlayer | | Video trim | Media3 Transformer | AVAssetExportSession | | GIF export | Custom GifEncoder | CGImageDestination (ImageIO) | | Thumbnails | MediaMetadataRetriever | AVAssetImageGenerator | | Image crop | BitmapRegionDecoder | CGImage.cropping |

All native code is bundled in the android/ and ios/ folders. No external npm packages are required for video processing.