Skip to content

PDF-Kit is a versatile, framework-agnostic library designed to render, manipulate, and interact with PDF documents seamlessly. Whether you're building a React, Next.js, Angular, or any other frontend application, PDF-Kit provides you with a well-structured, modular, and feature-rich solution for embedding PDF viewers into your web applications.

License

Notifications You must be signed in to change notification settings

AmanKrr/pdf-viewer-kit

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

86 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

PDF Viewer Kit πŸš€

npm version License: MIT TypeScript Build Status

PDF Viewer Kit is a modern, high-performance, framework-agnostic, lightweight PDF viewer and annotation library built with TypeScript. Built on top of pdf.js, it provides PDF viewing capabilities with basic annotation features, canvas pooling, and a robust public API.

⚠️ Note

1.0.0-canvas-pooling.1 is a beta release.

It is highly recommended to use this version, as it is mostly stable and will be promoted to a stable release soon.

✨ Features

🎯 Core PDF Viewing

  • High-Performance Rendering: Optimized PDF rendering using pdf.js with canvas pooling
  • Multi-Instance Support: Load multiple PDF documents simultaneously with complete isolation
  • Responsive Design: Adaptive layout that works on all device sizes
  • Memory Efficient: Advanced memory management with canvas pooling and image bitmap optimization

πŸ–ŠοΈ Advanced Annotation System

  • Multiple Annotation Types: Rectangle, Ellipse, Line, and Text Selection annotations
  • Interactive Drawing: Real-time annotation drawing with visual feedback
  • Smart Selection: Intelligent annotation selection with resize handles
  • State-Based UI: Dynamic toolbar and button visibility based on annotation state
  • Delete Confirmation: User-friendly deletion with confirmation popups
  • Legacy Support: Backward compatibility with both modern and legacy coordinate formats

πŸ”§ Developer Experience

  • TypeScript First: Full TypeScript support with comprehensive type definitions
  • Runtime Protection: JavaScript runtime protection with facade pattern
  • Clean API: Professional, well-organized public API with proper namespacing
  • Event System: Comprehensive event system for all PDF viewer interactions
  • Modular Architecture: Clean separation of concerns with internal/external APIs

🎨 UI & Customization

  • Customizable Toolbar: Flexible toolbar system with plugin architecture
  • Theme Support: CSS custom properties for easy theming
  • Responsive Layout: Adaptive design that works on all screen sizes

πŸš€ Quick Start

Installation

npm install pdf-viewer-kit
# or
yarn add pdf-viewer-kit
# or
pnpm add pdf-viewer-kit

Basic Usage

import { PdfViewerKit } from 'pdf-viewer-kit';

// Load a PDF document
const instance = await PdfViewerKit.load({
  containerId: 'pdf-container',
  url: 'https://example.com/document.pdf',
});

// Access viewer functionality
instance.goToPage(5);
instance.zoomIn();
instance.nextPage();

Advanced Usage with Annotations

import { PdfViewerKit, PDFViewerKit } from 'pdf-viewer-kit';

// Load PDF with options
const instance = await PdfViewerKit.load({
  containerId: 'pdf-container',
  url: 'document.pdf',
  toolbarOptions: {
    showThumbnail: true,
    showSearch: true,
    showAnnotation: true,
  },
});

// Create annotations
const annotationId = await instance.annotations.createAnnotation({
  type: 'rectangle',
  pageNumber: 1,
  position: {
    left: 100,
    top: 100,
    width: 200,
    height: 100,
  },
  style: {
    fillColor: 'rgba(0, 123, 255, 0.3)',
    strokeColor: '#007bff',
    strokeWidth: 2,
    opacity: 0.8,
  },
});

// Extract text from annotation area
const extractedText = await instance.annotations.getTextInsideRectangle(annotationId);
console.log('Extracted text:', extractedText);

// Listen to events
instance.events.on(PDFViewerKit.Events.ANNOTATION_CREATED, (annotation) => {
  console.log('New annotation created:', annotation.id);
});

