@linkurious/ogma-annotations 1.1.27 → 2.0.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.
@@ -1,41 +1,71 @@
1
1
  import { BBox } from 'geojson';
2
2
  import { default as default_2 } from 'eventemitter3';
3
- import { default as default_3 } from '@linkurious/ogma';
4
3
  import { Feature } from 'geojson';
5
4
  import { FeatureCollection } from 'geojson';
6
5
  import { Geometry } from 'geojson';
7
6
  import { GeometryObject } from 'geojson';
8
7
  import { LineString } from 'geojson';
9
- import { Options } from '@linkurious/ogma';
10
- import { Overlay } from '@linkurious/ogma';
11
- import { Point as Point_2 } from '@linkurious/ogma';
12
- import { Polygon } from 'geojson';
8
+ import { Node as Node_2 } from '@linkurious/ogma';
9
+ import { Ogma } from '@linkurious/ogma';
10
+ import { Point as Point_2 } from 'geojson';
11
+ import { Point as Point_3 } from '@linkurious/ogma';
12
+ import { Polygon as Polygon_2 } from 'geojson';
13
13
  import { Position } from 'geojson';
14
- import { SVGLayer } from '@linkurious/ogma';
14
+ import { Size } from '@linkurious/ogma';
15
15
 
16
- export declare type Annotation = Arrow | Text_2;
16
+ /**
17
+ * Automatically lightens or darkens a color (hex or rgba) for highlight purposes.
18
+ * @param color - Color string in hex (#RRGGBB or #RGB) or rgba format
19
+ * @param amount - Amount to lighten/darken (default 20 for lighter and -10 for darker)
20
+ * @returns Highlighted color in rgba format
21
+ */
22
+ export declare function adjustColorBrightness(color: Color, amount: number): RgbaColor;
23
+
24
+ /** Union type of all Annotation features */
25
+ export declare type Annotation = Arrow | Box | Text_2 | Comment_2 | Polygon;
17
26
 
27
+ /** Collection of Annotations, GeoJSON FeatureCollection */
18
28
  export declare interface AnnotationCollection extends FeatureCollection {
19
- features: (Arrow | Text_2)[];
29
+ features: Annotation[];
20
30
  }
21
31
 
32
+ /**
33
+ * Base interface for all annotation features.
34
+ * @template G - Geometry type
35
+ * @template P - Properties type
36
+ */
22
37
  export declare interface AnnotationFeature<G extends GeometryObject = GeometryObject, P = AnnotationProps> extends Feature<G, P> {
23
- id: string | number;
38
+ /** Unique identifier for the annotation */
39
+ id: Id;
24
40
  }
25
41
 
42
+ /** Function type to get an Annotation by its id */
43
+ export declare type AnnotationGetter = (id: Id) => Annotation | undefined;
44
+
26
45
  export declare type AnnotationOptions = {
27
46
  handleSize: number;
28
- placeholder: string;
47
+ placeholder?: string;
29
48
  };
30
49
 
50
+ /**
51
+ * Base properties for all annotations.
52
+ */
31
53
  export declare interface AnnotationProps {
54
+ /** Type of annotation */
32
55
  type: AnnotationType;
56
+ /** Optional style configuration */
33
57
  style?: unknown;
34
58
  }
35
59
 
36
- declare type AnnotationType = "arrow" | "text";
60
+ /** Types of annotations supported */
61
+ export declare type AnnotationType = "arrow" | "text" | "box" | "comment" | "polygon";
37
62
 
38
- export declare type Arrow = AnnotationFeature<LineString, ArrowProperties>;
63
+ /**
64
+ * Arrow annotation feature. Represents a directed line between two points,
65
+ * can connect a textbox to a shape.
66
+ */
67
+ export declare interface Arrow extends AnnotationFeature<LineString, ArrowProperties> {
68
+ }
39
69
 
