teamsync-pdf-viewer 1.1.0 → 1.2.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 CHANGED
@@ -2,6 +2,35 @@
2
2
 
3
3
  All notable changes to `teamsync-pdf-viewer` are documented here.
4
4
 
5
+ ## [1.2.0] — 2026-08-31
6
+
7
+ ### Added
8
+ - **`AnnotationManager`** (`instance.annotationManager`, also `instance.Core.annotationManager`):
9
+ the canonical annotation list with undo/redo, granular `annotationChanged` events
10
+ (`add` | `modify` | `delete`, with an `imported` flag), authorship stamping
11
+ (`currentUser`), edit permissions (read-only viewer, read-only annotation, other authors —
12
+ `permissions.canEditOthers`) and programmatic `addAnnotations` / `updateAnnotation` /
13
+ `deleteAnnotations` / `getAnnotationById`.
14
+ - **Native XFDF**: `annotationManager.importAnnotations(xfdf)` and
15
+ `exportAnnotations({ annotList?, useDisplayAuthor? })` (bare fragments per annotation, or a full
16
+ document). Reads Acrobat/Apryse XFDF (square, circle, line/arrow, ink, highlight quads, freetext,
17
+ callout, sticky note, stamp with image data, link) and keeps everything else as read-only
18
+ `opaque` annotations that re-export verbatim; unknown attributes/children (e.g. Apryse
19
+ `trn-custom-data`) are preserved across a round-trip. Stable UUID ids double as the XFDF `name`.
20
+ - **Page geometry module** (`createPageGeometry`, `rectToPdf`, `quadPointsToRects`, …): the single
21
+ authority for base-page-space ↔ PDF-user-space conversion, mirroring pdf.js's viewport transform.
22
+ - **Print** (menu item enabled, `instance.print()`): the exported document is printed through the
23
+ browser's PDF viewer in a hidden frame.
24
+ - `instance.on('annotationChanged', …)` typed event; `Annotation.author/authorId/createdAt/
25
+ modifiedAt/readOnly/strokes/rects` fields; multi-stroke ink and multi-rect highlights render.
26
+
27
+ ### Fixed
28
+ - Export geometry: annotations are baked exactly where they were drawn (any page size, CropBox
29
+ offset or intrinsic /Rotate) — replaces the hard-coded `scale = 1.5` conversion.
30
+ - Mixed page sizes: layout, scrolling, hit-testing and fit-to-width/page now use per-page
31
+ dimensions instead of page 1's.
32
+ - Annotation ids were timestamps (collision-prone); now `crypto.randomUUID()`.
33
+
5
34
  ## [1.1.0] — 2026-08-31
6
35
 
7
36
  ### Breaking
package/README.md CHANGED
@@ -34,8 +34,13 @@ Client-side PDF viewing, annotation, search, redaction and watermarking for Reac
34
34
  keyboard shortcuts apply to the focused viewer only, and importing the package is side-effect free
35
35
  (safe under SSR).
36
36
 
