@embedpdf/plugin-annotation 2.4.1 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +1061 -430
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/annotation-plugin.d.ts +24 -6
  6. package/dist/lib/geometry/index.d.ts +1 -0
  7. package/dist/lib/geometry/rotation.d.ts +32 -0
  8. package/dist/lib/handlers/types.d.ts +3 -1
  9. package/dist/lib/index.d.ts +1 -0
  10. package/dist/lib/patching/base-patch.d.ts +87 -0
  11. package/dist/lib/patching/index.d.ts +1 -0
  12. package/dist/lib/patching/insert-upright.d.ts +20 -0
  13. package/dist/lib/patching/patch-registry.d.ts +14 -1
  14. package/dist/lib/patching/patch-utils.d.ts +54 -1
  15. package/dist/lib/patching/patches/circle.patch.d.ts +3 -0
  16. package/dist/lib/patching/patches/freetext.patch.d.ts +3 -0
  17. package/dist/lib/patching/patches/index.d.ts +4 -0
  18. package/dist/lib/patching/patches/square.patch.d.ts +3 -0
  19. package/dist/lib/patching/patches/stamp.patch.d.ts +3 -0
  20. package/dist/lib/tools/default-tools.d.ts +32 -0
  21. package/dist/lib/tools/types.d.ts +20 -1
  22. package/dist/lib/types.d.ts +67 -3
  23. package/dist/preact/adapter.d.ts +3 -0
  24. package/dist/preact/index.cjs +1 -1
  25. package/dist/preact/index.cjs.map +1 -1
  26. package/dist/preact/index.js +797 -128
  27. package/dist/preact/index.js.map +1 -1
  28. package/dist/react/adapter.d.ts +2 -1
  29. package/dist/react/index.cjs +1 -1
  30. package/dist/react/index.cjs.map +1 -1
  31. package/dist/react/index.js +797 -128
  32. package/dist/react/index.js.map +1 -1
  33. package/dist/shared/components/annotation-container.d.ts +10 -2
  34. package/dist/shared/components/annotation-layer.d.ts +9 -3
  35. package/dist/shared/components/annotations.d.ts +4 -1
  36. package/dist/shared/components/group-selection-box.d.ts +12 -4
  37. package/dist/shared/components/render-annotation.d.ts +2 -1
  38. package/dist/shared/components/types.d.ts +51 -1
  39. package/dist/shared-preact/components/annotation-container.d.ts +10 -2
  40. package/dist/shared-preact/components/annotation-layer.d.ts +9 -3
  41. package/dist/shared-preact/components/annotations.d.ts +4 -1
  42. package/dist/shared-preact/components/group-selection-box.d.ts +12 -4
  43. package/dist/shared-preact/components/render-annotation.d.ts +2 -1
  44. package/dist/shared-preact/components/types.d.ts +51 -1
  45. package/dist/shared-react/components/annotation-container.d.ts +10 -2
  46. package/dist/shared-react/components/annotation-layer.d.ts +9 -3
  47. package/dist/shared-react/components/annotations.d.ts +4 -1
  48. package/dist/shared-react/components/group-selection-box.d.ts +12 -4
  49. package/dist/shared-react/components/render-annotation.d.ts +2 -1
  50. package/dist/shared-react/components/types.d.ts +51 -1
  51. package/dist/svelte/components/AnnotationLayer.svelte.d.ts +8 -2
  52. package/dist/svelte/components/Annotations.svelte.d.ts +7 -1
  53. package/dist/svelte/components/GroupSelectionBox.svelte.d.ts +11 -3
  54. package/dist/svelte/components/RenderAnnotation.svelte.d.ts +1 -0
  55. package/dist/svelte/components/types.d.ts +14 -1
  56. package/dist/svelte/index.cjs +1 -1
  57. package/dist/svelte/index.cjs.map +1 -1
  58. package/dist/svelte/index.js +1171 -332
  59. package/dist/svelte/index.js.map +1 -1
  60. package/dist/svelte/types.d.ts +53 -0
  61. package/dist/vue/components/annotation-container.vue.d.ts +35 -9
  62. package/dist/vue/components/annotation-layer.vue.d.ts +29 -5
  63. package/dist/vue/components/annotations.vue.d.ts +278 -134
  64. package/dist/vue/components/group-selection-box.vue.d.ts +35 -10
  65. package/dist/vue/components/render-annotation.vue.d.ts +2 -0
  66. package/dist/vue/index.cjs +1 -1
  67. package/dist/vue/index.cjs.map +1 -1
  68. package/dist/vue/index.js +949 -163
  69. package/dist/vue/index.js.map +1 -1
  70. package/dist/vue/types.d.ts +52 -0
  71. package/package.json +11 -10
