import * as i0 from '@angular/core'; import { AfterViewInit, OnChanges, ElementRef, QueryList, EventEmitter, SimpleChanges } from '@angular/core'; import { PDFDocumentProxy } from 'pdfjs-dist'; import { ContextMenuItem } from '@tvangular/context-menu'; declare enum TooltipPosition { ABOVE = "above", BELOW = "below", LEFT = "left", RIGHT = "right", DYNAMIC = "dynamic", DEFAULT = "below" } /** * W3C-Compatible PDF Annotation Data Model * Derived from: packages/pdf-annotator/src/model/core/pdf-annotation.ts */ interface PDFSelector { pageNumber: number; quote: string; start: number; end: number; quadpoints?: number[]; } interface PDFAnnotation { id: string; selector: PDFSelector; color?: string; comment?: string; createdAt?: string; creator?: string; } interface TextNodeSegment { node: Text; start: number; end: number; } interface TooltipConfig { backgroundColor: string; textColor: string; borderRadius: string; animationDuration: string; fontSize: string; fontStyle: string; padding: string; boxShadow: string; showDelay: number; hideDelay: number; } interface DocumentViewerConfig { fileUrl: string | Blob; fileType: string; fileName: string; file?: Blob | File; contextMenuItems?: any[]; documentNameVisibility?: boolean; paginationVisibility?: boolean; searchBtnVisibility?: boolean; zoomVisibility?: boolean; multiViewBtnVisibility?: boolean; downloadVisibility?: boolean; printerVisibility?: boolean; removeVisibility?: boolean; } declare class DocumentViewer implements AfterViewInit, OnChanges { /** * Security Note: * HTML content is rendered within a sandboxed iframe to prevent XSS attacks. * The sandbox attribute restricts the iframe's capabilities while allowing * necessary functionality for document viewing. Content is loaded via srcdoc * with bypassSecurityTrustHtml since the iframe sandbox provides the security layer. */ pdfCanvas: ElementRef; viewerContainer: ElementRef; htmlContentIframe: ElementRef; docxRenderContainer: ElementRef; thumbnailCanvases: QueryList>; observer: IntersectionObserver; private isManualNavigation; removeImageEvent: EventEmitter; closeRequest: EventEmitter; contextMenuItemClick: EventEmitter; annotationCreated: EventEmitter; annotationUpdated: EventEmitter; annotationDeleted: EventEmitter; annotationClicked: EventEmitter<{ annotationId: string; event: MouseEvent; }>; textLayerRendered: EventEmitter<{ pageNumber: number; textLayer: HTMLElement; }>; parentData: DocumentViewerConfig; customContextMenuItems?: ContextMenuItem[]; annotations: PDFAnnotation[]; private contextMenuService; private annotationService; private ngZone; showSelectionToolbar: boolean; selectionToolbarPos: { top: number; left: number; }; pendingSelection: { range: Range; pageNumber: number; } | null; showCommentBox: boolean; activeCommentAnnotation: PDFAnnotation | null; isNewAnnotation: boolean; isEditingComment: boolean; showCommentMenu: boolean; commentInputText: string; commentReplyText: string; commentBoxPosition: { top: number; left: number; }; isSidebarCollapsed: boolean; activeSidebarTab: 'thumbnails' | 'toc'; pdfOutline: any[]; viewMode: 'single' | 'multi'; tooltipPosition: typeof TooltipPosition; pdfDoc: PDFDocumentProxy | null; pdfDoc1: PDFDocumentProxy | null; pdfDoc2: PDFDocumentProxy | null; totalPages: any; currentPage: number; scale: any; /** Remembers the single-view zoom level so it can be restored when leaving multi-view. */ private singleViewScale; inputPageNumber: number; docxScale: number; get zoomPercentage(): number; pageThumbnails: HTMLCanvasElement[]; thumbnailDataUrls: string[]; base64Url: any; imgUrl: any; fileUrl: any; fileType: any; canvas: any; pdfIsLoaded: any; htmlContent: any; textContent: any; originalHtmlContent: string; originalTextContent: string; safeIframeSrc: any; private htmlBlobUrl; pdfText: any; pages: any[]; isMultiView: boolean; existCount: number; isSearchPanelVisible: boolean; isFindBarCollapsed: boolean; searchQuery: string; matchCase: boolean; wholeWord: boolean; useRegex: boolean; findCountText: string; findHistory: string[]; historyIndex: number; searchResults: Array<{ page: number; itemIndex: number; matchIndex: number; length: number; text: string; }>; currentSearchIndex: number; isSearching: boolean; searchTimeout: any; activeMatchCoordinates: { x: number; y: number; } | null; htmlScale: number; tooltipBelowConfig: TooltipConfig; private _appConstants; private _documentViewerService; private cdr; private sanitizer; constructor(); ngOnDestroy(): void; ngOnChanges(changes: SimpleChanges): void; /** * Re-paints annotations across all currently rendered pages. */ reRenderAnnotationsOnVisiblePages(): void; /** * Core rendering bridge that renders both PDF.js canvas and textLayer, * paints saved annotations, attaches interaction listeners, and emits textLayerRendered. */ private renderPageAndAnnotations; /** * Handles user selection on the PDF.js text layer (via mouseup event). * Immediately applies the yellow highlight and opens the comment card beside the selection (Pic 1). */ onTextLayerMouseUp(event: MouseEvent, pageNumber: number): void; /** * Triggered when user clicks the "Highlight" icon on the selection pill toolbar. */ onToolbarAddHighlight(): void; /** * Handles click on an existing highlighted annotation to view/edit comment. */ private handleAnnotationClick; /** * Opens the floating comment card in the right margin beside the PDF page (Pic 1). */ private openCommentBox; /** * Calculates (top, left) coordinates for the comment card placed in the right margin beside the PDF page. */ private positionCommentBox; /** * Formats timestamp for comment card e.g. "5:46 PM Today" */ getFormattedCommentTime(isoString?: string): string; /** * Toggles the dropdown menu for edit/delete on comment card header. */ toggleCommentMenu(): void; /** * Resolves the annotation (checkmark action). */ resolveAnnotation(): void; /** * Submits reply text entered on existing comment card. */ submitReply(): void; /** * Saves the entered comment on the active annotation. */ saveComment(): void; /** * Cancels comment input. If it was a newly created unsaved selection without comment, * it removes the highlight from the page. */ cancelComment(): void; /** * Enters edit mode for an existing comment. */ editComment(): void; /** * Deletes the active annotation and re-renders visible highlights. */ deleteActiveAnnotation(): void; /** * Closes the floating comment card. */ closeCommentBox(): void; ngAfterViewInit(): void; initializeDocument(): void; private loadPdfContent; loadDocx(): Promise; private renderDocxBuffer; /** * Splits overflowing DOCX content into discrete visual A4 page cards */ private autoPaginateDocx; onDocxScroll(event: any): void; loadPdfFromBlob(blob: Blob): Promise; /** * Asynchronously loads a PDF document from a URL and performs * various operations on the loaded document, such as extracting text and * rendering thumbnails. * * @param {string} url - The URL of the PDF document. * @return {Promise} A promise that resolves when the PDF document has * been successfully loaded and processed. */ loadPdfFromUrl(url: string): Promise; loadPdf(base64Url: string): Promise; /** * Prevents the default behavior of the right-click event. * * @param {MouseEvent} event - The right-click event. */ disableRightClick(event: MouseEvent): void; extractTextFromPdf(): Promise; /** * Renders all PDF page thumbnails for the sidebar. * Clears existing thumbnails and renders new ones for each page. * Each thumbnail is a small preview of the page. * * @returns {Promise} Promise that resolves when all thumbnails are rendered. */ renderAllThumbnails(): Promise; /** * Navigates to the entered page number. * If the entered page number is less than 1, it sets the input page number to null and the value to null. * If the entered page number is greater than the total number of pages, it sets the input page number to null and the value to null. * If the entered page number is between 1 and the total number of pages, it sets the input page number to the entered value. * It then converts the input page number to an integer page number. * If the page number is between 1 and the total number of pages, it checks if multi-view is enabled. * If multi-view is enabled: * - Determines if the page number is even or odd. * - Sets pageNum1 and pageNum2 accordingly. * - Renders the pages at pageNum1 and pageNum2. * If multi-view is not enabled: * - Sets the current page to the page number. * - Renders the page at the current page. * * @param {any} value - The entered page number. */ goToEnteredPage(value: any): void; /** * Validates the page number input by the user. * * @param {any} event - The event object containing the input element. * @return {void} */ validatePageNumber(event: any): void; toggleSearchPanel(): void; toggleFindCollapse(): void; toggleMatchCase(): void; toggleWholeWord(): void; toggleUseRegex(): void; closeFindBar(): void; onFindInput(value: string): void; executeSearch(query: string): void; private clearDocxHighlights; private executeDocxSearch; private goToDocxSearchResult; goToSearchResult(index: number, activeStatus?: boolean): void; findNext(): void; findPrev(): void; reRenderForSearch(): void; onFindKeydown(event: KeyboardEvent, input: HTMLInputElement): void; onFindChange(value: string): void; onWindowKeydown(e: KeyboardEvent): void; /** * Navigates to the specified page in the PDF document. * * @param pageNavigation - The page navigation action to perform. * Must be one of 'previousPage', 'nextPage', 'firstPage', or 'lastPage'. * If none of the cases match, the function does nothing. */ pageNavigation(pageNavigation: any): void; /** * Navigates to the specified page number, rendering the page in the viewer. * If multi-view mode is enabled, the left and right pages will be rendered. * @param pageNumber The page number to navigate to. * @param activeStatus Optional boolean indicating if search results should be highlighted. */ goToPage(pageNumber: number, activeStatus: any): void; /** * Increases the zoom level of the document. * Uses the AppConstants.maxScaleValue ceiling. * Preserves the viewport scroll centre so zoom feels browser-native. */ zoomIn(): void; /** * Decreases the zoom level of the document. * Uses the AppConstants.minScaleValue floor. * Preserves the viewport scroll centre so zoom feels browser-native. */ zoomOut(): void; /** * Applies zoom to HTML/TXT content by modifying iframe CSS */ private applyHtmlZoom; /** * Re-renders all pages at the current zoom scale, preserving the viewport * scroll centre — matching the behaviour of the browser's native PDF viewer. */ private applyZoom; /** * Downloads a document (PDF, HTML, or TXT). * * This function creates a download link for a document. It handles different * file types appropriately and triggers the download. * * @return {void} This function does not return anything. */ downloadPdf(): void; /** * Opens a new window and prints the document (PDF, HTML, or TXT). * * This function handles different file types appropriately for printing. * * @return {void} This function does not return anything. */ printPdf(): void; /** * Converts a base64 encoded string to a Blob object. * * @param {string} base64 - The base64 encoded string to convert. * @param {string} type - The MIME type of the Blob object. * @return {Blob} The resulting Blob object. */ base64ToBlob(base64: string, type: string): Blob; /** * Emits a 'remove file' event to the parent component, indicating that * the user wishes to remove the current file. * * @emits closeRequest - Emits a 'remove file' event to the parent component. */ removeImage(): void; /** * Emits a 'normal close' event to the parent component, indicating a normal * closure of the modal dialog. * * @emits closeRequest - Emits a 'normal close' event to the parent component. */ dismissModal(): void; /** * Toggles the view between single view and multi view of a PDF document. * * When entering multi-view, the scale is reset to 60% so * both pages fit side-by-side without being clipped. The previous single-view * zoom level is saved and restored when returning to single view. */ toggleView(): void; setupIntersectionObserver(): void; renderMainPageLazily(pageNumber: number): void; syncThumbnailSidebar(): void; isElementInViewport(el: HTMLElement): boolean; onViewerScroll(event: any): void; getDocumentName(): string; /** * Universal loader for HTML and text content. * Supports Blob objects, blob: URLs, http(s) URLs, base64 data URIs, and raw HTML/text strings. */ loadHtmlOrTextContent(providedUrl?: string): Promise; /** * Writes HTML string directly into the iframe's contentDocument. * Ensures styles and colors render immediately without cross-origin or sandboxed blob issues. */ private writeHtmlToIframe; loadHtmlFromBlobUrl(blobUrl: string): Promise; loadTextFromBlobUrl(blobUrl: string): Promise; /** * Escapes HTML special characters to prevent XSS * @param text - The text to escape */ private escapeHtml; /** * Converts HTML/TXT content to PDF and triggers download * @param content - The HTML or text content to convert * @param fileName - The desired filename for the download * @param isPlainText - Whether the content is plain text */ private convertHtmlToPdf; /** * Converts HTML to PDF using html2pdf library * @param content - The HTML content to convert * @param fileName - The desired filename * @param isPlainText - Whether the content is plain text */ private convertWithHtml2Pdf; /** * Downloads content as HTML file with print-to-PDF instructions * @param content - The HTML content to download * @param fileName - The desired filename * @param isPlainText - Whether the content is plain text */ private downloadAsHtmlWithPrintInstructions; /** * Shows feedback to the user about the download * @param fileName - The name of the downloaded file */ private showDownloadFeedback; /** * Fallback method to download content in its original format * @param content - The content to download * @param fileName - The filename * @param isPlainText - Whether the content is plain text */ private downloadAsOriginalFormat; /** * Checks if the current content is DOCX */ get isDocxContent(): boolean; /** * Checks if the current content is HTML */ get isHtmlContent(): boolean; /** * Checks if the current content is PDF */ get isPdfContent(): boolean; /** * Checks if the current content is text (TXT) */ get isTextContent(): boolean; get isToolbarVisible(): boolean; /** * Toggles sidebar collapsed state */ toggleSidebar(): void; /** * Sets active sidebar tab ('thumbnails' or 'toc') */ setSidebarTab(tab: 'thumbnails' | 'toc'): void; /** * Loads and parses PDF document outline / bookmarks into Table of Contents structure */ loadPdfOutline(): Promise; /** * Recursively parses raw pdf.js outline items into structured TOC items with target page numbers */ private parseOutlineItems; /** * Toggles expansion state of a nested TOC outline item */ toggleOutlineItem(item: any, event: Event): void; /** * Navigates viewer to the page specified by a TOC item */ goToOutlineItem(item: any): void; /** * Opens custom context menu on right click */ onContextMenu(event: MouseEvent): void; /** * Handles action executed from context menu selection */ handleContextMenuAction(action: string): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; } declare const DEFAULT_CONTEXT_MENU_ITEMS: ContextMenuItem[]; /** * 1. SELECTION CAPTURE (DOM Selection to Character Offsets) * Derived from: packages/text-annotator/src/utils/annotation/range-to-selector.ts * * Uses rangeBefore to measure exact character offset from the start of the textLayer container. */ declare const getSelectionOffsets: (range: Range, container: HTMLElement, pageNumber: number) => PDFSelector | null; /** * Helper: Calculates exact quadpoint coordinates for W3C PDF Compliance * Derived from: packages/pdf-annotator/src/utils/pdf/get-quad-points.ts */ declare const getQuadPoints: (range: Range, container: HTMLElement) => number[]; /** * 2. THE MATCHER (Offsets to Dynamic DOM Spans) * Derived from: packages/text-annotator-tei/src/crosswalk/crosswalk.ts * and packages/text-annotator/src/utils/annotation/revive-annotation.ts * * Traverses dynamic PDF.js text spans using TreeWalker to split selections across fragmented nodes. */ declare const findNodesInTextLayer: (container: HTMLElement, start: number, end: number) => TextNodeSegment[]; /** * 3. RENDERING LOGIC (Painting the Highlight) * Derived from: packages/text-annotator/src/rendering/renderer-spans/spans-renderer.ts * * Wraps segments in tags safely without breaking the PDF structure. */ declare const applyHighlight: (segments: TextNodeSegment[], annotationId?: string, color?: string) => void; declare class AnnotationService { /** * 1. Captures the user's active window.getSelection() on a page textLayer */ captureSelection(range: Range, textLayer: HTMLElement, pageNumber: number, color?: string): PDFAnnotation | null; /** * 2. Finds matching text nodes in textLayer for given character offsets */ findNodesInTextLayer(container: HTMLElement, start: number, end: number): TextNodeSegment[]; /** * 3. Applies highlight to given segments */ applyHighlight(segments: TextNodeSegment[], annotationId?: string, color?: string): void; /** * 4. Repaints all annotations for a specific PDF page when rendered or zoomed */ renderPageHighlights(textLayer: HTMLElement, pageNumber: number, annotations: PDFAnnotation[]): void; /** * 5. Attaches delegated click listener to detect clicked annotations */ attachClickListener(textLayer: HTMLElement, callback: (annotationId: string, event: MouseEvent) => void): () => void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵprov: i0.ɵɵInjectableDeclaration; } export { AnnotationService, DEFAULT_CONTEXT_MENU_ITEMS, DocumentViewer, applyHighlight, findNodesInTextLayer, getQuadPoints, getSelectionOffsets }; export type { PDFAnnotation, PDFSelector, TextNodeSegment };