37
- Not yet supported: printing (planned for 1.2), AcroForm filling, rendering of annotations already
38
- embedded in the PDF, document outline/bookmarks, password prompts (password-protected files raise
37
+ - **Annotation API** — `instance.annotationManager`: undo/redo, granular `annotationChanged`
38
+ events, authorship + edit permissions, programmatic add/update/delete and **native XFDF**
39
+ import/export (Acrobat/Apryse-compatible; unknown markup is preserved as read-only pass-through).
40
+ - **Print** — via the menu or `instance.print()`.
41
+
42
+ Not yet supported: AcroForm filling, rendering of annotations already embedded in the PDF (only
43
+ XFDF-imported ones), document outline/bookmarks, password prompts (password-protected files raise
39
44
  `onPasswordRequired`).
40
45
 
41
46
  ---
@@ -162,6 +167,9 @@ instance.destroy(); // unmounts and releases every listener
162
167
  | `autoFocus` | `boolean` | `false` | Focus the viewer on mount (keyboard shortcuts). |
163
168
  | `plugins` | `ViewerPlugin[]` | `[]` | Extension plugins. |
164
169
 
170
+ `permissions.canEditOthers` (default `false`) lets a user edit or delete annotations authored by
171
+ someone else; annotations carry `author`/`authorId` from `currentUser`.
172
+
165
173
  Callbacks: `onReady(instance)`, `onDocumentLoaded({ url, numPages })`,
166
174
  `onDocumentLoadError(error, retry(newUrl?), { url, passwordRequired })`, `onFirstPageRendered`,
167
175
  `onPasswordRequired`, `onPageChange(page, numPages)`, `onAnnotationsChange(annotations)`.
@@ -172,7 +180,12 @@ Callbacks: `onReady(instance)`, `onDocumentLoaded({ url, numPages })`,
172
180
  `firstPageRendered`, `pageChanged`, `annotationsChanged`, `toolChanged`, `destroy`.
173
181
  - `loadDocument(url)` — load or reload (resolves on load, rejects on error).
174
182
  - `getFileData({ explicitAnnotations? })` — export the document as `Uint8Array`.
175
- - `getAnnotations()`, `getCurrentPage()`, `getPageCount()`, `getPdfDocument()`.
183
+ - `getAnnotations()`, `getCurrentPage()`, `getPageCount()`, `getPdfDocument()`, `print()`.
184
+ - `annotationManager` — `getAnnotationsList()`, `getAnnotationById(id)`, `addAnnotations(list)`,
185
+ `updateAnnotation(id, patch)`, `deleteAnnotations(ids, { force })`, `undo()`/`redo()`,
186
+ `importAnnotations(xfdf)`, `exportAnnotations({ annotList?, useDisplayAuthor? })`,
187
+ `setCurrentUser(name, id?)`, `setReadOnly(bool)`, `canEdit(annotation)`,
188
+ `addEventListener('annotationChanged', ({ annotations, action, imported }) => …)`.
176
189
  - `destroy()` — unmount (imperative API) and release every listener.
177
190
  - `UI.*` / `Core.*` — legacy facades (`UI.openElements`, `UI.fitWidth`,
178
191
  `Core.annotationManager.exportAnnotations()`, `Core.documentViewer.getDocument().getFileData()`).
@@ -216,6 +229,13 @@ src/
216
229
  └── demo/ # demo & iframe-package bootstrap (not published)
217
230
  ```
218
231
 
232
+ ### Releasing
233
+
234
+ 1. Bump `version` in `package.json` + add a `CHANGELOG.md` entry, merge to `main`.
235
+ 2. Either push a tag `vX.Y.Z` on that commit, or run the **Publish to npm** workflow manually
236
+ with the ref to publish. The workflow re-runs the full verification chain, checks the version
237
+ is not already on the registry, and publishes with provenance (needs the `NPM_TOKEN` secret).
238
+
219
239
  ### Iframe package (script-tag hosts)
220
240
 
221
241
  `npm run build:app` produces a self-contained viewer; `public/webviewer.js` wraps it in an iframe
@@ -0,0 +1,90 @@
1
+ import { PDFDocumentProxy } from 'pdfjs-dist';
2
+ import { Annotation, AnnotationInput } from './types';
3
+ import { XfdfExportOptions } from './xfdf';
4
+ export type AnnotationAction = 'add' | 'modify' | 'delete';
5
+ export interface AnnotationChangedEvent {
6
+ annotations: Annotation[];
7
+ action: AnnotationAction;
8
+ /** True when the change came from importAnnotations()/programmatic APIs flagged as imported. */
9
+ imported: boolean;
10
+ }
11
+ export interface CommitOptions {
12
+ /** Mark the change as an import round-trip (not persisted by host bridges, not undoable). */
13
+ imported?: boolean;
14
+ /** Bypass read-only / authorship checks (programmatic host operations). */
15
+ force?: boolean;
16
+ /** Record in the undo history (default: true unless imported). */
17
+ undoable?: boolean;
18
+ }
19
+ export interface ViewerUserInfo {
20
+ id?: string;
21
+ name?: string;
22
+ }
23
+ type ChangedListener = (event: AnnotationChangedEvent) => void;
24
+ export declare class AnnotationManager {
25
+ private list;
26
+ private past;
27
+ private future;
28
+ private changedListeners;
29
+ private listListeners;
30
+ private user;
31
+ private readOnly;
32
+ private canEditOthers;
33
+ private resolver;
34
+ setDocument(doc: PDFDocumentProxy | null): void;
35
+ hasDocument(): boolean;
36
+ setCurrentUser(name: string, id?: string): void;
37
+ setCurrentUserInfo(user: ViewerUserInfo | undefined): void;
38
+ getCurrentUser(): string;
39
+ getCurrentUserInfo(): ViewerUserInfo;
40
+ setReadOnly(readOnly: boolean): void;
41
+ isReadOnly(): boolean;
42
+ /** Allow editing/deleting annotations authored by other users (default false). */
43
+ setCanEditOthers(value: boolean): void;
44
+ /** Whether the current user may modify or delete this annotation through the UI. */
45
+ canEdit(a: Annotation): boolean;
46
+ canAdd(): boolean;
47
+ /** The current list. The array reference is stable until the next change. */
48
+ getAnnotationsList(): Annotation[];
49
+ getAnnotationById(id: string): Annotation | undefined;
50
+ /** React `useSyncExternalStore` pair. */
51
+ subscribe: (listener: () => void) => (() => void);
52
+ getSnapshot: () => Annotation[];
53
+ addEventListener(type: 'annotationChanged', listener: ChangedListener): () => void;
54
+ removeEventListener(type: 'annotationChanged', listener: ChangedListener): void;
55
+ /** Apryse-compat no-op: React re-renders from the list. */
56
+ drawAnnotationsFromList(_annotations: Annotation[]): void;
57
+ get canUndo(): boolean;
58
+ get canRedo(): boolean;
59
+ undo(): boolean;
60
+ redo(): boolean;
61
+ /**
62
+ * Replace the whole list (the UI's edit path). Diffs against the current list, enforces
63
+ * permissions (rejected edits keep the previous version), records history and emits one
64
+ * `annotationChanged` event per action.
65
+ */
66
+ commit(next: Annotation[], opts?: CommitOptions): Annotation[];
67
+ addAnnotations(inputs: AnnotationInput[], opts?: CommitOptions): Annotation[];
68
+ updateAnnotation(id: string, patch: Partial<AnnotationInput>, opts?: CommitOptions): Annotation | undefined;
69
+ deleteAnnotations(targets: Array<Annotation | string>, opts?: CommitOptions): void;
70
+ /** Remove every annotation (e.g. on document switch). Not undoable, emits deletes as imported. */
71
+ clear(): void;
72
+ /**
73
+ * Import an XFDF document or bare fragments. Annotations whose `name` already exists are
74
+ * replaced (modify), new ones added; the change is flagged `imported` and is not undoable.
75
+ * Returns the imported annotations as they now exist in the list.
76
+ */
77
+ importAnnotations(xfdf: string): Promise<Annotation[]>;
78
+ /**
79
+ * Export as XFDF. With `annotList`, returns the bare fragment(s) for those annotations (the
80
+ * form hosts persist per annotation); without it, a complete XFDF document.
81
+ */
82
+ exportAnnotations(opts?: XfdfExportOptions): Promise<string>;
83
+ /** Legacy bespoke JSON export (pre-1.2 `exportAnnotations()` shape). */
84
+ exportAnnotationsLegacyJson(): string;
85
+ private requireResolver;
86
+ private apply;
87
+ private stampNew;
88
+ private emit;
89
+ }
90
+ export {};
@@ -0,0 +1,51 @@
1
+ import { PDFDocumentProxy, PDFPageProxy } from 'pdfjs-dist';
2
+ export type Matrix = [number, number, number, number, number, number];
3
+ export interface PageGeometry {
4
+ /** 1-based page number */
5
+ pageNumber: number;
6
+ /** PDF user-space bounding box [x0, y0, x1, y1] (the CropBox pdf.js renders). */
7
+ viewBox: [number, number, number, number];
8
+ /** Intrinsic page rotation (/Rotate), normalized to 0/90/180/270. */
9
+ rotate: number;
10
+ /** Base page size in points (already swapped for 90/270). */
11
+ width: number;
12
+ height: number;
13
+ /** Base-space (viewer) -> PDF user-space transform is the inverse of this viewport transform. */
14
+ transform: Matrix;
15
+ }
16
+ export interface Rect {
17
+ x: number;
18
+ y: number;
19
+ width: number;
20
+ height: number;
21
+ }
22
+ export interface Point {
23
+ x: number;
24
+ y: number;
25
+ }
26
+ /** PDF rectangle as XFDF writes it: [llx, lly, urx, ury]. */
27
+ export type PdfRect = [number, number, number, number];
28
+ /** Build the geometry for a page from its viewBox and intrinsic rotation (mirrors pdf.js PageViewport at scale 1). */
29
+ export declare function createPageGeometry(pageNumber: number, viewBox: [number, number, number, number], rotate: number): PageGeometry;
30
+ export declare function geometryFromPage(page: PDFPageProxy): PageGeometry;
31
+ /** Small per-document cache so callers can resolve geometry for many annotations cheaply. */
32
+ export declare function createGeometryResolver(pdfDoc: PDFDocumentProxy): (pageNumber: number) => Promise<PageGeometry>;
33
+ export type GeometryResolver = (pageNumber: number) => Promise<PageGeometry>;
34
+ export declare function toPdfPoint(g: PageGeometry, p: Point): Point;
35
+ export declare function fromPdfPoint(g: PageGeometry, p: Point): Point;
36
+ /** Viewer rect (top-left origin) -> PDF rect [llx, lly, urx, ury]. */
37
+ export declare function rectToPdf(g: PageGeometry, r: Rect): PdfRect;
38
+ /** PDF rect [llx, lly, urx, ury] -> viewer rect (top-left origin). */
39
+ export declare function rectFromPdf(g: PageGeometry, r: PdfRect): Rect;
40
+ export declare function pathToPdf(g: PageGeometry, points: Point[]): Point[];
41
+ export declare function pathFromPdf(g: PageGeometry, points: Point[]): Point[];
42
+ /**
43
+ * XFDF QuadPoints for a viewer rect: x1,y1 (upper-left) x2,y2 (upper-right) x3,y3 (lower-left)
44
+ * x4,y4 (lower-right) in PDF space — the order Acrobat and Apryse write for text markup.
45
+ */
46
+ export declare function rectToQuadPoints(g: PageGeometry, r: Rect): number[];
47
+ /** Bounding viewer rect of one or more XFDF quads (8 numbers each). */
48
+ export declare function quadPointsToRects(g: PageGeometry, quads: number[]): Rect[];
49
+ export declare function unionRects(rects: Rect[]): Rect;
50
+ /** Round to 3 decimals for XFDF output (Apryse writes 3, Acrobat up to 6). */
51
+ export declare const fmt: (n: number) => string;
@@ -0,0 +1,6 @@
1
+ /**
2
+ * © 2026 AngelBot Ai Pvt Ltd. All rights reserved.
3
+ * Stable, collision-free annotation ids. They double as the XFDF `name` attribute, which hosts use
4
+ * to match persisted rows to live annotations, so they must never be timestamps.
5
+ */
6
+ export declare function newAnnotationId(): string;
@@ -6,7 +6,13 @@
6
6
  * /Rotate applied (top-left origin, PDF points). UI rotation applied by the viewer is composed on
7
7
  * top of this space at render time, so stored annotations are independent of the current view.
8
8
  */
9
- export type AnnotationType = 'rectangle' | 'ellipse' | 'line' | 'arrow' | 'freehand' | 'text' | 'note' | 'callout' | 'signature' | 'highlight' | 'digital_signature_placeholder' | 'link';
9
+ export type AnnotationType = 'rectangle' | 'ellipse' | 'line' | 'arrow' | 'freehand' | 'text' | 'note' | 'callout' | 'signature' | 'highlight' | 'digital_signature_placeholder' | 'link'
10
+ /**
11
+ * An annotation imported from XFDF that this viewer cannot edit or render natively (e.g.
12
+ * underline, squiggly, polygon, redaction). It is drawn as a read-only outline at its bounding
13
+ * box and re-exported verbatim (`rawXfdf`) so nothing is lost on a save round-trip.
14
+ */
15
+ | 'opaque';
10
16
  export interface AnnotationPoint {
11
17
  x: number;
12
18
  y: number;
@@ -42,4 +48,25 @@ export interface Annotation {
42
48
  authorId?: string;
43
49
  /** When true the annotation cannot be moved, edited or deleted in the UI. */
44
50
  readOnly?: boolean;
51
+ /** Multi-stroke ink (each stroke a polyline). `points` holds the first stroke for legacy consumers. */
52
+ strokes?: AnnotationPoint[][];
53
+ /** ISO-8601 timestamps (XFDF creationdate / date). */
54
+ createdAt?: string;
55
+ modifiedAt?: string;
56
+ /** Subject / XFDF element name of an opaque annotation (informational). */
57
+ opaqueKind?: string;
58
+ /** Verbatim XFDF element for `opaque` annotations. */
59
+ rawXfdf?: string;
60
+ /**
61
+ * XFDF attributes and child elements this viewer does not model (e.g. Apryse `trn-custom-data`,
62
+ * `defaultappearance`). Preserved on import and re-emitted on export so other viewers keep
63
+ * their metadata across a round-trip.
64
+ */
65
+ xfdfExtras?: {
66
+ attrs?: Record<string, string>;
67
+ children?: string[];
68
+ };
45
69
  }
70
+ export type AnnotationInput = Omit<Annotation, 'id'> & {
71
+ id?: string;
72
+ };
@@ -0,0 +1,18 @@
1
+ import { Annotation } from './types';
2
+ import { GeometryResolver } from './geometry';
3
+ export declare const XFDF_NS = "http://ns.adobe.com/xfdf/";
4
+ export interface XfdfExportOptions {
5
+ /** Annotations to serialize (default: all given). */
6
+ annotList?: Annotation[];
7
+ /** Write the author's display name into `title` (default true). */
8
+ useDisplayAuthor?: boolean;
9
+ }
10
+ /** ISO-8601 -> PDF date `D:YYYYMMDDHHmmSS+HH'mm'`. */
11
+ export declare function toPdfDate(iso: string | undefined): string;
12
+ /** PDF date -> ISO-8601 (best effort; returns undefined when unparseable). */
13
+ export declare function fromPdfDate(pdf: string | null | undefined): string | undefined;
14
+ /** Serialize one annotation to an XFDF element (no envelope). */
15
+ export declare function annotationToXfdfFragment(a: Annotation, resolve: GeometryResolver, opts?: XfdfExportOptions): Promise<string>;
16
+ /** Serialize annotations to a complete XFDF document. */
17
+ export declare function annotationsToXfdf(annotations: Annotation[], resolve: GeometryResolver, opts?: XfdfExportOptions): Promise<string>;
18
+ export declare function parseXfdf(xml: string, resolve: GeometryResolver): Promise<Annotation[]>;
@@ -1,5 +1,6 @@
1
1
  import { default as React } from 'react';
2
2
  import { Annotation } from '../annotations/types';
3
+ import { AnnotationManager } from '../annotations/AnnotationManager';
3
4
  import { Redaction, WatermarkOptions, SDKPermissions, PdfAssetPaths } from '../core/types';
4
5
  import * as pdfjsLib from 'pdfjs-dist';
5
6
  export interface DocumentLoadErrorInfo {
@@ -10,6 +11,8 @@ interface DocumentViewerProps {
10
11
  leftSidebarOpen: boolean;
11
12
  rightSidebarOpen: boolean;
12
13
  activeTab: string;
14
+ /** Canonical annotation list, history, permissions and XFDF (owned by the viewer instance). */
15
+ annotationManager: AnnotationManager;
13
16
  initialDoc?: string;
14
17
  /** Bump to force a reload of the same URL (retry after a load error). */
15
18
  loadNonce?: number;
@@ -43,5 +46,5 @@ interface DocumentViewerProps {
43
46
  initialPage?: number;
44
47
  permissions?: SDKPermissions;
45
48
  }
46
- export default function DocumentViewer({ leftSidebarOpen, rightSidebarOpen, activeTab, initialDoc, loadNonce, withCredentials, assets, sidebars, redactions, regexRedactions, scale, setScale, sidebarTab, setSidebarTab, onAnnotationsChange, onRedactionsChange, onDocumentLoaded, onLoadError, onFirstPageRendered, onPageChange, pageTransition, pageLayout, rotation, setRotation, watermark, watermarkText, enableAnnotations: _enableAnnotations, initialPage, permissions }: DocumentViewerProps): React.JSX.Element;
49
+ export default function DocumentViewer({ leftSidebarOpen, rightSidebarOpen, activeTab, annotationManager, initialDoc, loadNonce, withCredentials, assets, sidebars, redactions, regexRedactions, scale, setScale, sidebarTab, setSidebarTab, onAnnotationsChange, onRedactionsChange, onDocumentLoaded, onLoadError, onFirstPageRendered, onPageChange, pageTransition, pageLayout, rotation, setRotation, watermark, watermarkText, enableAnnotations: _enableAnnotations, initialPage, permissions }: DocumentViewerProps): React.JSX.Element;
47
50
  export {};
@@ -16,6 +16,7 @@ interface HeaderProps {
16
16
  onDownload: () => void;
17
17
  onFullScreen: () => void;
18
18
  onSaveAs: () => void;
19
+ onPrint?: () => void;
19
20
  onOpenSettings: () => void;
20
21
  onOpenAbout: () => void;
21
22
  onOpenSidebarTab: (tab: 'Comments' | 'Search') => void;
@@ -31,5 +32,5 @@ interface HeaderProps {
31
32
  plugins?: ViewerPlugin[];
32
33
  permissions?: SDKPermissions;
33
34
  }
34
- export default function Header({ activeTab, setActiveTab, leftSidebarOpen, setLeftSidebarOpen, rightSidebarOpen, setRightSidebarOpen: _setRightSidebarOpen, sidebarTab, scale, onZoomIn, onZoomOut, onZoomSet, onDownload, onFullScreen, onSaveAs, onOpenSettings, onOpenAbout, onOpenSidebarTab, pageTransition, setPageTransition, pageLayout, setPageLayout, rotation, setRotation, signatureCount, enableAnnotations, enableSign, plugins, permissions }: HeaderProps): React.JSX.Element;
35
+ export default function Header({ activeTab, setActiveTab, leftSidebarOpen, setLeftSidebarOpen, rightSidebarOpen, setRightSidebarOpen: _setRightSidebarOpen, sidebarTab, scale, onZoomIn, onZoomOut, onZoomSet, onDownload, onFullScreen, onSaveAs, onPrint, onOpenSettings, onOpenAbout, onOpenSidebarTab, pageTransition, setPageTransition, pageLayout, setPageLayout, rotation, setRotation, signatureCount, enableAnnotations, enableSign, plugins, permissions }: HeaderProps): React.JSX.Element;
35
36
  export {};
@@ -1,6 +1,7 @@
1
1
  import { ViewerBus } from './eventBus';
2
2
  import { ExportOptions } from './export';
3
3
  import { Annotation } from '../annotations/types';
4
+ import { AnnotationManager } from '../annotations/AnnotationManager';
4
5
  import { Redaction, WatermarkOptions, ViewerEventMap, ViewerEventType } from './types';
5
6
  /**
6
7
  * © 2026 AngelBot Ai Pvt Ltd. All rights reserved.
@@ -23,12 +24,14 @@ export interface ViewerBinding {
23
24
  }
24
25
  export declare class WebViewerInstance {
25
26
  readonly bus: ViewerBus;
27
+ /** Annotation list, history, permissions and XFDF import/export. */
28
+ readonly annotationManager: AnnotationManager;
26
29
  /** Root element of the viewer once mounted. */
27
30
  element: HTMLElement | null;
28
31
  private binding;
29
32
  private unmountRoot;
30
33
  private destroyed;
31
- constructor(bus: ViewerBus);
34
+ constructor(bus: ViewerBus, annotationManager?: AnnotationManager);
32
35
  /** @internal */
33
36
  _bind(binding: ViewerBinding, element: HTMLElement | null): void;
34
37
  /** @internal */
@@ -54,6 +57,8 @@ export declare class WebViewerInstance {
54
57
  getCurrentPage(): number;
55
58
  getPageCount(): number;
56
59
  getAnnotations(): Annotation[];
60
+ /** Print the exported document (annotations, redactions and watermark baked in). */
61
+ print(): void;
57
62
  /**
58
63
  * Build the exported PDF (annotations + watermark baked, redacted pages rasterized).
59
64
  * Uses the bytes of the loaded document; never re-fetches the URL.
@@ -74,11 +79,8 @@ export declare class WebViewerInstance {
74
79
  fitToPage: () => void;
75
80
  };
76
81
  readonly Core: {
77
- annotationManager: {
78
- /** Legacy: returns the bespoke JSON annotation list. XFDF import/export arrives in 1.2.0. */
79
- exportAnnotations: () => string;
80
- getAnnotationsList: () => Annotation[];
81
- };
82
+ /** The real AnnotationManager (XFDF import/export, granular events, permissions). */
83
+ readonly annotationManager: AnnotationManager;
82
84
  documentViewer: {
83
85
  addEventListener: (event: string, callback: (detail: unknown) => void) => (() => void);
84
86
  removeEventListener: (event: string, callback: (detail: unknown) => void) => void;
@@ -1,10 +1,13 @@
1
1
  import { Annotation } from '../annotations/types';
2
2
  import { Redaction, WatermarkOptions } from './types';
3
+ import { GeometryResolver } from '../annotations/geometry';
3
4
  /** Refuse to build documents larger than this in the browser (memory safety). */
4
5
  export declare const MAX_EXPORT_BYTES: number;
5
6
  export interface ExportInput {
6
7
  /** Returns the original document bytes (prefer `pdfDocument.getData()`). */
7
8
  getSourceBytes: () => Promise<Uint8Array | ArrayBuffer>;
9
+ /** Page geometry resolver (from the loaded pdf.js document). Derived from the bytes when absent. */
10
+ getPageGeometry?: GeometryResolver;
8
11
  annotations: Annotation[];
9
12
  redactions: Redaction[];
10
13
  watermark?: WatermarkOptions;
@@ -14,7 +17,7 @@ export interface ExportInput {
14
17
  export interface ExportOptions {
15
18
  /** Bake exactly these annotations instead of the live list. */
16
19
  explicitAnnotations?: Annotation[];
17
- /** Accepted for API compatibility. Honoured from 1.2.0 (native XFDF import). */
20
+ /** Accepted for API compatibility; annotations are always taken from the live list / explicitAnnotations. */
18
21
  xfdfString?: string;
19
22
  }
20
23
  export declare function buildPdfBytes(input: ExportInput, options?: ExportOptions): Promise<Uint8Array>;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * © 2026 AngelBot Ai Pvt Ltd. All rights reserved.
3
+ * Printing: the exported document (annotations / redactions / watermark baked in) is loaded into a
4
+ * hidden iframe and printed through the browser's PDF viewer. Falls back to opening the PDF in a
5
+ * new tab when the frame cannot print (e.g. the browser has no inline PDF viewer).
6
+ */
7
+ export interface PrintOptions {
8
+ title?: string;
9
+ /** How long the hidden frame is kept alive for the print dialog (default 60s). */
10
+ timeoutMs?: number;
11
+ }
12
+ export declare function printPdfBytes(bytes: Uint8Array, opts?: PrintOptions): Promise<void>;
@@ -1,5 +1,6 @@
1
1
  import { ViewerPlugin } from '../plugins/types';
2
2
  import { Annotation } from '../annotations/types';
3
+ import { AnnotationChangedEvent } from '../annotations/AnnotationManager';
3
4
  import { PdfAssetPaths } from './pdfAssets';
4
5
  export type { PdfAssetPaths };
5
6
  export interface Redaction {
@@ -24,6 +25,8 @@ export interface SDKPermissions {
24
25
  canEditAnnotations?: boolean;
25
26
  canDeleteAnnotations?: boolean;
26
27
  canRedact?: boolean;
28
+ /** Allow editing/deleting annotations authored by other users (default false). */
29
+ canEditOthers?: boolean;
27
30
  }
28
31
  export interface ViewerUser {
29
32
  id: string;
@@ -95,6 +98,8 @@ export interface ViewerEventMap {
95
98
  annotationsChanged: {
96
99
  annotations: Annotation[];
97
100
  };
101
+ /** Granular add / modify / delete (with the `imported` flag) from the AnnotationManager. */
102
+ annotationChanged: AnnotationChangedEvent;
98
103
  toolChanged: {
99
104
  tool: string | null;
100
105
  };
@@ -16,5 +16,14 @@ export type { BusListener } from './core/eventBus';
16
16
  export { buildPdfBytes, MAX_EXPORT_BYTES } from './core/export';
17
17
  export type { ExportInput, ExportOptions } from './core/export';
18
18
  export type { WebViewerOptions, Redaction, WatermarkOptions, SDKPermissions, ViewerUser, InitialScale, ViewerEventMap, ViewerEventType, } from './core/types';
19
- export type { Annotation, AnnotationType, AnnotationPoint } from './annotations/types';
19
+ export type { Annotation, AnnotationType, AnnotationPoint, AnnotationInput } from './annotations/types';
20
+ export { AnnotationManager } from './annotations/AnnotationManager';
21
+ export type { AnnotationAction, AnnotationChangedEvent, CommitOptions, ViewerUserInfo } from './annotations/AnnotationManager';
22
+ export { newAnnotationId } from './annotations/ids';
23
+ export { createPageGeometry, geometryFromPage, createGeometryResolver, toPdfPoint, fromPdfPoint, rectToPdf, rectFromPdf, rectToQuadPoints, quadPointsToRects, } from './annotations/geometry';
24
+ export type { PageGeometry, GeometryResolver, PdfRect, Rect, Point } from './annotations/geometry';
25
+ export { annotationsToXfdf, annotationToXfdfFragment, parseXfdf, toPdfDate, fromPdfDate, XFDF_NS } from './annotations/xfdf';
26
+ export type { XfdfExportOptions } from './annotations/xfdf';
27
+ export { printPdfBytes } from './core/print';
28
+ export type { PrintOptions } from './core/print';
20
29
  export * from './plugins/types';