@embedpdf/plugin-annotation 2.8.0 → 2.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +829 -148
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/geometry/cloudy-border.d.ts +90 -0
  6. package/dist/lib/geometry/index.d.ts +1 -0
  7. package/dist/lib/handlers/types.d.ts +2 -1
  8. package/dist/lib/tools/default-tools.d.ts +43 -88
  9. package/dist/lib/tools/types.d.ts +34 -1
  10. package/dist/lib/types.d.ts +3 -0
  11. package/dist/preact/index.cjs +1 -1
  12. package/dist/preact/index.cjs.map +1 -1
  13. package/dist/preact/index.js +371 -242
  14. package/dist/preact/index.js.map +1 -1
  15. package/dist/react/index.cjs +1 -1
  16. package/dist/react/index.cjs.map +1 -1
  17. package/dist/react/index.js +371 -242
  18. package/dist/react/index.js.map +1 -1
  19. package/dist/shared/components/annotation-container.d.ts +4 -2
  20. package/dist/shared/components/annotations/circle.d.ts +6 -2
  21. package/dist/shared/components/annotations/polygon.d.ts +3 -1
  22. package/dist/shared/components/annotations/square.d.ts +6 -2
  23. package/dist/shared/components/types.d.ts +6 -2
  24. package/dist/shared-preact/components/annotation-container.d.ts +4 -2
  25. package/dist/shared-preact/components/annotations/circle.d.ts +6 -2
  26. package/dist/shared-preact/components/annotations/polygon.d.ts +3 -1
  27. package/dist/shared-preact/components/annotations/square.d.ts +6 -2
  28. package/dist/shared-preact/components/types.d.ts +6 -2
  29. package/dist/shared-react/components/annotation-container.d.ts +4 -2
  30. package/dist/shared-react/components/annotations/circle.d.ts +6 -2
  31. package/dist/shared-react/components/annotations/polygon.d.ts +3 -1
  32. package/dist/shared-react/components/annotations/square.d.ts +6 -2
  33. package/dist/shared-react/components/types.d.ts +6 -2
  34. package/dist/svelte/components/annotations/Circle.svelte.d.ts +3 -1
  35. package/dist/svelte/components/annotations/Polygon.svelte.d.ts +1 -0
  36. package/dist/svelte/components/annotations/Square.svelte.d.ts +3 -1
  37. package/dist/svelte/components/types.d.ts +2 -1
  38. package/dist/svelte/context/types.d.ts +6 -2
  39. package/dist/svelte/index.cjs +1 -1
  40. package/dist/svelte/index.cjs.map +1 -1
  41. package/dist/svelte/index.js +525 -298
  42. package/dist/svelte/index.js.map +1 -1
  43. package/dist/vue/components/annotation-container.vue.d.ts +7 -6
  44. package/dist/vue/components/annotations/circle.vue.d.ts +5 -1
  45. package/dist/vue/components/annotations/polygon.vue.d.ts +2 -0
  46. package/dist/vue/components/annotations/square.vue.d.ts +5 -1
  47. package/dist/vue/components/annotations.vue.d.ts +8 -9
  48. package/dist/vue/context/types.d.ts +6 -2
  49. package/dist/vue/index.cjs +1 -1
  50. package/dist/vue/index.cjs.map +1 -1
  51. package/dist/vue/index.js +289 -135
  52. package/dist/vue/index.js.map +1 -1
  53. package/package.json +10 -10
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Cloudy border path generator for PDF annotations.
3
+ *
4
+ * Framework-agnostic utility that generates SVG path `d` strings for cloudy
5
+ * (scalloped) borders on Rectangle, Ellipse, and Polygon shapes.
6
+ *
7
+ * Derived from Apache PDFBox's CloudyBorder.java:
8
+ * https://github.com/apache/pdfbox/blob/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/interactive/annotation/handlers/CloudyBorder.java
9
+ *
10
+ * Original code licensed under the Apache License, Version 2.0:
11
+ * https://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Substantially modified: ported from Java to TypeScript, adapted for SVG
14
+ * path output, and reworked curl distribution and merging logic.
15
+ *
16
+ * Copyright (c) 2026 CloudPDF / EmbedPDF
17
+ *
18
+ * @module
19
+ */
20
+ interface BBox {
21
+ minX: number;
22
+ minY: number;
23
+ maxX: number;
24
+ maxY: number;
25
+ }
26
+ /** Rect differences (inset from annotation Rect to drawn shape). */
27
+ export interface RectDifferences {
28
+ left: number;
29
+ top: number;
30
+ right: number;
31
+ bottom: number;
32
+ }
33
+ export interface CloudyPathResult {
34
+ /** SVG path `d` attribute string */
35
+ path: string;
36
+ /** Bounding box of the generated cloudy border (in annotation-local coords) */
37
+ bbox: BBox;
38
+ }
39
+ /**
40
+ * Returns the per-side outward extent of a cloudy border (how far the
41
+ * scallop peaks + stroke extend beyond the inner shape boundary).
42
+ *
43
+ * Use this to compute `rectangleDifferences` for Square/Circle or the
44
+ * padding for Polygon Rect computation.
45
+ */
46
+ export declare function getCloudyBorderExtent(intensity: number, lineWidth: number, isEllipse: boolean): number;
47
+ /**
48
+ * Generates a cloudy border SVG path for a rectangle (Square annotation).
49
+ *
50
+ * @param rect - The annotation rect `{ x, y, width, height }` (top-left origin)
51
+ * @param rd - Rectangle differences (inset), or undefined
52
+ * @param intensity - Cloudy border intensity (typically 1 or 2)
53
+ * @param lineWidth - Stroke width of the annotation border
54
+ */
55
+ export declare function generateCloudyRectanglePath(rect: {
56
+ x: number;
57
+ y: number;
58
+ width: number;
59
+ height: number;
60
+ }, rd: RectDifferences | undefined, intensity: number, lineWidth: number): CloudyPathResult;
61
+ /**
62
+ * Generates a cloudy border SVG path for an ellipse (Circle annotation).
63
+ *
64
+ * @param rect - The annotation rect `{ x, y, width, height }` (top-left origin)
65
+ * @param rd - Rectangle differences (inset), or undefined
66
+ * @param intensity - Cloudy border intensity (typically 1 or 2)
67
+ * @param lineWidth - Stroke width of the annotation border
68
+ */
69
+ export declare function generateCloudyEllipsePath(rect: {
70
+ x: number;
71
+ y: number;
72
+ width: number;
73
+ height: number;
74
+ }, rd: RectDifferences | undefined, intensity: number, lineWidth: number): CloudyPathResult;
75
+ /**
76
+ * Generates a cloudy border SVG path for a polygon.
77
+ *
78
+ * @param vertices - The polygon vertices in annotation-local coordinates
79
+ * @param rectOrigin - The annotation rect origin `{ x, y }` for coordinate translation
80
+ * @param intensity - Cloudy border intensity (typically 1 or 2)
81
+ * @param lineWidth - Stroke width of the annotation border
82
+ */
83
+ export declare function generateCloudyPolygonPath(vertices: ReadonlyArray<{
84
+ x: number;
85
+ y: number;
86
+ }>, rectOrigin: {
87
+ x: number;
88
+ y: number;
89
+ }, intensity: number, lineWidth: number): CloudyPathResult;
90
+ export {};
@@ -1 +1,2 @@
1
1
  export * from './rotation';
