@aprova.ch/ngx-next-pdf-viewer 20.0.8
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 +145 -0
- package/fesm2022/aprova.ch-ngx-next-pdf-viewer.mjs +744 -0
- package/fesm2022/aprova.ch-ngx-next-pdf-viewer.mjs.map +1 -0
- package/index.d.ts +213 -0
- package/package.json +51 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aprova.ch-ngx-next-pdf-viewer.mjs","sources":["../../../projects/ngx-next-pdf-viewer/src/lib/tokens.ts","../../../projects/ngx-next-pdf-viewer/src/lib/ngx-next-pdf-viewer.component.ts","../../../projects/ngx-next-pdf-viewer/src/lib/ngx-next-pdf-viewer.component.html","../../../projects/ngx-next-pdf-viewer/src/aprova.ch-ngx-next-pdf-viewer.ts"],"sourcesContent":["import { InjectionToken } from '@angular/core';\n\n/**\n * URL to the PDF.js worker script.\n *\n * Default: `'assets/pdf.worker.min.mjs'`\n *\n * Override in your application by providing this token:\n * ```ts\n * providers: [\n * { provide: NGX_PDF_WORKER_SRC, useValue: 'assets/pdf.worker.min.mjs' }\n * ]\n * ```\n */\nexport const NGX_PDF_WORKER_SRC = new InjectionToken<string>(\n 'NGX_PDF_WORKER_SRC',\n { factory: () => 'assets/pdf.worker.min.mjs' }\n);\n","import {\n Component, Input, Output, EventEmitter, Inject,\n OnChanges, OnDestroy, SimpleChanges,\n ViewChild, ElementRef, ChangeDetectorRef,\n HostListener, NgZone, AfterViewInit\n} from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { FormsModule } from '@angular/forms';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { MatInputModule } from '@angular/material/input';\nimport { MatFormFieldModule } from '@angular/material/form-field';\nimport * as pdfjsLib from 'pdfjs-dist';\nimport { PDFDocumentProxy, PDFPageProxy } from 'pdfjs-dist';\n\nimport { BoundingBox, ContextMenuItem, PdfViewerLabels, ZoomMode } from './models';\nimport { NGX_PDF_WORKER_SRC } from './tokens';\n\n// ──────────────────────────────────────────────\n// Internal helpers\n// ──────────────────────────────────────────────\n\ninterface RenderedPage {\n pageNum: number;\n width: number;\n height: number;\n rotation: number;\n}\n\ninterface DragState {\n active: boolean;\n pageNum: number;\n startX: number;\n startY: number;\n currentX: number;\n currentY: number;\n}\n\ninterface SearchMatch {\n pageNum: number;\n polygon: number[];\n}\n\n// ──────────────────────────────────────────────\n// Component\n// ──────────────────────────────────────────────\n\n@Component({\n selector: 'ngx-next-pdf-viewer',\n standalone: true,\n imports: [\n CommonModule,\n FormsModule,\n MatIconModule,\n MatButtonModule,\n MatTooltipModule,\n MatInputModule,\n MatFormFieldModule\n ],\n templateUrl: './ngx-next-pdf-viewer.component.html',\n styleUrl: './ngx-next-pdf-viewer.component.scss'\n})\nexport class NgxNextPdfViewerComponent implements OnChanges, OnDestroy, AfterViewInit {\n\n // ── Inputs ──────────────────────────────────\n /** PDF file to display */\n @Input() blob: Blob | undefined;\n /** Bounding-box annotations to overlay */\n @Input() annotations: BoundingBox[] = [];\n /** Items shown in the context menu after drag-selecting boxes */\n @Input() contextMenuItems: ContextMenuItem[] = [];\n /** Fill colour for a single-clicked box (CSS colour string) */\n @Input() highlightingColor = 'rgba(255, 200, 0, 0.35)';\n /** Fill colour for drag-selected boxes (CSS colour string) */\n @Input() selectedColor = 'rgba(0, 120, 215, 0.35)';\n /** Stroke colour for all annotation polygons */\n @Input() annotationStroke = '#e97332';\n /** Initial zoom: numeric level (1.0 = 100 %) or 'fit-to-page' | 'fit-to-width' | 'fit-to-height' */\n @Input() initialZoom: ZoomMode = 1.5;\n /** Override any subset of the viewer's user-visible strings */\n @Input() labels: Partial<PdfViewerLabels> = {};\n\n private static readonly DEFAULT_LABELS: PdfViewerLabels = {\n zoomOut: 'Zoom out',\n zoomIn: 'Zoom in',\n rotateLeft: 'Rotate left',\n rotateRight: 'Rotate right',\n previousPage: 'Previous page',\n nextPage: 'Next page',\n search: 'Search',\n previousResult: 'Previous result',\n nextResult: 'Next result',\n previousAnnotation: 'Previous annotation',\n nextAnnotation: 'Next annotation',\n selectArea: 'Select area',\n selectText: 'Select & copy text',\n searchPlaceholder: 'Search in PDF…',\n noResults: 'No results',\n loading: 'Loading PDF…',\n noDocument: 'No PDF loaded',\n loadError: 'Failed to load PDF',\n };\n\n get l(): PdfViewerLabels {\n return { ...NgxNextPdfViewerComponent.DEFAULT_LABELS, ...this.labels };\n }\n\n // ── Outputs ─────────────────────────────────\n /** Fired when the user clicks a single annotation box */\n @Output() boxClicked = new EventEmitter<{ box: BoundingBox; selected: boolean }>();\n /** Fired when the user picks a context-menu item after drag-selection */\n @Output() boxesSelected = new EventEmitter<{ boxes: BoundingBox[]; action: string }>();\n\n // ── View refs ────────────────────────────────\n @ViewChild('pdfContainer') pdfContainer!: ElementRef<HTMLDivElement>;\n\n // ── PDF state ────────────────────────────────\n pdfDoc: PDFDocumentProxy | null = null;\n renderedPages: RenderedPage[] = [];\n currentPage = 1;\n totalPages = 0;\n zoom = 1.5;\n userRotation = 0;\n\n // ── Annotation state ─────────────────────────\n clickedBoxKey: string | null = null;\n multiSelectedKeys: Set<string> = new Set();\n\n // ── Drag-select state ────────────────────────\n drag: DragState = { active: false, pageNum: 0, startX: 0, startY: 0, currentX: 0, currentY: 0 };\n\n // ── Context-menu state ───────────────────────\n ctxVisible = false;\n ctxX = 0;\n ctxY = 0;\n\n // ── Search state ─────────────────────────────\n searchVisible = false;\n searchQuery = '';\n searchMatches: SearchMatch[] = [];\n searchIndex = -1;\n\n // ── Selection mode ───────────────────────────\n selectionMode: 'select-area' | 'select-text' = 'select-area';\n\n // ── Loading ──────────────────────────────────\n loading = false;\n loadError = false;\n\n private renderTasks: Map<number, any> = new Map();\n private textLayers: Map<number, any> = new Map();\n private wheelListener?: (e: WheelEvent) => void;\n\n constructor(\n private cdr: ChangeDetectorRef,\n private zone: NgZone,\n private el: ElementRef,\n @Inject(NGX_PDF_WORKER_SRC) workerSrc: string\n ) {\n pdfjsLib.GlobalWorkerOptions.workerSrc = workerSrc;\n }\n\n ngAfterViewInit(): void {\n if (typeof this.initialZoom === 'number') {\n this.zoom = this.initialZoom;\n }\n // Ctrl+scroll zooming – requires passive:false to call preventDefault()\n this.zone.runOutsideAngular(() => {\n this.wheelListener = (e: WheelEvent) => {\n if (!e.ctrlKey) return;\n e.preventDefault();\n this.zone.run(() => e.deltaY < 0 ? this.zoomIn() : this.zoomOut());\n };\n this.el.nativeElement.addEventListener('wheel', this.wheelListener, { passive: false });\n });\n }\n\n ngOnChanges(changes: SimpleChanges): void {\n if (changes['blob'] && this.blob) {\n console.log('load new file');\n this.loadPdf(this.blob);\n }\n if (changes['annotations'] && !changes['blob']) {\n console.log('set new annotations', this.annotations.length);\n this.cdr.detectChanges();\n if (this.annotations.length === 1) {\n this.scrollToBox(this.annotations[0]);\n }\n }\n }\n\n ngOnDestroy(): void {\n if (this.wheelListener) {\n this.el.nativeElement.removeEventListener('wheel', this.wheelListener);\n }\n this.removeAllTextLayers();\n this.pdfDoc?.destroy();\n }\n\n // ─────────────────────────────────────────────\n // PDF loading & rendering\n // ─────────────────────────────────────────────\n\n private async loadPdf(blob: Blob): Promise<void> {\n this.loading = true;\n this.loadError = false;\n this.renderedPages = [];\n this.clickedBoxKey = null;\n this.multiSelectedKeys.clear();\n this.searchMatches = [];\n this.searchIndex = -1;\n this.removeAllTextLayers();\n this.cdr.detectChanges();\n\n try {\n this.pdfDoc?.destroy();\n const buf = await blob.arrayBuffer();\n this.pdfDoc = await pdfjsLib.getDocument({ data: buf }).promise;\n this.totalPages = this.pdfDoc.numPages;\n this.currentPage = 1;\n if (typeof this.initialZoom !== 'number') {\n this.zoom = await this.computeFitZoom(this.initialZoom);\n }\n this.loading = false;\n this.cdr.detectChanges();\n\n for (let p = 1; p <= this.totalPages; p++) {\n await this.renderPage(p);\n }\n\n if (this.annotations.length === 1) {\n this.scrollToBox(this.annotations[0]);\n }\n } catch {\n this.loading = false;\n this.loadError = true;\n }\n this.cdr.detectChanges();\n }\n\n private async computeFitZoom(mode: Exclude<ZoomMode, number>): Promise<number> {\n if (!this.pdfDoc) return 1;\n const page = await this.pdfDoc.getPage(1);\n const rotation = (page.rotate + this.userRotation) % 360;\n const vp = page.getViewport({ scale: 1, rotation });\n page.cleanup();\n\n const container = this.pdfContainer?.nativeElement;\n if (!container) return 1;\n\n // Subtract the 16 px padding on each side defined in npv-scroll-inner\n const availW = container.clientWidth - 32;\n const availH = container.clientHeight - 32;\n const scaleW = availW / vp.width;\n const scaleH = availH / vp.height;\n\n switch (mode) {\n case 'fit-to-width': return scaleW;\n case 'fit-to-height': return scaleH;\n case 'fit-to-page': return Math.min(scaleW, scaleH);\n }\n }\n\n private async renderPage(pageNum: number): Promise<void> {\n if (!this.pdfDoc) return;\n const page: PDFPageProxy = await this.pdfDoc.getPage(pageNum);\n const totalRotation = (page.rotate + this.userRotation) % 360;\n const viewport = page.getViewport({ scale: this.zoom, rotation: totalRotation });\n\n // HiDPI: render at physical pixel density, display at CSS size\n const dpr = window.devicePixelRatio || 1;\n const hiResViewport = page.getViewport({ scale: this.zoom * dpr, rotation: totalRotation });\n\n const canvas = document.getElementById(`npv-canvas-${pageNum}`) as HTMLCanvasElement | null;\n if (!canvas) return;\n\n canvas.width = hiResViewport.width;\n canvas.height = hiResViewport.height;\n canvas.style.width = `${viewport.width}px`;\n canvas.style.height = `${viewport.height}px`;\n\n if (this.renderTasks.has(pageNum)) {\n try { this.renderTasks.get(pageNum).cancel(); } catch (_) {}\n }\n\n const ctx = canvas.getContext('2d')!;\n const task = page.render({ canvasContext: ctx, viewport: hiResViewport });\n this.renderTasks.set(pageNum, task);\n try {\n await task.promise;\n } catch (e: any) {\n if (e?.name !== 'RenderingCancelledException') console.error(e);\n return;\n }\n this.renderTasks.delete(pageNum);\n\n const existing = this.renderedPages.find(r => r.pageNum === pageNum);\n if (existing) {\n existing.width = viewport.width;\n existing.height = viewport.height;\n existing.rotation = totalRotation;\n } else {\n this.renderedPages.push({ pageNum, width: viewport.width, height: viewport.height, rotation: totalRotation });\n }\n this.cdr.detectChanges();\n page.cleanup();\n }\n\n private async rerenderAll(): Promise<void> {\n if (!this.pdfDoc) return;\n if (this.selectionMode === 'select-text') {\n this.removeAllTextLayers();\n }\n for (let p = 1; p <= this.totalPages; p++) {\n await this.renderPage(p);\n if (this.selectionMode === 'select-text') {\n await this.renderTextLayer(p);\n }\n }\n this.cdr.detectChanges();\n }\n\n // ─────────────────────────────────────────────\n // Coordinate transformation\n // ─────────────────────────────────────────────\n\n /** Converts a polygon (y=0 at top, any consistent unit) to SVG canvas coordinates */\n transformPolygon(\n polygon: number[],\n pdfWidth: number,\n pdfHeight: number,\n canvasWidth: number,\n canvasHeight: number,\n rotation: number\n ): number[] {\n const norm = ((rotation % 360) + 360) % 360;\n const result: number[] = [];\n for (let i = 0; i < polygon.length; i += 2) {\n const px = polygon[i];\n const py = polygon[i + 1];\n let cx: number, cy: number;\n switch (norm) {\n case 90:\n cx = (pdfHeight - py) * canvasWidth / pdfHeight;\n cy = px * canvasHeight / pdfWidth;\n break;\n case 180:\n cx = (pdfWidth - px) * canvasWidth / pdfWidth;\n cy = (pdfHeight - py) * canvasHeight / pdfHeight;\n break;\n case 270:\n cx = py * canvasWidth / pdfHeight;\n cy = (pdfWidth - px) * canvasHeight / pdfWidth;\n break;\n default:\n cx = px * canvasWidth / pdfWidth;\n cy = py * canvasHeight / pdfHeight;\n }\n result.push(cx, cy);\n }\n return result;\n }\n\n getSvgPoints(box: BoundingBox, pi: RenderedPage): string {\n const pts = this.transformPolygon(\n box.polygon, box.width, box.height, pi.width, pi.height, pi.rotation\n );\n const pairs: string[] = [];\n for (let i = 0; i < pts.length; i += 2) {\n pairs.push(`${pts[i].toFixed(2)},${pts[i + 1].toFixed(2)}`);\n }\n return pairs.join(' ');\n }\n\n private polygonBBox(pts: number[]): { x: number; y: number; w: number; h: number } {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (let i = 0; i < pts.length; i += 2) {\n minX = Math.min(minX, pts[i]); maxX = Math.max(maxX, pts[i]);\n minY = Math.min(minY, pts[i+1]); maxY = Math.max(maxY, pts[i+1]);\n }\n return { x: minX, y: minY, w: maxX - minX, h: maxY - minY };\n }\n\n private boxKey(box: BoundingBox): string {\n return JSON.stringify({ page: box.page, polygon: box.polygon });\n }\n\n // ─────────────────────────────────────────────\n // Template helpers\n // ─────────────────────────────────────────────\n\n getPageInfo(pageNum: number): RenderedPage | undefined {\n return this.renderedPages.find(r => r.pageNum === pageNum);\n }\n\n getBoxesForPage(pageNum: number): BoundingBox[] {\n return this.annotations.filter(b => b.page === pageNum);\n }\n\n isClicked(box: BoundingBox): boolean {\n return this.clickedBoxKey === this.boxKey(box);\n }\n\n isMultiSelected(box: BoundingBox): boolean {\n return this.multiSelectedKeys.has(this.boxKey(box));\n }\n\n pageRange(): number[] {\n return Array.from({ length: this.totalPages }, (_, i) => i + 1);\n }\n\n getDragRect(pageNum: number): { x: number; y: number; w: number; h: number } | null {\n if (!this.drag.active || this.drag.pageNum !== pageNum) return null;\n return {\n x: Math.min(this.drag.startX, this.drag.currentX),\n y: Math.min(this.drag.startY, this.drag.currentY),\n w: Math.abs(this.drag.currentX - this.drag.startX),\n h: Math.abs(this.drag.currentY - this.drag.startY)\n };\n }\n\n getSearchMatchesForPage(pageNum: number): SearchMatch[] {\n return this.searchMatches.filter(m => m.pageNum === pageNum);\n }\n\n getSearchIndexOffset(pageNum: number): number {\n return this.searchMatches.findIndex(m => m.pageNum === pageNum);\n }\n\n isCurrentSearchMatch(pageNum: number, localIndex: number): boolean {\n const offset = this.getSearchIndexOffset(pageNum);\n return offset >= 0 && offset + localIndex === this.searchIndex;\n }\n\n searchMatchPoints(m: SearchMatch): string {\n const pairs: string[] = [];\n for (let i = 0; i < m.polygon.length; i += 2) {\n pairs.push(`${m.polygon[i].toFixed(2)},${m.polygon[i + 1].toFixed(2)}`);\n }\n return pairs.join(' ');\n }\n\n // ─────────────────────────────────────────────\n // Box interaction\n // ─────────────────────────────────────────────\n\n onBoxClick(event: MouseEvent, box: BoundingBox): void {\n event.stopPropagation();\n this.ctxVisible = false;\n this.multiSelectedKeys.clear();\n const key = this.boxKey(box);\n const wasSelected = this.clickedBoxKey === key;\n this.clickedBoxKey = wasSelected ? null : key;\n this.cdr.detectChanges();\n this.boxClicked.emit({ box, selected: !wasSelected });\n }\n\n // ─────────────────────────────────────────────\n // Drag-select\n // ─────────────────────────────────────────────\n\n onSvgMouseDown(event: MouseEvent, pageNum: number): void {\n if (this.selectionMode === 'select-text') return;\n if (event.button !== 0) return;\n const tag = (event.target as Element).tagName?.toLowerCase();\n if (tag === 'polygon' || tag === 'title') return;\n this.ctxVisible = false;\n this.clickedBoxKey = null;\n const pt = this.svgPoint(event, pageNum);\n if (!pt) return;\n this.drag = { active: true, pageNum, startX: pt.x, startY: pt.y, currentX: pt.x, currentY: pt.y };\n }\n\n @HostListener('mousemove', ['$event'])\n onDocMouseMove(event: MouseEvent): void {\n if (!this.drag.active) return;\n const pt = this.svgPoint(event, this.drag.pageNum);\n if (!pt) return;\n this.drag.currentX = pt.x;\n this.drag.currentY = pt.y;\n this.cdr.detectChanges();\n }\n\n @HostListener('mouseup', ['$event'])\n onDocMouseUp(event: MouseEvent): void {\n if (!this.drag.active) return;\n const rect = this.getDragRect(this.drag.pageNum);\n this.drag.active = false;\n\n if (!rect || (rect.w < 5 && rect.h < 5)) { this.cdr.detectChanges(); return; }\n\n const pageInfo = this.getPageInfo(this.drag.pageNum);\n if (!pageInfo) { this.cdr.detectChanges(); return; }\n\n const hits: BoundingBox[] = [];\n for (const box of this.annotations) {\n const pts = this.transformPolygon(\n box.polygon, box.width, box.height, pageInfo.width, pageInfo.height, pageInfo.rotation\n );\n const bb = this.polygonBBox(pts);\n if (this.rectsIntersect(rect, bb)) hits.push(box);\n }\n\n this.multiSelectedKeys = new Set(hits.map(b => this.boxKey(b)));\n\n if (hits.length > 0 && this.contextMenuItems.length > 0) {\n this.ctxX = event.clientX;\n this.ctxY = event.clientY;\n this.ctxVisible = true;\n }\n this.cdr.detectChanges();\n }\n\n private svgPoint(event: MouseEvent, pageNum: number): { x: number; y: number } | null {\n const svg = document.getElementById(`npv-svg-${pageNum}`) as SVGSVGElement | null;\n if (!svg) return null;\n const r = svg.getBoundingClientRect();\n return { x: event.clientX - r.left, y: event.clientY - r.top };\n }\n\n private rectsIntersect(\n a: { x: number; y: number; w: number; h: number },\n b: { x: number; y: number; w: number; h: number }\n ): boolean {\n return !(a.x + a.w < b.x || b.x + b.w < a.x || a.y + a.h < b.y || b.y + b.h < a.y);\n }\n\n // ─────────────────────────────────────────────\n // Context menu\n // ─────────────────────────────────────────────\n\n onContextMenuAction(item: ContextMenuItem): void {\n this.ctxVisible = false;\n const selected = this.annotations.filter(b => this.multiSelectedKeys.has(this.boxKey(b)));\n this.boxesSelected.emit({ boxes: selected, action: item.action });\n this.multiSelectedKeys.clear();\n this.cdr.detectChanges();\n }\n\n @HostListener('document:click')\n onDocClick(): void {\n if (this.ctxVisible) { this.ctxVisible = false; this.cdr.detectChanges(); }\n }\n\n // ─────────────────────────────────────────────\n // Toolbar – zoom\n // ─────────────────────────────────────────────\n\n zoomIn(): void { this.zoom = Math.min(this.zoom + 0.25, 5); this.rerenderAll(); }\n zoomOut(): void { this.zoom = Math.max(this.zoom - 0.25, 0.25); this.rerenderAll(); }\n\n get zoomPercent(): number { return Math.round(this.zoom * 100); }\n\n // ─────────────────────────────────────────────\n // Toolbar – rotation\n // ─────────────────────────────────────────────\n\n rotateLeft(): void { this.userRotation = (this.userRotation + 270) % 360; this.rerenderAll(); }\n rotateRight(): void { this.userRotation = (this.userRotation + 90) % 360; this.rerenderAll(); }\n\n // ─────────────────────────────────────────────\n // Toolbar – page navigation\n // ─────────────────────────────────────────────\n\n goToPrevPage(): void { if (this.currentPage > 1) this.scrollToPageNum(this.currentPage - 1); }\n goToNextPage(): void { if (this.currentPage < this.totalPages) this.scrollToPageNum(this.currentPage + 1); }\n\n scrollToPageNum(pageNum: number): void {\n this.currentPage = pageNum;\n document.getElementById(`npv-page-${pageNum}`)?.scrollIntoView({ behavior: 'smooth', block: 'start' });\n }\n\n scrollToBox(box: BoundingBox): void {\n this.currentPage = box.page;\n console.log('scroll to page', this.currentPage)\n const pageEl = document.getElementById(`npv-page-${box.page}`);\n if (!pageEl) {\n console.log('no page element found, stop scrolling')\n return;\n }\n const pi = this.getPageInfo(box.page);\n if (!pi) {\n pageEl.scrollIntoView({ behavior: 'smooth', block: 'start' });\n console.log('scroll into view done')\n return;\n }\n const pts = this.transformPolygon(box.polygon, box.width, box.height, pi.width, pi.height, pi.rotation);\n const bb = this.polygonBBox(pts);\n const top = (pageEl as HTMLElement).offsetTop + bb.y - window.innerHeight / 2;\n this.pdfContainer?.nativeElement.scrollTo({ top, behavior: 'smooth' });\n console.log('scrolling to element done')\n }\n\n // ─────────────────────────────────────────────\n // Toolbar – search\n // ─────────────────────────────────────────────\n\n toggleSearch(): void {\n this.searchVisible = !this.searchVisible;\n if (!this.searchVisible) {\n this.searchQuery = '';\n this.searchMatches = [];\n this.searchIndex = -1;\n this.cdr.detectChanges();\n }\n }\n\n async onSearchInput(): Promise<void> {\n const q = this.searchQuery.trim().toLowerCase();\n this.searchMatches = [];\n this.searchIndex = -1;\n if (!q || !this.pdfDoc) { this.cdr.detectChanges(); return; }\n\n for (let p = 1; p <= this.totalPages; p++) {\n const pi = this.getPageInfo(p);\n if (!pi) continue;\n const page = await this.pdfDoc.getPage(p);\n const text = await page.getTextContent();\n const vp = page.getViewport({ scale: this.zoom, rotation: pi.rotation });\n\n for (const item of text.items as any[]) {\n if (!item.str) continue;\n const idx = item.str.toLowerCase().indexOf(q);\n if (idx < 0) continue;\n\n const charW = (item.width / item.str.length) || 6;\n const itemH = Math.abs(item.transform[3]) || 10;\n const x0 = item.transform[4] + idx * charW;\n const y0 = item.transform[5];\n\n const t = vp.transform;\n const applyT = (x: number, y: number): [number, number] =>\n [t[0]*x + t[2]*y + t[4], t[1]*x + t[3]*y + t[5]];\n\n const [cx0, cy0] = applyT(x0, y0 + itemH);\n const [cx1, cy1] = applyT(x0 + q.length * charW, y0);\n\n this.searchMatches.push({\n pageNum: p,\n polygon: [cx0, cy0, cx1, cy0, cx1, cy1, cx0, cy1]\n });\n }\n page.cleanup();\n }\n\n if (this.searchMatches.length > 0) {\n this.searchIndex = 0;\n this.scrollToSearchMatch(0);\n }\n this.cdr.detectChanges();\n }\n\n searchNext(): void {\n if (!this.searchMatches.length) return;\n this.searchIndex = (this.searchIndex + 1) % this.searchMatches.length;\n this.scrollToSearchMatch(this.searchIndex);\n this.cdr.detectChanges();\n }\n\n searchPrev(): void {\n if (!this.searchMatches.length) return;\n this.searchIndex = (this.searchIndex - 1 + this.searchMatches.length) % this.searchMatches.length;\n this.scrollToSearchMatch(this.searchIndex);\n this.cdr.detectChanges();\n }\n\n private scrollToSearchMatch(idx: number): void {\n const m = this.searchMatches[idx];\n if (!m) return;\n document.getElementById(`npv-page-${m.pageNum}`)?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n\n // ─────────────────────────────────────────────\n // Toolbar – annotation navigation\n // ─────────────────────────────────────────────\n\n get annotationIndex(): number {\n if (!this.clickedBoxKey) return -1;\n return this.annotations.findIndex(b => this.boxKey(b) === this.clickedBoxKey);\n }\n\n goToPrevAnnotation(): void {\n if (!this.annotations.length) return;\n const prev = (this.annotationIndex - 1 + this.annotations.length) % this.annotations.length;\n this.selectAnnotation(prev);\n }\n\n goToNextAnnotation(): void {\n if (!this.annotations.length) return;\n const next = (this.annotationIndex + 1) % this.annotations.length;\n this.selectAnnotation(next);\n }\n\n private selectAnnotation(index: number): void {\n const box = this.annotations[index];\n if (!box) return;\n this.multiSelectedKeys.clear();\n this.ctxVisible = false;\n this.clickedBoxKey = this.boxKey(box);\n this.cdr.detectChanges();\n this.scrollToBox(box);\n this.boxClicked.emit({ box, selected: true });\n }\n\n // ─────────────────────────────────────────────\n // Toolbar – selection mode\n // ─────────────────────────────────────────────\n\n toggleSelectionMode(): void {\n this.selectionMode = this.selectionMode === 'select-area' ? 'select-text' : 'select-area';\n if (this.selectionMode === 'select-text') {\n this.renderedPages.forEach(rp => this.renderTextLayer(rp.pageNum));\n } else {\n this.removeAllTextLayers();\n }\n this.cdr.detectChanges();\n }\n\n private async renderTextLayer(pageNum: number): Promise<void> {\n if (!this.pdfDoc) return;\n const pi = this.getPageInfo(pageNum);\n if (!pi) return;\n\n const wrapper = document.getElementById(`npv-page-${pageNum}`) as HTMLElement | null;\n if (!wrapper) return;\n\n this.removeTextLayer(pageNum);\n\n const page = await this.pdfDoc.getPage(pageNum);\n const totalRotation = (page.rotate + this.userRotation) % 360;\n const viewport = page.getViewport({ scale: this.zoom, rotation: totalRotation });\n\n const div = document.createElement('div');\n div.className = 'npv-text-layer';\n div.style.width = `${pi.width}px`;\n div.style.height = `${pi.height}px`;\n wrapper.appendChild(div);\n\n const textLayer = new (pdfjsLib as any).TextLayer({\n textContentSource: page.streamTextContent(),\n container: div,\n viewport,\n });\n\n this.textLayers.set(pageNum, textLayer);\n try {\n await textLayer.render();\n } catch (_) {}\n page.cleanup();\n }\n\n private removeTextLayer(pageNum: number): void {\n const tl = this.textLayers.get(pageNum);\n if (tl) {\n try { tl.cancel(); } catch (_) {}\n this.textLayers.delete(pageNum);\n }\n const wrapper = document.getElementById(`npv-page-${pageNum}`);\n wrapper?.querySelector('.npv-text-layer')?.remove();\n }\n\n private removeAllTextLayers(): void {\n for (const pageNum of Array.from(this.textLayers.keys())) {\n this.removeTextLayer(pageNum);\n }\n }\n\n // ─────────────────────────────────────────────\n // Scroll tracking\n // ─────────────────────────────────────────────\n\n onContainerScroll(): void {\n if (!this.pdfContainer) return;\n const top = this.pdfContainer.nativeElement.scrollTop;\n let closest = 1, minDist = Infinity;\n for (let p = 1; p <= this.totalPages; p++) {\n const el = document.getElementById(`npv-page-${p}`) as HTMLElement | null;\n if (!el) continue;\n const dist = Math.abs(el.offsetTop - top);\n if (dist < minDist) { minDist = dist; closest = p; }\n }\n if (this.currentPage !== closest) { this.currentPage = closest; this.cdr.detectChanges(); }\n }\n}\n","<div class=\"npv-root\">\n\n <!-- ─────────── Toolbar ─────────── -->\n <div class=\"npv-toolbar\">\n\n <button mat-icon-button [matTooltip]=\"l.zoomOut\" (click)=\"zoomOut()\" [disabled]=\"zoom <= 0.25\">\n <mat-icon>zoom_out</mat-icon>\n </button>\n <span class=\"npv-label\">{{ zoomPercent }}%</span>\n <button mat-icon-button [matTooltip]=\"l.zoomIn\" (click)=\"zoomIn()\" [disabled]=\"zoom >= 5\">\n <mat-icon>zoom_in</mat-icon>\n </button>\n\n <div class=\"npv-sep\"></div>\n\n <button mat-icon-button [matTooltip]=\"l.rotateLeft\" (click)=\"rotateLeft()\">\n <mat-icon>rotate_left</mat-icon>\n </button>\n <button mat-icon-button [matTooltip]=\"l.rotateRight\" (click)=\"rotateRight()\">\n <mat-icon>rotate_right</mat-icon>\n </button>\n\n <div class=\"npv-sep\"></div>\n\n <button mat-icon-button [matTooltip]=\"l.previousPage\" (click)=\"goToPrevPage()\" [disabled]=\"currentPage <= 1\">\n <mat-icon>chevron_left</mat-icon>\n </button>\n <span class=\"npv-label\">{{ currentPage }} / {{ totalPages }}</span>\n <button mat-icon-button [matTooltip]=\"l.nextPage\" (click)=\"goToNextPage()\" [disabled]=\"currentPage >= totalPages\">\n <mat-icon>chevron_right</mat-icon>\n </button>\n\n <ng-container *ngIf=\"annotations.length\">\n <div class=\"npv-sep\"></div>\n\n <button mat-icon-button [matTooltip]=\"l.previousAnnotation\" (click)=\"goToPrevAnnotation()\">\n <mat-icon>navigate_before</mat-icon>\n </button>\n <span class=\"npv-label\">\n {{ annotationIndex >= 0 ? annotationIndex + 1 : '–' }} / {{ annotations.length }}\n </span>\n <button mat-icon-button [matTooltip]=\"l.nextAnnotation\" (click)=\"goToNextAnnotation()\">\n <mat-icon>navigate_next</mat-icon>\n </button>\n </ng-container>\n\n <div class=\"npv-sep\"></div>\n\n <button mat-icon-button\n [matTooltip]=\"selectionMode === 'select-area' ? l.selectText : l.selectArea\"\n (click)=\"toggleSelectionMode()\"\n [class.npv-active]=\"selectionMode === 'select-text'\">\n <mat-icon>text_fields</mat-icon>\n </button>\n\n <div class=\"npv-sep\"></div>\n\n <button mat-icon-button [matTooltip]=\"l.search\" (click)=\"toggleSearch()\" [class.npv-active]=\"searchVisible\">\n <mat-icon>search</mat-icon>\n </button>\n\n <ng-container *ngIf=\"searchVisible\">\n <input\n class=\"npv-search-input\"\n type=\"text\"\n [placeholder]=\"l.searchPlaceholder\"\n [(ngModel)]=\"searchQuery\"\n (input)=\"onSearchInput()\"\n (keydown.enter)=\"searchNext()\"\n (keydown.shift.enter)=\"searchPrev()\"\n autofocus\n />\n <button mat-icon-button [matTooltip]=\"l.previousResult\"\n (click)=\"searchPrev()\" [disabled]=\"!searchMatches.length\">\n <mat-icon>expand_less</mat-icon>\n </button>\n <button mat-icon-button [matTooltip]=\"l.nextResult\"\n (click)=\"searchNext()\" [disabled]=\"!searchMatches.length\">\n <mat-icon>expand_more</mat-icon>\n </button>\n <span class=\"npv-search-count\" *ngIf=\"searchMatches.length\">\n {{ searchIndex + 1 }} / {{ searchMatches.length }}\n </span>\n <span class=\"npv-search-count npv-no-match\" *ngIf=\"searchQuery && !searchMatches.length\">\n {{ l.noResults }}\n </span>\n </ng-container>\n\n </div>\n\n <!-- ─────────── Loading ─────────── -->\n <div class=\"npv-loading\" *ngIf=\"loading\">\n <span class=\"npv-spinner\"></span> {{ l.loading }}\n </div>\n\n <!-- ─────────── Scroll area ─────────── -->\n <div class=\"npv-scroll-area\" #pdfContainer\n (scroll)=\"onContainerScroll()\" (click)=\"ctxVisible = false\">\n <div class=\"npv-scroll-inner\">\n\n <ng-container *ngFor=\"let p of pageRange()\">\n <div class=\"npv-page-wrapper\" [id]=\"'npv-page-' + p\">\n\n <canvas [id]=\"'npv-canvas-' + p\" class=\"npv-canvas\"></canvas>\n\n <svg *ngIf=\"getPageInfo(p) as pi\"\n [id]=\"'npv-svg-' + p\"\n class=\"npv-overlay\"\n [class.npv-overlay--text-mode]=\"selectionMode === 'select-text'\"\n [attr.width]=\"pi.width\" [attr.height]=\"pi.height\"\n [attr.viewBox]=\"'0 0 ' + pi.width + ' ' + pi.height\"\n (mousedown)=\"onSvgMouseDown($event, p)\">\n\n <!-- Hit area for drag selection on empty page space -->\n <rect x=\"0\" y=\"0\" [attr.width]=\"pi.width\" [attr.height]=\"pi.height\"\n fill=\"transparent\"></rect>\n\n <!-- Annotation boxes -->\n <polygon\n *ngFor=\"let box of getBoxesForPage(p)\"\n [attr.points]=\"getSvgPoints(box, pi)\"\n class=\"npv-box\"\n [class.npv-box--clicked]=\"isClicked(box)\"\n [class.npv-box--multi]=\"isMultiSelected(box)\"\n [style.fill]=\"isClicked(box) ? highlightingColor : (isMultiSelected(box) ? selectedColor : 'transparent')\"\n [style.stroke]=\"annotationStroke\"\n (click)=\"onBoxClick($event, box)\">\n <title>{{ box.content || '' }}</title>\n </polygon>\n\n <!-- Search highlights -->\n <polygon\n *ngFor=\"let m of getSearchMatchesForPage(p); let mi = index\"\n [attr.points]=\"searchMatchPoints(m)\"\n class=\"npv-search-highlight\"\n [class.npv-search-highlight--current]=\"isCurrentSearchMatch(p, mi)\">\n </polygon>\n\n <!-- Drag selection rectangle -->\n <rect *ngIf=\"getDragRect(p) as dr\"\n [attr.x]=\"dr.x\" [attr.y]=\"dr.y\"\n [attr.width]=\"dr.w\" [attr.height]=\"dr.h\"\n class=\"npv-drag-rect\">\n </rect>\n\n </svg>\n </div>\n </ng-container>\n\n <div class=\"npv-placeholder npv-placeholder--error\" *ngIf=\"!loading && loadError\">\n {{ l.loadError }}\n </div>\n <div class=\"npv-placeholder\" *ngIf=\"!loading && !loadError && totalPages === 0\">\n {{ l.noDocument }}\n </div>\n\n </div><!-- /npv-scroll-inner -->\n </div>\n\n <!-- ─────────── Context menu ─────────── -->\n <div *ngIf=\"ctxVisible && contextMenuItems.length\"\n class=\"npv-context-menu\"\n [style.left.px]=\"ctxX\" [style.top.px]=\"ctxY\"\n (click)=\"$event.stopPropagation()\">\n <div *ngFor=\"let item of contextMenuItems\"\n class=\"npv-context-item\"\n (click)=\"onContextMenuAction(item)\">\n {{ item.label }}\n </div>\n </div>\n\n</div>\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,213 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { OnChanges, OnDestroy, AfterViewInit, EventEmitter, ElementRef, ChangeDetectorRef, NgZone, SimpleChanges, InjectionToken } from '@angular/core';
|
|
3
|
+
import { PDFDocumentProxy } from 'pdfjs-dist';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A bounding box annotation returned by a document intelligence / OCR service.
|
|
7
|
+
* Coordinates are in pixel space with y=0 at the top of the page.
|
|
8
|
+
*/
|
|
9
|
+
interface BoundingBox {
|
|
10
|
+
/** 1-based page number */
|
|
11
|
+
page: number;
|
|
12
|
+
/** Original page width (pixels) used when the polygon was extracted */
|
|
13
|
+
width: number;
|
|
14
|
+
/** Original page height (pixels) used when the polygon was extracted */
|
|
15
|
+
height: number;
|
|
16
|
+
/**
|
|
17
|
+
* Quadrilateral vertices as a flat array:
|
|
18
|
+
* [x1, y1, x2, y2, x3, y3, x4, y4]
|
|
19
|
+
* – (x1,y1) = top-left, clockwise order, y=0 at top
|
|
20
|
+
*/
|
|
21
|
+
polygon: number[];
|
|
22
|
+
/** Optional text content of the region */
|
|
23
|
+
content?: string;
|
|
24
|
+
/** Coordinate hint (e.g. "pixel") */
|
|
25
|
+
unit?: string;
|
|
26
|
+
/** Page rotation angle when the polygon was extracted */
|
|
27
|
+
angle?: number;
|
|
28
|
+
/** Any additional fields from the source document */
|
|
29
|
+
[key: string]: any;
|
|
30
|
+
}
|
|
31
|
+
/** Numeric zoom level (1.0 = 100 %) or a fit mode applied when the PDF first loads */
|
|
32
|
+
type ZoomMode = number | 'fit-to-page' | 'fit-to-width' | 'fit-to-height';
|
|
33
|
+
/** All user-visible strings rendered by the viewer. Pass a partial object to override any subset. */
|
|
34
|
+
interface PdfViewerLabels {
|
|
35
|
+
zoomOut: string;
|
|
36
|
+
zoomIn: string;
|
|
37
|
+
rotateLeft: string;
|
|
38
|
+
rotateRight: string;
|
|
39
|
+
previousPage: string;
|
|
40
|
+
nextPage: string;
|
|
41
|
+
search: string;
|
|
42
|
+
previousResult: string;
|
|
43
|
+
nextResult: string;
|
|
44
|
+
previousAnnotation: string;
|
|
45
|
+
nextAnnotation: string;
|
|
46
|
+
selectArea: string;
|
|
47
|
+
selectText: string;
|
|
48
|
+
searchPlaceholder: string;
|
|
49
|
+
noResults: string;
|
|
50
|
+
loading: string;
|
|
51
|
+
noDocument: string;
|
|
52
|
+
loadError: string;
|
|
53
|
+
}
|
|
54
|
+
/** A single entry in the right-click context menu shown after drag selection */
|
|
55
|
+
interface ContextMenuItem {
|
|
56
|
+
/** Display label */
|
|
57
|
+
label: string;
|
|
58
|
+
/** Unique action identifier emitted in the output event */
|
|
59
|
+
action: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface RenderedPage {
|
|
63
|
+
pageNum: number;
|
|
64
|
+
width: number;
|
|
65
|
+
height: number;
|
|
66
|
+
rotation: number;
|
|
67
|
+
}
|
|
68
|
+
interface DragState {
|
|
69
|
+
active: boolean;
|
|
70
|
+
pageNum: number;
|
|
71
|
+
startX: number;
|
|
72
|
+
startY: number;
|
|
73
|
+
currentX: number;
|
|
74
|
+
currentY: number;
|
|
75
|
+
}
|
|
76
|
+
interface SearchMatch {
|
|
77
|
+
pageNum: number;
|
|
78
|
+
polygon: number[];
|
|
79
|
+
}
|
|
80
|
+
declare class NgxNextPdfViewerComponent implements OnChanges, OnDestroy, AfterViewInit {
|
|
81
|
+
private cdr;
|
|
82
|
+
private zone;
|
|
83
|
+
private el;
|
|
84
|
+
/** PDF file to display */
|
|
85
|
+
blob: Blob | undefined;
|
|
86
|
+
/** Bounding-box annotations to overlay */
|
|
87
|
+
annotations: BoundingBox[];
|
|
88
|
+
/** Items shown in the context menu after drag-selecting boxes */
|
|
89
|
+
contextMenuItems: ContextMenuItem[];
|
|
90
|
+
/** Fill colour for a single-clicked box (CSS colour string) */
|
|
91
|
+
highlightingColor: string;
|
|
92
|
+
/** Fill colour for drag-selected boxes (CSS colour string) */
|
|
93
|
+
selectedColor: string;
|
|
94
|
+
/** Stroke colour for all annotation polygons */
|
|
95
|
+
annotationStroke: string;
|
|
96
|
+
/** Initial zoom: numeric level (1.0 = 100 %) or 'fit-to-page' | 'fit-to-width' | 'fit-to-height' */
|
|
97
|
+
initialZoom: ZoomMode;
|
|
98
|
+
/** Override any subset of the viewer's user-visible strings */
|
|
99
|
+
labels: Partial<PdfViewerLabels>;
|
|
100
|
+
private static readonly DEFAULT_LABELS;
|
|
101
|
+
get l(): PdfViewerLabels;
|
|
102
|
+
/** Fired when the user clicks a single annotation box */
|
|
103
|
+
boxClicked: EventEmitter<{
|
|
104
|
+
box: BoundingBox;
|
|
105
|
+
selected: boolean;
|
|
106
|
+
}>;
|
|
107
|
+
/** Fired when the user picks a context-menu item after drag-selection */
|
|
108
|
+
boxesSelected: EventEmitter<{
|
|
109
|
+
boxes: BoundingBox[];
|
|
110
|
+
action: string;
|
|
111
|
+
}>;
|
|
112
|
+
pdfContainer: ElementRef<HTMLDivElement>;
|
|
113
|
+
pdfDoc: PDFDocumentProxy | null;
|
|
114
|
+
renderedPages: RenderedPage[];
|
|
115
|
+
currentPage: number;
|
|
116
|
+
totalPages: number;
|
|
117
|
+
zoom: number;
|
|
118
|
+
userRotation: number;
|
|
119
|
+
clickedBoxKey: string | null;
|
|
120
|
+
multiSelectedKeys: Set<string>;
|
|
121
|
+
drag: DragState;
|
|
122
|
+
ctxVisible: boolean;
|
|
123
|
+
ctxX: number;
|
|
124
|
+
ctxY: number;
|
|
125
|
+
searchVisible: boolean;
|
|
126
|
+
searchQuery: string;
|
|
127
|
+
searchMatches: SearchMatch[];
|
|
128
|
+
searchIndex: number;
|
|
129
|
+
selectionMode: 'select-area' | 'select-text';
|
|
130
|
+
loading: boolean;
|
|
131
|
+
loadError: boolean;
|
|
132
|
+
private renderTasks;
|
|
133
|
+
private textLayers;
|
|
134
|
+
private wheelListener?;
|
|
135
|
+
constructor(cdr: ChangeDetectorRef, zone: NgZone, el: ElementRef, workerSrc: string);
|
|
136
|
+
ngAfterViewInit(): void;
|
|
137
|
+
ngOnChanges(changes: SimpleChanges): void;
|
|
138
|
+
ngOnDestroy(): void;
|
|
139
|
+
private loadPdf;
|
|
140
|
+
private computeFitZoom;
|
|
141
|
+
private renderPage;
|
|
142
|
+
private rerenderAll;
|
|
143
|
+
/** Converts a polygon (y=0 at top, any consistent unit) to SVG canvas coordinates */
|
|
144
|
+
transformPolygon(polygon: number[], pdfWidth: number, pdfHeight: number, canvasWidth: number, canvasHeight: number, rotation: number): number[];
|
|
145
|
+
getSvgPoints(box: BoundingBox, pi: RenderedPage): string;
|
|
146
|
+
private polygonBBox;
|
|
147
|
+
private boxKey;
|
|
148
|
+
getPageInfo(pageNum: number): RenderedPage | undefined;
|
|
149
|
+
getBoxesForPage(pageNum: number): BoundingBox[];
|
|
150
|
+
isClicked(box: BoundingBox): boolean;
|
|
151
|
+
isMultiSelected(box: BoundingBox): boolean;
|
|
152
|
+
pageRange(): number[];
|
|
153
|
+
getDragRect(pageNum: number): {
|
|
154
|
+
x: number;
|
|
155
|
+
y: number;
|
|
156
|
+
w: number;
|
|
157
|
+
h: number;
|
|
158
|
+
} | null;
|
|
159
|
+
getSearchMatchesForPage(pageNum: number): SearchMatch[];
|
|
160
|
+
getSearchIndexOffset(pageNum: number): number;
|
|
161
|
+
isCurrentSearchMatch(pageNum: number, localIndex: number): boolean;
|
|
162
|
+
searchMatchPoints(m: SearchMatch): string;
|
|
163
|
+
onBoxClick(event: MouseEvent, box: BoundingBox): void;
|
|
164
|
+
onSvgMouseDown(event: MouseEvent, pageNum: number): void;
|
|
165
|
+
onDocMouseMove(event: MouseEvent): void;
|
|
166
|
+
onDocMouseUp(event: MouseEvent): void;
|
|
167
|
+
private svgPoint;
|
|
168
|
+
private rectsIntersect;
|
|
169
|
+
onContextMenuAction(item: ContextMenuItem): void;
|
|
170
|
+
onDocClick(): void;
|
|
171
|
+
zoomIn(): void;
|
|
172
|
+
zoomOut(): void;
|
|
173
|
+
get zoomPercent(): number;
|
|
174
|
+
rotateLeft(): void;
|
|
175
|
+
rotateRight(): void;
|
|
176
|
+
goToPrevPage(): void;
|
|
177
|
+
goToNextPage(): void;
|
|
178
|
+
scrollToPageNum(pageNum: number): void;
|
|
179
|
+
scrollToBox(box: BoundingBox): void;
|
|
180
|
+
toggleSearch(): void;
|
|
181
|
+
onSearchInput(): Promise<void>;
|
|
182
|
+
searchNext(): void;
|
|
183
|
+
searchPrev(): void;
|
|
184
|
+
private scrollToSearchMatch;
|
|
185
|
+
get annotationIndex(): number;
|
|
186
|
+
goToPrevAnnotation(): void;
|
|
187
|
+
goToNextAnnotation(): void;
|
|
188
|
+
private selectAnnotation;
|
|
189
|
+
toggleSelectionMode(): void;
|
|
190
|
+
private renderTextLayer;
|
|
191
|
+
private removeTextLayer;
|
|
192
|
+
private removeAllTextLayers;
|
|
193
|
+
onContainerScroll(): void;
|
|
194
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<NgxNextPdfViewerComponent, never>;
|
|
195
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<NgxNextPdfViewerComponent, "ngx-next-pdf-viewer", never, { "blob": { "alias": "blob"; "required": false; }; "annotations": { "alias": "annotations"; "required": false; }; "contextMenuItems": { "alias": "contextMenuItems"; "required": false; }; "highlightingColor": { "alias": "highlightingColor"; "required": false; }; "selectedColor": { "alias": "selectedColor"; "required": false; }; "annotationStroke": { "alias": "annotationStroke"; "required": false; }; "initialZoom": { "alias": "initialZoom"; "required": false; }; "labels": { "alias": "labels"; "required": false; }; }, { "boxClicked": "boxClicked"; "boxesSelected": "boxesSelected"; }, never, never, true, never>;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* URL to the PDF.js worker script.
|
|
200
|
+
*
|
|
201
|
+
* Default: `'assets/pdf.worker.min.mjs'`
|
|
202
|
+
*
|
|
203
|
+
* Override in your application by providing this token:
|
|
204
|
+
* ```ts
|
|
205
|
+
* providers: [
|
|
206
|
+
* { provide: NGX_PDF_WORKER_SRC, useValue: 'assets/pdf.worker.min.mjs' }
|
|
207
|
+
* ]
|
|
208
|
+
* ```
|
|
209
|
+
*/
|
|
210
|
+
declare const NGX_PDF_WORKER_SRC: InjectionToken<string>;
|
|
211
|
+
|
|
212
|
+
export { NGX_PDF_WORKER_SRC, NgxNextPdfViewerComponent };
|
|
213
|
+
export type { BoundingBox, ContextMenuItem, PdfViewerLabels, ZoomMode };
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@aprova.ch/ngx-next-pdf-viewer",
|
|
3
|
+
"version": "20.0.8",
|
|
4
|
+
"description": "Angular PDF viewer with bounding-box annotations, search, zoom and page rotation",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"angular",
|
|
7
|
+
"pdf",
|
|
8
|
+
"viewer",
|
|
9
|
+
"annotations",
|
|
10
|
+
"bounding-box",
|
|
11
|
+
"labeling",
|
|
12
|
+
"pdf.js"
|
|
13
|
+
],
|
|
14
|
+
"author": "Aprova GmbH",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://github.com/Aprova-GmbH/ngx-next-pdf-viewer.git"
|
|
19
|
+
},
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/Aprova-GmbH/ngx-next-pdf-viewer/issues"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://aprova.ch",
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"@angular/common": ">=20.0.0",
|
|
26
|
+
"@angular/core": ">=20.0.0",
|
|
27
|
+
"@angular/forms": ">=20.0.0",
|
|
28
|
+
"@angular/material": ">=20.0.0",
|
|
29
|
+
"pdfjs-dist": ">=4.7.0"
|
|
30
|
+
},
|
|
31
|
+
"peerDependenciesMeta": {
|
|
32
|
+
"pdfjs-dist": {
|
|
33
|
+
"optional": false
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"tslib": "^2.3.0"
|
|
38
|
+
},
|
|
39
|
+
"module": "fesm2022/aprova.ch-ngx-next-pdf-viewer.mjs",
|
|
40
|
+
"typings": "index.d.ts",
|
|
41
|
+
"exports": {
|
|
42
|
+
"./package.json": {
|
|
43
|
+
"default": "./package.json"
|
|
44
|
+
},
|
|
45
|
+
".": {
|
|
46
|
+
"types": "./index.d.ts",
|
|
47
|
+
"default": "./fesm2022/aprova.ch-ngx-next-pdf-viewer.mjs"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"sideEffects": false
|
|
51
|
+
}
|