@@ -1,6 +1,6 @@
1
1
  import { BasePlugin, PluginRegistry } from '@embedpdf/core';
2
2
  import { PdfAnnotationObject, Position, Rect } from '@embedpdf/models';
3
- import { AnnotationCapability, AnnotationPluginConfig, AnnotationState, UnifiedDragOptions, UnifiedDragState, UnifiedDragEvent, UnifiedResizeOptions, UnifiedResizeState, UnifiedResizeEvent } from './types';
3
+ import { AnnotationCapability, AnnotationPluginConfig, AnnotationState, UnifiedDragOptions, UnifiedDragState, UnifiedDragEvent, UnifiedResizeOptions, UnifiedResizeState, UnifiedResizeEvent, UnifiedRotateOptions, UnifiedRotateState, UnifiedRotateEvent } from './types';
4
4
  import { AnnotationAction } from './actions';
5
5
  import { AnnotationTool } from './tools/types';
6
6
  import { AnyPreviewState, HandlerServices } from './handlers/types';
@@ -25,6 +25,8 @@ export declare class AnnotationPlugin extends BasePlugin<AnnotationPluginConfig,
25
25
  private readonly unifiedDrag$;
26
26
  private readonly unifiedResizeStates;
27
27
  private readonly unifiedResize$;
28
+ private readonly unifiedRotateStates;
29
+ private readonly unifiedRotate$;
28
30
  constructor(id: string, registry: PluginRegistry, config: AnnotationPluginConfig);
29
31
  protected onDocumentLoadingStarted(documentId: string): void;
30
32
  protected onDocumentLoaded(documentId: string): void;
@@ -59,6 +61,12 @@ export declare class AnnotationPlugin extends BasePlugin<AnnotationPluginConfig,
59
61
  private purgeAnnotationMethod;
60
62
  private selectAnnotation;
61
63
  private deselectAnnotation;
64
+ /**
65
+ * Derive page activity from the current annotation selection.
66
+ * Called from onStoreUpdated whenever selectedUids changes,
67
+ * so ALL selection code paths are covered automatically.
68
+ */
69
+ private updateAnnotationSelectionActivity;
62
70
  private getSelectedAnnotationsMethod;
63
71
  private getSelectedAnnotationIdsMethod;
64
72
  private toggleSelectionMethod;
@@ -203,6 +211,21 @@ export declare class AnnotationPlugin extends BasePlugin<AnnotationPluginConfig,
203
211
  * Framework components use this for preview updates.
204
212
  */
205
213
  get onResizeChange(): import('@embedpdf/core').EventHook<UnifiedResizeEvent>;
214
+ private cloneRect;
215
+ private translateRect;
216
+ private normalizeAngle;
217
+ private normalizeDelta;
218
+ private buildRotationParticipants;
219
+ private computeRotatePreviewPatches;
220
+ startRotation(documentId: string, options: UnifiedRotateOptions): void;
221
+ updateRotation(documentId: string, cursorAngle: number, rotationDelta?: number): void;
222
+ commitRotation(documentId: string): void;
223
+ cancelRotation(documentId: string): void;
224
+ getRotateState(documentId: string): UnifiedRotateState | null;
225
+ /**
226
+ * Subscribe to unified rotation state changes.
227
+ */
228
+ get onRotateChange(): import('@embedpdf/core').EventHook<UnifiedRotateEvent>;
206
229
  private updateAnnotationsMethod;
207
230
  getActiveTool(documentId?: string): AnnotationTool | null;
208
231
  setActiveTool(toolId: string | null, documentId?: string): void;
@@ -233,9 +256,4 @@ export declare class AnnotationPlugin extends BasePlugin<AnnotationPluginConfig,
233
256
  */
234
257
  private releaseCommitLock;
235
258
  private commit;
236
- /**
237
- * Gets the effective behavior setting for a tool, checking tool-specific config first,
238
- * then falling back to plugin config.
239
- */
240
- private getToolBehavior;
241
259
  }