πŸ“š API Reference

Core Classes

PdfViewerKit

The main entry point for the library.

// Load PDF document
static async load(options: LoadOptions): Promise<IPDFViewerInstance>

// Get existing instance
static getInstance(instanceId: string): IPDFViewerInstance | undefined

// Get instance by container
static getInstanceByContainer(containerId: string): IPDFViewerInstance | undefined

// Get all instances
static getAllInstances(): IPDFViewerInstance[]

// Unload instance
static async unload(instanceId: string): Promise<void>

// Unload all instances
static async unloadAll(): Promise<void>

IPDFViewerInstance

Represents a loaded PDF viewer instance.

// Properties
instanceId: string
containerId: string
isReady: boolean
currentPage: number
totalPages: number
currentScale: number
pdfDocument: PDFDocumentProxy | null

// Methods
goToPage(pageNumber: number): void
nextPage(): void
previousPage(): void
zoomIn(): void
zoomOut(): void

// Services
events: IPDFViewerEvents
annotations: IPDFViewerAnnotations
search: IPDFViewerSearch

Annotation System

IPDFViewerAnnotations

Manages all annotation operations.

// Create annotations
createAnnotation(config: IAnnotationConfig): Promise<string>

// Get annotations
getAnnotations(pageNumber: number): IAnnotation[]

// Delete annotations
deleteAnnotation(annotationId: string): void

// Text extraction
getTextInsideRectangle(annotationId: string): Promise<string>

// Get annotation configuration
getAnnotationShapeConfig(annotationId: string): IShapeConfig

// Utility methods
isPageManagerRegistered(pageNumber: number): boolean
getRegisteredPages(): number[]

Annotation Types

// Rectangle annotation
interface IRectangleConfig {
  type: 'rectangle';
  pageNumber: number;
  position: {
    left: number;
    top: number;
    width: number;
    height: number;
  };
  // OR legacy format
  x0?: number;
  y0?: number;
  x1?: number;
  y1?: number;
  style: IAnnotationStyle;
}

// Ellipse annotation
interface IEllipseConfig {
  type: 'ellipse';
  pageNumber: number;
  position: {
    left: number;
    top: number;
    width: number;
    height: number;
  };
  style: IAnnotationStyle;
}

// Line annotation
interface ILineConfig {
  type: 'line';
  pageNumber: number;
  position: {
    startX: number;
    startY: number;
    endX: number;
    endY: number;
  };
  style: IAnnotationStyle;
}

Event System

Available Events

// Annotation events
'ANNOTATION_SELECTED';
'ANNOTATION_CREATED';
'ANNOTATION_DELETED';
'ANNOTATION_DESELECT';
'ANNOTATION_UPDATED';

Event Usage

// Listen to events
instance.events.on('ANNOTATION_CREATED', (annotation) => {
  console.log('Annotation created:', annotation);
});

// Remove specific listener
instance.events.off('ANNOTATION_CREATED', listener);

// Remove all listeners for an event
instance.events.removeAllListeners('ANNOTATION_CREATED');

Namespace Access

import { PDFViewerKit } from 'pdf-viewer-kit';

// Access organized functionality
PDFViewerKit.Viewer.load(options); // Main viewer class
PDFViewerKit.Events.ANNOTATION_CREATED; // Event constants
PDFViewerKit.Utils.normalizeRect(coords); // Utility functions

🎨 Customization

Toolbar Configuration

const instance = await PdfViewerKit.load({
  containerId: 'pdf-container',
  url: 'document.pdf',
  toolbarOptions: {
    showThumbnail: true,
    showSearch: true,
    showAnnotation: true,
    showDownload: true,
    showZoom: true,
    showPageNavigation: true,
  },
});

Custom Styling

/* Customize annotation colors */
:root {
  --annotation-fill-color: rgba(0, 123, 255, 0.3);
  --annotation-stroke-color: #007bff;
  --annotation-selected-color: #ff6b6b;
}

