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

react-native-view-capture

v1.0.0

Published

Zero-dependency utilities for React Native view capture — options builders, format helpers, URI/base64 converters, dimension tools, filename generators, share payloads

Readme

react-native-view-capture

Zero-dependency utilities for React Native view capture.

Options builders, format/MIME helpers, URI & base64 converters, dimension scaling, crop helpers, filename generators, share payloads, watermark configs, native module bridge, batch capture, retry logic, and React hook factories — the full JavaScript layer for capturing views in React Native.

npm install react-native-view-capture

Native module required for captureRef and captureScreen. Wire up your native module with registerNativeModule(). All other utilities are pure JS and work anywhere.


Setup

import { NativeModules } from 'react-native';
import { registerNativeModule } from 'react-native-view-capture';

// Register once at app startup (e.g. index.js)
registerNativeModule(NativeModules.RNViewCapture);

Capturing a view

import { useRef } from 'react';
import { View, Button } from 'react-native';
import { captureRef } from 'react-native-view-capture';

function MyScreen() {
  const ref = useRef(null);

  async function onCapture() {
    const uri = await captureRef(ref, { format: 'jpg', quality: 0.9 });
    console.log(uri); // file:///tmp/capture_20240615_143022.jpg
  }

  return (
    <>
      <View ref={ref}>
        {/* … */}
      </View>
      <Button title="Capture" onPress={onCapture} />
    </>
  );
}

captureRef(ref, opts?)

| Option | Type | Default | Description | |---|---|---|---| | format | 'png' \| 'jpg' \| 'webp' | 'png' | Output format | | quality | number 0–1 | 1.0 | JPEG/WebP quality | | result | 'tmpfile' \| 'file' \| 'base64' \| 'data-uri' | 'tmpfile' | Where to return the result | | width | number | — | Override output width | | height | number | — | Override output height | | path | string | — | Output path when result: 'file' | | snapshotContentContainer | boolean | false | Capture full scroll content | | useRenderInContext | boolean | false | iOS: avoid GPU surfaces | | handleGLSurfaceViewOnAndroid | boolean | false | Android GL surfaces |

captureScreen(opts?)

Same options as captureRef, captures the entire screen.

releaseCapture(uri)

Release a temp file once you're done with it.


Hook factory

import { useRef, useCallback } from 'react';
import { createUseViewCapture } from 'react-native-view-capture';

const useViewCapture = createUseViewCapture({ useRef, useCallback });

function MyComponent() {
  const { ref, capture } = useViewCapture({ format: 'png' });

  return (
    <View ref={ref}>
      <Button title="Save" onPress={() => capture()} />
    </View>
  );
}

Capture history hook

import { useState, useCallback } from 'react';
import { createUseCaptureHistory } from 'react-native-view-capture';

const useCaptureHistory = createUseCaptureHistory({ useState, useCallback });

function GalleryScreen() {
  const { history, push, clear, last } = useCaptureHistory(10);

  async function onCapture() {
    const uri = await captureRef(ref);
    push(uri);
  }
}

Batch capture

import { captureRefs, captureRefWithRetry } from 'react-native-view-capture';

// Capture multiple refs in sequence
const uris = await captureRefs([refA, refB, refC], { format: 'jpg' }, { delayMs: 100 });

// Retry on failure
const uri = await captureRefWithRetry(ref, { format: 'png' }, { retries: 3, retryDelayMs: 200 });

Options builder

import { buildCaptureOptions, defaultCaptureOptions } from 'react-native-view-capture';

const opts = buildCaptureOptions({ format: 'jpg', quality: 0.85 });
// Validates quality range, unknown format, dimension signs
// Throws RangeError / TypeError on invalid input

Format helpers

import { mimeTypeForFormat, extensionForMime, formatFromExtension, formatFromMime } from 'react-native-view-capture';

mimeTypeForFormat('jpg')          // 'image/jpeg'
mimeTypeForFormat('png')          // 'image/png'
extensionForMime('image/jpeg')    // 'jpg'
formatFromExtension('photo.webp') // 'webp'
formatFromMime('image/png')       // 'png'

URI / base64 utilities

import {
  isDataUri, isFileUri, isBase64,
  base64ToDataUri, dataUriToBase64, mimeFromDataUri,
  parseDataUri, normaliseCaptureResult,
} from 'react-native-view-capture';

isFileUri('file:///tmp/cap.png')  // true
isDataUri('data:image/png;base64,...') // true
isBase64('iVBORw0KGgoAAAANSUhEUgAA...') // true

base64ToDataUri(b64, 'png')       // 'data:image/png;base64,...'
dataUriToBase64(dataUri)          // raw base64 string
mimeFromDataUri(dataUri)          // 'image/png'
parseDataUri(dataUri)             // { mime: 'image/png', base64: '...' }

// Normalise any result into a unified object
normaliseCaptureResult(uri, 'jpg')
// { type: 'file', uri: 'file:///...', mime: 'image/jpeg' }
// { type: 'base64', base64: '...', uri: 'data:...', mime: 'image/jpeg' }
// { type: 'dataUri', uri: 'data:...', base64: '...', mime: 'image/png' }

Dimension helpers

import { scaleDimensions, coverDimensions, normaliseCropRect, absoluteCropRect, aspectRatioString, estimateFileSize } from 'react-native-view-capture';

// Fit within a 800×600 box
scaleDimensions(1920, 1080, 800, 600)
// { width: 800, height: 450, scale: 0.416 }

// Cover a 400×400 thumbnail
coverDimensions(1920, 1080, 400, 400)
// { width: 711, height: 400, scale: 0.37 }

// Normalised crop rect
normaliseCropRect(100, 50, 300, 200, 1200, 800)
// { x: 0.083, y: 0.0625, width: 0.25, height: 0.25 }

aspectRatioString(1920, 1080)  // '16:9'
aspectRatioString(1, 1)        // '1:1'

estimateFileSize(1080, 1920, 'jpg', 0.85) // ~45000 bytes
estimateFileSize(1080, 1920, 'png')       // ~3110400 bytes

Filename and path helpers

import { generateFilename, buildFileUri, filenameFromUri, replaceExtension } from 'react-native-view-capture';

generateFilename()                           // 'capture_20240615_143022.png'
generateFilename({ prefix: 'shot', format: 'jpg', suffix: 'home' })
// 'shot_20240615_143022_home.jpg'

buildFileUri('/tmp/captures', 'shot.png')    // 'file:///tmp/captures/shot.png'
filenameFromUri('file:///tmp/cap_123.jpg')   // 'cap_123.jpg'
replaceExtension('capture.png', 'webp')      // 'capture.webp'

Share & export

import { buildSharePayload, buildCameraRollOptions } from 'react-native-view-capture';
import { Share } from 'react-native';

const payload = buildSharePayload(uri, { message: 'Check this out!', title: 'My capture' });
await Share.share(payload);

// CameraRoll
import CameraRoll from '@react-native-camera-roll/camera-roll';
const opts = buildCameraRollOptions(uri, { album: 'My App' });
await CameraRoll.save(uri, opts);

Watermark config

import { buildWatermarkConfig, watermarkPosition } from 'react-native-view-capture';

const wm = buildWatermarkConfig('© MyApp 2024', {
  position: 'bottom-right',
  fontSize: 12,
  color: '#ffffff',
  opacity: 0.6,
  padding: 12,
});

const anchor = watermarkPosition('bottom-right', 1080, 1920, 12);
// { x: 1068, y: 1908, anchor: 'right' }

CommonJS

const { captureRef, buildCaptureOptions, normaliseCaptureResult } = require('react-native-view-capture');

License

MIT