@@ -0,0 +1 @@
1
+ export * from './rotation';
@@ -0,0 +1,32 @@
1
+ import { Rect } from '@embedpdf/models';
2
+ /**
3
+ * Re-export rotation geometry utilities from @embedpdf/models.
4
+ *
5
+ * These functions used to live here but have been promoted to the shared models
6
+ * package so that both @embedpdf/utils (DragResizeController) and
7
+ * @embedpdf/plugin-annotation (patches) can import from the same source.
8
+ *
9
+ * Existing imports from this module continue to work unchanged.
10
+ */
11
+ export { rotatePointAround as rotatePointAroundCenter, rotateVertices, getRectCenter, calculateRotatedRectAABBAroundPoint, calculateRotatedRectAABB, inferRotationCenterFromRects, } from '@embedpdf/models';
12
+ /**
13
+ * Convert an AABB-space rect to unrotated space.
14
+ *
15
+ * During group resize the pipeline works in AABB space (axis-aligned bounding
16
+ * box), but `baseResizeScaling` expects the incoming rect in unrotated space.
17
+ *
18
+ * The AABB of a rect rotated by θ around its center is:
19
+ * AABB_w = w·|cosθ| + h·|sinθ|
20
+ * AABB_h = w·|sinθ| + h·|cosθ|
21
+ *
22
+ * This function inverts that system to recover (w, h) from the new AABB size.
23
+ * Near 45° the system is degenerate (the AABB is always square), so we fall
24
+ * back to uniform scaling based on the area ratio.
25
+ *
26
+ * @param newAABBRect - the proportionally scaled AABB rect from the group resize
27
+ * @param originalAABBRect - the original AABB rect captured at resize start
28
+ * @param originalUnrotatedRect - the original unrotated rect captured at resize start
29
+ * @param rotationDegrees - the annotation's rotation in degrees
30
+ * @returns the equivalent rect in unrotated space
31
+ */
32
+ export declare function convertAABBRectToUnrotatedSpace(newAABBRect: Rect, originalAABBRect: Rect, originalUnrotatedRect: Rect, rotationDegrees: number): Rect;
@@ -1,5 +1,5 @@
1
1
  import { PointerEventHandlersWithLifecycle } from '@embedpdf/plugin-interaction-manager';
2
- import { PdfAnnotationObject, PdfAnnotationSubtype, Rect, 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 } from '@embedpdf/models';
3
3
  import { AnnotationTool } from '../tools/types';
