ng2-pdfjs-viewer 25.0.6 → 25.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,794 +1,796 @@
1
- # Angular PDF viewer powered by Mozilla's PDF.js
2
-
3
- The most reliable, feature-rich Angular PDF viewer component powered by Mozilla's PDF.js
4
-
5
- <div align="center">
6
- <img src="logo.svg" alt="ng2-pdfjs-viewer Logo" width="120" height="140" />
7
- </div>
8
-
9
- <div align="center">
10
-
11
- [![NPM Version](https://img.shields.io/npm/v/ng2-pdfjs-viewer?logo=npm&color=blue)](https://www.npmjs.com/package/ng2-pdfjs-viewer)
12
- [![PDF.js Version](https://img.shields.io/badge/PDF.js%20v5.3.93-latest-green?logo=mozilla)](https://github.com/mozilla/pdf.js)
13
- [![Angular Support](https://img.shields.io/badge/Angular%2020+-supported-red?logo=angular)](https://angular.dev/overview)
14
- [![NPM Downloads](https://img.shields.io/npm/dm/ng2-pdfjs-viewer?label=downloads%2Fmonth&color=orange)](https://www.npmjs.com/package/ng2-pdfjs-viewer)
15
- [![Total Downloads](https://img.shields.io/badge/total%20downloads-7M+-brightgreen?logo=npm)](https://www.npmjs.com/package/ng2-pdfjs-viewer)
16
- [![Since 2018](https://img.shields.io/badge/since-2018-blue?logo=calendar)](https://www.npmjs.com/package/ng2-pdfjs-viewer)
17
- [![License](https://img.shields.io/badge/license-Apache%202.0%20%2B%20Commons%20Clause-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
18
- [![GitHub Stars](https://img.shields.io/github/stars/intbot/ng2-pdfjs-viewer?logo=github)](https://github.com/intbot/ng2-pdfjs-viewer)
19
-
20
- </div>
21
-
22
- <div align="center">
23
-
24
- [**Live Demo**](https://angular-pdf-viewer-demo.vercel.app/) • [**API Reference**](#-api-reference) • [**Examples**](#-examples) • [**Server Examples**](../Server-Side-Examples.md) • [**Migration Guide**](#-migration-guide)
25
-
26
- </div>
27
-
28
- ---
29
-
30
- ng2-pdfjs-viewer is the most comprehensive and feature-rich Angular PDF viewer component available. **Born in 2018** and still going strong with over **7+ million downloads**, this battle-tested library has been trusted by developers worldwide for **over 8 years**, powering thousands of applications.
31
-
32
- This powerful library enables developers to seamlessly integrate PDF viewing capabilities into Angular applications with enterprise-grade features, custom theming, and mobile-first responsive design. Built on Mozilla's PDF.js v5.3.93, ng2-pdfjs-viewer provides advanced PDF rendering, document navigation, search functionality, and extensive customization options.
33
-
34
- Whether you need a simple embedded PDF viewer or a complex document management system, this component delivers the performance and flexibility required for modern Angular applications. **The most mature and reliable Angular PDF viewer solution** with continuous updates and long-term support.
35
-
36
- ### Why Choose ng2-pdfjs-viewer?
37
-
38
- - **🚀 Always Up-to-Date** - Continuously updated with the latest PDF.js versions and Angular compatibility
39
- - **🏗️ Enterprise-Ready** - Built for production with comprehensive error handling and performance optimization
40
- - **🎨 Highly Customizable** - Extensive theming options, custom templates, and flexible configuration
41
- - **📱 Mobile Optimized** - Touch-friendly interface with responsive design for all screen sizes
42
- - **🔧 Developer Friendly** - Full TypeScript support, comprehensive documentation, and easy integration
43
- - **⚡ High Performance** - Event-driven architecture with efficient memory management and lazy loading
44
- - **🌍 Global Support** - Multi-language support with automatic locale detection and RTL compatibility
45
- - **🛡️ Production Tested** - Trusted by thousands of applications with millions of downloads
46
- - **📈 Proven Track Record** - 8+ years of continuous development and community support
47
- - **🔒 Security Focused** - Regular security updates and vulnerability patches
48
-
49
- ### 🆕 Latest Features (v25.x)
50
-
51
- | Feature | Description | Status |
52
- | ----------------------------- | ------------------------------------------------------------------ | ------ |
53
- | **Advanced Theme System** | CSS custom properties for complete visual customization | ✅ New |
54
- | **Template-Based UI** | Custom loading spinners and error displays using Angular templates | ✅ New |
55
- | **Convenience Configuration** | Object-based configuration for cleaner, more maintainable code | ✅ New |
56
- | **Event-Driven Architecture** | Pure event-based system with universal action dispatcher | ✅ New |
57
- | **Enhanced Error Handling** | Multiple error display styles with custom templates | ✅ New |
58
- | **Mobile-First Design** | Responsive layout optimized for touch devices | ✅ New |
59
- | **TypeScript Strict Mode** | Full type safety with comprehensive API coverage | ✅ New |
60
-
61
- ### 🏆 Unique Advantages
62
-
63
- - **Universal Action Dispatcher** - Single pathway for all actions with readiness validation
64
- - **Template-Based Customization** - Use Angular templates for loading and error states
65
- - **Comprehensive Event System** - 24+ events covering all user interactions and state changes
66
- - **Advanced Configuration Objects** - Clean, object-based configuration for complex setups
67
- - **Production-Ready Architecture** - Event-driven design with no timeouts or polling
68
- - **Complete API Coverage** - 19+ methods with consistent Promise-based returns
69
-
70
- ### 🎯 Perfect For
71
-
72
- - **Enterprise Applications** - Robust, scalable PDF viewing for business applications
73
- - **Document Management Systems** - Complete PDF handling with search and navigation
74
- - **E-Learning Platforms** - Interactive PDF viewing for educational content
75
- - **Financial Applications** - Secure PDF viewing for reports and statements
76
- - **Healthcare Systems** - Reliable PDF viewing for medical documents
77
- - **Government Portals** - Accessible PDF viewing for public services
78
- - **E-Commerce Platforms** - Product catalogs and documentation viewing
79
- - **Content Management Systems** - Integrated PDF viewing and management
80
-
81
- ---
82
-
83
- ## 📋 Table of Contents
84
-
85
- - [Quick Start](#-quick-start)
86
- - [Features](#-features)
87
- - [Installation](#-installation)
88
- - [Basic Usage](#-basic-usage)
89
- - [Advanced Configuration](#advanced-configuration)
90
- - [API Reference](#-api-reference)
91
- - [Examples](#-examples)
92
- - [Migration Guide](#-migration-guide)
93
- - [Deprecated Features](#deprecated-features)
94
- - [Contributing](#-contributing)
95
- - [License](#-license)
96
-
97
- ---
98
-
99
- ## 🚀 Quick Start
100
-
101
- > **🎯 Live Demo**: [https://angular-pdf-viewer-demo.vercel.app/](https://angular-pdf-viewer-demo.vercel.app/)
102
- > **📁 Source Code**: [https://github.com/intbot/ng2-pdfjs-viewer/tree/main/SampleApp](https://github.com/intbot/ng2-pdfjs-viewer/tree/main/SampleApp)
103
-
104
- ### 1. Install the Package
105
-
106
- ```bash
107
- npm install ng2-pdfjs-viewer --save
108
- ```
109
-
110
- ### 2. Import the Module
111
-
112
- ```typescript
113
- import { NgModule } from "@angular/core";
114
- import { BrowserModule } from "@angular/platform-browser";
115
- import { PdfJsViewerModule } from "ng2-pdfjs-viewer";
116
-
117
- @NgModule({
118
- imports: [BrowserModule, PdfJsViewerModule],
119
- // ... rest of your module
120
- })
121
- export class AppModule {}
122
- ```
123
-
124
- ### 3. Use in Your Component
125
-
126
- ```html
127
- <ng2-pdfjs-viewer
128
- pdfSrc="assets/sample.pdf"
129
- [showSpinner]="true"
130
- [theme]="'light'"
131
- >
132
- </ng2-pdfjs-viewer>
133
- ```
134
-
135
- ### 4. Configure Assets (Required)
136
-
137
- Add PDF.js assets to your `angular.json`:
138
-
139
- ```json
140
- {
141
- "projects": {
142
- "your-app": {
143
- "architect": {
144
- "build": {
145
- "options": {
146
- "assets": [
147
- {
148
- "glob": "**/*",
149
- "input": "node_modules/ng2-pdfjs-viewer/pdfjs",
150
- "output": "/assets/pdfjs"
151
- }
152
- ]
153
- }
154
- }
155
- }
156
- }
157
- }
158
- }
159
- ```
160
-
161
- ---
162
-
163
- ## ✨ Features
164
-
165
- **🎉 7+ Million Downloads & Counting!** - Trusted by developers worldwide for reliable PDF viewing in Angular applications since 2018.
166
-
167
- ### 🎯 Core PDF Viewing Features
168
-
169
- - **📄 High-Quality PDF Rendering** - Powered by Mozilla's PDF.js v5.3.93 for superior document display
170
- - **🔄 Multiple Display Modes** - Embedded viewer, new window, or external tab options
171
- - **📱 Mobile-First Responsive Design** - Touch-friendly controls optimized for all devices
172
- - **🌍 Complete Internationalization** - Support for 50+ languages with automatic locale detection
173
- - **⚡ Optimized Performance** - Lazy loading, memory management, and efficient rendering
174
-
175
- ### 🎨 Visual Customization
176
-
177
- - **🎨 Theme System** - Light, dark, and auto themes with custom color schemes
178
- - **🎭 Custom Styling** - CSS custom properties for complete visual control
179
- - **🔄 Loading States** - Custom loading spinners with template support
180
- - **❌ Error Handling** - Multiple error display styles with custom templates
181
- - **📐 Layout Control** - Toolbar density, sidebar width, and positioning options
182
-
183
- ### 🔧 Developer Features
184
-
185
- - **📝 TypeScript Support** - Full type safety with strict mode
186
- - **🔌 Event System** - Comprehensive event handling for all user interactions
187
- - **⚙️ Configuration Objects** - Convenience setters for cleaner code
188
- - **🛠️ API Methods** - Promise-based methods for programmatic control
189
- - **🐛 Debugging** - Built-in diagnostic logging and error tracking
190
-
191
- ### 📊 Advanced Features
192
-
193
- - **🔍 Search & Navigation** - Full-text search with highlighting
194
- - **📖 Bookmarks & Attachments** - Document structure navigation
195
- - **🖨️ Print & Download** - Built-in print and download functionality
196
- - **🔄 Rotation & Zoom** - Document manipulation with smooth animations
197
- - **📱 Touch Gestures** - Mobile-optimized touch interactions
198
-
199
- ---
200
-
201
- ## 📦 Installation
202
-
203
- ### Prerequisites
204
-
205
- - **Angular**: 20.0+ (recommended) | 2.0+ (supported)
206
- - **Node.js**: 18.0+
207
- - **TypeScript**: 5.0+
208
-
209
- ### Angular Version Support
210
-
211
- | Angular Version | Support Level | Notes |
212
- |----------------|---------------|-------|
213
- | **20.0+** | ✅ **Recommended** | Fully tested and optimized |
214
- | **15.0 - 19.x** | ✅ **Supported** | Should work with minor testing |
215
- | **10.0 - 14.x** | ✅ **Supported** | Compatible with testing |
216
- | **2.0 - 9.x** | ⚠️ **Legacy** | May require additional testing |
217
-
218
- **Note**: While the library supports Angular 2.0+, it's primarily tested and optimized for Angular 20+. For production use with older versions, thorough testing is recommended. The library uses relaxed peer dependencies (Angular >=10.0.0) to ensure compatibility across different Angular versions.
219
-
220
- ### Install Package
221
-
222
- ```bash
223
- # Using npm
224
- npm install ng2-pdfjs-viewer --save
225
-
226
- # Using yarn
227
- yarn add ng2-pdfjs-viewer
228
-
229
- # Using pnpm
230
- pnpm add ng2-pdfjs-viewer
231
- ```
232
-
233
- ### Configure Assets
234
-
235
- Add PDF.js assets to your `angular.json`:
236
-
237
- ```json
238
- {
239
- "projects": {
240
- "your-app": {
241
- "architect": {
242
- "build": {
243
- "options": {
244
- "assets": [
245
- {
246
- "glob": "**/*",
247
- "input": "node_modules/ng2-pdfjs-viewer/pdfjs",
248
- "output": "/assets/pdfjs"
249
- }
250
- ]
251
- }
252
- }
253
- }
254
- }
255
- }
256
- }
257
- ```
258
-
259
- ---
260
-
261
- ## 🎯 Basic Usage
262
-
263
- ### Simple PDF Viewer
264
-
265
- ```html
266
- <ng2-pdfjs-viewer pdfSrc="assets/document.pdf" [showSpinner]="true">
267
- </ng2-pdfjs-viewer>
268
- ```
269
-
270
- ### Advanced Configuration
271
-
272
- ```html
273
- <ng2-pdfjs-viewer
274
- pdfSrc="assets/document.pdf"
275
- [theme]="'dark'"
276
- [primaryColor]="'#007acc'"
277
- [showSpinner]="true"
278
- [customSpinnerTpl]="customSpinner"
279
- [customErrorTpl]="customError"
280
- (onDocumentLoad)="onDocumentLoaded($event)"
281
- (onPageChange)="onPageChanged($event)"
282
- >
283
- </ng2-pdfjs-viewer>
284
- ```
285
-
286
- ### Programmatic Control
287
-
288
- ```typescript
289
- import { Component, ViewChild } from "@angular/core";
290
- import { PdfJsViewerComponent } from "ng2-pdfjs-viewer";
291
-
292
- @Component({
293
- template: `
294
- <ng2-pdfjs-viewer #pdfViewer pdfSrc="document.pdf"></ng2-pdfjs-viewer>
295
- <button (click)="goToPage(5)">Go to Page 5</button>
296
- `,
297
- })
298
- export class MyComponent {
299
- @ViewChild("pdfViewer") pdfViewer!: PdfJsViewerComponent;
300
-
301
- async goToPage(page: number) {
302
- await this.pdfViewer.goToPage(page);
303
- }
304
- }
305
- ```
306
-
307
- ---
308
-
309
- ## Advanced Configuration
310
-
311
- ### Theme Customization
312
-
313
- ```typescript
314
- // Component
315
- export class MyComponent {
316
- themeConfig = {
317
- theme: "light",
318
- primaryColor: "#007acc",
319
- backgroundColor: "#ffffff",
320
- toolbarColor: "#f5f5f5",
321
- textColor: "#333333",
322
- borderRadius: "8px",
323
- };
324
- }
325
- ```
326
-
327
- ```html
328
- <!-- Template -->
329
- <ng2-pdfjs-viewer [themeConfig]="themeConfig" [customCSS]="customStyles">
330
- </ng2-pdfjs-viewer>
331
- ```
332
-
333
- ### Custom Loading Spinner
334
-
335
- ```html
336
- <ng-template #customSpinner>
337
- <div class="custom-spinner">
338
- <div class="spinner"></div>
339
- <p>Loading PDF...</p>
340
- </div>
341
- </ng-template>
342
-
343
- <ng2-pdfjs-viewer
344
- [customSpinnerTpl]="customSpinner"
345
- [spinnerClass]="'my-spinner'"
346
- >
347
- </ng2-pdfjs-viewer>
348
- ```
349
-
350
- ### Custom Error Display
351
-
352
- ```html
353
- <ng-template #customError>
354
- <div class="error-container">
355
- <mat-icon>error</mat-icon>
356
- <h3>Failed to Load PDF</h3>
357
- <p>Please check your internet connection and try again.</p>
358
- <button mat-button (click)="retry()">Retry</button>
359
- </div>
360
- </ng-template>
361
-
362
- <ng2-pdfjs-viewer [customErrorTpl]="customError" [errorClass]="'my-error'">
363
- </ng2-pdfjs-viewer>
364
- ```
365
-
366
- ---
367
-
368
- ## 📚 API Reference
369
-
370
- ### Input Properties
371
-
372
- | Property | Type | Default | Description |
373
- | ---------------------------- | ----------------------------------------- | ------------ | ------------------------------------- |
374
- | `pdfSrc` | `string \| Blob \| Uint8Array` | - | PDF source (URL, Blob, or byte array) |
375
- | `viewerId` | `string` | auto | Unique viewer identifier |
376
- | `viewerFolder` | `string` | `'assets'` | Path to PDF.js assets |
377
- | `externalWindow` | `boolean` | `false` | Open in new window |
378
- | `externalWindowOptions` | `string` | - | External window options |
379
- | `target` | `string` | `'_blank'` | Target for external window |
380
- | `theme` | `'light' \| 'dark' \| 'auto'` | `'light'` | Theme selection |
381
- | `primaryColor` | `string` | `'#007acc'` | Primary color for UI elements |
382
- | `backgroundColor` | `string` | `'#ffffff'` | Background color |
383
- | `pageBorderColor` | `string` | - | Page border color |
384
- | `toolbarColor` | `string` | - | Toolbar background color |
385
- | `textColor` | `string` | - | Text color |
386
- | `borderRadius` | `string` | - | Border radius |
387
- | `customCSS` | `string` | - | Custom CSS styles |
388
- | `showSpinner` | `boolean` | `true` | Show loading spinner |
389
- | `customSpinnerTpl` | `TemplateRef` | - | Custom spinner template |
390
- | `spinnerClass` | `string` | - | Custom spinner CSS class |
391
- | `customErrorTpl` | `TemplateRef` | - | Custom error template |
392
- | `errorClass` | `string` | - | Custom error CSS class |
393
- | `errorOverride` | `boolean` | `false` | Override default error handling |
394
- | `errorAppend` | `boolean` | `true` | Append to default error messages |
395
- | `errorMessage` | `string` | - | Custom error message |
396
- | `locale` | `string` | `'en-US'` | UI language |
397
- | `useOnlyCssZoom` | `boolean` | `false` | Use CSS-based zoom for mobile |
398
- | `diagnosticLogs` | `boolean` | `false` | Enable diagnostic logging |
399
- | `zoom` | `string` | `'auto'` | Initial zoom level (two-way binding) |
400
- | `page` | `number` | `1` | Initial page number |
401
- | `namedDest` | `string` | - | Named destination to navigate to |
402
- | `cursor` | `string` | `'select'` | Cursor type (two-way binding) |
403
- | `scroll` | `string` | `'vertical'` | Scroll mode (two-way binding) |
404
- | `spread` | `string` | `'none'` | Spread mode (two-way binding) |
405
- | `pageMode` | `string` | `'none'` | Page mode (two-way binding) |
406
- | `rotation` | `number` | `0` | Document rotation (two-way binding) |
407
- | `showOpenFile` | `boolean` | `true` | Show open file button |
408
- | `showDownload` | `boolean` | `true` | Show download button |
409
- | `showPrint` | `boolean` | `true` | Show print button |
410
- | `showFind` | `boolean` | `true` | Show search button |
411
- | `showFullScreen` | `boolean` | `true` | Show fullscreen button |
412
- | `showViewBookmark` | `boolean` | `true` | Show bookmark button |
413
- | `showAnnotations` | `boolean` | `false` | Show annotations |
414
- | `showToolbarLeft` | `boolean` | `true` | Show left toolbar section |
415
- | `showToolbarMiddle` | `boolean` | `true` | Show middle toolbar section |
416
- | `showToolbarRight` | `boolean` | `true` | Show right toolbar section |
417
- | `showSecondaryToolbarToggle` | `boolean` | `true` | Show secondary toolbar toggle |
418
- | `showSidebar` | `boolean` | `true` | Show sidebar |
419
- | `showSidebarLeft` | `boolean` | `true` | Show left sidebar |
420
- | `showSidebarRight` | `boolean` | `true` | Show right sidebar |
421
- | `toolbarDensity` | `'compact' \| 'default' \| 'comfortable'` | `'default'` | Toolbar density |
422
- | `sidebarWidth` | `string` | - | Sidebar width (e.g., '280px') |
423
- | `toolbarPosition` | `'top' \| 'bottom'` | `'top'` | Toolbar position |
424
- | `sidebarPosition` | `'left' \| 'right'` | `'left'` | Sidebar position |
425
- | `responsiveBreakpoint` | `string \| number` | - | Responsive breakpoint |
426
- | `downloadOnLoad` | `boolean` | `false` | Auto-download on load |
427
- | `printOnLoad` | `boolean` | `false` | Auto-print on load |
428
- | `rotateCW` | `boolean` | `false` | Rotate clockwise on load |
429
- | `rotateCCW` | `boolean` | `false` | Rotate counter-clockwise on load |
430
- | `showLastPageOnLoad` | `boolean` | `false` | Go to last page on load |
431
- | `downloadFileName` | `string` | - | Custom download filename |
432
- | `controlVisibility` | `ControlVisibilityConfig` | - | Control visibility configuration |
433
- | `autoActions` | `AutoActionConfig` | - | Auto actions configuration |
434
- | `errorHandling` | `ErrorConfig` | - | Error handling configuration |
435
- | `viewerConfig` | `ViewerConfig` | - | Viewer configuration |
436
- | `themeConfig` | `ThemeConfig` | - | Theme configuration |
437
- | `groupVisibility` | `GroupVisibilityConfig` | - | Group visibility configuration |
438
- | `layoutConfig` | `LayoutConfig` | - | Layout configuration |
439
-
440
- ### Output Events
441
-
442
- | Event | Type | Description |
443
- | --------------------------- | ------------------------------------------ | ---------------------------------------------- |
444
- | `onDocumentLoad` | `EventEmitter<void>` | Fired when document loads |
445
- | `onDocumentInit` | `EventEmitter<void>` | Fired when document initializes |
446
- | `onDocumentError` | `EventEmitter<DocumentError>` | Fired when document fails to load |
447
- | `onPageChange` | `EventEmitter<ChangedPage>` | Fired when page changes |
448
- | `onPagesInit` | `EventEmitter<PagesInfo>` | Fired when pages are initialized |
449
- | `onPageRendered` | `EventEmitter<PageRenderInfo>` | Fired when a page is rendered |
450
- | `onScaleChange` | `EventEmitter<ChangedScale>` | Fired when zoom/scale changes |
451
- | `onRotationChange` | `EventEmitter<ChangedRotation>` | Fired when rotation changes |
452
- | `onPresentationModeChanged` | `EventEmitter<PresentationMode>` | Fired when presentation mode changes |
453
- | `onOpenFile` | `EventEmitter<void>` | Fired when open file is clicked |
454
- | `onFind` | `EventEmitter<FindOperation>` | Fired when search is performed |
455
- | `onUpdateFindMatchesCount` | `EventEmitter<FindMatchesCount>` | Fired when search matches are updated |
456
- | `onMetadataLoaded` | `EventEmitter<DocumentMetadata>` | Fired when document metadata loads |
457
- | `onOutlineLoaded` | `EventEmitter<DocumentOutline>` | Fired when document outline loads |
458
- | `onAnnotationLayerRendered` | `EventEmitter<AnnotationLayerRenderEvent>` | Fired when annotation layer renders |
459
- | `onBookmarkClick` | `EventEmitter<BookmarkClick>` | Fired when bookmark is clicked |
460
- | `onIdle` | `EventEmitter<void>` | Fired when viewer becomes idle |
461
- | `onBeforePrint` | `EventEmitter<void>` | Fired before printing |
462
- | `onAfterPrint` | `EventEmitter<void>` | Fired after printing |
463
- | `zoomChange` | `EventEmitter<string>` | Fired when zoom changes (two-way binding) |
464
- | `cursorChange` | `EventEmitter<string>` | Fired when cursor changes (two-way binding) |
465
- | `scrollChange` | `EventEmitter<string>` | Fired when scroll changes (two-way binding) |
466
- | `spreadChange` | `EventEmitter<string>` | Fired when spread changes (two-way binding) |
467
- | `pageModeChange` | `EventEmitter<string>` | Fired when page mode changes (two-way binding) |
468
-
469
- ### Methods
470
-
471
- | Method | Parameters | Returns | Description |
472
- | -------------------------------------------------------- | ----------------------------------------------------------- | ---------------------------------------------------- | --------------------------------- |
473
- | `refresh()` | - | `void` | Refresh viewer |
474
- | `goToPage(page: number)` | `page: number` | `Promise<ActionExecutionResult>` | Navigate to specific page |
475
- | `setPage(page: number)` | `page: number` | `Promise<ActionExecutionResult>` | Set current page |
476
- | `setZoom(zoom: string)` | `zoom: string` | `Promise<ActionExecutionResult>` | Set zoom level |
477
- | `setCursor(cursor: string)` | `cursor: 'select' \| 'hand' \| 'zoom'` | `Promise<ActionExecutionResult>` | Set cursor type |
478
- | `setScroll(scroll: string)` | `scroll: 'vertical' \| 'horizontal' \| 'wrapped' \| 'page'` | `Promise<ActionExecutionResult>` | Set scroll mode |
479
- | `setSpread(spread: string)` | `spread: 'none' \| 'odd' \| 'even'` | `Promise<ActionExecutionResult>` | Set spread mode |
480
- | `setPageMode(mode: string)` | `mode: 'none' \| 'thumbs' \| 'bookmarks' \| 'attachments'` | `Promise<ActionExecutionResult>` | Set page mode |
481
- | `triggerDownload()` | - | `Promise<ActionExecutionResult>` | Trigger download |
482
- | `triggerPrint()` | - | `Promise<ActionExecutionResult>` | Trigger print |
483
- | `triggerRotation(direction: string)` | `direction: 'cw' \| 'ccw'` | `Promise<ActionExecutionResult>` | Rotate document |
484
- | `goToLastPage()` | - | `Promise<ActionExecutionResult>` | Navigate to last page |
485
- | `sendViewerControlMessage(action: string, payload: any)` | `action: string, payload: any` | `Promise<any>` | Send custom control message |
486
- | `getActionStatus(actionId: string)` | `actionId: string` | `Promise<ActionExecutionResult \| null>` | Get action status |
487
- | `getQueueStatus()` | - | `{ queuedActions: number; executedActions: number }` | Get queue status |
488
- | `clearActionQueue()` | - | `void` | Clear action queue |
489
- | `reloadViewer()` | - | `void` | Reload viewer (alias for refresh) |
490
- | `goBack()` | - | `void` | Go back in browser history |
491
- | `closeViewer()` | - | `void` | Close viewer window |
492
- | `getErrorTemplateData()` | - | `any` | Get error template data |
493
-
494
- ---
495
-
496
- ## 🎨 Examples
497
-
498
- > **🎯 Live Demo**: [https://angular-pdf-viewer-demo.vercel.app/](https://angular-pdf-viewer-demo.vercel.app/)
499
- > **📁 Source Code**: [https://github.com/intbot/ng2-pdfjs-viewer/tree/main/SampleApp](https://github.com/intbot/ng2-pdfjs-viewer/tree/main/SampleApp)
500
-
501
- ### 1. Basic PDF Viewer
502
-
503
- ```html
504
- <ng2-pdfjs-viewer pdfSrc="assets/sample.pdf" [showSpinner]="true">
505
- </ng2-pdfjs-viewer>
506
- ```
507
-
508
- ### 2. Themed PDF Viewer
509
-
510
- ```html
511
- <ng2-pdfjs-viewer
512
- pdfSrc="assets/sample.pdf"
513
- [theme]="'dark'"
514
- [primaryColor]="'#ff6b6b'"
515
- [backgroundColor]="'#2c3e50'"
516
- >
517
- </ng2-pdfjs-viewer>
518
- ```
519
-
520
- ### 3. Custom Loading & Error
521
-
522
- ```html
523
- <ng-template #loadingTemplate>
524
- <div class="loading">
525
- <mat-spinner></mat-spinner>
526
- <p>Loading your document...</p>
527
- </div>
528
- </ng-template>
529
-
530
- <ng-template #errorTemplate>
531
- <div class="error">
532
- <mat-icon>error_outline</mat-icon>
533
- <h3>Oops! Something went wrong</h3>
534
- <p>We couldn't load your PDF. Please try again.</p>
535
- <button mat-button (click)="retry()">Retry</button>
536
- </div>
537
- </ng-template>
538
-
539
- <ng2-pdfjs-viewer
540
- pdfSrc="assets/sample.pdf"
541
- [customSpinnerTpl]="loadingTemplate"
542
- [customErrorTpl]="errorTemplate"
543
- >
544
- </ng2-pdfjs-viewer>
545
- ```
546
-
547
- ### 4. Convenience Setters (Object-Based Configuration)
548
-
549
- ```typescript
550
- export class PdfController {
551
- // Group visibility configuration
552
- groupVisibility = {
553
- "download": true,
554
- "print": true,
555
- "find": true,
556
- "fullScreen": true,
557
- "openFile": true,
558
- "viewBookmark": true,
559
- "annotations": false
560
- };
561
-
562
- // Auto actions configuration
563
- autoActions = {
564
- "downloadOnLoad": false,
565
- "printOnLoad": false
566
- };
567
-
568
- // Control visibility configuration
569
- controlVisibility = {
570
- "showToolbarLeft": true,
571
- "showToolbarMiddle": true,
572
- "showToolbarRight": true,
573
- "showSecondaryToolbarToggle": true,
574
- "showSidebar": true,
575
- "showSidebarLeft": true,
576
- "showSidebarRight": true
577
- };
578
- }
579
- ```
580
-
581
- ```html
582
- <ng2-pdfjs-viewer
583
- pdfSrc="assets/sample.pdf"
584
- [groupVisibility]="groupVisibility"
585
- [autoActions]="autoActions"
586
- [controlVisibility]="controlVisibility"
587
- >
588
- </ng2-pdfjs-viewer>
589
- ```
590
-
591
- ### 5. Programmatic Control
592
-
593
- ```typescript
594
- export class PdfController {
595
- @ViewChild("pdfViewer") pdfViewer!: PdfJsViewerComponent;
596
-
597
- async loadDocument(url: string) {
598
- this.pdfViewer.pdfSrc = url;
599
- await this.pdfViewer.refresh();
600
- }
601
-
602
- async goToPage(page: number) {
603
- await this.pdfViewer.goToPage(page);
604
- }
605
-
606
- async setZoom(zoom: string) {
607
- await this.pdfViewer.setZoom(zoom);
608
- }
609
- }
610
- ```
611
-
612
- ### 6. Server-Side Integration
613
-
614
- For server-side developers, we provide comprehensive examples for integrating PDF APIs with ng2-pdfjs-viewer:
615
-
616
- **[📋 Server-Side Examples](../Server-Side-Examples.md)** - Complete examples for:
617
- - **ASP.NET Core (C#)** - RDLC reports, physical files, iTextSharp
618
- - **Node.js (Express)** - File serving, PDFKit, Puppeteer
619
- - **Python (FastAPI)** - ReportLab, WeasyPrint, file handling
620
- - **Java (Spring Boot)** - iText, JasperReports, file serving
621
- - **PHP (Laravel)** - TCPDF, DomPDF, file management
622
- - **Go (Gin)** - gofpdf, file serving, PDF generation
623
-
624
- Each example includes proper Content-Type headers, error handling, CORS configuration, and Angular integration patterns.
625
-
626
- ---
627
-
628
- ## 🔄 Migration Guide
629
-
630
- ### From v20.x to v25.x
631
-
632
- #### Breaking Changes
633
-
634
- 1. **PDF.js Upgrade**: Updated to v5.3.93 - some APIs may have changed
635
- 2. **Theme System**: New theme properties replace old styling options
636
- 3. **Error Handling**: Template-based error system replaces HTML strings
637
-
638
- #### Migration Steps
639
-
640
- 1. **Update Dependencies**
641
-
642
- ```bash
643
- npm install ng2-pdfjs-viewer@latest
644
- ```
645
-
646
- 2. **Update Theme Configuration**
647
-
648
- ```typescript
649
- // Old way
650
- [customCSS]="'body { background: red; }'"
651
-
652
- // New way
653
- [theme]="'light'"
654
- [primaryColor]="'#ff0000'"
655
- [backgroundColor]="'#ffffff'"
656
- ```
657
-
658
- 3. **Update Error Handling**
659
-
660
- ```html
661
- <!-- Old way -->
662
- [errorHtml]="'<div>Custom error</div>'"
663
-
664
- <!-- New way -->
665
- <ng-template #errorTemplate>
666
- <div>Custom error</div>
667
- </ng-template>
668
- <ng2-pdfjs-viewer [customErrorTpl]="errorTemplate"></ng2-pdfjs-viewer>
669
- ```
670
-
671
- 4. **Update Spinner Handling**
672
-
673
- ```html
674
- <!-- Old way -->
675
- [spinnerHtml]="'<div class=\"spinner\">Loading...</div>'"
676
-
677
- <!-- New way -->
678
- <ng-template #spinnerTemplate>
679
- <div class="spinner">Loading...</div>
680
- </ng-template>
681
- <ng2-pdfjs-viewer [customSpinnerTpl]="spinnerTemplate"></ng2-pdfjs-viewer>
682
- ```
683
-
684
- ```typescript
685
- // Old way
686
- this.pdfViewer.setSpinnerHtml('<div>Loading...</div>');
687
-
688
- // New way
689
- // Use [customSpinnerTpl] with ng-template
690
- ```
691
-
692
- ---
693
-
694
- ## Deprecated Features
695
-
696
- The following features are deprecated and will be removed in future versions:
697
-
698
- ### Deprecated Properties
699
-
700
- | Deprecated | Replacement | Description |
701
- | ----------------- | -------------------- | --------------------------------------------- |
702
- | `[startDownload]` | `[downloadOnLoad]` | Download document automatically when it opens |
703
- | `[startPrint]` | `[printOnLoad]` | Print document automatically when it opens |
704
- | `[errorHtml]` | `[customErrorTpl]` | Custom error HTML (use template instead) |
705
- | `[errorTemplate]` | `[customErrorTpl]` | Custom error template (renamed) |
706
- | `[spinnerHtml]` | `[customSpinnerTpl]` | Custom spinner HTML (use template instead) |
707
-
708
- ### Deprecated Methods
709
-
710
- | Deprecated | Replacement | Description |
711
- | ------------------ | ------------------------ | ---------------------------------------------- |
712
- | `setErrorHtml()` | Use `[customErrorTpl]` | Set custom error HTML (use template instead) |
713
- | `setSpinnerHtml()` | Use `[customSpinnerTpl]` | Set custom spinner HTML (use template instead) |
714
-
715
- ### Migration Help
716
-
717
- ```typescript
718
- // Deprecated - Error Handling
719
- this.pdfViewer.setErrorHtml("<div>Error</div>");
720
-
721
- // New way - Error Handling
722
- // Use [customErrorTpl] with ng-template
723
-
724
- // Deprecated - Spinner Handling
725
- this.pdfViewer.setSpinnerHtml("<div>Loading...</div>");
726
-
727
- // New way - Spinner Handling
728
- // Use [customSpinnerTpl] with ng-template
729
- ```
730
-
731
- ---
732
-
733
- ## 📚 Additional Resources
734
-
735
- - **[Custom CSS Examples](Custom-CSS-Examples.md)** - Complete styling guide with theme customization examples
736
- - **[Error Display Examples](Error-Display-Examples.md)** - Custom error template examples and styling options
737
- - **[Contributing Guide](CONTRIBUTING.md)** - How to contribute to the project
738
-
739
- ## 🤝 Contributing
740
-
741
- We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
742
-
743
- ### Development Setup
744
-
745
- ```bash
746
- # Clone the repository
747
- git clone https://github.com/intbot/ng2-pdfjs-viewer.git
748
-
749
-
750
- # Clear Angular cache (Windows)
751
- Remove-Item -Recurse -Force "SampleApp\.angular"
752
-
753
-
754
- # Build and test - All at once (Windows)
755
- @test.bat
756
- ```
757
-
758
-
759
- ---
760
-
761
- ## 📄 License
762
-
763
- This project is licensed under the **Apache License 2.0 + Commons Clause License Condition v1.0** - see the [LICENSE](LICENSE) file for details.
764
-
765
- ---
766
-
767
- ## 🙏 Acknowledgments
768
-
769
-
770
-
771
- - **Community Contributors** - For bug reports, feature requests, and contributions
772
- - **7+ Million Users** - For trusting us with your PDF viewing needs
773
- - **Mozilla PDF.js Team** - For the amazing PDF.js library
774
-
775
- ---
776
-
777
- ## 📞 Support
778
-
779
- - 📖 **Documentation**: [GitHub Wiki](https://github.com/intbot/ng2-pdfjs-viewer/wiki)
780
- - 💬 **Community**: [GitHub Discussions](https://github.com/intbot/ng2-pdfjs-viewer/discussions)
781
- - 🐛 **Issues**: [GitHub Issues](https://github.com/intbot/ng2-pdfjs-viewer/issues)
782
- - 📧 **Email**: codehippie1@gmail.com
783
- - 📧 **Author**: [Aneesh Gopalakrishnan](http://github.com/codehippie1)
784
-
785
- ---
786
-
787
- <div align="center">
788
-
789
-
790
- [![GitHub](https://img.shields.io/badge/GitHub-Repository-blue?logo=github)](https://github.com/intbot/ng2-pdfjs-viewer)
791
- [![NPM](https://img.shields.io/badge/NPM-Package-red?logo=npm)](https://www.npmjs.com/package/ng2-pdfjs-viewer)
792
- [![Angular](https://img.shields.io/badge/Angular-Component-green?logo=angular)](https://angular.dev/overview)
793
-
794
- </div>
1
+ # Angular PDF viewer powered by Mozilla's PDF.js
2
+
3
+ The most reliable, feature-rich Angular PDF viewer component powered by Mozilla's PDF.js
4
+
5
+ <div align="center">
6
+ <img src="https://raw.githubusercontent.com/intbot/ng2-pdfjs-viewer/master/lib/logo.svg" alt="ng2-pdfjs-viewer Logo" width="120" height="140" />
7
+ </div>
8
+
9
+ <div align="center">
10
+
11
+ [![NPM Version](https://img.shields.io/npm/v/ng2-pdfjs-viewer?logo=npm&color=blue)](https://www.npmjs.com/package/ng2-pdfjs-viewer)
12
+ [![PDF.js Version](https://img.shields.io/badge/PDF.js%20v5.3.93-latest-green?logo=mozilla)](https://github.com/mozilla/pdf.js)
13
+ [![Angular Support](https://img.shields.io/badge/Angular%2020+-supported-red?logo=angular)](https://angular.dev/overview)
14
+ [![NPM Downloads](https://img.shields.io/npm/dm/ng2-pdfjs-viewer?label=downloads%2Fmonth&color=orange)](https://www.npmjs.com/package/ng2-pdfjs-viewer)
15
+ [![Total Downloads](https://img.shields.io/badge/total%20downloads-7M+-brightgreen?logo=npm)](https://www.npmjs.com/package/ng2-pdfjs-viewer)
16
+ [![Since 2018](https://img.shields.io/badge/since-2018-blue?logo=calendar)](https://www.npmjs.com/package/ng2-pdfjs-viewer)
17
+ [![License](https://img.shields.io/badge/license-Apache%202.0%20%2B%20Commons%20Clause-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
18
+ [![GitHub Stars](https://img.shields.io/github/stars/intbot/ng2-pdfjs-viewer?logo=github)](https://github.com/intbot/ng2-pdfjs-viewer)
19
+
20
+ </div>
21
+
22
+ <div align="center">
23
+
24
+ [**Live Demo**](https://angular-pdf-viewer-demo.vercel.app/) • [**Documentation**](https://angular-pdf-viewer-docs.vercel.app/) • [**API Reference**](#-api-reference) • [**Examples**](#-examples) • [**Server Examples**](../Server-Side-Examples.md) • [**Migration Guide**](#-migration-guide)
25
+
26
+ </div>
27
+
28
+ ---
29
+
30
+ ng2-pdfjs-viewer is the most comprehensive and feature-rich Angular PDF viewer component available. **Born in 2018** and still going strong with over **7+ million downloads**, this battle-tested library has been trusted by developers worldwide for **over 8 years**, powering thousands of applications.
31
+
32
+ This powerful library enables developers to seamlessly integrate PDF viewing capabilities into Angular applications with enterprise-grade features, custom theming, and mobile-first responsive design. Built on Mozilla's PDF.js v5.3.93, ng2-pdfjs-viewer provides advanced PDF rendering, document navigation, search functionality, and extensive customization options.
33
+
34
+ Whether you need a simple embedded PDF viewer or a complex document management system, this component delivers the performance and flexibility required for modern Angular applications. **The most mature and reliable Angular PDF viewer solution** with continuous updates and long-term support.
35
+
36
+ ### Why Choose ng2-pdfjs-viewer?
37
+
38
+ - **🚀 Always Up-to-Date** - Continuously updated with the latest PDF.js versions and Angular compatibility
39
+ - **🏗️ Enterprise-Ready** - Built for production with comprehensive error handling and performance optimization
40
+ - **🎨 Highly Customizable** - Extensive theming options, custom templates, and flexible configuration
41
+ - **📱 Mobile Optimized** - Touch-friendly interface with responsive design for all screen sizes
42
+ - **🔧 Developer Friendly** - Full TypeScript support, comprehensive documentation, and easy integration
43
+ - **⚡ High Performance** - Event-driven architecture with efficient memory management and lazy loading
44
+ - **🌍 Global Support** - Multi-language support with automatic locale detection and RTL compatibility
45
+ - **🛡️ Production Tested** - Trusted by thousands of applications with millions of downloads
46
+ - **📈 Proven Track Record** - 8+ years of continuous development and community support
47
+ - **🔒 Security Focused** - Regular security updates and vulnerability patches
48
+
49
+ ### 🆕 Latest Features (v25.x)
50
+
51
+ | Feature | Description | Status |
52
+ | ----------------------------- | ------------------------------------------------------------------ | ------ |
53
+ | **Advanced Theme System** | CSS custom properties for complete visual customization | ✅ New |
54
+ | **Template-Based UI** | Custom loading spinners and error displays using Angular templates | ✅ New |
55
+ | **Convenience Configuration** | Object-based configuration for cleaner, more maintainable code | ✅ New |
56
+ | **Event-Driven Architecture** | Pure event-based system with universal action dispatcher | ✅ New |
57
+ | **Enhanced Error Handling** | Multiple error display styles with custom templates | ✅ New |
58
+ | **Mobile-First Design** | Responsive layout optimized for touch devices | ✅ New |
59
+ | **TypeScript Strict Mode** | Full type safety with comprehensive API coverage | ✅ New |
60
+
61
+ ### 🏆 Unique Advantages
62
+
63
+ - **Universal Action Dispatcher** - Single pathway for all actions with readiness validation
64
+ - **Template-Based Customization** - Use Angular templates for loading and error states
65
+ - **Comprehensive Event System** - 24+ events covering all user interactions and state changes
66
+ - **Advanced Configuration Objects** - Clean, object-based configuration for complex setups
67
+ - **Production-Ready Architecture** - Event-driven design with no timeouts or polling
68
+ - **Complete API Coverage** - 19+ methods with consistent Promise-based returns
69
+
70
+ ### 🎯 Perfect For
71
+
72
+ - **Enterprise Applications** - Robust, scalable PDF viewing for business applications
73
+ - **Document Management Systems** - Complete PDF handling with search and navigation
74
+ - **E-Learning Platforms** - Interactive PDF viewing for educational content
75
+ - **Financial Applications** - Secure PDF viewing for reports and statements
76
+ - **Healthcare Systems** - Reliable PDF viewing for medical documents
77
+ - **Government Portals** - Accessible PDF viewing for public services
78
+ - **E-Commerce Platforms** - Product catalogs and documentation viewing
79
+ - **Content Management Systems** - Integrated PDF viewing and management
80
+
81
+ ---
82
+
83
+ ## 📋 Table of Contents
84
+
85
+ - [Quick Start](#-quick-start)
86
+ - [Features](#-features)
87
+ - [Installation](#-installation)
88
+ - [Basic Usage](#-basic-usage)
89
+ - [Advanced Configuration](#advanced-configuration)
90
+ - [API Reference](#-api-reference)
91
+ - [Examples](#-examples)
92
+ - [Migration Guide](#-migration-guide)
93
+ - [Deprecated Features](#deprecated-features)
94
+ - [Contributing](#-contributing)
95
+ - [License](#-license)
96
+
97
+ ---
98
+
99
+ ## 🚀 Quick Start
100
+
101
+ > **🎯 Live Demo**: [https://angular-pdf-viewer-demo.vercel.app/](https://angular-pdf-viewer-demo.vercel.app/)
102
+ > **📚 Documentation**: [https://angular-pdf-viewer-docs.vercel.app/](https://angular-pdf-viewer-docs.vercel.app/)
103
+ > **📁 Source Code**: [https://github.com/intbot/ng2-pdfjs-viewer/tree/main/SampleApp](https://github.com/intbot/ng2-pdfjs-viewer/tree/main/SampleApp)
104
+
105
+ ### 1. Install the Package
106
+
107
+ ```bash
108
+ npm install ng2-pdfjs-viewer --save
109
+ ```
110
+
111
+ ### 2. Import the Module
112
+
113
+ ```typescript
114
+ import { NgModule } from "@angular/core";
115
+ import { BrowserModule } from "@angular/platform-browser";
116
+ import { PdfJsViewerModule } from "ng2-pdfjs-viewer";
117
+
118
+ @NgModule({
119
+ imports: [BrowserModule, PdfJsViewerModule],
120
+ // ... rest of your module
121
+ })
122
+ export class AppModule {}
123
+ ```
124
+
125
+ ### 3. Use in Your Component
126
+
127
+ ```html
128
+ <ng2-pdfjs-viewer
129
+ pdfSrc="assets/sample.pdf"
130
+ [showSpinner]="true"
131
+ [theme]="'light'"
132
+ >
133
+ </ng2-pdfjs-viewer>
134
+ ```
135
+
136
+ ### 4. Configure Assets (Required)
137
+
138
+ Add PDF.js assets to your `angular.json`:
139
+
140
+ ```json
141
+ {
142
+ "projects": {
143
+ "your-app": {
144
+ "architect": {
145
+ "build": {
146
+ "options": {
147
+ "assets": [
148
+ {
149
+ "glob": "**/*",
150
+ "input": "node_modules/ng2-pdfjs-viewer/pdfjs",
151
+ "output": "/assets/pdfjs"
152
+ }
153
+ ]
154
+ }
155
+ }
156
+ }
157
+ }
158
+ }
159
+ }
160
+ ```
161
+
162
+ ---
163
+
164
+ ## ✨ Features
165
+
166
+ **🎉 7+ Million Downloads & Counting!** - Trusted by developers worldwide for reliable PDF viewing in Angular applications since 2018.
167
+
168
+ ### 🎯 Core PDF Viewing Features
169
+
170
+ - **📄 High-Quality PDF Rendering** - Powered by Mozilla's PDF.js v5.3.93 for superior document display
171
+ - **🔄 Multiple Display Modes** - Embedded viewer, new window, or external tab options
172
+ - **📱 Mobile-First Responsive Design** - Touch-friendly controls optimized for all devices
173
+ - **🌍 Complete Internationalization** - Support for 50+ languages with automatic locale detection
174
+ - **⚡ Optimized Performance** - Lazy loading, memory management, and efficient rendering
175
+
176
+ ### 🎨 Visual Customization
177
+
178
+ - **🎨 Theme System** - Light, dark, and auto themes with custom color schemes
179
+ - **🎭 Custom Styling** - CSS custom properties for complete visual control
180
+ - **🔄 Loading States** - Custom loading spinners with template support
181
+ - **❌ Error Handling** - Multiple error display styles with custom templates
182
+ - **📐 Layout Control** - Toolbar density, sidebar width, and positioning options
183
+
184
+ ### 🔧 Developer Features
185
+
186
+ - **📝 TypeScript Support** - Full type safety with strict mode
187
+ - **🔌 Event System** - Comprehensive event handling for all user interactions
188
+ - **⚙️ Configuration Objects** - Convenience setters for cleaner code
189
+ - **🛠️ API Methods** - Promise-based methods for programmatic control
190
+ - **🐛 Debugging** - Built-in diagnostic logging and error tracking
191
+
192
+ ### 📊 Advanced Features
193
+
194
+ - **🔍 Search & Navigation** - Full-text search with highlighting
195
+ - **📖 Bookmarks & Attachments** - Document structure navigation
196
+ - **🖨️ Print & Download** - Built-in print and download functionality
197
+ - **🔄 Rotation & Zoom** - Document manipulation with smooth animations
198
+ - **📱 Touch Gestures** - Mobile-optimized touch interactions
199
+
200
+ ---
201
+
202
+ ## 📦 Installation
203
+
204
+ ### Prerequisites
205
+
206
+ - **Angular**: 20.0+ (recommended) | 2.0+ (supported)
207
+ - **Node.js**: 18.0+
208
+ - **TypeScript**: 5.0+
209
+
210
+ ### Angular Version Support
211
+
212
+ | Angular Version | Support Level | Notes |
213
+ |----------------|---------------|-------|
214
+ | **20.0+** | ✅ **Recommended** | Fully tested and optimized |
215
+ | **15.0 - 19.x** | ✅ **Supported** | Should work with minor testing |
216
+ | **10.0 - 14.x** | **Supported** | Compatible with testing |
217
+ | **2.0 - 9.x** | ⚠️ **Legacy** | May require additional testing |
218
+
219
+ **Note**: While the library supports Angular 2.0+, it's primarily tested and optimized for Angular 20+. For production use with older versions, thorough testing is recommended. The library uses relaxed peer dependencies (Angular >=10.0.0) to ensure compatibility across different Angular versions.
220
+
221
+ ### Install Package
222
+
223
+ ```bash
224
+ # Using npm
225
+ npm install ng2-pdfjs-viewer --save
226
+
227
+ # Using yarn
228
+ yarn add ng2-pdfjs-viewer
229
+
230
+ # Using pnpm
231
+ pnpm add ng2-pdfjs-viewer
232
+ ```
233
+
234
+ ### Configure Assets
235
+
236
+ Add PDF.js assets to your `angular.json`:
237
+
238
+ ```json
239
+ {
240
+ "projects": {
241
+ "your-app": {
242
+ "architect": {
243
+ "build": {
244
+ "options": {
245
+ "assets": [
246
+ {
247
+ "glob": "**/*",
248
+ "input": "node_modules/ng2-pdfjs-viewer/pdfjs",
249
+ "output": "/assets/pdfjs"
250
+ }
251
+ ]
252
+ }
253
+ }
254
+ }
255
+ }
256
+ }
257
+ }
258
+ ```
259
+
260
+ ---
261
+
262
+ ## 🎯 Basic Usage
263
+
264
+ ### Simple PDF Viewer
265
+
266
+ ```html
267
+ <ng2-pdfjs-viewer pdfSrc="assets/document.pdf" [showSpinner]="true">
268
+ </ng2-pdfjs-viewer>
269
+ ```
270
+
271
+ ### Advanced Configuration
272
+
273
+ ```html
274
+ <ng2-pdfjs-viewer
275
+ pdfSrc="assets/document.pdf"
276
+ [theme]="'dark'"
277
+ [primaryColor]="'#007acc'"
278
+ [showSpinner]="true"
279
+ [customSpinnerTpl]="customSpinner"
280
+ [customErrorTpl]="customError"
281
+ (onDocumentLoad)="onDocumentLoaded($event)"
282
+ (onPageChange)="onPageChanged($event)"
283
+ >
284
+ </ng2-pdfjs-viewer>
285
+ ```
286
+
287
+ ### Programmatic Control
288
+
289
+ ```typescript
290
+ import { Component, ViewChild } from "@angular/core";
291
+ import { PdfJsViewerComponent } from "ng2-pdfjs-viewer";
292
+
293
+ @Component({
294
+ template: `
295
+ <ng2-pdfjs-viewer #pdfViewer pdfSrc="document.pdf"></ng2-pdfjs-viewer>
296
+ <button (click)="goToPage(5)">Go to Page 5</button>
297
+ `,
298
+ })
299
+ export class MyComponent {
300
+ @ViewChild("pdfViewer") pdfViewer!: PdfJsViewerComponent;
301
+
302
+ async goToPage(page: number) {
303
+ await this.pdfViewer.goToPage(page);
304
+ }
305
+ }
306
+ ```
307
+
308
+ ---
309
+
310
+ ## Advanced Configuration
311
+
312
+ ### Theme Customization
313
+
314
+ ```typescript
315
+ // Component
316
+ export class MyComponent {
317
+ themeConfig = {
318
+ theme: "light",
319
+ primaryColor: "#007acc",
320
+ backgroundColor: "#ffffff",
321
+ toolbarColor: "#f5f5f5",
322
+ textColor: "#333333",
323
+ borderRadius: "8px",
324
+ };
325
+ }
326
+ ```
327
+
328
+ ```html
329
+ <!-- Template -->
330
+ <ng2-pdfjs-viewer [themeConfig]="themeConfig" [customCSS]="customStyles">
331
+ </ng2-pdfjs-viewer>
332
+ ```
333
+
334
+ ### Custom Loading Spinner
335
+
336
+ ```html
337
+ <ng-template #customSpinner>
338
+ <div class="custom-spinner">
339
+ <div class="spinner"></div>
340
+ <p>Loading PDF...</p>
341
+ </div>
342
+ </ng-template>
343
+
344
+ <ng2-pdfjs-viewer
345
+ [customSpinnerTpl]="customSpinner"
346
+ [spinnerClass]="'my-spinner'"
347
+ >
348
+ </ng2-pdfjs-viewer>
349
+ ```
350
+
351
+ ### Custom Error Display
352
+
353
+ ```html
354
+ <ng-template #customError>
355
+ <div class="error-container">
356
+ <mat-icon>error</mat-icon>
357
+ <h3>Failed to Load PDF</h3>
358
+ <p>Please check your internet connection and try again.</p>
359
+ <button mat-button (click)="retry()">Retry</button>
360
+ </div>
361
+ </ng-template>
362
+
363
+ <ng2-pdfjs-viewer [customErrorTpl]="customError" [errorClass]="'my-error'">
364
+ </ng2-pdfjs-viewer>
365
+ ```
366
+
367
+ ---
368
+
369
+ ## 📚 API Reference
370
+
371
+ ### Input Properties
372
+
373
+ | Property | Type | Default | Description |
374
+ | ---------------------------- | ----------------------------------------- | ------------ | ------------------------------------- |
375
+ | `pdfSrc` | `string \| Blob \| Uint8Array` | - | PDF source (URL, Blob, or byte array) |
376
+ | `viewerId` | `string` | auto | Unique viewer identifier |
377
+ | `viewerFolder` | `string` | `'assets'` | Path to PDF.js assets |
378
+ | `externalWindow` | `boolean` | `false` | Open in new window |
379
+ | `externalWindowOptions` | `string` | - | External window options |
380
+ | `target` | `string` | `'_blank'` | Target for external window |
381
+ | `theme` | `'light' \| 'dark' \| 'auto'` | `'light'` | Theme selection |
382
+ | `primaryColor` | `string` | `'#007acc'` | Primary color for UI elements |
383
+ | `backgroundColor` | `string` | `'#ffffff'` | Background color |
384
+ | `pageBorderColor` | `string` | - | Page border color |
385
+ | `toolbarColor` | `string` | - | Toolbar background color |
386
+ | `textColor` | `string` | - | Text color |
387
+ | `borderRadius` | `string` | - | Border radius |
388
+ | `customCSS` | `string` | - | Custom CSS styles |
389
+ | `showSpinner` | `boolean` | `true` | Show loading spinner |
390
+ | `customSpinnerTpl` | `TemplateRef` | - | Custom spinner template |
391
+ | `spinnerClass` | `string` | - | Custom spinner CSS class |
392
+ | `customErrorTpl` | `TemplateRef` | - | Custom error template |
393
+ | `errorClass` | `string` | - | Custom error CSS class |
394
+ | `errorOverride` | `boolean` | `false` | Override default error handling |
395
+ | `errorAppend` | `boolean` | `true` | Append to default error messages |
396
+ | `errorMessage` | `string` | - | Custom error message |
397
+ | `locale` | `string` | `'en-US'` | UI language |
398
+ | `useOnlyCssZoom` | `boolean` | `false` | Use CSS-based zoom for mobile |
399
+ | `diagnosticLogs` | `boolean` | `false` | Enable diagnostic logging |
400
+ | `zoom` | `string` | `'auto'` | Initial zoom level (two-way binding) |
401
+ | `page` | `number` | `1` | Initial page number |
402
+ | `namedDest` | `string` | - | Named destination to navigate to |
403
+ | `cursor` | `string` | `'select'` | Cursor type (two-way binding) |
404
+ | `scroll` | `string` | `'vertical'` | Scroll mode (two-way binding) |
405
+ | `spread` | `string` | `'none'` | Spread mode (two-way binding) |
406
+ | `pageMode` | `string` | `'none'` | Page mode (two-way binding) |
407
+ | `rotation` | `number` | `0` | Document rotation (two-way binding) |
408
+ | `showOpenFile` | `boolean` | `true` | Show open file button |
409
+ | `showDownload` | `boolean` | `true` | Show download button |
410
+ | `showPrint` | `boolean` | `true` | Show print button |
411
+ | `showFind` | `boolean` | `true` | Show search button |
412
+ | `showFullScreen` | `boolean` | `true` | Show fullscreen button |
413
+ | `showViewBookmark` | `boolean` | `true` | Show bookmark button |
414
+ | `showAnnotations` | `boolean` | `false` | Show annotations |
415
+ | `showToolbarLeft` | `boolean` | `true` | Show left toolbar section |
416
+ | `showToolbarMiddle` | `boolean` | `true` | Show middle toolbar section |
417
+ | `showToolbarRight` | `boolean` | `true` | Show right toolbar section |
418
+ | `showSecondaryToolbarToggle` | `boolean` | `true` | Show secondary toolbar toggle |
419
+ | `showSidebar` | `boolean` | `true` | Show sidebar |
420
+ | `showSidebarLeft` | `boolean` | `true` | Show left sidebar |
421
+ | `showSidebarRight` | `boolean` | `true` | Show right sidebar |
422
+ | `toolbarDensity` | `'compact' \| 'default' \| 'comfortable'` | `'default'` | Toolbar density |
423
+ | `sidebarWidth` | `string` | - | Sidebar width (e.g., '280px') |
424
+ | `toolbarPosition` | `'top' \| 'bottom'` | `'top'` | Toolbar position |
425
+ | `sidebarPosition` | `'left' \| 'right'` | `'left'` | Sidebar position |
426
+ | `responsiveBreakpoint` | `string \| number` | - | Responsive breakpoint |
427
+ | `downloadOnLoad` | `boolean` | `false` | Auto-download on load |
428
+ | `printOnLoad` | `boolean` | `false` | Auto-print on load |
429
+ | `rotateCW` | `boolean` | `false` | Rotate clockwise on load |
430
+ | `rotateCCW` | `boolean` | `false` | Rotate counter-clockwise on load |
431
+ | `showLastPageOnLoad` | `boolean` | `false` | Go to last page on load |
432
+ | `downloadFileName` | `string` | - | Custom download filename |
433
+ | `controlVisibility` | `ControlVisibilityConfig` | - | Control visibility configuration |
434
+ | `autoActions` | `AutoActionConfig` | - | Auto actions configuration |
435
+ | `errorHandling` | `ErrorConfig` | - | Error handling configuration |
436
+ | `viewerConfig` | `ViewerConfig` | - | Viewer configuration |
437
+ | `themeConfig` | `ThemeConfig` | - | Theme configuration |
438
+ | `groupVisibility` | `GroupVisibilityConfig` | - | Group visibility configuration |
439
+ | `layoutConfig` | `LayoutConfig` | - | Layout configuration |
440
+
441
+ ### Output Events
442
+
443
+ | Event | Type | Description |
444
+ | --------------------------- | ------------------------------------------ | ---------------------------------------------- |
445
+ | `onDocumentLoad` | `EventEmitter<void>` | Fired when document loads |
446
+ | `onDocumentInit` | `EventEmitter<void>` | Fired when document initializes |
447
+ | `onDocumentError` | `EventEmitter<DocumentError>` | Fired when document fails to load |
448
+ | `onPageChange` | `EventEmitter<ChangedPage>` | Fired when page changes |
449
+ | `onPagesInit` | `EventEmitter<PagesInfo>` | Fired when pages are initialized |
450
+ | `onPageRendered` | `EventEmitter<PageRenderInfo>` | Fired when a page is rendered |
451
+ | `onScaleChange` | `EventEmitter<ChangedScale>` | Fired when zoom/scale changes |
452
+ | `onRotationChange` | `EventEmitter<ChangedRotation>` | Fired when rotation changes |
453
+ | `onPresentationModeChanged` | `EventEmitter<PresentationMode>` | Fired when presentation mode changes |
454
+ | `onOpenFile` | `EventEmitter<void>` | Fired when open file is clicked |
455
+ | `onFind` | `EventEmitter<FindOperation>` | Fired when search is performed |
456
+ | `onUpdateFindMatchesCount` | `EventEmitter<FindMatchesCount>` | Fired when search matches are updated |
457
+ | `onMetadataLoaded` | `EventEmitter<DocumentMetadata>` | Fired when document metadata loads |
458
+ | `onOutlineLoaded` | `EventEmitter<DocumentOutline>` | Fired when document outline loads |
459
+ | `onAnnotationLayerRendered` | `EventEmitter<AnnotationLayerRenderEvent>` | Fired when annotation layer renders |
460
+ | `onBookmarkClick` | `EventEmitter<BookmarkClick>` | Fired when bookmark is clicked |
461
+ | `onIdle` | `EventEmitter<void>` | Fired when viewer becomes idle |
462
+ | `onBeforePrint` | `EventEmitter<void>` | Fired before printing |
463
+ | `onAfterPrint` | `EventEmitter<void>` | Fired after printing |
464
+ | `zoomChange` | `EventEmitter<string>` | Fired when zoom changes (two-way binding) |
465
+ | `cursorChange` | `EventEmitter<string>` | Fired when cursor changes (two-way binding) |
466
+ | `scrollChange` | `EventEmitter<string>` | Fired when scroll changes (two-way binding) |
467
+ | `spreadChange` | `EventEmitter<string>` | Fired when spread changes (two-way binding) |
468
+ | `pageModeChange` | `EventEmitter<string>` | Fired when page mode changes (two-way binding) |
469
+
470
+ ### Methods
471
+
472
+ | Method | Parameters | Returns | Description |
473
+ | -------------------------------------------------------- | ----------------------------------------------------------- | ---------------------------------------------------- | --------------------------------- |
474
+ | `refresh()` | - | `void` | Refresh viewer |
475
+ | `goToPage(page: number)` | `page: number` | `Promise<ActionExecutionResult>` | Navigate to specific page |
476
+ | `setPage(page: number)` | `page: number` | `Promise<ActionExecutionResult>` | Set current page |
477
+ | `setZoom(zoom: string)` | `zoom: string` | `Promise<ActionExecutionResult>` | Set zoom level |
478
+ | `setCursor(cursor: string)` | `cursor: 'select' \| 'hand' \| 'zoom'` | `Promise<ActionExecutionResult>` | Set cursor type |
479
+ | `setScroll(scroll: string)` | `scroll: 'vertical' \| 'horizontal' \| 'wrapped' \| 'page'` | `Promise<ActionExecutionResult>` | Set scroll mode |
480
+ | `setSpread(spread: string)` | `spread: 'none' \| 'odd' \| 'even'` | `Promise<ActionExecutionResult>` | Set spread mode |
481
+ | `setPageMode(mode: string)` | `mode: 'none' \| 'thumbs' \| 'bookmarks' \| 'attachments'` | `Promise<ActionExecutionResult>` | Set page mode |
482
+ | `triggerDownload()` | - | `Promise<ActionExecutionResult>` | Trigger download |
483
+ | `triggerPrint()` | - | `Promise<ActionExecutionResult>` | Trigger print |
484
+ | `triggerRotation(direction: string)` | `direction: 'cw' \| 'ccw'` | `Promise<ActionExecutionResult>` | Rotate document |
485
+ | `goToLastPage()` | - | `Promise<ActionExecutionResult>` | Navigate to last page |
486
+ | `sendViewerControlMessage(action: string, payload: any)` | `action: string, payload: any` | `Promise<any>` | Send custom control message |
487
+ | `getActionStatus(actionId: string)` | `actionId: string` | `Promise<ActionExecutionResult \| null>` | Get action status |
488
+ | `getQueueStatus()` | - | `{ queuedActions: number; executedActions: number }` | Get queue status |
489
+ | `clearActionQueue()` | - | `void` | Clear action queue |
490
+ | `reloadViewer()` | - | `void` | Reload viewer (alias for refresh) |
491
+ | `goBack()` | - | `void` | Go back in browser history |
492
+ | `closeViewer()` | - | `void` | Close viewer window |
493
+ | `getErrorTemplateData()` | - | `any` | Get error template data |
494
+
495
+ ---
496
+
497
+ ## 🎨 Examples
498
+
499
+ > **🎯 Live Demo**: [https://angular-pdf-viewer-demo.vercel.app/](https://angular-pdf-viewer-demo.vercel.app/)
500
+ > **📚 Documentation**: [https://angular-pdf-viewer-docs.vercel.app/](https://angular-pdf-viewer-docs.vercel.app/)
501
+ > **📁 Source Code**: [https://github.com/intbot/ng2-pdfjs-viewer/tree/main/SampleApp](https://github.com/intbot/ng2-pdfjs-viewer/tree/main/SampleApp)
502
+
503
+ ### 1. Basic PDF Viewer
504
+
505
+ ```html
506
+ <ng2-pdfjs-viewer pdfSrc="assets/sample.pdf" [showSpinner]="true">
507
+ </ng2-pdfjs-viewer>
508
+ ```
509
+
510
+ ### 2. Themed PDF Viewer
511
+
512
+ ```html
513
+ <ng2-pdfjs-viewer
514
+ pdfSrc="assets/sample.pdf"
515
+ [theme]="'dark'"
516
+ [primaryColor]="'#ff6b6b'"
517
+ [backgroundColor]="'#2c3e50'"
518
+ >
519
+ </ng2-pdfjs-viewer>
520
+ ```
521
+
522
+ ### 3. Custom Loading & Error
523
+
524
+ ```html
525
+ <ng-template #loadingTemplate>
526
+ <div class="loading">
527
+ <mat-spinner></mat-spinner>
528
+ <p>Loading your document...</p>
529
+ </div>
530
+ </ng-template>
531
+
532
+ <ng-template #errorTemplate>
533
+ <div class="error">
534
+ <mat-icon>error_outline</mat-icon>
535
+ <h3>Oops! Something went wrong</h3>
536
+ <p>We couldn't load your PDF. Please try again.</p>
537
+ <button mat-button (click)="retry()">Retry</button>
538
+ </div>
539
+ </ng-template>
540
+
541
+ <ng2-pdfjs-viewer
542
+ pdfSrc="assets/sample.pdf"
543
+ [customSpinnerTpl]="loadingTemplate"
544
+ [customErrorTpl]="errorTemplate"
545
+ >
546
+ </ng2-pdfjs-viewer>
547
+ ```
548
+
549
+ ### 4. Convenience Setters (Object-Based Configuration)
550
+
551
+ ```typescript
552
+ export class PdfController {
553
+ // Group visibility configuration
554
+ groupVisibility = {
555
+ "download": true,
556
+ "print": true,
557
+ "find": true,
558
+ "fullScreen": true,
559
+ "openFile": true,
560
+ "viewBookmark": true,
561
+ "annotations": false
562
+ };
563
+
564
+ // Auto actions configuration
565
+ autoActions = {
566
+ "downloadOnLoad": false,
567
+ "printOnLoad": false
568
+ };
569
+
570
+ // Control visibility configuration
571
+ controlVisibility = {
572
+ "showToolbarLeft": true,
573
+ "showToolbarMiddle": true,
574
+ "showToolbarRight": true,
575
+ "showSecondaryToolbarToggle": true,
576
+ "showSidebar": true,
577
+ "showSidebarLeft": true,
578
+ "showSidebarRight": true
579
+ };
580
+ }
581
+ ```
582
+
583
+ ```html
584
+ <ng2-pdfjs-viewer
585
+ pdfSrc="assets/sample.pdf"
586
+ [groupVisibility]="groupVisibility"
587
+ [autoActions]="autoActions"
588
+ [controlVisibility]="controlVisibility"
589
+ >
590
+ </ng2-pdfjs-viewer>
591
+ ```
592
+
593
+ ### 5. Programmatic Control
594
+
595
+ ```typescript
596
+ export class PdfController {
597
+ @ViewChild("pdfViewer") pdfViewer!: PdfJsViewerComponent;
598
+
599
+ async loadDocument(url: string) {
600
+ this.pdfViewer.pdfSrc = url;
601
+ await this.pdfViewer.refresh();
602
+ }
603
+
604
+ async goToPage(page: number) {
605
+ await this.pdfViewer.goToPage(page);
606
+ }
607
+
608
+ async setZoom(zoom: string) {
609
+ await this.pdfViewer.setZoom(zoom);
610
+ }
611
+ }
612
+ ```
613
+
614
+ ### 6. Server-Side Integration
615
+
616
+ For server-side developers, we provide comprehensive examples for integrating PDF APIs with ng2-pdfjs-viewer:
617
+
618
+ **[📋 Server-Side Examples](../Server-Side-Examples.md)** - Complete examples for:
619
+ - **ASP.NET Core (C#)** - RDLC reports, physical files, iTextSharp
620
+ - **Node.js (Express)** - File serving, PDFKit, Puppeteer
621
+ - **Python (FastAPI)** - ReportLab, WeasyPrint, file handling
622
+ - **Java (Spring Boot)** - iText, JasperReports, file serving
623
+ - **PHP (Laravel)** - TCPDF, DomPDF, file management
624
+ - **Go (Gin)** - gofpdf, file serving, PDF generation
625
+
626
+ Each example includes proper Content-Type headers, error handling, CORS configuration, and Angular integration patterns.
627
+
628
+ ---
629
+
630
+ ## 🔄 Migration Guide
631
+
632
+ ### From v20.x to v25.x
633
+
634
+ #### Breaking Changes
635
+
636
+ 1. **PDF.js Upgrade**: Updated to v5.3.93 - some APIs may have changed
637
+ 2. **Theme System**: New theme properties replace old styling options
638
+ 3. **Error Handling**: Template-based error system replaces HTML strings
639
+
640
+ #### Migration Steps
641
+
642
+ 1. **Update Dependencies**
643
+
644
+ ```bash
645
+ npm install ng2-pdfjs-viewer@latest
646
+ ```
647
+
648
+ 2. **Update Theme Configuration**
649
+
650
+ ```typescript
651
+ // Old way
652
+ [customCSS]="'body { background: red; }'"
653
+
654
+ // New way
655
+ [theme]="'light'"
656
+ [primaryColor]="'#ff0000'"
657
+ [backgroundColor]="'#ffffff'"
658
+ ```
659
+
660
+ 3. **Update Error Handling**
661
+
662
+ ```html
663
+ <!-- Old way -->
664
+ [errorHtml]="'<div>Custom error</div>'"
665
+
666
+ <!-- New way -->
667
+ <ng-template #errorTemplate>
668
+ <div>Custom error</div>
669
+ </ng-template>
670
+ <ng2-pdfjs-viewer [customErrorTpl]="errorTemplate"></ng2-pdfjs-viewer>
671
+ ```
672
+
673
+ 4. **Update Spinner Handling**
674
+
675
+ ```html
676
+ <!-- Old way -->
677
+ [spinnerHtml]="'<div class=\"spinner\">Loading...</div>'"
678
+
679
+ <!-- New way -->
680
+ <ng-template #spinnerTemplate>
681
+ <div class="spinner">Loading...</div>
682
+ </ng-template>
683
+ <ng2-pdfjs-viewer [customSpinnerTpl]="spinnerTemplate"></ng2-pdfjs-viewer>
684
+ ```
685
+
686
+ ```typescript
687
+ // Old way
688
+ this.pdfViewer.setSpinnerHtml('<div>Loading...</div>');
689
+
690
+ // New way
691
+ // Use [customSpinnerTpl] with ng-template
692
+ ```
693
+
694
+ ---
695
+
696
+ ## Deprecated Features
697
+
698
+ The following features are deprecated and will be removed in future versions:
699
+
700
+ ### Deprecated Properties
701
+
702
+ | Deprecated | Replacement | Description |
703
+ | ----------------- | -------------------- | --------------------------------------------- |
704
+ | `[startDownload]` | `[downloadOnLoad]` | Download document automatically when it opens |
705
+ | `[startPrint]` | `[printOnLoad]` | Print document automatically when it opens |
706
+ | `[errorHtml]` | `[customErrorTpl]` | Custom error HTML (use template instead) |
707
+ | `[errorTemplate]` | `[customErrorTpl]` | Custom error template (renamed) |
708
+ | `[spinnerHtml]` | `[customSpinnerTpl]` | Custom spinner HTML (use template instead) |
709
+
710
+ ### Deprecated Methods
711
+
712
+ | Deprecated | Replacement | Description |
713
+ | ------------------ | ------------------------ | ---------------------------------------------- |
714
+ | `setErrorHtml()` | Use `[customErrorTpl]` | Set custom error HTML (use template instead) |
715
+ | `setSpinnerHtml()` | Use `[customSpinnerTpl]` | Set custom spinner HTML (use template instead) |
716
+
717
+ ### Migration Help
718
+
719
+ ```typescript
720
+ // Deprecated - Error Handling
721
+ this.pdfViewer.setErrorHtml("<div>Error</div>");
722
+
723
+ // New way - Error Handling
724
+ // Use [customErrorTpl] with ng-template
725
+
726
+ // Deprecated - Spinner Handling
727
+ this.pdfViewer.setSpinnerHtml("<div>Loading...</div>");
728
+
729
+ // New way - Spinner Handling
730
+ // Use [customSpinnerTpl] with ng-template
731
+ ```
732
+
733
+ ---
734
+
735
+ ## 📚 Additional Resources
736
+
737
+ - **[Custom CSS Examples](Custom-CSS-Examples.md)** - Complete styling guide with theme customization examples
738
+ - **[Error Display Examples](Error-Display-Examples.md)** - Custom error template examples and styling options
739
+ - **[Contributing Guide](CONTRIBUTING.md)** - How to contribute to the project
740
+
741
+ ## 🤝 Contributing
742
+
743
+ We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.
744
+
745
+ ### Development Setup
746
+
747
+ ```bash
748
+ # Clone the repository
749
+ git clone https://github.com/intbot/ng2-pdfjs-viewer.git
750
+
751
+
752
+ # Clear Angular cache (Windows)
753
+ Remove-Item -Recurse -Force "SampleApp\.angular"
754
+
755
+
756
+ # Build and test - All at once (Windows)
757
+ @test.bat
758
+ ```
759
+
760
+
761
+ ---
762
+
763
+ ## 📄 License
764
+
765
+ This project is licensed under the **Apache License 2.0 + Commons Clause License Condition v1.0** - see the [LICENSE](LICENSE) file for details.
766
+
767
+ ---
768
+
769
+ ## 🙏 Acknowledgments
770
+
771
+
772
+
773
+ - **Community Contributors** - For bug reports, feature requests, and contributions
774
+ - **7+ Million Users** - For trusting us with your PDF viewing needs
775
+ - **Mozilla PDF.js Team** - For the amazing PDF.js library
776
+
777
+ ---
778
+
779
+ ## 📞 Support
780
+
781
+ - 📖 **Documentation**: [GitHub Wiki](https://github.com/intbot/ng2-pdfjs-viewer/wiki)
782
+ - 💬 **Community**: [GitHub Discussions](https://github.com/intbot/ng2-pdfjs-viewer/discussions)
783
+ - 🐛 **Issues**: [GitHub Issues](https://github.com/intbot/ng2-pdfjs-viewer/issues)
784
+ - 📧 **Email**: codehippie1@gmail.com
785
+ - 📧 **Author**: [Aneesh Gopalakrishnan](http://github.com/codehippie1)
786
+
787
+ ---
788
+
789
+ <div align="center">
790
+
791
+
792
+ [![GitHub](https://img.shields.io/badge/GitHub-Repository-blue?logo=github)](https://github.com/intbot/ng2-pdfjs-viewer)
793
+ [![NPM](https://img.shields.io/badge/NPM-Package-red?logo=npm)](https://www.npmjs.com/package/ng2-pdfjs-viewer)
794
+ [![Angular](https://img.shields.io/badge/Angular-Component-green?logo=angular)](https://angular.dev/overview)
795
+
796
+ </div>