genus-pdf-viewer 0.0.5

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 ADDED
@@ -0,0 +1,73 @@
1
+ # @genus/pdf-viewer
2
+
3
+ Angular PDF viewer built on pdf.js (`pdfjs-dist`) with a small API and worker setup that works in Amplify/Capacitor.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm i pdfjs-dist
9
+ ```
10
+
11
+ This library declares `pdfjs-dist` as a dependency and Angular as peer dependencies.
12
+
13
+ ## Worker setup (recommended: library provider)
14
+
15
+ Use the provider shipped by the library, which sets a sensible default and allows overrides.
16
+
17
+ ```ts
18
+ // main.ts or app.config.ts
19
+ import { bootstrapApplication } from '@angular/platform-browser';
20
+ import { provideGenusPdfViewer } from '@genus/pdf-viewer';
21
+ import { AppComponent } from './app/app.component';
22
+
23
+ bootstrapApplication(AppComponent, {
24
+ providers: [
25
+ provideGenusPdfViewer({
26
+ // optional overrides:
27
+ // workerSrc: '/assets/pdf.worker.min.mjs',
28
+ // tryModuleWorker: true,
29
+ })
30
+ ]
31
+ });
32
+ ```
33
+
34
+ Notes:
35
+ - The provider first tries a module worker (`new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url)`) and falls back to `workerSrc` if needed.
36
+ - Default `workerSrc` is `/assets/pdf.worker.min.mjs`. If using that, copy `node_modules/pdfjs-dist/build/pdf.worker.min.mjs` to `src/assets/pdf.worker.min.mjs` and ensure `angular.json` includes `src/assets`.
37
+ - Optional CMaps: copy `node_modules/pdfjs-dist/cmaps` to `src/assets/cmaps/` and set `cMapUrl`/`cMapPacked` if you enable text layer.
38
+
39
+ Manual alternative (not recommended): set `GlobalWorkerOptions.workerSrc` yourself at bootstrap.
40
+
41
+ ## Usage
42
+
43
+ ```ts
44
+ import { GenusPdfViewerComponent } from '@genus/pdf-viewer';
45
+ ```
46
+
47
+ ```html
48
+ <genus-pdf-viewer
49
+ [src]="docUrl"
50
+ [page]="page"
51
+ [fit]="'width'"
52
+ [zoom]="1.0"
53
+ [continuous]="true" <!-- render all pages stacked -->
54
+ [showToolbar]="true"> <!-- built-in toolbar -->
55
+ </genus-pdf-viewer>
56
+ ```
57
+
58
+ Inputs: `src`, `page`, `zoom`, `maxZoom`, `minZoom`, `fit`, `disableTextLayer`, `continuous`, `showToolbar`.
59
+
60
+ Methods (via `ViewChild`): `goTo(page)`, `zoomIn(step)`, `zoomOut(step)`.
61
+
62
+ ## Build
63
+
64
+ ```bash
65
+ ng build genus-pdf-viewer
66
+ ```
67
+
68
+ Artifacts appear in `dist/genus-pdf-viewer`.
69
+
70
+ ## Notes
71
+
72
+ - Keep worker at `/assets/pdf.worker.min.mjs` for Amplify/Capacitor.
73
+ - Ensure your server supports range requests for streaming PDFs.
@@ -0,0 +1,249 @@
1
+ import * as i0 from '@angular/core';
2
+ import { signal, effect, ViewChild, Input, Component, InjectionToken } from '@angular/core';
3
+ import * as i1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import * as pdfjsLib from 'pdfjs-dist';
6
+
7
+ class GenusPdfViewerComponent {
8
+ src;
9
+ page = 1;
10
+ zoom = 1.0;
11
+ maxZoom = 4;
12
+ minZoom = 0.25;
13
+ fit = 'width';
14
+ disableTextLayer = true;
15
+ continuous = true;
16
+ showToolbar = true;
17
+ canvas;
18
+ stage;
19
+ doc;
20
+ currentPage;
21
+ pageSig = signal(1, ...(ngDevMode ? [{ debugName: "pageSig" }] : []));
22
+ zoomSig = signal(1, ...(ngDevMode ? [{ debugName: "zoomSig" }] : []));
23
+ constructor() {
24
+ effect(() => { this.safeRender(); });
25
+ }
26
+ async ngOnChanges() {
27
+ this.pageSig.set(this.page);
28
+ this.zoomSig.set(this.zoom);
29
+ if (!this.src)
30
+ return;
31
+ const task = pdfjsLib.getDocument(this.src);
32
+ this.doc = await task.promise;
33
+ const pages = this.doc.numPages;
34
+ if (this.pageSig() < 1)
35
+ this.pageSig.set(1);
36
+ if (this.pageSig() > pages)
37
+ this.pageSig.set(pages);
38
+ await this.render();
39
+ }
40
+ async safeRender() {
41
+ try {
42
+ await this.render();
43
+ }
44
+ catch (_) { }
45
+ }
46
+ async render() {
47
+ if (!this.doc)
48
+ return;
49
+ if (this.continuous) {
50
+ await this.renderAllPages();
51
+ return;
52
+ }
53
+ const pageNum = this.pageSig();
54
+ const pdfPage = await this.doc.getPage(pageNum);
55
+ this.currentPage = pdfPage;
56
+ const canvas = this.canvas?.nativeElement;
57
+ if (!canvas)
58
+ return;
59
+ const ctx = canvas.getContext('2d');
60
+ const baseViewport = pdfPage.getViewport({ scale: 1 });
61
+ const parent = canvas.parentElement;
62
+ const pW = parent.clientWidth, pH = parent.clientHeight || baseViewport.height;
63
+ let baseScale = 1;
64
+ if (this.fit === 'width')
65
+ baseScale = (pW - 16) / baseViewport.width;
66
+ if (this.fit === 'height')
67
+ baseScale = (pH - 16) / baseViewport.height;
68
+ if (this.fit === 'page')
69
+ baseScale = Math.min((pW - 16) / baseViewport.width, (pH - 16) / baseViewport.height);
70
+ const minScale = baseScale * this.minZoom;
71
+ const maxScale = baseScale * this.maxZoom;
72
+ const finalScale = Math.max(minScale, Math.min(maxScale, baseScale * this.zoomSig()));
73
+ const viewport = pdfPage.getViewport({ scale: finalScale });
74
+ canvas.width = Math.floor(viewport.width);
75
+ canvas.height = Math.floor(viewport.height);
76
+ await pdfPage.render({ canvas, canvasContext: ctx, viewport }).promise;
77
+ }
78
+ async renderAllPages() {
79
+ if (!this.doc)
80
+ return;
81
+ const stageEl = this.stage?.nativeElement;
82
+ if (!stageEl)
83
+ return;
84
+ stageEl.innerHTML = '';
85
+ stageEl.scrollTop = 0;
86
+ const total = this.doc.numPages;
87
+ const parentRect = stageEl.getBoundingClientRect();
88
+ const parentWidth = parentRect.width || stageEl.clientWidth || 800;
89
+ for (let i = 1; i <= total; i++) {
90
+ const page = await this.doc.getPage(i);
91
+ const baseViewport = page.getViewport({ scale: 1 });
92
+ let baseScale = 1;
93
+ if (this.fit === 'width')
94
+ baseScale = (parentWidth - 16) / baseViewport.width;
95
+ if (this.fit === 'page')
96
+ baseScale = (parentWidth - 16) / baseViewport.width; // simple width-fit for page mode in continuous
97
+ const minScale = baseScale * this.minZoom;
98
+ const maxScale = baseScale * this.maxZoom;
99
+ const finalScale = Math.max(minScale, Math.min(maxScale, baseScale * this.zoomSig()));
100
+ const viewport = page.getViewport({ scale: finalScale });
101
+ const wrapper = document.createElement('div');
102
+ wrapper.className = 'pdf-page';
103
+ wrapper.setAttribute('data-page', String(i));
104
+ wrapper.style.width = Math.floor(viewport.width) + 'px';
105
+ wrapper.style.margin = '0 auto 12px auto';
106
+ const canvas = document.createElement('canvas');
107
+ canvas.width = Math.floor(viewport.width);
108
+ canvas.height = Math.floor(viewport.height);
109
+ const ctx = canvas.getContext('2d');
110
+ wrapper.appendChild(canvas);
111
+ stageEl.appendChild(wrapper);
112
+ await page.render({ canvas, canvasContext: ctx, viewport }).promise;
113
+ }
114
+ }
115
+ async goTo(page) {
116
+ if (!this.doc)
117
+ return;
118
+ const p = Math.max(1, Math.min(this.doc.numPages, page));
119
+ this.pageSig.set(p);
120
+ if (this.continuous) {
121
+ const stageEl = this.stage?.nativeElement;
122
+ const el = stageEl?.querySelector(`[data-page="${p}"]`);
123
+ el?.scrollIntoView({ behavior: 'smooth', block: 'start' });
124
+ }
125
+ else {
126
+ await this.render();
127
+ }
128
+ }
129
+ async zoomIn(step = 0.1) { this.zoomSig.set(Math.min(this.maxZoom, this.zoomSig() + step)); await this.render(); }
130
+ async zoomOut(step = 0.1) { this.zoomSig.set(Math.max(this.minZoom, this.zoomSig() - step)); await this.render(); }
131
+ async nextPage() { await this.goTo(this.pageSig() + 1); }
132
+ async prevPage() { await this.goTo(this.pageSig() - 1); }
133
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: GenusPdfViewerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
134
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.1", type: GenusPdfViewerComponent, isStandalone: true, selector: "genus-pdf-viewer", inputs: { src: "src", page: "page", zoom: "zoom", maxZoom: "maxZoom", minZoom: "minZoom", fit: "fit", disableTextLayer: "disableTextLayer", continuous: "continuous", showToolbar: "showToolbar" }, viewQueries: [{ propertyName: "canvas", first: true, predicate: ["canvas"], descendants: true }, { propertyName: "stage", first: true, predicate: ["stage"], descendants: true }], usesOnChanges: true, ngImport: i0, template: `
135
+ <div class="genus-pdf-shell">
136
+ <ng-content select="[toolbar]"></ng-content>
137
+
138
+ <div class="genus-pdf-toolbar" *ngIf="showToolbar">
139
+ <button type="button" title="Zoom out" aria-label="Zoom out" (click)="zoomOut()">−</button>
140
+ <span class="pct">{{ (zoomSig() * 100) | number:'1.0-0' }}%</span>
141
+ <button type="button" title="Zoom in" aria-label="Zoom in" (click)="zoomIn()">+</button>
142
+ <span class="spacer"></span>
143
+ <button type="button" title="Previous page" aria-label="Previous page" (click)="prevPage()" [disabled]="pageSig() <= 1">⟨</button>
144
+ <span>{{ pageSig() }} / {{ doc ? doc.numPages : 0 }}</span>
145
+ <button type="button" title="Next page" aria-label="Next page" (click)="nextPage()" [disabled]="doc ? pageSig() >= doc.numPages : true">⟩</button>
146
+ </div>
147
+
148
+ <div class="genus-pdf-stage" [style.display]="continuous ? 'none' : 'flex'">
149
+ <canvas #canvas></canvas>
150
+ </div>
151
+
152
+ <div class="genus-pdf-stage genus-pdf-stage--continuous" #stage [style.display]="continuous ? 'block' : 'none'"></div>
153
+ </div>
154
+ `, isInline: true, styles: [".genus-pdf-shell{display:flex;flex-direction:column;gap:8px;width:100%;height:100%;background:#f3f4f6}.genus-pdf-toolbar{position:sticky;top:0;z-index:2;display:flex;align-items:center;gap:8px;padding:6px 8px;border:1px solid #e5e7eb;border-radius:8px;background:#ffffffd9;-webkit-backdrop-filter:saturate(1.2) blur(6px);backdrop-filter:saturate(1.2) blur(6px);box-shadow:0 1px 2px #0000000f}.genus-pdf-toolbar .pct{min-width:48px;text-align:center;font-variant-numeric:tabular-nums;color:#111827}.genus-pdf-toolbar button{appearance:none;border:1px solid #e5e7eb;background:#fff;padding:6px 10px;border-radius:6px;cursor:pointer;color:#111827;font-size:14px;line-height:1;font-weight:500;min-width:32px;-webkit-user-select:none;user-select:none}.genus-pdf-toolbar button:disabled{opacity:.5;cursor:not-allowed}.genus-pdf-toolbar .spacer{flex:1}.genus-pdf-stage{flex:1;overflow:auto;display:flex;align-items:flex-start;justify-content:center;background:#fafafa}.genus-pdf-stage--continuous{display:block;align-items:unset;justify-content:unset;padding:8px;scroll-behavior:smooth}.genus-pdf-stage--continuous .pdf-page{margin:0 auto 12px;background:#fff;box-shadow:0 1px 2px #00000014}canvas{display:block;max-width:100%;height:auto}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "pipe", type: i1.DecimalPipe, name: "number" }] });
155
+ }
156
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.1", ngImport: i0, type: GenusPdfViewerComponent, decorators: [{
157
+ type: Component,
158
+ args: [{ selector: 'genus-pdf-viewer', standalone: true, imports: [CommonModule], template: `
159
+ <div class="genus-pdf-shell">
160
+ <ng-content select="[toolbar]"></ng-content>
161
+
162
+ <div class="genus-pdf-toolbar" *ngIf="showToolbar">
163
+ <button type="button" title="Zoom out" aria-label="Zoom out" (click)="zoomOut()">−</button>
164
+ <span class="pct">{{ (zoomSig() * 100) | number:'1.0-0' }}%</span>
165
+ <button type="button" title="Zoom in" aria-label="Zoom in" (click)="zoomIn()">+</button>
166
+ <span class="spacer"></span>
167
+ <button type="button" title="Previous page" aria-label="Previous page" (click)="prevPage()" [disabled]="pageSig() <= 1">⟨</button>
168
+ <span>{{ pageSig() }} / {{ doc ? doc.numPages : 0 }}</span>
169
+ <button type="button" title="Next page" aria-label="Next page" (click)="nextPage()" [disabled]="doc ? pageSig() >= doc.numPages : true">⟩</button>
170
+ </div>
171
+
172
+ <div class="genus-pdf-stage" [style.display]="continuous ? 'none' : 'flex'">
173
+ <canvas #canvas></canvas>
174
+ </div>
175
+
176
+ <div class="genus-pdf-stage genus-pdf-stage--continuous" #stage [style.display]="continuous ? 'block' : 'none'"></div>
177
+ </div>
178
+ `, styles: [".genus-pdf-shell{display:flex;flex-direction:column;gap:8px;width:100%;height:100%;background:#f3f4f6}.genus-pdf-toolbar{position:sticky;top:0;z-index:2;display:flex;align-items:center;gap:8px;padding:6px 8px;border:1px solid #e5e7eb;border-radius:8px;background:#ffffffd9;-webkit-backdrop-filter:saturate(1.2) blur(6px);backdrop-filter:saturate(1.2) blur(6px);box-shadow:0 1px 2px #0000000f}.genus-pdf-toolbar .pct{min-width:48px;text-align:center;font-variant-numeric:tabular-nums;color:#111827}.genus-pdf-toolbar button{appearance:none;border:1px solid #e5e7eb;background:#fff;padding:6px 10px;border-radius:6px;cursor:pointer;color:#111827;font-size:14px;line-height:1;font-weight:500;min-width:32px;-webkit-user-select:none;user-select:none}.genus-pdf-toolbar button:disabled{opacity:.5;cursor:not-allowed}.genus-pdf-toolbar .spacer{flex:1}.genus-pdf-stage{flex:1;overflow:auto;display:flex;align-items:flex-start;justify-content:center;background:#fafafa}.genus-pdf-stage--continuous{display:block;align-items:unset;justify-content:unset;padding:8px;scroll-behavior:smooth}.genus-pdf-stage--continuous .pdf-page{margin:0 auto 12px;background:#fff;box-shadow:0 1px 2px #00000014}canvas{display:block;max-width:100%;height:auto}\n"] }]
179
+ }], ctorParameters: () => [], propDecorators: { src: [{
180
+ type: Input
181
+ }], page: [{
182
+ type: Input
183
+ }], zoom: [{
184
+ type: Input
185
+ }], maxZoom: [{
186
+ type: Input
187
+ }], minZoom: [{
188
+ type: Input
189
+ }], fit: [{
190
+ type: Input
191
+ }], disableTextLayer: [{
192
+ type: Input
193
+ }], continuous: [{
194
+ type: Input
195
+ }], showToolbar: [{
196
+ type: Input
197
+ }], canvas: [{
198
+ type: ViewChild,
199
+ args: ['canvas', { static: false }]
200
+ }], stage: [{
201
+ type: ViewChild,
202
+ args: ['stage', { static: false }]
203
+ }] } });
204
+
205
+ const GENUS_PDF_WORKER_CONFIG = new InjectionToken('GENUS_PDF_WORKER_CONFIG');
206
+ function isBrowser() {
207
+ return typeof window !== 'undefined' && typeof document !== 'undefined';
208
+ }
209
+ function provideGenusPdfViewer(cfg = {}) {
210
+ const defaults = {
211
+ workerSrc: '/assets/pdf.worker.min.mjs',
212
+ tryModuleWorker: true,
213
+ };
214
+ const merged = { ...defaults, ...cfg };
215
+ return [
216
+ { provide: GENUS_PDF_WORKER_CONFIG, useValue: merged },
217
+ {
218
+ provide: 'GENUS_PDF_WORKER_INIT',
219
+ useFactory: (config) => {
220
+ if (!isBrowser())
221
+ return true;
222
+ try {
223
+ if (config.tryModuleWorker && 'Worker' in window) {
224
+ const w = new Worker(new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url), { type: 'module' });
225
+ pdfjsLib.GlobalWorkerOptions.workerPort = w;
226
+ return true;
227
+ }
228
+ }
229
+ catch {
230
+ // ignore, fall back to workerSrc
231
+ }
232
+ pdfjsLib.GlobalWorkerOptions.workerSrc = config.workerSrc;
233
+ return true;
234
+ },
235
+ deps: [GENUS_PDF_WORKER_CONFIG],
236
+ },
237
+ ];
238
+ }
239
+
240
+ /*
241
+ * Public API Surface of genus-pdf-viewer
242
+ */
243
+
244
+ /**
245
+ * Generated bundle index. Do not edit.
246
+ */
247
+
248
+ export { GENUS_PDF_WORKER_CONFIG, GenusPdfViewerComponent, provideGenusPdfViewer };
249
+ //# sourceMappingURL=genus-pdf-viewer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"genus-pdf-viewer.mjs","sources":["../../../projects/genus-pdf-viewer/src/lib/genus-pdf-viewer.ts","../../../projects/genus-pdf-viewer/src/lib/pdfjs-worker.provider.ts","../../../projects/genus-pdf-viewer/src/public-api.ts","../../../projects/genus-pdf-viewer/src/genus-pdf-viewer.ts"],"sourcesContent":["import { Component, Input, ViewChild, ElementRef, OnChanges, effect, signal } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport * as pdfjsLib from 'pdfjs-dist';\nimport type { PDFDocumentProxy, PDFPageProxy } from 'pdfjs-dist/types/src/display/api';\n\n@Component({\n selector: 'genus-pdf-viewer',\n standalone: true,\n imports: [CommonModule],\n template: `\n <div class=\"genus-pdf-shell\">\n <ng-content select=\"[toolbar]\"></ng-content>\n\n <div class=\"genus-pdf-toolbar\" *ngIf=\"showToolbar\">\n <button type=\"button\" title=\"Zoom out\" aria-label=\"Zoom out\" (click)=\"zoomOut()\">−</button>\n <span class=\"pct\">{{ (zoomSig() * 100) | number:'1.0-0' }}%</span>\n <button type=\"button\" title=\"Zoom in\" aria-label=\"Zoom in\" (click)=\"zoomIn()\">+</button>\n <span class=\"spacer\"></span>\n <button type=\"button\" title=\"Previous page\" aria-label=\"Previous page\" (click)=\"prevPage()\" [disabled]=\"pageSig() <= 1\">⟨</button>\n <span>{{ pageSig() }} / {{ doc ? doc.numPages : 0 }}</span>\n <button type=\"button\" title=\"Next page\" aria-label=\"Next page\" (click)=\"nextPage()\" [disabled]=\"doc ? pageSig() >= doc.numPages : true\">⟩</button>\n </div>\n\n <div class=\"genus-pdf-stage\" [style.display]=\"continuous ? 'none' : 'flex'\">\n <canvas #canvas></canvas>\n </div>\n\n <div class=\"genus-pdf-stage genus-pdf-stage--continuous\" #stage [style.display]=\"continuous ? 'block' : 'none'\"></div>\n </div>\n `,\n styles: [`\n .genus-pdf-shell { display:flex; flex-direction:column; gap:8px; width:100%; height:100%; background:#f3f4f6; }\n .genus-pdf-toolbar { position:sticky; top:0; z-index:2; display:flex; align-items:center; gap:8px; padding:6px 8px; border:1px solid #e5e7eb; border-radius:8px; background:#ffffffd9; backdrop-filter:saturate(1.2) blur(6px); box-shadow:0 1px 2px rgba(0,0,0,0.06); }\n .genus-pdf-toolbar .pct { min-width: 48px; text-align:center; font-variant-numeric: tabular-nums; color:#111827; }\n .genus-pdf-toolbar button { appearance:none; border:1px solid #e5e7eb; background:#fff; padding:6px 10px; border-radius:6px; cursor:pointer; color:#111827; font-size:14px; line-height:1; font-weight:500; min-width:32px; user-select:none; }\n .genus-pdf-toolbar button:disabled { opacity:0.5; cursor:not-allowed; }\n .genus-pdf-toolbar .spacer { flex:1; }\n .genus-pdf-stage { flex:1; overflow:auto; display:flex; align-items:flex-start; justify-content:center; background:#fafafa; }\n .genus-pdf-stage--continuous { display:block; align-items:unset; justify-content:unset; padding:8px; scroll-behavior:smooth; }\n .genus-pdf-stage--continuous .pdf-page { margin:0 auto 12px auto; background:white; box-shadow:0 1px 2px rgba(0,0,0,0.08); }\n canvas { display:block; max-width:100%; height:auto; }\n `]\n})\nexport class GenusPdfViewerComponent implements OnChanges {\n @Input() src!: string | URL | Uint8Array | Blob;\n @Input() page = 1;\n @Input() zoom = 1.0;\n @Input() maxZoom = 4;\n @Input() minZoom = 0.25;\n @Input() fit: 'width'|'height'|'page'|'none' = 'width';\n @Input() disableTextLayer = true;\n @Input() continuous = true;\n @Input() showToolbar = true;\n\n @ViewChild('canvas', { static: false }) canvas!: ElementRef<HTMLCanvasElement>;\n @ViewChild('stage', { static: false }) stage!: ElementRef<HTMLDivElement>;\n\n doc?: PDFDocumentProxy;\n private currentPage?: PDFPageProxy;\n\n pageSig = signal(1);\n zoomSig = signal(1);\n\n constructor() {\n effect(() => { this.safeRender(); });\n }\n\n async ngOnChanges() {\n this.pageSig.set(this.page);\n this.zoomSig.set(this.zoom);\n if (!this.src) return;\n\n const task = pdfjsLib.getDocument(this.src as any);\n this.doc = await task.promise;\n\n const pages = this.doc.numPages;\n if (this.pageSig() < 1) this.pageSig.set(1);\n if (this.pageSig() > pages) this.pageSig.set(pages);\n\n await this.render();\n }\n\n async safeRender() {\n try { await this.render(); } catch (_) {}\n }\n\n async render() {\n if (!this.doc) return;\n if (this.continuous) {\n await this.renderAllPages();\n return;\n }\n\n const pageNum = this.pageSig();\n const pdfPage = await this.doc.getPage(pageNum);\n this.currentPage = pdfPage;\n\n const canvas = this.canvas?.nativeElement;\n if (!canvas) return;\n const ctx = canvas.getContext('2d')!;\n\n const baseViewport = pdfPage.getViewport({ scale: 1 });\n const parent = canvas.parentElement!;\n const pW = parent.clientWidth, pH = parent.clientHeight || baseViewport.height;\n\n let baseScale = 1;\n if (this.fit === 'width') baseScale = (pW - 16) / baseViewport.width;\n if (this.fit === 'height') baseScale = (pH - 16) / baseViewport.height;\n if (this.fit === 'page') baseScale = Math.min((pW - 16) / baseViewport.width, (pH - 16) / baseViewport.height);\n\n const minScale = baseScale * this.minZoom;\n const maxScale = baseScale * this.maxZoom;\n const finalScale = Math.max(minScale, Math.min(maxScale, baseScale * this.zoomSig()));\n const viewport = pdfPage.getViewport({ scale: finalScale });\n\n canvas.width = Math.floor(viewport.width);\n canvas.height = Math.floor(viewport.height);\n await pdfPage.render({ canvas, canvasContext: ctx, viewport }).promise;\n }\n\n private async renderAllPages() {\n if (!this.doc) return;\n const stageEl = this.stage?.nativeElement;\n if (!stageEl) return;\n stageEl.innerHTML = '';\n stageEl.scrollTop = 0;\n const total = this.doc.numPages;\n const parentRect = stageEl.getBoundingClientRect();\n const parentWidth = parentRect.width || stageEl.clientWidth || 800;\n\n for (let i = 1; i <= total; i++) {\n const page = await this.doc.getPage(i);\n const baseViewport = page.getViewport({ scale: 1 });\n let baseScale = 1;\n if (this.fit === 'width') baseScale = (parentWidth - 16) / baseViewport.width;\n if (this.fit === 'page') baseScale = (parentWidth - 16) / baseViewport.width; // simple width-fit for page mode in continuous\n const minScale = baseScale * this.minZoom;\n const maxScale = baseScale * this.maxZoom;\n const finalScale = Math.max(minScale, Math.min(maxScale, baseScale * this.zoomSig()));\n const viewport = page.getViewport({ scale: finalScale });\n\n const wrapper = document.createElement('div');\n wrapper.className = 'pdf-page';\n wrapper.setAttribute('data-page', String(i));\n wrapper.style.width = Math.floor(viewport.width) + 'px';\n wrapper.style.margin = '0 auto 12px auto';\n\n const canvas = document.createElement('canvas');\n canvas.width = Math.floor(viewport.width);\n canvas.height = Math.floor(viewport.height);\n const ctx = canvas.getContext('2d')!;\n\n wrapper.appendChild(canvas);\n stageEl.appendChild(wrapper);\n\n await page.render({ canvas, canvasContext: ctx, viewport }).promise;\n }\n }\n\n async goTo(page: number) {\n if (!this.doc) return;\n const p = Math.max(1, Math.min(this.doc.numPages, page));\n this.pageSig.set(p);\n if (this.continuous) {\n const stageEl = this.stage?.nativeElement;\n const el = stageEl?.querySelector(`[data-page=\"${p}\"]`) as HTMLElement | null;\n el?.scrollIntoView({ behavior: 'smooth', block: 'start' });\n } else {\n await this.render();\n }\n }\n async zoomIn(step = 0.1) { this.zoomSig.set(Math.min(this.maxZoom, this.zoomSig() + step)); await this.render(); }\n async zoomOut(step = 0.1) { this.zoomSig.set(Math.max(this.minZoom, this.zoomSig() - step)); await this.render(); }\n\n async nextPage() { await this.goTo(this.pageSig() + 1); }\n async prevPage() { await this.goTo(this.pageSig() - 1); }\n}\n","import { InjectionToken, Provider } from '@angular/core';\nimport * as pdfjsLib from 'pdfjs-dist';\n\nexport type GenusPdfWorkerConfig = {\n workerSrc?: string;\n tryModuleWorker?: boolean;\n};\n\nexport const GENUS_PDF_WORKER_CONFIG = new InjectionToken<GenusPdfWorkerConfig>('GENUS_PDF_WORKER_CONFIG');\n\nfunction isBrowser(): boolean {\n return typeof window !== 'undefined' && typeof document !== 'undefined';\n}\n\nexport function provideGenusPdfViewer(cfg: GenusPdfWorkerConfig = {}): Provider[] {\n const defaults: Required<GenusPdfWorkerConfig> = {\n workerSrc: '/assets/pdf.worker.min.mjs',\n tryModuleWorker: true,\n };\n const merged = { ...defaults, ...cfg };\n\n return [\n { provide: GENUS_PDF_WORKER_CONFIG, useValue: merged },\n {\n provide: 'GENUS_PDF_WORKER_INIT',\n useFactory: (config: GenusPdfWorkerConfig) => {\n if (!isBrowser()) return true;\n try {\n if (config.tryModuleWorker && 'Worker' in window) {\n const w = new Worker(\n new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url),\n { type: 'module' }\n );\n (pdfjsLib as any).GlobalWorkerOptions.workerPort = w;\n return true;\n }\n } catch {\n // ignore, fall back to workerSrc\n }\n (pdfjsLib as any).GlobalWorkerOptions.workerSrc = config.workerSrc;\n return true;\n },\n deps: [GENUS_PDF_WORKER_CONFIG],\n },\n ];\n}\n\n\n","/*\n * Public API Surface of genus-pdf-viewer\n */\n\nexport * from './lib/genus-pdf-viewer';\nexport { GenusPdfViewerComponent } from './lib/genus-pdf-viewer';\nexport * from './lib/pdfjs-worker.provider';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/index.d.ts ADDED
@@ -0,0 +1,43 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { OnChanges, ElementRef, InjectionToken, Provider } from '@angular/core';
3
+ import { PDFDocumentProxy } from 'pdfjs-dist/types/src/display/api';
4
+
5
+ declare class GenusPdfViewerComponent implements OnChanges {
6
+ src: string | URL | Uint8Array | Blob;
7
+ page: number;
8
+ zoom: number;
9
+ maxZoom: number;
10
+ minZoom: number;
11
+ fit: 'width' | 'height' | 'page' | 'none';
12
+ disableTextLayer: boolean;
13
+ continuous: boolean;
14
+ showToolbar: boolean;
15
+ canvas: ElementRef<HTMLCanvasElement>;
16
+ stage: ElementRef<HTMLDivElement>;
17
+ doc?: PDFDocumentProxy;
18
+ private currentPage?;
19
+ pageSig: _angular_core.WritableSignal<number>;
20
+ zoomSig: _angular_core.WritableSignal<number>;
21
+ constructor();
22
+ ngOnChanges(): Promise<void>;
23
+ safeRender(): Promise<void>;
24
+ render(): Promise<void>;
25
+ private renderAllPages;
26
+ goTo(page: number): Promise<void>;
27
+ zoomIn(step?: number): Promise<void>;
28
+ zoomOut(step?: number): Promise<void>;
29
+ nextPage(): Promise<void>;
30
+ prevPage(): Promise<void>;
31
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<GenusPdfViewerComponent, never>;
32
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<GenusPdfViewerComponent, "genus-pdf-viewer", never, { "src": { "alias": "src"; "required": false; }; "page": { "alias": "page"; "required": false; }; "zoom": { "alias": "zoom"; "required": false; }; "maxZoom": { "alias": "maxZoom"; "required": false; }; "minZoom": { "alias": "minZoom"; "required": false; }; "fit": { "alias": "fit"; "required": false; }; "disableTextLayer": { "alias": "disableTextLayer"; "required": false; }; "continuous": { "alias": "continuous"; "required": false; }; "showToolbar": { "alias": "showToolbar"; "required": false; }; }, {}, never, ["[toolbar]"], true, never>;
33
+ }
34
+
35
+ type GenusPdfWorkerConfig = {
36
+ workerSrc?: string;
37
+ tryModuleWorker?: boolean;
38
+ };
39
+ declare const GENUS_PDF_WORKER_CONFIG: InjectionToken<GenusPdfWorkerConfig>;
40
+ declare function provideGenusPdfViewer(cfg?: GenusPdfWorkerConfig): Provider[];
41
+
42
+ export { GENUS_PDF_WORKER_CONFIG, GenusPdfViewerComponent, provideGenusPdfViewer };
43
+ export type { GenusPdfWorkerConfig };
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "genus-pdf-viewer",
3
+ "version": "0.0.5",
4
+ "peerDependencies": {
5
+ "@angular/common": ">=17 <21",
6
+ "@angular/core": ">=17 <21"
7
+ },
8
+ "dependencies": {
9
+ "tslib": "^2.3.0",
10
+ "pdfjs-dist": "^5.4.149"
11
+ },
12
+ "sideEffects": false,
13
+ "module": "fesm2022/genus-pdf-viewer.mjs",
14
+ "typings": "index.d.ts",
15
+ "exports": {
16
+ "./package.json": {
17
+ "default": "./package.json"
18
+ },
19
+ ".": {
20
+ "types": "./index.d.ts",
21
+ "default": "./fesm2022/genus-pdf-viewer.mjs"
22
+ }
23
+ }
24
+ }