2
+ export * from './cloudy-border';
@@ -1,5 +1,5 @@
1
1
  import { PointerEventHandlersWithLifecycle } from '@embedpdf/plugin-interaction-manager';
2
- import { PdfAnnotationObject, PdfAnnotationSubtype, Rect, Rotation, Size, AnnotationCreateContext, PdfAnnotationBorderStyle, Position, LineEndings, PdfInkListObject, PdfStandardFont, PdfTextAlignment, PdfVerticalAlignment } from '@embedpdf/models';
2
+ import { PdfAnnotationObject, PdfAnnotationSubtype, Rect, Rotation, Size, AnnotationCreateContext, PdfAnnotationBorderStyle, Position, LineEndings, PdfInkListObject, PdfStandardFont, PdfTextAlignment, PdfVerticalAlignment, PdfBlendMode } from '@embedpdf/models';
3
3
  import { FormattedSelection } from '@embedpdf/plugin-selection';
4
4
  import { AnnotationTool } from '../tools/types';
5
5
  export interface CirclePreviewData {
@@ -54,6 +54,7 @@ export interface InkPreviewData {
54
54
  strokeWidth: number;
55
55
  strokeColor: string;
56
56
  opacity: number;
57
+ blendMode?: PdfBlendMode;
57
58
  }
58
59
  export interface FreeTextPreviewData {
59
60
  rect: Rect;
@@ -1,8 +1,34 @@
1
1
  import { PdfAnnotationBorderStyle, PdfAnnotationLineEnding, PdfAnnotationSubtype, PdfBlendMode, PdfStandardFont, PdfTextAlignment, PdfVerticalAlignment } from '@embedpdf/models';
2
2
  export declare const defaultTools: ({
3
+ id: string;
4
+ name: string;
5
+ matchScore: (annotation: import('@embedpdf/models').PdfAnnotationObject) => number;
6
+ defaults: Partial<import('@embedpdf/models').PdfInkAnnoObject>;
7
+ interaction: {
8
+ mode?: string;
9
+ exclusive: boolean;
10
+ cursor?: string;
11
+ textSelection?: boolean;
12
+ showSelectionRects?: boolean;
13
+ isDraggable?: import('./types').DynamicBooleanProp;
14
+ isResizable?: import('./types').DynamicBooleanProp;
15
+ isRotatable?: import('./types').DynamicBooleanProp;
16
+ lockAspectRatio?: import('./types').DynamicBooleanProp;
17
+ lockGroupAspectRatio?: import('./types').DynamicBooleanProp;
18
+ isGroupDraggable?: import('./types').DynamicBooleanProp;
19
+ isGroupResizable?: import('./types').DynamicBooleanProp;
20
+ isGroupRotatable?: import('./types').DynamicBooleanProp;
21
+ };
22
+ behavior?: ({
23
+ deactivateToolAfterCreate?: boolean;
24
+ selectAfterCreate?: boolean;
25
+ editAfterCreate?: boolean;
26
+ useAppearanceStream?: boolean;
27
+ } & import('./types').InkBehavior) | undefined;
28
+ } | {
3
29
  id: "highlight";
4
30
  name: string;
5
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 1 | 0;
31
+ matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 1;
6
32
  interaction: {
7
33
  exclusive: false;
8
34
  textSelection: true;
@@ -39,7 +65,7 @@ export declare const defaultTools: ({
39
65
  } | {
40
66
  id: "underline";
41
67
  name: string;
42
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 1 | 0;
68
+ matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 1;
43
69
  interaction: {
44
70
  exclusive: false;
45
71
  textSelection: true;
@@ -76,7 +102,7 @@ export declare const defaultTools: ({
76
102
  } | {
77
103
  id: "strikeout";
78
104
  name: string;
79
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 1 | 0;
105
+ matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 1;
80
106
  interaction: {
81
107
  exclusive: false;
82
108
  textSelection: true;
@@ -113,7 +139,7 @@ export declare const defaultTools: ({
113
139
  } | {
114
140
  id: "squiggly";
115
141
  name: string;
116
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 1 | 0;
142
+ matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 1;
117
143
  interaction: {
118
144
  exclusive: false;
119
145
  textSelection: true;
@@ -150,7 +176,7 @@ export declare const defaultTools: ({
150
176
  } | {
151
177
  id: "insertText";
152
178
  name: string;
153
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 1 | 0 | 2;
179
+ matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 1 | 2;
154
180
  interaction: {
155
181
  exclusive: false;
156
182
  textSelection: true;
@@ -221,84 +247,10 @@ export declare const defaultTools: ({
221
247
  };
222
248
  clickBehavior?: undefined;
223
249
  behavior?: undefined;
224
- } | {
225
- id: "ink";
226
- name: string;
227
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 5;
228
- interaction: {
229
- exclusive: false;
230
- cursor: string;
231
- isDraggable: true;
232
- isResizable: true;
233
- lockAspectRatio: false;
234
- textSelection?: undefined;
235
- isRotatable?: undefined;
236
- isGroupDraggable?: undefined;
237
- isGroupResizable?: undefined;
238
- showSelectionRects?: undefined;
239
- lockGroupAspectRatio?: undefined;
240
- };
241
- defaults: {
242
- type: PdfAnnotationSubtype.INK;
243
- strokeColor: string;
244
- color: string;
245
- opacity: number;
246
- strokeWidth: number;
247
- blendMode?: undefined;
248
- intent?: undefined;
249
- strokeStyle?: undefined;
250
- lineEndings?: undefined;
251
- contents?: undefined;
252
- fontSize?: undefined;
253
- fontColor?: undefined;
254
- fontFamily?: undefined;
255
- textAlign?: undefined;
256
- verticalAlign?: undefined;
257
- backgroundColor?: undefined;
258
- };
259
- clickBehavior?: undefined;
260
- behavior?: undefined;
261
- } | {
262
- id: "inkHighlighter";
263
- name: string;
264
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 10;
265
- interaction: {
266
- exclusive: false;
267
- cursor: string;
268
- isDraggable: true;
269
- isResizable: true;
270
- lockAspectRatio: false;
271
- lockGroupAspectRatio: (a: import('@embedpdf/models').PdfAnnotationObject) => boolean;
272
- textSelection?: undefined;
273
- isRotatable?: undefined;
274
- isGroupDraggable?: undefined;
275
- isGroupResizable?: undefined;
276
- showSelectionRects?: undefined;
277
- };
278
- defaults: {
279
- type: PdfAnnotationSubtype.INK;
280
- intent: string;
281
- strokeColor: string;
282
- color: string;
283
- opacity: number;
284
- strokeWidth: number;
285
- blendMode: PdfBlendMode.Multiply;
286
- strokeStyle?: undefined;
287
- lineEndings?: undefined;
288
- contents?: undefined;
289
- fontSize?: undefined;
290
- fontColor?: undefined;
291
- fontFamily?: undefined;
292
- textAlign?: undefined;
293
- verticalAlign?: undefined;
294
- backgroundColor?: undefined;
295
- };
296
- clickBehavior?: undefined;
297
- behavior?: undefined;
298
250
  } | {
299
251
  id: "circle";
300
252
  name: string;
301
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 1 | 0;
253
+ matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 1;
302
254
  interaction: {
303
255
  exclusive: false;
304
256
  cursor: string;
@@ -344,7 +296,7 @@ export declare const defaultTools: ({
344
296
  } | {
345
297
  id: "square";
346
298
  name: string;
347
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 1 | 0;
299
+ matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 1;
348
300
  interaction: {
349
301
  exclusive: false;
350
302
  cursor: string;
@@ -390,7 +342,7 @@ export declare const defaultTools: ({
390
342
  } | {
391
343
  id: "line";
392
344
  name: string;
393
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 5;
345
+ matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 5 | 0;
394
346
  interaction: {
395
347
  exclusive: false;
396
348
  cursor: string;
@@ -479,7 +431,7 @@ export declare const defaultTools: ({
479
431
  } | {
480
432
  id: "polyline";
481
433
  name: string;
482
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 1 | 0;
434
+ matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 1;
483
435
  interaction: {
484
436
  exclusive: false;
485
437
  cursor: string;
@@ -516,7 +468,7 @@ export declare const defaultTools: ({
516
468
  } | {
517
469
  id: "polygon";
518
470
  name: string;
519
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 1 | 0;
471
+ matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 1;
520
472
  interaction: {
521
473
  exclusive: false;
522
474
  cursor: string;
@@ -553,7 +505,7 @@ export declare const defaultTools: ({
553
505
  } | {
554
506
  id: "textComment";
555
507
  name: string;
556
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 1 | 0;
508
+ matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 1;
557
509
  interaction: {
558
510
  exclusive: false;
559
511
  cursor: string;
@@ -588,13 +540,14 @@ export declare const defaultTools: ({
588
540
  behavior: {
589
541
  selectAfterCreate: true;
590
542
  insertUpright?: undefined;
543
+ editAfterCreate?: undefined;
591
544
  useAppearanceStream?: undefined;
592
545
  };
593
546
  clickBehavior?: undefined;
594
547
  } | {
595
548
  id: "freeText";
596
549
  name: string;
597
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 1 | 0;
550
+ matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 1;
598
551
  interaction: {
599
552
  exclusive: false;
600
553
  cursor: string;
@@ -638,13 +591,14 @@ export declare const defaultTools: ({
638
591
  };
639
592
  behavior: {
640
593
  insertUpright: true;
641
- selectAfterCreate?: undefined;
594
+ editAfterCreate: true;
595
+ selectAfterCreate: true;
642
596
  useAppearanceStream?: undefined;
643
597
  };
644
598
  } | {
645
599
  id: "stamp";
646
600
  name: string;
647
- matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 1 | 0;
601
+ matchScore: (a: import('@embedpdf/models').PdfAnnotationObject) => 0 | 1;
648
602
  interaction: {
649
603
  exclusive: false;
650
604
  cursor: string;
@@ -680,6 +634,7 @@ export declare const defaultTools: ({
680
634
  insertUpright: true;
681
635
  useAppearanceStream: false;
682
636
  selectAfterCreate?: undefined;
637
+ editAfterCreate?: undefined;
683
638
  };
684
639
  clickBehavior?: undefined;
685
640
  })[];
@@ -83,6 +83,37 @@ type InsertUprightBehaviorFor<T extends PdfAnnotationObject> = Extract<T['type']
83
83
  /** Counter-rotate new annotations to appear visually upright on rotated pages. */
84
84
  insertUpright?: boolean;
85
85
  };
86
+ /**
87
+ * Ink-specific behavior settings. Only available on tools whose annotation
88
+ * type is PdfAnnotationSubtype.INK (i.e. 'ink' and 'inkHighlighter').
89
+ */
90
+ export interface InkBehavior {
91
+ /** ms of pointer inactivity before the accumulated strokes are committed. Default: 800. */
92
+ commitDelay?: number;
93
+ /** When true, line-like strokes are snapped to a clean 2-point straight line on pointerUp. */
94
+ smartLineRecognition?: boolean;
95
+ /**
96
+ * Maximum allowed perpendicular-deviation ratio (maxDeviation / strokeLength) for a stroke
97
+ * to qualify as a straight line. Lower = stricter. Default: 0.15.
98
+ */
99
+ smartLineThreshold?: number;
100
+ /**
101
+ * How many degrees from horizontal or vertical a recognised straight line may deviate
102
+ * before axis-snapping is skipped. Default: 15.
103
+ */
104
+ snapAngleDeg?: number;
105
+ }
106
+ /**
107
+ * Non-distributive conditional: wrapping both sides in [...] prevents TypeScript from
108
+ * distributing over a union. [PdfAnnotationObject] extends [PdfInkAnnoObject] is false
109
+ * (the full union is not a subtype of the specific ink type), so InkBehavior is only added
110
+ * when T is specifically the INK annotation type.
111
+ */
112
+ type InkBehaviorFor<T extends PdfAnnotationObject> = [T] extends [
113
+ Extract<PdfAnnotationObject, {
114
+ type: PdfAnnotationSubtype.INK;
115
+ }>
116
+ ] ? InkBehavior : {};
86
117
  /**
87
118
  * The primary interface for defining an annotation tool.
88
119
  * Uses a type alias to properly combine the base interface with conditional properties.
@@ -134,8 +165,10 @@ export type AnnotationTool<T extends PdfAnnotationObject = PdfAnnotationObject>
134
165
  deactivateToolAfterCreate?: boolean;
135
166
  /** When true, select the annotation immediately after creation. Overrides plugin config. */
136
167
  selectAfterCreate?: boolean;
168
+ /** When true, automatically enter editing mode after creating the annotation. Implies selectAfterCreate. */
169
+ editAfterCreate?: boolean;
137
170
  /** Override whether this annotation type uses AP rendering before editing (default: true) */
138
171
  useAppearanceStream?: boolean;
139
- } & InsertUprightBehaviorFor<T>;
172
+ } & InsertUprightBehaviorFor<T> & InkBehaviorFor<T>;
140
173
  } & ClickBehaviorFor<T>;
141
174
  export {};
@@ -17,6 +17,7 @@ export type AnnotationEvent = {
17
17
  pageIndex: number;
18
18
  ctx?: AnnotationCreateContext<any>;
19
19
  committed: boolean;
20
+ editAfterCreate?: boolean;
20
21
  } | {
21
22
  type: 'update';
22
23
  documentId: string;
@@ -123,6 +124,8 @@ export interface AnnotationPluginConfig extends BasePluginConfig {
123
124
  deactivateToolAfterCreate?: boolean;
124
125
  /** When true (default false), select the annotation immediately after creation. */
125
126
  selectAfterCreate?: boolean;
127
+ /** When true (default false), automatically enter edit mode after creating an annotation. */
128
+ editAfterCreate?: boolean;
126
129
  }
127
130
  /**
128
131
  * Options for transforming an annotation