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.1is 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.
- 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
- 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
- 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
- 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
npm install pdf-viewer-kit
# or
yarn add pdf-viewer-kit
# or
pnpm add pdf-viewer-kitimport { 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();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);
});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>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: IPDFViewerSearchManages 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[]// 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;
}// Annotation events
'ANNOTATION_SELECTED';
'ANNOTATION_CREATED';
'ANNOTATION_DELETED';
'ANNOTATION_DESELECT';
'ANNOTATION_UPDATED';// 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');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 functionsconst instance = await PdfViewerKit.load({
containerId: 'pdf-container',
url: 'document.pdf',
toolbarOptions: {
showThumbnail: true,
showSearch: true,
showAnnotation: true,
showDownload: true,
showZoom: true,
showPageNavigation: true,
},
});/* 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);
}// Create custom toolbar plugins
class CustomPlugin extends BaseAnnotationToolbarPlugin {
initialize(context: AnnotationContext) {
// Custom initialization logic
}
render() {
// Custom rendering logic
}
}interface LoadOptions {
containerId: string;
url?: string;
document?: ArrayBuffer | Uint8Array;
password?: string;
toolbarOptions?: ToolbarOptions;
}// 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);- Memory Optimization: Reuses canvas elements to reduce memory allocation
- Performance Boost: Faster rendering and smoother interactions
- Configurable: Adjustable pool size based on your needs
- Efficient Memory Usage: Only renders visible pages
- Smooth Scrolling: Handles large documents without performance degradation
- Smart Caching: Intelligent page caching for optimal performance
- Reduced Memory Pressure: Efficient handling of PDF images
- Faster Rendering: Optimized image processing pipeline
- Better UX: Smoother page transitions and zoom operations
<!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>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();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)
- 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
- JavaScript Safety: Prevents direct access to internal properties
- Facade Pattern: Controlled access to library functionality
- Type Safety: Full TypeScript support with strict typing
- Coordinate Validation: Ensures annotation coordinates are valid
- File Validation: Secure PDF file handling
- Event Validation: Safe event emission and handling
| Browser | Version | Support |
|---|---|---|
| Chrome | 90+ | β Full Support |
| Firefox | 88+ | β Full Support |
| Safari | 14+ | β Full Support |
| Edge | 90+ | β Full Support |
npm install pdf-viewer-kit<div id="pdf-container"></div>import { PdfViewerKit } from 'pdf-viewer-kit';
const instance = await PdfViewerKit.load({
containerId: 'pdf-container',
url: 'your-document.pdf',
});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)' },
});instance.events.on('ANNOTATION_CREATED', (annotation) => {
console.log('Annotation created:', annotation);
});We welcome contributions! Please see our Contributing Guide for details.
# 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- TypeScript: Strict typing with comprehensive interfaces
- ESLint: Consistent code style and quality
- Prettier: Automatic code formatting
- Conventional Commits: Standardized commit messages
This project is licensed under the MIT License - see the LICENSE file for details.
- 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
- Documentation: Wiki
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with β€οΈ by Aman Kumar
PDF Viewer Kit - Lightweight PDF viewing and annotation for modern web applications