custom-react-pdf-viewer
v4.0.1
Published
A production-ready React wrapper around PDF.js with toolbar and find bar, licensed under Apache 2.0
Maintainers
Readme
custom-react-pdf-viewer
A production-ready React wrapper around Mozilla's pdf.js that provides a "drop-in" PDF viewer with a fully-featured toolbar, find bar, and automatic state persistence.

Features
- Batteries Included: Full toolbar with page navigation, zoom, rotation, print, download, and fullscreen out of the box.
- State Persistence: Automatically saves and restores scroll position (precise ratio), zoom level, and rotation for each document.
- Find Bar:
Ctrl+F/Cmd+Fsupport with highlighting, match case, and whole word options. - Feature Flags: Easily opt-out of specific features (e.g., disable rotation or the toolbar) via props.
- Simple API: Just pass a
File,Blob, or URL string. - TypeScript: First-class type definitions included.
Installation
# npm
npm install custom-react-pdf-viewer
# pnpm
pnpm add custom-react-pdf-viewer
# yarn
yarn add custom-react-pdf-viewerRequirements:
reactandreact-dom(>=18 <20) are peer dependencies — provide them from your app (you almost certainly already have them).pdf.jsis pulled in automatically as a pinned dependency, so there's nothing extra to install; it's pinned to an exact version (currently6.0.227) rather than a range because the viewer integrates deeply withpdf.jsinternals and ships its stylesheet built against that exact release, so it's bumped deliberately with each version.
Usage
Level 1: The Simplest Use-Case
If you just want to render a PDF without worrying about state or persistence, simply import the component and pass it a file.
Note:* The viewer is designed to fill 100% of the width and height of its parent container. Ensure the parent element has a defined height (e.g., 100vh, 500px, or flex: 1).
import { CustomPdfViewer } from "custom-react-pdf-viewer";
import "custom-react-pdf-viewer/style.css"; // Don't forget the styles!
function SimpleViewer({ fileBlob }) {
return (
<div style={{ height: "100vh" }}>
<CustomPdfViewer
file={fileBlob}
fileName="my-document.pdf"
/>
</div>
);
}Level 2: Enabling State Persistence
To automatically remember zoom levels and scroll positions when users switch between documents, you need two things:
- Wrap your app with the
<PdfStoreProvider>. - Give your viewer a unique
viewerId.
Step A: Add the Provider
// src/main.tsx
import { PdfStoreProvider } from "custom-react-pdf-viewer";
<PdfStoreProvider>
<App />
</PdfStoreProvider>Step B: Use the Viewer with an ID
// src/App.tsx
import { CustomPdfViewer } from "custom-react-pdf-viewer";
function App() {
// ... file loading logic ...
return (
<CustomPdfViewer
file={file}
fileName="sample.pdf"
// 1. Required: Unique ID for this UI slot (e.g. "main-viewer", "sidebar")
viewerId="main-pdf-viewer"
// 2. Recommended: Unique ID for the document content
sessionKey="doc-123"
/>
);
}Result: If a user zooms to 150%, switches to another document, and returns to "doc-123", the viewer will automatically restore the zoom level and exact scroll position.
Level 3: Persisting Across Reloads (LocalStorage)
By default, the PdfStoreProvider uses in-memory storage, meaning state is lost on refresh.
To persist state across browser restarts, pass LocalStorageStore to the provider.
import { PdfStoreProvider, LocalStorageStore } from "custom-react-pdf-viewer";
<PdfStoreProvider store={new LocalStorageStore()}>
<App />
</PdfStoreProvider>The component usage (viewerId, sessionKey) remains exactly the same as in Level 2.
Component Props
| Prop | Type | Description |
|--------------------|---------------------------------------|-------------|
| file | Blob \| File \| string \| null | Required. The source of the PDF. |
| fileName | string | Optional. The name shown in the toolbar and used for downloads. |
| documentTitle | string | Optional. Overrides the displayed title. Defaults to fileName. |
| viewerId | string | Required for persistence. Unique identifier for this viewer slot. |
| sessionKey | string | Optional. Identifies the document; if it changes, the viewer treats it as a new document. |
| persistenceStore | PdfPersistenceStore | Optional. Store override for this instance; falls back to the PdfStoreProvider context. |
| disabledFeatures | string[] | Optional. Features to hide: "toolbar", "find", "rotation", "zoom", "pagination", "print", "download". |
| highlightInfo | { [page: number]: string } \| null | Optional. Text to highlight, keyed by page number. |
| jumpToPage | number \| null | Optional. Programmatically scroll to a page. |
| iconSet | IconSet | Optional. Icon set for the toolbar and menu. Defaults to Lucide. |
| toolbarSize | 'sm' \| 'md' \| 'lg' | Optional. Toolbar size preset. Defaults to 'md'. |
| onOpen | () => void | Optional. Wires the menu's "Open" item; omit to hide it. |
| onClose | () => void | Optional. Wires the menu's "Close" item; omit to hide it. |
| allowDownload | boolean | Optional. Allow downloading the document. Default true. |
| allowPrint | boolean | Optional. Allow printing the document. Default true. |
| allowFullscreen | boolean | Optional. Allow toggling fullscreen. Default true. |
Disabling Features
<CustomPdfViewer
file={file}
disabledFeatures={['rotation', 'find']}
/>Styling
:root {
/* Toolbar & Backgrounds */
--custom-pdf-toolbar-bg: #f9f9fa;
--custom-pdf-toolbar-border-color: #b8b8b8;
--custom-pdf-viewer-bg: #f1f5f9;
--custom-pdf-main-color: #181819;
/* Accent Colors */
--custom-pdf-accent-color: #0a84ff;
--custom-pdf-button-hover-color: #ddd;
}License
Apache-2.0 © Roland Arnold
