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-pdfrender

v0.1.6

Published

React Native PDF rendering library with TurboModules and Fabric components

Readme

react-native-pdfrender

A production-ready React Native PDF rendering library built on the New Architecture (TurboModules + Fabric components).

  • Embedded viewer — drop <PdfViewerView /> anywhere in your render tree
  • Imperative viewer — use the usePdfViewer hook to open a modal-style PDF viewer
  • Native rendering — CGPDFDocument / Core Graphics on iOS, Android PdfRenderer on Android
  • Jetpack Compose — modern Android UI, no XML layouts
  • Codegen-driven — TypeScript specs generate type-safe native bindings at build time
  • Zero JS dependencies — no third-party npm packages required at runtime

Requirements

| Platform | Minimum version | |----------|----------------| | React Native | 0.70+ | | iOS | 13.0+ | | Android | SDK 24+ (Android 7.0) | | Node | 18+ |


Installation

npm install react-native-pdfrender
# or
yarn add react-native-pdfrender

iOS

cd ios && pod install

Android

No extra steps — auto-linking handles it.


Usage

1. Declarative (embedded viewer)

import { PdfViewerView } from 'react-native-pdfrender';

function MyScreen() {
  return (
    <PdfViewerView
      uri="file:///path/to/document.pdf"
      initialPage={0}
      defaultZoom={1.5}
      isFullScreen={false}
      style={{ flex: 1 }}
      onZoomChange={(pct) => console.log('zoom:', pct)}
      onFullScreenChange={(fs) => setFullScreen(fs)}
    />
  );
}

2. Imperative (hook — modal viewer)

import { usePdfViewer } from 'react-native-pdfrender';

function MyScreen() {
  const { open, dismiss, getPageCount, createPdf } = usePdfViewer({
    onFullScreenChanged: (isFS) => console.log('fullscreen:', isFS),
    onZoomChanged: (zoom) => console.log('zoom:', zoom),
    onDismiss: () => console.log('viewer closed'),
  });

  return (
    <>
      <Button title="Open PDF" onPress={() => open('file:///path/to/doc.pdf')} />
      <Button title="Dismiss"  onPress={dismiss} />
      <Button title="Page count" onPress={async () => {
        const n = await getPageCount('file:///path/to/doc.pdf');
        console.log('pages:', n);
      }} />
    </>
  );
}

API

<PdfViewerView />

| Prop | Type | Default | Description | |------|------|---------|-------------| | uri | string | required | file:// or content:// path to the PDF | | initialPage | number | -1 (first) | 0-based page index to open on | | defaultZoom | number | 1.5 | Initial zoom level (1.0 = 100%) | | isFullScreen | boolean | false | Fills the parent container when true | | rightLayout | boolean | false | Positions viewer on right side (split-view) | | maxWidth | number | — | Max pixel width (split-view) | | screenWidthPercentage | number | 100 | % of screen width | | icons | IconSet | — | Custom toolbar icon assets | | iconSize | number | 40 | Icon size in logical pixels | | backButtonText | string | — | Toolbar back button label | | headerText | string | — | Toolbar header label | | style | ViewStyle | — | Container style | | onFullScreenChange | (isFullScreen: boolean) => void | — | Fires when fullscreen state changes | | onZoomChange | (zoomPercentage: number) => void | — | Fires when zoom changes | | onLeftScreenChange | (isLeftScreen: boolean) => void | — | Fires in split-view | | onRightScreenChange | (isRightScreen: boolean) => void | — | Fires in split-view |

IconSet

interface IconSet {
  zoomIn?:         number | string; // require('./zoom_in.png') or URI
  zoomOut?:        number | string;
  fullScreen?:     number | string;
  minimizeScreen?: number | string;
  leftLayout?:     number | string;
  rightLayout?:    number | string;
}

usePdfViewer(options?)

interface UsePdfViewerOptions {
  onFullScreenChanged?: (isFullScreen: boolean) => void;
  onZoomChanged?:       (zoomPercentage: number) => void;
  onDismiss?:           () => void;
  onError?:             (error: string) => void;
}

interface UsePdfViewerReturn {
  open:        (uri: string, pageIndex?: number, defaultZoom?: number) => void;
  dismiss:     () => void;
  getPageCount:(uri: string) => Promise<number>;
  createPdf:   (pages: PdfPage[], widthPx: number, heightPx: number) => Promise<PdfCreationResult>;
}

