teamsync-pdf-viewer 2.2.1 → 2.2.3
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 +68 -1
- package/README.md +1 -1
- package/dist/src/annotations/AnnotationManager.d.ts +2 -0
- package/dist/src/annotations/xfdf.d.ts +8 -0
- package/dist/src/components/DocumentViewer.d.ts +10 -5
- package/dist/src/components/FormFieldEditorModal.d.ts +1 -0
- package/dist/src/components/FormFieldLayer.d.ts +1 -0
- package/dist/src/components/FormSignatureModal.d.ts +1 -0
- package/dist/src/components/PageRenderer.d.ts +3 -1
- package/dist/src/components/TeamSyncViewer.d.ts +18 -2
- package/dist/src/core/ViewerInstance.d.ts +17 -0
- package/dist/src/core/export.d.ts +4 -0
- package/dist/src/core/pdfAssets.d.ts +40 -0
- package/dist/src/core/types.d.ts +44 -3
- package/dist/src/forms/FormManager.d.ts +38 -4
- package/dist/src/forms/acroFormIngestion.d.ts +6 -0
- package/dist/src/forms/types.d.ts +38 -0
- package/dist/src/index.d.ts +3 -1
- package/dist/src/utils/zoomUtils.d.ts +4 -0
- package/dist/src/version.d.ts +1 -0
- package/dist/style.css +1 -1
- package/dist/teamsync-pdf-viewer.js +3060 -2426
- package/dist/teamsync-pdf-viewer.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,7 +2,74 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `teamsync-pdf-viewer` are documented here.
|
|
4
4
|
|
|
5
|
-
## [2.2.
|
|
5
|
+
## [2.2.3] — 2026-11-08
|
|
6
|
+
|
|
7
|
+
### Performance & Loading Optimizations
|
|
8
|
+
- **Lazy Page-Dimension Scanning**:
|
|
9
|
+
- Deferred scanning page dimensions for pages 2 through $N$ until after Page 1 has completed its first canvas paint (`onFirstPageRendered`).
|
|
10
|
+
- Replaced eager 25-page parallel Promise batches with background idle slices (6 pages per slice via `requestIdleCallback`) to eliminate network contention on document open.
|
|
11
|
+
- Applied slice-level scroll offset compensation (`delta = newTop - oldTop`) in continuous mode to prevent layout jumps when non-uniform pages are measured.
|
|
12
|
+
- **Viewport-Gated Text & Link Extraction**:
|
|
13
|
+
- `fetchText()` and `fetchNativeLinks()` now run only for pages currently in view (`isInViewport`) or that have previously rendered.
|
|
14
|
+
- Off-screen virtualization buffer rows no longer issue concurrent network requests for text content, fonts, and annotation dictionaries on mount.
|
|
15
|
+
- Extracted text and links are cached in component state, eliminating redundant network reads when scrolling back into view.
|
|
16
|
+
- **Shared PDF.js Worker Lifecycle & Pre-Warming**:
|
|
17
|
+
- Added support for passing an explicit `worker?: pdfjsLib.PDFWorker` instance to `<TeamSyncViewer>`, `<DocumentViewer>`, and `createWebViewer()`.
|
|
18
|
+
- Added `createPdfWorker()`, `getSharedPdfWorker()`, and `destroySharedPdfWorker()` helpers in `src/core/pdfAssets.ts` for host idle warm-up.
|
|
19
|
+
- Reused a persistent shared worker singleton when none is passed, eliminating the 1.2 MB worker script re-evaluation overhead on every document load, retry, or split pane.
|
|
20
|
+
- Added self-healing recovery that automatically instantiates a fresh worker if `worker.destroyed` is detected.
|
|
21
|
+
- **Single-Pass Initial Fit Scale**:
|
|
22
|
+
- Pre-calculates target `fit-width` and `fit-page` scale as soon as Page 1 dimensions and container width are retrieved in `loadPdf`.
|
|
23
|
+
- Page 1 paints directly at the fitted scale on its initial canvas render, eliminating double-rendering and scale flicker.
|
|
24
|
+
- **Optimized HTTP/2 Network Defaults**:
|
|
25
|
+
- Defaulted `disableStream: true` in `resolveNetworkParams()`, aborting full-file HTTP 200 download streams after headers to prioritize HTTP 206 range reads for Page 1.
|
|
26
|
+
- Defaulted `rangeChunkSize: 524288` (512 KiB) to minimize round-trip overhead on high-latency links. Explicit host props continue to override defaults.
|
|
27
|
+
- **Load Telemetry Reporting**:
|
|
28
|
+
- Added `LoadProgressInfo` interface reporting `{ bytesLoaded, totalBytes, rangeRequests }`.
|
|
29
|
+
- Hooked `loadingTask.onProgress` to emit progress telemetry through `onLoadProgress` and the event bus (`loadProgress`).
|
|
30
|
+
- Included telemetry payload in `onFirstPageRendered` and `firstPageRendered` event to measure first-page render performance.
|
|
31
|
+
|
|
32
|
+
## [2.2.2] — 2026-11-05
|
|
33
|
+
|
|
34
|
+
### Added & Enhanced
|
|
35
|
+
- **AcroForm In-Place Updates & Round-Trip Export (F1)**:
|
|
36
|
+
- Form fields already present in a PDF are updated in-place during export via `form.getFields()` rather than failing with `FieldAlreadyExistsError` or skipping value updates.
|
|
37
|
+
- **Interactive Radio Group Export (F2)**:
|
|
38
|
+
- Radio options are exported into native interactive PDF radio groups using `form.createRadioGroup()` with calculated bounding boxes, Helvetica text labels, and selection state.
|
|
39
|
+
- **Hierarchical Checklist Export (F3)**:
|
|
40
|
+
- Multi-select checklist fields export with standardized hierarchical naming (`fieldName.OptionName`) and drawn text labels.
|
|
41
|
+
- **Clean Signature Page Stream & Flatten Option (F4, F5)**:
|
|
42
|
+
- Unsigned signature placeholders no longer burn permanent ink artifacts onto the PDF content stream unless `flatten: true` is explicitly configured in `getFileData()`.
|
|
43
|
+
- Added `field.readOnly` checkbox in `FormFieldEditorModal` locking fields against modification, and enforced `enableReadOnly()` on AcroForms.
|
|
44
|
+
- Added `{ flatten?: boolean }` export option to flatten interactive fields into static page content when desired.
|
|
45
|
+
- **Duplicate Field Key Collision Prevention (F6)**:
|
|
46
|
+
- Added duplicate name detection banner in the field configuration modal and deterministic suffix naming (`name_1`, `name_2`) during export to prevent collisions.
|
|
47
|
+
- **Electronic vs Digital Signature Clarification (F7, F10)**:
|
|
48
|
+
- Electronic signatures are explicitly labeled `"Signed electronically by ..."` without misrepresenting visual signatures as digital certificates.
|
|
49
|
+
- Removed misleading pseudo-random hex strings; digital certificate signatures now show genuine status indicators.
|
|
50
|
+
- Strict signature value validation rejecting raw strings (e.g. `[object Object]` or `hello`) while accepting structured signature objects and Base64 images.
|
|
51
|
+
- **Manager-Level Role Locking & Security (F8)**:
|
|
52
|
+
- `FormManager` enforces role assignment and read-only checks on `setValue()` and `setValues()`, blocking unauthorized edits unless `{ force: true }` is passed.
|
|
53
|
+
- **Proportional Option Font Scaling (F9)**:
|
|
54
|
+
- Replaced rigid 10px minimum clamp on radio and checklist options with proportional scaling down to 7px, eliminating overflow clipping and scrollbars on zoom-out.
|
|
55
|
+
- **Aligned Validation & Unassigned Role Policies (F11)**:
|
|
56
|
+
- Configurable `unassignedFieldsRole` (`'all' | 'none' | roleId`) ensuring completion counters and `validate()` agree. Validation errors now include role names (e.g., `(Buyer)`).
|
|
57
|
+
- **Native AcroForm & XFDF Form Ingestion (F12, F13)**:
|
|
58
|
+
- Introduced `extractAcroFormFields` to detect and parse existing PDF `Widget` annotations into interactive form field models.
|
|
59
|
+
- Introduced `parseXfdfFormFields` to parse XFDF `<widget>` and `<field>` tags directly into `FormManager` without creating dead grey outline annotations.
|
|
60
|
+
- **Form Role Metadata (F14)**:
|
|
61
|
+
- Added `partyType` (`'signer' | 'viewer' | 'notary'`), `signingOrder`, and custom `metadata` to `FormRole`.
|
|
62
|
+
- **Programmatic Tab Navigation & Granular Events (F15, F18)**:
|
|
63
|
+
- Added `instance.UI.setActiveTab(tab)` and `instance.UI.getActiveTab()` with `tabChanged` event emission.
|
|
64
|
+
- Added granular event hooks: `fieldValueChanged`, `signatureApplied`, `signatureCleared`, `fieldAdded`, `fieldRemoved`, `fieldUpdated`.
|
|
65
|
+
- **Role Field Highlighting (F16)**:
|
|
66
|
+
- Added `instance.highlightRoleFields(roleId)` with accent glow across matching fields.
|
|
67
|
+
- **Adopted Signature Caching & 1-Click Sign All (F17)**:
|
|
68
|
+
- Added session-level adopted signature persistence with 1-click application across all pending signature fields for the active role.
|
|
69
|
+
- **Prop Synchronization & Undo Isolation (F19)**:
|
|
70
|
+
- Props passed to `<TeamSyncViewer>` (`formFields`, `formData`) synchronize cleanly without resetting state or polluting undo history stacks.
|
|
71
|
+
- **Dynamic Schema Versioning (F20)**:
|
|
72
|
+
- Exported field templates now dynamically reflect library version `2.2.2`.
|
|
6
73
|
|
|
7
74
|
### Security
|
|
8
75
|
- **Cryptographically Secure Identifier Generation**: Replaced pseudo-random number generator routines with cryptographically secure random values (`crypto.randomUUID()` and `crypto.getRandomValues()`) across fallback blob URLs, manual redactions, and form roles, resolving CodeQL alert CWE-338.
|
package/README.md
CHANGED
|
@@ -31,6 +31,8 @@ export declare class AnnotationManager {
|
|
|
31
31
|
private readOnly;
|
|
32
32
|
private canEditOthers;
|
|
33
33
|
private resolver;
|
|
34
|
+
private formManager;
|
|
35
|
+
setFormManager(fm: any): void;
|
|
34
36
|
setDocument(doc: PDFDocumentProxy | null): void;
|
|
35
37
|
hasDocument(): boolean;
|
|
36
38
|
setCurrentUser(name: string, id?: string): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Annotation } from './types';
|
|
2
|
+
import { FormField, FormDataRecord } from '../forms/types';
|
|
2
3
|
import { GeometryResolver } from './geometry';
|
|
3
4
|
export declare const XFDF_NS = "http://ns.adobe.com/xfdf/";
|
|
4
5
|
export interface XfdfExportOptions {
|
|
@@ -16,3 +17,10 @@ export declare function annotationToXfdfFragment(a: Annotation, resolve: Geometr
|
|
|
16
17
|
/** Serialize annotations to a complete XFDF document. */
|
|
17
18
|
export declare function annotationsToXfdf(annotations: Annotation[], resolve: GeometryResolver, opts?: XfdfExportOptions): Promise<string>;
|
|
18
19
|
export declare function parseXfdf(xml: string, resolve: GeometryResolver): Promise<Annotation[]>;
|
|
20
|
+
/**
|
|
21
|
+
* Extracts form field definitions (<widget>) and field values (<fields>) from an XFDF document (F13).
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseXfdfFormFields(xml: string, resolve?: GeometryResolver, roleMapper?: (customData: Record<string, string>) => string | undefined): Promise<{
|
|
24
|
+
fields: FormField[];
|
|
25
|
+
values: FormDataRecord;
|
|
26
|
+
}>;
|
|
@@ -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, InitialScale, LinkClickEvent, WebViewerInstance } from '../core/types';
|
|
4
|
+
import { Redaction, WatermarkOptions, SDKPermissions, PdfAssetPaths, TransientHighlight, InitialScale, LinkClickEvent, WebViewerInstance, LoadProgressInfo } from '../core/types';
|
|
5
5
|
import { FormManager } from '../forms/FormManager';
|
|
6
6
|
import * as pdfjsLib from 'pdfjs-dist';
|
|
7
7
|
export interface DocumentLoadErrorInfo {
|
|
@@ -23,14 +23,16 @@ interface DocumentViewerProps {
|
|
|
23
23
|
httpHeaders?: Record<string, string>;
|
|
24
24
|
/** Alias for `httpHeaders` providing an alternative headers option. */
|
|
25
25
|
customHeaders?: Record<string, string>;
|
|
26
|
-
/** Maximum number of bytes fetched per HTTP 206 range request. Default is
|
|
26
|
+
/** Maximum number of bytes fetched per HTTP 206 range request. Default is 524288 (512 KB). */
|
|
27
27
|
rangeChunkSize?: number;
|
|
28
|
-
/** Disable chunked streaming of PDF file data. Default
|
|
28
|
+
/** Disable chunked streaming of PDF file data. Default true. */
|
|
29
29
|
disableStream?: boolean;
|
|
30
30
|
/** Disable automatic background pre-fetching of remaining PDF file chunks. Default false. */
|
|
31
31
|
disableAutoFetch?: boolean;
|
|
32
32
|
/** Disable HTTP 206 range requests entirely, forcing full PDF download. Default false. */
|
|
33
33
|
disableRange?: boolean;
|
|
34
|
+
/** Optional dedicated or pre-warmed pdf.js worker instance. Defaults to shared worker singleton. */
|
|
35
|
+
worker?: pdfjsLib.PDFWorker;
|
|
34
36
|
/** Password for password-protected PDFs. */
|
|
35
37
|
password?: string;
|
|
36
38
|
/** pdf.js asset locations, applied right before the document is opened. */
|
|
@@ -51,7 +53,9 @@ interface DocumentViewerProps {
|
|
|
51
53
|
onDocumentLoaded?: (doc: pdfjsLib.PDFDocumentProxy, url: string) => void;
|
|
52
54
|
onLoadError?: (error: Error, info: DocumentLoadErrorInfo) => void;
|
|
53
55
|
/** Fires once per loaded document, after the first page canvas has been painted. */
|
|
54
|
-
onFirstPageRendered?: (pageNumber: number) => void;
|
|
56
|
+
onFirstPageRendered?: (pageNumber: number, telemetry?: LoadProgressInfo) => void;
|
|
57
|
+
/** Telemetry callback reporting download progress and range requests. */
|
|
58
|
+
onLoadProgress?: (info: LoadProgressInfo) => void;
|
|
55
59
|
/** Fires whenever any page canvas has finished rendering. */
|
|
56
60
|
onPageRendered?: (pageNumber: number) => void;
|
|
57
61
|
onPageChange?: (pageNumber: number, numPages: number) => void;
|
|
@@ -90,6 +94,7 @@ interface DocumentViewerProps {
|
|
|
90
94
|
formManager?: FormManager;
|
|
91
95
|
setActiveTab?: (tab: string) => void;
|
|
92
96
|
onDownloadFilledPdf?: () => void;
|
|
97
|
+
highlightedRoleId?: string | null;
|
|
93
98
|
}
|
|
94
|
-
export default function DocumentViewer({ leftSidebarOpen, rightSidebarOpen, activeTab, annotationManager, initialDoc, loadNonce, withCredentials, httpHeaders, customHeaders, rangeChunkSize, disableStream, disableAutoFetch, disableRange, password, 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, formManager, setActiveTab, onDownloadFilledPdf, }: DocumentViewerProps): React.JSX.Element;
|
|
99
|
+
export default function DocumentViewer({ leftSidebarOpen, rightSidebarOpen, activeTab, annotationManager, initialDoc, loadNonce, withCredentials, httpHeaders, customHeaders, rangeChunkSize, disableStream, disableAutoFetch, disableRange, password, assets, sidebars, redactions, regexRedactions, scale, setScale, sidebarTab, setSidebarTab, onAnnotationsChange, onRedactionsChange, onRedactionsApplied, onDocumentLoaded, onLoadError, onFirstPageRendered, onLoadProgress, 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, formManager, setActiveTab, onDownloadFilledPdf, highlightedRoleId, worker, }: DocumentViewerProps): React.JSX.Element;
|
|
95
100
|
export {};
|
|
@@ -3,6 +3,7 @@ import { FormField, FormRole } from '../forms/types';
|
|
|
3
3
|
interface FormFieldEditorModalProps {
|
|
4
4
|
field: FormField;
|
|
5
5
|
roles?: FormRole[];
|
|
6
|
+
existingFields?: FormField[];
|
|
6
7
|
onAddRole?: (role: FormRole) => void;
|
|
7
8
|
onSave: (updated: Partial<FormField>) => void;
|
|
8
9
|
onClose: () => void;
|
|
@@ -6,6 +6,7 @@ interface FormSignatureModalProps {
|
|
|
6
6
|
role?: FormRole;
|
|
7
7
|
currentUser?: ViewerUser | null;
|
|
8
8
|
currentValue?: FormSignatureValue | any;
|
|
9
|
+
adoptedSignature?: FormSignatureValue | null;
|
|
9
10
|
defaultSignerName?: string;
|
|
10
11
|
onSave: (value: FormSignatureValue) => void;
|
|
11
12
|
onClear?: () => void;
|
|
@@ -49,7 +49,9 @@ interface PageRendererProps {
|
|
|
49
49
|
canFillForms?: boolean;
|
|
50
50
|
showFlowOrder?: boolean;
|
|
51
51
|
selectedRoleFilter?: string | null;
|
|
52
|
+
highlightedRoleId?: string | null;
|
|
53
|
+
isInViewport?: boolean;
|
|
52
54
|
}
|
|
53
|
-
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, formManager, activeFormTool, setActiveFormTool, canFillForms, showFlowOrder, selectedRoleFilter }: PageRendererProps): React.JSX.Element;
|
|
55
|
+
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, formManager, activeFormTool, setActiveFormTool, canFillForms, showFlowOrder, selectedRoleFilter, highlightedRoleId, isInViewport: propIsInViewport }: PageRendererProps): React.JSX.Element;
|
|
54
56
|
declare const PageRenderer: React.MemoExoticComponent<typeof PageRendererComponent>;
|
|
55
57
|
export default PageRenderer;
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { DocumentLoadErrorInfo } from './DocumentViewer';
|
|
3
3
|
import { WebViewerInstance } from '../core/ViewerInstance';
|
|
4
|
-
import {
|
|
4
|
+
import { FormField, FormDataRecord } from '../forms/types';
|
|
5
|
+
import { WebViewerOptions, Redaction, TransientHighlight, LinkClickEvent, LoadProgressInfo } from '../core/types';
|
|
5
6
|
import { Annotation } from '../annotations/types';
|
|
6
7
|
import { OfficeConverterConfig, OfficeFileType } from '../office';
|
|
7
8
|
export interface TeamSyncViewerProps extends Omit<WebViewerOptions, 'path'> {
|
|
@@ -18,11 +19,16 @@ export interface TeamSyncViewerProps extends Omit<WebViewerOptions, 'path'> {
|
|
|
18
19
|
* the previous one was a presigned link that expired.
|
|
19
20
|
*/
|
|
20
21
|
onDocumentLoadError?: (error: Error, retry: (newUrl?: string) => void, info: DocumentLoadErrorInfo) => void;
|
|
21
|
-
/** Fires once per document, after the first page canvas has been painted. */
|
|
22
|
+
/** Fires once per document, after the first page canvas has been painted. Includes load telemetry. */
|
|
22
23
|
onFirstPageRendered?: (info: {
|
|
23
24
|
url: string;
|
|
24
25
|
pageNumber: number;
|
|
26
|
+
bytesLoaded?: number;
|
|
27
|
+
totalBytes?: number;
|
|
28
|
+
rangeRequests?: number;
|
|
25
29
|
}) => void;
|
|
30
|
+
/** Telemetry callback reporting download progress and range requests. */
|
|
31
|
+
onLoadProgress?: (info: LoadProgressInfo) => void;
|
|
26
32
|
/** Fires whenever any page canvas has finished rendering. */
|
|
27
33
|
onPageRendered?: (info: {
|
|
28
34
|
url: string;
|
|
@@ -97,6 +103,16 @@ export interface TeamSyncViewerProps extends Omit<WebViewerOptions, 'path'> {
|
|
|
97
103
|
error: Error;
|
|
98
104
|
url?: string;
|
|
99
105
|
}) => void;
|
|
106
|
+
/** Initial active UI mode tab: 'View' | 'Annotate' | 'Forms' (default 'View') (F15). */
|
|
107
|
+
initialTab?: string;
|
|
108
|
+
/** Initial form fields definition (F19). */
|
|
109
|
+
initialFormFields?: FormField[];
|
|
110
|
+
/** Initial form data values (F19). */
|
|
111
|
+
initialFormData?: FormDataRecord;
|
|
112
|
+
/** Fires when active UI tab changes (F15). */
|
|
113
|
+
onTabChanged?: (info: {
|
|
114
|
+
tab: string;
|
|
115
|
+
}) => void;
|
|
100
116
|
className?: string;
|
|
101
117
|
style?: React.CSSProperties;
|
|
102
118
|
}
|
|
@@ -47,6 +47,10 @@ export interface LoadDocumentOptions {
|
|
|
47
47
|
withCredentials?: boolean;
|
|
48
48
|
/** Password for password-protected PDFs. */
|
|
49
49
|
password?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Optional dedicated or pre-warmed pdf.js PDFWorker instance.
|
|
52
|
+
*/
|
|
53
|
+
worker?: pdfjsLib.PDFWorker;
|
|
50
54
|
}
|
|
51
55
|
/** Callbacks the React component installs so the instance can reach live state. */
|
|
52
56
|
export interface ViewerBinding {
|
|
@@ -65,6 +69,7 @@ export interface ViewerBinding {
|
|
|
65
69
|
}): void;
|
|
66
70
|
getTransientHighlights(): TransientHighlight[];
|
|
67
71
|
setTransientHighlights(highlights: TransientHighlight[]): void;
|
|
72
|
+
getActiveTab?(): string;
|
|
68
73
|
}
|
|
69
74
|
export declare class WebViewerInstance {
|
|
70
75
|
private static instances;
|
|
@@ -89,7 +94,15 @@ export declare class WebViewerInstance {
|
|
|
89
94
|
private unmountRoot;
|
|
90
95
|
private destroyed;
|
|
91
96
|
private targetViewerTarget;
|
|
97
|
+
private currentActiveTab;
|
|
92
98
|
constructor(bus: ViewerBus, annotationManager?: AnnotationManager, id?: string, formManager?: FormManager);
|
|
99
|
+
/**
|
|
100
|
+
* Visually highlights form fields belonging to a specific role with an accent glow (F16).
|
|
101
|
+
* Pass null to clear active highlights.
|
|
102
|
+
*/
|
|
103
|
+
highlightRoleFields(roleId: string | null): void;
|
|
104
|
+
/** Returns current active tab in the viewer (F15). */
|
|
105
|
+
getActiveTab(): string;
|
|
93
106
|
/** Sets the target viewer instance, ref, getter, or ID to receive cross-document links. */
|
|
94
107
|
setTargetViewer(target: WebViewerInstance | React.RefObject<WebViewerInstance | null> | (() => WebViewerInstance | null) | string | null): void;
|
|
95
108
|
/** Resolves the target viewer instance if configured. */
|
|
@@ -266,6 +279,10 @@ export declare class WebViewerInstance {
|
|
|
266
279
|
*/
|
|
267
280
|
copySelectedText(): Promise<boolean>;
|
|
268
281
|
readonly UI: {
|
|
282
|
+
/** Sets active UI mode tab: 'View' | 'Annotate' | 'Forms' (F15). */
|
|
283
|
+
setActiveTab: (tab: "View" | "Annotate" | "Forms" | string) => void;
|
|
284
|
+
/** Returns currently active tab (F15). */
|
|
285
|
+
getActiveTab: () => string;
|
|
269
286
|
/** Theming is not implemented; kept for API compatibility. */
|
|
270
287
|
setTheme: (_theme: string) => void;
|
|
271
288
|
goToPage: (pageNumber: number) => void;
|
|
@@ -16,11 +16,15 @@ export interface ExportInput {
|
|
|
16
16
|
signerName?: string;
|
|
17
17
|
formFields?: FormField[];
|
|
18
18
|
formData?: FormDataRecord;
|
|
19
|
+
/** Whether to lock and flatten form fields into static page content on export (F5). */
|
|
20
|
+
flatten?: boolean;
|
|
19
21
|
}
|
|
20
22
|
export interface ExportOptions {
|
|
21
23
|
/** Bake exactly these annotations instead of the live list. */
|
|
22
24
|
explicitAnnotations?: Annotation[];
|
|
23
25
|
/** Accepted for API compatibility; annotations are always taken from the live list / explicitAnnotations. */
|
|
24
26
|
xfdfString?: string;
|
|
27
|
+
/** Whether to lock and flatten form fields into static page content on export (F5). */
|
|
28
|
+
flatten?: boolean;
|
|
25
29
|
}
|
|
26
30
|
export declare function buildPdfBytes(input: ExportInput, options?: ExportOptions): Promise<Uint8Array>;
|
|
@@ -1,4 +1,25 @@
|
|
|
1
1
|
import { DocumentInitParameters } from 'pdfjs-dist/types/src/display/api';
|
|
2
|
+
/**
|
|
3
|
+
* © 2026 AngelBot Ai Pvt Ltd. All rights reserved.
|
|
4
|
+
* pdf.js asset configuration.
|
|
5
|
+
*
|
|
6
|
+
* The library never bundles or inlines the pdf.js worker (that produced a 5 MB bundle with a
|
|
7
|
+
* `data:` URL worker, which strict Content-Security-Policies reject). Hosts serve the worker,
|
|
8
|
+
* CMaps, standard fonts and wasm decoders from their own origin and tell us where they live.
|
|
9
|
+
*
|
|
10
|
+
* Next.js example (copy from node_modules/pdfjs-dist into public/pdfjs/):
|
|
11
|
+
* configurePdfAssets({
|
|
12
|
+
* workerSrc: '/pdfjs/pdf.worker.min.mjs',
|
|
13
|
+
* cMapUrl: '/pdfjs/cmaps/',
|
|
14
|
+
* standardFontDataUrl: '/pdfjs/standard_fonts/',
|
|
15
|
+
* wasmUrl: '/pdfjs/wasm/',
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* Vite example:
|
|
19
|
+
* import workerSrc from 'pdfjs-dist/build/pdf.worker.min.mjs?url';
|
|
20
|
+
* configurePdfAssets({ workerSrc });
|
|
21
|
+
*/
|
|
22
|
+
import * as pdfjsLib from 'pdfjs-dist';
|
|
2
23
|
export interface PdfAssetPaths {
|
|
3
24
|
/** URL of `pdf.worker.min.mjs` matching the installed pdfjs-dist version. REQUIRED. */
|
|
4
25
|
workerSrc?: string;
|
|
@@ -25,3 +46,22 @@ export declare function assertWorkerConfigured(): void;
|
|
|
25
46
|
export declare function getDocumentParams(): Partial<DocumentInitParameters>;
|
|
26
47
|
/** pdfjs-dist version this build was compiled against (useful for worker-version mismatch checks). */
|
|
27
48
|
export declare const pdfjsVersion: string;
|
|
49
|
+
export type PDFWorker = pdfjsLib.PDFWorker;
|
|
50
|
+
/**
|
|
51
|
+
* Creates a new dedicated pdf.js worker instance.
|
|
52
|
+
* Useful for host applications that pre-warm the worker thread during idle periods.
|
|
53
|
+
*/
|
|
54
|
+
export declare function createPdfWorker(params?: {
|
|
55
|
+
name?: string;
|
|
56
|
+
port?: any;
|
|
57
|
+
verbosity?: number;
|
|
58
|
+
}): pdfjsLib.PDFWorker;
|
|
59
|
+
/**
|
|
60
|
+
* Returns a shared library-level pdf.js worker singleton.
|
|
61
|
+
* Self-healing: if the worker was destroyed or terminated, instantiates a fresh worker instance.
|
|
62
|
+
*/
|
|
63
|
+
export declare function getSharedPdfWorker(): pdfjsLib.PDFWorker | undefined;
|
|
64
|
+
/**
|
|
65
|
+
* Destroys the shared library-level pdf.js worker singleton, releasing its worker thread.
|
|
66
|
+
*/
|
|
67
|
+
export declare function destroySharedPdfWorker(): void;
|
package/dist/src/core/types.d.ts
CHANGED
|
@@ -6,7 +6,8 @@ import { PdfAssetPaths } from './pdfAssets';
|
|
|
6
6
|
import { WebViewerInstance } from './ViewerInstance';
|
|
7
7
|
import { OfficeConverterConfig, OfficeFileType } from '../office/types';
|
|
8
8
|
import { FormManager } from '../forms/FormManager';
|
|
9
|
-
import { FormField, FormDataRecord, FormRole, FormFeatureOptions } from '../forms/types';
|
|
9
|
+
import { FormField, FormDataRecord, FormRole, FormFeatureOptions, FormFieldValueChangedEvent, FormSignatureAppliedEvent, FormSignatureClearedEvent, FormFieldAddedEvent, FormFieldRemovedEvent, FormFieldUpdatedEvent } from '../forms/types';
|
|
10
|
+
import type * as pdfjsLib from 'pdfjs-dist';
|
|
10
11
|
export type { PdfAssetPaths, WebViewerInstance, OfficeConverterConfig, OfficeFileType, FormManager, FormField, FormDataRecord, FormRole, FormFeatureOptions, };
|
|
11
12
|
export interface SearchBounds {
|
|
12
13
|
x: number;
|
|
@@ -79,6 +80,12 @@ export type ToolMode = 'select' | 'pan' | 'rectangle' | 'ellipse' | 'line' | 'ar
|
|
|
79
80
|
* Options accepted by `createWebViewer()` (and the deprecated `WebViewer()` alias).
|
|
80
81
|
* Every option is also available as a prop on `<TeamSyncViewer>`.
|
|
81
82
|
*/
|
|
83
|
+
/** Loading telemetry reported during PDF document retrieval. */
|
|
84
|
+
export interface LoadProgressInfo {
|
|
85
|
+
bytesLoaded: number;
|
|
86
|
+
totalBytes: number;
|
|
87
|
+
rangeRequests?: number;
|
|
88
|
+
}
|
|
82
89
|
export interface WebViewerOptions {
|
|
83
90
|
/** @deprecated Only meaningful for the iframe package (`public/webviewer.js`). */
|
|
84
91
|
path?: string;
|
|
@@ -157,12 +164,12 @@ export interface WebViewerOptions {
|
|
|
157
164
|
customHeaders?: Record<string, string>;
|
|
158
165
|
/**
|
|
159
166
|
* Maximum number of bytes fetched per HTTP 206 range request.
|
|
160
|
-
* Default is
|
|
167
|
+
* Default is 524288 (= 512 KB), optimizing round-trip latency over HTTP/2.
|
|
161
168
|
*/
|
|
162
169
|
rangeChunkSize?: number;
|
|
163
170
|
/**
|
|
164
171
|
* Disable chunked streaming of PDF file data.
|
|
165
|
-
* Default is
|
|
172
|
+
* Default is true, prioritizing initial page range requests over full-file download streams.
|
|
166
173
|
*/
|
|
167
174
|
disableStream?: boolean;
|
|
168
175
|
/**
|
|
@@ -177,6 +184,12 @@ export interface WebViewerOptions {
|
|
|
177
184
|
* Default is false.
|
|
178
185
|
*/
|
|
179
186
|
disableRange?: boolean;
|
|
187
|
+
/**
|
|
188
|
+
* Optional dedicated or pre-warmed pdf.js PDFWorker instance.
|
|
189
|
+
* If omitted, a persistent shared library-level worker singleton is used to avoid
|
|
190
|
+
* recreating a 1.2 MB worker thread on every document open or retry.
|
|
191
|
+
*/
|
|
192
|
+
worker?: pdfjsLib.PDFWorker;
|
|
180
193
|
/** Render the top toolbar. Default true. */
|
|
181
194
|
toolbar?: boolean;
|
|
182
195
|
/** Render the left (thumbnails) and right (comments/search) panels. Default true. */
|
|
@@ -269,7 +282,11 @@ export interface ViewerEventMap {
|
|
|
269
282
|
firstPageRendered: {
|
|
270
283
|
url: string;
|
|
271
284
|
pageNumber: number;
|
|
285
|
+
bytesLoaded?: number;
|
|
286
|
+
totalBytes?: number;
|
|
287
|
+
rangeRequests?: number;
|
|
272
288
|
};
|
|
289
|
+
loadProgress: LoadProgressInfo;
|
|
273
290
|
pageRendered: {
|
|
274
291
|
url: string;
|
|
275
292
|
pageNumber: number;
|
|
@@ -302,6 +319,30 @@ export interface ViewerEventMap {
|
|
|
302
319
|
text: string;
|
|
303
320
|
};
|
|
304
321
|
linkClicked: LinkClickEvent;
|
|
322
|
+
/** Fires when active UI tab changes (View / Annotate / Forms). */
|
|
323
|
+
tabChanged: {
|
|
324
|
+
tab: string;
|
|
325
|
+
};
|
|
326
|
+
/** Granular form field value change event (F18). */
|
|
327
|
+
fieldValueChanged: FormFieldValueChangedEvent;
|
|
328
|
+
/** Granular signature applied event (F18). */
|
|
329
|
+
signatureApplied: FormSignatureAppliedEvent;
|
|
330
|
+
/** Granular signature cleared event (F18). */
|
|
331
|
+
signatureCleared: FormSignatureClearedEvent;
|
|
332
|
+
/** Form field schema added (F18). */
|
|
333
|
+
fieldAdded: FormFieldAddedEvent;
|
|
334
|
+
/** Form field schema removed (F18). */
|
|
335
|
+
fieldRemoved: FormFieldRemovedEvent;
|
|
336
|
+
/** Form field schema updated (F18). */
|
|
337
|
+
fieldUpdated: FormFieldUpdatedEvent;
|
|
338
|
+
/** Full form data changed event. */
|
|
339
|
+
formDataChanged: {
|
|
340
|
+
data: Record<string, any>;
|
|
341
|
+
};
|
|
342
|
+
/** Full form fields schema changed event. */
|
|
343
|
+
formFieldsChanged: {
|
|
344
|
+
fields: FormField[];
|
|
345
|
+
};
|
|
305
346
|
/** Fires when an Office document begins conversion. */
|
|
306
347
|
officeConverting: {
|
|
307
348
|
fileType: OfficeFileType;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FormField, FormDataRecord, FormValidationResult, FormRole, FormFeatureOptions } from './types';
|
|
1
|
+
import { FormField, FormDataRecord, FormValidationResult, FormRole, FormFeatureOptions, FormSignatureValue, FormFieldValueChangedEvent, FormSignatureAppliedEvent, FormSignatureClearedEvent, FormFieldAddedEvent, FormFieldRemovedEvent, FormFieldUpdatedEvent } from './types';
|
|
2
2
|
import { ViewerUser } from '../core/types';
|
|
3
3
|
export declare const DEFAULT_FORM_OPTIONS: FormFeatureOptions;
|
|
4
4
|
export declare const DEFAULT_ROLES: FormRole[];
|
|
@@ -25,10 +25,31 @@ export declare class FormManager {
|
|
|
25
25
|
private activeFieldListeners;
|
|
26
26
|
private optionsListeners;
|
|
27
27
|
private userListeners;
|
|
28
|
+
private fieldValueListeners;
|
|
29
|
+
private signatureAppliedListeners;
|
|
30
|
+
private signatureClearedListeners;
|
|
31
|
+
private fieldAddedListeners;
|
|
32
|
+
private fieldRemovedListeners;
|
|
33
|
+
private fieldUpdatedListeners;
|
|
34
|
+
private adoptedSignature;
|
|
28
35
|
private readOnly;
|
|
29
36
|
constructor(initialFields?: FormField[], initialValues?: FormDataRecord, initialRoles?: FormRole[], initialOptions?: Partial<FormFeatureOptions>, initialUser?: ViewerUser | null);
|
|
30
37
|
onFieldsChange(listener: FormFieldsChangeListener): () => void;
|
|
31
38
|
onDataChange(listener: FormDataChangeListener): () => void;
|
|
39
|
+
onFieldValueChanged(listener: (event: FormFieldValueChangedEvent) => void): () => void;
|
|
40
|
+
onSignatureApplied(listener: (event: FormSignatureAppliedEvent) => void): () => void;
|
|
41
|
+
onSignatureCleared(listener: (event: FormSignatureClearedEvent) => void): () => void;
|
|
42
|
+
onFieldAdded(listener: (event: FormFieldAddedEvent) => void): () => void;
|
|
43
|
+
onFieldRemoved(listener: (event: FormFieldRemovedEvent) => void): () => void;
|
|
44
|
+
onFieldUpdated(listener: (event: FormFieldUpdatedEvent) => void): () => void;
|
|
45
|
+
private notifyFieldValueChanged;
|
|
46
|
+
private notifySignatureApplied;
|
|
47
|
+
private notifySignatureCleared;
|
|
48
|
+
private notifyFieldAdded;
|
|
49
|
+
private notifyFieldRemoved;
|
|
50
|
+
private notifyFieldUpdated;
|
|
51
|
+
getAdoptedSignature(): FormSignatureValue | null;
|
|
52
|
+
setAdoptedSignature(sig: FormSignatureValue | null): void;
|
|
32
53
|
private notifyFieldsChange;
|
|
33
54
|
private notifyDataChange;
|
|
34
55
|
private pushHistory;
|
|
@@ -40,15 +61,28 @@ export declare class FormManager {
|
|
|
40
61
|
getFieldsForPage(pageIndex: number): FormField[];
|
|
41
62
|
getField(id: string): FormField | undefined;
|
|
42
63
|
getFieldByName(name: string): FormField | undefined;
|
|
43
|
-
setFields(fields: FormField[]): void;
|
|
64
|
+
setFields(fields: FormField[], recordHistory?: boolean): void;
|
|
44
65
|
addField(field: FormField): void;
|
|
45
66
|
updateField(id: string, updates: Partial<Omit<FormField, 'id'>>, recordHistory?: boolean): boolean;
|
|
46
67
|
deleteField(id: string): boolean;
|
|
68
|
+
/** Alias for deleteField (F18). */
|
|
69
|
+
removeField(id: string): boolean;
|
|
47
70
|
clearFields(): void;
|
|
48
71
|
getValues(): FormDataRecord;
|
|
49
72
|
getValue(name: string): any;
|
|
50
|
-
|
|
51
|
-
|
|
73
|
+
/**
|
|
74
|
+
* Checks whether a form field can currently be modified based on form read-only state,
|
|
75
|
+
* field-level read-only setting, and the active role assignment (F8).
|
|
76
|
+
*/
|
|
77
|
+
canEditField(fieldOrName: FormField | string): boolean;
|
|
78
|
+
setValue(name: string, value: any, options?: {
|
|
79
|
+
force?: boolean;
|
|
80
|
+
source?: 'user' | 'code';
|
|
81
|
+
}): boolean;
|
|
82
|
+
setValues(newValues: FormDataRecord, options?: {
|
|
83
|
+
force?: boolean;
|
|
84
|
+
source?: 'user' | 'code';
|
|
85
|
+
}): void;
|
|
52
86
|
clearValues(): void;
|
|
53
87
|
setReadOnly(readOnly: boolean): void;
|
|
54
88
|
isReadOnly(): boolean;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { FormField, FormDataRecord } from './types';
|
|
2
|
+
import { GeometryResolver } from '../annotations/geometry';
|
|
3
|
+
export declare function extractAcroFormFields(pdfDoc: any, resolver?: GeometryResolver): Promise<{
|
|
4
|
+
fields: FormField[];
|
|
5
|
+
values: FormDataRecord;
|
|
6
|
+
}>;
|
|
@@ -98,6 +98,37 @@ export interface FormRole {
|
|
|
98
98
|
color: string;
|
|
99
99
|
/** Optional human-readable description for the role */
|
|
100
100
|
description?: string;
|
|
101
|
+
/** Optional party type classification (e.g. 'internal', 'external', 'signer', 'viewer') */
|
|
102
|
+
partyType?: 'internal' | 'external' | string;
|
|
103
|
+
/** Optional signing order or sequence index in a multi-party workflow */
|
|
104
|
+
signingOrder?: number;
|
|
105
|
+
/** Optional custom host-specific metadata attributes */
|
|
106
|
+
metadata?: Record<string, any>;
|
|
107
|
+
}
|
|
108
|
+
export interface FormFieldValueChangedEvent {
|
|
109
|
+
fieldName: string;
|
|
110
|
+
oldValue: any;
|
|
111
|
+
newValue: any;
|
|
112
|
+
source: 'user' | 'code';
|
|
113
|
+
}
|
|
114
|
+
export interface FormSignatureAppliedEvent {
|
|
115
|
+
fieldName: string;
|
|
116
|
+
signature: FormSignatureValue;
|
|
117
|
+
signerName?: string;
|
|
118
|
+
}
|
|
119
|
+
export interface FormSignatureClearedEvent {
|
|
120
|
+
fieldName: string;
|
|
121
|
+
}
|
|
122
|
+
export interface FormFieldAddedEvent {
|
|
123
|
+
field: FormField;
|
|
124
|
+
}
|
|
125
|
+
export interface FormFieldRemovedEvent {
|
|
126
|
+
fieldId: string;
|
|
127
|
+
fieldName: string;
|
|
128
|
+
}
|
|
129
|
+
export interface FormFieldUpdatedEvent {
|
|
130
|
+
field: FormField;
|
|
131
|
+
changes: Partial<FormField>;
|
|
101
132
|
}
|
|
102
133
|
export type FormDataRecord = Record<string, any>;
|
|
103
134
|
export interface FormValidationResult {
|
|
@@ -176,4 +207,11 @@ export interface FormFeatureOptions {
|
|
|
176
207
|
* Controls which fields and signature flags are active for the current user.
|
|
177
208
|
*/
|
|
178
209
|
currentRole?: string | null;
|
|
210
|
+
/**
|
|
211
|
+
* Defines which role unassigned fields (fields with no roleId) belong to during validation:
|
|
212
|
+
* - 'all': unassigned fields are required for everyone (default)
|
|
213
|
+
* - 'none': unassigned fields are never treated as required for any specific role
|
|
214
|
+
* - string: role ID that unassigned fields belong to
|
|
215
|
+
*/
|
|
216
|
+
unassignedFieldsRole?: 'all' | 'none' | string;
|
|
179
217
|
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -51,4 +51,6 @@ export type { OfficeConverterConfig, OfficeConversionConfig, OfficeConversionSta
|
|
|
51
51
|
export { VERSION } from './version';
|
|
52
52
|
export { FormManager, DEFAULT_FORM_OPTIONS, DEFAULT_ROLES } from './forms/FormManager';
|
|
53
53
|
export type { FormFieldsChangeEvent, FormFieldsChangeListener, FormDataChangeListener } from './forms/FormManager';
|
|
54
|
-
export
|
|
54
|
+
export { extractAcroFormFields } from './forms/acroFormIngestion';
|
|
55
|
+
export { parseXfdfFormFields } from './annotations/xfdf';
|
|
56
|
+
export type { FormField, FormFieldType, DateTimeFormat, SignatureType, FormSignatureValue, FormRole, FormDataRecord, FormValidationResult, FormToolType, FormFeatureOptions, FormFieldValueChangedEvent, FormSignatureAppliedEvent, FormSignatureClearedEvent, FormFieldAddedEvent, FormFieldRemovedEvent, FormFieldUpdatedEvent, } from './forms/types';
|
|
@@ -32,6 +32,10 @@ export declare function clampScale(scale: number, minScale?: number, maxScale?:
|
|
|
32
32
|
* optionally scaled by a width ratio (e.g. 0.7 for 70% of available width).
|
|
33
33
|
*/
|
|
34
34
|
export declare function calculateFitWidthScale(availableWidth: number, pageWidth: number, ratio?: number, minScale?: number, maxScale?: number): number;
|
|
35
|
+
/**
|
|
36
|
+
* Calculates the target scale to fit a given page (both width and height) inside an available container viewport.
|
|
37
|
+
*/
|
|
38
|
+
export declare function calculateFitPageScale(availableWidth: number, availableHeight: number, pageWidth: number, pageHeight: number, minScale?: number, maxScale?: number): number;
|
|
35
39
|
/**
|
|
36
40
|
* Calculates the safe rasterization scale for PDF.js viewport rendering so that
|
|
37
41
|
* canvas dimensions and texture memory stay strictly within hardware limits.
|
package/dist/src/version.d.ts
CHANGED