/* Customize toolbar appearance */
.pdf-viewer-toolbar {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 12px;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
}

Plugin System

// Create custom toolbar plugins
class CustomPlugin extends BaseAnnotationToolbarPlugin {
  initialize(context: AnnotationContext) {
    // Custom initialization logic
  }

  render() {
    // Custom rendering logic
  }
}

πŸ”§ Advanced Configuration

Load Options

interface LoadOptions {
  containerId: string;
  url?: string;
  document?: ArrayBuffer | Uint8Array;
  password?: string;
  toolbarOptions?: ToolbarOptions;
}

πŸ“± Multi-Instance Support

// Load multiple PDFs simultaneously
const instance1 = await PdfViewerKit.load({
  containerId: 'pdf-container-1',
  url: 'document1.pdf',
});

const instance2 = await PdfViewerKit.load({
  containerId: 'pdf-container-2',
  url: 'document2.pdf',
});

// Each instance is completely isolated
instance1.goToPage(5);
instance2.zoomIn();

// Get all instances
const allInstances = PdfViewerKit.getAllInstances();
console.log('Active instances:', allInstances.length);

πŸš€ Performance Features

Canvas Pooling

  • Memory Optimization: Reuses canvas elements to reduce memory allocation
  • Performance Boost: Faster rendering and smoother interactions
  • Configurable: Adjustable pool size based on your needs

Page Virtualization

  • Efficient Memory Usage: Only renders visible pages
  • Smooth Scrolling: Handles large documents without performance degradation
  • Smart Caching: Intelligent page caching for optimal performance

Image Bitmap Pooling

  • Reduced Memory Pressure: Efficient handling of PDF images
  • Faster Rendering: Optimized image processing pipeline
  • Better UX: Smoother page transitions and zoom operations

πŸ§ͺ Examples

Basic PDF Viewer

<!DOCTYPE html>
<html>
  <head>
    <title>PDF Viewer Kit - Basic Example</title>
  </head>
  <body>
    <div id="pdf-container" style="width: 100%; height: 600px;"></div>

    <script type="module">
      import { PdfViewerKit } from 'pdf-viewer-kit';

      PdfViewerKit.load({
        containerId: 'pdf-container',
        url: 'sample.pdf',
      });
    </script>
  </body>
</html>

Advanced Annotation Example

import { PdfViewerKit, PDFViewerKit } from 'pdf-viewer-kit';

class PDFAnnotationManager {
  private instance: any;

  async initialize() {
    this.instance = await PdfViewerKit.load({
      containerId: 'pdf-container',
      url: 'document.pdf',
      toolbarOptions: {
        showAnnotation: true,
        showThumbnail: true,
      },
    });

    this.setupEventListeners();
  }

  private setupEventListeners() {
    // Listen to annotation events
    this.instance.events.on(PDFViewerKit.Events.ANNOTATION_CREATED, (annotation) => {
      this.onAnnotationCreated(annotation);
    });

    this.instance.events.on(PDFViewerKit.Events.ANNOTATION_DELETED, (annotation) => {
      this.onAnnotationDeleted(annotation);
    });
  }

  async createRectangleAnnotation(page: number, x: number, y: number, width: number, height: number) {
    return await this.instance.annotations.createAnnotation({
      type: 'rectangle',
      pageNumber: page,
      position: { left: x, top: y, width, height },
      style: {
        fillColor: 'rgba(255, 0, 0, 0.3)',
        strokeColor: '#ff0000',
        strokeWidth: 2,
      },
    });
  }

  private onAnnotationCreated(annotation: any) {
    console.log('Annotation created:', annotation);
    // Update UI, save to database, etc.
  }

  private onAnnotationDeleted(annotation: any) {
    console.log('Annotation deleted:', annotation);
    // Update UI, remove from database, etc.
  }
}

// Usage
const manager = new PDFAnnotationManager();
manager.initialize();

πŸ—οΈ Architecture

Core Components