NativePdfViewerModule (low-level TurboModule)

Exposed for advanced use cases. Prefer usePdfViewer for most scenarios.

import { NativePdfViewerModule } from 'react-native-pdfrender';

NativePdfViewerModule.openPdfViewer(uri, pageIndex, defaultZoom);
NativePdfViewerModule.dismissPdfViewer();
const count = await NativePdfViewerModule.getPdfPageCount(uri);
const result = await NativePdfViewerModule.createMultiPagePdfBase64(pages, width, height);

Architecture

react-native-pdfrender/
├── android/
│   ├── build.gradle                  ← library module (com.android.library)
│   └── src/main/java/com/pdfrender/
│       ├── PdfViewerTurboModule.kt   ← TurboModule (imperative API)
│       ├── PdfViewerFabricManager.kt ← Fabric ViewManager (embedded viewer)
│       ├── PdfViewerFragment.kt      ← modal viewer Fragment
│       ├── PdfRenderingLogic.kt      ← Android PdfRenderer wrapper
│       ├── ComposeRenderer.kt        ← Jetpack Compose UI
│       └── events/                   ← Fabric event classes
├── ios/
│   ├── PdfViewerTurboModule.mm       ← ObjC++ TurboModule bridge
│   ├── PdfViewerTurboModuleImpl.swift ← Swift business logic
│   ├── PdfViewerComponentView.mm     ← ObjC++ Fabric ViewManager
│   ├── PdfViewerView.swift           ← main PDF rendering view
│   ├── PdfRenderingLogic.swift       ← CGPDFDocument wrapper
│   └── ...
├── src/
│   ├── index.tsx                     ← public API exports
│   ├── PdfViewerView.tsx             ← React component
│   ├── usePdfViewer.ts               ← hook
│   └── specs/
│       ├── NativePdfViewerModule.ts  ← TurboModule codegen spec
│       └── NativePdfViewerComponent.ts ← Fabric codegen spec
├── lib/                              ← compiled output (generated by bob)
├── example/                          ← example React Native app
└── react-native-pdfrender.podspec

New Architecture (codegen)

The codegenConfig in package.json points to src/specs/. At build time:

  • iOS — CocoaPods generates PdfViewerSpecs.h and the Fabric C++ headers
  • Android — Gradle generates the abstract NativePdfViewerModuleSpec Kotlin class

Building the library

# Install deps
yarn install

# Compile TypeScript → lib/
yarn build
# runs automatically as `prepare` before npm publish

# Type-check only
yarn typecheck

Running the example app

Install dependencies

# Library deps
yarn install

# Example deps
cd example && yarn install

iOS (one-time Xcode project cleanup required)

The example Xcode project was migrated from the original monolithic app and still includes the library Swift files in the app target. Because CocoaPods now compiles those same files as part of the library pod, you must remove them from the app target first to avoid duplicate-symbol errors:

  1. Open example/ios/pdfRender.xcodeproj in Xcode
  2. Select the pdfRender app target → Build PhasesCompile Sources
  3. Remove these files (click each, press ):
    • PdfViewerView.swift, PdfViewerViewController.swift
    • PdfViewerTurboModuleImpl.swift, PdfRenderingLogic.swift
    • PdfPageView.swift, PdfToolbarView.swift
    • PdfCacheManager.swift, PdfConstants.swift
    • PdfViewerTurboModule.mm, PdfViewerComponentView.mm
  4. Save the Xcode project, then:
cd example/ios && pod install && cd ../..
yarn example:ios

Android

yarn example:android

Publishing to npm

# Build the library
yarn prepare

# Verify what will be published
npm pack --dry-run

# Publish publicly
npm publish --access public

Common Issues

PdfViewerSpecs/PdfViewerSpecs.h not found (iOS build)

Run pod install inside example/ios/ (or the consuming app's ios/). This triggers codegen which produces the PdfViewerSpecs headers.

Duplicate symbol errors on iOS

Follow the Xcode project cleanup steps above.

NativePdfViewerModuleSpec not found (Android)

Run the app once — Gradle auto-generates the spec. Or run manually:

cd example/android && ./gradlew generateCodegenArtifactsFromSchema

Metro can't resolve react-native-pdfrender

Run yarn install inside example/ (not just the root). The file:../ entry creates a symlink in example/node_modules/react-native-pdfrender that Metro follows.


License

MIT © Shubham Keshari