4
4
  export interface CirclePreviewData {
5
5
  rect: Rect;
@@ -131,6 +131,8 @@ export interface HandlerContext<A extends PdfAnnotationObject> {
131
131
  getTool: () => AnnotationTool<A> | undefined;
132
132
  pageIndex: number;
133
133
  pageSize: Size;
134
+ /** Effective page rotation (page intrinsic + document rotation), as a quarter-turn value (0-3). */
135
+ pageRotation: Rotation;
134
136
  scale: number;
135
137
  services: HandlerServices;
136
138
  onPreview: (state: AnyPreviewState | null) => void;
@@ -11,5 +11,6 @@ export * from './helpers';
11
11
  export * from './handlers/types';
12
12
  export * from './tools/types';
13
13
  export * from './tools/tools-utils';
14
+ export * from './geometry';
14
15
  export * as patching from './patching';
15
16
  export { initialState, initialDocumentState } from './reducer';
@@ -0,0 +1,87 @@
1
+ import { Rect } from '@embedpdf/models';
2
+ import { TransformContext } from './patch-registry';
3
+ /**
4
+ * Minimal shape required by the shared patch helpers.
5
+ * All annotation objects satisfy this through PdfAnnotationObject.
6
+ */
7
+ export interface RotatableAnnotation {
8
+ rect: Rect;
9
+ unrotatedRect?: Rect;
10
+ rotation?: number;
11
+ }
12
+ /**
13
+ * Shared rotate logic.
14
+ * Returns the full patch (rect, unrotatedRect, rotation) or `null` when the
15
+ * context doesn't carry a rotationAngle (in which case the caller should
16
+ * fall through to `ctx.changes`).
17
+ */
18
+ export declare function baseRotateChanges(orig: RotatableAnnotation, ctx: TransformContext<any>): Partial<{
19
+ rect: Rect;
20
+ unrotatedRect: Rect;
21
+ rotation: number;
22
+ }> | null;
23
+ /**
24
+ * Shared property-update rotation logic.
25
+ * Recomputes rect and unrotatedRect for a new rotation angle, preserving
26
+ * the annotation's rotation center. Works for all annotation types since
27
+ * it only touches rect/unrotatedRect/rotation.
28
+ */
29
+ export declare function basePropertyRotationChanges(orig: RotatableAnnotation, newRotation: number): {
30
+ rotation: number;
31
+ rect: Rect;
32
+ unrotatedRect: Rect;
33
+ };
34
+ /**
35
+ * Shared move logic: computes dx/dy and translates rect + unrotatedRect.
36
+ * Callers use the returned `dx`/`dy` to translate their own type-specific
37
+ * data (vertices, linePoints, inkList, etc.).
38
+ */
39
+ export declare function baseMoveChanges(orig: RotatableAnnotation, newRect: Rect): {
40
+ dx: number;
41
+ dy: number;
42
+ rects: {
43
+ rect: Rect;
44
+ unrotatedRect?: Rect;
45
+ };
46
+ };
47
+ export interface ResizeScalingResult {
48
+ /** Horizontal scale factor */
49
+ scaleX: number;
50
+ /** Vertical scale factor */
51
+ scaleY: number;
52
+ /** The old rect used as the scaling reference (unrotatedRect ?? rect) */
53
+ oldRect: Rect;
54
+ /** The adjusted new rect after min-size and aspect-ratio enforcement */
55
+ resolvedRect: Rect;
56
+ /** The final rect + unrotatedRect patches to spread into the result */
57
+ rects: {
58
+ rect: Rect;
59
+ unrotatedRect?: Rect;
60
+ };
61
+ }
62
+ /**
63
+ * Shared resize scaling logic:
64
+ * 1. Determines scale factors from oldRect → newRect
65
+ * 2. Enforces a minimum size of 10
66
+ * 3. Optionally maintains aspect ratio
67
+ * 4. Resolves rect vs unrotatedRect for rotated annotations
68
+ *
69
+ * Callers use `scaleX`, `scaleY`, `oldRect`, and `resolvedRect` to scale
70
+ * their own type-specific data (vertices, linePoints, etc.), then spread
71
+ * `rects` into their result.
72
+ */
73
+ export declare function baseResizeScaling(orig: RotatableAnnotation, newRect: Rect, metadata?: {
74
+ maintainAspectRatio?: boolean;
75
+ }): ResizeScalingResult;
76
+ /**
77
+ * Compute the orbit translation (dx/dy) from a rotation result.
78
+ * Point-based annotations (line, polyline, polygon, ink) use this to
79
+ * translate their vertices/points alongside the rect orbit during
80
+ * group rotation. For single-annotation rotation the delta is zero.
81
+ */
82
+ export declare function rotateOrbitDelta(orig: RotatableAnnotation, rotateResult: {
83
+ unrotatedRect?: Rect;
84
+ }): {
85
+ dx: number;
86
+ dy: number;
87
+ };
@@ -2,3 +2,4 @@ export * from './patch-utils';
2
2
  export * from './line-ending-handlers';
3
3
  export * from './line-endings';
4
4
  export * from './patch-registry';
5
+ export * from './insert-upright';
@@ -0,0 +1,20 @@
1
+ import { PdfAnnotationObject, Rotation, Size } from '@embedpdf/models';
2
+ /**
3
+ * Applies a counter-rotation to make an annotation appear visually upright
4
+ * on a rotated page. Uses `basePropertyRotationChanges` to correctly compute
5
+ * rect, unrotatedRect, and rotation for the annotation.
6
+ *
7
+ * @param annotation - The annotation to transform
8
+ * @param pageRotation - Effective page rotation as quarter-turn value (0-3)
9
+ * @param rectWasDrawn - `true` if the rect was produced by a marquee drag
10
+ * (PagePointerProvider transposes dimensions on 90/270 pages),
11
+ * `false` if the rect was placed from config/content (click-to-place, stamp)
12
+ * @returns The annotation with rotation, unrotatedRect, and rect set
13
+ */
14
+ export declare function applyInsertUpright<T extends PdfAnnotationObject>(annotation: T, pageRotation: Rotation, rectWasDrawn: boolean): T;
15
+ /**
16
+ * Clamps an annotation's rect to stay within page bounds.
17
+ * If the annotation has an unrotatedRect, it is shifted by the same delta
18
+ * to keep the geometry consistent.
19
+ */
20
+ export declare function clampAnnotationToPage<T extends PdfAnnotationObject>(annotation: T, pageSize: Size): T;
@@ -1,12 +1,25 @@
1
1
  import { PdfAnnotationObject, PdfAnnotationSubtype } from '@embedpdf/models';
2
2
  export interface TransformContext<T extends PdfAnnotationObject = PdfAnnotationObject> {
3
3
  /** The type of transformation being applied */
4
- type: 'move' | 'resize' | 'vertex-edit' | 'property-update';
4
+ type: 'move' | 'resize' | 'vertex-edit' | 'rotate' | 'property-update';
5
5
  /** The changes being applied - can be any properties of the annotation */
6
6
  changes: Partial<T>;
7
7
  /** Optional metadata about the transformation */
8
8
  metadata?: {
9
9
  maintainAspectRatio?: boolean;
10
+ /** Rotation angle in degrees (for 'rotate' transform type) */
11
+ rotationAngle?: number;
12
+ /** Delta from the initial rotation angle in degrees */
13
+ rotationDelta?: number;
14
+ /** Center point for rotation (defaults to rect center) */
15
+ rotationCenter?: {
16
+ x: number;
17
+ y: number;
18
+ };
19
+ /** Whether the rotation input is currently snapped */
20
+ isSnapped?: boolean;
21
+ /** Snap target angle when isSnapped is true */
22
+ snappedAngle?: number;
10
23
  [key: string]: any;
11
24
  };
12
25
  }
@@ -1,7 +1,60 @@
1
- import { Rect, Position, LineEndings } from '@embedpdf/models';
1
+ import { Rect, Position, LineEndings, getRectCenter, rotatePointAround, rotateVertices, calculateRotatedRectAABB, calculateRotatedRectAABBAroundPoint } from '@embedpdf/models';
2
+ export { rotatePointAround as rotatePointAroundCenter, rotateVertices, getRectCenter, calculateRotatedRectAABB, calculateRotatedRectAABBAroundPoint, };
3
+ /**
4
+ * Calculate the axis-aligned bounding box for rotated vertices.
5
+ * @param vertices - The rotated vertices
6
+ * @param padding - Optional padding to add around the bounding box
7
+ * @returns The axis-aligned bounding box
8
+ */
9
+ export declare function calculateAABBFromVertices(vertices: Position[], padding?: number): Rect;
2
10
  /**
3
11
  * Computes the exact bounding box for a line or polyline, including its endings and stroke width.
4
12
  * This function uses the central `LINE_ENDING_HANDLERS` to ensure calculations are
5
13
  * perfectly in sync with the rendering logic.
6
14
  */
7
15
  export declare function lineRectWithEndings(vertices: Position[], strokeWidth: number, endings: LineEndings | undefined): Rect;
16
+ /**
17
+ * Build rect patches for vertex editing.
18
+ * For rotated annotations, the tight rect is kept as unrotatedRect and the AABB is
19
+ * computed around the new content center so rotation UI follows the edited geometry.
20
+ */
21
+ export declare function resolveVertexEditRects(original: {
22
+ rect: Rect;
23
+ unrotatedRect?: Rect;
24
+ rotation?: number;
25
+ }, tightRect: Rect): {
26
+ rect: Rect;
27
+ unrotatedRect?: Rect;
28
+ };
29
+ /**
30
+ * Resolve an annotation's effective rotation center in page coordinates.
31
+ */
32
+ export declare function resolveAnnotationRotationCenter(original: {
33
+ rect: Rect;
34
+ unrotatedRect?: Rect;
35
+ rotation?: number;
36
+ }): Position;
37
+ /**
38
+ * Build rotate patches while preserving an annotation's effective rotation center.
39
+ * The incoming unrotated rect may already include a translation (group rotation/orbit).
40
+ */
41
+ export declare function resolveRotateRects(original: {
42
+ rect: Rect;
43
+ unrotatedRect?: Rect;
44
+ rotation?: number;
45
+ }, nextUnrotatedRect: Rect, angleDegrees: number): {
46
+ rect: Rect;
47
+ unrotatedRect: Rect;
48
+ };
49
+ /**
50
+ * Compensate vertices for rotated vertex editing so the dragged point tracks the cursor
51
+ * while the rotation center follows edited geometry.
52
+ *
53
+ * Without this compensation, changing the tight bounds center during a rotated vertex edit
54
+ * applies an additional translation to all points, which appears as opposite-end drift.
55
+ */
56
+ export declare function compensateRotatedVertexEdit(original: {
57
+ rect: Rect;
58
+ unrotatedRect?: Rect;
59
+ rotation?: number;
60
+ }, vertices: Position[], tightRect: Rect): Position[];
@@ -0,0 +1,3 @@
1
+ import { PdfCircleAnnoObject } from '@embedpdf/models';
2
+ import { PatchFunction } from '../patch-registry';
3
+ export declare const patchCircle: PatchFunction<PdfCircleAnnoObject>;
@@ -0,0 +1,3 @@
1
+ import { PdfFreeTextAnnoObject } from '@embedpdf/models';
2
+ import { PatchFunction } from '../patch-registry';
3
+ export declare const patchFreeText: PatchFunction<PdfFreeTextAnnoObject>;
@@ -2,3 +2,7 @@ export * from './ink.patch';
2
2
  export * from './line.patch';
3
3
  export * from './polyline.patch';
4
4
  export * from './polygon.patch';
5
+ export * from './circle.patch';
6
+ export * from './square.patch';
7
+ export * from './freetext.patch';
8
+ export * from './stamp.patch';
@@ -0,0 +1,3 @@
1
+ import { PdfSquareAnnoObject } from '@embedpdf/models';
2
+ import { PatchFunction } from '../patch-registry';
3
+ export declare const patchSquare: PatchFunction<PdfSquareAnnoObject>;
@@ -0,0 +1,3 @@
1
+ import { PdfStampAnnoObject } from '@embedpdf/models';
2
+ import { PatchFunction } from '../patch-registry';
3
+ export declare const patchStamp: PatchFunction<PdfStampAnnoObject>;
@@ -12,6 +12,7 @@ export declare const defaultTools: ({
12
12
  isGroupResizable: false;
13
13
  cursor?: undefined;
14
14
  lockAspectRatio?: undefined;
15
+ lockGroupAspectRatio?: undefined;
15
16
  };
16
17
  defaults: {
17
18
  type: PdfAnnotationSubtype.HIGHLIGHT;
@@ -32,6 +33,7 @@ export declare const defaultTools: ({
32
33
  backgroundColor?: undefined;
33
34
  };
34
35
  clickBehavior?: undefined;
36
+ behavior?: undefined;
35
37
  } | {
36
38
  id: "underline";
37
39
  name: string;
@@ -45,6 +47,7 @@ export declare const defaultTools: ({
45
47
  isGroupResizable: false;
46
48
  cursor?: undefined;
47
49
  lockAspectRatio?: undefined;
50
+ lockGroupAspectRatio?: undefined;
48
51
  };
49
52
  defaults: {
50
53
  type: PdfAnnotationSubtype.UNDERLINE;
@@ -65,6 +68,7 @@ export declare const defaultTools: ({
65
68
  backgroundColor?: undefined;
66
69
  };
67
70
  clickBehavior?: undefined;
71
+ behavior?: undefined;
68
72
  } | {
69
73
  id: "strikeout";
70
74
  name: string;
@@ -78,6 +82,7 @@ export declare const defaultTools: ({
78
82
  isGroupResizable: false;
79
83
  cursor?: undefined;
80
84
  lockAspectRatio?: undefined;
85
+ lockGroupAspectRatio?: undefined;
81
86
  };
82
87
  defaults: {
83
88
  type: PdfAnnotationSubtype.STRIKEOUT;
@@ -98,6 +103,7 @@ export declare const defaultTools: ({
98
103
  backgroundColor?: undefined;
99
104
  };
100
105
  clickBehavior?: undefined;
106
+ behavior?: undefined;
101
107
  } | {
102
108
  id: "squiggly";
103
109
  name: string;
@@ -111,6 +117,7 @@ export declare const defaultTools: ({
111
117
  isGroupResizable: false;
112
118
  cursor?: undefined;
113
119
  lockAspectRatio?: undefined;
120
+ lockGroupAspectRatio?: undefined;
114
121
  };
115
122
  defaults: {
116
123
  type: PdfAnnotationSubtype.SQUIGGLY;
@@ -131,6 +138,7 @@ export declare const defaultTools: ({
131
138
  backgroundColor?: undefined;
132
139
  };
133
140
  clickBehavior?: undefined;
141
+ behavior?: undefined;
134
142
  } | {
135
143
  id: "ink";
136
144
  name: string;
@@ -144,6 +152,7 @@ export declare const defaultTools: ({
144
152
  textSelection?: undefined;
145
153
  isGroupDraggable?: undefined;
146
154
  isGroupResizable?: undefined;
155
+ lockGroupAspectRatio?: undefined;
147
156
  };
148
157
  defaults: {
149
158
  type: PdfAnnotationSubtype.INK;
@@ -164,6 +173,7 @@ export declare const defaultTools: ({
164
173
  backgroundColor?: undefined;
165
174
  };
166
175
  clickBehavior?: undefined;
176
+ behavior?: undefined;
167
177
  } | {
168
178
  id: "inkHighlighter";
169
179
  name: string;
@@ -174,6 +184,7 @@ export declare const defaultTools: ({
174
184
  isDraggable: true;
175
185
  isResizable: true;
176
186
  lockAspectRatio: false;
187
+ lockGroupAspectRatio: (a: import('@embedpdf/models').PdfAnnotationObject) => boolean;
177
188
  textSelection?: undefined;
178
189
  isGroupDraggable?: undefined;
179
190
  isGroupResizable?: undefined;
@@ -197,6 +208,7 @@ export declare const defaultTools: ({
197
208
  backgroundColor?: undefined;
198
209
  };
199
210
  clickBehavior?: undefined;
211
+ behavior?: undefined;
200
212
  } | {
201
213
  id: "circle";
202
214
  name: string;
@@ -207,6 +219,7 @@ export declare const defaultTools: ({
207
219
  isDraggable: true;
208
220
  isResizable: true;
209
221
  lockAspectRatio: false;
222
+ lockGroupAspectRatio: (a: import('@embedpdf/models').PdfAnnotationObject) => boolean;
210
223
  textSelection?: undefined;
211
224
  isGroupDraggable?: undefined;
212
225
  isGroupResizable?: undefined;
@@ -239,6 +252,7 @@ export declare const defaultTools: ({
239
252
  defaultAngle?: undefined;
240
253
  defaultContent?: undefined;
241
254
  };
255
+ behavior?: undefined;
242
256
  } | {
243
257
  id: "square";
244
258
  name: string;
@@ -249,6 +263,7 @@ export declare const defaultTools: ({
249
263
  isDraggable: true;
250
264
  isResizable: true;
251
265
  lockAspectRatio: false;
266
+ lockGroupAspectRatio: (a: import('@embedpdf/models').PdfAnnotationObject) => boolean;
252
267
  textSelection?: undefined;
253
268
  isGroupDraggable?: undefined;
254
269
  isGroupResizable?: undefined;
@@ -281,6 +296,7 @@ export declare const defaultTools: ({
281
296
  defaultAngle?: undefined;
282
297
  defaultContent?: undefined;
283
298
  };
299
+ behavior?: undefined;
284
300
  } | {
285
301
  id: "line";
286
302
  name: string;
@@ -292,6 +308,7 @@ export declare const defaultTools: ({
292
308
  isResizable: false;
293
309
  lockAspectRatio: false;
294
310
  isGroupResizable: true;
311
+ lockGroupAspectRatio: (a: import('@embedpdf/models').PdfAnnotationObject) => boolean;
295
312
  textSelection?: undefined;
296
313
  isGroupDraggable?: undefined;
297
314
  };
@@ -320,6 +337,7 @@ export declare const defaultTools: ({
320
337
  defaultSize?: undefined;
321
338
  defaultContent?: undefined;
322
339
  };
340
+ behavior?: undefined;
323
341
  } | {
324
342
  id: "lineArrow";
325
343
  name: string;
@@ -331,6 +349,7 @@ export declare const defaultTools: ({
331
349
  isResizable: false;
332
350
  lockAspectRatio: false;
333
351
  isGroupResizable: true;
352
+ lockGroupAspectRatio: (a: import('@embedpdf/models').PdfAnnotationObject) => boolean;
334
353
  textSelection?: undefined;
335
354
  isGroupDraggable?: undefined;
336
355
  };
@@ -362,6 +381,7 @@ export declare const defaultTools: ({
362
381
  defaultSize?: undefined;
363
382
  defaultContent?: undefined;
364
383
  };
384
+ behavior?: undefined;
365
385
  } | {
366
386
  id: "polyline";
367
387
  name: string;
@@ -373,6 +393,7 @@ export declare const defaultTools: ({
373
393
  isResizable: false;
374
394
  lockAspectRatio: false;
375
395
  isGroupResizable: true;
396
+ lockGroupAspectRatio: (a: import('@embedpdf/models').PdfAnnotationObject) => boolean;
376
397
  textSelection?: undefined;
377
398
  isGroupDraggable?: undefined;
378
399
  };
@@ -395,6 +416,7 @@ export declare const defaultTools: ({
395
416
  backgroundColor?: undefined;
396
417
  };
397
418
  clickBehavior?: undefined;
419
+ behavior?: undefined;
398
420
  } | {
399
421
  id: "polygon";
400
422
  name: string;
@@ -406,6 +428,7 @@ export declare const defaultTools: ({
406
428
  isResizable: false;
407
429
  lockAspectRatio: false;
408
430
  isGroupResizable: true;
431
+ lockGroupAspectRatio: (a: import('@embedpdf/models').PdfAnnotationObject) => boolean;
409
432
  textSelection?: undefined;
410
433
  isGroupDraggable?: undefined;
411
434
  };
@@ -428,6 +451,7 @@ export declare const defaultTools: ({
428
451
  backgroundColor?: undefined;
429
452
  };
430
453
  clickBehavior?: undefined;
454
+ behavior?: undefined;
431
455
  } | {
432
456
  id: "freeText";
433
457
  name: string;
@@ -438,6 +462,7 @@ export declare const defaultTools: ({
438
462
  isDraggable: true;
439
463
  isResizable: true;
440
464
  lockAspectRatio: false;
465
+ lockGroupAspectRatio: (a: import('@embedpdf/models').PdfAnnotationObject) => boolean;
441
466
  textSelection?: undefined;
442
467
  isGroupDraggable?: undefined;
443
468
  isGroupResizable?: undefined;
@@ -470,6 +495,9 @@ export declare const defaultTools: ({
470
495
  defaultLength?: undefined;
471
496
  defaultAngle?: undefined;
472
497
  };
498
+ behavior: {
499
+ insertUpright: true;
500
+ };
473
501
  } | {
474
502
  id: "stamp";
475
503
  name: string;
@@ -480,6 +508,7 @@ export declare const defaultTools: ({
480
508
  isDraggable: true;
481
509
  isResizable: true;
482
510
  lockAspectRatio: true;
511
+ lockGroupAspectRatio: true;
483
512
  textSelection?: undefined;
484
513
  isGroupDraggable?: undefined;
485
514
  isGroupResizable?: undefined;
@@ -502,5 +531,8 @@ export declare const defaultTools: ({
502
531
  verticalAlign?: undefined;
503
532
  backgroundColor?: undefined;
504
533
  };
534
+ behavior: {
535
+ insertUpright: true;
536
+ };
505
537
  clickBehavior?: undefined;
506
538
  })[];
@@ -70,6 +70,19 @@ type GetToolConfig<T extends PdfAnnotationObject> = T['type'] extends keyof Tool
70
70
  type ClickBehaviorFor<T extends PdfAnnotationObject> = Extract<T['type'], keyof ClickBehaviorMap> extends never ? {} : {
71
71
  clickBehavior?: ClickBehaviorMap[Extract<T['type'], keyof ClickBehaviorMap>];
72
72
  };
73
+ /**
74
+ * Map of annotation types that support the insertUpright behavior.
75
+ * Only types with a "natural upright orientation" (readable text, image content)
76
+ * should be listed here.
77
+ */
78
+ export interface InsertUprightBehaviorMap {
79
+ [PdfAnnotationSubtype.STAMP]: true;
80
+ [PdfAnnotationSubtype.FREETEXT]: true;
81
+ }
82
+ type InsertUprightBehaviorFor<T extends PdfAnnotationObject> = Extract<T['type'], keyof InsertUprightBehaviorMap> extends never ? {} : {
83
+ /** Counter-rotate new annotations to appear visually upright on rotated pages. */
84
+ insertUpright?: boolean;
85
+ };
73
86
  /**
74
87
  * The primary interface for defining an annotation tool.
75
88
  * Uses a type alias to properly combine the base interface with conditional properties.
@@ -100,12 +113,18 @@ export type AnnotationTool<T extends PdfAnnotationObject = PdfAnnotationObject>
100
113
  isDraggable?: DynamicBooleanProp;
101
114
  /** Whether this annotation can be resized when selected individually. Can be dynamic based on annotation. */
102
115
  isResizable?: DynamicBooleanProp;
116
+ /** Whether this annotation can be rotated when selected individually. Can be dynamic based on annotation. */
117
+ isRotatable?: DynamicBooleanProp;
103
118
  /** Whether to maintain aspect ratio during resize. Can be dynamic based on annotation. */
104
119
  lockAspectRatio?: DynamicBooleanProp;
120
+ /** Whether to maintain aspect ratio during group resize. Defaults to lockAspectRatio. Can be dynamic based on annotation. */
121
+ lockGroupAspectRatio?: DynamicBooleanProp;
105
122
  /** Whether this annotation can be dragged when part of a group. Defaults to isDraggable. Can be dynamic based on annotation. */
106
123
  isGroupDraggable?: DynamicBooleanProp;
107
124
  /** Whether this annotation can be resized when part of a group. Defaults to isResizable. Can be dynamic based on annotation. */
108
125
  isGroupResizable?: DynamicBooleanProp;
126
+ /** Whether this annotation can be rotated when part of a group. Defaults to isRotatable. Can be dynamic based on annotation. */
127
+ isGroupRotatable?: DynamicBooleanProp;
109
128
  };
110
129
  /** Tool-specific behavior settings that override plugin defaults */
111
130
  behavior?: {
@@ -113,6 +132,6 @@ export type AnnotationTool<T extends PdfAnnotationObject = PdfAnnotationObject>
113
132
  deactivateToolAfterCreate?: boolean;
114
133
  /** When true, select the annotation immediately after creation. Overrides plugin config. */
115
134
  selectAfterCreate?: boolean;
116
- };
135
+ } & InsertUprightBehaviorFor<T>;
117
136
  } & ClickBehaviorFor<T>;
118
137
  export {};