PDF Viewer Kit
β”œβ”€β”€ Core System
β”‚   β”œβ”€β”€ PdfViewerKit (Main class)
β”‚   β”œβ”€β”€ PDFViewerInstance (Instance management)
β”‚   └── EventEmitter (Event system)
β”œβ”€β”€ Viewer Components
β”‚   β”œβ”€β”€ WebViewer (Main viewer)
β”‚   β”œβ”€β”€ PageVirtualization (Page management)
β”‚   └── Toolbar (User interface)
β”œβ”€β”€ Annotation System
β”‚   β”œβ”€β”€ AnnotationService (Core logic)
β”‚   β”œβ”€β”€ AnnotationManager (Page-level management)
β”‚   └── Annotation Types (Rectangle, Ellipse, Line)
β”œβ”€β”€ Performance Features
β”‚   β”œβ”€β”€ CanvasPool (Memory optimization)
β”‚   β”œβ”€β”€ ImageBitmapPool (Image handling)
β”‚   └── PageVirtualization (Efficient rendering)
└── Public API
    β”œβ”€β”€ Facade Pattern (Runtime protection)
    β”œβ”€β”€ TypeScript Interfaces (Type safety)
    └── Namespace Organization (Clean API)

Design Patterns

  • Facade Pattern: Clean public API with runtime protection
  • Observer Pattern: Event-driven architecture for loose coupling
  • Factory Pattern: Annotation creation and management
  • Pool Pattern: Memory optimization with canvas and image pooling
  • Strategy Pattern: Flexible annotation rendering and interaction

πŸ”’ Security Features

Runtime Protection

  • JavaScript Safety: Prevents direct access to internal properties
  • Facade Pattern: Controlled access to library functionality
  • Type Safety: Full TypeScript support with strict typing

Input Validation

  • Coordinate Validation: Ensures annotation coordinates are valid
  • File Validation: Secure PDF file handling
  • Event Validation: Safe event emission and handling

πŸ“Š Browser Support

Browser Version Support
Chrome 90+ βœ… Full Support
Firefox 88+ βœ… Full Support
Safari 14+ βœ… Full Support
Edge 90+ βœ… Full Support

πŸš€ Getting Started

1. Installation

npm install pdf-viewer-kit

2. Basic Setup

<div id="pdf-container"></div>
import { PdfViewerKit } from 'pdf-viewer-kit';

const instance = await PdfViewerKit.load({
  containerId: 'pdf-container',
  url: 'your-document.pdf',
});

3. Add Annotations

const annotationId = await instance.annotations.createAnnotation({
  type: 'rectangle',
  pageNumber: 1,
  position: { left: 100, top: 100, width: 200, height: 100 },
  style: { fillColor: 'rgba(0, 123, 255, 0.3)' },
});

4. Listen to Events

instance.events.on('ANNOTATION_CREATED', (annotation) => {
  console.log('Annotation created:', annotation);
});

🀝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

# Clone the repository
git clone https://github.com/AmanKrr/pdf-viewer-kit.git

# Install dependencies
npm install

# Start development server
npm run dev

# Build the library
npm run build

# Run tests
npm test

Code Style

  • TypeScript: Strict typing with comprehensive interfaces
  • ESLint: Consistent code style and quality
  • Prettier: Automatic code formatting
  • Conventional Commits: Standardized commit messages

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

Acknowledgments

  • pdf.js: The foundation for PDF rendering
  • TypeScript: For type safety and developer experience
  • Canvas API: For high-performance graphics
  • Open Source Community: For inspiration and contributions

πŸ“ž Support


Made with ❀️ by Aman Kumar

PDF Viewer Kit - Lightweight PDF viewing and annotation for modern web applications

About

PDF-Kit is a versatile, framework-agnostic library designed to render, manipulate, and interact with PDF documents seamlessly. Whether you're building a React, Next.js, Angular, or any other frontend application, PDF-Kit provides you with a well-structured, modular, and feature-rich solution for embedding PDF viewers into your web applications.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •