@gvorax/pdf-editor
v1.1.2
Published
Angular PDF editor library with annotation support (pen, highlighter, shapes, text, eraser)
Maintainers
Readme
@gvorax/pdf-editor
An Angular library for viewing and annotating PDF files. Supports freehand drawing, highlighting, text, shapes, eraser, undo/redo, zoom, and export.
Requirements
- Angular 17 or higher
fabric≥ 6.0.0pdfjs-dist≥ 4.0.0pdf-lib≥ 1.0.0
Installation
npm install @gvorax/pdf-editor fabric pdfjs-dist pdf-libConfigure the PDF.js worker
In your angular.json, add the worker and WASM files to the assets of your application:
"assets": [
"src/favicon.ico",
"src/assets",
{
"glob": "pdf.worker.mjs",
"input": "node_modules/pdfjs-dist/build/",
"output": "/"
},
{
"glob": "*.wasm",
"input": "node_modules/pdfjs-dist/wasm/",
"output": "/wasm/"
}
]Note: The WASM files (
jbig2.wasm,openjpeg.wasm, etc.) are required by pdfjs-dist 5.x to decode scanned documents that use JBIG2/CCITTFax Group-4 image compression (common in Canon/Kyocera/Ricoh scanners). Without them, such pages render as blank white.
Basic Usage
Import PdfEditorComponent into your standalone component:
import { Component } from '@angular/core';
import { PdfEditorComponent } from '@gvorax/pdf-editor';
@Component({
selector: 'app-root',
standalone: true,
imports: [PdfEditorComponent],
template: `
<pdf-editor style="width: 100%; height: 100vh; display: block;" />
`,
})
export class AppComponent {}The editor renders a drag-and-drop zone when no PDF is loaded. The user can drop a PDF file or click the upload button.
Loading a PDF Programmatically
You can pass a URL, a File object, or an ArrayBuffer via the [src] input:
@Component({
imports: [PdfEditorComponent],
template: `<pdf-editor [src]="url" style="width:100%;height:100vh;display:block;" />`,
})
export class AppComponent {
url = 'https://example.com/document.pdf';
}Or trigger loading from a button using a @ViewChild reference:
import { Component, ViewChild } from '@angular/core';
import { PdfEditorComponent } from '@gvorax/pdf-editor';
@Component({
imports: [PdfEditorComponent],
template: `
<pdf-editor #editor style="width:100%;height:100vh;display:block;" />
<button (click)="load()">Load PDF</button>
`,
})
export class AppComponent {
@ViewChild('editor') editor!: PdfEditorComponent;
async load() {
await this.editor.loadSrc('https://example.com/document.pdf');
}
}Configuration
Pass an EditorConfig object to the [config] input to customize the editor:
import { PdfEditorComponent, EditorConfig } from '@gvorax/pdf-editor';
@Component({
imports: [PdfEditorComponent],
template: `<pdf-editor [config]="config" style="width:100%;height:100vh;display:block;" />`,
})
export class AppComponent {
config: EditorConfig = {
theme: 'dark',
toolbar: { position: 'left' },
defaultTool: 'pen',
pageGap: 24,
zoom: { default: 1.25, min: 0.5, max: 3, step: 0.25 },
};
}EditorConfig Options
| Option | Type | Default | Description |
|---|---|---|---|
| theme | 'light' \| 'dark' \| 'custom' | 'light' | Editor color theme |
| toolbar.position | 'top' \| 'bottom' \| 'left' \| 'right' | 'top' | Toolbar placement |
| toolbar.show | boolean | true | Show or hide the toolbar |
| toolbar.showSave | boolean | true | Show or hide the Save button in the toolbar |
| toolbar.tools | ToolType[] | all tools | Restrict which tools appear |
| defaultTool | ToolType | 'pen' | Active tool on load |
| defaultColor | string | '#e53935' | Default drawing color |
| colors | string[] | 8 colors | Color palette swatches |
| zoom.default | number | 1 | Initial zoom level |
| zoom.min | number | 0.5 | Minimum zoom level |
| zoom.max | number | 3 | Maximum zoom level |
| zoom.step | number | 0.25 | Zoom step on each click |
| pageGap | number | 16 | Gap between pages in px |
| cssVars | Record<string, string> | {} | Override CSS variables (use with theme: 'custom') |
Available Tools
| Tool | Value | Description |
|---|---|---|
| Select | 'select' | Select and move annotations |
| Pen | 'pen' | Freehand drawing |
| Highlighter | 'highlighter' | Semi-transparent freehand brush |
| Text | 'text' | Add a text box |
| Rectangle | 'rectangle' | Draw a rectangle |
| Circle | 'circle' | Draw an ellipse |
| Arrow | 'arrow' | Draw an arrow |
| Line | 'line' | Draw a straight line |
| Eraser | 'eraser' | Click an annotation to select it, then click the red ✕ control or press Delete to remove it |
Show only specific tools
import { EditorConfig, ToolType } from '@gvorax/pdf-editor';
config: EditorConfig = {
toolbar: {
tools: [ToolType.Pen, ToolType.Highlighter, ToolType.Text, ToolType.Eraser],
},
};Theming
Built-in themes
// Light (default)
config: EditorConfig = { theme: 'light' };
// Dark
config: EditorConfig = { theme: 'dark' };Custom theme via CSS variables
Set theme: 'custom' and override any --pfe-* variable:
config: EditorConfig = {
theme: 'custom',
cssVars: {
'--pfe-bg': '#1a1a2e',
'--pfe-toolbar-bg': '#16213e',
'--pfe-accent': '#e94560',
'--pfe-text': '#eaeaea',
'--pfe-border': '#0f3460',
},
};All available CSS variables
| Variable | Description |
|---|---|
| --pfe-bg | Editor background color |
| --pfe-toolbar-bg | Toolbar background color |
| --pfe-toolbar-shadow | Toolbar box shadow |
| --pfe-border | Border and divider color |
| --pfe-accent | Accent / active color |
| --pfe-accent-hover | Accent hover color |
| --pfe-hover | Button hover background |
| --pfe-text | Primary text color |
| --pfe-muted | Muted / secondary text color |
| --pfe-icon | Icon color |
| --pfe-page-shadow | PDF page drop shadow |
| --pfe-page-radius | PDF page border radius |
Keyboard Shortcuts
| Shortcut | Action |
|---|---|
| Ctrl + Z | Undo last annotation |
| Ctrl + Shift + Z | Redo |
| Ctrl + Y | Redo (alternative) |
| Delete / Backspace | Delete selected annotation (Select or Eraser mode) |
Triggering Save Programmatically
Hide the toolbar's Save button and call save() from your own UI via @ViewChild:
import { Component, ViewChild } from '@angular/core';
import { PdfEditorComponent, EditorConfig } from '@gvorax/pdf-editor';
@Component({
imports: [PdfEditorComponent],
template: `
<pdf-editor #editor [config]="config" style="width:100%;height:100vh;display:block;" />
<button (click)="editor.save()">Export PDF</button>
`,
})
export class AppComponent {
config: EditorConfig = {
toolbar: { showSave: false },
};
}Or call it from the component class:
@ViewChild('editor') editor!: PdfEditorComponent;
async handleSave(): Promise<void> {
await this.editor.save();
}Custom Worker / WASM URL
By default the library loads the PDF.js worker from /pdf.worker.mjs and WASM files from /wasm/. Override either via injection tokens in your app.config.ts:
import { ApplicationConfig } from '@angular/core';
import { PDFJS_WORKER_URL, PDFJS_WASM_URL } from '@gvorax/pdf-editor';
export const appConfig: ApplicationConfig = {
providers: [
{ provide: PDFJS_WORKER_URL, useValue: '/assets/pdf.worker.mjs' },
{ provide: PDFJS_WASM_URL, useValue: '/assets/wasm/' },
],
};License
MIT
