teamsync-pdf-viewer 1.6.0 → 1.6.1

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,15 @@
2
2
 
3
3
  All notable changes to `teamsync-pdf-viewer` are documented here.
4
4
 
5
+ ## [1.6.1] — 2026-09-15
6
+
7
+ ### Added
8
+ - **`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).
9
+ - **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.
10
+ - **`responsive` Prop**: Added `responsive?: boolean` (defaults to `true`) to `<TeamSyncViewer>` and `WebViewerOptions` for explicit control over auto-refitting on container resize.
11
+ - **Public `calculateFitWidthScale` Utility**: Exported `calculateFitWidthScale(availableWidth, pageWidth, ratio?, minScale?, maxScale?)` from the public package root.
12
+ - **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()`.
13
+
5
14
  ## [1.6.0] — 2026-09-06
6
15
 
7
16
  ### 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 WebAssembly**: Documents never leave the browser sandbox. Process, redact, and render PDFs entirely on the client.
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 } from '../core/types';
5
5
  import * as pdfjsLib from 'pdfjs-dist';
6
6
  export interface DocumentLoadErrorInfo {
7
7
  url: string;
@@ -56,6 +56,9 @@ interface DocumentViewerProps {
56
56
  enableTextSelection?: boolean;
57
57
  defaultTool?: 'select' | 'pan';
58
58
  showSelectionTooltip?: boolean;
59
+ initialScale?: InitialScale;
60
+ initialWidthRatio?: number;
61
+ responsive?: boolean;
59
62
  }
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;
63
+ 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, }: DocumentViewerProps): React.JSX.Element;
61
64
  export {};
@@ -68,6 +68,19 @@ export declare class WebViewerInstance {
68
68
  }): void;
69
69
  /** Set the current page number (1-based). Alias of goToPage. */
70
70
  setCurrentPage(pageNumber: number): void;
71
+ /**
72
+ * Scale the document to fit the container width.
73
+ *
74
+ * @param ratio - Optional width ratio fraction (e.g. `0.7` for 70% of available width).
75
+ * Defaults to `1.0` (100% full-width fit).
76
+ */
77
+ fitWidth(ratio?: number): void;
78
+ /** Alias of `fitWidth`. */
79
+ fitToWidth(ratio?: number): void;
80
+ /** Scale the document to fit the entire page within the container viewport. */
81
+ fitPage(): void;
82
+ /** Alias of `fitPage`. */
83
+ fitToPage(): void;
71
84
  /**
72
85
  * Search the document for text matches, returning snippets and page bounding boxes.
73
86
  *
@@ -145,9 +158,9 @@ export declare class WebViewerInstance {
145
158
  setToolMode: (tool: string | null) => void;
146
159
  getSelectedText: () => string;
147
160
  copySelectedText: () => Promise<boolean>;
148
- fitWidth: () => void;
161
+ fitWidth: (ratio?: number) => void;
149
162
  fitPage: () => void;
150
- fitToWidth: () => void;
163
+ fitToWidth: (ratio?: number) => void;
151
164
  fitToPage: () => void;
152
165
  startCompare: (docA: any, docB: any, options?: any) => void;
153
166
  stopCompare: () => void;
@@ -53,7 +53,10 @@ export interface ViewerUser {
53
53
  id: string;
54
54
  name: string;
55
55
  }
56
- export type InitialScale = number | 'fit-width' | 'fit-page';
56
+ export type InitialScale = number | 'fit-width' | 'fit-page' | {
57
+ type: 'fit-width';
58
+ ratio?: number;
59
+ };
57
60
  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
61
  /**
59
62
  * Options accepted by `createWebViewer()` (and the deprecated `WebViewer()` alias).
@@ -67,6 +70,18 @@ export interface WebViewerOptions {
67
70
  /** Display name used for downloads. */
68
71
  fileName?: string;
69
72
  initialScale?: InitialScale;
73
+ /**
74
+ * Initial page width target as a ratio of the available viewing container width (e.g. `0.7` for 70%).
75
+ * When provided, the viewer scales the document to occupy this fraction of available width on initial render.
76
+ */
77
+ initialWidthRatio?: number;
78
+ /** Alias of `initialWidthRatio`. */
79
+ widthRatio?: number;
80
+ /**
81
+ * Automatically re-calculate scale when the viewer container or window resizes while in a fit or width-ratio mode.
82
+ * Default: true.
83
+ */
84
+ responsive?: boolean;
70
85
  /** 1-based page to scroll to after load. */
71
86
  initialPage?: number;
72
87
  /** Current 1-based page to display. Changes navigate to the given page. */
@@ -33,7 +33,7 @@ export type { PrintOptions } from './core/print';
33
33
  export { usePdfSearch, searchPdfText } from './hooks/usePdfSearch';
34
34
  export type { SearchResult, SearchBounds } from './hooks/usePdfSearch';
35
35
  export type { TransientHighlight } from './core/types';
36
- export { MIN_SCALE, MAX_SCALE, clampScale, calculateNextZoomIn, calculateNextZoomOut, calculateScrollCompensation } from './utils/zoomUtils';
36
+ export { MIN_SCALE, MAX_SCALE, clampScale, calculateNextZoomIn, calculateNextZoomOut, calculateFitWidthScale, calculateScrollCompensation } from './utils/zoomUtils';
37
37
  export type { ScrollCompensationParams, ScrollPosition } from './utils/zoomUtils';
38
38
  export { estimatePageDimensions, computeRowLayout, DEFAULT_FALLBACK_DIMS, hasDimensionMismatch } from './utils/layoutUtils';
39
39
  export type { PageDimension, RowLayout } from './utils/layoutUtils';
@@ -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.