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