@vue-pdf-viewer/viewer
Version:
The PDF Viewer component for Vue 3 and Nuxt
735 lines (734 loc) • 21.7 kB
TypeScript
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 {};