teamsync-pdf-viewer 1.3.5 → 1.4.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,23 @@
2
2
 
3
3
  All notable changes to `teamsync-pdf-viewer` are documented here.
4
4
 
5
+ ## [1.4.0] — 2026-09-04
6
+
7
+ ### Added
8
+ - **Text Selection & Copying Support**: Users can now select and copy text directly from PDF pages in the viewer.
9
+ - **Select & Pan Tool Modes**: Added `'select'` as a first-class `ToolMode`. Defaulted `activeTool` to `'select'` (matching Adobe Acrobat, Chrome, and PDF.js). Added "Select Text" (`MousePointer`) and "Pan Tool" (`Hand`) toggle buttons to the top toolbar. Added `defaultTool?: 'select' | 'pan'` and `enableTextSelection?: boolean` props to `WebViewerOptions` and `<TeamSyncViewer>`.
10
+ - **Triple-Layer Copy Workflows**:
11
+ - **Keyboard**: `Cmd+C` (macOS) / `Ctrl+C` (Windows/Linux) copies selected text to the clipboard.
12
+ - **Native Context Menu**: Right-clicking selected text preserves the native browser context menu ("Copy", "Look Up", "Search", "Translate").
13
+ - **Floating Quick-Copy Tooltip**: Rendered a sleek floating pill above active text selections with a `[Copy]` button and `✓ Copied!` visual feedback.
14
+ - **Public SDK APIs & Events**: Added `instance.getSelectedText(): string` and `instance.copySelectedText(): Promise<boolean>`, Apryse tool aliases in `instance.UI.setToolMode('select' | 'textSelect' | 'pan')`, and `textSelected` and `textCopied` events to `ViewerEventMap`.
15
+ - **Cross-Environment Clipboard Utility**: Exported `copyTextToClipboard` with modern `navigator.clipboard.writeText` and a hidden `document.execCommand('copy')` fallback for non-HTTPS and iframe environments.
16
+
17
+ ### Fixed
18
+ - **Panning Drag Interference**: Drag-panning is now strictly scoped to `activeTool === 'pan'`, ensuring text selection click-and-drag is never hijacked.
19
+ - **SVG Overlay Pointer Events**: Configured SVG overlay to `pointerEvents: 'none'` in select and pan modes so clicks reach the text layer, while preserving `pointerEvents: 'all'` on individual annotation elements.
20
+ - **PDF.js v6 Text Layer CSS Variables**: Declared `--total-scale-factor: 1; --scale-factor: 1; --user-unit: 1; --min-font-size: 1; --scale-round-x: 1px; --scale-round-y: 1px;` on `.textLayer`, resolving collapsed 0px font sizes and heights. Styled `.textLayer span::selection` with transparent text so the underlying canvas raster remains crisp without double glyphs.
21
+
5
22
  ## [1.3.5] — 2026-09-04
6
23
 
7
24
  ### Fixed
@@ -51,6 +51,9 @@ interface DocumentViewerProps {
51
51
  permissions?: SDKPermissions;
52
52
  /** Whether to hide annotations and transient highlights until the page canvas has finished rendering. Default: true. */
53
53
  hideAnnotationsUntilPageRendered?: boolean;
54
+ enableTextSelection?: boolean;
55
+ defaultTool?: 'select' | 'pan';
56
+ showSelectionTooltip?: boolean;
54
57
  }
