@embedpdf/plugin-annotation 1.0.6 → 1.0.7

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/lib/manifest.ts","../src/lib/annotation-plugin.ts","../../models/src/geometry.ts","../../models/src/logger.ts","../../models/src/task.ts","../../models/src/pdf.ts","../../models/src/index.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["export * from './lib';\n","import { PluginManifest } from '@embedpdf/core';\nimport { AnnotationPluginConfig } from './types';\n\nexport const ANNOTATION_PLUGIN_ID = 'annotation';\n\nexport const manifest: PluginManifest<AnnotationPluginConfig> = {\n id: ANNOTATION_PLUGIN_ID,\n name: 'Annotation Plugin',\n version: '1.0.0',\n provides: ['annotation'],\n requires: [],\n optional: [],\n defaultConfig: {\n enabled: true,\n },\n};\n","import { BasePlugin, createBehaviorEmitter, PluginRegistry, SET_DOCUMENT } from '@embedpdf/core';\nimport {\n ignore,\n PdfAnnotationObject,\n PdfDocumentObject,\n PdfEngine,\n PdfErrorReason,\n Task,\n PdfAlphaColor,\n PdfAnnotationSubtype,\n} from '@embedpdf/models';\nimport {\n AnnotationCapability,\n AnnotationPluginConfig,\n AnnotationState,\n GetPageAnnotationsOptions,\n} from './types';\nimport {\n setAnnotations,\n selectAnnotation,\n deselectAnnotation,\n setAnnotationMode,\n updateAnnotationColor,\n AnnotationAction,\n} from './actions';\n\nexport class AnnotationPlugin extends BasePlugin<\n AnnotationPluginConfig,\n AnnotationCapability,\n AnnotationState,\n AnnotationAction\n> {\n static readonly id = 'annotation' as const;\n\n private engine: PdfEngine;\n private readonly state$ = createBehaviorEmitter<AnnotationState>();\n\n constructor(id: string, registry: PluginRegistry, engine: PdfEngine) {\n super(id, registry);\n this.engine = engine;\n\n this.coreStore.onAction(SET_DOCUMENT, (_action, state) => {\n const doc = state.core.document;\n if (doc) {\n this.getAllAnnotations(doc);\n }\n });\n }\n\n async initialize(): Promise<void> {}\n\n protected buildCapability(): AnnotationCapability {\n return {\n getPageAnnotations: (options: GetPageAnnotationsOptions) => {\n return this.getPageAnnotations(options);\n },\n selectAnnotation: (pageIndex: number, annotationId: number) => {\n this.selectAnnotation(pageIndex, annotationId);\n },\n deselectAnnotation: () => {\n this.dispatch(deselectAnnotation());\n },\n updateAnnotationColor: async (color: PdfAlphaColor) => {\n return this.updateSelectedAnnotationColor(color);\n },\n setAnnotationMode: (mode: PdfAnnotationSubtype | null) => {\n this.dispatch(setAnnotationMode(mode));\n },\n onStateChange: this.state$.on,\n };\n }\n\n override onStoreUpdated(_prevState: AnnotationState, newState: AnnotationState): void {\n this.state$.emit(newState);\n }\n\n private getAllAnnotations(doc: PdfDocumentObject) {\n const task = this.engine.getAllAnnotations(doc);\n task.wait((annotations) => this.dispatch(setAnnotations(annotations)), ignore);\n }\n\n private getPageAnnotations(\n options: GetPageAnnotationsOptions,\n ): Task<PdfAnnotationObject[], PdfErrorReason> {\n const { pageIndex } = options;\n\n const doc = this.coreState.core.document;\n\n if (!doc) {\n throw new Error('document does not open');\n }\n\n const page = doc.pages.find((p) => p.index === pageIndex);\n\n if (!page) {\n throw new Error('page does not open');\n }\n\n return this.engine.getPageAnnotations(doc, page);\n }\n\n private selectAnnotation(pageIndex: number, annotationId: number) {\n const pageAnnotations = this.state.annotations[pageIndex];\n\n if (!pageAnnotations) {\n return;\n }\n\n const annotation = pageAnnotations.find((a) => a.id === annotationId);\n\n if (annotation) {\n this.dispatch(selectAnnotation(pageIndex, annotationId, annotation));\n }\n }\n\n private async updateSelectedAnnotationColor(color: PdfAlphaColor): Promise<boolean> {\n const selected = this.state.selectedAnnotation;\n\n if (!selected) {\n return false;\n }\n\n // Only allow color updates for highlight annotations\n if (selected.annotation.type !== PdfAnnotationSubtype.HIGHLIGHT) {\n return false;\n }\n\n const doc = this.coreState.core.document;\n if (!doc) {\n return false;\n }\n\n // Update the annotation in the local state first\n this.dispatch(updateAnnotationColor(selected.pageIndex, selected.annotationId, color));\n\n try {\n // Here you would update the annotation in the PDF engine\n // This depends on your PDF engine's capabilities\n // For now, we'll just return true to indicate success\n\n // Example of what this might look like:\n // const page = doc.pages[selected.pageIndex];\n // const updatedAnnotation = { ...selected.annotation, color };\n // await this.engine.updatePageAnnotation(doc, page, updatedAnnotation);\n\n return true;\n } catch (error) {\n console.error('Failed to update annotation color:', error);\n return false;\n }\n }\n}\n","/**\n * Clockwise direction\n * @public\n */\nexport enum Rotation {\n Degree0 = 0,\n Degree90 = 1,\n Degree180 = 2,\n Degree270 = 3,\n}\n\n/** Clamp a Position to device-pixel integers (floor) */\nexport function toIntPos(p: Position): Position {\n return { x: Math.floor(p.x), y: Math.floor(p.y) };\n}\n\n/** Clamp a Size so it never truncates right / bottom (ceil) */\nexport function toIntSize(s: Size): Size {\n return { width: Math.ceil(s.width), height: Math.ceil(s.height) };\n}\n\n/** Apply both rules to a Rect */\nexport function toIntRect(r: Rect): Rect {\n return {\n origin: toIntPos(r.origin),\n size: toIntSize(r.size),\n };\n}\n\n/**\n * Calculate degree that match the rotation type\n * @param rotation - type of rotation\n * @returns rotated degree\n *\n * @public\n */\nexport function calculateDegree(rotation: Rotation) {\n switch (rotation) {\n case Rotation.Degree0:\n return 0;\n case Rotation.Degree90:\n return 90;\n case Rotation.Degree180:\n return 180;\n case Rotation.Degree270:\n return 270;\n }\n}\n\n/**\n * Calculate angle that match the rotation type\n * @param rotation - type of rotation\n * @returns rotated angle\n *\n * @public\n */\nexport function calculateAngle(rotation: Rotation) {\n return (calculateDegree(rotation) * Math.PI) / 180;\n}\n\n/**\n * Represent the size of object\n *\n * @public\n */\nexport interface Size {\n /**\n * width of the object\n */\n width: number;\n\n /**\n * height of the object\n */\n height: number;\n}\n\n/**\n * Represents a rectangle defined by its left, top, right, and bottom edges\n *\n * @public\n */\nexport interface Box {\n /**\n * The x-coordinate of the left edge\n */\n left: number;\n\n /**\n * The y-coordinate of the top edge\n */\n top: number;\n\n /**\n * The x-coordinate of the right edge\n */\n right: number;\n\n /**\n * The y-coordinate of the bottom edge\n */\n bottom: number;\n}\n\n/**\n * Swap the width and height of the size object\n * @param size - the original size\n * @returns swapped size\n *\n * @public\n */\nexport function swap(size: Size): Size {\n const { width, height } = size;\n\n return {\n width: height,\n height: width,\n };\n}\n\n/**\n * Transform size with specified rotation angle and scale factor\n * @param size - orignal size of rect\n * @param rotation - rotation angle\n * @param scaleFactor - - scale factor\n * @returns size that has been transformed\n *\n * @public\n */\nexport function transformSize(size: Size, rotation: Rotation, scaleFactor: number): Size {\n size = rotation % 2 === 0 ? size : swap(size);\n\n return {\n width: size.width * scaleFactor,\n height: size.height * scaleFactor,\n };\n}\n\n/**\n * position of point\n *\n * @public\n */\nexport interface Position {\n /**\n * x coordinate\n */\n x: number;\n\n /**\n * y coordinate\n */\n y: number;\n}\n\n/**\n * Quadrilateral\n *\n * @public\n */\nexport interface Quad {\n p1: Position;\n p2: Position;\n p3: Position;\n p4: Position;\n}\n\n/**\n * Convert quadrilateral to rectangle\n * @param q - quadrilateral\n * @returns rectangle\n *\n * @public\n */\nexport function quadToRect(q: Quad): Rect {\n const xs = [q.p1.x, q.p2.x, q.p3.x, q.p4.x];\n const ys = [q.p1.y, q.p2.y, q.p3.y, q.p4.y];\n\n return {\n origin: { x: Math.min(...xs), y: Math.min(...ys) },\n size: {\n width: Math.max(...xs) - Math.min(...xs),\n height: Math.max(...ys) - Math.min(...ys),\n },\n };\n}\n\n/**\n * Rotate the container and calculate the new position for a point\n * in specified position\n * @param containerSize - size of the container\n * @param position - position of the point\n * @param rotation - rotated angle\n * @returns new position of the point\n *\n * @public\n */\nexport function rotatePosition(\n containerSize: Size,\n position: Position,\n rotation: Rotation,\n): Position {\n let x = position.x;\n let y = position.y;\n\n switch (rotation) {\n case Rotation.Degree0:\n x = position.x;\n y = position.y;\n break;\n case Rotation.Degree90:\n x = containerSize.height - position.y;\n y = position.x;\n break;\n case Rotation.Degree180:\n x = containerSize.width - position.x;\n y = containerSize.height - position.y;\n break;\n case Rotation.Degree270:\n x = position.y;\n y = containerSize.width - position.x;\n break;\n }\n\n return {\n x,\n y,\n };\n}\n\n/**\n * Calculate the position of point by scaling the container\n * @param position - position of the point\n * @param scaleFactor - factor of scaling\n * @returns new position of point\n *\n * @public\n */\nexport function scalePosition(position: Position, scaleFactor: number): Position {\n return {\n x: position.x * scaleFactor,\n y: position.y * scaleFactor,\n };\n}\n\n/**\n * Calculate the position of the point by applying the specified transformation\n * @param containerSize - size of container\n * @param position - position of the point\n * @param rotation - rotated angle\n * @param scaleFactor - factor of scaling\n * @returns new position of point\n *\n * @public\n */\nexport function transformPosition(\n containerSize: Size,\n position: Position,\n rotation: Rotation,\n scaleFactor: number,\n): Position {\n return scalePosition(rotatePosition(containerSize, position, rotation), scaleFactor);\n}\n\n/**\n * Restore the position in a transformed cotainer\n * @param containerSize - size of the container\n * @param position - position of the point\n * @param rotation - rotated angle\n * @param scaleFactor - factor of scaling\n * @returns the original position of the point\n *\n * @public\n */\nexport function restorePosition(\n containerSize: Size,\n position: Position,\n rotation: Rotation,\n scaleFactor: number,\n): Position {\n return scalePosition(\n rotatePosition(containerSize, position, (4 - rotation) % 4),\n 1 / scaleFactor,\n );\n}\n\n/**\n * representation of rectangle\n *\n * @public\n */\nexport interface Rect {\n /**\n * origin of the rectangle\n */\n origin: Position;\n\n /**\n * size of the rectangle\n */\n size: Size;\n}\n\n/**\n * Calculate the rect after rotated the container\n * @param containerSize - size of container\n * @param rect - target rect\n * @param rotation - rotation angle\n * @returns rotated rect\n *\n * @public\n */\nexport function rotateRect(containerSize: Size, rect: Rect, rotation: Rotation): Rect {\n let x = rect.origin.x;\n let y = rect.origin.y;\n let size = rect.size;\n\n switch (rotation) {\n case Rotation.Degree0:\n break;\n case Rotation.Degree90:\n x = containerSize.height - rect.origin.y - rect.size.height;\n y = rect.origin.x;\n size = swap(rect.size);\n break;\n case Rotation.Degree180:\n x = containerSize.width - rect.origin.x - rect.size.width;\n y = containerSize.height - rect.origin.y - rect.size.height;\n break;\n case Rotation.Degree270:\n x = rect.origin.y;\n y = containerSize.width - rect.origin.x - rect.size.width;\n size = swap(rect.size);\n break;\n }\n\n return {\n origin: {\n x,\n y,\n },\n size: {\n width: size.width,\n height: size.height,\n },\n };\n}\n\n/**\n * Scale the rectangle\n * @param rect - rectangle\n * @param scaleFactor - factor of scaling\n * @returns new rectangle\n *\n * @public\n */\nexport function scaleRect(rect: Rect, scaleFactor: number): Rect {\n return {\n origin: {\n x: rect.origin.x * scaleFactor,\n y: rect.origin.y * scaleFactor,\n },\n size: {\n width: rect.size.width * scaleFactor,\n height: rect.size.height * scaleFactor,\n },\n };\n}\n\n/**\n * Calculate new rectangle after transforming the container\n * @param containerSize - size of the container\n * @param rect - the target rectangle\n * @param rotation - rotated angle\n * @param scaleFactor - factor of scaling\n * @returns new rectangle after transformation\n *\n * @public\n */\nexport function transformRect(\n containerSize: Size,\n rect: Rect,\n rotation: Rotation,\n scaleFactor: number,\n): Rect {\n return scaleRect(rotateRect(containerSize, rect, rotation), scaleFactor);\n}\n\n/**\n * Calculate new rectangle before transforming the container\n * @param containerSize - size of the container\n * @param rect - the target rectangle\n * @param rotation - rotated angle\n * @param scaleFactor - factor of scaling\n * @returns original rectangle before transformation\n *\n * @public\n */\nexport function restoreRect(\n containerSize: Size,\n rect: Rect,\n rotation: Rotation,\n scaleFactor: number,\n): Rect {\n return scaleRect(rotateRect(containerSize, rect, (4 - rotation) % 4), 1 / scaleFactor);\n}\n\n/**\n * Calculate the original offset in a transformed container\n * @param offset - position of the point\n * @param rotation - rotated angle\n * @param scaleFactor - factor of scaling\n * @returns original position of the point\n *\n * @public\n */\nexport function restoreOffset(offset: Position, rotation: Rotation, scaleFactor: number): Position {\n let offsetX = offset.x;\n let offsetY = offset.y;\n switch (rotation) {\n case Rotation.Degree0:\n offsetX = offset.x / scaleFactor;\n offsetY = offset.y / scaleFactor;\n break;\n case Rotation.Degree90:\n offsetX = offset.y / scaleFactor;\n offsetY = -offset.x / scaleFactor;\n break;\n case Rotation.Degree180:\n offsetX = -offset.x / scaleFactor;\n offsetY = -offset.y / scaleFactor;\n break;\n case Rotation.Degree270:\n offsetX = -offset.y / scaleFactor;\n offsetY = offset.x / scaleFactor;\n break;\n }\n\n return {\n x: offsetX,\n y: offsetY,\n };\n}\n\n/**\n * Return the smallest rectangle that encloses *all* `rects`.\n * If the array is empty, returns `null`.\n *\n * @param rects - array of rectangles\n * @returns smallest rectangle that encloses all the rectangles\n *\n * @public\n */\nexport function boundingRect(rects: Rect[]): Rect | null {\n if (rects.length === 0) return null;\n\n let minX = rects[0].origin.x,\n minY = rects[0].origin.y,\n maxX = rects[0].origin.x + rects[0].size.width,\n maxY = rects[0].origin.y + rects[0].size.height;\n\n for (const r of rects) {\n minX = Math.min(minX, r.origin.x);\n minY = Math.min(minY, r.origin.y);\n maxX = Math.max(maxX, r.origin.x + r.size.width);\n maxY = Math.max(maxY, r.origin.y + r.size.height);\n }\n\n return {\n origin: {\n x: minX,\n y: minY,\n },\n size: {\n width: maxX - minX,\n height: maxY - minY,\n },\n };\n}\n","/**\n * logger for logging\n *\n * @public\n */\nexport interface Logger {\n /**\n * Log debug message\n * @param source - source of log\n * @param category - category of log\n * @param args - parameters of log\n * @returns\n *\n * @public\n */\n debug: (source: string, category: string, ...args: any) => void;\n\n /**\n * Log infor message\n * @param source - source of log\n * @param category - category of log\n * @param args - parameters of log\n * @returns\n *\n * @public\n */\n info: (source: string, category: string, ...args: any) => void;\n\n /**\n * Log warning message\n * @param source - source of log\n * @param category - category of log\n * @param args - parameters of log\n * @returns\n *\n * @public\n */\n warn: (source: string, category: string, ...args: any) => void;\n /**\n * Log error message\n * @param source - source of log\n * @param category - category of log\n * @param args - parameters of log\n * @returns\n *\n * @public\n */\n error: (source: string, category: string, ...args: any) => void;\n\n /**\n * Log performance log\n * @param source - source of log\n * @param category - category of log\n * @param event - event of log\n * @param phase - event phase of log\n * @param args - parameters of log\n * @returns\n *\n * @public\n */\n perf: (\n source: string,\n category: string,\n event: string,\n phase: 'Begin' | 'End',\n ...args: any\n ) => void;\n}\n\n/**\n * Logger that log nothing, it will ignore all the logs\n *\n * @public\n */\nexport class NoopLogger implements Logger {\n /** {@inheritDoc Logger.debug} */\n debug() {}\n /** {@inheritDoc Logger.info} */\n info() {}\n /** {@inheritDoc Logger.warn} */\n warn() {}\n /** {@inheritDoc Logger.error} */\n error() {}\n /** {@inheritDoc Logger.perf} */\n perf() {}\n}\n\n/**\n * Logger that use console as the output\n *\n * @public\n */\nexport class ConsoleLogger implements Logger {\n /** {@inheritDoc Logger.debug} */\n debug(source: string, category: string, ...args: any) {\n console.debug(`${source}.${category}`, ...args);\n }\n\n /** {@inheritDoc Logger.info} */\n info(source: string, category: string, ...args: any) {\n console.info(`${source}.${category}`, ...args);\n }\n\n /** {@inheritDoc Logger.warn} */\n warn(source: string, category: string, ...args: any) {\n console.warn(`${source}.${category}`, ...args);\n }\n\n /** {@inheritDoc Logger.error} */\n error(source: string, category: string, ...args: any) {\n console.error(`${source}.${category}`, ...args);\n }\n\n /** {@inheritDoc Logger.perf} */\n perf(source: string, category: string, event: string, phase: 'Begin' | 'End', ...args: any) {\n console.info(`${source}.${category}.${event}.${phase}`, ...args);\n }\n}\n\n/**\n * Level of log\n *\n * @public\n */\nexport enum LogLevel {\n Debug = 0,\n Info,\n Warn,\n Error,\n}\n\n/**\n * Logger that support filtering by log level\n *\n * @public\n */\nexport class LevelLogger implements Logger {\n /**\n * create new LevelLogger\n * @param logger - the original logger\n * @param level - log level that used for filtering, all logs lower than this level will be filtered out\n */\n constructor(\n private logger: Logger,\n private level: LogLevel,\n ) {}\n\n /** {@inheritDoc Logger.debug} */\n debug(source: string, category: string, ...args: any) {\n if (this.level <= LogLevel.Debug) {\n this.logger.debug(source, category, ...args);\n }\n }\n\n /** {@inheritDoc Logger.info} */\n info(source: string, category: string, ...args: any) {\n if (this.level <= LogLevel.Info) {\n this.logger.info(source, category, ...args);\n }\n }\n\n /** {@inheritDoc Logger.warn} */\n warn(source: string, category: string, ...args: any) {\n if (this.level <= LogLevel.Warn) {\n this.logger.warn(source, category, ...args);\n }\n }\n\n /** {@inheritDoc Logger.error} */\n error(source: string, category: string, ...args: any) {\n if (this.level <= LogLevel.Error) {\n this.logger.error(source, category, ...args);\n }\n }\n\n /** {@inheritDoc Logger.perf} */\n perf(source: string, category: string, event: string, phase: 'Begin' | 'End', ...args: any) {\n this.logger.perf(source, category, event, phase, ...args);\n }\n}\n\n/**\n * Logger for performance tracking\n *\n * @public\n */\nexport class PerfLogger implements Logger {\n /**\n * create new PerfLogger\n */\n constructor() {}\n\n /** {@inheritDoc Logger.debug} */\n debug(source: string, category: string, ...args: any) {}\n\n /** {@inheritDoc Logger.info} */\n info(source: string, category: string, ...args: any) {}\n\n /** {@inheritDoc Logger.warn} */\n warn(source: string, category: string, ...args: any) {}\n\n /** {@inheritDoc Logger.error} */\n error(source: string, category: string, ...args: any) {}\n\n /** {@inheritDoc Logger.perf} */\n perf(\n source: string,\n category: string,\n event: string,\n phase: 'Begin' | 'End',\n identifier: string,\n ...args: any\n ) {\n switch (phase) {\n case 'Begin':\n window.performance.mark(`${source}.${category}.${event}.${phase}.${identifier}`, {\n detail: args,\n });\n break;\n case 'End':\n window.performance.mark(`${source}.${category}.${event}.${phase}.${identifier}`, {\n detail: args,\n });\n window.performance.measure(\n `${source}.${category}.${event}.Measure.${identifier}`,\n `${source}.${category}.${event}.Begin.${identifier}`,\n `${source}.${category}.${event}.End.${identifier}`,\n );\n break;\n }\n }\n}\n\n/**\n * Logger that will track and call child loggers\n *\n * @public\n */\nexport class AllLogger implements Logger {\n /**\n * create new PerfLogger\n */\n constructor(private loggers: Logger[]) {}\n\n /** {@inheritDoc Logger.debug} */\n debug(source: string, category: string, ...args: any) {\n for (const logger of this.loggers) {\n logger.debug(source, category, ...args);\n }\n }\n\n /** {@inheritDoc Logger.info} */\n info(source: string, category: string, ...args: any) {\n for (const logger of this.loggers) {\n logger.info(source, category, ...args);\n }\n }\n\n /** {@inheritDoc Logger.warn} */\n warn(source: string, category: string, ...args: any) {\n for (const logger of this.loggers) {\n logger.warn(source, category, ...args);\n }\n }\n\n /** {@inheritDoc Logger.error} */\n error(source: string, category: string, ...args: any) {\n for (const logger of this.loggers) {\n logger.error(source, category, ...args);\n }\n }\n\n /** {@inheritDoc Logger.perf} */\n perf(source: string, category: string, event: string, phase: 'Begin' | 'End', ...args: any) {\n for (const logger of this.loggers) {\n logger.perf(source, category, event, phase, ...args);\n }\n }\n}\n","/**\n * Stage of task\n *\n * @public\n */\nexport enum TaskStage {\n /**\n * Task is pending, means it just start executing\n */\n Pending = 0,\n /**\n * Task is succeed\n */\n Resolved = 1,\n /**\n * Task is failed\n */\n Rejected = 2,\n /**\n * Task is aborted\n */\n Aborted = 3,\n}\n\nexport interface TaskError<D> {\n /**\n * task error type\n */\n type: 'reject' | 'abort';\n /**\n * task error\n */\n reason: D;\n}\n\n/**\n * callback that will be called when task is resolved\n *\n * @public\n */\nexport type ResolvedCallback<R> = (r: R) => void;\n\n/**\n * callback that will be called when task is rejected\n *\n * @public\n */\nexport type RejectedCallback<D> = (e: TaskError<D>) => void;\n\n/**\n * Task state in different stage\n *\n * @public\n */\nexport type TaskState<R, D> =\n | {\n stage: TaskStage.Pending;\n }\n | {\n stage: TaskStage.Resolved;\n result: R;\n }\n | {\n stage: TaskStage.Rejected;\n reason: D;\n }\n | {\n stage: TaskStage.Aborted;\n reason: D;\n };\n\nexport class TaskAbortedError<D> extends Error {\n constructor(reason: D) {\n super(`Task aborted: ${JSON.stringify(reason)}`);\n this.name = 'TaskAbortedError';\n }\n}\n\nexport class TaskRejectedError<D> extends Error {\n constructor(reason: D) {\n super(`Task rejected: ${JSON.stringify(reason)}`);\n this.name = 'TaskRejectedError';\n }\n}\n\n/**\n * Base class of task\n *\n * @public\n */\nexport class Task<R, D> {\n state: TaskState<R, D> = {\n stage: TaskStage.Pending,\n };\n /**\n * callbacks that will be executed when task is resolved\n */\n resolvedCallbacks: ResolvedCallback<R>[] = [];\n /**\n * callbacks that will be executed when task is rejected\n */\n rejectedCallbacks: RejectedCallback<D>[] = [];\n\n /**\n * Promise that will be resolved when task is settled\n */\n private _promise: Promise<R> | null = null;\n\n /**\n * Convert task to promise\n * @returns promise that will be resolved when task is settled\n */\n toPromise(): Promise<R> {\n if (!this._promise) {\n this._promise = new Promise((resolve, reject) => {\n this.wait(\n (result) => resolve(result),\n (error) => {\n if (error.type === 'abort') {\n reject(new TaskAbortedError(error.reason));\n } else {\n reject(new TaskRejectedError(error.reason));\n }\n },\n );\n });\n }\n return this._promise;\n }\n\n /**\n * wait for task to be settled\n * @param resolvedCallback - callback for resolved value\n * @param rejectedCallback - callback for rejected value\n */\n wait(resolvedCallback: ResolvedCallback<R>, rejectedCallback: RejectedCallback<D>) {\n switch (this.state.stage) {\n case TaskStage.Pending:\n this.resolvedCallbacks.push(resolvedCallback);\n this.rejectedCallbacks.push(rejectedCallback);\n break;\n case TaskStage.Resolved:\n resolvedCallback(this.state.result);\n break;\n case TaskStage.Rejected:\n rejectedCallback({\n type: 'reject',\n reason: this.state.reason,\n });\n break;\n case TaskStage.Aborted:\n rejectedCallback({\n type: 'abort',\n reason: this.state.reason,\n });\n break;\n }\n }\n\n /**\n * resolve task with specific result\n * @param result - result value\n */\n resolve(result: R) {\n if (this.state.stage === TaskStage.Pending) {\n this.state = {\n stage: TaskStage.Resolved,\n result,\n };\n for (const resolvedCallback of this.resolvedCallbacks) {\n try {\n resolvedCallback(result);\n } catch (e) {\n /* ignore */\n }\n }\n this.resolvedCallbacks = [];\n this.rejectedCallbacks = [];\n }\n }\n\n /**\n * reject task with specific reason\n * @param reason - abort reason\n *\n */\n reject(reason: D) {\n if (this.state.stage === TaskStage.Pending) {\n this.state = {\n stage: TaskStage.Rejected,\n reason,\n };\n for (const rejectedCallback of this.rejectedCallbacks) {\n try {\n rejectedCallback({\n type: 'reject',\n reason,\n });\n } catch (e) {\n /*ignore */\n }\n }\n this.resolvedCallbacks = [];\n this.rejectedCallbacks = [];\n }\n }\n\n /**\n * abort task with specific reason\n * @param reason - abort reason\n */\n abort(reason: D) {\n if (this.state.stage === TaskStage.Pending) {\n this.state = {\n stage: TaskStage.Aborted,\n reason,\n };\n for (const rejectedCallback of this.rejectedCallbacks) {\n try {\n rejectedCallback({\n type: 'abort',\n reason,\n });\n } catch (e) {\n /* ignore */\n }\n }\n this.resolvedCallbacks = [];\n this.rejectedCallbacks = [];\n }\n }\n\n /**\n * fail task with a TaskError from another task\n * This is a convenience method for error propagation between tasks\n * @param error - TaskError from another task\n */\n fail(error: TaskError<D>) {\n if (error.type === 'abort') {\n this.abort(error.reason);\n } else {\n this.reject(error.reason);\n }\n }\n}\n\n/**\n * Type that represent the result of executing task\n */\nexport type TaskReturn<T extends Task<any, any>> =\n T extends Task<infer R, infer E>\n ? { type: 'result'; value: R } | { type: 'error'; value: TaskError<E> }\n : never;\n","import { Size, Rect, Position, Rotation, Quad } from './geometry';\nimport { Task, TaskError } from './task';\n\n/**\n * Representation of pdf page\n *\n * @public\n */\nexport interface PdfPageObject {\n /**\n * Index of this page, starts from 0\n */\n index: number;\n\n /**\n * Orignal size of this page\n */\n size: Size;\n}\n\n/**\n * Representation of pdf page with rotated size\n *\n * @public\n */\nexport interface PdfPageObjectWithRotatedSize extends PdfPageObject {\n /**\n * Rotated size of this page\n */\n rotatedSize: Size;\n}\n\n/**\n * Representation of pdf document\n *\n * @public\n */\nexport interface PdfDocumentObject {\n /**\n * Identity of document\n */\n id: string;\n\n /**\n * Count of pages in this document\n */\n pageCount: number;\n\n /**\n * Pages in this document\n */\n pages: PdfPageObject[];\n}\n\n/**\n * metadata of pdf document\n *\n * @public\n */\nexport interface PdfMetadataObject {\n /**\n * title of the document\n */\n title: string;\n /**\n * author of the document\n */\n author: string;\n /**\n * subject of the document\n */\n subject: string;\n /**\n * keywords of the document\n */\n keywords: string;\n /**\n * producer of the document\n */\n producer: string;\n /**\n * creator of the document\n */\n creator: string;\n /**\n * creation date of the document\n */\n creationDate: string;\n /**\n * modification date of the document\n */\n modificationDate: string;\n}\n\n/**\n * Unicode **soft-hyphen** marker (`U+00AD`).\n * Often embedded by PDF generators as discretionary hyphens.\n *\n * @public\n */\nexport const PdfSoftHyphenMarker = '\\u00AD';\n\n/**\n * Unicode **zero-width space** (`U+200B`).\n *\n * @public\n */\nexport const PdfZeroWidthSpace = '\\u200B';\n\n/**\n * Unicode **word-joiner** (`U+2060`) – zero-width no-break.\n *\n * @public\n */\nexport const PdfWordJoiner = '\\u2060';\n\n/**\n * Unicode **byte-order mark / zero-width&nbsp;no-break space** (`U+FEFF`).\n *\n * @public\n */\nexport const PdfBomOrZwnbsp = '\\uFEFF';\n\n/**\n * Unicode non-character `U+FFFE`.\n *\n * @public\n */\nexport const PdfNonCharacterFFFE = '\\uFFFE';\n\n/**\n * Unicode non-character `U+FFFF`.\n *\n * @public\n */\nexport const PdfNonCharacterFFFF = '\\uFFFF';\n\n/**\n * **Frozen list** of all unwanted markers in canonical order.\n *\n * @public\n */\nexport const PdfUnwantedTextMarkers = Object.freeze([\n PdfSoftHyphenMarker,\n PdfZeroWidthSpace,\n PdfWordJoiner,\n PdfBomOrZwnbsp,\n PdfNonCharacterFFFE,\n PdfNonCharacterFFFF,\n] as const);\n\n/**\n * Compiled regular expression that matches any unwanted marker.\n *\n * @public\n */\nexport const PdfUnwantedTextRegex = new RegExp(`[${PdfUnwantedTextMarkers.join('')}]`, 'g');\n\n/**\n * Remove all {@link PdfUnwantedTextMarkers | unwanted markers} from *text*.\n *\n * @param text - raw text extracted from PDF\n * @returns cleaned text\n *\n * @public\n */\nexport function stripPdfUnwantedMarkers(text: string): string {\n return text.replace(PdfUnwantedTextRegex, '');\n}\n\n/**\n * zoom mode\n *\n * @public\n */\nexport enum PdfZoomMode {\n Unknown = 0,\n /**\n * Zoom level with specified offset.\n */\n XYZ = 1,\n /**\n * Fit both the width and height of the page (whichever smaller).\n */\n FitPage = 2,\n /**\n * Fit the page width.\n */\n FitHorizontal = 3,\n /**\n * Fit the page height.\n */\n FitVertical = 4,\n /**\n * Fit a specific rectangle area within the window.\n */\n FitRectangle = 5,\n}\n\n/**\n * Representation of the linked destination\n *\n * @public\n */\nexport interface PdfDestinationObject {\n /**\n * Index of target page\n */\n pageIndex: number;\n /**\n * zoom config for target destination\n */\n zoom:\n | {\n mode: PdfZoomMode.Unknown;\n }\n | { mode: PdfZoomMode.XYZ; params: { x: number; y: number; zoom: number } }\n | {\n mode: PdfZoomMode.FitPage;\n }\n | {\n mode: PdfZoomMode.FitHorizontal;\n }\n | {\n mode: PdfZoomMode.FitVertical;\n }\n | {\n mode: PdfZoomMode.FitRectangle;\n };\n view: number[];\n}\n\n/**\n * Type of pdf action\n *\n * @public\n */\nexport enum PdfActionType {\n Unsupported = 0,\n /**\n * Goto specified position in this document\n */\n Goto = 1,\n /**\n * Goto specified position in another document\n */\n RemoteGoto = 2,\n /**\n * Goto specified URI\n */\n URI = 3,\n /**\n * Launch specifed application\n */\n LaunchAppOrOpenFile = 4,\n}\n\nexport type PdfImage = {\n data: Uint8ClampedArray;\n width: number;\n height: number;\n};\n\n/**\n * Representation of pdf action\n *\n * @public\n */\nexport type PdfActionObject =\n | {\n type: PdfActionType.Unsupported;\n }\n | {\n type: PdfActionType.Goto;\n destination: PdfDestinationObject;\n }\n | {\n type: PdfActionType.RemoteGoto;\n destination: PdfDestinationObject;\n }\n | {\n type: PdfActionType.URI;\n uri: string;\n }\n | {\n type: PdfActionType.LaunchAppOrOpenFile;\n path: string;\n };\n\n/**\n * target of pdf link\n *\n * @public\n */\nexport type PdfLinkTarget =\n | {\n type: 'action';\n action: PdfActionObject;\n }\n | {\n type: 'destination';\n destination: PdfDestinationObject;\n };\n\n/**\n * PDF bookmark\n *\n * @public\n */\nexport interface PdfBookmarkObject {\n /**\n * title of bookmark\n */\n title: string;\n\n /**\n * target of bookmark\n */\n target?: PdfLinkTarget | undefined;\n\n /**\n * bookmarks in the next level\n */\n children?: PdfBookmarkObject[];\n}\n\n/**\n * Pdf Signature\n *\n * @public\n */\nexport interface PdfSignatureObject {\n /**\n * contents of signature\n */\n contents: ArrayBuffer;\n\n /**\n * byte range of signature\n */\n byteRange: ArrayBuffer;\n\n /**\n * sub filters of signature\n */\n subFilter: ArrayBuffer;\n\n /**\n * reason of signature\n */\n reason: string;\n\n /**\n * creation time of signature\n */\n time: string;\n\n /**\n * MDP\n */\n docMDP: number;\n}\n\n/**\n * Bookmark tree of pdf\n *\n * @public\n */\nexport interface PdfBookmarksObject {\n bookmarks: PdfBookmarkObject[];\n}\n\n/**\n * Text rectangle in pdf page\n *\n * @public\n */\nexport interface PdfTextRectObject {\n /**\n * Font of the text\n */\n font: {\n /**\n * font family\n */\n family: string;\n\n /**\n * font size\n */\n size: number;\n };\n\n /**\n * content in this rectangle area\n */\n content: string;\n\n /**\n * rectangle of the text\n */\n rect: Rect;\n}\n\n/**\n * Color\n *\n * @public\n */\nexport interface PdfAlphaColor {\n /**\n * red\n */\n red: number;\n /**\n * green\n */\n green: number;\n /**\n * blue\n */\n blue: number;\n /**\n * alpha\n */\n alpha: number;\n}\n\n/**\n * Annotation type\n *\n * @public\n */\nexport enum PdfAnnotationSubtype {\n UNKNOWN = 0,\n TEXT,\n LINK,\n FREETEXT,\n LINE,\n SQUARE,\n CIRCLE,\n POLYGON,\n POLYLINE,\n HIGHLIGHT,\n UNDERLINE,\n SQUIGGLY,\n STRIKEOUT,\n STAMP,\n CARET,\n INK,\n POPUP,\n FILEATTACHMENT,\n SOUND,\n MOVIE,\n WIDGET,\n SCREEN,\n PRINTERMARK,\n TRAPNET,\n WATERMARK,\n THREED,\n RICHMEDIA,\n XFAWIDGET,\n REDACT,\n}\n\n/**\n * Name of annotation type\n *\n * @public\n */\nexport const PdfAnnotationSubtypeName: Record<PdfAnnotationSubtype, string> = {\n [PdfAnnotationSubtype.UNKNOWN]: 'unknow',\n [PdfAnnotationSubtype.TEXT]: 'text',\n [PdfAnnotationSubtype.LINK]: 'link',\n [PdfAnnotationSubtype.FREETEXT]: 'freetext',\n [PdfAnnotationSubtype.LINE]: 'line',\n [PdfAnnotationSubtype.SQUARE]: 'square',\n [PdfAnnotationSubtype.CIRCLE]: 'circle',\n [PdfAnnotationSubtype.POLYGON]: 'polygon',\n [PdfAnnotationSubtype.POLYLINE]: 'polyline',\n [PdfAnnotationSubtype.HIGHLIGHT]: 'highlight',\n [PdfAnnotationSubtype.UNDERLINE]: 'underline',\n [PdfAnnotationSubtype.SQUIGGLY]: 'squiggly',\n [PdfAnnotationSubtype.STRIKEOUT]: 'strikeout',\n [PdfAnnotationSubtype.STAMP]: 'stamp',\n [PdfAnnotationSubtype.CARET]: 'caret',\n [PdfAnnotationSubtype.INK]: 'ink',\n [PdfAnnotationSubtype.POPUP]: 'popup',\n [PdfAnnotationSubtype.FILEATTACHMENT]: 'fileattachment',\n [PdfAnnotationSubtype.SOUND]: 'sound',\n [PdfAnnotationSubtype.MOVIE]: 'movie',\n [PdfAnnotationSubtype.WIDGET]: 'widget',\n [PdfAnnotationSubtype.SCREEN]: 'screen',\n [PdfAnnotationSubtype.PRINTERMARK]: 'printermark',\n [PdfAnnotationSubtype.TRAPNET]: 'trapnet',\n [PdfAnnotationSubtype.WATERMARK]: 'watermark',\n [PdfAnnotationSubtype.THREED]: 'threed',\n [PdfAnnotationSubtype.RICHMEDIA]: 'richmedia',\n [PdfAnnotationSubtype.XFAWIDGET]: 'xfawidget',\n [PdfAnnotationSubtype.REDACT]: 'redact',\n};\n\n/**\n * Status of pdf annotation\n *\n * @public\n */\nexport enum PdfAnnotationObjectStatus {\n /**\n * Annotation is created\n */\n Created,\n /**\n * Annotation is committed to PDF file\n */\n Committed,\n}\n\n/**\n * Appearance mode\n *\n * @public\n */\nexport enum AppearanceMode {\n Normal = 0,\n Rollover = 1,\n Down = 2,\n}\n\n/**\n * State of pdf annotation\n *\n * @public\n */\nexport enum PdfAnnotationState {\n /**\n * Annotation is active\n */\n Marked = 'Marked',\n /**\n * Annotation is unmarked\n */\n Unmarked = 'Unmarked',\n /**\n * Annotation is ink\n */\n Accepted = 'Accepted',\n /**\n * Annotation is rejected\n */\n Rejected = 'Rejected',\n /**\n * Annotation is complete\n */\n Complete = 'Complete',\n /**\n * Annotation is cancelled\n */\n Cancelled = 'Cancelled',\n /**\n * Annotation is none\n */\n None = 'None',\n}\n\n/**\n * State model of pdf annotation\n *\n * @public\n */\nexport enum PdfAnnotationStateModel {\n /**\n * Annotation is marked\n */\n Marked = 'Marked',\n /**\n * Annotation is reviewed\n */\n Reviewed = 'Reviewed',\n}\n\n/**\n * Basic information of pdf annotation\n *\n * @public\n */\nexport interface PdfAnnotationObjectBase {\n /**\n * Author of the annotation\n */\n author?: string;\n\n /**\n * Modified date of the annotation\n */\n modified?: string;\n\n /**\n * Sub type of annotation\n */\n type: PdfAnnotationSubtype;\n\n /**\n * Status of pdf annotation\n */\n status: PdfAnnotationObjectStatus;\n\n /**\n * The index of page that this annotation belong to\n */\n pageIndex: number;\n\n /**\n * id of the annotation\n */\n id: number;\n\n /**\n * Rectangle of the annotation\n */\n rect: Rect;\n\n /**\n * Related popup annotation\n */\n popup?: PdfPopupAnnoObject | undefined;\n\n /**\n * Appearences of annotation\n */\n appearances: {\n normal: string;\n rollover: string;\n down: string;\n };\n}\n\n/**\n * Popup annotation\n *\n * @public\n */\nexport interface PdfPopupAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.POPUP;\n /**\n * Contents of the popup\n */\n contents: string;\n\n /**\n * Whether the popup is opened or not\n */\n open: boolean;\n}\n\n/**\n * Pdf Link annotation\n *\n * @public\n */\nexport interface PdfLinkAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.LINK;\n /**\n * Text of the link\n */\n text: string;\n /**\n * target of the link\n */\n target: PdfLinkTarget | undefined;\n}\n\n/**\n * Pdf Text annotation\n *\n * @public\n */\nexport interface PdfTextAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.TEXT;\n /**\n * Text contents of the annotation\n */\n contents: string;\n\n /**\n * Color of the text\n */\n color: PdfAlphaColor;\n\n /**\n * In reply to id\n */\n inReplyToId?: number;\n\n /**\n * State of the text annotation\n */\n state?: PdfAnnotationState;\n\n /**\n * State model of the text annotation\n */\n stateModel?: PdfAnnotationStateModel;\n}\n\n/**\n * Type of form field\n *\n * @public\n */\nexport enum PDF_FORM_FIELD_TYPE {\n /**\n * Unknow\n */\n UNKNOWN = 0,\n /**\n * push button type\n */\n PUSHBUTTON = 1,\n /**\n * check box type.\n */\n CHECKBOX = 2,\n /**\n * radio button type.\n */\n RADIOBUTTON = 3,\n /**\n * combo box type.\n */\n COMBOBOX = 4,\n /**\n * list box type.\n */\n LISTBOX = 5,\n /**\n * text field type\n */\n TEXTFIELD = 6,\n /**\n * signature field type.\n */\n SIGNATURE = 7,\n /**\n * Generic XFA type.\n */\n XFA = 8,\n /**\n * XFA check box type.\n */\n XFA_CHECKBOX = 9,\n /**\n * XFA combo box type.\n */\n XFA_COMBOBOX = 10,\n /**\n * XFA image field type.\n */\n XFA_IMAGEFIELD = 11,\n /**\n * XFA list box type.\n */\n XFA_LISTBOX = 12,\n /**\n * XFA push button type.\n */\n XFA_PUSHBUTTON = 13,\n /**\n * XFA signture field type.\n */\n XFA_SIGNATURE = 14,\n /**\n * XFA text field type.\n */\n XFA_TEXTFIELD = 15,\n}\n\n/**\n * Flag of form field\n *\n * @public\n */\nexport enum PDF_FORM_FIELD_FLAG {\n NONE = 0,\n READONLY = 1 << 0,\n REQUIRED = 1 << 1,\n NOEXPORT = 1 << 2,\n TEXT_MULTIPLINE = 1 << 12,\n TEXT_PASSWORD = 1 << 13,\n CHOICE_COMBO = 1 << 17,\n CHOICE_EDIT = 1 << 18,\n CHOICE_MULTL_SELECT = 1 << 21,\n}\n\n/**\n * Type of pdf object\n *\n * @public\n */\nexport enum PdfPageObjectType {\n UNKNOWN = 0,\n TEXT = 1,\n PATH = 2,\n IMAGE = 3,\n SHADING = 4,\n FORM = 5,\n}\n\n/**\n * Options of pdf widget annotation\n *\n * @public\n */\nexport interface PdfWidgetAnnoOption {\n label: string;\n isSelected: boolean;\n}\n\n/**\n * Field of PDF widget annotation\n *\n * @public\n */\nexport interface PdfWidgetAnnoField {\n /**\n * flag of field\n */\n flag: PDF_FORM_FIELD_FLAG;\n /**\n * name of field\n */\n name: string;\n /**\n * alternate name of field\n */\n alternateName: string;\n /**\n * type of field\n */\n type: PDF_FORM_FIELD_TYPE;\n /**\n * value of field\n */\n value: string;\n /**\n * whether field is checked\n */\n isChecked: boolean;\n /**\n * options of field\n */\n options: PdfWidgetAnnoOption[];\n}\n\n/**\n * PDF widget object\n *\n * @public\n */\nexport interface PdfWidgetAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.WIDGET;\n /**\n * Field of pdf widget object\n */\n field: PdfWidgetAnnoField;\n}\n\n/**\n * Pdf file attachments annotation\n *\n * @public\n */\nexport interface PdfFileAttachmentAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.FILEATTACHMENT;\n}\n\n/**\n * ink list in pdf ink annotation\n *\n * @public\n */\nexport interface PdfInkListObject {\n points: Position[];\n}\n\n/**\n * Pdf ink annotation\n *\n * @public\n */\nexport interface PdfInkAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.INK;\n inkList: PdfInkListObject[];\n}\n\n/**\n * Pdf polygon annotation\n *\n * @public\n */\nexport interface PdfPolygonAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.POLYGON;\n /**\n * vertices of annotation\n */\n vertices: Position[];\n}\n\n/**\n * PDF polyline annotation\n *\n * @public\n */\nexport interface PdfPolylineAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.POLYLINE;\n /**\n * vertices of annotation\n */\n vertices: Position[];\n}\n\n/**\n * PDF line annotation\n *\n * @public\n */\nexport interface PdfLineAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.LINE;\n /**\n * start point of line\n */\n startPoint: Position;\n /**\n * end point of line\n */\n endPoint: Position;\n}\n\n/**\n * PDF highlight annotation\n *\n * @public\n */\nexport interface PdfHighlightAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.HIGHLIGHT;\n\n /**\n * color of highlight area\n */\n color?: PdfAlphaColor;\n\n /**\n * quads of highlight area\n */\n segmentRects: Rect[];\n}\n\n/**\n * Matrix for transformation, in the form [a b c d e f], equivalent to:\n * | a b 0 |\n * | c d 0 |\n * | e f 1 |\n *\n * Translation is performed with [1 0 0 1 tx ty].\n * Scaling is performed with [sx 0 0 sy 0 0].\n * See PDF Reference 1.7, 4.2.2 Common Transformations for more.\n */\nexport interface PdfTransformMatrix {\n a: number;\n b: number;\n c: number;\n d: number;\n e: number;\n f: number;\n}\n\n/**\n * type of segment type in pdf path object\n *\n * @public\n */\nexport enum PdfSegmentObjectType {\n UNKNOWN = -1,\n LINETO = 0,\n BEZIERTO = 1,\n MOVETO = 2,\n}\n\n/**\n * segment of path object\n *\n * @public\n */\nexport interface PdfSegmentObject {\n type: PdfSegmentObjectType;\n /**\n * point of the segment\n */\n point: Position;\n /**\n * whether this segment close the path\n */\n isClosed: boolean;\n}\n\n/**\n * Pdf path object\n *\n * @public\n */\nexport interface PdfPathObject {\n type: PdfPageObjectType.PATH;\n /**\n * bound that contains the path\n */\n bounds: { left: number; bottom: number; right: number; top: number };\n /**\n * segments of the path\n */\n segments: PdfSegmentObject[];\n /**\n * transform matrix\n */\n matrix: PdfTransformMatrix;\n}\n\n/**\n * Pdf image object\n *\n * @public\n */\nexport interface PdfImageObject {\n type: PdfPageObjectType.IMAGE;\n /**\n * data of the image\n */\n imageData: ImageData;\n /**\n * transform matrix\n */\n matrix: PdfTransformMatrix;\n}\n\n/**\n * Pdf form object\n *\n * @public\n */\nexport interface PdfFormObject {\n type: PdfPageObjectType.FORM;\n /**\n * objects that in this form object\n */\n objects: (PdfImageObject | PdfPathObject | PdfFormObject)[];\n /**\n * transform matrix\n */\n matrix: PdfTransformMatrix;\n}\n\n/**\n * Contents type of pdf stamp annotation\n *\n * @public\n */\nexport type PdfStampAnnoObjectContents = Array<PdfPathObject | PdfImageObject | PdfFormObject>;\n\n/**\n * Pdf stamp annotation\n *\n * @public\n */\nexport interface PdfStampAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.STAMP;\n /**\n * contents in this stamp annotation\n */\n contents: PdfStampAnnoObjectContents;\n}\n\n/**\n * Pdf circle annotation\n *\n * @public\n */\nexport interface PdfCircleAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.CIRCLE;\n}\n\n/**\n * Pdf square annotation\n *\n * @public\n */\nexport interface PdfSquareAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.SQUARE;\n}\n\n/**\n * Pdf squiggly annotation\n *\n * @public\n */\nexport interface PdfSquigglyAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.SQUIGGLY;\n}\n\n/**\n * Pdf underline annotation\n *\n * @public\n */\nexport interface PdfUnderlineAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.UNDERLINE;\n}\n\n/**\n * Pdf strike out annotation\n *\n * @public\n */\nexport interface PdfStrikeOutAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.STRIKEOUT;\n}\n\n/**\n * Pdf caret annotation\n *\n * @public\n */\nexport interface PdfCaretAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.CARET;\n}\n\n/**\n * Pdf free text annotation\n *\n * @public\n */\nexport interface PdfFreeTextAnnoObject extends PdfAnnotationObjectBase {\n /** {@inheritDoc PdfAnnotationObjectBase.type} */\n type: PdfAnnotationSubtype.FREETEXT;\n contents: string;\n}\n\n/**\n * All annotation that support\n *\n * @public\n */\nexport type PdfSupportedAnnoObject =\n | PdfInkAnnoObject\n | PdfTextAnnoObject\n | PdfLinkAnnoObject\n | PdfPolygonAnnoObject\n | PdfPolylineAnnoObject\n | PdfHighlightAnnoObject\n | PdfLineAnnoObject\n | PdfWidgetAnnoObject\n | PdfFileAttachmentAnnoObject\n | PdfStampAnnoObject\n | PdfSquareAnnoObject\n | PdfCircleAnnoObject\n | PdfSquigglyAnnoObject\n | PdfUnderlineAnnoObject\n | PdfStrikeOutAnnoObject\n | PdfCaretAnnoObject\n | PdfFreeTextAnnoObject;\n\n/**\n * Pdf annotation that does not support\n *\n * @public\n */\nexport interface PdfUnsupportedAnnoObject extends PdfAnnotationObjectBase {\n type: Exclude<PdfAnnotationSubtype, PdfSupportedAnnoObject['type']>;\n}\n\n/**\n * all annotations\n *\n * @public\n */\nexport type PdfAnnotationObject = PdfSupportedAnnoObject | PdfUnsupportedAnnoObject;\n\n/**\n * Pdf attachment\n *\n * @public\n */\nexport interface PdfAttachmentObject {\n index: number;\n name: string;\n creationDate: string;\n checksum: string;\n}\n\n/**\n * Pdf engine features\n *\n * @public\n */\nexport enum PdfEngineFeature {\n RenderPage,\n RenderPageRect,\n Thumbnails,\n Bookmarks,\n Annotations,\n}\n\n/**\n * All operations for this engine\n *\n * @public\n */\nexport enum PdfEngineOperation {\n Create,\n Read,\n Update,\n Delete,\n}\n\n/**\n * flags to match the text during searching\n *\n * @public\n */\nexport enum MatchFlag {\n None = 0,\n MatchCase = 1,\n MatchWholeWord = 2,\n MatchConsecutive = 4,\n}\n\n/**\n * Union all the flags\n * @param flags - all the flags\n * @returns union of flags\n *\n * @public\n */\nexport function unionFlags(flags: MatchFlag[]) {\n return flags.reduce((flag, currFlag) => {\n return flag | currFlag;\n }, MatchFlag.None);\n}\n\n/**\n * Image conversion types\n *\n * @public\n */\nexport type ImageConversionTypes = 'image/webp' | 'image/png' | 'image/jpeg';\n\n/**\n * Targe for searching\n *\n * @public\n */\nexport interface SearchTarget {\n keyword: string;\n flags: MatchFlag[];\n}\n\n/**\n * compare 2 search target\n * @param targetA - first target for search\n * @param targetB - second target for search\n * @returns whether 2 search target are the same\n *\n * @public\n */\nexport function compareSearchTarget(targetA: SearchTarget, targetB: SearchTarget) {\n const flagA = unionFlags(targetA.flags);\n const flagB = unionFlags(targetB.flags);\n\n return flagA === flagB && targetA.keyword === targetB.keyword;\n}\n\n/** Context of one hit */\nexport interface TextContext {\n /** Complete words that come *before* the hit (no ellipsis) */\n before: string;\n /** Exactly the text that matched (case-preserved) */\n match: string;\n /** Complete words that come *after* the hit (no ellipsis) */\n after: string;\n /** `true` ⇢ there were more words on the left that we cut off */\n truncatedLeft: boolean;\n /** `true` ⇢ there were more words on the right that we cut off */\n truncatedRight: boolean;\n}\n\n/**\n * Text slice\n *\n * @public\n */\nexport interface PageTextSlice {\n /**\n * Index of the pdf page\n */\n pageIndex: number;\n /**\n * Index of the first character\n */\n charIndex: number;\n /**\n * Count of the characters\n */\n charCount: number;\n}\n\n/**\n * search result\n *\n * @public\n */\nexport interface SearchResult {\n /**\n * Index of the pdf page\n */\n pageIndex: number;\n /**\n * index of the first character\n */\n charIndex: number;\n /**\n * count of the characters\n */\n charCount: number;\n /**\n * highlight rects\n */\n rects: Rect[];\n /**\n * context of the hit\n */\n context: TextContext;\n}\n\n/**\n * Results of searching through the entire document\n */\nexport interface SearchAllPagesResult {\n /**\n * Array of all search results across all pages\n */\n results: SearchResult[];\n\n /**\n * Total number of results found\n */\n total: number;\n}\n\n/**\n * Glyph object\n *\n * @public\n */\nexport interface PdfGlyphObject {\n /**\n * Origin of the glyph\n */\n origin: { x: number; y: number };\n /**\n * Size of the glyph\n */\n size: { width: number; height: number };\n /**\n * Whether the glyph is a space\n */\n isSpace?: boolean;\n /**\n * Whether the glyph is a empty\n */\n isEmpty?: boolean;\n}\n\n/**\n * Glyph object\n *\n * @public\n */\nexport interface PdfGlyphSlim {\n /**\n * X coordinate of the glyph\n */\n x: number;\n /**\n * Y coordinate of the glyph\n */\n y: number;\n /**\n * Width of the glyph\n */\n width: number;\n /**\n * Height of the glyph\n */\n height: number;\n /**\n * Flags of the glyph\n */\n flags: number;\n}\n\n/**\n * Run object\n *\n * @public\n */\nexport interface PdfRun {\n /**\n * Rectangle of the run\n */\n rect: { x: number; y: number; width: number; height: number };\n /**\n * Start index of the run\n */\n charStart: number;\n /**\n * Glyphs of the run\n */\n glyphs: PdfGlyphSlim[];\n}\n\n/**\n * Page geometry\n *\n * @public\n */\nexport interface PdfPageGeometry {\n /**\n * Runs of the page\n */\n runs: PdfRun[];\n}\n\n/**\n * form field value\n * @public\n */\nexport type FormFieldValue =\n | { kind: 'text'; text: string }\n | { kind: 'selection'; index: number; isSelected: boolean }\n | { kind: 'checked'; isChecked: boolean };\n\n/**\n * Transformation that will be applied to annotation\n *\n * @public\n */\nexport interface PdfAnnotationTransformation {\n /**\n * Translated offset\n */\n offset: Position;\n /**\n * Scaled factors\n */\n scale: Size;\n}\n\n/**\n * Render options\n *\n * @public\n */\nexport interface PdfRenderOptions {\n /**\n * Whether needs to render the page with annotations\n */\n withAnnotations: boolean;\n}\n\n/**\n * source can be byte array contains pdf content\n *\n * @public\n */\nexport type PdfFileContent = ArrayBuffer;\n\nexport enum PdfPermission {\n PrintDocument = 2 ** 3,\n ModifyContent = 2 ** 4,\n CopyOrExtract = 2 ** 5,\n AddOrModifyTextAnnot = 2 ** 6,\n FillInExistingForm = 2 ** 9,\n ExtractTextOrGraphics = 2 ** 10,\n AssembleDocument = 2 ** 11,\n PrintHighQuality = 2 ** 12,\n}\n\nexport enum PdfPageFlattenFlag {\n Display = 0,\n Print = 1,\n}\n\nexport enum PdfPageFlattenResult {\n Fail = 0,\n Success = 1,\n NothingToDo = 2,\n}\n\n/**\n * Pdf File without content\n *\n * @public\n */\nexport interface PdfFileWithoutContent {\n /**\n * id of file\n */\n id: string;\n}\n\nexport interface PdfFileLoader extends PdfFileWithoutContent {\n /**\n * length of file\n */\n fileLength: number;\n /**\n * read block of file\n * @param offset - offset of file\n * @param length - length of file\n * @returns block of file\n */\n callback: (offset: number, length: number) => Uint8Array;\n}\n\n/**\n * Pdf File\n *\n * @public\n */\nexport interface PdfFile extends PdfFileWithoutContent {\n /**\n * content of file\n */\n content: PdfFileContent;\n}\n\nexport interface PdfFileUrl extends PdfFileWithoutContent {\n url: string;\n}\n\nexport interface PdfUrlOptions {\n mode?: 'auto' | 'range-request' | 'full-fetch';\n password?: string;\n}\n\nexport enum PdfErrorCode {\n Ok, // #define FPDF_ERR_SUCCESS 0 // No error.\n Unknown, // #define FPDF_ERR_UNKNOWN 1 // Unknown error.\n NotFound, // #define FPDF_ERR_FILE 2 // File not found or could not be opened.\n WrongFormat, // #define FPDF_ERR_FORMAT 3 // File not in PDF format or corrupted.\n Password, // #define FPDF_ERR_PASSWORD 4 // Password required or incorrect password.\n Security, // #define FPDF_ERR_SECURITY 5 // Unsupported security scheme.\n PageError, // #define FPDF_ERR_PAGE 6 // Page not found or content error.\n XFALoad, // #ifdef PDF_ENABLE_XFA\n XFALayout, //\n Cancelled,\n Initialization,\n NotReady,\n NotSupport,\n LoadDoc,\n DocNotOpen,\n CantCloseDoc,\n CantCreateNewDoc,\n CantImportPages,\n CantCreateAnnot,\n CantSetAnnotRect,\n CantSetAnnotContent,\n CantRemoveInkList,\n CantAddInkStoke,\n CantReadAttachmentSize,\n CantReadAttachmentContent,\n CantFocusAnnot,\n CantSelectText,\n CantSelectOption,\n CantCheckField,\n}\n\nexport interface PdfErrorReason {\n code: PdfErrorCode;\n message: string;\n}\n\nexport type PdfEngineError = TaskError<PdfErrorReason>;\n\nexport type PdfTask<R> = Task<R, PdfErrorReason>;\n\nexport class PdfTaskHelper {\n /**\n * Create a task\n * @returns new task\n */\n static create<R>(): Task<R, PdfErrorReason> {\n return new Task<R, PdfErrorReason>();\n }\n\n /**\n * Create a task that has been resolved with value\n * @param result - resolved value\n * @returns resolved task\n */\n static resolve<R>(result: R): Task<R, PdfErrorReason> {\n const task = new Task<R, PdfErrorReason>();\n task.resolve(result);\n\n return task;\n }\n\n /**\n * Create a task that has been rejected with error\n * @param reason - rejected error\n * @returns rejected task\n */\n static reject<T = any>(reason: PdfErrorReason): Task<T, PdfErrorReason> {\n const task = new Task<T, PdfErrorReason>();\n task.reject(reason);\n\n return task;\n }\n\n /**\n * Create a task that has been aborted with error\n * @param reason - aborted error\n * @returns aborted task\n */\n static abort<T = any>(reason: PdfErrorReason): Task<T, PdfErrorReason> {\n const task = new Task<T, PdfErrorReason>();\n task.reject(reason);\n\n return task;\n }\n}\n\n/**\n * Pdf engine\n *\n * @public\n */\nexport interface PdfEngine<T = Blob> {\n /**\n * Check whether pdf engine supports this feature\n * @param feature - which feature want to check\n * @returns support or not\n */\n isSupport?: (feature: PdfEngineFeature) => PdfTask<PdfEngineOperation[]>;\n /**\n * Initialize the engine\n * @returns task that indicate whether initialization is successful\n */\n initialize?: () => PdfTask<boolean>;\n /**\n * Destroy the engine\n * @returns task that indicate whether destroy is successful\n */\n destroy?: () => PdfTask<boolean>;\n /**\n * Open a PDF from a URL with specified mode\n * @param url - The PDF file URL\n * @param options - Additional options including mode (auto, range-request, full-fetch) and password\n * @returns Task that resolves with the PdfDocumentObject or an error\n */\n openDocumentUrl: (file: PdfFileUrl, options?: PdfUrlOptions) => PdfTask<PdfDocumentObject>;\n /**\n * Open pdf document from buffer\n * @param file - pdf file\n * @param password - protected password for this file\n * @returns task that contains the file or error\n */\n openDocumentFromBuffer: (file: PdfFile, password: string) => PdfTask<PdfDocumentObject>;\n /**\n * Open pdf document from loader\n * @param file - pdf file\n * @param password - protected password for this file\n * @returns task that contains the file or error\n */\n openDocumentFromLoader: (file: PdfFileLoader, password: string) => PdfTask<PdfDocumentObject>;\n /**\n * Get the metadata of the file\n * @param doc - pdf document\n * @returns task that contains the metadata or error\n */\n getMetadata: (doc: PdfDocumentObject) => PdfTask<PdfMetadataObject>;\n /**\n * Get permissions of the file\n * @param doc - pdf document\n * @returns task that contains a 32-bit integer indicating permission flags\n */\n getDocPermissions: (doc: PdfDocumentObject) => PdfTask<number>;\n /**\n * Get the user permissions of the file\n * @param doc - pdf document\n * @returns task that contains a 32-bit integer indicating permission flags\n */\n getDocUserPermissions: (doc: PdfDocumentObject) => PdfTask<number>;\n /**\n * Get the signatures of the file\n * @param doc - pdf document\n * @returns task that contains the signatures or error\n */\n getSignatures: (doc: PdfDocumentObject) => PdfTask<PdfSignatureObject[]>;\n /**\n * Get the bookmarks of the file\n * @param doc - pdf document\n * @returns task that contains the bookmarks or error\n */\n getBookmarks: (doc: PdfDocumentObject) => PdfTask<PdfBookmarksObject>;\n /**\n * Render the specified pdf page\n * @param doc - pdf document\n * @param page - pdf page\n * @param scaleFactor - factor of scaling\n * @param rotation - rotated angle\n * @param dpr - devicePixelRatio\n * @param options - render options\n * @returns task contains the rendered image or error\n */\n renderPage: (\n doc: PdfDocumentObject,\n page: PdfPageObject,\n scaleFactor: number,\n rotation: Rotation,\n dpr: number,\n options: PdfRenderOptions,\n imageType?: ImageConversionTypes,\n ) => PdfTask<T>;\n /**\n * Render the specified rect of pdf page\n * @param doc - pdf document\n * @param page - pdf page\n * @param scaleFactor - factor of scaling\n * @param rotation - rotated angle\n * @param dpr - devicePixelRatio\n * @param rect - target rect\n * @param options - render options\n * @returns task contains the rendered image or error\n */\n renderPageRect: (\n doc: PdfDocumentObject,\n page: PdfPageObject,\n scaleFactor: number,\n rotation: Rotation,\n dpr: number,\n rect: Rect,\n options: PdfRenderOptions,\n imageType?: ImageConversionTypes,\n ) => PdfTask<T>;\n /**\n * Get annotations of pdf page\n * @param doc - pdf document\n * @param page - pdf page\n * @param scaleFactor - factor of scaling\n * @param rotation - rotated angle\n * @returns task contains the annotations or error\n */\n getPageAnnotations: (\n doc: PdfDocumentObject,\n page: PdfPageObject,\n ) => PdfTask<PdfAnnotationObject[]>;\n /**\n * Create a annotation on specified page\n * @param doc - pdf document\n * @param page - pdf page\n * @param annotation - new annotations\n * @returns task whether the annotations is created successfully\n */\n createPageAnnotation: (\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: PdfAnnotationObject,\n ) => PdfTask<boolean>;\n /**\n * Transform the annotation\n * @param doc - pdf document\n * @param page - pdf page\n * @param annotation - new annotations\n * @param transformation - transformation applied on the annotation\n * @returns task whether the annotations is transformed successfully\n */\n transformPageAnnotation: (\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: PdfAnnotationObject,\n transformation: PdfAnnotationTransformation,\n ) => PdfTask<boolean>;\n /**\n * Remove a annotation on specified page\n * @param doc - pdf document\n * @param page - pdf page\n * @param annotation - new annotations\n * @returns task whether the annotations is removed successfully\n */\n removePageAnnotation: (\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: PdfAnnotationObject,\n ) => PdfTask<boolean>;\n /**\n * get all text rects in pdf page\n * @param doc - pdf document\n * @param page - pdf page\n * @param scaleFactor - factor of scaling\n * @param rotation - rotated angle\n * @returns task contains the text rects or error\n */\n getPageTextRects: (\n doc: PdfDocumentObject,\n page: PdfPageObject,\n scaleFactor: number,\n rotation: Rotation,\n ) => PdfTask<PdfTextRectObject[]>;\n /**\n * Render the thumbnail of specified pdf page\n * @param doc - pdf document\n * @param page - pdf page\n * @param scaleFactor - factor of scaling\n * @param rotation - rotated angle\n * @param dpr - devicePixelRatio\n * @param options - render options\n * @returns task contains the rendered image or error\n */\n renderThumbnail: (\n doc: PdfDocumentObject,\n page: PdfPageObject,\n scaleFactor: number,\n rotation: Rotation,\n dpr: number,\n ) => PdfTask<T>;\n /**\n * Search across all pages in the document\n * @param doc - pdf document\n * @param keyword - search keyword\n * @param flags - match flags for search\n * @returns Task contains all search results throughout the document\n */\n searchAllPages: (\n doc: PdfDocumentObject,\n keyword: string,\n flags?: MatchFlag[],\n ) => PdfTask<SearchAllPagesResult>;\n /**\n * Get all annotations in this file\n * @param doc - pdf document\n * @returns task that contains the annotations or error\n */\n getAllAnnotations: (doc: PdfDocumentObject) => PdfTask<Record<number, PdfAnnotationObject[]>>;\n /**\n * Get all attachments in this file\n * @param doc - pdf document\n * @returns task that contains the attachments or error\n */\n getAttachments: (doc: PdfDocumentObject) => PdfTask<PdfAttachmentObject[]>;\n /**\n * Read content of pdf attachment\n * @param doc - pdf document\n * @param attachment - pdf attachments\n * @returns task that contains the content of specified attachment or error\n */\n readAttachmentContent: (\n doc: PdfDocumentObject,\n attachment: PdfAttachmentObject,\n ) => PdfTask<ArrayBuffer>;\n /**\n * Set form field value\n * @param doc - pdf document\n * @param page - pdf page\n * @param annotation - pdf annotation\n * @param text - text value\n */\n setFormFieldValue: (\n doc: PdfDocumentObject,\n page: PdfPageObject,\n annotation: PdfWidgetAnnoObject,\n value: FormFieldValue,\n ) => PdfTask<boolean>;\n /**\n * Flatten annotations and form fields into the page contents.\n * @param doc - pdf document\n * @param page - pdf page\n * @param flag - flatten flag\n */\n flattenPage: (\n doc: PdfDocumentObject,\n page: PdfPageObject,\n flag: PdfPageFlattenFlag,\n ) => PdfTask<PdfPageFlattenResult>;\n /**\n * Extract pdf pages to a new file\n * @param doc - pdf document\n * @param pageIndexes - indexes of pdf pages\n * @returns task contains the new pdf file content\n */\n extractPages: (doc: PdfDocumentObject, pageIndexes: number[]) => PdfTask<ArrayBuffer>;\n /**\n * Extract text on specified pdf pages\n * @param doc - pdf document\n * @param pageIndexes - indexes of pdf pages\n * @returns task contains the text\n */\n extractText: (doc: PdfDocumentObject, pageIndexes: number[]) => PdfTask<string>;\n /**\n * Extract text on specified pdf pages\n * @param doc - pdf document\n * @param pageIndexes - indexes of pdf pages\n * @returns task contains the text\n */\n getTextSlices: (doc: PdfDocumentObject, slices: PageTextSlice[]) => PdfTask<string[]>;\n /**\n * Get all glyphs in the specified pdf page\n * @param doc - pdf document\n * @param page - pdf page\n * @returns task contains the glyphs\n */\n getPageGlyphs: (doc: PdfDocumentObject, page: PdfPageObject) => PdfTask<PdfGlyphObject[]>;\n /**\n * Get the geometry of the specified pdf page\n * @param doc - pdf document\n * @param page - pdf page\n * @returns task contains the geometry\n */\n getPageGeometry: (doc: PdfDocumentObject, page: PdfPageObject) => PdfTask<PdfPageGeometry>;\n /**\n * Merge multiple pdf documents\n * @param files - all the pdf files\n * @returns task contains the merged pdf file\n */\n merge: (files: PdfFile[]) => PdfTask<PdfFile>;\n /**\n * Merge specific pages from multiple PDF documents in a custom order\n * @param mergeConfigs Array of configurations specifying which pages to merge from which documents\n * @returns A PdfTask that resolves with the merged PDF file\n * @public\n */\n mergePages: (mergeConfigs: Array<{ docId: string; pageIndices: number[] }>) => PdfTask<PdfFile>;\n /**\n * Save a copy of pdf document\n * @param doc - pdf document\n * @returns task contains the new pdf file content\n */\n saveAsCopy: (doc: PdfDocumentObject) => PdfTask<ArrayBuffer>;\n /**\n * Close pdf document\n * @param doc - pdf document\n * @returns task that file is closed or not\n */\n closeDocument: (doc: PdfDocumentObject) => PdfTask<boolean>;\n}\n\n/**\n * Method name of PdfEngine interface\n *\n * @public\n */\nexport type PdfEngineMethodName = keyof Required<PdfEngine>;\n\n/**\n * Arguments of PdfEngine method\n *\n * @public\n */\nexport type PdfEngineMethodArgs<P extends PdfEngineMethodName> = Readonly<\n Parameters<Required<PdfEngine>[P]>\n>;\n\n/**\n * Return type of PdfEngine method\n *\n * @public\n */\nexport type PdfEngineMethodReturnType<P extends PdfEngineMethodName> = ReturnType<\n Required<PdfEngine>[P]\n>;\n","/**\n * Library contains the common definitions of data types and logic\n *\n * @remarks\n * The `@embedpdf/models` defines the interface and classes which are used to\n * handling PDF files.\n *\n * @packageDocumentation\n */\nexport * from './geometry';\nexport * from './logger';\nexport * from './pdf';\nexport * from './task';\n\n/**\n * ignore will do nothing when called.\n *\n * @public\n */\nexport function ignore() {}\n","import { Action } from '@embedpdf/core';\nimport { PdfAnnotationObject, PdfAlphaColor, PdfAnnotationSubtype } from '@embedpdf/models';\nimport { SelectedAnnotation } from './types';\n\nexport const SET_ANNOTATIONS = 'SET_ANNOTATIONS';\nexport const SELECT_ANNOTATION = 'SELECT_ANNOTATION';\nexport const DESELECT_ANNOTATION = 'DESELECT_ANNOTATION';\nexport const SET_ANNOTATION_MODE = 'SET_ANNOTATION_MODE';\nexport const UPDATE_ANNOTATION_COLOR = 'UPDATE_ANNOTATION_COLOR';\n\nexport interface SetAnnotationsAction extends Action {\n type: typeof SET_ANNOTATIONS;\n payload: Record<number, PdfAnnotationObject[]>;\n}\n\nexport interface SelectAnnotationAction extends Action {\n type: typeof SELECT_ANNOTATION;\n payload: SelectedAnnotation;\n}\n\nexport interface DeselectAnnotationAction extends Action {\n type: typeof DESELECT_ANNOTATION;\n}\n\nexport interface SetAnnotationModeAction extends Action {\n type: typeof SET_ANNOTATION_MODE;\n payload: PdfAnnotationSubtype | null;\n}\n\nexport interface UpdateAnnotationColorAction extends Action {\n type: typeof UPDATE_ANNOTATION_COLOR;\n payload: {\n pageIndex: number;\n annotationId: number;\n color: PdfAlphaColor;\n };\n}\n\nexport type AnnotationAction =\n | SetAnnotationsAction\n | SelectAnnotationAction\n | DeselectAnnotationAction\n | SetAnnotationModeAction\n | UpdateAnnotationColorAction;\n\nexport function setAnnotations(\n payload: Record<number, PdfAnnotationObject[]>,\n): SetAnnotationsAction {\n return { type: SET_ANNOTATIONS, payload };\n}\n\nexport function selectAnnotation(\n pageIndex: number,\n annotationId: number,\n annotation: PdfAnnotationObject,\n): SelectAnnotationAction {\n return {\n type: SELECT_ANNOTATION,\n payload: { pageIndex, annotationId, annotation },\n };\n}\n\nexport function deselectAnnotation(): DeselectAnnotationAction {\n return { type: DESELECT_ANNOTATION };\n}\n\nexport function setAnnotationMode(mode: PdfAnnotationSubtype | null): SetAnnotationModeAction {\n return {\n type: SET_ANNOTATION_MODE,\n payload: mode,\n };\n}\n\nexport function updateAnnotationColor(\n pageIndex: number,\n annotationId: number,\n color: PdfAlphaColor,\n): UpdateAnnotationColorAction {\n return {\n type: UPDATE_ANNOTATION_COLOR,\n payload: { pageIndex, annotationId, color },\n };\n}\n","import { Reducer } from '@embedpdf/core';\nimport { PdfAnnotationSubtype } from '@embedpdf/models';\nimport {\n AnnotationAction,\n SET_ANNOTATIONS,\n SELECT_ANNOTATION,\n DESELECT_ANNOTATION,\n SET_ANNOTATION_MODE,\n UPDATE_ANNOTATION_COLOR,\n} from './actions';\nimport { AnnotationState } from './types';\n\nexport const initialState: AnnotationState = {\n annotations: {},\n selectedAnnotation: null,\n annotationMode: null,\n};\n\nexport const reducer: Reducer<AnnotationState, AnnotationAction> = (state, action) => {\n switch (action.type) {\n case SET_ANNOTATIONS:\n return {\n ...state,\n annotations: action.payload,\n // Clear selection if the annotations have changed\n selectedAnnotation: null,\n };\n\n case SELECT_ANNOTATION:\n return {\n ...state,\n selectedAnnotation: action.payload,\n };\n\n case DESELECT_ANNOTATION:\n return {\n ...state,\n selectedAnnotation: null,\n };\n\n case SET_ANNOTATION_MODE:\n return {\n ...state,\n annotationMode: action.payload,\n };\n\n case UPDATE_ANNOTATION_COLOR: {\n const { pageIndex, annotationId, color } = action.payload;\n const pageAnnotations = state.annotations[pageIndex];\n\n if (!pageAnnotations) {\n return state;\n }\n\n const updatedAnnotations = pageAnnotations.map((annotation) => {\n if (annotation.id === annotationId) {\n // Only update color for annotations that support it (highlights, etc.)\n if (annotation.type === PdfAnnotationSubtype.HIGHLIGHT) {\n return {\n ...annotation,\n color,\n };\n }\n }\n return annotation;\n });\n\n const newAnnotations = {\n ...state.annotations,\n [pageIndex]: updatedAnnotations,\n };\n\n // Update selected annotation if it matches\n let newSelectedAnnotation = state.selectedAnnotation;\n if (\n newSelectedAnnotation &&\n newSelectedAnnotation.pageIndex === pageIndex &&\n newSelectedAnnotation.annotationId === annotationId\n ) {\n const updatedAnnotation = updatedAnnotations.find((a) => a.id === annotationId);\n if (updatedAnnotation) {\n newSelectedAnnotation = {\n ...newSelectedAnnotation,\n annotation: updatedAnnotation,\n };\n }\n }\n\n return {\n ...state,\n annotations: newAnnotations,\n selectedAnnotation: newSelectedAnnotation,\n };\n }\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, ANNOTATION_PLUGIN_ID } from './manifest';\nimport { AnnotationPluginConfig, AnnotationState } from './types';\nimport { AnnotationPlugin } from './annotation-plugin';\nimport { initialState, reducer } from './reducer';\nimport { AnnotationAction } from './actions';\n\nexport const AnnotationPluginPackage: PluginPackage<\n AnnotationPlugin,\n AnnotationPluginConfig,\n AnnotationState,\n AnnotationAction\n> = {\n manifest,\n create: (registry, engine) => new AnnotationPlugin(ANNOTATION_PLUGIN_ID, registry, engine),\n reducer,\n initialState,\n};\n\nexport * from './annotation-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"mappings":"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","names":["PdfAnnotationSubtype"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/lib/manifest.ts","../src/lib/annotation-plugin.ts","../src/lib/actions.ts","../src/lib/utils.ts","../src/lib/selectors.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["export * from './lib';\n","import { PluginManifest } from '@embedpdf/core';\nimport { AnnotationPluginConfig } from './types';\n\nexport const ANNOTATION_PLUGIN_ID = 'annotation';\n\nexport const manifest: PluginManifest<AnnotationPluginConfig> = {\n id: ANNOTATION_PLUGIN_ID,\n name: 'Annotation Plugin',\n version: '1.0.0',\n provides: ['annotation'],\n requires: ['interaction-manager', 'selection'],\n optional: ['history'],\n defaultConfig: {\n enabled: true,\n autoCommit: true,\n },\n};\n","import {\n BasePlugin,\n createBehaviorEmitter,\n enumEntries,\n PluginRegistry,\n SET_DOCUMENT,\n} from '@embedpdf/core';\nimport {\n ignore,\n PdfAnnotationObject,\n PdfDocumentObject,\n PdfEngine,\n PdfErrorReason,\n Task,\n PdfAnnotationSubtype,\n PdfTaskHelper,\n PdfErrorCode,\n PdfTask,\n} from '@embedpdf/models';\nimport {\n ActiveTool,\n AnnotationCapability,\n AnnotationPluginConfig,\n AnnotationState,\n BaseAnnotationDefaults,\n GetPageAnnotationsOptions,\n StylableSubtype,\n TrackedAnnotation,\n} from './types';\nimport {\n setAnnotations,\n selectAnnotation,\n deselectAnnotation,\n setAnnotationMode,\n AnnotationAction,\n updateToolDefaults,\n addColorPreset,\n createAnnotation,\n patchAnnotation,\n deleteAnnotation,\n commitPendingChanges,\n storePdfId,\n purgeAnnotation,\n reindexPageAnnotations,\n} from './actions';\nimport {\n InteractionManagerCapability,\n InteractionManagerPlugin,\n InteractionMode,\n} from '@embedpdf/plugin-interaction-manager';\nimport { SelectionPlugin, SelectionCapability } from '@embedpdf/plugin-selection';\nimport { HistoryPlugin, HistoryCapability, Command } from '@embedpdf/plugin-history';\nimport { getSelectedAnnotation } from './selectors';\nimport { makeUid, parseUid } from './utils';\n\nexport class AnnotationPlugin extends BasePlugin<\n AnnotationPluginConfig,\n AnnotationCapability,\n AnnotationState,\n AnnotationAction\n> {\n static readonly id = 'annotation' as const;\n\n private readonly ANNOTATION_HISTORY_TOPIC = 'annotations';\n\n private readonly config: AnnotationPluginConfig;\n\n private engine: PdfEngine;\n private readonly state$ = createBehaviorEmitter<AnnotationState>();\n private readonly interactionManager: InteractionManagerCapability | null;\n private readonly selection: SelectionCapability | null;\n private readonly history: HistoryCapability | null;\n\n /** Map <subtype> → <modeId>. Filled once in `initialize()`. */\n private readonly modeBySubtype = new Map<StylableSubtype, string>();\n /** The inverse map for quick lookup in onModeChange(). */\n private readonly subtypeByMode = new Map<string, StylableSubtype>();\n private readonly modeChange$ = createBehaviorEmitter<StylableSubtype | null>();\n private readonly activeTool$ = createBehaviorEmitter<ActiveTool>({\n mode: null,\n defaults: null,\n });\n\n constructor(\n id: string,\n registry: PluginRegistry,\n engine: PdfEngine,\n config: AnnotationPluginConfig,\n ) {\n super(id, registry);\n this.engine = engine;\n this.config = config;\n\n const selection = registry.getPlugin<SelectionPlugin>('selection');\n this.selection = selection?.provides() ?? null;\n\n const history = registry.getPlugin<HistoryPlugin>('history');\n this.history = history?.provides() ?? null;\n\n const interactionManager = registry.getPlugin<InteractionManagerPlugin>('interaction-manager');\n this.interactionManager = interactionManager?.provides() ?? null;\n\n this.coreStore.onAction(SET_DOCUMENT, (_action, state) => {\n const doc = state.core.document;\n if (doc) {\n this.getAllAnnotations(doc);\n }\n });\n }\n\n async initialize(): Promise<void> {\n for (const [subtype, defaults] of enumEntries(this.state.toolDefaults)) {\n this.registerTool(subtype, defaults);\n }\n\n this.history?.onHistoryChange((topic) => {\n if (topic === this.ANNOTATION_HISTORY_TOPIC && this.config.autoCommit !== false) {\n this.commit();\n }\n });\n\n this.interactionManager?.onModeChange((s) => {\n const newSubtype = this.subtypeByMode.get(s.activeMode) ?? null;\n if (newSubtype !== this.state.annotationMode) {\n this.dispatch(setAnnotationMode(newSubtype));\n this.modeChange$.emit(newSubtype);\n }\n });\n\n this.selection?.onEndSelection(() => {\n if (!this.state.annotationMode) return;\n\n const formattedSelection = this.selection?.getFormattedSelection();\n if (!formattedSelection) return;\n\n for (const selection of formattedSelection) {\n const rect = selection.rect;\n const segmentRects = selection.segmentRects;\n const type = this.state.annotationMode;\n const color = this.state.toolDefaults[type].color;\n const opacity = this.state.toolDefaults[type].opacity;\n\n this.createAnnotation(selection.pageIndex, {\n type,\n rect,\n segmentRects,\n color,\n opacity,\n pageIndex: selection.pageIndex,\n id: Date.now() + Math.random(),\n });\n }\n\n this.selection?.clear();\n });\n }\n\n private registerTool(subtype: StylableSubtype, defaults: BaseAnnotationDefaults) {\n const modeId = defaults.interaction.mode;\n const interactionMode: InteractionMode = {\n id: modeId,\n scope: 'page',\n exclusive: defaults.interaction.exclusive,\n cursor: defaults.interaction.cursor,\n };\n\n this.interactionManager?.registerMode(interactionMode);\n\n if (defaults.textSelection) {\n this.selection?.enableForMode(modeId);\n }\n this.modeBySubtype.set(subtype, modeId);\n this.subtypeByMode.set(modeId, subtype);\n }\n\n protected buildCapability(): AnnotationCapability {\n return {\n getPageAnnotations: (options: GetPageAnnotationsOptions) => {\n return this.getPageAnnotations(options);\n },\n getSelectedAnnotation: () => {\n return getSelectedAnnotation(this.state);\n },\n selectAnnotation: (pageIndex: number, annotationId: number) => {\n this.selectAnnotation(pageIndex, annotationId);\n },\n deselectAnnotation: () => {\n this.dispatch(deselectAnnotation());\n },\n getAnnotationMode: () => {\n return this.state.annotationMode;\n },\n setAnnotationMode: (subtype: StylableSubtype | null) => {\n if (subtype === this.state.annotationMode) return;\n if (subtype) {\n const mode = this.modeBySubtype.get(subtype);\n if (!mode) throw new Error(`Mode missing for subtype ${subtype}`);\n this.interactionManager?.activate(mode);\n } else {\n this.interactionManager?.activate('default');\n }\n },\n getToolDefaults: (subtype) => {\n const defaults = this.state.toolDefaults[subtype];\n if (!defaults) {\n throw new Error(`No defaults found for subtype: ${subtype}`);\n }\n return defaults;\n },\n setToolDefaults: (subtype, patch) => {\n this.dispatch(updateToolDefaults(subtype, patch));\n },\n getColorPresets: () => [...this.state.colorPresets],\n addColorPreset: (color) => this.dispatch(addColorPreset(color)),\n createAnnotation: (pageIndex: number, annotation: PdfAnnotationObject) =>\n this.createAnnotation(pageIndex, annotation),\n updateAnnotation: (pageIndex: number, localId: number, patch: Partial<PdfAnnotationObject>) =>\n this.updateAnnotation(pageIndex, localId, patch),\n deleteAnnotation: (pageIndex: number, localId: number) =>\n this.deleteAnnotation(pageIndex, localId),\n onStateChange: this.state$.on,\n onModeChange: this.modeChange$.on,\n onActiveToolChange: this.activeTool$.on,\n commit: () => this.commit(),\n };\n }\n\n private emitActiveTool(state: AnnotationState) {\n const mode = state.annotationMode;\n this.activeTool$.emit({\n mode,\n defaults: mode ? state.toolDefaults[mode] : null,\n });\n }\n\n override onStoreUpdated(prev: AnnotationState, next: AnnotationState): void {\n this.state$.emit(next);\n if (\n prev.annotationMode !== next.annotationMode ||\n prev.toolDefaults[prev.annotationMode ?? PdfAnnotationSubtype.HIGHLIGHT] !==\n next.toolDefaults[next.annotationMode ?? PdfAnnotationSubtype.HIGHLIGHT]\n ) {\n this.emitActiveTool(next);\n }\n }\n\n private getAllAnnotations(doc: PdfDocumentObject) {\n const task = this.engine.getAllAnnotations(doc);\n task.wait((annotations) => this.dispatch(setAnnotations(annotations)), ignore);\n }\n\n private getPageAnnotations(\n options: GetPageAnnotationsOptions,\n ): Task<PdfAnnotationObject[], PdfErrorReason> {\n const { pageIndex } = options;\n\n const doc = this.coreState.core.document;\n\n if (!doc) {\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n }\n\n const page = doc.pages.find((p) => p.index === pageIndex);\n\n if (!page) {\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Page not found' });\n }\n\n return this.engine.getPageAnnotations(doc, page);\n }\n\n private selectAnnotation(pageIndex: number, annotationId: number) {\n this.dispatch(selectAnnotation(pageIndex, annotationId));\n }\n\n private createAnnotation(pageIndex: number, annotation: PdfAnnotationObject) {\n const localId = annotation.id;\n const execute = () => this.dispatch(createAnnotation(pageIndex, localId, annotation));\n\n if (!this.history) {\n execute();\n if (this.config.autoCommit) this.commit();\n return;\n }\n const command: Command = {\n execute,\n undo: () => {\n this.dispatch(deselectAnnotation());\n this.dispatch(deleteAnnotation(pageIndex, localId));\n },\n };\n this.history.register(command, this.ANNOTATION_HISTORY_TOPIC);\n }\n\n private updateAnnotation(\n pageIndex: number,\n localId: number,\n patch: Partial<PdfAnnotationObject>,\n ) {\n if (!this.history) {\n this.dispatch(patchAnnotation(pageIndex, localId, patch));\n if (this.config.autoCommit !== false) {\n this.commit();\n }\n return;\n }\n const originalObject = this.state.byUid[makeUid(pageIndex, localId)].object;\n const originalPatch = Object.fromEntries(\n Object.keys(patch).map((key) => [key, originalObject[key as keyof PdfAnnotationObject]]),\n );\n const command: Command = {\n execute: () => this.dispatch(patchAnnotation(pageIndex, localId, patch)),\n undo: () => this.dispatch(patchAnnotation(pageIndex, localId, originalPatch)),\n };\n this.history.register(command, this.ANNOTATION_HISTORY_TOPIC);\n }\n\n private deleteAnnotation(pageIndex: number, localId: number) {\n if (!this.history) {\n this.dispatch(deselectAnnotation());\n this.dispatch(deleteAnnotation(pageIndex, localId));\n if (this.config.autoCommit !== false) {\n this.commit();\n }\n return;\n }\n const originalAnnotation = this.state.byUid[makeUid(pageIndex, localId)].object;\n const command: Command = {\n execute: () => {\n this.dispatch(deselectAnnotation());\n this.dispatch(deleteAnnotation(pageIndex, localId));\n },\n undo: () => this.dispatch(createAnnotation(pageIndex, localId, originalAnnotation)),\n };\n this.history.register(command, this.ANNOTATION_HISTORY_TOPIC);\n }\n\n private commit(): Task<boolean, PdfErrorReason> {\n const task = new Task<boolean, PdfErrorReason>();\n\n if (!this.state.hasPendingChanges) return PdfTaskHelper.resolve(true);\n\n const doc = this.coreState.core.document;\n if (!doc)\n return PdfTaskHelper.reject({ code: PdfErrorCode.NotFound, message: 'Document not found' });\n\n const creations: Task<any, PdfErrorReason>[] = [];\n const updates: Task<any, PdfErrorReason>[] = [];\n const deletionsByPage = new Map<number, { ta: TrackedAnnotation; uid: string }[]>();\n const affectedPages = new Set<number>();\n\n // 1. Group all pending changes by operation type\n for (const [uid, ta] of Object.entries(this.state.byUid)) {\n if (ta.commitState === 'synced') continue;\n\n const { pageIndex } = parseUid(uid);\n const page = doc.pages.find((p) => p.index === pageIndex);\n if (!page) continue;\n\n affectedPages.add(pageIndex);\n\n switch (ta.commitState) {\n case 'new':\n const task = this.engine.createPageAnnotation!(doc, page, ta.object);\n task.wait((annoId) => this.dispatch(storePdfId(uid, annoId)), ignore);\n creations.push(task);\n break;\n case 'dirty':\n updates.push(\n this.engine.updatePageAnnotation!(doc, page, { ...ta.object, id: ta.pdfId! }),\n );\n break;\n case 'deleted':\n if (!deletionsByPage.has(pageIndex)) {\n deletionsByPage.set(pageIndex, []);\n }\n deletionsByPage.get(pageIndex)!.push({ ta, uid });\n break;\n }\n }\n\n // 2. Create deletion tasks, sorted by ID descending\n const deletionTasks: Task<any, PdfErrorReason>[] = [];\n for (const [pageIndex, deletions] of deletionsByPage.entries()) {\n const page = doc.pages.find((p) => p.index === pageIndex)!;\n\n deletions.sort((a, b) => (b.ta.pdfId ?? -1) - (a.ta.pdfId ?? -1));\n\n for (const { ta, uid } of deletions) {\n if (ta.pdfId !== undefined) {\n const task = new Task<any, PdfErrorReason>();\n const removeTask = this.engine.removePageAnnotation!(doc, page, {\n ...ta.object,\n id: ta.pdfId!,\n });\n removeTask.wait(() => {\n this.dispatch(purgeAnnotation(uid));\n task.resolve(true);\n }, task.fail);\n deletionTasks.push(task);\n } else {\n this.dispatch(purgeAnnotation(uid));\n }\n }\n }\n\n // 3. Chain the operations: creations/updates -> deletions -> re-sync\n const allWriteTasks = [...creations, ...updates, ...deletionTasks];\n\n Task.allSettled(allWriteTasks).wait(() => {\n // 4. Client-Side Re-indexing\n // After all engine operations are done, tell the reducer to re-index each affected page.\n for (const pageIndex of affectedPages) {\n this.dispatch(reindexPageAnnotations(pageIndex));\n }\n\n // 5. Finalize the commit by updating the commitState of all items.\n this.dispatch(commitPendingChanges());\n task.resolve(true);\n }, task.fail);\n\n return task;\n }\n}\n","import { Action } from '@embedpdf/core';\nimport { PdfAnnotationObject } from '@embedpdf/models';\nimport { StylableSubtype, ToolDefaultsBySubtype } from './types';\n\n/* ─────────── action constants ─────────── */\nexport const SET_ANNOTATIONS = 'ANNOTATION/SET_ANNOTATIONS';\nexport const REINDEX_PAGE_ANNOTATIONS = 'ANNOTATION/REINDEX_PAGE';\nexport const SELECT_ANNOTATION = 'ANNOTATION/SELECT_ANNOTATION';\nexport const DESELECT_ANNOTATION = 'ANNOTATION/DESELECT_ANNOTATION';\nexport const SET_ANNOTATION_MODE = 'ANNOTATION/SET_ANNOTATION_MODE';\nexport const UPDATE_TOOL_DEFAULTS = 'ANNOTATION/UPDATE_TOOL_DEFAULTS';\nexport const ADD_COLOR_PRESET = 'ANNOTATION/ADD_COLOR_PRESET';\nexport const CREATE_ANNOTATION = 'ANNOTATION/CREATE_ANNOTATION';\nexport const PATCH_ANNOTATION = 'ANNOTATION/PATCH_ANNOTATION';\nexport const DELETE_ANNOTATION = 'ANNOTATION/DELETE_ANNOTATION';\nexport const COMMIT_PENDING_CHANGES = 'ANNOTATION/COMMIT';\nexport const STORE_PDF_ID = 'ANNOTATION/STORE_PDF_ID';\nexport const PURGE_ANNOTATION = 'ANNOTATION/PURGE_ANNOTATION';\n\n/* ─────────── action interfaces ─────────── */\nexport interface SetAnnotationsAction extends Action {\n type: typeof SET_ANNOTATIONS;\n payload: Record<number, PdfAnnotationObject[]>;\n}\nexport interface ReindexPageAnnotationsAction extends Action {\n type: typeof REINDEX_PAGE_ANNOTATIONS;\n payload: { pageIndex: number };\n}\nexport interface SelectAnnotationAction extends Action {\n type: typeof SELECT_ANNOTATION;\n payload: { pageIndex: number; localId: number };\n}\nexport interface DeselectAnnotationAction extends Action {\n type: typeof DESELECT_ANNOTATION;\n}\nexport interface SetAnnotationModeAction extends Action {\n type: typeof SET_ANNOTATION_MODE;\n payload: StylableSubtype | null;\n}\n\nexport interface UpdateToolDefaultsAction extends Action {\n type: typeof UPDATE_TOOL_DEFAULTS;\n payload: { subtype: StylableSubtype; patch: Partial<ToolDefaultsBySubtype[StylableSubtype]> };\n}\n\nexport interface AddColorPresetAction extends Action {\n type: typeof ADD_COLOR_PRESET;\n payload: string;\n}\nexport interface CreateAnnotationAction extends Action {\n type: typeof CREATE_ANNOTATION;\n payload: { pageIndex: number; localId: number; annotation: PdfAnnotationObject };\n}\nexport interface PatchAnnotationAction extends Action {\n type: typeof PATCH_ANNOTATION;\n payload: { pageIndex: number; localId: number; patch: Partial<PdfAnnotationObject> };\n}\nexport interface DeleteAnnotationAction extends Action {\n type: typeof DELETE_ANNOTATION;\n payload: { pageIndex: number; localId: number };\n}\nexport interface CommitAction extends Action {\n type: typeof COMMIT_PENDING_CHANGES;\n}\n\nexport interface StorePdfIdAction extends Action {\n type: typeof STORE_PDF_ID;\n payload: { uid: string; pdfId: number };\n}\n\nexport interface PurgeAnnotationAction extends Action {\n type: typeof PURGE_ANNOTATION;\n payload: { uid: string };\n}\n\nexport type AnnotationAction =\n | SetAnnotationsAction\n | ReindexPageAnnotationsAction\n | SelectAnnotationAction\n | DeselectAnnotationAction\n | SetAnnotationModeAction\n | UpdateToolDefaultsAction\n | AddColorPresetAction\n | CreateAnnotationAction\n | PatchAnnotationAction\n | DeleteAnnotationAction\n | CommitAction\n | StorePdfIdAction\n | PurgeAnnotationAction;\n\n/* ─────────── action creators ─────────── */\nexport const setAnnotations = (p: Record<number, PdfAnnotationObject[]>): SetAnnotationsAction => ({\n type: SET_ANNOTATIONS,\n payload: p,\n});\n\nexport const reindexPageAnnotations = (pageIndex: number): ReindexPageAnnotationsAction => ({\n type: REINDEX_PAGE_ANNOTATIONS,\n payload: { pageIndex },\n});\n\nexport const selectAnnotation = (pageIndex: number, localId: number): SelectAnnotationAction => ({\n type: SELECT_ANNOTATION,\n payload: { pageIndex, localId },\n});\n\nexport const deselectAnnotation = (): DeselectAnnotationAction => ({ type: DESELECT_ANNOTATION });\n\nexport const setAnnotationMode = (m: StylableSubtype | null): SetAnnotationModeAction => ({\n type: SET_ANNOTATION_MODE,\n payload: m,\n});\n\nexport const updateToolDefaults = <S extends StylableSubtype>(\n subtype: S,\n patch: Partial<ToolDefaultsBySubtype[S]>,\n): UpdateToolDefaultsAction => ({ type: UPDATE_TOOL_DEFAULTS, payload: { subtype, patch } });\n\nexport const addColorPreset = (c: string): AddColorPresetAction => ({\n type: ADD_COLOR_PRESET,\n payload: c,\n});\n\nexport const createAnnotation = (\n pageIndex: number,\n localId: number,\n annotation: PdfAnnotationObject,\n): CreateAnnotationAction => ({\n type: CREATE_ANNOTATION,\n payload: { pageIndex, localId, annotation },\n});\n\nexport const patchAnnotation = (\n pageIndex: number,\n localId: number,\n patch: Partial<PdfAnnotationObject>,\n): PatchAnnotationAction => ({\n type: PATCH_ANNOTATION,\n payload: { pageIndex, localId, patch },\n});\n\nexport const deleteAnnotation = (pageIndex: number, localId: number): DeleteAnnotationAction => ({\n type: DELETE_ANNOTATION,\n payload: { pageIndex, localId },\n});\n\nexport const commitPendingChanges = (): CommitAction => ({ type: COMMIT_PENDING_CHANGES });\n\nexport const storePdfId = (uid: string, pdfId: number): StorePdfIdAction => ({\n type: STORE_PDF_ID,\n payload: { uid, pdfId },\n});\n\nexport const purgeAnnotation = (uid: string): PurgeAnnotationAction => ({\n type: PURGE_ANNOTATION,\n payload: { uid },\n});\n","/**\n * Creates a stable, document-wide unique ID from a page index and a stable local ID.\n */\nexport const makeUid = (pageIndex: number, localId: number): string => `p${pageIndex}#${localId}`;\n\n/**\n * Parses a UID string back into its constituent page index and stable local ID.\n */\nexport const parseUid = (uid: string): { pageIndex: number; localId: number } => {\n const [pg, rest] = uid.slice(1).split('#');\n return { pageIndex: Number(pg), localId: Number(rest) };\n};\n","import { AnnotationState, SelectedAnnotation } from './types';\nimport { parseUid } from './utils';\n\n/* helper – mirrors the one in reducer */\nconst makeUid = (page: number, id: number) => `p${page}#${id}`;\n\n/* ─────────── public selectors ─────────── */\n\n/** All annotations _objects_ on a single page (order preserved). */\nexport const getAnnotationsByPageIndex = (s: AnnotationState, page: number) =>\n (s.pages[page] ?? []).map((uid) => s.byUid[uid]);\n\n/** Shortcut: every page → list of annotation objects. */\nexport const getAnnotations = (s: AnnotationState) => {\n const out: Record<number, ReturnType<typeof getAnnotationsByPageIndex>> = {};\n for (const p of Object.keys(s.pages).map(Number)) out[p] = getAnnotationsByPageIndex(s, p);\n return out;\n};\n\n/** The full `TrackedAnnotation` for the current selection. */\nexport const getSelectedAnnotation = (s: AnnotationState) =>\n s.selectedUid ? s.byUid[s.selectedUid] : null;\n\nexport const getSelectedAnnotationWithPageIndex = (\n s: AnnotationState,\n): SelectedAnnotation | null => {\n if (!s.selectedUid) return null;\n const { pageIndex, localId } = parseUid(s.selectedUid);\n return { pageIndex, localId, annotation: s.byUid[s.selectedUid].object };\n};\n\nexport const getSelectedAnnotationByPageIndex = (s: AnnotationState, pageIndex: number) => {\n if (!s.selectedUid) return null;\n\n const pageUids = s.pages[pageIndex] ?? [];\n\n // Check if the selected UID is on the requested page\n if (pageUids.includes(s.selectedUid)) {\n return s.byUid[s.selectedUid];\n }\n\n return null;\n};\n\nexport const isInAnnotationMode = (s: AnnotationState) => s.annotationMode !== null;\nexport const getSelectedAnnotationMode = (s: AnnotationState) => s.annotationMode;\n\n/** Check if a given anno on a page is the current selection. */\nexport const isAnnotationSelected = (s: AnnotationState, page: number, id: number) =>\n s.selectedUid === makeUid(page, id);\n","import { Reducer } from '@embedpdf/core';\nimport { PdfAnnotationSubtype } from '@embedpdf/models';\nimport {\n ADD_COLOR_PRESET,\n COMMIT_PENDING_CHANGES,\n CREATE_ANNOTATION,\n DESELECT_ANNOTATION,\n PATCH_ANNOTATION,\n DELETE_ANNOTATION,\n SELECT_ANNOTATION,\n SET_ANNOTATION_MODE,\n SET_ANNOTATIONS,\n UPDATE_TOOL_DEFAULTS,\n AnnotationAction,\n PURGE_ANNOTATION,\n STORE_PDF_ID,\n REINDEX_PAGE_ANNOTATIONS,\n} from './actions';\nimport { AnnotationPluginConfig, AnnotationState, TrackedAnnotation } from './types';\nimport { makeUid } from './utils';\n\n/* ─────────── util helpers ─────────── */\nconst DEFAULT_COLORS = [\n '#E44234',\n '#FF8D00',\n '#FFCD45',\n '#5CC96E',\n '#25D2D1',\n '#597CE2',\n '#C544CE',\n '#7D2E25',\n];\n\n/* helper to immutably replace one annotation (preserving pdfId) */\nconst patchAnno = (\n state: AnnotationState,\n uid: string,\n patch: Partial<TrackedAnnotation['object']>,\n): AnnotationState => {\n const prev = state.byUid[uid];\n if (!prev) return state;\n return {\n ...state,\n byUid: {\n ...state.byUid,\n [uid]: {\n ...prev,\n commitState: prev.commitState === 'synced' ? 'dirty' : prev.commitState,\n object: { ...prev.object, ...patch },\n } as TrackedAnnotation,\n },\n hasPendingChanges: true,\n };\n};\n\n/* ─────────── initialState ─────────── */\nexport const initialState = (cfg: AnnotationPluginConfig): AnnotationState => ({\n pages: {},\n byUid: {},\n selectedUid: null,\n annotationMode: null,\n\n toolDefaults: {\n [PdfAnnotationSubtype.HIGHLIGHT]: {\n name: 'Highlight',\n color: '#FFCD45',\n opacity: 1,\n interaction: { mode: 'highlight', exclusive: false },\n textSelection: true,\n },\n [PdfAnnotationSubtype.UNDERLINE]: {\n name: 'Underline',\n color: '#E44234',\n opacity: 1,\n interaction: { mode: 'underline', exclusive: false },\n textSelection: true,\n },\n [PdfAnnotationSubtype.STRIKEOUT]: {\n name: 'Strikeout',\n color: '#E44234',\n opacity: 1,\n interaction: { mode: 'strikeout', exclusive: false },\n textSelection: true,\n },\n [PdfAnnotationSubtype.SQUIGGLY]: {\n name: 'Squiggly',\n color: '#E44234',\n opacity: 1,\n interaction: { mode: 'squiggly', exclusive: false },\n textSelection: true,\n },\n ...cfg.toolDefaults,\n },\n colorPresets: cfg.colorPresets ?? DEFAULT_COLORS,\n hasPendingChanges: false,\n});\n\n/* ─────────── reducer ─────────── */\nexport const reducer: Reducer<AnnotationState, AnnotationAction> = (state, action) => {\n switch (action.type) {\n /* ───── bulk load from engine ───── */\n case SET_ANNOTATIONS: {\n const newPages = { ...state.pages };\n const newByUid = { ...state.byUid };\n for (const [pgStr, list] of Object.entries(action.payload)) {\n const pageIndex = Number(pgStr);\n const oldUidsOnPage = state.pages[pageIndex] || [];\n for (const uid of oldUidsOnPage) {\n delete newByUid[uid];\n }\n const newUidsOnPage = list.map((a, index) => {\n const localId = Date.now() + Math.random() + index;\n const uid = makeUid(pageIndex, localId);\n newByUid[uid] = { localId, pdfId: a.id, commitState: 'synced', object: a };\n return uid;\n });\n newPages[pageIndex] = newUidsOnPage;\n }\n return { ...state, pages: newPages, byUid: newByUid };\n }\n\n /* ───── GUI bits ───── */\n case SET_ANNOTATION_MODE:\n return { ...state, annotationMode: action.payload };\n case SELECT_ANNOTATION:\n return {\n ...state,\n selectedUid: makeUid(action.payload.pageIndex, action.payload.localId),\n };\n case DESELECT_ANNOTATION:\n return { ...state, selectedUid: null };\n\n case ADD_COLOR_PRESET:\n return state.colorPresets.includes(action.payload)\n ? state\n : { ...state, colorPresets: [...state.colorPresets, action.payload] };\n\n case UPDATE_TOOL_DEFAULTS: {\n const { subtype, patch } = action.payload;\n return {\n ...state,\n toolDefaults: {\n ...state.toolDefaults,\n [subtype]: { ...state.toolDefaults[subtype], ...patch },\n },\n };\n }\n\n /* ───── create ───── */\n case CREATE_ANNOTATION: {\n const { pageIndex, localId, annotation } = action.payload;\n const uid = makeUid(pageIndex, localId);\n\n return {\n ...state,\n pages: { ...state.pages, [pageIndex]: [...(state.pages[pageIndex] ?? []), uid] },\n byUid: {\n ...state.byUid,\n [uid]: { localId, pdfId: undefined, commitState: 'new', object: annotation },\n },\n hasPendingChanges: true,\n };\n }\n\n /* ───── delete ───── */\n case DELETE_ANNOTATION: {\n const { pageIndex, localId } = action.payload;\n const uid = makeUid(pageIndex, localId);\n if (!state.byUid[uid]) return state;\n\n /* keep the object but mark it as deleted */\n return {\n ...state,\n pages: {\n ...state.pages,\n [pageIndex]: (state.pages[pageIndex] ?? []).filter((u) => u !== uid),\n },\n byUid: {\n ...state.byUid,\n [uid]: { ...state.byUid[uid], commitState: 'deleted' },\n },\n hasPendingChanges: true,\n };\n }\n\n /* ───── field edits ───── */\n case PATCH_ANNOTATION: {\n const uid = makeUid(action.payload.pageIndex, action.payload.localId);\n return patchAnno(state, uid, action.payload.patch);\n }\n\n /* ───── commit bookkeeping ───── */\n case COMMIT_PENDING_CHANGES: {\n const cleaned: AnnotationState['byUid'] = {};\n for (const [uid, ta] of Object.entries(state.byUid)) {\n cleaned[uid] = {\n ...ta,\n commitState:\n ta.commitState === 'dirty' || ta.commitState === 'new' ? 'synced' : ta.commitState,\n };\n }\n return { ...state, byUid: cleaned, hasPendingChanges: false };\n }\n\n case REINDEX_PAGE_ANNOTATIONS: {\n const { pageIndex } = action.payload;\n const newByUid = { ...state.byUid };\n\n const uidsOnPage = state.pages[pageIndex] || [];\n const annosOnPage = uidsOnPage\n .map((uid) => state.byUid[uid])\n .filter((ta) => ta && ta.commitState !== 'deleted'); // Filter out annotations pending deletion\n\n // CORRECTED: Sort by the existing pdfId to maintain relative order.\n annosOnPage.sort((a, b) => (a.pdfId ?? Infinity) - (b.pdfId ?? Infinity));\n\n // Update the pdfId for each annotation based on its new sorted index\n annosOnPage.forEach((ta, newPdfId) => {\n const uid = makeUid(pageIndex, ta.localId);\n newByUid[uid] = { ...newByUid[uid], pdfId: newPdfId };\n });\n\n return { ...state, byUid: newByUid };\n }\n\n case STORE_PDF_ID: {\n const { uid, pdfId } = action.payload;\n\n const ta = state.byUid[uid];\n if (!ta) return state;\n return {\n ...state,\n byUid: {\n ...state.byUid,\n [uid]: { ...ta, pdfId, commitState: 'synced' },\n },\n };\n }\n\n case PURGE_ANNOTATION: {\n const { uid } = action.payload;\n const { [uid]: _gone, ...rest } = state.byUid;\n return { ...state, byUid: rest };\n }\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, ANNOTATION_PLUGIN_ID } from './manifest';\nimport { AnnotationPluginConfig, AnnotationState } from './types';\nimport { AnnotationPlugin } from './annotation-plugin';\nimport { initialState, reducer } from './reducer';\nimport { AnnotationAction } from './actions';\n\nexport const AnnotationPluginPackage: PluginPackage<\n AnnotationPlugin,\n AnnotationPluginConfig,\n AnnotationState,\n AnnotationAction\n> = {\n manifest,\n create: (registry, engine, config) =>\n new AnnotationPlugin(ANNOTATION_PLUGIN_ID, registry, engine, config),\n reducer,\n initialState: (_, config) => initialState(config),\n};\n\nexport * from './annotation-plugin';\nexport * from './types';\nexport * from './manifest';\nexport * from './selectors';\n"],"mappings":"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","names":["makeUid","task","import_models"]}
package/dist/index.d.cts CHANGED
@@ -1,82 +1,244 @@
1
1
  import { BasePluginConfig, EventHook, Action, BasePlugin, PluginRegistry, PluginManifest, PluginPackage } from '@embedpdf/core';
2
- import { Task, PdfAnnotationObject, PdfErrorReason, PdfAlphaColor, PdfAnnotationSubtype, PdfEngine } from '@embedpdf/models';
2
+ import { PdfAnnotationSubtype, WebAlphaColor, Task, PdfAnnotationObject, PdfErrorReason, PdfEngine } from '@embedpdf/models';
3
3
 
4
- interface AnnotationState {
5
- annotations: Record<number, PdfAnnotationObject[]>;
6
- selectedAnnotation: SelectedAnnotation | null;
7
- annotationMode: PdfAnnotationSubtype | null;
4
+ type CommitState = 'new' | 'dirty' | 'deleted' | 'synced' | 'ignored';
5
+ interface TrackedAnnotation {
6
+ /** A stable, client-side unique identifier for history and state management. */
7
+ localId: number;
8
+ /**
9
+ * If the engine has already created the annotation in the PDF
10
+ * this is the definitive id coming from the engine.
11
+ * It is **never** cleared once set.
12
+ */
13
+ pdfId?: number;
14
+ /** local commit bookkeeping */
15
+ commitState: CommitState;
16
+ /** the actual annotation object */
17
+ object: PdfAnnotationObject;
8
18
  }
9
- interface SelectedAnnotation {
10
- pageIndex: number;
11
- annotationId: number;
12
- annotation: PdfAnnotationObject;
19
+ interface BaseAnnotationDefaults extends WebAlphaColor {
20
+ interaction: {
21
+ mode: string;
22
+ exclusive: boolean;
23
+ cursor?: string;
24
+ };
25
+ textSelection?: boolean;
26
+ }
27
+ interface HighlightDefaults extends BaseAnnotationDefaults {
28
+ name: 'Highlight';
29
+ }
30
+ interface UnderlineDefaults extends BaseAnnotationDefaults {
31
+ name: 'Underline';
32
+ }
33
+ interface StrikeoutDefaults extends BaseAnnotationDefaults {
34
+ name: 'Strikeout';
35
+ }
36
+ interface SquigglyDefaults extends BaseAnnotationDefaults {
37
+ name: 'Squiggly';
38
+ }
39
+ type AnnotationDefaults = HighlightDefaults | UnderlineDefaults | StrikeoutDefaults | SquigglyDefaults;
40
+ type ToolDefaultsBySubtype = {
41
+ [PdfAnnotationSubtype.HIGHLIGHT]: HighlightDefaults;
42
+ [PdfAnnotationSubtype.UNDERLINE]: UnderlineDefaults;
43
+ [PdfAnnotationSubtype.STRIKEOUT]: StrikeoutDefaults;
44
+ [PdfAnnotationSubtype.SQUIGGLY]: SquigglyDefaults;
45
+ };
46
+ type StylableSubtype = keyof ToolDefaultsBySubtype;
47
+ type ToolDefaults<S extends PdfAnnotationSubtype> = ToolDefaultsBySubtype[Extract<S, keyof ToolDefaultsBySubtype>];
48
+ interface ActiveTool {
49
+ mode: StylableSubtype | null;
50
+ defaults: AnnotationDefaults | null;
51
+ }
52
+ interface AnnotationState {
53
+ pages: Record<number, string[]>;
54
+ byUid: Record<string, TrackedAnnotation>;
55
+ selectedUid: string | null;
56
+ annotationMode: StylableSubtype | null;
57
+ toolDefaults: ToolDefaultsBySubtype;
58
+ colorPresets: string[];
59
+ hasPendingChanges: boolean;
13
60
  }
14
61
  interface AnnotationPluginConfig extends BasePluginConfig {
62
+ toolDefaults?: Partial<ToolDefaultsBySubtype>;
63
+ colorPresets?: string[];
64
+ /**
65
+ * When `false` mutations are kept in memory and must be
66
+ * flushed with `commitPendingChanges()`.
67
+ */
68
+ autoCommit?: boolean;
15
69
  }
16
70
  interface AnnotationCapability {
17
71
  getPageAnnotations: (options: GetPageAnnotationsOptions) => Task<PdfAnnotationObject[], PdfErrorReason>;
72
+ getSelectedAnnotation: () => TrackedAnnotation | null;
18
73
  selectAnnotation: (pageIndex: number, annotationId: number) => void;
19
74
  deselectAnnotation: () => void;
20
- updateAnnotationColor: (color: PdfAlphaColor) => Promise<boolean>;
21
- setAnnotationMode: (mode: PdfAnnotationSubtype | null) => void;
75
+ getAnnotationMode: () => StylableSubtype | null;
76
+ setAnnotationMode: (mode: StylableSubtype | null) => void;
77
+ /** strongly typed – only sub-types we have defaults for */
78
+ getToolDefaults: <S extends StylableSubtype>(subtype: S) => ToolDefaultsBySubtype[S];
79
+ /** Partially patch a single tool’s defaults */
80
+ setToolDefaults: <S extends StylableSubtype>(subtype: S, patch: Partial<ToolDefaultsBySubtype[S]>) => void;
81
+ /** current palette – UI just reads this */
82
+ getColorPresets: () => string[];
83
+ /** append a swatch (deduped by RGBA) */
84
+ addColorPreset: (color: string) => void;
85
+ createAnnotation: (pageIndex: number, annotation: PdfAnnotationObject) => void;
86
+ updateAnnotation: (pageIndex: number, annotationId: number, patch: Partial<PdfAnnotationObject>) => void;
87
+ deleteAnnotation: (pageIndex: number, annotationId: number) => void;
88
+ /** undo / redo */
22
89
  onStateChange: EventHook<AnnotationState>;
90
+ onModeChange: EventHook<StylableSubtype | null>;
91
+ onActiveToolChange: EventHook<ActiveTool>;
92
+ commit: () => void;
93
+ }
94
+ interface SelectedAnnotation {
95
+ pageIndex: number;
96
+ localId: number;
97
+ annotation: PdfAnnotationObject;
23
98
  }
24
99
  interface GetPageAnnotationsOptions {
25
100
  pageIndex: number;
26
101
  }
27
- interface UpdateAnnotationColorOptions {
102
+ interface UpdateAnnotationColorOptions extends WebAlphaColor {
28
103
  pageIndex: number;
29
104
  annotationId: number;
30
- color: PdfAlphaColor;
31
105
  }
32
106
 
33
- declare const SET_ANNOTATIONS = "SET_ANNOTATIONS";
34
- declare const SELECT_ANNOTATION = "SELECT_ANNOTATION";
35
- declare const DESELECT_ANNOTATION = "DESELECT_ANNOTATION";
36
- declare const SET_ANNOTATION_MODE = "SET_ANNOTATION_MODE";
37
- declare const UPDATE_ANNOTATION_COLOR = "UPDATE_ANNOTATION_COLOR";
107
+ declare const SET_ANNOTATIONS = "ANNOTATION/SET_ANNOTATIONS";
108
+ declare const REINDEX_PAGE_ANNOTATIONS = "ANNOTATION/REINDEX_PAGE";
109
+ declare const SELECT_ANNOTATION = "ANNOTATION/SELECT_ANNOTATION";
110
+ declare const DESELECT_ANNOTATION = "ANNOTATION/DESELECT_ANNOTATION";
111
+ declare const SET_ANNOTATION_MODE = "ANNOTATION/SET_ANNOTATION_MODE";
112
+ declare const UPDATE_TOOL_DEFAULTS = "ANNOTATION/UPDATE_TOOL_DEFAULTS";
113
+ declare const ADD_COLOR_PRESET = "ANNOTATION/ADD_COLOR_PRESET";
114
+ declare const CREATE_ANNOTATION = "ANNOTATION/CREATE_ANNOTATION";
115
+ declare const PATCH_ANNOTATION = "ANNOTATION/PATCH_ANNOTATION";
116
+ declare const DELETE_ANNOTATION = "ANNOTATION/DELETE_ANNOTATION";
117
+ declare const COMMIT_PENDING_CHANGES = "ANNOTATION/COMMIT";
118
+ declare const STORE_PDF_ID = "ANNOTATION/STORE_PDF_ID";
119
+ declare const PURGE_ANNOTATION = "ANNOTATION/PURGE_ANNOTATION";
38
120
  interface SetAnnotationsAction extends Action {
39
121
  type: typeof SET_ANNOTATIONS;
40
122
  payload: Record<number, PdfAnnotationObject[]>;
41
123
  }
124
+ interface ReindexPageAnnotationsAction extends Action {
125
+ type: typeof REINDEX_PAGE_ANNOTATIONS;
126
+ payload: {
127
+ pageIndex: number;
128
+ };
129
+ }
42
130
  interface SelectAnnotationAction extends Action {
43
131
  type: typeof SELECT_ANNOTATION;
44
- payload: SelectedAnnotation;
132
+ payload: {
133
+ pageIndex: number;
134
+ localId: number;
135
+ };
45
136
  }
46
137
  interface DeselectAnnotationAction extends Action {
47
138
  type: typeof DESELECT_ANNOTATION;
48
139
  }
49
140
  interface SetAnnotationModeAction extends Action {
50
141
  type: typeof SET_ANNOTATION_MODE;
51
- payload: PdfAnnotationSubtype | null;
142
+ payload: StylableSubtype | null;
143
+ }
144
+ interface UpdateToolDefaultsAction extends Action {
145
+ type: typeof UPDATE_TOOL_DEFAULTS;
146
+ payload: {
147
+ subtype: StylableSubtype;
148
+ patch: Partial<ToolDefaultsBySubtype[StylableSubtype]>;
149
+ };
150
+ }
151
+ interface AddColorPresetAction extends Action {
152
+ type: typeof ADD_COLOR_PRESET;
153
+ payload: string;
154
+ }
155
+ interface CreateAnnotationAction extends Action {
156
+ type: typeof CREATE_ANNOTATION;
157
+ payload: {
158
+ pageIndex: number;
159
+ localId: number;
160
+ annotation: PdfAnnotationObject;
161
+ };
162
+ }
163
+ interface PatchAnnotationAction extends Action {
164
+ type: typeof PATCH_ANNOTATION;
165
+ payload: {
166
+ pageIndex: number;
167
+ localId: number;
168
+ patch: Partial<PdfAnnotationObject>;
169
+ };
52
170
  }
53
- interface UpdateAnnotationColorAction extends Action {
54
- type: typeof UPDATE_ANNOTATION_COLOR;
171
+ interface DeleteAnnotationAction extends Action {
172
+ type: typeof DELETE_ANNOTATION;
55
173
  payload: {
56
174
  pageIndex: number;
57
- annotationId: number;
58
- color: PdfAlphaColor;
175
+ localId: number;
59
176
  };
60
177
  }
61
- type AnnotationAction = SetAnnotationsAction | SelectAnnotationAction | DeselectAnnotationAction | SetAnnotationModeAction | UpdateAnnotationColorAction;
178
+ interface CommitAction extends Action {
179
+ type: typeof COMMIT_PENDING_CHANGES;
180
+ }
181
+ interface StorePdfIdAction extends Action {
182
+ type: typeof STORE_PDF_ID;
183
+ payload: {
184
+ uid: string;
185
+ pdfId: number;
186
+ };
187
+ }
188
+ interface PurgeAnnotationAction extends Action {
189
+ type: typeof PURGE_ANNOTATION;
190
+ payload: {
191
+ uid: string;
192
+ };
193
+ }
194
+ type AnnotationAction = SetAnnotationsAction | ReindexPageAnnotationsAction | SelectAnnotationAction | DeselectAnnotationAction | SetAnnotationModeAction | UpdateToolDefaultsAction | AddColorPresetAction | CreateAnnotationAction | PatchAnnotationAction | DeleteAnnotationAction | CommitAction | StorePdfIdAction | PurgeAnnotationAction;
62
195
 
63
196
  declare class AnnotationPlugin extends BasePlugin<AnnotationPluginConfig, AnnotationCapability, AnnotationState, AnnotationAction> {
64
197
  static readonly id: "annotation";
198
+ private readonly ANNOTATION_HISTORY_TOPIC;
199
+ private readonly config;
65
200
  private engine;
66
201
  private readonly state$;
67
- constructor(id: string, registry: PluginRegistry, engine: PdfEngine);
202
+ private readonly interactionManager;
203
+ private readonly selection;
204
+ private readonly history;
205
+ /** Map <subtype> → <modeId>. Filled once in `initialize()`. */
206
+ private readonly modeBySubtype;
207
+ /** The inverse map for quick lookup in onModeChange(). */
208
+ private readonly subtypeByMode;
209
+ private readonly modeChange$;
210
+ private readonly activeTool$;
211
+ constructor(id: string, registry: PluginRegistry, engine: PdfEngine, config: AnnotationPluginConfig);
68
212
  initialize(): Promise<void>;
213
+ private registerTool;
69
214
  protected buildCapability(): AnnotationCapability;
70
- onStoreUpdated(_prevState: AnnotationState, newState: AnnotationState): void;
215
+ private emitActiveTool;
216
+ onStoreUpdated(prev: AnnotationState, next: AnnotationState): void;
71
217
  private getAllAnnotations;
72
218
  private getPageAnnotations;
73
219
  private selectAnnotation;
74
- private updateSelectedAnnotationColor;
220
+ private createAnnotation;
221
+ private updateAnnotation;
222
+ private deleteAnnotation;
223
+ private commit;
75
224
  }
76
225
 
77
226
  declare const ANNOTATION_PLUGIN_ID = "annotation";
78
227
  declare const manifest: PluginManifest<AnnotationPluginConfig>;
79
228
 
229
+ /** All annotations _objects_ on a single page (order preserved). */
230
+ declare const getAnnotationsByPageIndex: (s: AnnotationState, page: number) => TrackedAnnotation[];
231
+ /** Shortcut: every page → list of annotation objects. */
232
+ declare const getAnnotations: (s: AnnotationState) => Record<number, TrackedAnnotation[]>;
233
+ /** The full `TrackedAnnotation` for the current selection. */
234
+ declare const getSelectedAnnotation: (s: AnnotationState) => TrackedAnnotation | null;
235
+ declare const getSelectedAnnotationWithPageIndex: (s: AnnotationState) => SelectedAnnotation | null;
236
+ declare const getSelectedAnnotationByPageIndex: (s: AnnotationState, pageIndex: number) => TrackedAnnotation | null;
237
+ declare const isInAnnotationMode: (s: AnnotationState) => boolean;
238
+ declare const getSelectedAnnotationMode: (s: AnnotationState) => keyof ToolDefaultsBySubtype | null;
239
+ /** Check if a given anno on a page is the current selection. */
240
+ declare const isAnnotationSelected: (s: AnnotationState, page: number, id: number) => boolean;
241
+
80
242
  declare const AnnotationPluginPackage: PluginPackage<AnnotationPlugin, AnnotationPluginConfig, AnnotationState, AnnotationAction>;
81
243
 
82
- export { ANNOTATION_PLUGIN_ID, type AnnotationCapability, AnnotationPlugin, type AnnotationPluginConfig, AnnotationPluginPackage, type AnnotationState, type GetPageAnnotationsOptions, type SelectedAnnotation, type UpdateAnnotationColorOptions, manifest };
244
+ export { ANNOTATION_PLUGIN_ID, type ActiveTool, type AnnotationCapability, type AnnotationDefaults, AnnotationPlugin, type AnnotationPluginConfig, AnnotationPluginPackage, type AnnotationState, type BaseAnnotationDefaults, type CommitState, type GetPageAnnotationsOptions, type HighlightDefaults, type SelectedAnnotation, type SquigglyDefaults, type StrikeoutDefaults, type StylableSubtype, type ToolDefaults, type ToolDefaultsBySubtype, type TrackedAnnotation, type UnderlineDefaults, type UpdateAnnotationColorOptions, getAnnotations, getAnnotationsByPageIndex, getSelectedAnnotation, getSelectedAnnotationByPageIndex, getSelectedAnnotationMode, getSelectedAnnotationWithPageIndex, isAnnotationSelected, isInAnnotationMode, manifest };