@kopexa/pdf-viewer
v1.0.8
Published
A PDF viewer component powered by react-pdf
Readme
@kopexa/pdf-viewer
A PDF viewer component powered by react-pdf with smooth loading transitions, i18n support, and text selection.
Part of the Kopexa Sight Design System.
- Author: Kopexa (https://kopexa.com)
- License: Apache-2.0
- Repository: kopexa-grc/sight
Installation
pnpm add @kopexa/pdf-viewer react-pdf pdfjs-dist motionPeer Dependencies
| Package | Version |
| ----------- | ------------ |
| react | >=19.0.0 |
| react-dom | >=19.0.0 |
| react-pdf | >=9.0.0 |
| motion | >=12.23.6 |
Usage
Worker Configuration
You must configure the PDF.js worker before rendering any PDFViewer. Call configurePDFWorker() once at application startup.
import { configurePDFWorker } from "@kopexa/pdf-viewer";
// Option 1: CDN (simplest, no bundler config needed)
configurePDFWorker();
// Option 2: Local worker via import.meta.url (recommended for production)
configurePDFWorker(
new URL("pdfjs-dist/build/pdf.worker.min.mjs", import.meta.url).toString()
);
// Option 3: Custom URL (e.g. self-hosted worker)
configurePDFWorker("https://cdn.example.com/pdf.worker.min.mjs");Basic Example
import { configurePDFWorker, PDFViewer } from "@kopexa/pdf-viewer";
configurePDFWorker();
function MyPage() {
return (
<PDFViewer
source={{ type: "url", url: "/document.pdf" }}
onDocumentLoad={(doc) => console.log(`Loaded ${doc.numPages} pages`)}
/>
);
}With Next.js (App Router)
Since pdfjs-dist requires browser APIs, use next/dynamic with ssr: false:
"use client";
import dynamic from "next/dynamic";
const PDFViewer = dynamic(
() =>
import("@kopexa/pdf-viewer").then((mod) => {
mod.configurePDFWorker(
new URL("pdfjs-dist/build/pdf.worker.min.mjs", import.meta.url).toString()
);
return { default: mod.PDFViewer };
}),
{ ssr: false }
);
export default function Page() {
return <PDFViewer source={{ type: "url", url: "/sample.pdf" }} />;
}Lazy-Loaded Variant
PDFViewerLazy wraps the viewer in React.lazy + ClientOnly so it only loads on the client with built-in loading state:
import { configurePDFWorker, PDFViewerLazy } from "@kopexa/pdf-viewer";
configurePDFWorker();
function MyPage() {
return <PDFViewerLazy source={{ type: "url", url: "/document.pdf" }} />;
}PDF Source Types
// URL (react-pdf fetches internally)
<PDFViewer source={{ type: "url", url: "/report.pdf" }} />
// Binary data
<PDFViewer source={{ type: "data", data: myUint8Array }} />
// Base64-encoded string
<PDFViewer source={{ type: "base64", data: base64String }} />Features
- Smooth transitions — Animated fade from loading state to rendered pages via
motion - Text selection — Text and annotation layers are enabled by default
- i18n — All user-facing strings are translatable via
@kopexa/i18n(EN + DE included) - Responsive — Pages scale to container width automatically
- Click tracking —
onPageClickprovides page-relative coordinates - Custom renderers — Pass
customPageRendererfor custom page rendering - Error handling — Built-in error state with customizable content
Props
| Prop | Type | Description |
| -------------------- | ------------------------------------------ | ---------------------------------------------- |
| source | PDFSource | The PDF source (url, data, or base64) |
| className | string | CSS class for the root element |
| onDocumentLoad | (doc: LoadedPDFDocument) => void | Called when the document finishes loading |
| onPageClick | OnPDFViewerPageClick | Called with page-relative click coordinates |
| customPageRenderer | React.FunctionComponent | Custom page renderer component |
| options | Record<string, unknown> | PDF.js document options (e.g. cMapUrl) |
| loadingContent | React.ReactNode | Custom loading state content |
| errorContent | React.ReactNode | Custom error state content |
| pageLabel | (page: number, total: number) => ReactNode | Custom page label renderer |
Contribution
Yes please! See the contributing guidelines for details.
License
This project is licensed under the terms of the Apache-2.0 license.