40
70
  export declare interface ArrowProperties extends AnnotationProps {
41
71
  type: "arrow";
@@ -44,45 +74,39 @@ export declare interface ArrowProperties extends AnnotationProps {
44
74
  }
45
75
 
46
76
  /**
47
- * @class Arrows
48
- * Draw and edit arrows
49
- */
50
- export declare class Arrows extends Editor<Arrow> {
51
- private draggedHandle;
52
- private start;
53
- private end;
54
- private arrow;
55
- private startX;
56
- private startY;
57
- private minArrowHeight;
58
- private maxArrowHeight;
59
- private handles;
60
- constructor(ogma: default_3, options?: Pick<Partial<ControllerOptions>, "arrowHandleSize" | "maxArrowHeight" | "minArrowHeight">);
61
- private onHandleMouseDown;
62
- /**
63
- * Start drawing a new arrow, it will also be added as a new annotation
64
- * @param x
65
- * @param y
66
- * @param arrow
67
- */
68
- startDrawing(x: number, y: number, arrow?: Arrow): void;
69
- cancelDrawing(): void;
70
- private startDragging;
71
- private onMouseUp;
72
- private onMouseMove;
73
- detect(point: Point_2, margin?: number): Arrow | undefined;
74
- refreshEditor(): void;
75
- getDefaultOptions(): Arrow;
76
- draw(svg: SVGSVGElement): void;
77
- refreshDrawing(): void;
78
- destroy(): void;
79
- }
80
-
77
+ * Styles specific to arrow annotations.
78
+ */
81
79
  export declare interface ArrowStyles extends StrokeOptions {
80
+ /** Tail extremity style */
82
81
  tail?: Extremity;
82
+ /** Head extremity style */
83
83
  head?: Extremity;
84
84
  }
85
85
 
86
+ /**
87
+ * Safely cast a string to a Color type with runtime validation
88
+ * @throws {Error} if the color format is invalid
89
+ */
90
+ export declare function asColor(color: string): Color;
91
+
92
+ /**
93
+ * Safely cast a string to a HexColor type with runtime validation
94
+ * @throws {Error} if the color format is invalid
95
+ */
96
+ export declare function asHexColor(color: string): HexColor;
97
+
98
+ /**
99
+ * Safely cast a string to an RgbaColor type with runtime validation
100
+ * @throws {Error} if the color format is invalid
101
+ */
102
+ export declare function asRgbaColor(color: string): RgbaColor;
103
+
104
+ /**
105
+ * Safely cast a string to an RgbColor type with runtime validation
106
+ * @throws {Error} if the color format is invalid
107
+ */
108
+ export declare function asRgbColor(color: string): RgbColor;
109
+
86
110
  /**
87
111
  * Bounding box object, with the following properties:
88
112
  * - [0]: min x
@@ -92,130 +116,706 @@ export declare interface ArrowStyles extends StrokeOptions {
92
116
  */
93
117
  export declare type Bounds = [number, number, number, number];
94
118
 
95
- export declare function clientToContainerPosition(evt: {
119
+ /**
120
+ * Box annotation feature
121
+ */
122
+ export declare interface Box extends AnnotationFeature<Point_2, BoxProperties> {
123
+ }
124
+
125
+ /** Properties specific to box annotations. */
126
+ export declare interface BoxProperties extends AnnotationProps {
127
+ type: "box";
128
+ /** Width of the box */
129
+ width: number;
130
+ /** Height of the box */
131
+ height: number;
132
+ /** Style options for the box */
133
+ style?: BoxStyle;
134
+ }
135
+
136
+ /** Styles specific to box annotations. */
137
+ export declare interface BoxStyle extends StrokeOptions {
138
+ /** background color: empty for transparent #f00, yellow...*/
139
+ background?: Color;
140
+ /** padding around the box */
141
+ padding?: number;
142
+ /** border radius */
143
+ borderRadius?: number;
144
+ /** if true, the box scales with zoom. Default is true */
145
+ scaled?: boolean;
146
+ /** box shadow in CSS format, e.g. "0px 4px 6px rgba(0, 0, 0, 0.1)" */
147
+ boxShadow?: string;
148
+ }
149
+
150
+ /**
151
+ * Brighten a color for highlight purposes.
152
+ * @param color - Color string in hex (#RRGGBB or #RGB) or rgba format
153
+ * @returns
154
+ */
155
+ export declare const brighten: (color: Color) => RgbaColor;
156
+
157
+ /**
158
+ * Calculate optimal zoom threshold for auto-collapse based on comment dimensions
159
+ *
160
+ * The threshold is computed so that the comment collapses when its screen-space
161
+ * size would be smaller than a minimum readable size.
162
+ *
163
+ * @param comment - Comment annotation
164
+ * @param minReadableWidth - Minimum readable width in pixels (default: 80)
165
+ * @returns Zoom threshold below which comment should collapse
166
+ *
167
+ * @example
168
+ * // A 200px wide comment with minReadable=80 will collapse at zoom < 0.4
169
+ * // because 200 * 0.4 = 80
170
+ */
171
+ export declare function calculateCommentZoomThreshold(comment: Comment_2, minReadableWidth?: number): number;
172
+
173
+ /**
174
+ * Check if arrow endpoint can be detached from its target
175
+ *
176
+ * Always returns true since arrow endpoints can be freely retargeted,
177
+ * even for comment arrows. The comment is typically on the start side.
178
+ *
179
+ * @param _arrow - The arrow feature (unused, kept for API consistency)
180
+ * @returns Always true - arrow ends can be detached
181
+ *
182
+ * @example
183
+ * ```typescript
184
+ * if (canDetachArrowEnd(arrow)) {
185
+ * // Allow user to drag arrow end point
186
+ * }
187
+ * ```
188
+ */
189
+ export declare function canDetachArrowEnd(_arrow: Arrow): boolean;
190
+
191
+ /**
192
+ * Check if arrow start point can be detached from its source
193
+ *
194
+ * Returns false for arrows originating FROM comments, since comment arrows
195
+ * must always remain attached to the comment on their start side.
196
+ *
197
+ * @param arrow - The arrow feature
198
+ * @returns True if arrow start can be detached
199
+ *
200
+ * @example
201
+ * ```typescript
202
+ * if (canDetachArrowStart(arrow)) {
203
+ * // Allow user to drag arrow start point
204
+ * } else {
205
+ * // Keep arrow start locked to comment
206
+ * }
207
+ * ```
208
+ */
209
+ export declare function canDetachArrowStart(arrow: Arrow): boolean;
210
+
211
+ /** Event related to a single annotation feature */
212
+ export declare interface ClickEvent {
213
+ /** Annotation ID involved in the event */
214
+ id?: Id;
215
+ /** Mouse position in pixel coordinates */
216
+ position: {
217
+ x: number;
218
+ y: number;
219
+ };
220
+ }
221
+
222
+ export declare type ClientMouseEvent = {
96
223
  clientX: number;
97
224
  clientY: number;
98
- }, container?: HTMLElement | null): {
225
+ };
226
+
227
+ export declare function clientToContainerPosition(evt: ClientMouseEvent, container?: HTMLElement | null): {
99
228
  x: number;
100
229
  y: number;
101
230
  };
102
231
 
103
- export declare function colorToRgba(color: string, alpha: number): string;
232
+ /**
233
+ * Any valid color format
234
+ */
235
+ export declare type Color = HexColor | RgbColor | RgbaColor | "transparent" | "none" | string;
236
+
237
+ export declare function colorToRgba(color: Color, alpha: number): RgbaColor;
104
238
 
239
+ /**
240
+ * Comment annotation type
241
+ * Geometry: Point (center position of comment box/icon)
242
+ *
243
+ * Note: Arrows are stored separately in Arrow features.
244
+ * Arrows reference comments via their link.start or link.end properties.
245
+ */
246
+ declare interface Comment_2 extends AnnotationFeature<Point_2, CommentProps> {
247
+ }
248
+ export { Comment_2 as Comment }
249
+
250
+ export declare const COMMENT_MODE_COLLAPSED = "collapsed";
251
+
252
+ export declare const COMMENT_MODE_EXPANDED = "expanded";
253
+
254
+ /**
255
+ * Properties for Comment annotations
256
+ *
257
+ * Comments are specialized annotations that:
258
+ * - Always maintain fixed screen-space size
259
+ * - Always have at least one arrow pointing TO them
260
+ * - Can be collapsed (icon) or expanded (text box)
261
+ * - Support multiple arrows pointing to them
262
+ */
263
+ export declare interface CommentProps extends AnnotationProps {
264
+ type: "comment";
265
+ /** Text content (similar to text annotation) */
266
+ content: string;
267
+ /** Display mode: collapsed (icon) or expanded (text box) */
268
+ mode: typeof COMMENT_MODE_COLLAPSED | typeof COMMENT_MODE_EXPANDED;
269
+ /** Width in expanded mode (pixels) */
270
+ width: number;
271
+ /** Height (auto-grows with content, pixels) */
272
+ height: number;
273
+ /** Optional metadata */
274
+ author?: string;
275
+ timestamp?: Date;
276
+ /** Styling */
277
+ style?: CommentStyle;
278
+ }
279
+
280
+ /**
281
+ * Style configuration for Comment annotations
282
+ */
283
+ export declare interface CommentStyle extends TextStyle {
284
+ /** Background color for collapsed icon (default: "#FFD700") */
285
+ iconColor?: Color;
286
+ /** Icon to display when collapsed (default: "💬") */
287
+ iconSymbol?: string;
288
+ /** Border color for collapsed icon */
289
+ iconBorderColor?: Color;
290
+ /** Border width for collapsed icon */
291
+ iconBorderWidth?: number;
292
+ /** Minimum height (default: 60px) */
293
+ minHeight?: number;
294
+ /** Maximum height before scrolling (default: 480px, undefined = no limit) */
295
+ maxHeight?: number;
296
+ /** Size when collapsed (default: 32px) */
297
+ iconSize?: number;
298
+ /** Zoom threshold below which comment auto-collapses (default: 0.5) */
299
+ collapseZoomThreshold?: number;
300
+ /** Show "send" button in edit mode (default: true) */
301
+ showSendButton?: boolean;
302
+ /** Auto-grow height with content (default: true) */
303
+ autoGrow?: boolean;
304
+ }
305
+
306
+ /**
307
+ * Main controller class for managing annotations.
308
+ * It manages rendering and editing of annotations.
309
+ */
105
310
  export declare class Control extends default_2<FeatureEvents> {
106
- private arrows;
107
- private texts;
108
- private links;
109
- private layer;
110
- private annotations;
111
311
  private ogma;
112
- private options;
113
- private selected;
114
- private updateTimeout;
115
- private hoveredNode;
116
- private dragged;
117
- private textToMagnet;
118
- private activeLinks;
119
- constructor(ogma: default_3, options?: Partial<ControllerOptions>);
120
- private _render;
121
- private _onFeatureDrag;
122
- private _onFeatureDragEnd;
123
- private _onFeatureDragStart;
124
- private _onNodesDragStart;
125
- private _onNodesDrag;
126
- private _onLayoutEnd;
127
- private _moveNodes;
128
- private _snapToText;
129
- private _findAndSnapToNode;
130
- private _snapToNode;
131
- private _onAdded;
132
- private _onRemoved;
133
- private _onUnselect;
134
- private _onSelect;
135
- private refreshTextLinks;
136
- /**
137
- * @returns the currently selected annotation
138
- */
139
- getSelected(): Annotation | null;
140
- private findMagnetPoint;
312
+ private store;
313
+ private renderers;
314
+ private interactions;
315
+ private editor;
316
+ private links;
317
+ private index;
318
+ private drawing;
319
+ private snapping;
320
+ private selectionManager;
321
+ private historyManager;
322
+ private updateManager;
323
+ private commentManager;
324
+ constructor(ogma: Ogma, options?: Partial<ControllerOptions>);
325
+ private initializeRenderers;
326
+ private setupEvents;
327
+ private onRotate;
328
+ private onZoom;
329
+ private onLayout;
141
330
  /**
142
331
  * Set the options for the controller
143
332
  * @param options new Options
144
333
  * @returns the updated options
145
334
  */
146
- setOptions(options?: Partial<ControllerOptions>): ControllerOptions;
147
- /**
148
- * Selects the annotation with the given id
149
- * @param id the id of the annotation to select
150
- */
151
- select(id: Id): this;
152
- /**
153
- * Unselects the currently selected annotation
154
- */
155
- unselect(): this;
335
+ setOptions(options?: Partial<ControllerOptions>): {
336
+ showSendButton: boolean;
337
+ showEditButton: boolean;
338
+ sendButtonIcon: string;
339
+ editButtonIcon: string;
340
+ minArrowHeight: number;
341
+ maxArrowHeight: number;
342
+ detectMargin: number;
343
+ magnetRadius: number;
344
+ magnetHandleRadius: number;
345
+ textPlaceholder: string;
346
+ };
156
347
  /**
157
348
  * Add an annotation to the controller
158
349
  * @param annotation The annotation to add
159
350
  */
160
- add(annotation: Arrow | Text_2 | AnnotationCollection): this;
351
+ add(annotation: Annotation | AnnotationCollection): this;
161
352
  /**
162
353
  * Remove an annotation or an array of annotations from the controller
163
354
  * @param annotation The annotation(s) to remove
164
355
  */
165
- remove(annotation: Arrow | Text_2 | AnnotationCollection): this;
166
- private loadLink;
356
+ remove(annotation: Annotation | AnnotationCollection): this;
357
+ /**
358
+ * Undo the last change
359
+ * @returns true if undo was successful, false if no changes to undo
360
+ */
361
+ undo(): boolean;
362
+ /**
363
+ * Redo the last undone change
364
+ * @returns true if redo was successful, false if no changes to redo
365
+ */
366
+ redo(): boolean;
367
+ /**
368
+ * Check if there are changes to undo
369
+ * @returns true if undo is possible
370
+ */
371
+ canUndo(): boolean;
372
+ /**
373
+ * Check if there are changes to redo
374
+ * @returns true if redo is possible
375
+ */
376
+ canRedo(): boolean;
377
+ /**
378
+ * Clear the undo/redo history
379
+ */
380
+ clearHistory(): void;
381
+ /**
382
+ * Get all annotations in the controller
383
+ * @returns A FeatureCollection containing all annotations
384
+ */
385
+ getAnnotations(): AnnotationCollection;
386
+ /**
387
+ * Select one or more annotations by id
388
+ * @param annotations The id(s) of the annotation(s) to select
389
+ * @returns this for chaining
390
+ */
391
+ select(annotations: Id | Id[]): this;
392
+ /**
393
+ * Unselect one or more annotations, or all if no ids provided
394
+ * @param annotations The id(s) of the annotation(s) to unselect, or undefined to unselect all
395
+ * @returns this for chaining
396
+ */
397
+ unselect(annotations?: Id | Id[]): this;
398
+ /**
399
+ * Cancel the current drawing operation
400
+ * @returns this for chaining
401
+ */
402
+ cancelDrawing(): this;
403
+ /**
404
+ * Enable arrow drawing mode - the recommended way to add arrows.
405
+ *
406
+ * Call this method when the user clicks an "Add Arrow" button. The control will:
407
+ * 1. Wait for the next mousedown event
408
+ * 2. Create an arrow at that position with the specified style
409
+ * 3. Start the interactive drawing process
410
+ * 4. Clean up automatically when done
411
+ *
412
+ * **This is the recommended API for 99% of use cases.** Only use `startArrow()`
413
+ * if you need to implement custom mouse handling or positioning logic.
414
+ *
415
+ * @example
416
+ * ```ts
417
+ * addArrowButton.addEventListener('click', () => {
418
+ * control.enableArrowDrawing({ strokeColor: '#3A03CF', strokeWidth: 2 });
419
+ * });
420
+ * ```
421
+ *
422
+ * @param style Arrow style options
423
+ * @returns this for chaining
424
+ * @see startArrow for low-level programmatic control
425
+ */
426
+ enableArrowDrawing(style?: Partial<Arrow["properties"]["style"]>): this;
427
+ /**
428
+ * Enable text drawing mode - the recommended way to add text annotations.
429
+ *
430
+ * Call this method when the user clicks an "Add Text" button. The control will:
431
+ * 1. Wait for the next mousedown event
432
+ * 2. Create a text box at that position with the specified style
433
+ * 3. Start the interactive drawing/editing process
434
+ * 4. Clean up automatically when done
435
+ *
436
+ * **This is the recommended API for 99% of use cases.** Only use `startText()`
437
+ * if you need to implement custom mouse handling or positioning logic.
438
+ *
439
+ * @example
440
+ * ```ts
441
+ * addTextButton.addEventListener('click', () => {
442
+ * control.enableTextDrawing({ color: '#3A03CF', fontSize: 24 });
443
+ * });
444
+ * ```
445
+ *
446
+ * @param style Text style options
447
+ * @returns this for chaining
448
+ * @see startText for low-level programmatic control
449
+ */
450
+ enableTextDrawing(style?: Partial<Text_2["properties"]["style"]>): this;
451
+ /**
452
+ * Enable box drawing mode - the recommended way to add boxes.
453
+ *
454
+ * Call this method when the user clicks an "Add Box" button. The control will:
455
+ * 1. Wait for the next mousedown event
456
+ * 2. Create a box at that position with the specified style
457
+ * 3. Start the interactive drawing process (drag to size)
458
+ * 4. Clean up automatically when done
459
+ *
460
+ * **This is the recommended API for 99% of use cases.** Only use `startBox()`
461
+ * if you need to implement custom mouse handling or positioning logic.
462
+ *
463
+ * @example
464
+ * ```ts
465
+ * addBoxButton.addEventListener('click', () => {
466
+ * control.enableBoxDrawing({ background: '#EDE6FF', borderRadius: 8 });
467
+ * });
468
+ * ```
469
+ *
470
+ * @param style Box style options
471
+ * @returns this for chaining
472
+ * @see startBox for low-level programmatic control
473
+ */
474
+ enableBoxDrawing(style?: Partial<Box["properties"]["style"]>): this;
475
+ /**
476
+ * Enable polygon drawing mode - the recommended way to add polygons.
477
+ *
478
+ * Call this method when the user clicks an "Add Polygon" button. The control will:
479
+ * 1. Wait for the next mousedown event
480
+ * 2. Create a polygon starting at that position with the specified style
481
+ * 3. Start the interactive drawing process (click points to draw shape)
482
+ * 4. Clean up automatically when done
483
+ *
484
+ * **This is the recommended API for 99% of use cases.** Only use `startPolygon()`
485
+ * if you need to implement custom mouse handling or positioning logic.
486
+ *
487
+ * @example
488
+ * ```ts
489
+ * addPolygonButton.addEventListener('click', () => {
490
+ * control.enablePolygonDrawing({ strokeColor: '#3A03CF', background: 'rgba(58, 3, 207, 0.15)' });
491
+ * });
492
+ * ```
493
+ *
494
+ * @param style Polygon style options
495
+ * @returns this for chaining
496
+ * @see startPolygon for low-level programmatic control
497
+ */
498
+ enablePolygonDrawing(style?: Partial<Polygon["properties"]["style"]>): this;
499
+ /**
500
+ * Enable comment drawing mode - the recommended way to add comments.
501
+ *
502
+ * Call this method when the user clicks an "Add Comment" button. The control will:
503
+ * 1. Wait for the next mousedown event
504
+ * 2. Create a comment with an arrow pointing to that position
505
+ * 3. Smart positioning: automatically finds the best placement for the comment box
506
+ * 4. Start the interactive editing process
507
+ * 5. Clean up automatically when done
508
+ *
509
+ * **This is the recommended API for 99% of use cases.** Only use `startComment()`
510
+ * if you need to implement custom mouse handling or positioning logic.
511
+ *
512
+ * @example
513
+ * ```ts
514
+ * addCommentButton.addEventListener('click', () => {
515
+ * control.enableCommentDrawing({
516
+ * commentStyle: { color: '#3A03CF', background: '#EDE6FF' },
517
+ * arrowStyle: { strokeColor: '#3A03CF', head: 'halo-dot' }
518
+ * });
519
+ * });
520
+ * ```
521
+ *
522
+ * @param options Drawing options including offsets and styles
523
+ * @param options.offsetX Manual X offset for comment placement (overrides smart positioning)
524
+ * @param options.offsetY Manual Y offset for comment placement (overrides smart positioning)
525
+ * @param options.commentStyle Style options for the comment box
526
+ * @param options.arrowStyle Style options for the arrow
527
+ * @returns this for chaining
528
+ * @see startComment for low-level programmatic control
529
+ */
530
+ enableCommentDrawing(options?: {
531
+ offsetX?: number;
532
+ offsetY?: number;
533
+ commentStyle?: Partial<CommentProps>;
534
+ arrowStyle?: Partial<ArrowProperties>;
535
+ }): this;
536
+ /**
537
+ * Place a pre-created annotation by moving it with the cursor.
538
+ * The annotation follows the mouse until the user clicks to place it.
539
+ * Press Escape to cancel.
540
+ *
541
+ * @param annotation The text or box annotation to place
542
+ * @returns this for chaining
543
+ */
544
+ enablePlacement(annotation: Text_2 | Box): this;
545
+ /**
546
+ * **Advanced API:** Programmatically start drawing a comment at specific coordinates.
547
+ *
548
+ * This is a low-level method that gives you full control over the drawing process.
549
+ * You must handle mouse events and create the comment object yourself.
550
+ *
551
+ * **For most use cases, use `enableCommentDrawing()` instead** - it handles all
552
+ * mouse events and annotation creation automatically.
553
+ *
554
+ * Use this method only when you need:
555
+ * - Custom mouse event handling (e.g., custom cursors, right-click menus)
556
+ * - Programmatic placement without user interaction
557
+ * - Integration with custom UI frameworks
558
+ *
559
+ * @example
560
+ * ```ts
561
+ * // Custom cursor example
562
+ * ogma.setOptions({ cursor: { default: 'crosshair' } });
563
+ * ogma.events.once('mousedown', (evt) => {
564
+ * const { x, y } = ogma.view.screenToGraphCoordinates(evt);
565
+ * const comment = createComment(x, y, 'My comment', { color: '#3A03CF' });
566
+ * control.startComment(x, y, comment);
567
+ * });
568
+ * ```
569
+ *
570
+ * @param x X coordinate to start drawing
571
+ * @param y Y coordinate to start drawing
572
+ * @param comment The comment annotation to add
573
+ * @param options Drawing options including offsets and styles
574
+ * @returns this for chaining
575
+ * @see enableCommentDrawing for the recommended high-level API
576
+ */
577
+ startComment(x: number, y: number, comment: Comment_2, options?: {
578
+ offsetX?: number;
579
+ offsetY?: number;
580
+ commentStyle?: Partial<CommentProps>;
581
+ arrowStyle?: Partial<ArrowProperties>;
582
+ }): this;
583
+ /**
584
+ * **Advanced API:** Programmatically start drawing a box at specific coordinates.
585
+ *
586
+ * This is a low-level method that gives you full control over the drawing process.
587
+ * You must handle mouse events and optionally create the box object yourself.
588
+ *
589
+ * **For most use cases, use `enableBoxDrawing()` instead** - it handles all
590
+ * mouse events and annotation creation automatically.
591
+ *
592
+ * Use this method only when you need:
593
+ * - Custom mouse event handling (e.g., custom cursors, right-click menus)
594
+ * - Programmatic placement without user interaction
595
+ * - Integration with custom UI frameworks
596
+ *
597
+ * @example
598
+ * ```ts
599
+ * // Custom cursor example
600
+ * ogma.setOptions({ cursor: { default: 'crosshair' } });
601
+ * ogma.events.once('mousedown', (evt) => {
602
+ * const { x, y } = ogma.view.screenToGraphCoordinates(evt);
603
+ * const box = createBox(x, y, 100, 50, { background: '#EDE6FF' });
604
+ * control.startBox(x, y, box);
605
+ * });
606
+ * ```
607
+ *
608
+ * @param x X coordinate for the box origin
609
+ * @param y Y coordinate for the box origin
610
+ * @param box The box annotation to add (optional, will be created if not provided)
611
+ * @returns this for chaining
612
+ * @see enableBoxDrawing for the recommended high-level API
613
+ */
614
+ startBox(x: number, y: number, box?: Box): this;
615
+ /**
616
+ * **Advanced API:** Programmatically start drawing an arrow at specific coordinates.
617
+ *
618
+ * This is a low-level method that gives you full control over the drawing process.
619
+ * You must handle mouse events and optionally create the arrow object yourself.
620
+ *
621
+ * **For most use cases, use `enableArrowDrawing()` instead** - it handles all
622
+ * mouse events and annotation creation automatically.
623
+ *
624
+ * Use this method only when you need:
625
+ * - Custom mouse event handling (e.g., custom cursors, right-click menus)
626
+ * - Programmatic placement without user interaction
627
+ * - Integration with custom UI frameworks
628
+ *
629
+ * @example
630
+ * ```ts
631
+ * // Custom cursor example
632
+ * ogma.setOptions({ cursor: { default: 'crosshair' } });
633
+ * ogma.events.once('mousedown', (evt) => {
634
+ * const { x, y } = ogma.view.screenToGraphCoordinates(evt);
635
+ * const arrow = createArrow(x, y, x, y, { strokeColor: '#3A03CF' });
636
+ * control.startArrow(x, y, arrow);
637
+ * });
638
+ * ```
639
+ *
640
+ * @param x X coordinate for the arrow start
641
+ * @param y Y coordinate for the arrow start
642
+ * @param arrow The arrow annotation to add (optional, will be created if not provided)
643
+ * @returns this for chaining
644
+ * @see enableArrowDrawing for the recommended high-level API
645
+ */
646
+ startArrow(x: number, y: number, arrow?: Arrow): this;
647
+ /**
648
+ * **Advanced API:** Programmatically start drawing a text annotation at specific coordinates.
649
+ *
650
+ * This is a low-level method that gives you full control over the drawing process.
651
+ * You must handle mouse events and optionally create the text object yourself.
652
+ *
653
+ * **For most use cases, use `enableTextDrawing()` instead** - it handles all
654
+ * mouse events and annotation creation automatically.
655
+ *
656
+ * Use this method only when you need:
657
+ * - Custom mouse event handling (e.g., custom cursors, right-click menus)
658
+ * - Programmatic placement without user interaction
659
+ * - Integration with custom UI frameworks
660
+ *
661
+ * @example
662
+ * ```ts
663
+ * // Custom cursor example
664
+ * ogma.setOptions({ cursor: { default: 'crosshair' } });
665
+ * ogma.events.once('mousedown', (evt) => {
666
+ * const { x, y } = ogma.view.screenToGraphCoordinates(evt);
667
+ * const text = createText(x, y, 0, 0, 'Hello', { color: '#3A03CF' });
668
+ * control.startText(x, y, text);
669
+ * });
670
+ * ```
671
+ *
672
+ * @param x X coordinate for the text
673
+ * @param y Y coordinate for the text
674
+ * @param text The text annotation to add (optional, will be created if not provided)
675
+ * @returns this for chaining
676
+ * @see enableTextDrawing for the recommended high-level API
677
+ */
678
+ startText(x: number, y: number, text?: Text_2): this;
167
679
  /**
168
- * Start adding an arrow (add it, and give control to the user)
169
- * @param x coord of the first point
170
- * @param y coord of the first point
171
- * @param arrow The arrow to add
680
+ * **Advanced API:** Programmatically start drawing a polygon at specific coordinates.
681
+ *
682
+ * This is a low-level method that gives you full control over the drawing process.
683
+ * You must handle mouse events and create the polygon object yourself.
684
+ *
685
+ * **For most use cases, use `enablePolygonDrawing()` instead** - it handles all
686
+ * mouse events and annotation creation automatically.
687
+ *
688
+ * Use this method only when you need:
689
+ * - Custom mouse event handling (e.g., custom cursors, right-click menus)
690
+ * - Programmatic placement without user interaction
691
+ * - Integration with custom UI frameworks
692
+ *
693
+ * @example
694
+ * ```ts
695
+ * // Custom cursor example
696
+ * ogma.setOptions({ cursor: { default: 'crosshair' } });
697
+ * ogma.events.once('mousedown', (evt) => {
698
+ * const { x, y } = ogma.view.screenToGraphCoordinates(evt);
699
+ * const polygon = createPolygon([[[x, y]]], { strokeColor: '#3A03CF' });
700
+ * control.startPolygon(x, y, polygon);
701
+ * });
702
+ * ```
703
+ *
704
+ * @param x X coordinate to start drawing
705
+ * @param y Y coordinate to start drawing
706
+ * @param polygon The polygon annotation to add
707
+ * @returns this for chaining
708
+ * @see enablePolygonDrawing for the recommended high-level API
172
709
  */
173
- startArrow(x: number, y: number, arrow?: Arrow): void;
710
+ startPolygon(x: number, y: number, polygon: Polygon): this;
174
711
  /**
175
- * Start adding a text (add it, and give control to the user)
176
- * @param x coord of the top left point
177
- * @param y coord of the top left point
178
- * @param text The text to add
712
+ * Get the currently selected annotations as a collection
713
+ * @returns A FeatureCollection of selected annotations
179
714
  */
180
- startText(x: number, y: number, text?: Text_2): void;
715
+ getSelectedAnnotations(): AnnotationCollection;
181
716
  /**
182
- * Cancel drawing on the current frame
717
+ * Get the first selected annotation (for backwards compatibility)
718
+ * @returns The currently selected annotation, or null if none selected
183
719
  */
184
- cancelDrawing(): void;
720
+ getSelected(): Annotation | null;
721
+ /**
722
+ * Get a specific annotation by id
723
+ * @param id The id of the annotation to retrieve
724
+ * @returns The annotation with the given id, or undefined if not found
725
+ */
726
+ getAnnotation<T = Annotation>(id: Id): T | undefined;
727
+ /**
728
+ * Scale an annotation by a given factor around an origin point
729
+ * @param id The id of the annotation to scale
730
+ * @param scale The scale factor
731
+ * @param ox Origin x coordinate
732
+ * @param oy Origin y coordinate
733
+ * @returns this for chaining
734
+ */
735
+ setScale(id: Id, scale: number, ox: number, oy: number): this;
185
736
  /**
186
- * Triggers the update event on the annotation
187
- * @param annotation The annotation updated
737
+ * Toggle a comment between collapsed and expanded mode
738
+ * @param id The id of the comment to toggle
739
+ * @returns this for chaining
188
740
  */
189
- onUpdate: (annotation: Annotation) => void;
190
- private _onUpdate;
741
+ toggleComment(id: Id): this;
742
+ /**
743
+ * Destroy the controller and its elements
744
+ */
745
+ destroy(): void;
191
746
  /**
192
747
  * Update the style of the annotation with the given id
193
748
  * @param id The id of the annotation to update
194
749
  * @param style The new style
195
750
  */
196
751
  updateStyle<A extends Annotation>(id: Id, style: A["properties"]["style"]): this;
197
- setScale(id: Id, scale: number, ox: number, oy: number): this;
198
752
  /**
199
- * @returns the annotations in the controller
753
+ * Update an annotation with partial updates
754
+ *
755
+ * This method allows you to update any properties of an annotation, including
756
+ * geometry, properties, and style. Updates are merged with existing data.
757
+ *
758
+ * @param annotation Partial annotation object with id and properties to update
759
+ * @returns this for chaining
760
+ *
761
+ * @example
762
+ * ```ts
763
+ * // Update arrow geometry
764
+ * controller.update({
765
+ * id: arrowId,
766
+ * geometry: {
767
+ * type: 'LineString',
768
+ * coordinates: [[0, 0], [200, 200]]
769
+ * }
770
+ * });
771
+ *
772
+ * // Update text content and position
773
+ * controller.update({
774
+ * id: textId,
775
+ * geometry: {
776
+ * type: 'Point',
777
+ * coordinates: [100, 100]
778
+ * },
779
+ * properties: {
780
+ * content: 'Updated text'
781
+ * }
782
+ * });
783
+ *
784
+ * // Update style only (prefer updateStyle for style-only updates)
785
+ * controller.update({
786
+ * id: boxId,
787
+ * properties: {
788
+ * style: {
789
+ * background: '#ff0000'
790
+ * }
791
+ * }
792
+ * });
793
+ * ```
200
794
  */
201
- getAnnotations(): AnnotationCollection;
795
+ update<A extends Annotation>(annotation: DeepPartial<A> & {
796
+ id: Id;
797
+ }): this;
202
798
  /**
203
- * Retrieve the annotation with the given id
204
- * @param id the id of the annotation to get
205
- * @returns The annotation with the given id
799
+ * Attach an arrow to a node at the specified side
800
+ * @param arrowId
801
+ * @param targetNode
802
+ * @param side
206
803
  */
207
- getAnnotation(id: Id): Arrow | Text_2 | undefined;
804
+ link(arrowId: Id, targetNode: Node_2, side: Side): this;
208
805
  /**
209
- * Destroy the controller and its elements
806
+ * Attach an arrow to an annotation at the specified side
807
+ * @param arrowId
808
+ * @param target
809
+ * @param side
210
810
  */
211
- destroy(): void;
811
+ link(arrowId: Id, target: Id, side: Side): this;
812
+ isDrawing(): boolean;
212
813
  }
213
814
 
815
+ /**
816
+ * Options for the annotations control
817
+ */
214
818
  export declare type ControllerOptions = {
215
- /**
216
- * The color of the magnet points
217
- */
218
- magnetColor: string;
219
819
  /**
220
820
  * The radius in which arrows are attracted
221
821
  */
@@ -233,13 +833,23 @@ export declare type ControllerOptions = {
233
833
  */
234
834
  textPlaceholder: string;
235
835
  /**
236
- * Size of the text handle
836
+ * Show send button in text editor
837
+ */
838
+ showSendButton: boolean;
839
+ /**
840
+ * Show edit button in text editor
841
+ */
842
+ showEditButton: boolean;
843
+ /**
844
+ * SVG icon for the send button in text editor
845
+ * Should be a complete SVG string (e.g., '<svg>...</svg>')
237
846
  */
238
- textHandleSize: number;
847
+ sendButtonIcon: string;
239
848
  /**
240
- * Size of the arrow handle
849
+ * SVG icon for the edit button in text editor
850
+ * Should be a complete SVG string (e.g., '<svg>...</svg>')
241
851
  */
242
- arrowHandleSize: number;
852
+ editButtonIcon: string;
243
853
  /**
244
854
  * Minimum height of the arrow in units
245
855
  */
@@ -251,132 +861,356 @@ export declare type ControllerOptions = {
251
861
  };
252
862
 
253
863
  export declare const createArrow: (x0?: number, y0?: number, x1?: number, y1?: number, styles?: {
864
+ /** Tail extremity style */
254
865
  tail?: Extremity | undefined;
866
+ /** Head extremity style */
255
867
  head?: Extremity | undefined;
256
- strokeType?: "none" | "plain" | "dashed" | undefined;
868
+ strokeType?: StrokeType | undefined;
257
869
  strokeColor?: string | undefined;
258
870
  strokeWidth?: number | undefined;
259
871
  }) => Arrow;
260
872
 
873
+ export declare const createBox: (x?: number, y?: number, width?: number, height?: number, styles?: Partial<BoxStyle>) => Box;
874
+
875
+ /**
876
+ * Create a new Comment annotation
877
+ *
878
+ * @param x - X coordinate of the comment box/icon center
879
+ * @param y - Y coordinate of the comment box/icon center
880
+ * @param content - Text content
881
+ * @param options - Optional configuration
882
+ * @returns New Comment feature
883
+ *
884
+ * @important This creates ONLY the comment box without an arrow. Since comments
885
+ * require at least one arrow, you should use {@link createCommentWithArrow}
886
+ * instead for programmatic creation. This function is primarily used internally
887
+ * by the interactive drawing handlers.
888
+ *
889
+ * @see createCommentWithArrow for creating comments programmatically
890
+ */
891
+ export declare function createComment(x: number, y: number, content: string, options?: Partial<CommentProps>): Comment_2;
892
+
893
+ /**
894
+ * Create a comment with an arrow pointing to a target location
895
+ *
896
+ * This is the recommended way to create comments programmatically, as it ensures
897
+ * that the comment always has at least one arrow (which is required).
898
+ *
899
+ * @param targetX - X coordinate where the arrow points to
900
+ * @param targetY - Y coordinate where the arrow points to
901
+ * @param commentX - X coordinate of the comment box center
902
+ * @param commentY - Y coordinate of the comment box center
903
+ * @param content - Text content of the comment
904
+ * @param options - Optional configuration
905
+ * @param options.commentStyle - Style options for the comment
906
+ * @param options.arrowStyle - Style options for the arrow
907
+ * @returns Object containing the comment and arrow features
908
+ *
909
+ * @example
910
+ * ```typescript
911
+ * import { createCommentWithArrow } from '@linkurious/ogma-annotations';
912
+ *
913
+ * // Create a comment pointing to a node at (100, 100)
914
+ * const { comment, arrow } = createCommentWithArrow(
915
+ * 100, 100, // Target position (where arrow points)
916
+ * 300, 50, // Comment position
917
+ * "Important node!", // Comment text
918
+ * {
919
+ * commentStyle: {
920
+ * style: {
921
+ * background: "#FFFACD",
922
+ * color: "#333"
923
+ * }
924
+ * },
925
+ * arrowStyle: {
926
+ * strokeColor: "#3498db",
927
+ * strokeWidth: 2,
928
+ * head: "arrow"
929
+ * }
930
+ * }
931
+ * );
932
+ *
933
+ * // Add both to the controller
934
+ * controller.add(comment);
935
+ * controller.add(arrow);
936
+ *
937
+ * // The arrow is automatically linked to the comment
938
+ * ```
939
+ */
940
+ export declare function createCommentWithArrow(targetX: number, targetY: number, commentX: number, commentY: number, content?: string, options?: {
941
+ commentStyle?: Partial<CommentProps>;
942
+ arrowStyle?: Partial<ArrowStyles>;
943
+ }): {
944
+ comment: Comment_2;
945
+ arrow: Arrow;
946
+ };
947
+
948
+ /**
949
+ * Create a polygon annotation
950
+ */
951
+ export declare function createPolygon(coordinates: [number, number][][], properties?: Partial<Omit<PolygonProperties, "type">> & {
952
+ id?: Id;
953
+ }): Polygon;
954
+
955
+ /** @private */
261
956
  export declare function createSVGElement<T extends SVGElement>(tag: string): T;
262
957
 
263
958
  export declare const createText: (x?: number, y?: number, width?: number, height?: number, content?: string, styles?: Partial<TextStyle>) => Text_2;
264
959
 
960
+ /** @private */
961
+ export declare type Cursor = "default" | "pointer" | "move" | "grab" | "grabbing" | "auto" | "resize" | "col-resize" | "row-resize" | "all-scroll" | "n-resize" | "e-resize" | "s-resize" | "w-resize" | "ne-resize" | "nw-resize" | "se-resize" | "sw-resize" | "ew-resize" | "ns-resize" | "nesw-resize" | "nwse-resize" | "alias" | "crosshair";
962
+
963
+ /** @private */
964
+ export declare const cursors: Record<string, Cursor>;
965
+
966
+ /**
967
+ * Darken a color for highlight purposes.
968
+ * @param color - Color string in hex (#RRGGBB or #RGB) or rgba format
969
+ * @returns
970
+ */
971
+ export declare const darken: (color: Color) => RgbaColor;
972
+
973
+ export declare const DATA_ATTR = "data-annotation";
974
+
975
+ /** @private */
976
+ export declare const debounce: <F extends (...args: Parameters<F>) => ReturnType<F>>(func: F, waitFor: number) => (...args: Parameters<F>) => void;
977
+
978
+ /** @private */
979
+ export declare function debounceTail<T, A extends unknown[]>(fn: (this: T, ...args: A) => void, delay: number): (this: T, ...args: A) => void;
980
+
981
+ export declare type DeepPartial<T> = {
982
+ [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
983
+ };
984
+
985
+ export declare const DEFAULT_EDIT_ICON = "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M12 6.00015H7.33333C6.97971 6.00015 6.64057 6.14063 6.39052 6.39068C6.14048 6.64072 6 6.97986 6 7.33348V16.6668C6 17.0204 6.14048 17.3596 6.39052 17.6096C6.64057 17.8597 6.97971 18.0002 7.33333 18.0002H16.6667C17.0203 18.0002 17.3594 17.8597 17.6095 17.6096C17.8595 17.3596 18 17.0204 18 16.6668V12.0002M16.25 5.75015C16.5152 5.48493 16.8749 5.33594 17.25 5.33594C17.6251 5.33594 17.9848 5.48493 18.25 5.75015C18.5152 6.01537 18.6642 6.37508 18.6642 6.75015C18.6642 7.12522 18.5152 7.48493 18.25 7.75015L12.2413 13.7595C12.083 13.9176 11.8875 14.0334 11.6727 14.0962L9.75733 14.6562C9.69997 14.6729 9.63916 14.6739 9.58127 14.6591C9.52339 14.6442 9.47055 14.6141 9.4283 14.5719C9.38604 14.5296 9.35593 14.4768 9.3411 14.4189C9.32627 14.361 9.32727 14.3002 9.344 14.2428L9.904 12.3275C9.96702 12.1129 10.083 11.9175 10.2413 11.7595L16.25 5.75015Z\" stroke=\"#1A70E5\" stroke-width=\"1.33333\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n</svg>\n";
986
+
987
+ /** Default send button icon (paper plane) */
988
+ export declare const DEFAULT_SEND_ICON = "<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M22 2L11 13M22 2L15 22L11 13M22 2L2 9L11 13\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n</svg>";
989
+
990
+ /**
991
+ * Default options for creating new Arrow annotations.
992
+ * Contains the default arrow structure with {@link defaultArrowStyle}.
993
+ */
265
994
  export declare const defaultArrowOptions: Arrow;
266
995
 
996
+ /**
997
+ * Default style configuration for arrow annotations.
998
+ *
999
+ * @example
1000
+ * ```typescript
1001
+ * {
1002
+ * strokeType: "plain",
1003
+ * strokeColor: "#202020",
1004
+ * strokeWidth: 1,
1005
+ * head: "none",
1006
+ * tail: "none"
1007
+ * }
1008
+ * ```
1009
+ */
267
1010
  export declare const defaultArrowStyle: ArrowStyles;
268
1011
 
269
- export declare const defaultControllerOptions: AnnotationOptions;
1012
+ /**
1013
+ * Default options for creating new Box annotations.
1014
+ * Contains the default box structure with {@link defaultBoxStyle}.
1015
+ */
1016
+ export declare const defaultBoxOptions: Box;
1017
+
1018
+ /**
1019
+ * Default style configuration for box annotations.
1020
+ *
1021
+ * @example
1022
+ * ```typescript
1023
+ * {
1024
+ * background: "#f5f5f5",
1025
+ * strokeWidth: 0,
1026
+ * borderRadius: 8,
1027
+ * padding: 16,
1028
+ * strokeType: "plain"
1029
+ * }
1030
+ * ```
1031
+ */
1032
+ export declare const defaultBoxStyle: BoxStyle;
1033
+
1034
+ /**
1035
+ * Default options for creating new Comments.
1036
+ * Contains the default comment configuration with {@link defaultCommentStyle}.
1037
+ *
1038
+ * @example
1039
+ * ```typescript
1040
+ * {
1041
+ * mode: "expanded",
1042
+ * width: 200,
1043
+ * height: 120,
1044
+ * content: "",
1045
+ * style: defaultCommentStyle
1046
+ * }
1047
+ * ```
1048
+ */
1049
+ export declare const defaultCommentOptions: Partial<CommentProps>;
1050
+
1051
+ /**
1052
+ * Default style for Comment annotations
1053
+ *
1054
+ * @example
1055
+ * ```typescript
1056
+ * {
1057
+ * // Box styling
1058
+ * background: "#FFFACD", // Light yellow (sticky note color)
1059
+ * padding: 8,
1060
+ * borderRadius: 4,
1061
+ * strokeColor: "#DDD",
1062
+ * strokeWidth: 1,
1063
+ * strokeType: "plain",
1064
+ *
1065
+ * // Icon styling (collapsed mode)
1066
+ * iconColor: "#FFCB2F", // Gold
1067
+ * iconSymbol: "💬",
1068
+ * iconBorderColor: "#aaa",
1069
+ * iconBorderWidth: 2,
1070
+ *
1071
+ * // Size properties
1072
+ * minHeight: 60,
1073
+ * iconSize: 32,
1074
+ *
1075
+ * // Text styling
1076
+ * color: "#333",
1077
+ * font: "Arial, sans-serif",
1078
+ * fontSize: 12,
1079
+ *
1080
+ * // Editing UI
1081
+ * showSendButton: true,
1082
+ * autoGrow: true,
1083
+ *
1084
+ * // Fixed size (always screen-aligned)
1085
+ * fixedSize: true
1086
+ * }
1087
+ * ```
1088
+ */
1089
+ export declare const defaultCommentStyle: CommentStyle;
270
1090
 
1091
+ /**
1092
+ * Default polygon properties for creating new Polygon annotations.
1093
+ * Contains the default polygon configuration with {@link defaultPolygonStyle}.
1094
+ */
1095
+ export declare const defaultPolygonProperties: PolygonProperties;
1096
+
1097
+ /**
1098
+ * Default style configuration for polygon annotations.
1099
+ *
1100
+ * @example
1101
+ * ```typescript
1102
+ * {
1103
+ * background: "transparent",
1104
+ * strokeWidth: 2,
1105
+ * borderRadius: 8,
1106
+ * padding: 16,
1107
+ * strokeType: "plain",
1108
+ * strokeColor: "#000000"
1109
+ * }
1110
+ * ```
1111
+ */
1112
+ export declare const defaultPolygonStyle: PolygonStyle;
1113
+
1114
+ /**
1115
+ * Default options for creating new Text annotations.
1116
+ * Contains the default text structure with {@link defaultTextStyle}.
1117
+ */
271
1118
  export declare const defaultTextOptions: Text_2;
272
1119
 
1120
+ /**
1121
+ * Default style configuration for text annotations.
1122
+ *
1123
+ * @example
1124
+ * ```typescript
1125
+ * {
1126
+ * font: "sans-serif",
1127
+ * fontSize: 18,
1128
+ * color: "#505050",
1129
+ * background: "#f5f5f5",
1130
+ * strokeWidth: 0,
1131
+ * borderRadius: 8,
1132
+ * padding: 16,
1133
+ * strokeType: "plain",
1134
+ * fixedSize: false
1135
+ * }
1136
+ * ```
1137
+ */
273
1138
  export declare const defaultTextStyle: TextStyle;
274
1139
 
275
1140
  /**
276
- * @class Annotations
277
- * Abstract class to display Texts and Arrows, provide add/remove/update and mouse events
278
- * Modifying annotation is handled by the child classes, it is too specific
279
- */
280
- declare abstract class Editor<T extends Annotation> extends default_2<Events<T>> {
281
- protected ogma: default_3;
282
- protected elements: T[];
283
- protected layer: SVGLayer;
284
- protected editor: Overlay;
285
- protected selectedId: Id;
286
- protected hoveredId: Id;
287
- protected ogmaOptions: Options;
288
- protected shouldDetect: boolean;
289
- protected isDragging: boolean;
290
- protected showeditorOnHover: boolean;
291
- constructor(ogma: default_3, editorHtml: string);
292
- private _onKeyUp;
293
- protected _canRemove(): boolean;
294
- private _onClickMouseMove;
295
- /**
296
- * @method add
297
- * @param options Params for the annotation (merged with default)
298
- * @returns the added annotation
299
- */
300
- add(options: T): T;
301
- updateStyle(annotation: T, style: Partial<T["properties"]["style"]>): void;
302
- updateGeometry(annotation: T, geometry: Partial<T["geometry"]>): void;
303
- scale(annotation: T, scale: number, ox: number, oy: number): void;
304
- /**
305
- * @method update
306
- * Updates an annotation (position, color etc)
307
- * @param id Id of the annotation to update
308
- * @param element params of the annotation
309
- */
310
- update(id: Id, element: Partial<T>): void;
311
- updateAnnotation(target: T, element: Partial<T>): void;
312
- getById(id: Id): T;
313
- /**
314
- * @method select
315
- * @param id id of the element to select
316
- * Select element, show editor, disable Ogma dragging and fire event
317
- */
318
- select(id: Id): void;
319
- hover(id: Id): void;
320
- getSelectedFeature(): T | null;
321
- unselect(): this;
322
- unhover(): this;
323
- /**
324
- * @method remove
325
- * @param id Id of the annotation to remove
326
- * Removes annotation with the given id
327
- */
328
- remove(id: Id): void;
329
- /**
330
- * @method disableDragging
331
- * Prevents Ogma from dragging elements or moving the view while dragging an annotation
332
- */
333
- disableDragging(): void;
334
- /**
335
- * @method restoreDragging
336
- * restore ogma options as they were before we start dragging an annotation
337
- */
338
- restoreDragging(): void;
339
- enableDetection(): void;
340
- /**
341
- * @method disableDetection
342
- * Disables the hover behaviour, used by controller to avoid hovering
343
- * arrows while dragging texts and vice versa
344
- */
345
- disableDetection(): void;
346
- refreshLayer(): void;
347
- refreshDrawing(): void;
348
- getElements(): T[];
349
- abstract refreshEditor(): void;
350
- abstract draw(svg: SVGSVGElement): void;
351
- abstract cancelDrawing(): void;
352
- abstract getDefaultOptions(): T;
353
- abstract detect(point: Point_2, margin: number): T | undefined;
354
- destroy(): void;
355
- }
1141
+ * @private
1142
+ * @param a Arrow annotation
1143
+ * @param point Point to test
1144
+ * @param threshold Detection threshold
1145
+ * @returns True if the point is on the arrow line within the given threshold
1146
+ */
1147
+ export declare function detectArrow(a: Arrow, point: Point_3, threshold: number): boolean;
356
1148
 
357
- export declare type Events<T> = {
358
- [EVT_HOVER]: (evt: T) => void;
359
- [EVT_UNHOVER]: (evt: T) => void;
360
- [EVT_SELECT]: (evt: T) => void;
361
- [EVT_UNSELECT]: (evt: T) => void;
362
- [EVT_DRAG_START]: (evt: T) => void;
363
- [EVT_DRAG]: (evt: T, key: "line" | "start" | "end" | "text") => void;
364
- [EVT_DRAG_END]: (evt: T) => void;
365
- [EVT_REMOVE]: (evt: T) => void;
366
- [EVT_ADD]: (evt: T) => void;
367
- [EVT_UPDATE]: (evt: T) => void;
368
- };
1149
+ /** @private */
1150
+ export declare function detectBox(a: Box, p: Point, sin?: number, cos?: number, threshold?: number): boolean;
1151
+
1152
+ /**
1153
+ * Detect if a point is within a comment's bounds
1154
+ * @private
1155
+ * @param comment - Comment to test
1156
+ * @param point - Point to test
1157
+ * @param threshold - Detection threshold in pixels
1158
+ * @param zoom - Current zoom level
1159
+ * @returns True if point is within comment bounds
1160
+ */
1161
+ export declare function detectComment(comment: Comment_2, point: Point, threshold: number | undefined, sin: number, cos: number, zoom?: number): boolean;
1162
+
1163
+ /**
1164
+ * Point-in-polygon detection using ray casting algorithm
1165
+ * @private
1166
+ * @param polygon The polygon annotation
1167
+ * @param point The point to test
1168
+ * @param threshold Detection threshold in pixels
1169
+ * @return True if the point is inside the polygon or within the threshold distance from its edges
1170
+ */
1171
+ export declare function detectPolygon(polygon: Polygon, point: Point, threshold?: number): boolean;
1172
+
1173
+ /**
1174
+ * Detects whether a point is within a text annotation's bounds.
1175
+ * @private
1176
+ * @param a Text annotation
1177
+ * @param p Point to test
1178
+ * @param threshold Detection threshold
1179
+ * @param sin Rotation sine
1180
+ * @param cos Rotation cosine
1181
+ * @param zoom Current zoom level
1182
+ * @returns True if the point is within the text bounds, false otherwise
1183
+ */
1184
+ export declare function detectText(a: Text_2, p: Point, threshold?: number, sin?: number, cos?: number, zoom?: number): boolean;
1185
+
1186
+ /** Event related to a single annotation feature */
1187
+ declare interface DragEvent_2 {
1188
+ /** Annotation ID involved in the event */
1189
+ id: Id;
1190
+ /** Current mouse position in pixel coordinates during the drag */
1191
+ position: {
1192
+ x: number;
1193
+ y: number;
1194
+ };
1195
+ }
1196
+ export { DragEvent_2 as DragEvent }
369
1197
 
370
1198
  export declare const EVT_ADD = "add";
371
1199
 
372
1200
  export declare const EVT_CANCEL_DRAWING = "cancelDrawing";
373
1201
 
1202
+ export declare const EVT_CLICK = "click";
1203
+
1204
+ export declare const EVT_COMPLETE_DRAWING = "completeDrawing";
1205
+
374
1206
  export declare const EVT_DRAG = "dragging";
375
1207
 
376
1208
  export declare const EVT_DRAG_END = "dragend";
377
1209
 
378
1210
  export declare const EVT_DRAG_START = "dragstart";
379
1211
 
1212
+ export declare const EVT_HISTORY = "history";
1213
+
380
1214
  export declare const EVT_HOVER = "hover";
381
1215
 
382
1216
  export declare const EVT_LINK = "link";
@@ -391,66 +1225,95 @@ export declare const EVT_UNSELECT = "unselect";
391
1225
 
392
1226
  export declare const EVT_UPDATE = "update";
393
1227
 
394
- declare type ExportedLink = {
1228
+ export declare type ExportedLink = {
395
1229
  id: Id;
396
- side: "start" | "end";
397
- type: "node" | "text";
1230
+ side: Side;
1231
+ type: TargetType;
398
1232
  magnet?: Point;
399
1233
  };
400
1234
 
1235
+ /** Extremity types for arrow annotations. */
401
1236
  export declare type Extremity = "none" | "arrow" | "arrow-plain" | "dot" | "halo-dot";
402
1237
 
1238
+ /** Event related to a single annotation feature */
1239
+ export declare interface FeatureEvent {
1240
+ /** Annotation ID involved in the event */
1241
+ id: Id;
1242
+ }
1243
+
403
1244
  export declare type FeatureEvents = {
404
1245
  /**
405
1246
  * Event trigerred when selecting an annotation
406
1247
  * @param evt The annotation selected
407
1248
  */
408
- [EVT_SELECT]: (evt: Annotation) => void;
1249
+ [EVT_SELECT]: (evt: FeaturesEvent) => void;
409
1250
  /**
410
1251
  * Event trigerred when unselecting an annotation
411
1252
  * @param evt The annotation unselected
412
1253
  */
413
- [EVT_UNSELECT]: (evt: Annotation) => void;
1254
+ [EVT_UNSELECT]: (evt: FeaturesEvent) => void;
414
1255
  /**
415
1256
  * Event trigerred when removing an annotation
416
1257
  * @param evt The annotation removed
417
1258
  */
418
- [EVT_REMOVE]: (evt: Annotation) => void;
1259
+ [EVT_REMOVE]: (evt: FeatureEvent) => void;
419
1260
  /**
420
1261
  * Event trigerred when adding an annotation
421
1262
  * @param evt The annotation added
422
1263
  */
423
- [EVT_ADD]: (evt: Annotation) => void;
1264
+ [EVT_ADD]: (evt: FeatureEvent) => void;
1265
+ /**
1266
+ * Event trigerred when canceling drawing mode
1267
+ */
424
1268
  [EVT_CANCEL_DRAWING]: () => void;
425
1269
  /**
426
- * Event trigerred when updating an annotation
427
- * @returns The annotation updated
1270
+ * Event trigerred when completing a drawing operation
1271
+ * @param evt Contains the ID of the completed annotation
1272
+ */
1273
+ [EVT_COMPLETE_DRAWING]: (evt: FeatureEvent) => void;
1274
+ /**
1275
+ * Event trigerred when updating an annotation.
1276
+ * This fires after any modification including drag operations, style changes, scaling, etc.
1277
+ * @param evt The updated annotation with all changes applied
428
1278
  */
429
1279
  [EVT_UPDATE]: (evt: Annotation) => void;
430
1280
  /**
431
- * Event trigerred when linking an arrow to a text or node
1281
+ * Event trigerred when linking an arrow to a node or annotation
1282
+ * @param evt Contains the arrow and link details
432
1283
  */
433
1284
  [EVT_LINK]: (evt: {
434
1285
  arrow: Arrow;
435
1286
  link: Link;
436
1287
  }) => void;
437
1288
  /**
438
- * Event trigerred when starting to drag an arrow or a text
1289
+ * Event trigerred when history state changes (after undo/redo operations)
1290
+ * @param evt Contains boolean flags for undo/redo availability
439
1291
  */
440
- [EVT_DRAG_START]: (evt: Arrow | Text_2) => void;
1292
+ [EVT_HISTORY]: (evt: HistoryEvent) => void;
441
1293
  /**
442
- * Event trigerred when dragging an arrow or a text
1294
+ * Event triggered when a drag operation starts on an annotation
443
1295
  */
444
- [EVT_DRAG]: (evt: Arrow | Text_2, key: "line" | "start" | "end" | "text") => void;
1296
+ [EVT_DRAG_START]: (evt: DragEvent_2) => void;
445
1297
  /**
446
- * Event trigerred when stopped dragging an arrow or a text
1298
+ * Event triggered when a drag operation ends on an annotation
447
1299
  */
448
- [EVT_DRAG_END]: (evt: Arrow | Text_2) => void;
1300
+ [EVT_DRAG_END]: (evt: DragEvent_2) => void;
1301
+ /**
1302
+ * Event triggered when a click completes on an annotation (mouseup without drag)
1303
+ */
1304
+ [EVT_CLICK]: (evt: ClickEvent) => void;
449
1305
  };
450
1306
 
1307
+ /** Event related to multiple annotation features */
1308
+ export declare interface FeaturesEvent {
1309
+ /** Annotation IDs involved in the event */
1310
+ ids: Id[];
1311
+ }
1312
+
451
1313
  /**
452
1314
  * Calculate the bounds of a collection of annotations
453
1315
  * @param annotations
1316
+ * @returns Bounds [minX, minY, maxX, maxY]
454
1317
  */
455
1318
  export declare function getAnnotationsBounds(annotations: AnnotationCollection): Bounds;
456
1319
 
@@ -470,7 +1333,7 @@ export declare function getArrowEndPoints(a: Arrow): {
470
1333
  };
471
1334
  };
472
1335
 
473
- export declare function getArrowSide(a: Arrow, side: "start" | "end"): {
1336
+ export declare function getArrowSide(a: Arrow, side: Side): {
474
1337
  x: number;
475
1338
  y: number;
476
1339
  };
@@ -480,40 +1343,179 @@ export declare function getArrowStart(a: Arrow): {
480
1343
  y: number;
481
1344
  };
482
1345
 
483
- export declare function getAttachmentPointOnNode(start: Point_2, nodeCenter: Point_2, nodeRadius: number): {
1346
+ export declare function getAttachmentPointOnNode(start: Point_3, nodeCenter: Point_3, nodeRadius: number): {
484
1347
  x: number;
485
1348
  y: number;
486
1349
  };
487
1350
 
488
- export declare function getCoordinates(gj: Feature | FeatureCollection | Geometry): Position[];
489
-
490
- export declare const getHandleId: (handle: HTMLDivElement) => number;
1351
+ declare function getBbox<T extends Annotation>(b: T): BBox;
1352
+ export { getBbox }
1353
+ export { getBbox as getTextBbox }
491
1354
 
492
- export declare function getTextBbox(t: Text_2): BBox;
1355
+ export declare function getBoxCenter<T extends Annotation>(t: T): {
1356
+ x: number;
1357
+ y: number;
1358
+ };
493
1359
 
494
- export declare function getTextPosition(t: Text_2): {
1360
+ declare function getBoxPosition<T extends Annotation>(t: T, fixedSize?: boolean, zoom?: number): {
495
1361
  x: number;
496
1362
  y: number;
497
1363
  };
1364
+ export { getBoxPosition }
1365
+ export { getBoxPosition as getTextPosition }
498
1366
 
499
- export declare function getTextSize(t: Text_2): {
1367
+ declare function getBoxSize<T extends Annotation>(t: T): {
500
1368
  width: number;
501
1369
  height: number;
502
1370
  };
1371
+ export { getBoxSize }
1372
+ export { getBoxSize as getTextSize }
1373
+
1374
+ /** @private */
1375
+ export declare function getBrowserWindow(): HTMLElement | undefined;
503
1376
 
504
- export declare function hexShortToLong(color: string): string;
1377
+ /**
1378
+ * Get the position (center) of a comment
1379
+ *
1380
+ * @param comment - Comment annotation
1381
+ * @returns Center position
1382
+ */
1383
+ export declare function getCommentPosition(comment: Comment_2): Point;
505
1384
 
506
- export declare function hexToRgba(color: string, alpha: number): string;
1385
+ /**
1386
+ * Get the dimensions of a comment based on its mode
1387
+ *
1388
+ * @param comment - Comment annotation
1389
+ * @returns Width and height
1390
+ */
1391
+ export declare function getCommentSize(comment: Comment_2): Size;
507
1392
 
1393
+ /**
1394
+ * Get the effective zoom threshold for a comment
1395
+ * Uses explicit threshold if set, otherwise calculates from dimensions
1396
+ *
1397
+ * @param comment - Comment annotation
1398
+ * @returns Effective zoom threshold
1399
+ */
1400
+ export declare function getCommentZoomThreshold(comment: Comment_2): number;
1401
+
1402
+ export declare function getCoordinates(geojson: Feature | FeatureCollection | Geometry): Position[];
1403
+
1404
+ export declare const getHandleId: (handle: HTMLDivElement) => number;
1405
+
1406
+ /**
1407
+ * Get bounding box of a polygon
1408
+ */
1409
+ export declare function getPolygonBounds(polygon: Polygon): Bounds;
1410
+
1411
+ /**
1412
+ * Get centroid (geometric center) of a polygon
1413
+ */
1414
+ export declare function getPolygonCenter(polygon: Polygon): Point;
1415
+
1416
+ export declare const handleDetectionThreshold = 5;
1417
+
1418
+ export declare const handleRadius = 3;
1419
+
1420
+ /**
1421
+ * Hex color string in format #RGB or #RRGGBB
1422
+ * @example "#fff" | "#ffffff" | "#F0A" | "#FF00AA"
1423
+ */
1424
+ export declare type HexColor = `#${string}`;
1425
+
1426
+ export declare function hexShortToLong(color: HexColor): HexColor;
1427
+
1428
+ /**
1429
+ * Adds alpha channel to a hex color
1430
+ * @param color
1431
+ * @param alpha
1432
+ * @returns rgba color string
1433
+ */
1434
+ export declare function hexToRgba(color: HexColor, alpha: number): RgbaColor;
1435
+
1436
+ /** History stack change event */
1437
+ export declare interface HistoryEvent {
1438
+ /** Indicates if undo operation is available */
1439
+ canUndo: boolean;
1440
+ /** Indicates if redo operation is available */
1441
+ canRedo: boolean;
1442
+ }
1443
+
1444
+ export declare const HL_BRIGHTEN = 0.2;
1445
+
1446
+ /** Unique identifier type for annotations */
508
1447
  export declare type Id = string | number;
509
1448
 
1449
+ /** Helper to check if a feature collection is an annotation collection */
510
1450
  export declare const isAnnotationCollection: (a: AnnotationFeature<Geometry, AnnotationProps> | FeatureCollection) => a is AnnotationCollection;
511
1451
 
512
1452
  export declare const isArrow: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Arrow;
513
1453
 
1454
+ export declare const isBox: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Box;
1455
+
1456
+ /**
1457
+ * Type guard to check if a string is a valid color
1458
+ */
1459
+ export declare function isColor(color: string): color is Color;
1460
+
1461
+ /**
1462
+ * Type guard to check if an annotation is a Comment
1463
+ */
1464
+ export declare const isComment: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Comment_2;
1465
+
1466
+ /**
1467
+ * Helper functions for managing comment-arrow relationships
1468
+ *
1469
+ * These functions provide utilities for:
1470
+ * - Checking if an arrow is connected to a comment
1471
+ * - Determining if arrow endpoints can be detached from comments
1472
+ *
1473
+ * Note: The core rule "comments must have at least one arrow" is enforced
1474
+ * in store/index.ts removeFeature() method, not here.
1475
+ */
1476
+ /**
1477
+ * Check if an arrow is connected to a comment
1478
+ *
1479
+ * @param arrow - The arrow feature to check
1480
+ * @returns True if the arrow has a comment on either end
1481
+ *
1482
+ * @example
1483
+ * ```typescript
1484
+ * if (isCommentArrow(arrow)) {
1485
+ * // Handle comment arrow specially
1486
+ * }
1487
+ * ```
1488
+ */
1489
+ export declare function isCommentArrow(arrow: Arrow): boolean;
1490
+
1491
+ /**
1492
+ * Type guard to check if a string is a valid hex color
1493
+ */
1494
+ export declare function isHexColor(color: string): color is HexColor;
1495
+
1496
+ export declare const isPolygon: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Polygon;
1497
+
1498
+ /**
1499
+ * Type guard to check if a string is a valid RGBA color
1500
+ */
1501
+ export declare function isRgbaColor(color: string): color is RgbaColor;
1502
+
1503
+ /**
1504
+ * Type guard to check if a string is a valid RGB color
1505
+ */
1506
+ export declare function isRgbColor(color: string): color is RgbColor;
1507
+
514
1508
  export declare const isText: (a: AnnotationFeature<Geometry, AnnotationProps>) => a is Text_2;
515
1509
 
516
- export declare type Link = {
1510
+ /** @private */
1511
+ export declare const LAYERS: {
1512
+ SHAPES: number;
1513
+ EDITOR: number;
1514
+ HANDLES: number;
1515
+ };
1516
+
1517
+ /** Link between an arrow and a text or node */
1518
+ export declare interface Link {
517
1519
  /** arrow attached to the text or node */
518
1520
  arrow: Id;
519
1521
  /** id of the text the arrow is attached to */
@@ -526,113 +1528,204 @@ export declare type Link = {
526
1528
  targetType: TargetType;
527
1529
  /**
528
1530
  * On which point relative to topleft corner the arrow is tighten, in case of
529
- * node, it can be deduced from the arrow itself
1531
+ * node, a 0 vector represents the center, otherwise it can be deduced from the arrow itself
530
1532
  */
531
- connectionPoint: Point;
532
- };
1533
+ magnet: Point;
1534
+ }
1535
+
1536
+ /**
1537
+ * Migrates old Polygon-based Box/Text to new Point-based format
1538
+ * Called only when annotations are added/loaded
1539
+ * @private
1540
+ */
1541
+ export declare function migrateBoxOrTextIfNeeded<T extends Annotation>(annotation: T): T;
533
1542
 
534
1543
  export declare const NONE = -1;
535
1544
 
1545
+ export declare function parseColor(color: Color): {
1546
+ r: number;
1547
+ g: number;
1548
+ b: number;
1549
+ a: number;
1550
+ };
1551
+
1552
+ /** 2D coordinate */
536
1553
  export declare type Point = {
537
1554
  x: number;
538
1555
  y: number;
539
1556
  };
540
1557
 
541
- export declare function rgbToRgba(color: string, alpha: number): string;
1558
+ /**
1559
+ * Polygon placed on the graph, use it to highlight areas
1560
+ */
1561
+ export declare interface Polygon extends AnnotationFeature<Polygon_2, PolygonProperties> {
1562
+ }
542
1563
 
543
- export declare function scaleGeometry(geometry: LineString | Polygon, scale: number, ox: number, oy: number): LineString | Polygon;
1564
+ export declare interface PolygonProperties extends AnnotationProps {
1565
+ type: "polygon";
1566
+ style?: PolygonStyle;
1567
+ }
1568
+
1569
+ export declare interface PolygonStyle extends BoxStyle {
1570
+ }
1571
+
1572
+ /**
1573
+ * RGBA color string in format rgba(r, g, b, a)
1574
+ * @example "rgba(255, 0, 0, 1)" | "rgba(128, 128, 128, 0.5)"
1575
+ */
1576
+ export declare type RgbaColor = `rgba(${number}, ${number}, ${number}, ${number})` | `rgba(${number},${number},${number},${number})`;
1577
+
1578
+ /**
1579
+ * RGB color string in format rgb(r, g, b)
1580
+ * @example "rgb(255, 0, 0)" | "rgb(128, 128, 128)"
1581
+ */
1582
+ export declare type RgbColor = `rgb(${number}, ${number}, ${number})` | `rgb(${number},${number},${number})`;
1583
+
1584
+ /**
1585
+ * Adds alpha channel to an rgb color
1586
+ * @param color
1587
+ * @param alpha
1588
+ * @returns rgba color string
1589
+ */
1590
+ export declare function rgbToRgba(color: RgbColor, alpha: number): RgbaColor;
1591
+
1592
+ export declare function scaleGeometry(geometry: LineString | Polygon_2, scale: number, ox: number, oy: number): LineString | Polygon_2;
1593
+
1594
+ /**
1595
+ * Scale polygon around an origin point
1596
+ */
1597
+ export declare function scalePolygon(polygon: Polygon, scale: number, originX: number, originY: number): Polygon;
544
1598
 
545
1599
  export declare function setArrowEnd(a: Arrow, x: number, y: number): void;
546
1600
 
547
- export declare function setArrowEndPoint(a: Arrow, side: "start" | "end", x: number, y: number): void;
1601
+ export declare function setArrowEndPoint(a: Arrow, side: Side, x: number, y: number): void;
548
1602
 
549
1603
  export declare function setArrowStart(a: Arrow, x: number, y: number): void;
550
1604
 
551
- export declare function setTextBbox(t: Text_2, x: number, y: number, width: number, height: number): void;
1605
+ declare function setBbox(t: Box | Text_2, x: number, y: number, width: number, height: number): void;
1606
+ export { setBbox }
1607
+ export { setBbox as setTextBbox }
1608
+
1609
+ export declare type Side = typeof SIDE_START | typeof SIDE_END;
552
1610
 
553
- export declare type Side = "start" | "end";
1611
+ export declare const SIDE_END: "end";
554
1612
 
1613
+ export declare const SIDE_START: "start";
1614
+
1615
+ /**
1616
+ * Polyline simplification using a combination of
1617
+ * the Radial Distance and
1618
+ * the Douglas-Peucker algorithms
1619
+ * See https://github.com/mourner/simplify-js for more details
1620
+ *
1621
+ * @param points Points to simplify
1622
+ * @param tolerance Tolerance in pixels
1623
+ * @param highestQuality Whether to skip radial distance simplification
1624
+ * @returns Simplified points
1625
+ */
1626
+ export declare function simplifyPolygon(points: Position[], tolerance: number, highestQuality: boolean): Position[];
1627
+
1628
+ /** Stroke style for arrow annotations */
555
1629
  export declare type Stroke = {
556
- type: "plain" | "dashed" | "none";
557
- color: string;
1630
+ /** Stroke type */
1631
+ type: StrokeType;
1632
+ /** Stroke color */
1633
+ color: Color;
1634
+ /** Stroke width */
558
1635
  width: number;
559
1636
  };
560
1637
 
1638
+ /** Stroke style options for annotations */
561
1639
  export declare type StrokeOptions = {
562
- strokeType?: "plain" | "dashed" | "none";
563
- strokeColor?: string;
1640
+ /** Type of stroke: plain, dashed, or none */
1641
+ strokeType?: StrokeType;
1642
+ /** Stroke color: #f00, yellow... */
1643
+ strokeColor?: Color;
1644
+ /** Stroke width */
564
1645
  strokeWidth?: number;
565
1646
  };
566
1647
 
567
1648
  export declare type StrokeStyle = Stroke;
568
1649
 
569
- export declare type TargetType = "text" | "node";
1650
+ /** Stroke types available for annotations */
1651
+ export declare type StrokeType = "plain" | "dashed" | "none";
1652
+
1653
+ /** @private */
1654
+ export declare const TARGET_TYPES: {
1655
+ TEXT: "text";
1656
+ NODE: "node";
1657
+ BOX: "box";
1658
+ COMMENT: "comment";
1659
+ POLYGON: "polygon";
1660
+ ANNOTATION: "annotation";
1661
+ EDGE: "edge";
1662
+ };
1663
+
1664
+ export declare type TargetType = (typeof TARGET_TYPES)[keyof typeof TARGET_TYPES];
570
1665
 
571
- declare type Text_2 = AnnotationFeature<Polygon, TextProperties>;
1666
+ /**
1667
+ * Text annotation feature, represents a text box at a specific position
1668
+ */
1669
+ declare interface Text_2 extends AnnotationFeature<Point_2, TextProperties> {
1670
+ }
572
1671
  export { Text_2 as Text }
573
1672
 
574
- export declare interface TextProperties extends AnnotationProps {
1673
+ export declare const TEXT_LINE_HEIGHT = 1.2;
1674
+
1675
+ export declare interface TextProperties extends Omit<BoxProperties, "type"> {
575
1676
  type: "text";
576
1677
  /**text to display*/
577
1678
  content: string;
1679
+ /** Width of the text box */
1680
+ width: number;
1681
+ /** Height of the text box */
1682
+ height: number;
578
1683
  style?: TextStyle;
579
1684
  }
580
1685
 
581
- /**
582
- * @class Texts
583
- * Draw, update, edit texts
584
- */
585
- export declare class Texts extends Editor<Text_2> {
586
- private textArea;
587
- private handleSize;
588
- private rect;
589
- private annotation;
590
- private startX;
591
- private startY;
592
- private handles;
593
- private draggedHandle;
594
- private isFocused;
595
- private placeholder;
596
- constructor(ogma: default_3, options?: Pick<Partial<ControllerOptions>, "textHandleSize" | "textPlaceholder">);
597
- private _onFocus;
598
- private _onBlur;
599
- protected _canRemove(): boolean;
600
- startDrawing: (x: number, y: number, text?: Text_2) => void;
601
- cancelDrawing: () => void;
602
- private startDragging;
603
- private onHandleMouseDown;
604
- private onMouseMove;
605
- private _onMouseMove;
606
- private onMouseUp;
607
- private _onMousedown;
608
- private onViewChanged;
609
- private _onInput;
610
- detect({ x, y }: Point_2, margin?: number): Text_2 | undefined;
611
- draw(svg: SVGSVGElement): void;
612
- refreshDrawing(): void;
613
- getDefaultOptions(): Text_2;
614
- refreshEditor(): void;
615
- select(id: Id): void;
616
- destroy(): void;
617
- }
618
-
619
- export declare interface TextStyle extends StrokeOptions {
1686
+ export declare interface TextStyle extends BoxStyle {
620
1687
  /** Helvetica, sans-serif... */
621
1688
  font?: string;
622
1689
  /** Font size, in pixels */
623
1690
  fontSize?: number | string;
624
1691
  /** text color: #f00, yellow...*/
625
- color?: string;
1692
+ color?: Color;
626
1693
  /** background color: empty for transparent #f00, yellow...*/
627
- background?: string;
1694
+ background?: Color;
628
1695
  /** padding around the text */
629
1696
  padding?: number;
630
1697
  /** Text box border radius */
631
1698
  borderRadius?: number;
1699
+ /** When true, text maintains constant size regardless of zoom level */
1700
+ fixedSize?: boolean;
632
1701
  }
633
1702
 
634
- export declare function updateTextBbox(t: Text_2): void;
1703
+ /** @private */
1704
+ export declare const throttle: <T extends unknown[]>(callback: (...args: T) => void, delay?: number, callIfWaiting?: boolean) => (...args: T) => void;
1705
+
1706
+ /**
1707
+ * Toggle comment mode between collapsed and expanded
1708
+ *
1709
+ * @param comment - Comment to toggle
1710
+ * @returns Updated comment with toggled mode
1711
+ */
1712
+ export declare function toggleCommentMode(comment: Comment_2): Comment_2;
1713
+
1714
+ /**
1715
+ * Translate (move) a polygon by dx, dy
1716
+ */
1717
+ export declare function translatePolygon(polygon: Polygon, dx: number, dy: number): Polygon;
1718
+
1719
+ declare function updateBbox<T extends Annotation>(t: T): void;
1720
+ export { updateBbox }
1721
+ export { updateBbox as updateTextBbox }
1722
+
1723
+ /**
1724
+ * Update bbox for a polygon
1725
+ */
1726
+ export declare function updatePolygonBbox(polygon: Polygon): void;
635
1727
 
1728
+ /** @private */
636
1729
  export declare type Vector = Point;
637
1730
 
638
1731
  export { }