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

@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 LocalStorage for 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

  1. Initial Scale: Use scale: 1.5 to set the default zoom to 100%. The library uses a base scale of 1.5 to represent standard 100% resolution.
  2. 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.
  3. 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