55
- export default function DocumentViewer({ leftSidebarOpen, rightSidebarOpen, activeTab, annotationManager, initialDoc, loadNonce, withCredentials, assets, sidebars, redactions, regexRedactions, scale, setScale, sidebarTab, setSidebarTab, onAnnotationsChange, onRedactionsChange, onDocumentLoaded, onLoadError, onFirstPageRendered, onPageRendered, onPageChange, pageTransition, pageLayout, rotation, setRotation, watermark, watermarkText, enableAnnotations: _enableAnnotations, initialPage, page, transientHighlights, permissions, hideAnnotationsUntilPageRendered }: DocumentViewerProps): React.JSX.Element;
58
+ export default function DocumentViewer({ leftSidebarOpen, rightSidebarOpen, activeTab, annotationManager, initialDoc, loadNonce, withCredentials, assets, sidebars, redactions, regexRedactions, scale, setScale, sidebarTab, setSidebarTab, onAnnotationsChange, onRedactionsChange, 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;
56
59
  export {};
@@ -35,6 +35,14 @@ export interface TeamSyncViewerProps extends Omit<WebViewerOptions, 'path'> {
35
35
  onAnnotationsChange?: (annotations: Annotation[]) => void;
36
36
  /** Fires whenever transient highlights change. */
37
37
  onTransientHighlightsChange?: (highlights: TransientHighlight[]) => void;
38
+ /** Fires whenever the user selects text within the document. */
39
+ onTextSelected?: (info: {
40
+ text: string;
41
+ }) => void;
42
+ /** Fires whenever text is copied from the document. */
43
+ onTextCopied?: (info: {
44
+ text: string;
45
+ }) => void;
38
46
  className?: string;
39
47
  style?: React.CSSProperties;
40
48
  }
@@ -0,0 +1,7 @@
1
+ import { default as React } from 'react';
2
+ interface TextSelectionTooltipProps {
3
+ containerRef: React.RefObject<HTMLDivElement | null>;
4
+ onCopy?: (text: string) => void;
5
+ }
6
+ export declare const TextSelectionTooltip: React.FC<TextSelectionTooltipProps>;
7
+ export default TextSelectionTooltip;
@@ -103,6 +103,15 @@ export declare class WebViewerInstance {
103
103
  * Uses the bytes of the loaded document; never re-fetches the URL.
104
104
  */
105
105
  getFileData(options?: ExportOptions): Promise<Uint8Array>;
106
+ /**
107
+ * Returns the currently selected text string from the document viewer, or an empty string if nothing is selected.
108
+ */
109
+ getSelectedText(): string;
110
+ /**
111
+ * Copies the currently selected text to the system clipboard.
112
+ * Resolves to true if copying succeeded, false otherwise.
113
+ */
114
+ copySelectedText(): Promise<boolean>;
106
115
  readonly UI: {
107
116
  /** Theming is not implemented; kept for API compatibility. */
108
117
  setTheme: (_theme: string) => void;
@@ -114,6 +123,8 @@ export declare class WebViewerInstance {
114
123
  disableElements: (elements: string[]) => void;
115
124
  setActiveLeftPanel: (panel: string) => void;
116
125
  setToolMode: (tool: string | null) => void;
126
+ getSelectedText: () => string;
127
+ copySelectedText: () => Promise<boolean>;
117
128
  fitWidth: () => void;
118
129
  fitPage: () => void;
119
130
  fitToWidth: () => void;
@@ -54,6 +54,7 @@ export interface ViewerUser {
54
54
  name: string;
55
55
  }
56
56
  export type InitialScale = number | 'fit-width' | 'fit-page';
57
+ export type ToolMode = 'select' | 'pan' | 'rectangle' | 'ellipse' | 'line' | 'arrow' | 'freehand' | 'highlight' | 'text' | 'eraser' | 'note' | 'callout' | 'signature' | 'digital_signature' | 'link' | 'redaction' | null;
57
58
  /**
58
59
  * Options accepted by `createWebViewer()` (and the deprecated `WebViewer()` alias).
59
60
  * Every option is also available as a prop on `<TeamSyncViewer>`.
@@ -106,6 +107,12 @@ export interface WebViewerOptions {
106
107
  * Default true.
107
108
  */
108
109
  hideAnnotationsUntilPageRendered?: boolean;
110
+ /** Allow selecting text from PDF pages (default true). */
111
+ enableTextSelection?: boolean;
112
+ /** Initial tool mode on load. Defaults to 'select'. */
113
+ defaultTool?: 'select' | 'pan';
114
+ /** Show floating quick-action copy badge above selected text (default true). */
115
+ showSelectionTooltip?: boolean;
109
116
  }
110
117
  /** Events available through `instance.on(type, listener)`. */
111
118
  export interface ViewerEventMap {
@@ -141,6 +148,12 @@ export interface ViewerEventMap {
141
148
  toolChanged: {
142
149
  tool: string | null;
143
150
  };
151
+ textSelected: {
152
+ text: string;
153
+ };
154
+ textCopied: {
155
+ text: string;
156
+ };
144
157
  destroy: Record<string, never>;
145
158
  }
146
159
  export type ViewerEventType = keyof ViewerEventMap;
@@ -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, } from './core/types';
20
+ export type { WebViewerOptions, Redaction, WatermarkOptions, SDKPermissions, ViewerUser, InitialScale, ViewerEventMap, ViewerEventType, ToolMode, } from './core/types';
21
+ export { copyTextToClipboard } from './utils/clipboardUtils';
22
+ export { TextSelectionTooltip } from './components/TextSelectionTooltip';
21
23
  export type { Annotation, AnnotationType, AnnotationPoint, AnnotationInput } from './annotations/types';
22
24
  export { AnnotationManager } from './annotations/AnnotationManager';
23
25
  export type { AnnotationAction, AnnotationChangedEvent, CommitOptions, ViewerUserInfo } from './annotations/AnnotationManager';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * © 2026 AngelBot Ai Pvt Ltd. All rights reserved.
3
+ * Cross-environment clipboard utility with secure and fallback execCommand copying.
4
+ */
5
+ export declare function copyTextToClipboard(text: string): Promise<boolean>;