UNPKG

@nutrient-sdk/viewer

Version:

View and annotate PDF files in your web app. Full support for mobile and desktop. Runs in the browser using WASM.

1,365 lines (1,316 loc) 1.09 MB
/** * This class should be used to create custom Immutable Record. It will overwrite the default * `Immutable#equals()` method to include the class name. if we don't do this, two different classes * with the same default value set will be treated as equal. * * @example * // With regular `Immutable.Record` * class A extends Record({ foo: 'bar' }) {} * class B extends Record({ foo: 'bar' }) {} * const a = new A() * const b = new B() * is(a, b) // true * * // With `InheritableImmutableRecord` * class A extends InheritableImmutableRecord { * static defaultValues = { foo: 'bar' } * } * mergeImmutableRecordDefaults(A) * class B extends InheritableImmutableRecord { * static defaultValues = { foo: 'bar' } * } * mergeImmutableRecordDefaults(B) * const a = new A() * const b = new B() * is(a, b) // false */ declare class __dangerousImmutableRecordFactory<TProps extends Record<string, unknown>> { has(key: unknown): boolean; get<K extends keyof TProps>(key: K): TProps[K]; set<K extends keyof TProps>(key: K, value: TProps[K]): this; delete<K extends keyof TProps>(key: K): this; clear(): this; update<K extends keyof TProps>(key: K, updater: (value: TProps[K]) => TProps[K]): this; merge(...collections: Array<Partial<TProps>>): this; mergeWith(merger: (previous?: unknown, next?: unknown, key?: string) => unknown, ...collections: Array<Partial<TProps> | Iterable<[string, unknown]>>): this; mergeDeep(...collections: Array<Partial<TProps> | Iterable<[string, unknown]>>): this; mergeDeepWith(merger: (previous?: unknown, next?: unknown, key?: string) => unknown, ...collections: Array<Partial<TProps> | Iterable<[string, unknown]>>): this; setIn(keyPath: Iterable<unknown>, value: unknown): this; deleteIn(keyPath: Iterable<unknown>): this; removeIn(keyPath: Iterable<unknown>): this; updateIn(keyPath: Iterable<unknown>, notSetValue: unknown, updater: (value: unknown) => unknown): this; updateIn(keyPath: Iterable<unknown>, updater: (value: unknown) => unknown): this; mergeIn(keyPath: Iterable<unknown>, ...collections: Array<Partial<TProps> | Iterable<[string, unknown]>>): this; mergeDeepIn(keyPath: Iterable<unknown>, ...collections: Array<Partial<TProps> | Iterable<[string, unknown]>>): this; withMutations(mutator: (mutable: this) => unknown): this; asMutable(): this; asImmutable(): this; getIn(keyPath: Iterable<unknown>, notSetValue?: unknown): unknown; toJS(): TProps; toJSON(): TProps; equals(other: unknown): boolean; toSeq(): Seq.Keyed<string, unknown>; } /** * @class * Base action type from which all Actions inherit. You can not instantiate from this type. * * It is an {@link https://immutable-js.com/docs/v5/Record/ | Immutable.Record}. * @summary Base action type from which all Actions inherit. */ export declare abstract class Action extends InheritableImmutableRecord<ActionProperties> { /** * Actions can be chained by adding them to this immutable List. */ subActions?: Immutable.List<Action> | null | undefined; protected constructor(args?: ActionProperties); } declare type ActionCreators = typeof textComparisonActionCreators; declare type ActionFlags = 'includeExclude' | 'includeNoValueFields' | 'exportFormat' | 'getMethod' | 'submitCoordinated' | 'xfdf' | 'includeAppendSaves' | 'includeAnnotations' | 'submitPDF' | 'canonicalFormat' | 'excludeNonUserAnnotations' | 'excludeFKey' | 'embedForm'; /** @inline */ declare type ActionProperties = { subActions?: Immutable.List<Action> | null; }; export declare namespace Actions { export { Action, GoToAction, GoToEmbeddedAction, GoToRemoteAction, HideAction, JavaScriptAction, LaunchAction, NamedAction, ResetFormAction, SubmitFormAction, URIAction }; } declare type ActionTriggerEventType = 'onPointerEnter' | 'onPointerLeave' | 'onPointerDown' | 'onPointerUp' | 'onPageOpen' | 'onPageClose' | 'onPageVisible' | 'onPageHidden'; declare interface AddPageConfiguration { backgroundColor: Color; pageWidth: number; pageHeight: number; rotateBy: Rotation; insets?: Rect; } /** * Payload for sending changes to AI services * * @public */ declare interface AIADocumentChangePayload { id: string; type: string; text: string; contextBefore: string; contextAfter: string; page: number; } /** * Base response item from AI services representing a single document change. * Contains the essential information about a text modification detected during comparison. * * @example * // Typical structure of a change item * { * id: "change-456", * type: "deletion", * text: "old contract terms", * page: 1, * contextBefore: "The following ", * contextAfter: " are no longer valid" * } */ export declare interface AIADocumentChangeResponseItem { /** Unique identifier for this change, used for tracking and correlation */ id: string; /** Type of change operation (e.g., "insertion", "deletion", "modification") */ type: string; /** The actual text content that was changed */ text: string; /** Zero-based page number where this change occurred */ page: number; /** Text content appearing before the change for context. */ contextBefore?: string; /** Text content appearing after the change for context. */ contextAfter?: string; } /** * Response from AI analysis service containing a high-level summary and categorization * of document changes. This is returned when using `NutrientViewer.AIComparisonOperationType.ANALYZE`. * * @example * // After running an ANALYZE operation * if (NutrientViewer.isAIDocumentAnalysisResult(result)) { * console.log(`Summary: ${result.summary}`); * // Example: "The document has undergone significant legal revisions with updated terminology and new clauses." * * console.log(`Categories: ${result.categories.join(', ')}`); * // Example: ["Legal Changes", "Terminology Updates", "Content Addition"] * * // Access detailed changes * console.log(`Total changes: ${result.changes.changes.size}`); * } */ export declare interface AIADocumentChangesAnalysisResponse { /** AI-generated natural language summary describing the overall nature of changes between the compared documents */ summary: string; /** Array of AI-detected change categories representing the types of modifications (e.g., "Formatting", "Content Addition", "Legal Changes", "Rewording") */ categories: string[]; /** The underlying standard document comparison result containing detailed text hunks and change operations */ changes: DocumentComparison.DocumentComparisonResult; } /** * Response from AI tagging service containing categorized change information. * This is returned when using `NutrientViewer.AIComparisonOperationType.TAG`. * * @example * // After running a TAG operation * if (NutrientViewer.isAIDocumentTaggingResult(result)) { * result.references.forEach((ref, index) => { * console.log(`Change ${index + 1}: ${ref.text}`); * console.log(`Categories: ${ref.tag.join(', ')}`); * console.log(`Page: ${ref.page}`); * }); * } */ export declare interface AIADocumentChangesTaggingResponse { /** * Array where each * item corresponds to a specific change and includes category tags assigned by the AI service. * Each reference contains the change details plus an array of category strings that classify * the type of modification (e.g., ["Legal", "Formatting"] for a legal change with formatting updates). * */ references: AIADocumentChangeTaggingItem[]; } /** * Individual change item with AI-assigned category tags from the tagging service. * Extends the base response item with categorization information. * * @example * // Typical structure of a tagged change * { * id: "change-123", * type: "insertion", * text: "confidential information", * page: 2, * contextBefore: "regarding the ", * contextAfter: " shall not be disclosed", * tag: ["Legal", "Confidentiality"] * } */ export declare interface AIADocumentChangeTaggingItem extends AIADocumentChangeResponseItem { /** Array of category strings assigned by AI to classify this change. */ tag: string[]; } /** * AI Assistant configuration namespace containing all public types. * * This namespace provides TypeScript interfaces and configuration options for integrating * the AI Assistant feature into your application. Use types from this namespace to * configure AI Assistant behavior, security policies, and custom skills. * * @namespace * @example * ```typescript * import { AIAssistant } from 'nutrient' * * const config: AIAssistant.Configuration = { * sessionId: 'user-session-123', * jwt: 'your-jwt-token', * backendUrl: 'https://ai-assistant.example.com' * } * ``` */ export declare namespace AIAssistant { /** * Configuration for the AI Assistant feature. * * Contains authentication details, backend connection information, and optional * customization settings for AI Agent behavior. * * @example * ```typescript * NutrientViewer.load({ * // ... other config * aiAssistant: { * sessionId: 'session-123', * jwt: 'eyJhbGciOiJIUzI1NiIs...', * backendUrl: 'https://localhost:4000' * } * }) * ``` */ export interface Configuration { /** * Session identifier for the AI Assistant conversation. * * Use a unique identifier to create a new session, or reuse an existing session ID * to restore a previous conversation. The ID must contain only alphanumeric characters. * * @example * ```typescript * sessionId: 'userdocsession20250128' * sessionId: 'session123abc' * ``` */ sessionId: string; /** * JSON Web Token (JWT) for authenticating requests to the AI Assistant backend. * * This token must be issued by your authentication service and should contain * user identity claims. The token is sent with every request to the backend. * * @example * ```typescript * jwt: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...' * ``` */ jwt: string; /** * URL of the AI Assistant service backend. * * This should be the base URL where your AI Assistant service is deployed. * The URL must include the protocol (http/https) but exclude trailing slashes. * * @example * ```typescript * backendUrl: 'https://ai-assistant.example.com' // ✓ correct * backendUrl: 'https://ai-assistant.example.com/' // ✗ avoid trailing slash * ``` */ backendUrl: string; /** * Optional user identifier for tracking and rate limiting. * * Provide a unique identifier for the current user. This enables per-user * rate limiting, usage analytics, and audit logging. Must contain only * alphanumeric characters. * * @example * ```typescript * userId: 'userabc12345' * userId: 'user123' * ``` */ userId?: string; /** * AI Agent preset or custom agent ID. * * Selects a base agent configuration with different capabilities and behavior. * * | Preset | Purpose | * |------------|--------------------------------------------------------------------------------| * | `chat` | Read-only Q&A mode. This agent can summarize, extract data, and answer questions. | * | `agentic` | Full autonomous agent. This agent can read, write, add annotations, fill forms, and redact documents. | * | `base` | Base configuration. This agent uses defaults for all settings and is intended for customization. | * * @default 'agentic' * @example * ```typescript * agentId: 'chat' // Use the read-only chat preset * ``` */ agentId?: 'chat' | 'agentic' | 'base' | string; /** * Advanced configuration for customizing AI Assistant agent behavior. * * Customize the system prompt, define specialized skills, configure tool execution * approval policies. * * @example * ```typescript * NutrientViewer.load({ * aiAssistant: { * sessionId: 'session-123', * jwt: 'token-here', * backendUrl: 'https://localhost:4000', * agentConfiguration: { * systemPromptTemplate: 'You are an expert legal document assistant.', * skills: [ * { * name: 'contract-review', * description: 'Analyze contracts for key terms', * content: 'Focus on liability and payment terms...' * } * ], * toolApproval: { * defaults: { default: 'allow', write: 'ask' } * } * } * } * }); * ``` */ agentConfiguration?: AgentConfiguration; } /** * Advanced configuration for AI Agent behavior and capabilities. * * Customize the agent's system instructions, define domain-specific skills, * control tool execution policies. * * This interface enables fine-grained control over how the AI Agent processes * requests, what knowledge it has access to, and which operations require user approval. * * @example * ```typescript * const config: AIAssistant.AgentConfiguration = { * systemPromptTemplate: 'You are an expert legal document assistant.', * skills: [ * { * name: 'contract-review', * description: 'Analyze contracts for key terms and risks', * content: '1. Identify all parties\n2. Extract key dates\n3. Highlight liability clauses' * } * ], * toolApproval: { * defaults: { default: 'allow', write: 'ask' } * } * } * ``` */ export interface AgentConfiguration { /** * Custom system prompt template for defining agent personality and behavior. * * Defines the base instructions, role, and guidelines that shape how the agent * processes requests and responds to users. This is the primary mechanism for * customizing the agent's expertise and behavior patterns. * * Keep prompts concise but descriptive. Focus on the agent's role, key principles, * and important constraints. * * @example * ```typescript * systemPromptTemplate: `You are an expert legal document analyst. * Your role is to: * - Identify and explain key contractual terms * - Highlight potential risks or unusual clauses * - Always cite the specific section numbers * - If uncertain, clearly state your limitations` * ``` * * @default A general-purpose document assistant prompt */ systemPromptTemplate?: string; /** * Seed messages for shaping agent behavior across all interactions. * * Messages injected before the conversation history on every model invocation. * Useful for few-shot prompting, additional constraints, and behavioral priming * that should persist across all conversation turns. * * **Important**: Seed messages are NOT persisted to the conversation history * and are injected fresh on each request. * * **Common use cases**: * - Few-shot learning: Include human/ai example pairs * - Additional instructions: Constraints that complement systemPromptTemplate * - Behavioral priming: Consistent patterns to reinforce across all responses * * @example * ```typescript * seedMessages: [ * { * type: 'human', * content: 'Analyze the indemnification clause in this contract.' * }, * { * type: 'ai', * content: 'I found the indemnification clause on page 3, section 5.2...' * } * ] * ``` */ seedMessages?: Array<{ /** * The sender type for this message. * * - `'human'`: User/human messages (used in few-shot examples) * - `'ai'`: Assistant responses (used in few-shot examples) */ type: 'human' | 'ai'; /** * The text content of the message. * * Use clear, concise language. For few-shot examples, make responses * representative of the desired behavior. */ content: string; }>; /** * User identifier for rate limiting and authorization. * * Provide a unique identifier for the current user to enable * per-user rate limiting and usage tracking. * * @example * ```typescript * userId: 'user12345' * ``` */ userId?: string; /** * Domain-specific skills for the AI Agent. * * Define specialized knowledge, instructions, or workflows that the agent * can access and apply when relevant to user requests. Skills allow you to * inject domain expertise without modifying the system prompt. * * The agent decides when to use each skill based on the skill description * and the user's request. Use descriptive names and clear instructions. * * @example * ```typescript * skills: [ * { * name: 'contract-review', * description: 'Analyze contracts for key terms and identify potential risks', * content: `When reviewing a contract: * 1. Identify all parties and signatories * 2. Extract critical dates (effective date, expiration, renewal) * 3. Summarize payment terms and amounts * 4. Highlight liability and indemnification clauses * 5. Flag unusual or potentially risky terms` * } * ] * ``` */ skills?: Array<{ /** * Unique identifier for this skill. * * Used internally by the agent to reference and invoke this skill. * Should be lowercase with hyphens (e.g., 'contract-analysis', 'data-extraction'). * Minimum 1 character, no spaces. * * @example * ```typescript * name: 'legal-clause-analysis' * ``` */ name: string; /** * Description of when and how to use this skill. * * Helps the agent decide when to apply this knowledge based on user requests. * Be specific about the skill's purpose and ideal use cases. Keep it under * 500 characters. * * @example * ```typescript * description: 'Use when analyzing legal contracts, identifying liability clauses, or explaining terms' * ``` */ description?: string; /** * Detailed knowledge and instructions for this skill. * * The actual content the agent uses when applying this skill. Include step-by-step * instructions, examples, or knowledge the agent should follow. Maximum 50,000 characters. * * @example * ```typescript * content: `Legal Contract Analysis Process: * * 1. PARTIES: Identify all parties, signatories, and roles * 2. DATES: Extract effective date, expiration, renewal dates * 3. PAYMENT: Summarize amounts, payment terms, billing cycles * 4. LIABILITY: Identify indemnification and liability caps * 5. TERMINATION: Note termination conditions and notice periods` * ``` */ content: string; }>; /** * Tool execution approval policies for security and user control. * * Controls which tools can execute automatically and which require user approval. * Use this to implement security policies, prevent unintended modifications, or * require confirmation for sensitive operations. * * **Resolution order** (first match wins): * 1. Pattern-based rules (if defined) * 2. Tool category defaults (read/write based on tool metadata) * 3. Fallback default setting * * @example * ```typescript * // Basic: Allow reads, ask for writes * toolApproval: { * defaults: { * default: 'allow', * read: 'allow', * write: 'ask' * } * } * ``` * * @example * ```typescript * // Advanced: Pattern-based rules with defaults * toolApproval: { * defaults: { default: 'allow' }, * rules: [ * { pattern: '*_delete_*', approval: 'deny' }, * { pattern: 'mcp__*_modify_*', approval: 'ask' } * ] * } * ``` */ toolApproval?: { /** * Default approval settings for tools by category. * * These defaults apply when no rule matches. The resolution order is: * 1. Check if a pattern rule matches (first match wins) * 2. Check tool's readOnlyHint - use 'read' or 'write' setting * 3. Fall back to 'default' setting */ defaults: { /** * Fallback approval mode for all tools not matching a rule or category. * * Used when: * - No pattern rule matches * - Tool has no readOnlyHint annotation * - No category-specific default is configured * * Values: * - `"allow"`: Executes immediately without user intervention * - `"ask"`: Pauses execution and requests user confirmation * - `"deny"`: Rejects the tool call */ default: 'allow' | 'ask' | 'deny'; /** * Approval mode for read-only tools. * * Applies to tools marked with `readOnlyHint: true`. * Typically used for safe operations like searching, analyzing, or retrieving data. * * Values: * - `"allow"`: Executes immediately without user intervention * - `"ask"`: Pauses execution and requests user confirmation * - `"deny"`: Rejects the tool call */ read?: 'allow' | 'ask' | 'deny'; /** * Approval mode for write/modification tools. * * Applies to tools marked with `readOnlyHint: false` that modify documents or state. * Recommended to set to 'ask' for user control over document changes. * * Values: * - `"allow"`: Executes immediately without user intervention * - `"ask"`: Pauses execution and requests user confirmation * - `"deny"`: Rejects the tool call */ write?: 'allow' | 'ask' | 'deny'; }; /** * Pattern-based rules for fine-grained tool control. * * Rules are evaluated in order - the first matching pattern determines the approval mode. * Place more specific patterns before general ones. * * Patterns use standard glob syntax where `*` matches any characters. */ rules?: Array<{ /** * Glob pattern to match against tool names. * * Tool names follow the format: `[namespace]__[server]__[function_name]` * * Common patterns: * - `"mcp__nutrient_*"`: All Nutrient MCP tools * - `"mcp__nutrient-ai-assistant__find_document"`: Specific tool * - `"mcp__nutrient-web-sdk__read_annotations"`: Web SDK tool * - `"mcp__*"`: All MCP tools from any server * - `"mcp__*__*_delete_*"`: Any MCP tool with delete in the name * * @example * ```typescript * pattern: "mcp__nutrient-websdk__add_annotation" * ``` */ pattern: string; /** * Approval mode for tools matching this pattern. * * Values: * - `"allow"`: Executes immediately without user intervention * - `"ask"`: Pauses execution and requests user confirmation * - `"deny"`: Rejects the tool call (will not execute) */ approval: 'allow' | 'ask' | 'deny'; }>; }; } } declare function AIAssistantMixin<T extends Class<BaseMixin>>(Base: T): { new (...args: any[]): { }; } & T; /** * Data structure for AI comparison results */ export declare interface AIComparisonData { /** AI-generated summary of document changes */ summary: string; /** Array of AI-detected change categories */ categories: string[]; /** Standard document comparison result */ changes: DocumentComparison.DocumentComparisonResult; /** Current phase of the AI comparison process */ phase: IAIComparisonPhase; /** Error information if comparison failed */ error: AIComparisonError | null; /** Changes tagged with categories (optional) */ taggedChanges?: AIADocumentChangeTaggingItem[]; /** Transformed changes for AI processing (optional) */ transformedChanges?: AIADocumentChangePayload[]; /** Enhanced changes with AI properties (optional) */ aiEnhancedChanges?: List<AIEnhancedTextComparisonChange>; } /** * Error information for AI comparison */ export declare interface AIComparisonError { /** The phase where the error occurred ('ANALYSIS' | 'TAGGING') */ phase: 'ANALYSIS' | 'TAGGING'; /** Human-readable error message */ message: string; /** Additional error details (optional) */ details?: unknown; } /** * Describes types of AI operations for document comparison. * These operations can be used with `ComparisonOperationType.AI`. * * @enum */ declare const AIComparisonOperationType: { /** Analyze and summarize differences between documents. */ readonly ANALYZE: "analyze"; /** Tag changes with specified categories. */ readonly TAG: "tag"; }; /** * Phases of the AI comparison process */ declare enum AIComparisonPhase { /** Initial state before comparison starts */ IDLE = "IDLE", /** Loading documents or initializing */ LOADING = "LOADING", /** AI is analyzing document differences */ ANALYZING = "ANALYZING", /** AI is tagging changes with categories */ TAGGING = "TAGGING", /** Comparison process completed successfully */ COMPLETED = "COMPLETED", /** Error occurred during comparison */ ERROR = "ERROR", } /** * Result returned by AI-powered document comparison operations. This union type represents * the response from {@link NutrientViewer.Instance#compareDocuments} when using * {@link NutrientViewer.ComparisonOperationType}.AI. * * The result type depends on the AI operation performed: * * - **Analysis Operation** (`NutrientViewer.AIComparisonOperationType.ANALYZE`): * Returns {@link AIADocumentChangesAnalysisResponse} containing: * - `summary`: AI-generated summary describing the overall nature of changes * - `categories`: Array of AI-detected change types (e.g., "Formatting", "Content Addition") * - `changes`: Standard {@link DocumentComparison.DocumentComparisonResult} with detailed differences * * - **Tagging Operation** (`NutrientViewer.AIComparisonOperationType.TAG`): * Returns {@link AIADocumentChangesTaggingResponse} containing: * - `references`: Array where each item corresponds to a change with assigned category tags * - `changes`: Standard {@link DocumentComparison.DocumentComparisonResult} with detailed differences * * Use the provided type guards to determine which specific result type you received: * - {@link NutrientViewer.isAIDocumentAnalysisResult} - Check for analysis results * - {@link NutrientViewer.isAIDocumentTaggingResult} - Check for tagging results * - {@link NutrientViewer.isAIDocumentComparisonResult} - Check for any AI result * * @example * const analyzeOperation = new NutrientViewer.ComparisonOperation( * NutrientViewer.ComparisonOperationType.AI, * { operationType: NutrientViewer.AIComparisonOperationType.ANALYZE } * ); * * instance.compareDocuments(documents, analyzeOperation) * .then((result) => { * if (NutrientViewer.isAIDocumentAnalysisResult(result)) { * console.log('Summary:', result.summary); * console.log('Categories:', result.categories); * } * }); * * @see {@link NutrientViewer.Instance#compareDocuments} * @see {@link NutrientViewer.AIComparisonOperationType} * @see {@link AIADocumentChangesAnalysisResponse} * @see {@link AIADocumentChangesTaggingResponse} * @see {@link NutrientViewer.isAIDocumentAnalysisResult} * @see {@link NutrientViewer.isAIDocumentTaggingResult} */ export declare type AIDocumentComparisonResult = AIADocumentChangesAnalysisResponse | AIADocumentChangesTaggingResponse; /** * Enhanced TextComparisonChange with AI-related properties * * @inline */ declare interface AIEnhancedTextComparisonChange extends TextComparisonChange { aiId?: string; categories?: string[]; aiProcessed?: boolean; } /** * Specifies the alignment of an UI element relative to its parent container. * * @enum */ declare const Alignment: { /** Aligns the element to the start of the container (left in LTR, right in RTL layout). */ readonly START: "START"; /** Aligns the element to the end of the container (right in LTR, left in RTL layout). */ readonly END: "END"; }; declare const allowedTextComparisonInnerToolbarItem: string[]; declare const allowedTextComparisonToolbarItem: string[]; declare const allowedToolbarTypes: ((typeof extraToolbarTypes)[number] | (typeof defaultToolbarTypes)[number])[]; /** * @class * Base annotation type from which all annotations inherit. You can not instantiate from this type. * * It is an {@link https://immutable-js.com/docs/v5/Record/ | Immutable.Record}. * @public * @summary Base annotation type from which all annotations inherit. * @hideconstructor * @abstract * @see {@link NutrientViewer.Instance#getSelectedAnnotations} | {@link NutrientViewer.Instance#setSelectedAnnotations} * @see {@link NutrientViewer.Instance#setEditableAnnotationTypes} | {@link NutrientViewer.Instance#setIsEditableAnnotation} * @see {@link NutrientViewer.Instance#create} | {@link NutrientViewer.Instance#delete} * @see {@link NutrientViewer.Instance#getAnnotations} | {@link NutrientViewer.Instance#ensureChangesSaved} * @see {@link NutrientViewer.Instance#hasUnsavedChanges} | {@link NutrientViewer.Instance#save} * @see {@link NutrientViewer.Instance#setAnnotationCreatorName} | {@link NutrientViewer.Instance#update} * @see {@link Configuration#editableAnnotationTypes} | {@link Configuration#isEditableAnnotation} * @see {@link NutrientViewer.EventName.ANNOTATIONS_LOAD} | {@link NutrientViewer.EventName.ANNOTATIONS_CHANGE} * @see {@link NutrientViewer.EventName.ANNOTATIONS_CREATE} | {@link NutrientViewer.EventName.ANNOTATIONS_UPDATE} * @see {@link NutrientViewer.EventName.ANNOTATIONS_DELETE} | {@link NutrientViewer.EventName.ANNOTATIONS_PRESS} * @see {@link NutrientViewer.EventName.ANNOTATIONS_WILL_SAVE} | {@link NutrientViewer.EventName.ANNOTATIONS_DID_SAVE} * @see {@link NutrientViewer.EventName.ANNOTATIONS_FOCUS} | {@link NutrientViewer.EventName.ANNOTATIONS_BLUR} * @see {@link NutrientViewer.EventName.ANNOTATIONS_WILL_CHANGE} | {@link NutrientViewer.EventName.ANNOTATION_SELECTION_CHANGE} */ export declare class Annotation<T extends AnnotationProperties = AnnotationProperties> extends InheritableImmutableRecord<T> { /** * A unique identifier to describe the annotation. When an annotation is created in the UI, the * viewer has to generate a unique ID. * * When changes are saved to the underlying annotation provider, we call * {@link Instance#ensureChangesSaved} to make sure the annotation has been persisted * from the provider. */ id: ID; /** * An optional field that may be used to identify the annotation. * * By default, we'll set that to the same value as the automatically generated * {@link Annotation#id}. */ name: null | string; /** * An optional annotation subject, representing a short description of * the subject being addressed by the annotation. This property has no effect * on the annotation rendering. */ subject: null | string; /** * When the annotation is extracted directly from a PDF file, the `pdfObjectId` refers to the * identifier that was used in the PDF document. * * This ID is optional since newly created annotations using the SYNCProvider annotation provider * won't have a `pdfObjectId` assigned. * * @default null */ pdfObjectId: null | number; /** * The page index on which the annotation is placed. It's important to notice that an annotation * can only ever be on one page. If you create for example an ink annotation with lines on two * pages, two annotation records will be created. * * `pageIndex` is zero-based and has a maximum value of `totalPageCount - 1`. */ pageIndex: number; /** * Position of this annotation on the page. It's necessary that this spans all visible points of * the annotation, otherwise hit testing and other features may not work. */ boundingBox: Rect; /** * A transparency value that is applied to the complete annotation. The value is capped between 0 * and 1 inclusive. * * @default 1 */ opacity: number; /** * An optional note that can be set on any annotation. * * This value is displayed in the Nutrient Web SDK UI for all annotations except * {@link NutrientViewer.Annotations.NoteAnnotation | NoteAnnotation}, {@link NutrientViewer.Annotations.TextAnnotation | TextAnnotation}, {@link NutrientViewer.Annotations.WidgetAnnotation | WidgetAnnotation} and {@link NutrientViewer.Annotations.CommentMarkerAnnotation | CommentMarkerAnnotation}. */ note: null | string; /** * The name of the creator of the annotation. This is a general purpose string which can easily be * spoofed and might not reflect the actual creator of the annotation. */ creatorName: null | string; /** * The date of the annotation creation. */ createdAt: Date; /** * The date of last annotation update. */ updatedAt: Date; /** * The annotation flag that prevents the annotation from being rendered in the UI. * * The annotation may still be part of the printed page, depending of the value of the * {@link Annotations.Annotation#noPrint} flag. * * @default false */ noView: boolean; /** * The annotation flag that prevents the annotation from being printed. * * @default false */ noPrint: boolean; /** * The annotation flag that prevents the annotation from being modified. * * @default false */ locked: boolean; /** * The annotation flag that prevents the annotation content from being modified. * * @default false */ lockedContents: boolean; /** * The annotation flag that makes the annotation read only. * * @default false */ readOnly: boolean; /** * If set, do not display or print the annotation or allow it to interact with the user. * * @default false */ hidden: boolean; /** * Annotations can store additional user-specified data. * * NutrientViewer will not use or evaluate `customData` in the UI directly. * You have full control over this property. For new annotations, this defaults to null. * * customData will be stored as JSON through `JSON.serialize()` and `JSON.parse()`, and * so must be a plain JSON-serializable object. * * @example * Adding a new {@link EllipseAnnotation} with custom data attached: * ```ts * const annotation = new NutrientViewer.Annotations.EllipseAnnotation({ * pageIndex: 0, * boundingBox: new NutrientViewer.Geometry.Rect({ * top: 10, * left: 10, * width: 100, * height: 100 * }), * customData: { * circleId: "my-circle" * } * }); * ``` */ customData: null | Record<string, unknown>; noZoom: boolean; noRotate: boolean; additionalActions: AnnotationAdditionalActionsType | null; rotation: number; /** * The blend mode defines how the color of the annotation will be applied to its background. * * @default "normal" */ blendMode: IBlendMode; isCommentThreadRoot: boolean; isAnonymous: boolean; /** * This property is used to define the permission scope for this annotation. * * It is only available when collaboration permissions is enabled on Server-Backed deployments. */ group?: string | null; /** * This property defines whether this annotation can be edited or not. * The value of this field depends on the set of collaboration permissions defined in the JWT token. * * It is only available when collaboration permissions is enabled on Server-Backed deployments. */ readonly isEditable?: boolean; /** * This property defines whether this annotation can be deleted or not. * The value of this field depends on the set of collaboration permissions defined in the JWT token. * * It is only available when collaboration permissions is enabled on Server-Backed deployments. */ readonly isDeletable?: boolean; /** * This property defines whether the user has permission to edit the group of this annotation. * * It is only available when collaboration permissions is enabled on Server-Backed deployments. */ readonly canSetGroup?: boolean; canReply?: boolean; APStreamCache?: { cache: string; } | { attach: string; }; action: Action | null; constructor(options?: Partial<T>); } declare namespace Annotation_2 { export { Annotation, HighlightAnnotation, ImageAnnotation, InkAnnotation, ShapeAnnotation, LineAnnotation, RectangleAnnotation, EllipseAnnotation, PolygonAnnotation, PolylineAnnotation, LinkAnnotation, NoteAnnotation, SquiggleAnnotation, StampAnnotation, StrikeOutAnnotation, TextAnnotation, TextMarkupAnnotation, UnderlineAnnotation, UnknownAnnotation, WidgetAnnotation, CommentMarkerAnnotation, RedactionAnnotation, MediaAnnotation }; } /** @inline */ declare type AnnotationAdditionalActionsType = { onPointerEnter?: Action; onPointerLeave?: Action; onPointerDown?: Action; onPointerUp?: Action; onPageOpen?: Action; onPageClose?: Action; onPageVisible?: Action; onPageHidden?: Action; }; /** @inline */ declare type AnnotationBackendJSON<K extends BaseAnnotationJSON = Serializers.AnnotationJSONUnion, R extends string = never> = { [P in keyof K]?: NonNullable<K[P]> } & { [P in Intersection<keyof K, BackendRequiredKeys | R>]-?: Exclude<NonNullable<K[P]>, undefined> }; declare type AnnotationJSONToAnnotation<T extends { type: keyof AnnotationSerializerTypeMap; }> = AnnotationSerializerTypeMap[GetTypeFromAnnotationJSON<T>]['annotation']; /** * @deprecated Use {@link Serializers.AnnotationJSONUnion} instead. * @hidden */ export declare type AnnotationJSONUnion = Serializers.AnnotationJSONUnion; /** * @class * * Represents an annotation note. Used as a note annotation when hovering over note icon or when * the note icon is selected. This annotation is not persisted in the document nor returned by the public API. */ declare class AnnotationNote extends NoteAnnotation<AnnotationNoteProps> { /** * Root annotation this note belongs to. */ parentAnnotation?: AnnotationsUnion; /** * Calculated position of this note on the page in PDF coordinates. */ position: Point; notePosition?: Point; } /** @inline */ declare interface AnnotationNoteProps extends INoteAnnotation { parentAnnotation: AnnotationsUnion | null; position: Point; notePosition?: Point; } declare function AnnotationPermissionMixin<T extends Class<BaseMixin>>(Base: T): { new (...args: any[]): { /** * Returns a deep copy of the latest editableAnnotationTypes. This value changes whenever * {@link Instance.setEditableAnnotationTypes} is called. * * Mutating this object will have no effect. * * @public */ readonly editableAnnotationTypes: Set_2<Class<AnnotationsUnion>>; /** * This method is used to update the editable annotation types. * * When one of the supplied {@link NutrientViewer.Annotations.Annotation} is invalid, this method will throw an * {@link Error} that contains a detailed error message. * * @example * ```ts * // Only allow editing ink annotations * instance.setEditableAnnotationTypes([NutrientViewer.Annotations.InkAnnotation]); * instance.editableAnnotationTypes === [NutrientViewer.Annotations.InkAnnotation]; // => true * ``` * * @public * @throws {Error} Will throw an error when the supplied array is not valid. */ setEditableAnnotationTypes(editableAnnotationTypes: Class<AnnotationsUnion>[]): void; /** * This method is used to update the isEditableAnnotation callback * * When the supplied callback is invalid it will throw a {@link Error} that contains a * detailed error message. * * @example * Only allow editing annotations from a specific creator name * ```ts * instance.setIsEditableAnnotation((annotation) => annotation.creatorName === "Alice"); * ``` * * @public * @throws {Error} Will throw an error when the supplied array is not valid. */ setIsEditableAnnotation(isEditableAnnotationCallback: IsEditableAnnotationCallback): void; }; } & T; /** * Describes and persists the properties of an annotation preset. * * Annotation presets are sets of property-value pairs for annotations that can be applied as default * annotations settings for toolbar items. When an annotation toolbar setting is changed by the user, * the annotation preset associated with the toolbar item that triggered the annotation toolbar is updated. * If the associated annotation preset doesn't exist, it's created with the settings that have changed. * * For properties not included in an annotation preset, the default values used when creating * an annotation are those of the annotation type. * * @example * Creating an annotation preset and adding it to the available annotation presets. * ```ts * const myAnnotationPresets = instance.annotationPresets * myAnnotationPresets['my-annotation-preset'] = { * strokeWidth: 2, * } * instance.setAnnotationPresets(myAnnotationPresets); * ``` * * @summary Annotation preset properties. * @see {@link Configuration#annotationPresets} * @see {@link Instance#setAnnotationPresets} * @see {@link Events.AnnotationPresetsUpdateEvent} */ export declare type AnnotationPreset = Record<string, unknown>; declare type AnnotationPreset_2 = AnnotationPreset; /** * This callback can be used in the {@link NutrientViewer.Instance#setAnnotationPresets | setAnnotationPresets()} * method to do atomic updates to the current annotation presets. * * @example * Use ES2015 arrow functions and the update callback to reduce boilerplate * ```ts * instance.setAnnotationPresets(presets => { * presets.custom = { * strokeWidth: 10, * }; * return presets; * }); * ``` * * @param currentAnnotationPresets - The current annotation presets * @returns The new annotation presets */ export declare type AnnotationPresetCallback = (currentAnnotationPresets: Record<AnnotationPresetID, AnnotationPreset>) => Record<AnnotationPresetID, AnnotationPreset>; /** @inline */ declare type AnnotationPresetID = string; declare type AnnotationPresetID_2 = AnnotationPresetID; export declare namespace AnnotationPresets { export { serializePreset as toSerializableObject, unserializePreset as fromSerializableObject }; } declare function AnnotationPresetsMixin<T extends Class<BaseMixin>>(Base: T): { new (...args: any[]): { /** * Returns a deep copy of the latest annotation presets. This value changes whenever the user * interacts with NutrientViewer or whenever {@link Instance.setAnnotationPresets} is called. * * Mutating this object will have no effect. */ readonly annotationPresets: { [key: string]: AnnotationPreset; }; /** * Get the current active annotation preset ID */ readonly currentAnnotationPreset: string | null | undefined; /** * This method is used to update the annotation presets. * * It makes it possible to add new {@link AnnotationPreset | annotation presets} and edit or remove existing ones. * * When you pass in an `object` with keyed {@link AnnotationPreset}, the current annotation presets * will be immediately updated. Calling this method is also idempotent. * * If you pass in a function, it will be immediately invoked and will receive the current annotation presets as argument. You can use this to modify the object based on its * current value. This type of update is guaranteed to be atomic - the value of `currentAnnotationPresets` can't change in between. See: {@link AnnotationPresetCallback} * * When one of the supplied {@link AnnotationPreset} is invalid, this method will throw an {@link Error} that contains a detailed error message. * * Since `annotationPresets` is a regular JavaScript `object`, it can be manipulated using standard `Object` * methods. * * @example * The new changes will be applied immediately * ```ts * instance.setAnnotationPresets(newAnnotationPresets); * instance.annotationPresets === newAnnotationPresets; // => true * ``` * * @example * Adding an annotation preset for an ellipse annotation variant. * ```ts * const myAnnotationPreset = { * dashedEllipse: { * strokeDashArray: [3, 3], * } * } * instance.setAnnotationPresets(annotationPresets => ({ ...annotationPresets, myAnnotationPreset })) * ``` * * @throws {Error} Will throw an error when the supplied annotation preset `object` is not valid. * @param stateOrFunction - Either a * new AnnotationPresets `object` which would overwrite the existing one, or a callback that will get * invoked with the current annotation presets and is expected to return the new annotation presets `object`. */ setAnnotationPresets(stateOrFunction: Record<AnnotationPresetID, AnnotationPreset> | AnnotationPresetCallback): void; /** * This method is used to set the current active annotation preset. * * It makes it possible to specify what annotation preset should be used when new annotations * are created in the UI by passing the annotation preset key string as argument. * * The current annotation preset is set when the toolbar annotation buttons are used to create * annotations. This method allows to set the current annotation preset programmatically, as well * as resetting it by passing `null` as argument. * * When the supplied key does not correspond with an existing {@link AnnotationPreset}, * this method will throw an {@link Error} that contains a detailed error message. * * @example * The new changes will be applied immediately * ```ts * instance.setCurrentAnnotationPreset("ink"); * instance.currentAnnotationPreset === "ink"; // => true * ``` * * @example * Setting an annotation preset for a closed arrow line annotation. * ```ts * instance.setAnnotationPresets(annotationPresets => { * return { * ...annotationPresets, * line: { * ...annotationPresets.line, * lineCaps: { * end: "closedArrow" * } * } * } * }); * instance.setCurrentAnnotationPreset("line"); * instance.setViewState(viewState => * viewState.set("interactionMode", NutrientViewer.InteractionMode.SHAPE_LINE), * ); * ``` * * @public * @param annotationPresetID - Annotation preset name. * @throws {Error} Will throw an error when the supplied annotation preset key does not exist. */ setCurrentAnnotationPreset(annotationPresetID?: string | null): void; }; } & T; /** @inline */ declare type AnnotationProperties = { id: string | null; name: string | null; subject: string | null; pdfObjectId: number | null; pageIndex: number | null; boundingBox: Rect | null; opacity: number | null; note: string | null; creatorName: string | null; createdAt: Date | null; updatedAt: Date | null; customData: Record<string, unknown> | null; noView: boolean | null; noPrint: boolean | null; locked: boolean | null; lockedContents: boolean | null; readOnly: boolean | null; hidden: boolean | null; group: string | null | undefined; isEditable: boolean | undefined; isDeletable: boolean | undefined; canSetGroup: boolean | undefined; canReply: boolean | undefined; rotation: number; additionalActions: AnnotationAdditionalActionsType | null; noZoom: boolean; noRotate: boolean; isCommentThreadRoot: boolean; isAnonymous: boolean; APStreamCache: { cache: string; } | { attach: string; } | undefined; blendMode: IBlendMode; action: Action | null; [key: string]: unknown; }; declare type AnnotationReference = { fieldName: string; } | { pdfObjectId: number; }; /** * A comparator function that defines a strict total order for annotation rendering.