teamsync-pdf-viewer 1.6.0 → 1.7.0
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/CHANGELOG.md +23 -0
- package/README.md +1 -1
- package/dist/src/components/DocumentViewer.d.ts +18 -2
- package/dist/src/components/PageRenderer.d.ts +2 -1
- package/dist/src/components/Sidebar.d.ts +2 -1
- package/dist/src/components/TeamSyncViewer.d.ts +28 -1
- package/dist/src/core/ViewerInstance.d.ts +53 -9
- package/dist/src/core/types.d.ts +66 -2
- package/dist/src/index.d.ts +4 -2
- package/dist/src/utils/linkUtils.d.ts +23 -0
- package/dist/src/utils/zoomUtils.d.ts +5 -0
- package/dist/teamsync-pdf-viewer.js +2312 -1981
- package/dist/teamsync-pdf-viewer.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,29 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `teamsync-pdf-viewer` are documented here.
|
|
4
4
|
|
|
5
|
+
## [1.7.0] — 2026-09-15
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **Cross-Instance Document Linking**: Links referring to other documents or specific pages can now automatically load and navigate the destination document in a designated target `TeamSyncViewer` instance.
|
|
9
|
+
- **`targetViewer` Prop & Option**: Added `targetViewer` to `<TeamSyncViewer>` and `WebViewerOptions`, accepting another `WebViewerInstance`, a React ref (`useRef<WebViewerInstance>`), a getter function `() => WebViewerInstance | null`, or an instance ID string.
|
|
10
|
+
- **Static Viewer Instance Registry**: Added `WebViewerInstance.getInstance(id)`, `WebViewerInstance.registerInstance(id, inst)`, `WebViewerInstance.unregisterInstance(id)`, and automatic unregistration when the viewer is unmounted/destroyed.
|
|
11
|
+
- **`loadOrNavigate` & `openLink` APIs**: Added `instance.loadOrNavigate(documentUrl, page?)` (smoothly navigates to the page if the document is already loaded, or reloads at that page if not) and `instance.openLink(url, options?)`.
|
|
12
|
+
- **Dual Link Support (TeamSync Annotations & Embedded PDF Links)**:
|
|
13
|
+
- Native embedded PDF `/Link` annotations are now extracted from PDF.js (`page.getAnnotations({ intent: 'display' })`) and rendered with interactive SVG hitboxes and tooltip preview.
|
|
14
|
+
- Link annotations and sidebar comment links seamlessly route through the link handler.
|
|
15
|
+
- **"Other Doc" Tab in Insert Link Modal**: Added a dedicated 3rd tab to `InsertLinkModal` for configuring cross-document links with document URL and target page number.
|
|
16
|
+
- **`linkClicked` Event & Custom Handlers**: Added `linkClicked` event to `ViewerEventMap` with a cancellable `LinkClickEvent` supporting `event.preventDefault()`, plus `onLinkClick` and `resolveLinkUrl` props for URL mapping and event interception.
|
|
17
|
+
- **Public Utilities Export**: Exported `parseLinkTarget`, `isDocumentUrl`, `ParsedLinkTarget`, and `LinkClickEvent` from the library root.
|
|
18
|
+
|
|
19
|
+
## [1.6.1] — 2026-09-15
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
- **`initialWidthRatio` Option**: Added `initialWidthRatio?: number` (with `widthRatio?: number` as an alias) to `<TeamSyncViewer>` and `WebViewerOptions`, allowing clients to target an exact fraction of the available viewing width on initial load (e.g. `0.7` for 70% width).
|
|
23
|
+
- **Responsive PDF Container Resizing**: Added automatic `ResizeObserver` tracking on the document container to refit the open PDF responsively at 60fps via `requestAnimationFrame` when the viewer page, container, or sidebars resize while in a width-ratio, fit-width, or fit-page mode.
|
|
24
|
+
- **`responsive` Prop**: Added `responsive?: boolean` (defaults to `true`) to `<TeamSyncViewer>` and `WebViewerOptions` for explicit control over auto-refitting on container resize.
|
|
25
|
+
- **Public `calculateFitWidthScale` Utility**: Exported `calculateFitWidthScale(availableWidth, pageWidth, ratio?, minScale?, maxScale?)` from the public package root.
|
|
26
|
+
- **Ratio Support in `fitWidth` & `fitToWidth`**: Updated `instance.UI.fitWidth(ratio?)`, `instance.UI.fitToWidth(ratio?)`, and added direct instance methods `instance.fitWidth(ratio?)`, `instance.fitToWidth(ratio?)`, `instance.fitPage()`, and `instance.fitToPage()`.
|
|
27
|
+
|
|
5
28
|
## [1.6.0] — 2026-09-06
|
|
6
29
|
|
|
7
30
|
### Added
|
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Try the **[Interactive Live Demo](https://pdfviewer.teamsync.com/)** or integrat
|
|
|
25
25
|
Traditional commercial PDF viewers force developers into expensive per-domain licenses, opaque sales calls, and heavy server-side processing dependencies. **TeamSync PDF Viewer** is built from the ground up to solve these pain points.
|
|
26
26
|
|
|
27
27
|
- 💰 **Zero-Cost, Transparent Licensing**: Uncapped usage, no per-server fees, and no commercial paywalls. 100% free and open-source under CPAL 1.0.
|
|
28
|
-
- ⚡ **100% Client-Side
|
|
28
|
+
- ⚡ **100% Client-Side PDF Processing**: Documents never leave the browser sandbox. Process, redact, and render PDFs entirely on the client.
|
|
29
29
|
- 🔌 **Universal WebViewer API**: Clean, intuitive `WebViewer({...})` API interface that makes integrating into your web applications effortless.
|
|
30
30
|
- 🎨 **Headless & Customizable**: Built for modern React 19 SPA lifecycles. No bloated iFrames to fight—customize toolbars, sidebars, context menus, and controls natively.
|
|
31
31
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { Annotation } from '../annotations/types';
|
|
3
3
|
import { AnnotationManager } from '../annotations/AnnotationManager';
|
|
4
|
-
import { Redaction, WatermarkOptions, SDKPermissions, PdfAssetPaths, TransientHighlight } from '../core/types';
|
|
4
|
+
import { Redaction, WatermarkOptions, SDKPermissions, PdfAssetPaths, TransientHighlight, InitialScale, LinkClickEvent, WebViewerInstance } from '../core/types';
|
|
5
5
|
import * as pdfjsLib from 'pdfjs-dist';
|
|
6
6
|
export interface DocumentLoadErrorInfo {
|
|
7
7
|
url: string;
|
|
@@ -56,6 +56,22 @@ interface DocumentViewerProps {
|
|
|
56
56
|
enableTextSelection?: boolean;
|
|
57
57
|
defaultTool?: 'select' | 'pan';
|
|
58
58
|
showSelectionTooltip?: boolean;
|
|
59
|
+
initialScale?: InitialScale;
|
|
60
|
+
initialWidthRatio?: number;
|
|
61
|
+
responsive?: boolean;
|
|
62
|
+
instance?: WebViewerInstance;
|
|
63
|
+
targetViewer?: WebViewerInstance | React.RefObject<WebViewerInstance | null> | (() => WebViewerInstance | null) | string;
|
|
64
|
+
resolveLinkUrl?: (linkUrl: string, context: {
|
|
65
|
+
sourceViewer: WebViewerInstance;
|
|
66
|
+
annotation?: Annotation;
|
|
67
|
+
}) => string | {
|
|
68
|
+
url: string;
|
|
69
|
+
page?: number;
|
|
70
|
+
} | Promise<string | {
|
|
71
|
+
url: string;
|
|
72
|
+
page?: number;
|
|
73
|
+
} | null> | null;
|
|
74
|
+
onLinkClick?: (event: LinkClickEvent) => boolean | void | Promise<void>;
|
|
59
75
|
}
|
|
60
|
-
export default function DocumentViewer({ leftSidebarOpen, rightSidebarOpen, activeTab, annotationManager, initialDoc, loadNonce, withCredentials, assets, sidebars, redactions, regexRedactions, scale, setScale, sidebarTab, setSidebarTab, onAnnotationsChange, onRedactionsChange, onRedactionsApplied, onDocumentLoaded, onLoadError, onFirstPageRendered, onPageRendered, onPageChange, pageTransition, pageLayout, rotation, setRotation, watermark, watermarkText, enableAnnotations: _enableAnnotations, initialPage, page, transientHighlights, permissions, hideAnnotationsUntilPageRendered, enableTextSelection, defaultTool, showSelectionTooltip }: DocumentViewerProps): React.JSX.Element;
|
|
76
|
+
export default function DocumentViewer({ leftSidebarOpen, rightSidebarOpen, activeTab, annotationManager, initialDoc, loadNonce, withCredentials, assets, sidebars, redactions, regexRedactions, scale, setScale, sidebarTab, setSidebarTab, onAnnotationsChange, onRedactionsChange, onRedactionsApplied, onDocumentLoaded, onLoadError, onFirstPageRendered, onPageRendered, onPageChange, pageTransition, pageLayout, rotation, setRotation, watermark, watermarkText, enableAnnotations: _enableAnnotations, initialPage, page, transientHighlights, permissions, hideAnnotationsUntilPageRendered, enableTextSelection, defaultTool, showSelectionTooltip, initialScale, initialWidthRatio, responsive, instance, targetViewer, resolveLinkUrl, onLinkClick, }: DocumentViewerProps): React.JSX.Element;
|
|
61
77
|
export {};
|
|
@@ -40,7 +40,8 @@ interface PageRendererProps {
|
|
|
40
40
|
onRendered?: (pageNum: number) => void;
|
|
41
41
|
/** Whether to hide annotations and transient highlights until the page canvas has finished rendering. Default: true. */
|
|
42
42
|
hideAnnotationsUntilPageRendered?: boolean;
|
|
43
|
+
onLinkClick?: (url: string, annotation?: Annotation, e?: React.MouseEvent) => void;
|
|
43
44
|
}
|
|
44
|
-
declare function PageRendererComponent({ pageNum, pdfDoc, scale, rotation, containerWidth: _containerWidth, containerHeight: _containerHeight, scrollTop: _scrollTop, scrollLeft: _scrollLeft, pageTop, pageLeft, basePageWidth, basePageHeight, activeTab, activeTool, annotations, selectedAnnotationId, activeSearchResult, transientHighlights, onMouseDown, onMouseMove, onMouseUp, onAnnotationClick, onAnnotationDoubleClick, onStartResize, onStartMove, onAnnotationMouseEnter, onClearSelection, watermark, watermarkText, redactions, onDiscardRedaction, onRendered, hideAnnotationsUntilPageRendered }: PageRendererProps): React.JSX.Element;
|
|
45
|
+
declare function PageRendererComponent({ pageNum, pdfDoc, scale, rotation, containerWidth: _containerWidth, containerHeight: _containerHeight, scrollTop: _scrollTop, scrollLeft: _scrollLeft, pageTop, pageLeft, basePageWidth, basePageHeight, activeTab, activeTool, annotations, selectedAnnotationId, activeSearchResult, transientHighlights, onMouseDown, onMouseMove, onMouseUp, onAnnotationClick, onAnnotationDoubleClick, onStartResize, onStartMove, onAnnotationMouseEnter, onClearSelection, watermark, watermarkText, redactions, onDiscardRedaction, onRendered, hideAnnotationsUntilPageRendered, onLinkClick }: PageRendererProps): React.JSX.Element;
|
|
45
46
|
declare const PageRenderer: React.MemoExoticComponent<typeof PageRendererComponent>;
|
|
46
47
|
export default PageRenderer;
|
|
@@ -13,6 +13,7 @@ interface SidebarProps {
|
|
|
13
13
|
onResultClick: (result: SearchResult) => void;
|
|
14
14
|
activeTab: 'Comments' | 'Search';
|
|
15
15
|
setActiveTab: (tab: 'Comments' | 'Search') => void;
|
|
16
|
+
onLinkClick?: (url: string, annotation?: any, e?: React.MouseEvent) => void;
|
|
16
17
|
}
|
|
17
|
-
export default function Sidebar({ isOpen, annotations, setAnnotations, selectedAnnotationId, setSelectedAnnotationId, onSearch, searchResults, isSearching, searchProgress, onResultClick, activeTab, setActiveTab }: SidebarProps): React.JSX.Element;
|
|
18
|
+
export default function Sidebar({ isOpen, annotations, setAnnotations, selectedAnnotationId, setSelectedAnnotationId, onSearch, searchResults, isSearching, searchProgress, onResultClick, activeTab, setActiveTab, onLinkClick }: SidebarProps): React.JSX.Element;
|
|
18
19
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { DocumentLoadErrorInfo } from './DocumentViewer';
|
|
3
3
|
import { WebViewerInstance } from '../core/ViewerInstance';
|
|
4
|
-
import { WebViewerOptions, Redaction, TransientHighlight } from '../core/types';
|
|
4
|
+
import { WebViewerOptions, Redaction, TransientHighlight, LinkClickEvent } from '../core/types';
|
|
5
5
|
import { Annotation } from '../annotations/types';
|
|
6
6
|
export interface TeamSyncViewerProps extends Omit<WebViewerOptions, 'path'> {
|
|
7
7
|
/** URL of the PDF to display. Alias of `initialDoc`; `fileUrl` wins when both are set. */
|
|
@@ -47,6 +47,33 @@ export interface TeamSyncViewerProps extends Omit<WebViewerOptions, 'path'> {
|
|
|
47
47
|
onTextCopied?: (info: {
|
|
48
48
|
text: string;
|
|
49
49
|
}) => void;
|
|
50
|
+
/** Unique ID for this viewer instance, enabling other viewers to target it by name. */
|
|
51
|
+
id?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Target viewer instance, ref, getter, or instance ID to open cross-document links in.
|
|
54
|
+
* When a link annotation pointing to another PDF is clicked, the document will automatically
|
|
55
|
+
* be loaded and navigated in this target viewer instance.
|
|
56
|
+
*/
|
|
57
|
+
targetViewer?: WebViewerInstance | React.RefObject<WebViewerInstance | null> | (() => WebViewerInstance | null) | string;
|
|
58
|
+
/**
|
|
59
|
+
* Optional custom resolver for cross-document links.
|
|
60
|
+
* Allows transforming relative filenames, document IDs, or URNs into full fetchable document URLs or target pages.
|
|
61
|
+
*/
|
|
62
|
+
resolveLinkUrl?: (linkUrl: string, context: {
|
|
63
|
+
sourceViewer: WebViewerInstance;
|
|
64
|
+
annotation?: Annotation;
|
|
65
|
+
}) => string | {
|
|
66
|
+
url: string;
|
|
67
|
+
page?: number;
|
|
68
|
+
} | Promise<string | {
|
|
69
|
+
url: string;
|
|
70
|
+
page?: number;
|
|
71
|
+
} | null> | null;
|
|
72
|
+
/**
|
|
73
|
+
* Fires when a link annotation or embedded PDF link is clicked.
|
|
74
|
+
* Call `event.preventDefault()` to suppress default behavior.
|
|
75
|
+
*/
|
|
76
|
+
onLinkClick?: (event: LinkClickEvent) => boolean | void | Promise<void>;
|
|
50
77
|
className?: string;
|
|
51
78
|
style?: React.CSSProperties;
|
|
52
79
|
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
1
2
|
import { ViewerBus } from './eventBus';
|
|
2
3
|
import { ExportOptions } from './export';
|
|
3
4
|
import { Annotation } from '../annotations/types';
|
|
4
5
|
import { AnnotationManager } from '../annotations/AnnotationManager';
|
|
5
6
|
import { Redaction, WatermarkOptions, ViewerEventMap, ViewerEventType, TransientHighlight } from './types';
|
|
6
7
|
import { SearchResult } from '../hooks/usePdfSearch';
|
|
7
|
-
/**
|
|
8
|
-
* © 2026 AngelBot Ai Pvt Ltd. All rights reserved.
|
|
9
|
-
* WebViewerInstance — the imperative handle returned by `createWebViewer()` and exposed through
|
|
10
|
-
* `<TeamSyncViewer ref>`. Keeps the legacy `UI` / `Core` facade for drop-in compatibility.
|
|
11
|
-
*/
|
|
12
8
|
import type * as pdfjsLib from 'pdfjs-dist';
|
|
13
9
|
/** Callbacks the React component installs so the instance can reach live state. */
|
|
14
10
|
export interface ViewerBinding {
|
|
@@ -29,15 +25,31 @@ export interface ViewerBinding {
|
|
|
29
25
|
setTransientHighlights(highlights: TransientHighlight[]): void;
|
|
30
26
|
}
|
|
31
27
|
export declare class WebViewerInstance {
|
|
28
|
+
private static instances;
|
|
29
|
+
/** Retrieve a registered WebViewerInstance by its ID. */
|
|
30
|
+
static getInstance(id: string): WebViewerInstance | undefined;
|
|
31
|
+
/** Register a WebViewerInstance with an ID. */
|
|
32
|
+
static registerInstance(id: string, instance: WebViewerInstance): void;
|
|
33
|
+
/** Unregister an instance by its ID. */
|
|
34
|
+
static unregisterInstance(id: string): void;
|
|
35
|
+
/** Clear all registered instances (primarily for testing). */
|
|
36
|
+
static clearInstances(): void;
|
|
32
37
|
readonly bus: ViewerBus;
|
|
33
38
|
/** Annotation list, history, permissions and XFDF import/export. */
|
|
34
39
|
readonly annotationManager: AnnotationManager;
|
|
35
40
|
/** Root element of the viewer once mounted. */
|
|
36
41
|
element: HTMLElement | null;
|
|
42
|
+
/** Unique identifier for this instance. */
|
|
43
|
+
id?: string;
|
|
37
44
|
private binding;
|
|
38
45
|
private unmountRoot;
|
|
39
46
|
private destroyed;
|
|
40
|
-
|
|
47
|
+
private targetViewerTarget;
|
|
48
|
+
constructor(bus: ViewerBus, annotationManager?: AnnotationManager, id?: string);
|
|
49
|
+
/** Sets the target viewer instance, ref, getter, or ID to receive cross-document links. */
|
|
50
|
+
setTargetViewer(target: WebViewerInstance | React.RefObject<WebViewerInstance | null> | (() => WebViewerInstance | null) | string | null): void;
|
|
51
|
+
/** Resolves the target viewer instance if configured. */
|
|
52
|
+
getTargetViewer(): WebViewerInstance | null;
|
|
41
53
|
/** @internal */
|
|
42
54
|
_bind(binding: ViewerBinding, element: HTMLElement | null): void;
|
|
43
55
|
/** @internal */
|
|
@@ -54,10 +66,29 @@ export declare class WebViewerInstance {
|
|
|
54
66
|
on<K extends ViewerEventType>(type: K, listener: (detail: ViewerEventMap[K]) => void): () => void;
|
|
55
67
|
off<K extends ViewerEventType>(type: K, listener: (detail: ViewerEventMap[K]) => void): void;
|
|
56
68
|
/** Load (or reload) a document by URL. Resolves when loaded, rejects on load error. */
|
|
57
|
-
loadDocument(url: string
|
|
69
|
+
loadDocument(url: string, options?: {
|
|
70
|
+
page?: number;
|
|
71
|
+
initialPage?: number;
|
|
72
|
+
}): Promise<{
|
|
58
73
|
url: string;
|
|
59
74
|
numPages: number;
|
|
60
75
|
}>;
|
|
76
|
+
/**
|
|
77
|
+
* Loads a document or navigates to a page within it. If the document is already loaded,
|
|
78
|
+
* directly navigates to the requested page without reloading.
|
|
79
|
+
*/
|
|
80
|
+
loadOrNavigate(url: string, options?: {
|
|
81
|
+
page?: number;
|
|
82
|
+
initialPage?: number;
|
|
83
|
+
}): Promise<{
|
|
84
|
+
url: string;
|
|
85
|
+
numPages: number;
|
|
86
|
+
} | void>;
|
|
87
|
+
/**
|
|
88
|
+
* Programmatically trigger link following for a given link URL or target,
|
|
89
|
+
* routing through targetViewer or opening appropriately.
|
|
90
|
+
*/
|
|
91
|
+
openLink(linkUrl: string): void;
|
|
61
92
|
getDocumentUrl(): string | undefined;
|
|
62
93
|
getPdfDocument(): pdfjsLib.PDFDocumentProxy | null;
|
|
63
94
|
getCurrentPage(): number;
|
|
@@ -68,6 +99,19 @@ export declare class WebViewerInstance {
|
|
|
68
99
|
}): void;
|
|
69
100
|
/** Set the current page number (1-based). Alias of goToPage. */
|
|
70
101
|
setCurrentPage(pageNumber: number): void;
|
|
102
|
+
/**
|
|
103
|
+
* Scale the document to fit the container width.
|
|
104
|
+
*
|
|
105
|
+
* @param ratio - Optional width ratio fraction (e.g. `0.7` for 70% of available width).
|
|
106
|
+
* Defaults to `1.0` (100% full-width fit).
|
|
107
|
+
*/
|
|
108
|
+
fitWidth(ratio?: number): void;
|
|
109
|
+
/** Alias of `fitWidth`. */
|
|
110
|
+
fitToWidth(ratio?: number): void;
|
|
111
|
+
/** Scale the document to fit the entire page within the container viewport. */
|
|
112
|
+
fitPage(): void;
|
|
113
|
+
/** Alias of `fitPage`. */
|
|
114
|
+
fitToPage(): void;
|
|
71
115
|
/**
|
|
72
116
|
* Search the document for text matches, returning snippets and page bounding boxes.
|
|
73
117
|
*
|
|
@@ -145,9 +189,9 @@ export declare class WebViewerInstance {
|
|
|
145
189
|
setToolMode: (tool: string | null) => void;
|
|
146
190
|
getSelectedText: () => string;
|
|
147
191
|
copySelectedText: () => Promise<boolean>;
|
|
148
|
-
fitWidth: () => void;
|
|
192
|
+
fitWidth: (ratio?: number) => void;
|
|
149
193
|
fitPage: () => void;
|
|
150
|
-
fitToWidth: () => void;
|
|
194
|
+
fitToWidth: (ratio?: number) => void;
|
|
151
195
|
fitToPage: () => void;
|
|
152
196
|
startCompare: (docA: any, docB: any, options?: any) => void;
|
|
153
197
|
stopCompare: () => void;
|
package/dist/src/core/types.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
1
2
|
import { ViewerPlugin } from '../plugins/types';
|
|
2
3
|
import { Annotation } from '../annotations/types';
|
|
3
4
|
import { AnnotationChangedEvent } from '../annotations/AnnotationManager';
|
|
4
5
|
import { PdfAssetPaths } from './pdfAssets';
|
|
5
|
-
|
|
6
|
+
import { WebViewerInstance } from './ViewerInstance';
|
|
7
|
+
export type { PdfAssetPaths, WebViewerInstance };
|
|
6
8
|
export interface SearchBounds {
|
|
7
9
|
x: number;
|
|
8
10
|
y: number;
|
|
@@ -53,7 +55,10 @@ export interface ViewerUser {
|
|
|
53
55
|
id: string;
|
|
54
56
|
name: string;
|
|
55
57
|
}
|
|
56
|
-
export type InitialScale = number | 'fit-width' | 'fit-page'
|
|
58
|
+
export type InitialScale = number | 'fit-width' | 'fit-page' | {
|
|
59
|
+
type: 'fit-width';
|
|
60
|
+
ratio?: number;
|
|
61
|
+
};
|
|
57
62
|
export type ToolMode = 'select' | 'pan' | 'rectangle' | 'ellipse' | 'line' | 'arrow' | 'freehand' | 'highlight' | 'underline' | 'strikeout' | 'squiggly' | 'text' | 'eraser' | 'note' | 'callout' | 'signature' | 'digital_signature' | 'link' | 'redaction' | null;
|
|
58
63
|
/**
|
|
59
64
|
* Options accepted by `createWebViewer()` (and the deprecated `WebViewer()` alias).
|
|
@@ -67,6 +72,18 @@ export interface WebViewerOptions {
|
|
|
67
72
|
/** Display name used for downloads. */
|
|
68
73
|
fileName?: string;
|
|
69
74
|
initialScale?: InitialScale;
|
|
75
|
+
/**
|
|
76
|
+
* Initial page width target as a ratio of the available viewing container width (e.g. `0.7` for 70%).
|
|
77
|
+
* When provided, the viewer scales the document to occupy this fraction of available width on initial render.
|
|
78
|
+
*/
|
|
79
|
+
initialWidthRatio?: number;
|
|
80
|
+
/** Alias of `initialWidthRatio`. */
|
|
81
|
+
widthRatio?: number;
|
|
82
|
+
/**
|
|
83
|
+
* Automatically re-calculate scale when the viewer container or window resizes while in a fit or width-ratio mode.
|
|
84
|
+
* Default: true.
|
|
85
|
+
*/
|
|
86
|
+
responsive?: boolean;
|
|
70
87
|
/** 1-based page to scroll to after load. */
|
|
71
88
|
initialPage?: number;
|
|
72
89
|
/** Current 1-based page to display. Changes navigate to the given page. */
|
|
@@ -117,6 +134,52 @@ export interface WebViewerOptions {
|
|
|
117
134
|
onRedactionsChange?: (redactions: Redaction[]) => void;
|
|
118
135
|
/** Fires once per user click of Apply in the confirmation modal with all applied redactions. */
|
|
119
136
|
onRedactionsApplied?: (redactions: Redaction[]) => void;
|
|
137
|
+
/** Unique identifier for this viewer instance, allowing other viewers to target it by name. */
|
|
138
|
+
id?: string;
|
|
139
|
+
/**
|
|
140
|
+
* Target viewer instance, ref, getter, or instance ID to open cross-document links in.
|
|
141
|
+
* When a link annotation pointing to another PDF is clicked, the document will automatically
|
|
142
|
+
* be loaded and navigated in this target viewer instance.
|
|
143
|
+
*/
|
|
144
|
+
targetViewer?: WebViewerInstance | React.RefObject<WebViewerInstance | null> | (() => WebViewerInstance | null) | string;
|
|
145
|
+
/**
|
|
146
|
+
* Optional custom resolver for cross-document links.
|
|
147
|
+
* Allows transforming relative filenames, document IDs, or URNs into full fetchable document URLs or target pages.
|
|
148
|
+
*/
|
|
149
|
+
resolveLinkUrl?: (linkUrl: string, context: {
|
|
150
|
+
sourceViewer: WebViewerInstance;
|
|
151
|
+
annotation?: Annotation;
|
|
152
|
+
}) => string | {
|
|
153
|
+
url: string;
|
|
154
|
+
page?: number;
|
|
155
|
+
} | Promise<string | {
|
|
156
|
+
url: string;
|
|
157
|
+
page?: number;
|
|
158
|
+
} | null> | null;
|
|
159
|
+
/**
|
|
160
|
+
* Fires when a link annotation or embedded PDF link is clicked.
|
|
161
|
+
* Call `event.preventDefault()` to suppress default behavior.
|
|
162
|
+
*/
|
|
163
|
+
onLinkClick?: (event: LinkClickEvent) => boolean | void | Promise<void>;
|
|
164
|
+
}
|
|
165
|
+
/** Details provided when a link annotation or embedded PDF link is clicked. */
|
|
166
|
+
export interface LinkClickEvent {
|
|
167
|
+
/** The raw link URL or target string. */
|
|
168
|
+
url: string;
|
|
169
|
+
/** Target document URL if the link points to a document (clean without page hash). */
|
|
170
|
+
docUrl?: string;
|
|
171
|
+
/** Target page number (1-based), if specified in the link. */
|
|
172
|
+
pageNumber?: number;
|
|
173
|
+
/** True if the link points to an internal page in the current document. */
|
|
174
|
+
isInternalPage: boolean;
|
|
175
|
+
/** The annotation object if clicked from a link annotation. */
|
|
176
|
+
annotation?: Annotation;
|
|
177
|
+
/** Original mouse event if triggered by user interaction. */
|
|
178
|
+
originalEvent?: React.MouseEvent;
|
|
179
|
+
/** Calling this prevents default behavior (e.g. scrolling current document, auto-forwarding to targetViewer, or opening window.open). */
|
|
180
|
+
preventDefault: () => void;
|
|
181
|
+
/** Whether preventDefault() was called. */
|
|
182
|
+
readonly defaultPrevented: boolean;
|
|
120
183
|
}
|
|
121
184
|
/** Events available through `instance.on(type, listener)`. */
|
|
122
185
|
export interface ViewerEventMap {
|
|
@@ -164,6 +227,7 @@ export interface ViewerEventMap {
|
|
|
164
227
|
textCopied: {
|
|
165
228
|
text: string;
|
|
166
229
|
};
|
|
230
|
+
linkClicked: LinkClickEvent;
|
|
167
231
|
destroy: Record<string, never>;
|
|
168
232
|
}
|
|
169
233
|
export type ViewerEventType = keyof ViewerEventMap;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -17,7 +17,9 @@ export { ViewerBus } from './core/eventBus';
|
|
|
17
17
|
export type { BusListener } from './core/eventBus';
|
|
18
18
|
export { buildPdfBytes, MAX_EXPORT_BYTES } from './core/export';
|
|
19
19
|
export type { ExportInput, ExportOptions } from './core/export';
|
|
20
|
-
export type { WebViewerOptions, Redaction, WatermarkOptions, SDKPermissions, ViewerUser, InitialScale, ViewerEventMap, ViewerEventType, ToolMode, } from './core/types';
|
|
20
|
+
export type { WebViewerOptions, Redaction, WatermarkOptions, SDKPermissions, ViewerUser, InitialScale, ViewerEventMap, ViewerEventType, ToolMode, LinkClickEvent, } from './core/types';
|
|
21
|
+
export { parseLinkTarget, isDocumentUrl } from './utils/linkUtils';
|
|
22
|
+
export type { ParsedLinkTarget } from './utils/linkUtils';
|
|
21
23
|
export { copyTextToClipboard } from './utils/clipboardUtils';
|
|
22
24
|
export { TextSelectionTooltip } from './components/TextSelectionTooltip';
|
|
23
25
|
export type { Annotation, AnnotationType, AnnotationPoint, AnnotationInput } from './annotations/types';
|
|
@@ -33,7 +35,7 @@ export type { PrintOptions } from './core/print';
|
|
|
33
35
|
export { usePdfSearch, searchPdfText } from './hooks/usePdfSearch';
|
|
34
36
|
export type { SearchResult, SearchBounds } from './hooks/usePdfSearch';
|
|
35
37
|
export type { TransientHighlight } from './core/types';
|
|
36
|
-
export { MIN_SCALE, MAX_SCALE, clampScale, calculateNextZoomIn, calculateNextZoomOut, calculateScrollCompensation } from './utils/zoomUtils';
|
|
38
|
+
export { MIN_SCALE, MAX_SCALE, clampScale, calculateNextZoomIn, calculateNextZoomOut, calculateFitWidthScale, calculateScrollCompensation } from './utils/zoomUtils';
|
|
37
39
|
export type { ScrollCompensationParams, ScrollPosition } from './utils/zoomUtils';
|
|
38
40
|
export { estimatePageDimensions, computeRowLayout, DEFAULT_FALLBACK_DIMS, hasDimensionMismatch } from './utils/layoutUtils';
|
|
39
41
|
export type { PageDimension, RowLayout } from './utils/layoutUtils';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* © 2026 AngelBot Ai Pvt Ltd. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
export interface ParsedLinkTarget {
|
|
5
|
+
/** Raw input URL or link target string. */
|
|
6
|
+
rawUrl: string;
|
|
7
|
+
/** True if the link refers only to an internal page jump within the current document (e.g. '#page=5' or '#5'). */
|
|
8
|
+
isInternalPage: boolean;
|
|
9
|
+
/** Clean document URL without page hash if referencing another document (e.g. 'supporting.pdf' or 'https://.../doc.pdf'). */
|
|
10
|
+
docUrl?: string;
|
|
11
|
+
/** Target page number (1-based) if specified (e.g. 5 from '#page=5' or 'doc.pdf#page=5'). */
|
|
12
|
+
pageNumber?: number;
|
|
13
|
+
/** True if this is an external web URL (e.g. 'https://google.com') that is not a PDF/document. */
|
|
14
|
+
isExternalWeb: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Checks whether a given URL or filename refers to a PDF / document rather than a general web page.
|
|
18
|
+
*/
|
|
19
|
+
export declare function isDocumentUrl(url: string): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Parses any link URL into structured destination information, extracting target documents and page numbers.
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseLinkTarget(linkUrl: string): ParsedLinkTarget;
|
|
@@ -27,6 +27,11 @@ export declare function calculateNextZoomOut(currentScale: number, minScale?: nu
|
|
|
27
27
|
* Clamps and rounds a requested zoom level within [minScale, maxScale].
|
|
28
28
|
*/
|
|
29
29
|
export declare function clampScale(scale: number, minScale?: number, maxScale?: number): number;
|
|
30
|
+
/**
|
|
31
|
+
* Calculates the target scale to fit a given page width to an available container width,
|
|
32
|
+
* optionally scaled by a width ratio (e.g. 0.7 for 70% of available width).
|
|
33
|
+
*/
|
|
34
|
+
export declare function calculateFitWidthScale(availableWidth: number, pageWidth: number, ratio?: number, minScale?: number, maxScale?: number): number;
|
|
30
35
|
/**
|
|
31
36
|
* Calculates the safe rasterization scale for PDF.js viewport rendering so that
|
|
32
37
|
* canvas dimensions and texture memory stay strictly within hardware limits.
|