UNPKG

@vue-pdf-viewer/viewer

Version:

The PDF Viewer component for Vue 3 and Nuxt

735 lines (734 loc) 21.7 kB
import { ComputedRef, MaybeRef, PropType, Reactive, Ref, ShallowRef } from 'vue'; import type { PageViewport } from 'pdfjs-dist'; import type { DocumentInitParameters, OnProgressParameters, PDFDataRangeTransport, TextContent, TypedArray, PDFPageProxy, PDFDocumentProxy } from 'pdfjs-dist/types/src/display/api'; import type { Metadata } from 'pdfjs-dist/types/src/display/metadata'; import { ZoomLevel, ViewMode, ScrollMode, VPVAnnotationType, LicenseType } from './enumerators'; export interface VirtualRange { start: number; end: number; } export interface Match { start: { idx: number; offset: number; }; end: { idx: number; offset: number; }; str: string; oIndex: number; pageIndex: number; } export type LoadedEventPayload = number; export type FocusedPageEventPayload = number; export interface PageShowRatioChangePayload { page: number; ratio: number; } export interface OutlineRef { gen: number; num: number; } export type OutlineDestination = [ OutlineRef | number, OutlineDestinationName, ...any[] ]; export interface OutlineDestinationName { name: string; } interface AnnotationPoint { x: number; y: number; } interface Attachment { content: Uint8Array; filename: string; } type OutlineDestinationType = string | OutlineDestination; export interface Annotation { annotationType: number; color?: Uint8ClampedArray; dest: OutlineDestinationType; hasAppearance: boolean; id: string; rect: number[]; subtype: string; borderStyle: { dashArray: number[]; horizontalCornerRadius: number; style: number; verticalCornerRadius: number; width: number; }; hasPopup?: boolean; contents?: string; contentsObj?: { dir: string; str: string; }; modificationDate?: string; quadPoints?: AnnotationPoint[][]; title?: string; titleObj?: { dir: string; str: string; }; parentId?: string; parentType?: string; file?: Attachment; inkLists?: AnnotationPoint[][]; lineCoordinates: number[]; action?: string; unsafeUrl?: string; url?: string; newWindow?: boolean; vertices?: AnnotationPoint[]; name?: string; fieldType: string; pushButton: boolean; } export interface AnnotationEventPayload { type: VPVAnnotationType; data: any; } export interface RotateEvent { direction: 'clockwise' | 'counterclockwise'; rotate: number; } export interface CharacterIndex { char: string; charIdxInSpan: number; spanIdx: number; } export interface MatchRangeIndex { keyword: RegExp; startIndex: number; endIndex: number; } export interface FlagKeyword { keyword: string; matchCase?: boolean; wholeWords?: boolean; } export type SingleKeyword = string | RegExp | FlagKeyword; export interface NormalizedKeyword { keyword: string; regExp: RegExp; wholeWords: boolean; color?: string; } export interface HighlightArea { keywordStr: string; left: number; top: number; height: number; width: number; pageHeight: number; pageWidth: number; highlightColor?: string; } export interface HighlightEventPayload { matches: Match[]; page: number; textContent: TextContent; textDivs: HTMLElement[]; } export interface TextLayerLoadedEventPayload { textDivs: HTMLElement[]; textContent: TextContent | undefined; textLayerRef?: HTMLElement; } export interface HighlightOptions { matchCase?: boolean; wholeWords?: boolean; } export interface TextLayerHighlightProps { keyword: string; options?: HighlightOptions; } export interface Base<T, S> { type: T; spec: S; } export type XYZ = Base<'XYZ', [left: number, top: number, zoom: number]>; export type Fit = Base<'Fit', []>; export type FitH = Base<'FitH', [top: number]>; export type FitV = Base<'FitV', [left: number]>; export type FitR = Base<'FitR', [left: number, bottom: number, right: number, top: number]>; export type FitB = Base<'FitB', []>; export type FitBH = Base<'FitBH', [top: number]>; export type FitBV = Base<'FitBV', [left: number]>; export type PDFLocation = XYZ | Fit | FitH | FitV | FitR | FitB | FitBH | FitBV; export interface PDFDestination { pageIndex: number; location: PDFLocation; } export type OnProgressCallback = (progressData: OnProgressParameters) => void; export type UpdatePasswordFn = (newPassword: string) => void; export type OnPasswordCallback = (updatePassword: UpdatePasswordFn, reason: any) => void; export type OnErrorCallback = (error: any) => void; export type CharacterMap = { url: string; isCompressed?: boolean; }; export type PDFSrc = string | URL | TypedArray | PDFDataRangeTransport | DocumentInitParameters | undefined | null; export interface PDFOptions { onProgress?: OnProgressCallback; onPassword?: OnPasswordCallback; onError?: OnErrorCallback; password?: string; } export interface PDFInfoMetadata { info: Object; metadata: Metadata; } export interface PDFInfo { metadata: PDFInfoMetadata; attachments: Record<string, unknown>; javascript: string[] | null; outline: any; } export interface AppPdfPage { page: PDFPageProxy; viewport: PageViewport; height: number; scale: number; } export interface Rect { height: number; width: number; } export interface PdfPageSize { rotation: number; pageRect: Rect; } export interface VPVThumbnail { page: PDFPageProxy; } export interface Offset { left: number; top: number; } export interface ViewerPdfPage { page: PDFPageProxy; viewport: PageViewport; height: number; width: number; } export interface ItemMeasurement { index: number; start: Offset; size: Rect; end: Offset; visibility: number; } export interface VirtualItem extends ItemMeasurement { pdfPage: ViewerPdfPage; } export type DestinationOffsetFromViewport = (viewportWidth: number, viewportHeight: number) => number; export interface Destination { pageIndex: number; bottomOffset: number | DestinationOffsetFromViewport; leftOffset: number | DestinationOffsetFromViewport; label?: string; scaleTo?: number | ZoomLevel; } export interface PageDimensionsWithSummation { pageNumber: number; dimension: { width: number; height: number; }; summation: { totalWidth: number; totalHeight: number; }; } export interface ViewerState { pdfDocument: ShallowRef<PDFDocumentProxy | undefined>; pagesContainerRef: ShallowRef<HTMLElement | undefined>; pageIndex: Ref<number>; viewMode: Ref<ViewMode>; scrollMode: Ref<ScrollMode>; scale: Ref<number>; rotation: Ref<number>; } export interface VisibilityInfo { pageIndex: number; ratio: number; } export interface ToolbarOptions { /** * Determines whether the toolbar includes a search functionality. * If set to `true`, users can search for specific text within the PDF document. */ searchable: boolean; /** * Indicates whether navigation controls (such as next page and previous page buttons) are available in the toolbar. * When set to `true`, users can navigate through the pages of the PDF document. */ navigatable: boolean; /** * Specifies whether zoom controls (zoom in, zoom out buttons, and zoom dropdown menu) are part of the toolbar. * If `zoomable` is `true`, users can adjust the zoom level for better readability. */ zoomable: boolean; /** * Determines whether users can switch between different themes (e.g., light mode and dark mode) using the toolbar. * If enabled, users can customize the appearance of the PDF viewer. */ themeSwitchable: boolean; /** * Indicates whether a full-screen button is available in the toolbar. * When set to `true`, users can expand the PDF viewer to fill the entire screen. */ fullscreen: boolean; /** * Specifies whether a download button is included in the toolbar. * If enabled, users can download the PDF document directly. */ downloadable: boolean; /** * Determines whether a print button is part of the toolbar. * When set to `true`, users can print the PDF document. */ printable: boolean; /** * Indicates whether the functionality to open a file from the local computer, * including both the open file icon and drag-and-drop, is enabled or disabled. */ newFileOpenable: boolean; /** * Determines whether a sidebar is part of the viewer. */ sidebarEnable: boolean; /** * Determines whether a thumbnail button is part of the toolbar. */ thumbnailViewable: boolean; /** * Determines whether rotation group menu is a part of the others dropdown menu. */ rotatable: boolean; /** * Determines whether document properties menu is a part of the others dropdown menu. */ docPropertiesEnabled: boolean; /** * Determines whether text selection & hand tool menu are a part of the others dropdown menu. */ pointerSwitchable: boolean; /** * Determines whether top page & last page menu are a part of the others dropdown menu. */ jumpNavigatable: boolean; /** * Indicates whether the viewer's scrolling modes (vertical, horizontal, wrapped) can be toggled via the more options dropdown menu. */ scrollingSwitchable: boolean; /** * Indicates whether the viewer's page view modes (single, dual) can be toggled via the more options dropdown menu. */ pageViewSwitchable: boolean; /** * Indicates whether the comment panel is enabled. */ commentPanelEnabled: boolean; } export interface License { isValidating: boolean; isValidated: boolean; isValidKey: boolean; licenseKey: string | null; type: LicenseType; } export interface AppLicense extends Omit<License, 'licenseKey'> { invalidatedMessage?: string; } export type VPVSrc = Omit<PDFSrc, 'DocumentInitParameters' | 'PDFDataRangeTransport'>; export interface TextHighlight { /** * The keyword or regular expression to match text for highlighting. */ keyword: string | RegExp; /** * The color used to highlight the matched text. */ highlightColor: string; /** * Optional match options for fine-tuning the search behavior. */ options?: HighlightOptions; } export interface VPdfViewerProps { src: MaybeRef<VPVSrc>; /** * The path of your prefer pdfjs worker * If unspecified, the viewer will use the worker from pdfjs-dist@3.11.174 */ workerUrl?: string; /** * The number of page that will be displayed initially */ initialPage?: number; /** * The initial zoom level default * If unspecified, the initial zoom level is determined by the page dimensions and the width of the container */ initialScale?: number | ZoomLevel; /** * The initial scroll mode */ initialScrollMode?: ScrollMode; /** * The initial viewer mode */ initialViewMode?: ViewMode; /** * The initial rotation must be divisible by 90 */ initialRotation?: number; /** * The initial thumbnails visible default * If unspecified, the thumbnails visible will be `false` */ initialThumbnailsVisible?: boolean; /** * The initial search value */ initialSearch?: string; /** * A layer on a PDF to allow text selection */ textLayer?: boolean; /** * Specifies the character map (CMap) to be used for text rendering. * A CMap associates character codes with corresponding glyphs in CID fonts. * Use this property when displaying PDFs with complex character sets (e.g., East Asian languages). */ characterMap?: CharacterMap; /** * Determine whether the toolbar is visible in the VPV. * Remark: The toolbar consists of top bar and left sidebar. */ toolbarOptions?: Partial<ToolbarOptions> | false; /** * localization json data */ localization?: Record<string, Localization>; /** * A callback function that will be executed after each canvas is loaded. * The key is the page number, and the value is the callback function. */ afterCanvasLoaded?: Record<number, CanvasLoadedCallback>; /** * The initial text highlights */ textHighlights?: Array<TextHighlight>; } export interface HighlightMatchPosition { matchIdx: number; pageIdx: number; } export type Localization = { searchButtonTooltip: string; searchInputPlaceholder: string; searchInputTooltip: string; searchPrevTooltip: string; searchNextTooltip: string; searchCloseButtonTooltip: string; searchMatchCaseLabel: string; searchMatchCaseTooltip: string; searchWholeWordsLabel: string; searchWholeWordsTooltip: string; previousPageTooltip: string; currentPageTooltip: string; nextPageTooltip: string; zoomOutTooltip: string; zoomInTooltip: string; zoomSelectTooltip: string; zoomActualSize: string; zoomPageFit: string; zoomPageWidth: string; themeEnableDarkTooltip: string; themeEnableLightTooltip: string; openLocalFileLabel: string; openLocalFileTooltip: string; downloadFileLabel: string; downloadFileTooltip: string; commentPanelTooltip: string; printLabel: string; printTooltip: string; printLoadingMessage: string; printCancelLabel: string; fullScreenLabel: string; fullScreenTooltip: string; moreOptionTooltip: string; firstPageLabel: string; firstPageTooltip: string; lastPageLabel: string; lastPageTooltip: string; rotateClockwiseLabel: string; rotateClockwiseTooltip: string; rotateCounterclockwiseLabel: string; rotateCounterclockwiseTooltip: string; textSelectionLabel: string; textSelectionTooltip: string; handToolLabel: string; handToolTooltip: string; pageScrollingLabel: string; pageScrollingTooltip: string; verticalScrollingLabel: string; verticalScrollingTooltip: string; horizontalLabel: string; horizontalTooltip: string; wrappedScrollingLabel: string; wrappedScrollingTooltip: string; singlePageLabel: string; singlePageTooltip: string; dualPageLabel: string; dualPageTooltip: string; documentPropertiesLabel: string; documentPropertiesTooltip: string; propertiesFilenameLabel: string; propertiesFileSizeLabel: string; propertiesTitleLabel: string; propertiesAuthorLabel: string; propertiesSubjectLabel: string; propertiesKeywordLabel: string; propertiesCreatorLabel: string; propertiesCreateOnLabel: string; propertiesModifiedOnLabel: string; propertiesPDFProducerLabel: string; propertiesPDFVersionLabel: string; propertiesPageCountLabel: string; thumbnailTooltip: string; passwordModalTitle: string; passwordModalMessage: string; passwordPlaceholder: string; passwordConfirmLabel: string; passwordError: string; dragDropFileMessage: string; }; export interface HighlightMatchPosition { matchIdx: number; pageIdx: number; } export interface ViewportDimensions { width: number; height: number; canvasWidth: number; canvasHeight: number; widthRatio: number; heightRatio: number; } export type CanvasLoadedCallback = (element: HTMLCanvasElement, viewport: ViewportDimensions) => void; export interface PdfProperties { filename: string; fileSize: string; title: string; author: string; subject: string; keywords: string; creator: string; createdOn: string; modifierOn: string; pdfProducer: string; pdfVersion: string; pageCount?: number; } export declare const VPVBaseProps: { readonly src: { readonly type: PropType<string | VPVSrc>; readonly required: true; }; readonly workerUrl: { readonly type: PropType<string>; readonly default: undefined; }; readonly initialPage: { readonly type: PropType<number>; readonly default: () => number; }; readonly initialScale: { readonly type: PropType<number | ZoomLevel>; readonly default: () => ZoomLevel; }; readonly initialScrollMode: { readonly type: PropType<ScrollMode>; readonly default: () => ScrollMode; readonly validator: (initialScrollMode: ScrollMode, args: unknown) => boolean; }; readonly initialViewMode: { readonly type: PropType<ViewMode>; readonly default: () => ViewMode; readonly validator: (initialViewMode: ViewMode, args: unknown) => boolean; }; readonly initialRotation: { readonly type: PropType<number>; readonly default: () => number; }; readonly initialThumbnailsVisible: { readonly type: PropType<boolean>; readonly default: undefined; }; readonly textLayer: { readonly type: PropType<boolean>; readonly default: () => boolean; }; readonly characterMap: { readonly type: PropType<CharacterMap>; readonly default: undefined; }; readonly toolbarOptions: { readonly type: PropType<false | Partial<ToolbarOptions>>; readonly default: () => ToolbarOptions; }; readonly localization: { readonly type: PropType<Record<string, Localization>>; readonly default: () => Record<string, Localization>; }; readonly initialSearch: { readonly type: StringConstructor; readonly default: undefined; }; readonly afterCanvasLoaded: { readonly type: PropType<Record<number, CanvasLoadedCallback>>; readonly default: undefined; }; /** * Experiment property */ readonly textHighlights: { readonly type: PropType<TextHighlight[]>; readonly default: undefined; readonly validator: (value: Array<TextHighlight>) => boolean; }; readonly downloadFilename: { readonly type: StringConstructor; readonly default: undefined; }; }; export interface MatchValue extends Match { page: number; pageMatchIdx: number; } export interface MatchHighlight extends MatchValue { keyword: string | RegExp; color: string; } export interface SearchControlValue { textContentPages: Ref<Record<string, TextContent>>; searchValue: Ref<string | undefined>; matches: Ref<MatchValue[]>; matchCount: ComputedRef<number>; currentSearchMatchIndex: Ref<number | undefined>; currentSearchMatch: ComputedRef<MatchValue | undefined>; searching: Ref<boolean>; openSearch: Ref<boolean>; onOpenSearch: () => void; onCloseSearch: () => void; handleSelectNext: () => void; handleSelectPrev: () => void; search: (value: string) => void; goToMatch: (index: number) => void; } export interface SearchControl { searchMatches?: { totalMatches: number; matches: { index: number; page: number; }[]; }; searching: Ref<boolean>; search: (value: string) => void; goToMatch: (index: number) => void; nextSearchMatch: () => void; prevSearchMatch: () => void; } export interface PreparePrintProgress { loadedPages: number; totalPages: number; percentage: number; } export interface PrintControl { print(options?: { visibleDefaultProgress: boolean; }): Awaited<void>; cancel(): void; onProgress?: (progress: PreparePrintProgress) => void; onError?: (error: Error) => void; onComplete?: () => void; } export interface RotateControl { rotateClockwise: () => void; rotateCounterclockwise: () => void; currentRotation: number; } export interface PageControl { goToPage: (page: number) => void; currentPage: number; totalPages: number; } export interface DownloadPdfProgress { bytesDownloaded: number; percentage: number; } export interface DownloadControl { download(): Awaited<void>; onError?: (error: Error) => void; onComplete?: () => void; } export interface ZoomControl { scale: Ref<number>; zoom(scale: number | ZoomLevel): void; } export interface UseScaleCallback { status: 'success' | 'error'; scale: number; mode?: ZoomLevel; error?: string; } export interface VPVInstance { printControl: Reactive<PrintControl> | undefined; searchControl: SearchControl | undefined; pageControl: Reactive<PageControl> | undefined; rotateControl: Reactive<RotateControl> | undefined; downloadControl: Reactive<DownloadControl> | undefined; zoomControl: Reactive<ZoomControl> | undefined; } export interface NavigationAnnotation { action: 'FirstPage' | 'LastPage' | 'NextPage' | 'PrevPage'; } type CommentContents = { str: string; dir: string; }; export interface Comment { page: number; id: string; text: string; rect: [number, number, number, number]; creationDate: string | Date; modificationDate: string | Date; color: Uint8ClampedArray | null; inReplyTo?: string; contentsObj?: CommentContents; titleObj?: CommentContents; } export interface CommentWithReplies { original: Comment; replies: Comment[]; } export interface PdfCommentPage { page: number; comments: CommentWithReplies[]; } export interface UsePdfCommentsReturn { comments: Ref<Map<number, Comment[]>>; repliedCommentPages: Ref<PdfCommentPage[]>; } export {};