@pdf-annotator/pdf-annotator
v0.1.9
Published
Framework-agnostic PDF annotation library built on top of PDF.js.
Readme
PDF Annotator
A powerful, production-ready, framework-agnostic PDF annotation library built on top of PDF.js. Designed for high performance, pixel-perfect accuracy, and seamless mobile responsiveness.
🚀 Key Features
- 🛠 Rich Toolset: Professional-grade tools for all your document needs.
- 🖋 Freehand Drawing: High-precision vector paths with variable stroke width.
- 🖍 Highlighter Marker: Semi-transparent freehand marker with natural blend modes.
- 💬 Sticky Notes: Interactive page-relative comments and feedback popups.
- 🧽 Smooth Eraser: Intelligent drag-to-erase workflow for all annotation types.
- 📝 Text Markups: Standard Highlight, Underline, and Strikethrough.
- 📱 Mobile Optimized:
- Auto-Clamping: Intelligent zoom limits (Max 100%) on mobile to preserve layout.
- Touch Ready: Full support for touch gestures, including smooth drag-to-draw and drag-to-erase.
- Adaptive UI: Toolbar and sidebar automatically adjust for smaller viewports.
- 📡 Cloud Persistence:
- Firebase Real-time Sync: Instant synchronization across devices via Realtime Database.
- Cloud Storage Buckets: Direct GCS/Firebase Storage integration for JSON-based file persistence.
- Local Fallback: Built-in
LocalStoragefor offline-first usage.
- 🔍 Advanced Navigation:
- Integrated Search: Fast, highlighted document search with "find next/previous".
- Reading Progress: Subtle top-mounted progress bar and Jump-to-Page navigation.
- Sidebar Outline: Quick access to document metadata and annotations.
- 🌓 Theming:
- Native Dark Mode: Smart inversion that preserves annotation colors while making the PDF eye-friendly.
- CSS Variables: Fully customizable design system via standard CSS variables.
📦 Installation
npm install @pdf-annotator/pdf-annotator🛠 Usage & Plugin System
The library is modular. You only "use" the features you need, keeping your bundle size lean.
🅰️ Angular Implementation (Web)
Use this complete example to set up the viewer in an Angular application:
import { AfterViewInit, Component, ElementRef, OnDestroy, ViewChild } from '@angular/core';
import {
PDFAnnotator,
HighlightPlugin,
UnderlinePlugin,
StrikethroughPlugin,
NotePlugin,
DrawingPlugin,
LocalStorageAdapter,
HighlighterPlugin,
SearchPlugin,
DownloadPlugin,
ThemePlugin,
EraserPlugin
} from 'pdf-annotator';
@Component({
selector: 'app-pdf-viewer',
template: '<div #viewerHost style="height: 100vh;"></div>'
})
export class PdfViewerComponent implements AfterViewInit, OnDestroy {
@ViewChild('viewerHost', { static: true }) viewerHost!: ElementRef<HTMLDivElement>;
private viewer: PDFAnnotator | null = null;
async ngAfterViewInit(): Promise<void> {
const pdfUrl = 'https://example.com/your-document.pdf';
this.viewer = await PDFAnnotator.init(this.viewerHost.nativeElement, {
pdfUrl,
title: 'Percentage Book',
theme: 'light',
sidebar: true,
showBack: false,
showTitle: false,
scale: 1.5, // Initial zoom level (1.5 = 100%)
});
// Persistence with Local Storage
await this.viewer.setStorageAdapter(new LocalStorageAdapter(pdfUrl));
// Load Annotation Plugins
this.viewer.use(HighlightPlugin, { defaultColor: '#FFEB3B' });
this.viewer.use(UnderlinePlugin);
this.viewer.use(StrikethroughPlugin);
this.viewer.use(NotePlugin);
this.viewer.use(DrawingPlugin);
this.viewer.use(HighlighterPlugin);
this.viewer.use(EraserPlugin); // Smooth Erasing
// UI & Utility Plugins
this.viewer.use(SearchPlugin);
this.viewer.use(DownloadPlugin, { filename: 'Annotated_Document.pdf' });
this.viewer.use(ThemePlugin);
}
async ngOnDestroy(): Promise<void> {
if (this.viewer) {
await this.viewer.destroy();
this.viewer = null;
}
}
}⚛️ Mobile Integration (React Native)
To use the library in React Native, use a WebView. This allows you to leverage all features (including the Eraser and Smooth Drawing) with native performance.
import React from 'react';
import { WebView } from 'react-native-webview';
const PDFReader = ({ pdfUrl }) => {
const htmlTemplate = `
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/pdf.min.js"></script>
<style>body { margin:0; padding:0; overflow:hidden; }</style>
</head>
<body>
<div id="viewer" style="width:100vw; height:100vh;"></div>
<script type="module">
import {
PDFAnnotator, HighlightPlugin, DrawingPlugin, HighlighterPlugin,
EraserPlugin, NotePlugin, LocalStorageAdapter
} from 'https://cdn.jsdelivr.net/npm/@pdf-annotator/pdf-annotator/dist/pdf-annotator.es.js';
const viewer = await PDFAnnotator.init('#viewer', {
pdfUrl: '${pdfUrl}',
theme: 'light',
sidebar: true,
showBack: false,
showTitle: false,
scale: 1.5 // Automatically clamped to 1.5 (100%) on mobile
});
await viewer.setStorageAdapter(new LocalStorageAdapter('${pdfUrl}'));
// Plugins
viewer.use(HighlightPlugin);
viewer.use(DrawingPlugin);
viewer.use(HighlighterPlugin);
viewer.use(EraserPlugin);
viewer.use(NotePlugin);
</script>
</body>
</html>
`;
return <WebView originWhitelist={['*']} source={{ html: htmlTemplate }} />;
};📡 Storage Adapters
1. Firebase Cloud Storage (Buckets)
Stores annotations as a JSON file in a GCS/Firebase Storage bucket.
const adapter = new FirebaseCloudStorageAdapter({
bucket: 'your-app.appspot.com',
path: 'annotations/manual_001.json',
authToken: () => getAuth().currentUser?.getIdToken()
});2. Firebase Realtime Database (Cloud Sync)
Provides instant synchronization between devices.
import { CloudSyncPlugin } from 'pdf-annotator';
viewer.use(CloudSyncPlugin, {
databaseURL: 'https://my-app.firebaseio.com',
documentId: 'doc_567'
});3. Local Storage (Default)
Simple, zero-setup persistence in the browser's local storage. Best for single-user offline scenarios.
import { LocalStorageAdapter } from 'pdf-annotator';
// Initialize with a unique key (e.g. PDF URL or ID)
const adapter = new LocalStorageAdapter('unique_pdf_key_or_url');
await viewer.setStorageAdapter(adapter);🎨 Design Customization
:root {
--pa-primary: #3b82f6; /* Active state colors */
--pa-surface: #ffffff; /* Background */
--pa-text: #1e293b; /* Content text */
}📱 Mobile & Scale Best Practices
- Initial Scale: Use
scale: 1.5to set the default zoom to 100%. The library uses a base scale of 1.5 to represent standard 100% resolution. - Mobile Zoom Cap: On mobile devices (screen width < 1024px), the library automatically caps the maximum zoom at 100% (scale 1.5). This ensures optimal performance and prevents coordinate misalignment on touch screens.
- Viewport Configuration: When using in a WebView, always ensure your HTML has the correct meta tags for a non-scalable viewport:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
License
MIT © PDF Annotator Team
